xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 "llvm/DebugInfo/DWARF/DWARFFormValue.h"
10 #include "llvm/ADT/ArrayRef.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/BinaryFormat/Dwarf.h"
13 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
14 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
15 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
16 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
17 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
18 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/Format.h"
21 #include "llvm/Support/WithColor.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <cinttypes>
24 #include <cstdint>
25 #include <limits>
26 #include <optional>
27 
28 using namespace llvm;
29 using namespace dwarf;
30 
31 static const DWARFFormValue::FormClass DWARF5FormClasses[] = {
32     DWARFFormValue::FC_Unknown,  // 0x0
33     DWARFFormValue::FC_Address,  // 0x01 DW_FORM_addr
34     DWARFFormValue::FC_Unknown,  // 0x02 unused
35     DWARFFormValue::FC_Block,    // 0x03 DW_FORM_block2
36     DWARFFormValue::FC_Block,    // 0x04 DW_FORM_block4
37     DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2
38     // --- These can be FC_SectionOffset in DWARF3 and below:
39     DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4
40     DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8
41     // ---
42     DWARFFormValue::FC_String,        // 0x08 DW_FORM_string
43     DWARFFormValue::FC_Block,         // 0x09 DW_FORM_block
44     DWARFFormValue::FC_Block,         // 0x0a DW_FORM_block1
45     DWARFFormValue::FC_Constant,      // 0x0b DW_FORM_data1
46     DWARFFormValue::FC_Flag,          // 0x0c DW_FORM_flag
47     DWARFFormValue::FC_Constant,      // 0x0d DW_FORM_sdata
48     DWARFFormValue::FC_String,        // 0x0e DW_FORM_strp
49     DWARFFormValue::FC_Constant,      // 0x0f DW_FORM_udata
50     DWARFFormValue::FC_Reference,     // 0x10 DW_FORM_ref_addr
51     DWARFFormValue::FC_Reference,     // 0x11 DW_FORM_ref1
52     DWARFFormValue::FC_Reference,     // 0x12 DW_FORM_ref2
53     DWARFFormValue::FC_Reference,     // 0x13 DW_FORM_ref4
54     DWARFFormValue::FC_Reference,     // 0x14 DW_FORM_ref8
55     DWARFFormValue::FC_Reference,     // 0x15 DW_FORM_ref_udata
56     DWARFFormValue::FC_Indirect,      // 0x16 DW_FORM_indirect
57     DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
58     DWARFFormValue::FC_Exprloc,       // 0x18 DW_FORM_exprloc
59     DWARFFormValue::FC_Flag,          // 0x19 DW_FORM_flag_present
60     DWARFFormValue::FC_String,        // 0x1a DW_FORM_strx
61     DWARFFormValue::FC_Address,       // 0x1b DW_FORM_addrx
62     DWARFFormValue::FC_Reference,     // 0x1c DW_FORM_ref_sup4
63     DWARFFormValue::FC_String,        // 0x1d DW_FORM_strp_sup
64     DWARFFormValue::FC_Constant,      // 0x1e DW_FORM_data16
65     DWARFFormValue::FC_String,        // 0x1f DW_FORM_line_strp
66     DWARFFormValue::FC_Reference,     // 0x20 DW_FORM_ref_sig8
67     DWARFFormValue::FC_Constant,      // 0x21 DW_FORM_implicit_const
68     DWARFFormValue::FC_SectionOffset, // 0x22 DW_FORM_loclistx
69     DWARFFormValue::FC_SectionOffset, // 0x23 DW_FORM_rnglistx
70     DWARFFormValue::FC_Reference,     // 0x24 DW_FORM_ref_sup8
71     DWARFFormValue::FC_String,        // 0x25 DW_FORM_strx1
72     DWARFFormValue::FC_String,        // 0x26 DW_FORM_strx2
73     DWARFFormValue::FC_String,        // 0x27 DW_FORM_strx3
74     DWARFFormValue::FC_String,        // 0x28 DW_FORM_strx4
75     DWARFFormValue::FC_Address,       // 0x29 DW_FORM_addrx1
76     DWARFFormValue::FC_Address,       // 0x2a DW_FORM_addrx2
77     DWARFFormValue::FC_Address,       // 0x2b DW_FORM_addrx3
78     DWARFFormValue::FC_Address,       // 0x2c DW_FORM_addrx4
79     DWARFFormValue::FC_Address,       // 0x2001 DW_FORM_addrx_offset
80 };
81 
createFromSValue(dwarf::Form F,int64_t V)82 DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) {
83   return DWARFFormValue(F, ValueType(V));
84 }
85 
createFromUValue(dwarf::Form F,uint64_t V)86 DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) {
87   return DWARFFormValue(F, ValueType(V));
88 }
89 
createFromPValue(dwarf::Form F,const char * V)90 DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) {
91   return DWARFFormValue(F, ValueType(V));
92 }
93 
createFromBlockValue(dwarf::Form F,ArrayRef<uint8_t> D)94 DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F,
95                                                     ArrayRef<uint8_t> D) {
96   ValueType V;
97   V.uval = D.size();
98   V.data = D.data();
99   return DWARFFormValue(F, V);
100 }
101 
createFromUnit(dwarf::Form F,const DWARFUnit * U,uint64_t * OffsetPtr)102 DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U,
103                                               uint64_t *OffsetPtr) {
104   DWARFFormValue FormValue(F);
105   FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,
106                          U->getFormParams(), U);
107   return FormValue;
108 }
109 
skipValue(dwarf::Form Form,DataExtractor DebugInfoData,uint64_t * OffsetPtr,const dwarf::FormParams Params)110 bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
111                                uint64_t *OffsetPtr,
112                                const dwarf::FormParams Params) {
113   bool Indirect = false;
114   do {
115     switch (Form) {
116     // Blocks of inlined data that have a length field and the data bytes
117     // inlined in the .debug_info.
118     case DW_FORM_exprloc:
119     case DW_FORM_block: {
120       uint64_t size = DebugInfoData.getULEB128(OffsetPtr);
121       *OffsetPtr += size;
122       return true;
123     }
124     case DW_FORM_block1: {
125       uint8_t size = DebugInfoData.getU8(OffsetPtr);
126       *OffsetPtr += size;
127       return true;
128     }
129     case DW_FORM_block2: {
130       uint16_t size = DebugInfoData.getU16(OffsetPtr);
131       *OffsetPtr += size;
132       return true;
133     }
134     case DW_FORM_block4: {
135       uint32_t size = DebugInfoData.getU32(OffsetPtr);
136       *OffsetPtr += size;
137       return true;
138     }
139 
140     // Inlined NULL terminated C-strings.
141     case DW_FORM_string:
142       DebugInfoData.getCStr(OffsetPtr);
143       return true;
144 
145     case DW_FORM_addr:
146     case DW_FORM_ref_addr:
147     case DW_FORM_flag_present:
148     case DW_FORM_data1:
149     case DW_FORM_data2:
150     case DW_FORM_data4:
151     case DW_FORM_data8:
152     case DW_FORM_data16:
153     case DW_FORM_flag:
154     case DW_FORM_ref1:
155     case DW_FORM_ref2:
156     case DW_FORM_ref4:
157     case DW_FORM_ref8:
158     case DW_FORM_ref_sig8:
159     case DW_FORM_ref_sup4:
160     case DW_FORM_ref_sup8:
161     case DW_FORM_strx1:
162     case DW_FORM_strx2:
163     case DW_FORM_strx3:
164     case DW_FORM_strx4:
165     case DW_FORM_addrx1:
166     case DW_FORM_addrx2:
167     case DW_FORM_addrx3:
168     case DW_FORM_addrx4:
169     case DW_FORM_sec_offset:
170     case DW_FORM_strp:
171     case DW_FORM_strp_sup:
172     case DW_FORM_line_strp:
173     case DW_FORM_GNU_ref_alt:
174     case DW_FORM_GNU_strp_alt:
175     case DW_FORM_implicit_const:
176       if (std::optional<uint8_t> FixedSize =
177               dwarf::getFixedFormByteSize(Form, Params)) {
178         *OffsetPtr += *FixedSize;
179         return true;
180       }
181       return false;
182 
183     // signed or unsigned LEB 128 values.
184     case DW_FORM_sdata:
185       DebugInfoData.getSLEB128(OffsetPtr);
186       return true;
187 
188     case DW_FORM_udata:
189     case DW_FORM_ref_udata:
190     case DW_FORM_strx:
191     case DW_FORM_addrx:
192     case DW_FORM_loclistx:
193     case DW_FORM_rnglistx:
194     case DW_FORM_GNU_addr_index:
195     case DW_FORM_GNU_str_index:
196       DebugInfoData.getULEB128(OffsetPtr);
197       return true;
198 
199     case DW_FORM_LLVM_addrx_offset:
200       DebugInfoData.getULEB128(OffsetPtr);
201       *OffsetPtr += 4;
202       return true;
203 
204     case DW_FORM_indirect:
205       Indirect = true;
206       Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr));
207       break;
208 
209     default:
210       return false;
211     }
212   } while (Indirect);
213   return true;
214 }
215 
isFormClass(DWARFFormValue::FormClass FC) const216 bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
217   return doesFormBelongToClass(Form, FC, U ? U->getVersion() : 3);
218 }
219 
extractValue(const DWARFDataExtractor & Data,uint64_t * OffsetPtr,dwarf::FormParams FP,const DWARFContext * Ctx,const DWARFUnit * CU)220 bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
221                                   uint64_t *OffsetPtr, dwarf::FormParams FP,
222                                   const DWARFContext *Ctx,
223                                   const DWARFUnit *CU) {
224   if (!Ctx && CU)
225     Ctx = &CU->getContext();
226   C = Ctx;
227   U = CU;
228   Format = FP.Format;
229   bool Indirect = false;
230   bool IsBlock = false;
231   Value.data = nullptr;
232   // Read the value for the form into value and follow and DW_FORM_indirect
233   // instances we run into
234   Error Err = Error::success();
235   do {
236     Indirect = false;
237     switch (Form) {
238     case DW_FORM_addr:
239     case DW_FORM_ref_addr: {
240       uint16_t Size =
241           (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize();
242       Value.uval =
243           Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex, &Err);
244       break;
245     }
246     case DW_FORM_exprloc:
247     case DW_FORM_block:
248       Value.uval = Data.getULEB128(OffsetPtr, &Err);
249       IsBlock = true;
250       break;
251     case DW_FORM_block1:
252       Value.uval = Data.getU8(OffsetPtr, &Err);
253       IsBlock = true;
254       break;
255     case DW_FORM_block2:
256       Value.uval = Data.getU16(OffsetPtr, &Err);
257       IsBlock = true;
258       break;
259     case DW_FORM_block4:
260       Value.uval = Data.getU32(OffsetPtr, &Err);
261       IsBlock = true;
262       break;
263     case DW_FORM_data1:
264     case DW_FORM_ref1:
265     case DW_FORM_flag:
266     case DW_FORM_strx1:
267     case DW_FORM_addrx1:
268       Value.uval = Data.getU8(OffsetPtr, &Err);
269       break;
270     case DW_FORM_data2:
271     case DW_FORM_ref2:
272     case DW_FORM_strx2:
273     case DW_FORM_addrx2:
274       Value.uval = Data.getU16(OffsetPtr, &Err);
275       break;
276     case DW_FORM_strx3:
277     case DW_FORM_addrx3:
278       Value.uval = Data.getU24(OffsetPtr, &Err);
279       break;
280     case DW_FORM_data4:
281     case DW_FORM_ref4:
282     case DW_FORM_ref_sup4:
283     case DW_FORM_strx4:
284     case DW_FORM_addrx4:
285       Value.uval = Data.getRelocatedValue(4, OffsetPtr, nullptr, &Err);
286       break;
287     case DW_FORM_data8:
288     case DW_FORM_ref8:
289     case DW_FORM_ref_sup8:
290       Value.uval = Data.getRelocatedValue(8, OffsetPtr, nullptr, &Err);
291       break;
292     case DW_FORM_data16:
293       // Treat this like a 16-byte block.
294       Value.uval = 16;
295       IsBlock = true;
296       break;
297     case DW_FORM_sdata:
298       Value.sval = Data.getSLEB128(OffsetPtr, &Err);
299       break;
300     case DW_FORM_udata:
301     case DW_FORM_ref_udata:
302     case DW_FORM_rnglistx:
303     case DW_FORM_loclistx:
304     case DW_FORM_GNU_addr_index:
305     case DW_FORM_GNU_str_index:
306     case DW_FORM_addrx:
307     case DW_FORM_strx:
308       Value.uval = Data.getULEB128(OffsetPtr, &Err);
309       break;
310     case DW_FORM_LLVM_addrx_offset:
311       Value.uval = Data.getULEB128(OffsetPtr, &Err) << 32;
312       Value.uval |= Data.getU32(OffsetPtr, &Err);
313       break;
314     case DW_FORM_string:
315       Value.cstr = Data.getCStr(OffsetPtr, &Err);
316       break;
317     case DW_FORM_indirect:
318       Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr, &Err));
319       Indirect = true;
320       break;
321     case DW_FORM_strp:
322     case DW_FORM_sec_offset:
323     case DW_FORM_GNU_ref_alt:
324     case DW_FORM_GNU_strp_alt:
325     case DW_FORM_line_strp:
326     case DW_FORM_strp_sup: {
327       Value.uval = Data.getRelocatedValue(FP.getDwarfOffsetByteSize(),
328                                           OffsetPtr, nullptr, &Err);
329       break;
330     }
331     case DW_FORM_flag_present:
332       Value.uval = 1;
333       break;
334     case DW_FORM_ref_sig8:
335       Value.uval = Data.getU64(OffsetPtr, &Err);
336       break;
337     case DW_FORM_implicit_const:
338       // Value has been already set by DWARFFormValue::createFromSValue.
339       break;
340     default:
341       // DWARFFormValue::skipValue() will have caught this and caused all
342       // DWARF DIEs to fail to be parsed, so this code is not be reachable.
343       llvm_unreachable("unsupported form");
344     }
345   } while (Indirect && !Err);
346 
347   if (IsBlock)
348     Value.data = Data.getBytes(OffsetPtr, Value.uval, &Err).bytes_begin();
349 
350   return !errorToBool(std::move(Err));
351 }
352 
dumpAddress(raw_ostream & OS,uint8_t AddressSize,uint64_t Address)353 void DWARFFormValue::dumpAddress(raw_ostream &OS, uint8_t AddressSize,
354                                  uint64_t Address) {
355   uint8_t HexDigits = AddressSize * 2;
356   OS << format("0x%*.*" PRIx64, HexDigits, HexDigits, Address);
357 }
358 
dumpSectionedAddress(raw_ostream & OS,DIDumpOptions DumpOpts,object::SectionedAddress SA) const359 void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS,
360                                           DIDumpOptions DumpOpts,
361                                           object::SectionedAddress SA) const {
362   dumpAddress(OS, U->getAddressByteSize(), SA.Address);
363   dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts,
364                      SA.SectionIndex);
365 }
366 
dumpAddressSection(const DWARFObject & Obj,raw_ostream & OS,DIDumpOptions DumpOpts,uint64_t SectionIndex)367 void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,
368                                         DIDumpOptions DumpOpts,
369                                         uint64_t SectionIndex) {
370   if (!DumpOpts.Verbose || SectionIndex == -1ULL)
371     return;
372   ArrayRef<SectionName> SectionNames = Obj.getSectionNames();
373   const auto &SecRef = SectionNames[SectionIndex];
374 
375   OS << " \"" << SecRef.Name << '\"';
376 
377   // Print section index if name is not unique.
378   if (!SecRef.IsNameUnique)
379     OS << format(" [%" PRIu64 "]", SectionIndex);
380 }
381 
dump(raw_ostream & OS,DIDumpOptions DumpOpts) const382 void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
383   uint64_t UValue = Value.uval;
384   bool CURelativeOffset = false;
385   raw_ostream &AddrOS = DumpOpts.ShowAddresses
386                             ? WithColor(OS, HighlightColor::Address).get()
387                             : nulls();
388   int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
389   switch (Form) {
390   case DW_FORM_addr:
391     dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex});
392     break;
393   case DW_FORM_addrx:
394   case DW_FORM_addrx1:
395   case DW_FORM_addrx2:
396   case DW_FORM_addrx3:
397   case DW_FORM_addrx4:
398   case DW_FORM_GNU_addr_index:
399   case DW_FORM_LLVM_addrx_offset: {
400     if (U == nullptr) {
401       OS << "<invalid dwarf unit>";
402       break;
403     }
404     std::optional<object::SectionedAddress> A = getAsSectionedAddress();
405     if (!A || DumpOpts.Verbose) {
406       if (Form == DW_FORM_LLVM_addrx_offset) {
407         uint32_t Index = UValue >> 32;
408         uint32_t Offset = UValue & 0xffffffff;
409         AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset);
410       } else
411         AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue);
412     }
413     if (A)
414       dumpSectionedAddress(AddrOS, DumpOpts, *A);
415     else
416       OS << "<unresolved>";
417     break;
418   }
419   case DW_FORM_flag_present:
420     OS << "true";
421     break;
422   case DW_FORM_flag:
423   case DW_FORM_data1:
424     OS << format("0x%02x", (uint8_t)UValue);
425     break;
426   case DW_FORM_data2:
427     OS << format("0x%04x", (uint16_t)UValue);
428     break;
429   case DW_FORM_data4:
430     OS << format("0x%08x", (uint32_t)UValue);
431     break;
432   case DW_FORM_ref_sig8:
433     AddrOS << format("0x%016" PRIx64, UValue);
434     break;
435   case DW_FORM_data8:
436     OS << format("0x%016" PRIx64, UValue);
437     break;
438   case DW_FORM_data16:
439     OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), std::nullopt, 16, 16);
440     break;
441   case DW_FORM_string:
442     OS << '"';
443     OS.write_escaped(Value.cstr);
444     OS << '"';
445     break;
446   case DW_FORM_exprloc:
447   case DW_FORM_block:
448   case DW_FORM_block1:
449   case DW_FORM_block2:
450   case DW_FORM_block4:
451     if (UValue > 0) {
452       switch (Form) {
453       case DW_FORM_exprloc:
454       case DW_FORM_block:
455         AddrOS << format("<0x%" PRIx64 "> ", UValue);
456         break;
457       case DW_FORM_block1:
458         AddrOS << format("<0x%2.2x> ", (uint8_t)UValue);
459         break;
460       case DW_FORM_block2:
461         AddrOS << format("<0x%4.4x> ", (uint16_t)UValue);
462         break;
463       case DW_FORM_block4:
464         AddrOS << format("<0x%8.8x> ", (uint32_t)UValue);
465         break;
466       default:
467         break;
468       }
469 
470       const uint8_t *DataPtr = Value.data;
471       if (DataPtr) {
472         // UValue contains size of block
473         const uint8_t *EndDataPtr = DataPtr + UValue;
474         while (DataPtr < EndDataPtr) {
475           AddrOS << format("%2.2x ", *DataPtr);
476           ++DataPtr;
477         }
478       } else
479         OS << "NULL";
480     }
481     break;
482 
483   case DW_FORM_sdata:
484   case DW_FORM_implicit_const:
485     OS << Value.sval;
486     break;
487   case DW_FORM_udata:
488     OS << Value.uval;
489     break;
490   case DW_FORM_strp:
491     if (DumpOpts.Verbose)
492       OS << format(" .debug_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth, UValue);
493     dumpString(OS);
494     break;
495   case DW_FORM_line_strp:
496     if (DumpOpts.Verbose)
497       OS << format(" .debug_line_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth,
498                    UValue);
499     dumpString(OS);
500     break;
501   case DW_FORM_strx:
502   case DW_FORM_strx1:
503   case DW_FORM_strx2:
504   case DW_FORM_strx3:
505   case DW_FORM_strx4:
506   case DW_FORM_GNU_str_index:
507     if (DumpOpts.Verbose)
508       OS << format("indexed (%8.8x) string = ", (uint32_t)UValue);
509     dumpString(OS);
510     break;
511   case DW_FORM_GNU_strp_alt:
512     if (DumpOpts.Verbose)
513       OS << format("alt indirect string, offset: 0x%" PRIx64 "", UValue);
514     dumpString(OS);
515     break;
516   case DW_FORM_ref_addr:
517     AddrOS << format("0x%016" PRIx64, UValue);
518     break;
519   case DW_FORM_ref1:
520     CURelativeOffset = true;
521     if (DumpOpts.Verbose)
522       AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue);
523     break;
524   case DW_FORM_ref2:
525     CURelativeOffset = true;
526     if (DumpOpts.Verbose)
527       AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue);
528     break;
529   case DW_FORM_ref4:
530     CURelativeOffset = true;
531     if (DumpOpts.Verbose)
532       AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue);
533     break;
534   case DW_FORM_ref8:
535     CURelativeOffset = true;
536     if (DumpOpts.Verbose)
537       AddrOS << format("cu + 0x%8.8" PRIx64, UValue);
538     break;
539   case DW_FORM_ref_udata:
540     CURelativeOffset = true;
541     if (DumpOpts.Verbose)
542       AddrOS << format("cu + 0x%" PRIx64, UValue);
543     break;
544   case DW_FORM_GNU_ref_alt:
545     AddrOS << format("<alt 0x%" PRIx64 ">", UValue);
546     break;
547 
548   // All DW_FORM_indirect attributes should be resolved prior to calling
549   // this function
550   case DW_FORM_indirect:
551     OS << "DW_FORM_indirect";
552     break;
553 
554   case DW_FORM_rnglistx:
555     OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue);
556     break;
557 
558   case DW_FORM_loclistx:
559     OS << format("indexed (0x%x) loclist = ", (uint32_t)UValue);
560     break;
561 
562   case DW_FORM_sec_offset:
563     AddrOS << format("0x%0*" PRIx64, OffsetDumpWidth, UValue);
564     break;
565 
566   default:
567     OS << format("DW_FORM(0x%4.4x)", Form);
568     break;
569   }
570 
571   if (CURelativeOffset) {
572     if (DumpOpts.Verbose)
573       OS << " => {";
574     if (DumpOpts.ShowAddresses)
575       WithColor(OS, HighlightColor::Address).get()
576           << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0));
577     if (DumpOpts.Verbose)
578       OS << "}";
579   }
580 }
581 
dumpString(raw_ostream & OS) const582 void DWARFFormValue::dumpString(raw_ostream &OS) const {
583   if (auto DbgStr = dwarf::toString(*this)) {
584     auto COS = WithColor(OS, HighlightColor::String);
585     COS.get() << '"';
586     COS.get().write_escaped(*DbgStr);
587     COS.get() << '"';
588   }
589 }
590 
getAsCString() const591 Expected<const char *> DWARFFormValue::getAsCString() const {
592   if (!isFormClass(FC_String))
593     return make_error<StringError>("Invalid form for string attribute",
594                                    inconvertibleErrorCode());
595   if (Form == DW_FORM_string)
596     return Value.cstr;
597   // FIXME: Add support for DW_FORM_GNU_strp_alt
598   if (Form == DW_FORM_GNU_strp_alt || C == nullptr)
599     return make_error<StringError>("Unsupported form for string attribute",
600                                    inconvertibleErrorCode());
601   uint64_t Offset = Value.uval;
602   std::optional<uint32_t> Index;
603   if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx ||
604       Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 ||
605       Form == DW_FORM_strx4) {
606     if (!U)
607       return make_error<StringError>("API limitation - string extraction not "
608                                      "available without a DWARFUnit",
609                                      inconvertibleErrorCode());
610     Expected<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset);
611     Index = Offset;
612     if (!StrOffset)
613       return StrOffset.takeError();
614     Offset = *StrOffset;
615   }
616   // Prefer the Unit's string extractor, because for .dwo it will point to
617   // .debug_str.dwo, while the Context's extractor always uses .debug_str.
618   bool IsDebugLineString = Form == DW_FORM_line_strp;
619   DataExtractor StrData =
620       IsDebugLineString ? C->getLineStringExtractor()
621                         : U ? U->getStringExtractor() : C->getStringExtractor();
622   if (const char *Str = StrData.getCStr(&Offset))
623     return Str;
624   std::string Msg = FormEncodingString(Form).str();
625   if (Index)
626     Msg += (" uses index " + Twine(*Index) + ", but the referenced string").str();
627   Msg += (" offset " + Twine(Offset) + " is beyond " +
628           (IsDebugLineString ? ".debug_line_str" : ".debug_str") + " bounds")
629              .str();
630   return make_error<StringError>(Msg,
631       inconvertibleErrorCode());
632 }
633 
getAsAddress() const634 std::optional<uint64_t> DWARFFormValue::getAsAddress() const {
635   if (auto SA = getAsSectionedAddress())
636     return SA->Address;
637   return std::nullopt;
638 }
639 
getAsSectionedAddress(const ValueType & Value,const dwarf::Form Form,const DWARFUnit * U)640 std::optional<object::SectionedAddress> DWARFFormValue::getAsSectionedAddress(
641     const ValueType &Value, const dwarf::Form Form, const DWARFUnit *U) {
642   if (!doesFormBelongToClass(Form, FC_Address, U ? U->getVersion() : 3))
643     return std::nullopt;
644   bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;
645   if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx ||
646       Form == DW_FORM_addrx1 || Form == DW_FORM_addrx2 ||
647       Form == DW_FORM_addrx3 || Form == DW_FORM_addrx4 || AddrOffset) {
648 
649     uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval;
650     if (!U)
651       return std::nullopt;
652     std::optional<object::SectionedAddress> SA =
653         U->getAddrOffsetSectionItem(Index);
654     if (!SA)
655       return std::nullopt;
656     if (AddrOffset)
657       SA->Address += (Value.uval & 0xffffffff);
658     return SA;
659   }
660   return {{Value.uval, Value.SectionIndex}};
661 }
662 
663 std::optional<object::SectionedAddress>
getAsSectionedAddress() const664 DWARFFormValue::getAsSectionedAddress() const {
665   return getAsSectionedAddress(Value, Form, U);
666 }
667 
getAsRelativeReference() const668 std::optional<uint64_t> DWARFFormValue::getAsRelativeReference() const {
669   switch (Form) {
670   case DW_FORM_ref1:
671   case DW_FORM_ref2:
672   case DW_FORM_ref4:
673   case DW_FORM_ref8:
674   case DW_FORM_ref_udata:
675     if (!U)
676       return std::nullopt;
677     return Value.uval;
678   default:
679     return std::nullopt;
680   }
681 }
682 
getAsDebugInfoReference() const683 std::optional<uint64_t> DWARFFormValue::getAsDebugInfoReference() const {
684   if (Form == DW_FORM_ref_addr)
685     return Value.uval;
686   return std::nullopt;
687 }
688 
getAsSignatureReference() const689 std::optional<uint64_t> DWARFFormValue::getAsSignatureReference() const {
690   if (Form == DW_FORM_ref_sig8)
691     return Value.uval;
692   return std::nullopt;
693 }
694 
getAsSupplementaryReference() const695 std::optional<uint64_t> DWARFFormValue::getAsSupplementaryReference() const {
696   switch (Form) {
697   case DW_FORM_GNU_ref_alt:
698   case DW_FORM_ref_sup4:
699   case DW_FORM_ref_sup8:
700     return Value.uval;
701   default:
702     return std::nullopt;
703   }
704 }
705 
getAsSectionOffset() const706 std::optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
707   if (!isFormClass(FC_SectionOffset))
708     return std::nullopt;
709   return Value.uval;
710 }
711 
getAsUnsignedConstant() const712 std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
713   if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||
714       Form == DW_FORM_sdata)
715     return std::nullopt;
716   return Value.uval;
717 }
718 
getAsSignedConstant() const719 std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const {
720   if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||
721       (Form == DW_FORM_udata &&
722        uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval))
723     return std::nullopt;
724   switch (Form) {
725   case DW_FORM_data4:
726     return int32_t(Value.uval);
727   case DW_FORM_data2:
728     return int16_t(Value.uval);
729   case DW_FORM_data1:
730     return int8_t(Value.uval);
731   case DW_FORM_sdata:
732   case DW_FORM_data8:
733   default:
734     return Value.sval;
735   }
736 }
737 
getAsBlock() const738 std::optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {
739   if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc) &&
740       Form != DW_FORM_data16)
741     return std::nullopt;
742   return ArrayRef(Value.data, Value.uval);
743 }
744 
getAsCStringOffset() const745 std::optional<uint64_t> DWARFFormValue::getAsCStringOffset() const {
746   if (!isFormClass(FC_String) && Form == DW_FORM_string)
747     return std::nullopt;
748   return Value.uval;
749 }
750 
getAsReferenceUVal() const751 std::optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const {
752   if (!isFormClass(FC_Reference))
753     return std::nullopt;
754   return Value.uval;
755 }
756 
757 std::optional<std::string>
getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const758 DWARFFormValue::getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {
759   if (U == nullptr || !isFormClass(FC_Constant))
760     return std::nullopt;
761   DWARFUnit *DLU = const_cast<DWARFUnit *>(U)->getLinkedUnit();
762   if (auto *LT = DLU->getContext().getLineTableForUnit(DLU)) {
763     std::string FileName;
764     if (LT->getFileNameByIndex(Value.uval, DLU->getCompilationDir(), Kind,
765                                FileName))
766       return FileName;
767   }
768   return std::nullopt;
769 }
770 
doesFormBelongToClass(dwarf::Form Form,DWARFFormValue::FormClass FC,uint16_t DwarfVersion)771 bool llvm::dwarf::doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC,
772                            uint16_t DwarfVersion) {
773   // First, check DWARF5 form classes.
774   if (Form < std::size(DWARF5FormClasses) && DWARF5FormClasses[Form] == FC)
775     return true;
776   // Check more forms from extensions and proposals.
777   switch (Form) {
778   case DW_FORM_GNU_ref_alt:
779     return (FC == DWARFFormValue::FC_Reference);
780   case DW_FORM_GNU_addr_index:
781     return (FC == DWARFFormValue::FC_Address);
782   case DW_FORM_GNU_str_index:
783   case DW_FORM_GNU_strp_alt:
784     return (FC == DWARFFormValue::FC_String);
785   case DW_FORM_LLVM_addrx_offset:
786     return (FC == DWARFFormValue::FC_Address);
787   case DW_FORM_strp:
788   case DW_FORM_line_strp:
789     return (FC == DWARFFormValue::FC_SectionOffset);
790   case DW_FORM_data4:
791   case DW_FORM_data8:
792     // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section
793     // offset.
794     return (FC == DWARFFormValue::FC_SectionOffset) && (DwarfVersion <= 3);
795   default:
796     return false;
797   }
798 }
799