xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1 //===-- DWARFFormValue.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <cassert>
10 #include <optional>
11 
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/dwarf.h"
14 #include "lldb/Symbol/ObjectFile.h"
15 #include "lldb/Utility/Stream.h"
16 
17 #include "DWARFDebugInfo.h"
18 #include "DWARFFormValue.h"
19 #include "DWARFUnit.h"
20 
21 class DWARFUnit;
22 
23 using namespace lldb_private;
24 using namespace lldb_private::dwarf;
25 using namespace lldb_private::plugin::dwarf;
26 
27 void DWARFFormValue::Clear() {
28   m_unit = nullptr;
29   m_form = dw_form_t(0);
30   m_value = ValueTypeTag();
31 }
32 
33 bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
34                                   lldb::offset_t *offset_ptr) {
35   if (m_form == DW_FORM_implicit_const)
36     return true;
37 
38   bool indirect = false;
39   bool is_block = false;
40   m_value.data = nullptr;
41   uint8_t ref_addr_size;
42   // Read the value for the form into value and follow and DW_FORM_indirect
43   // instances we run into
44   do {
45     indirect = false;
46     switch (m_form) {
47     case DW_FORM_addr:
48       assert(m_unit);
49       m_value.value.uval =
50           data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit));
51       break;
52     case DW_FORM_block1:
53       m_value.value.uval = data.GetU8(offset_ptr);
54       is_block = true;
55       break;
56     case DW_FORM_block2:
57       m_value.value.uval = data.GetU16(offset_ptr);
58       is_block = true;
59       break;
60     case DW_FORM_block4:
61       m_value.value.uval = data.GetU32(offset_ptr);
62       is_block = true;
63       break;
64     case DW_FORM_data16:
65       m_value.value.uval = 16;
66       is_block = true;
67       break;
68     case DW_FORM_exprloc:
69     case DW_FORM_block:
70       m_value.value.uval = data.GetULEB128(offset_ptr);
71       is_block = true;
72       break;
73     case DW_FORM_string:
74       m_value.value.cstr = data.GetCStr(offset_ptr);
75       break;
76     case DW_FORM_sdata:
77       m_value.value.sval = data.GetSLEB128(offset_ptr);
78       break;
79     case DW_FORM_strp:
80     case DW_FORM_line_strp:
81     case DW_FORM_sec_offset:
82       m_value.value.uval = data.GetMaxU64(offset_ptr, 4);
83       break;
84     case DW_FORM_addrx1:
85     case DW_FORM_strx1:
86     case DW_FORM_ref1:
87     case DW_FORM_data1:
88     case DW_FORM_flag:
89       m_value.value.uval = data.GetU8(offset_ptr);
90       break;
91     case DW_FORM_addrx2:
92     case DW_FORM_strx2:
93     case DW_FORM_ref2:
94     case DW_FORM_data2:
95       m_value.value.uval = data.GetU16(offset_ptr);
96       break;
97     case DW_FORM_addrx3:
98     case DW_FORM_strx3:
99       m_value.value.uval = data.GetMaxU64(offset_ptr, 3);
100       break;
101     case DW_FORM_addrx4:
102     case DW_FORM_strx4:
103     case DW_FORM_ref4:
104     case DW_FORM_data4:
105       m_value.value.uval = data.GetU32(offset_ptr);
106       break;
107     case DW_FORM_data8:
108     case DW_FORM_ref8:
109     case DW_FORM_ref_sig8:
110       m_value.value.uval = data.GetU64(offset_ptr);
111       break;
112     case DW_FORM_addrx:
113     case DW_FORM_loclistx:
114     case DW_FORM_rnglistx:
115     case DW_FORM_strx:
116     case DW_FORM_udata:
117     case DW_FORM_ref_udata:
118     case DW_FORM_GNU_str_index:
119     case DW_FORM_GNU_addr_index:
120       m_value.value.uval = data.GetULEB128(offset_ptr);
121       break;
122     case DW_FORM_ref_addr:
123       assert(m_unit);
124       if (m_unit->GetVersion() <= 2)
125         ref_addr_size = m_unit->GetAddressByteSize();
126       else
127         ref_addr_size = 4;
128       m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
129       break;
130     case DW_FORM_indirect:
131       m_form = static_cast<dw_form_t>(data.GetULEB128(offset_ptr));
132       indirect = true;
133       break;
134     case DW_FORM_flag_present:
135       m_value.value.uval = 1;
136       break;
137     default:
138       return false;
139     }
140   } while (indirect);
141 
142   if (is_block) {
143     m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
144     if (m_value.data != nullptr) {
145       *offset_ptr += m_value.value.uval;
146     }
147   }
148 
149   return true;
150 }
151 
152 struct FormSize {
153   uint8_t valid:1, size:7;
154 };
155 static FormSize g_form_sizes[] = {
156     {0, 0}, // 0x00 unused
157     {0, 0}, // 0x01 DW_FORM_addr
158     {0, 0}, // 0x02 unused
159     {0, 0}, // 0x03 DW_FORM_block2
160     {0, 0}, // 0x04 DW_FORM_block4
161     {1, 2}, // 0x05 DW_FORM_data2
162     {1, 4}, // 0x06 DW_FORM_data4
163     {1, 8}, // 0x07 DW_FORM_data8
164     {0, 0}, // 0x08 DW_FORM_string
165     {0, 0}, // 0x09 DW_FORM_block
166     {0, 0}, // 0x0a DW_FORM_block1
167     {1, 1}, // 0x0b DW_FORM_data1
168     {1, 1}, // 0x0c DW_FORM_flag
169     {0, 0}, // 0x0d DW_FORM_sdata
170     {1, 4}, // 0x0e DW_FORM_strp
171     {0, 0}, // 0x0f DW_FORM_udata
172     {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes
173             // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
174     {1, 1},  // 0x11 DW_FORM_ref1
175     {1, 2},  // 0x12 DW_FORM_ref2
176     {1, 4},  // 0x13 DW_FORM_ref4
177     {1, 8},  // 0x14 DW_FORM_ref8
178     {0, 0},  // 0x15 DW_FORM_ref_udata
179     {0, 0},  // 0x16 DW_FORM_indirect
180     {1, 4},  // 0x17 DW_FORM_sec_offset
181     {0, 0},  // 0x18 DW_FORM_exprloc
182     {1, 0},  // 0x19 DW_FORM_flag_present
183     {0, 0},  // 0x1a DW_FORM_strx (ULEB128)
184     {0, 0},  // 0x1b DW_FORM_addrx (ULEB128)
185     {1, 4},  // 0x1c DW_FORM_ref_sup4
186     {0, 0},  // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)
187     {1, 16}, // 0x1e DW_FORM_data16
188     {1, 4},  // 0x1f DW_FORM_line_strp
189     {1, 8},  // 0x20 DW_FORM_ref_sig8
190 };
191 
192 std::optional<uint8_t> DWARFFormValue::GetFixedSize(dw_form_t form,
193                                                     const DWARFUnit *u) {
194   if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid)
195     return static_cast<uint8_t>(g_form_sizes[form].size);
196   if (form == DW_FORM_addr && u)
197     return u->GetAddressByteSize();
198   return std::nullopt;
199 }
200 
201 std::optional<uint8_t> DWARFFormValue::GetFixedSize() const {
202   return GetFixedSize(m_form, m_unit);
203 }
204 
205 bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,
206                                lldb::offset_t *offset_ptr) const {
207   return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit);
208 }
209 
210 bool DWARFFormValue::SkipValue(dw_form_t form,
211                                const DWARFDataExtractor &debug_info_data,
212                                lldb::offset_t *offset_ptr,
213                                const DWARFUnit *unit) {
214   uint8_t ref_addr_size;
215   switch (form) {
216   // Blocks if inlined data that have a length field and the data bytes inlined
217   // in the .debug_info
218   case DW_FORM_exprloc:
219   case DW_FORM_block: {
220     uint64_t size = debug_info_data.GetULEB128(offset_ptr);
221     *offset_ptr += size;
222   }
223     return true;
224   case DW_FORM_block1: {
225     uint8_t size = debug_info_data.GetU8(offset_ptr);
226     *offset_ptr += size;
227   }
228     return true;
229   case DW_FORM_block2: {
230     uint16_t size = debug_info_data.GetU16(offset_ptr);
231     *offset_ptr += size;
232   }
233     return true;
234   case DW_FORM_block4: {
235     uint32_t size = debug_info_data.GetU32(offset_ptr);
236     *offset_ptr += size;
237   }
238     return true;
239 
240   // Inlined NULL terminated C-strings
241   case DW_FORM_string:
242     debug_info_data.GetCStr(offset_ptr);
243     return true;
244 
245   // Compile unit address sized values
246   case DW_FORM_addr:
247     *offset_ptr += DWARFUnit::GetAddressByteSize(unit);
248     return true;
249 
250   case DW_FORM_ref_addr:
251     ref_addr_size = 4;
252     assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will
253                   // get this wrong
254     if (unit->GetVersion() <= 2)
255       ref_addr_size = unit->GetAddressByteSize();
256     else
257       ref_addr_size = 4;
258     *offset_ptr += ref_addr_size;
259     return true;
260 
261   // 0 bytes values (implied from DW_FORM)
262   case DW_FORM_flag_present:
263   case DW_FORM_implicit_const:
264     return true;
265 
266     // 1 byte values
267     case DW_FORM_addrx1:
268     case DW_FORM_data1:
269     case DW_FORM_flag:
270     case DW_FORM_ref1:
271     case DW_FORM_strx1:
272       *offset_ptr += 1;
273       return true;
274 
275     // 2 byte values
276     case DW_FORM_addrx2:
277     case DW_FORM_data2:
278     case DW_FORM_ref2:
279     case DW_FORM_strx2:
280       *offset_ptr += 2;
281       return true;
282 
283     // 3 byte values
284     case DW_FORM_addrx3:
285     case DW_FORM_strx3:
286       *offset_ptr += 3;
287       return true;
288 
289     // 32 bit for DWARF 32, 64 for DWARF 64
290     case DW_FORM_sec_offset:
291     case DW_FORM_strp:
292     case DW_FORM_line_strp:
293       *offset_ptr += 4;
294       return true;
295 
296     // 4 byte values
297     case DW_FORM_addrx4:
298     case DW_FORM_data4:
299     case DW_FORM_ref4:
300     case DW_FORM_strx4:
301       *offset_ptr += 4;
302       return true;
303 
304     // 8 byte values
305     case DW_FORM_data8:
306     case DW_FORM_ref8:
307     case DW_FORM_ref_sig8:
308       *offset_ptr += 8;
309       return true;
310 
311     // signed or unsigned LEB 128 values
312     case DW_FORM_addrx:
313     case DW_FORM_loclistx:
314     case DW_FORM_rnglistx:
315     case DW_FORM_sdata:
316     case DW_FORM_udata:
317     case DW_FORM_ref_udata:
318     case DW_FORM_GNU_addr_index:
319     case DW_FORM_GNU_str_index:
320     case DW_FORM_strx:
321       debug_info_data.Skip_LEB128(offset_ptr);
322       return true;
323 
324   case DW_FORM_indirect: {
325       auto indirect_form =
326           static_cast<dw_form_t>(debug_info_data.GetULEB128(offset_ptr));
327       return DWARFFormValue::SkipValue(indirect_form, debug_info_data,
328                                        offset_ptr, unit);
329   }
330 
331   default:
332     break;
333   }
334   return false;
335 }
336 
337 void DWARFFormValue::Dump(Stream &s) const {
338   uint64_t uvalue = Unsigned();
339   bool unit_relative_offset = false;
340 
341   switch (m_form) {
342   case DW_FORM_addr:
343     DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t));
344     break;
345   case DW_FORM_flag:
346   case DW_FORM_data1:
347     s.PutHex8(uvalue);
348     break;
349   case DW_FORM_data2:
350     s.PutHex16(uvalue);
351     break;
352   case DW_FORM_sec_offset:
353   case DW_FORM_data4:
354     s.PutHex32(uvalue);
355     break;
356   case DW_FORM_ref_sig8:
357   case DW_FORM_data8:
358     s.PutHex64(uvalue);
359     break;
360   case DW_FORM_string:
361     s.QuotedCString(AsCString());
362     break;
363   case DW_FORM_exprloc:
364   case DW_FORM_block:
365   case DW_FORM_block1:
366   case DW_FORM_block2:
367   case DW_FORM_block4:
368     if (uvalue > 0) {
369       switch (m_form) {
370       case DW_FORM_exprloc:
371       case DW_FORM_block:
372         s.Printf("<0x%" PRIx64 "> ", uvalue);
373         break;
374       case DW_FORM_block1:
375         s.Printf("<0x%2.2x> ", (uint8_t)uvalue);
376         break;
377       case DW_FORM_block2:
378         s.Printf("<0x%4.4x> ", (uint16_t)uvalue);
379         break;
380       case DW_FORM_block4:
381         s.Printf("<0x%8.8x> ", (uint32_t)uvalue);
382         break;
383       default:
384         break;
385       }
386 
387       const uint8_t *data_ptr = m_value.data;
388       if (data_ptr) {
389         const uint8_t *end_data_ptr =
390             data_ptr + uvalue; // uvalue contains size of block
391         while (data_ptr < end_data_ptr) {
392           s.Printf("%2.2x ", *data_ptr);
393           ++data_ptr;
394         }
395       } else
396         s.PutCString("NULL");
397     }
398     break;
399 
400   case DW_FORM_sdata:
401     s.PutSLEB128(uvalue);
402     break;
403   case DW_FORM_udata:
404     s.PutULEB128(uvalue);
405     break;
406   case DW_FORM_strp:
407   case DW_FORM_line_strp: {
408     const char *dbg_str = AsCString();
409     if (dbg_str) {
410       s.QuotedCString(dbg_str);
411     } else {
412       s.PutHex32(uvalue);
413     }
414   } break;
415 
416   case DW_FORM_ref_addr: {
417     assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we
418                     // will get this wrong
419     if (m_unit->GetVersion() <= 2)
420       DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t) * 2);
421     else
422       DumpAddress(s.AsRawOstream(), uvalue,
423                   4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
424                           // support DWARF64 yet
425     break;
426   }
427   case DW_FORM_ref1:
428     unit_relative_offset = true;
429     break;
430   case DW_FORM_ref2:
431     unit_relative_offset = true;
432     break;
433   case DW_FORM_ref4:
434     unit_relative_offset = true;
435     break;
436   case DW_FORM_ref8:
437     unit_relative_offset = true;
438     break;
439   case DW_FORM_ref_udata:
440     unit_relative_offset = true;
441     break;
442 
443   // All DW_FORM_indirect attributes should be resolved prior to calling this
444   // function
445   case DW_FORM_indirect:
446     s.PutCString("DW_FORM_indirect");
447     break;
448   case DW_FORM_flag_present:
449     break;
450   default:
451     s.Printf("DW_FORM(0x%4.4x)", m_form);
452     break;
453   }
454 
455   if (unit_relative_offset) {
456     assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
457                     // unit relative or we will get this wrong
458     s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset());
459   }
460 }
461 
462 const char *DWARFFormValue::AsCString() const {
463   DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext();
464 
465   if (m_form == DW_FORM_string)
466     return m_value.value.cstr;
467   if (m_form == DW_FORM_strp)
468     return context.getOrLoadStrData().PeekCStr(m_value.value.uval);
469 
470   if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx ||
471       m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 ||
472       m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) {
473 
474     std::optional<uint64_t> offset =
475         m_unit->GetStringOffsetSectionItem(m_value.value.uval);
476     if (!offset)
477       return nullptr;
478     return context.getOrLoadStrData().PeekCStr(*offset);
479   }
480 
481   if (m_form == DW_FORM_line_strp)
482     return context.getOrLoadLineStrData().PeekCStr(m_value.value.uval);
483 
484   return nullptr;
485 }
486 
487 dw_addr_t DWARFFormValue::Address() const {
488   SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();
489 
490   if (m_form == DW_FORM_addr)
491     return Unsigned();
492 
493   assert(m_unit);
494   assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||
495          m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||
496          m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);
497 
498   uint32_t index_size = m_unit->GetAddressByteSize();
499   dw_offset_t addr_base = m_unit->GetAddrBase();
500   lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
501   return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64(
502       &offset, index_size);
503 }
504 
505 DWARFDIE DWARFFormValue::Reference() const {
506   uint64_t value = m_value.value.uval;
507   switch (m_form) {
508   case DW_FORM_ref1:
509   case DW_FORM_ref2:
510   case DW_FORM_ref4:
511   case DW_FORM_ref8:
512   case DW_FORM_ref_udata:
513     assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
514                     // unit relative or we will get this wrong
515     value += m_unit->GetOffset();
516     if (!m_unit->ContainsDIEOffset(value)) {
517       m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
518           "DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value);
519       return {};
520     }
521     return const_cast<DWARFUnit *>(m_unit)->GetDIE(value);
522 
523   case DW_FORM_ref_addr: {
524     DWARFUnit *ref_cu =
525         m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset(
526             DIERef::Section::DebugInfo, value);
527     if (!ref_cu) {
528       m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
529           "DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value);
530       return {};
531     }
532     return ref_cu->GetDIE(value);
533   }
534 
535   case DW_FORM_ref_sig8: {
536     DWARFTypeUnit *tu =
537         m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value);
538     if (!tu)
539       return {};
540     return tu->GetDIE(tu->GetTypeOffset());
541   }
542 
543   default:
544     return {};
545   }
546 }
547 
548 uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
549   uint64_t value = m_value.value.uval;
550   switch (m_form) {
551   case DW_FORM_ref1:
552   case DW_FORM_ref2:
553   case DW_FORM_ref4:
554   case DW_FORM_ref8:
555   case DW_FORM_ref_udata:
556     return value + base_offset;
557 
558   case DW_FORM_ref_addr:
559   case DW_FORM_ref_sig8:
560   case DW_FORM_GNU_ref_alt:
561     return value;
562 
563   default:
564     return DW_INVALID_OFFSET;
565   }
566 }
567 
568 const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
569 
570 bool DWARFFormValue::IsBlockForm(const dw_form_t form) {
571   switch (form) {
572   case DW_FORM_exprloc:
573   case DW_FORM_block:
574   case DW_FORM_block1:
575   case DW_FORM_block2:
576   case DW_FORM_block4:
577     return true;
578   default:
579     return false;
580   }
581   llvm_unreachable("All cases handled above!");
582 }
583 
584 bool DWARFFormValue::IsDataForm(const dw_form_t form) {
585   switch (form) {
586   case DW_FORM_sdata:
587   case DW_FORM_udata:
588   case DW_FORM_data1:
589   case DW_FORM_data2:
590   case DW_FORM_data4:
591   case DW_FORM_data8:
592     return true;
593   default:
594     return false;
595   }
596   llvm_unreachable("All cases handled above!");
597 }
598 
599 bool DWARFFormValue::FormIsSupported(dw_form_t form) {
600   switch (form) {
601     case DW_FORM_addr:
602     case DW_FORM_addrx:
603     case DW_FORM_loclistx:
604     case DW_FORM_rnglistx:
605     case DW_FORM_block2:
606     case DW_FORM_block4:
607     case DW_FORM_data2:
608     case DW_FORM_data4:
609     case DW_FORM_data8:
610     case DW_FORM_string:
611     case DW_FORM_block:
612     case DW_FORM_block1:
613     case DW_FORM_data1:
614     case DW_FORM_flag:
615     case DW_FORM_sdata:
616     case DW_FORM_strp:
617     case DW_FORM_line_strp:
618     case DW_FORM_strx:
619     case DW_FORM_strx1:
620     case DW_FORM_strx2:
621     case DW_FORM_strx3:
622     case DW_FORM_strx4:
623     case DW_FORM_udata:
624     case DW_FORM_ref_addr:
625     case DW_FORM_ref1:
626     case DW_FORM_ref2:
627     case DW_FORM_ref4:
628     case DW_FORM_ref8:
629     case DW_FORM_ref_udata:
630     case DW_FORM_indirect:
631     case DW_FORM_sec_offset:
632     case DW_FORM_exprloc:
633     case DW_FORM_flag_present:
634     case DW_FORM_ref_sig8:
635     case DW_FORM_GNU_str_index:
636     case DW_FORM_GNU_addr_index:
637     case DW_FORM_implicit_const:
638       return true;
639     default:
640       break;
641   }
642   return false;
643 }
644