1 //===- DWARFFormValue.cpp -------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
10 #include "llvm/ADT/ArrayRef.h"
11 #include "llvm/ADT/None.h"
12 #include "llvm/ADT/Optional.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/BinaryFormat/Dwarf.h"
15 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
16 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
17 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/Format.h"
20 #include "llvm/Support/WithColor.h"
21 #include "llvm/Support/raw_ostream.h"
27 using namespace dwarf
;
29 static const DWARFFormValue::FormClass DWARF5FormClasses
[] = {
30 DWARFFormValue::FC_Unknown
, // 0x0
31 DWARFFormValue::FC_Address
, // 0x01 DW_FORM_addr
32 DWARFFormValue::FC_Unknown
, // 0x02 unused
33 DWARFFormValue::FC_Block
, // 0x03 DW_FORM_block2
34 DWARFFormValue::FC_Block
, // 0x04 DW_FORM_block4
35 DWARFFormValue::FC_Constant
, // 0x05 DW_FORM_data2
36 // --- These can be FC_SectionOffset in DWARF3 and below:
37 DWARFFormValue::FC_Constant
, // 0x06 DW_FORM_data4
38 DWARFFormValue::FC_Constant
, // 0x07 DW_FORM_data8
40 DWARFFormValue::FC_String
, // 0x08 DW_FORM_string
41 DWARFFormValue::FC_Block
, // 0x09 DW_FORM_block
42 DWARFFormValue::FC_Block
, // 0x0a DW_FORM_block1
43 DWARFFormValue::FC_Constant
, // 0x0b DW_FORM_data1
44 DWARFFormValue::FC_Flag
, // 0x0c DW_FORM_flag
45 DWARFFormValue::FC_Constant
, // 0x0d DW_FORM_sdata
46 DWARFFormValue::FC_String
, // 0x0e DW_FORM_strp
47 DWARFFormValue::FC_Constant
, // 0x0f DW_FORM_udata
48 DWARFFormValue::FC_Reference
, // 0x10 DW_FORM_ref_addr
49 DWARFFormValue::FC_Reference
, // 0x11 DW_FORM_ref1
50 DWARFFormValue::FC_Reference
, // 0x12 DW_FORM_ref2
51 DWARFFormValue::FC_Reference
, // 0x13 DW_FORM_ref4
52 DWARFFormValue::FC_Reference
, // 0x14 DW_FORM_ref8
53 DWARFFormValue::FC_Reference
, // 0x15 DW_FORM_ref_udata
54 DWARFFormValue::FC_Indirect
, // 0x16 DW_FORM_indirect
55 DWARFFormValue::FC_SectionOffset
, // 0x17 DW_FORM_sec_offset
56 DWARFFormValue::FC_Exprloc
, // 0x18 DW_FORM_exprloc
57 DWARFFormValue::FC_Flag
, // 0x19 DW_FORM_flag_present
58 DWARFFormValue::FC_String
, // 0x1a DW_FORM_strx
59 DWARFFormValue::FC_Address
, // 0x1b DW_FORM_addrx
60 DWARFFormValue::FC_Reference
, // 0x1c DW_FORM_ref_sup4
61 DWARFFormValue::FC_String
, // 0x1d DW_FORM_strp_sup
62 DWARFFormValue::FC_Constant
, // 0x1e DW_FORM_data16
63 DWARFFormValue::FC_String
, // 0x1f DW_FORM_line_strp
64 DWARFFormValue::FC_Reference
, // 0x20 DW_FORM_ref_sig8
65 DWARFFormValue::FC_Constant
, // 0x21 DW_FORM_implicit_const
66 DWARFFormValue::FC_SectionOffset
, // 0x22 DW_FORM_loclistx
67 DWARFFormValue::FC_SectionOffset
, // 0x23 DW_FORM_rnglistx
68 DWARFFormValue::FC_Reference
, // 0x24 DW_FORM_ref_sup8
69 DWARFFormValue::FC_String
, // 0x25 DW_FORM_strx1
70 DWARFFormValue::FC_String
, // 0x26 DW_FORM_strx2
71 DWARFFormValue::FC_String
, // 0x27 DW_FORM_strx3
72 DWARFFormValue::FC_String
, // 0x28 DW_FORM_strx4
73 DWARFFormValue::FC_Address
, // 0x29 DW_FORM_addrx1
74 DWARFFormValue::FC_Address
, // 0x2a DW_FORM_addrx2
75 DWARFFormValue::FC_Address
, // 0x2b DW_FORM_addrx3
76 DWARFFormValue::FC_Address
, // 0x2c DW_FORM_addrx4
80 DWARFFormValue
DWARFFormValue::createFromSValue(dwarf::Form F
, int64_t V
) {
81 return DWARFFormValue(F
, ValueType(V
));
84 DWARFFormValue
DWARFFormValue::createFromUValue(dwarf::Form F
, uint64_t V
) {
85 return DWARFFormValue(F
, ValueType(V
));
88 DWARFFormValue
DWARFFormValue::createFromPValue(dwarf::Form F
, const char *V
) {
89 return DWARFFormValue(F
, ValueType(V
));
92 DWARFFormValue
DWARFFormValue::createFromBlockValue(dwarf::Form F
,
93 ArrayRef
<uint8_t> D
) {
97 return DWARFFormValue(F
, V
);
100 DWARFFormValue
DWARFFormValue::createFromUnit(dwarf::Form F
, const DWARFUnit
*U
,
101 uint64_t *OffsetPtr
) {
102 DWARFFormValue
FormValue(F
);
103 FormValue
.extractValue(U
->getDebugInfoExtractor(), OffsetPtr
,
104 U
->getFormParams(), U
);
108 bool DWARFFormValue::skipValue(dwarf::Form Form
, DataExtractor DebugInfoData
,
110 const dwarf::FormParams Params
) {
111 bool Indirect
= false;
114 // Blocks of inlined data that have a length field and the data bytes
115 // inlined in the .debug_info.
116 case DW_FORM_exprloc
:
117 case DW_FORM_block
: {
118 uint64_t size
= DebugInfoData
.getULEB128(OffsetPtr
);
122 case DW_FORM_block1
: {
123 uint8_t size
= DebugInfoData
.getU8(OffsetPtr
);
127 case DW_FORM_block2
: {
128 uint16_t size
= DebugInfoData
.getU16(OffsetPtr
);
132 case DW_FORM_block4
: {
133 uint32_t size
= DebugInfoData
.getU32(OffsetPtr
);
138 // Inlined NULL terminated C-strings.
140 DebugInfoData
.getCStr(OffsetPtr
);
144 case DW_FORM_ref_addr
:
145 case DW_FORM_flag_present
:
156 case DW_FORM_ref_sig8
:
157 case DW_FORM_ref_sup4
:
158 case DW_FORM_ref_sup8
:
165 case DW_FORM_sec_offset
:
167 case DW_FORM_strp_sup
:
168 case DW_FORM_line_strp
:
169 case DW_FORM_GNU_ref_alt
:
170 case DW_FORM_GNU_strp_alt
:
171 if (Optional
<uint8_t> FixedSize
=
172 dwarf::getFixedFormByteSize(Form
, Params
)) {
173 *OffsetPtr
+= *FixedSize
;
178 // signed or unsigned LEB 128 values.
180 DebugInfoData
.getSLEB128(OffsetPtr
);
184 case DW_FORM_ref_udata
:
187 case DW_FORM_loclistx
:
188 case DW_FORM_rnglistx
:
189 case DW_FORM_GNU_addr_index
:
190 case DW_FORM_GNU_str_index
:
191 DebugInfoData
.getULEB128(OffsetPtr
);
194 case DW_FORM_indirect
:
196 Form
= static_cast<dwarf::Form
>(DebugInfoData
.getULEB128(OffsetPtr
));
206 bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC
) const {
207 // First, check DWARF5 form classes.
208 if (Form
< makeArrayRef(DWARF5FormClasses
).size() &&
209 DWARF5FormClasses
[Form
] == FC
)
211 // Check more forms from extensions and proposals.
213 case DW_FORM_GNU_ref_alt
:
214 return (FC
== FC_Reference
);
215 case DW_FORM_GNU_addr_index
:
216 return (FC
== FC_Address
);
217 case DW_FORM_GNU_str_index
:
218 case DW_FORM_GNU_strp_alt
:
219 return (FC
== FC_String
);
224 if (FC
== FC_SectionOffset
) {
225 if (Form
== DW_FORM_strp
|| Form
== DW_FORM_line_strp
)
227 // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section
228 // offset. If we don't have a DWARFUnit, default to the old behavior.
229 if (Form
== DW_FORM_data4
|| Form
== DW_FORM_data8
)
230 return !U
|| U
->getVersion() <= 3;
236 bool DWARFFormValue::extractValue(const DWARFDataExtractor
&Data
,
237 uint64_t *OffsetPtr
, dwarf::FormParams FP
,
238 const DWARFContext
*Ctx
,
239 const DWARFUnit
*CU
) {
241 Ctx
= &CU
->getContext();
244 bool Indirect
= false;
245 bool IsBlock
= false;
246 Value
.data
= nullptr;
247 // Read the value for the form into value and follow and DW_FORM_indirect
248 // instances we run into
253 case DW_FORM_ref_addr
: {
255 (Form
== DW_FORM_addr
) ? FP
.AddrSize
: FP
.getRefAddrByteSize();
256 Value
.uval
= Data
.getRelocatedValue(Size
, OffsetPtr
, &Value
.SectionIndex
);
259 case DW_FORM_exprloc
:
261 Value
.uval
= Data
.getULEB128(OffsetPtr
);
265 Value
.uval
= Data
.getU8(OffsetPtr
);
269 Value
.uval
= Data
.getU16(OffsetPtr
);
273 Value
.uval
= Data
.getU32(OffsetPtr
);
281 Value
.uval
= Data
.getU8(OffsetPtr
);
287 Value
.uval
= Data
.getU16(OffsetPtr
);
290 Value
.uval
= Data
.getU24(OffsetPtr
);
294 case DW_FORM_ref_sup4
:
297 Value
.uval
= Data
.getRelocatedValue(4, OffsetPtr
);
301 case DW_FORM_ref_sup8
:
302 Value
.uval
= Data
.getRelocatedValue(8, OffsetPtr
);
305 // Treat this like a 16-byte block.
310 Value
.sval
= Data
.getSLEB128(OffsetPtr
);
313 case DW_FORM_ref_udata
:
314 case DW_FORM_rnglistx
:
315 Value
.uval
= Data
.getULEB128(OffsetPtr
);
318 Value
.cstr
= Data
.getCStr(OffsetPtr
);
320 case DW_FORM_indirect
:
321 Form
= static_cast<dwarf::Form
>(Data
.getULEB128(OffsetPtr
));
325 case DW_FORM_sec_offset
:
326 case DW_FORM_GNU_ref_alt
:
327 case DW_FORM_GNU_strp_alt
:
328 case DW_FORM_line_strp
:
329 case DW_FORM_strp_sup
: {
331 Data
.getRelocatedValue(FP
.getDwarfOffsetByteSize(), OffsetPtr
);
334 case DW_FORM_flag_present
:
337 case DW_FORM_ref_sig8
:
338 Value
.uval
= Data
.getU64(OffsetPtr
);
340 case DW_FORM_GNU_addr_index
:
341 case DW_FORM_GNU_str_index
:
344 Value
.uval
= Data
.getULEB128(OffsetPtr
);
347 // DWARFFormValue::skipValue() will have caught this and caused all
348 // DWARF DIEs to fail to be parsed, so this code is not be reachable.
349 llvm_unreachable("unsupported form");
354 StringRef Str
= Data
.getData().substr(*OffsetPtr
, Value
.uval
);
355 Value
.data
= nullptr;
357 Value
.data
= Str
.bytes_begin();
358 *OffsetPtr
+= Value
.uval
;
365 void DWARFFormValue::dumpSectionedAddress(raw_ostream
&OS
,
366 DIDumpOptions DumpOpts
,
367 object::SectionedAddress SA
) const {
368 OS
<< format("0x%016" PRIx64
, SA
.Address
);
369 dumpAddressSection(U
->getContext().getDWARFObj(), OS
, DumpOpts
,
373 void DWARFFormValue::dumpAddressSection(const DWARFObject
&Obj
, raw_ostream
&OS
,
374 DIDumpOptions DumpOpts
,
375 uint64_t SectionIndex
) {
376 if (!DumpOpts
.Verbose
|| SectionIndex
== -1ULL)
378 ArrayRef
<SectionName
> SectionNames
= Obj
.getSectionNames();
379 const auto &SecRef
= SectionNames
[SectionIndex
];
381 OS
<< " \"" << SecRef
.Name
<< '\"';
383 // Print section index if name is not unique.
384 if (!SecRef
.IsNameUnique
)
385 OS
<< format(" [%" PRIu64
"]", SectionIndex
);
388 void DWARFFormValue::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
389 uint64_t UValue
= Value
.uval
;
390 bool CURelativeOffset
= false;
391 raw_ostream
&AddrOS
= DumpOpts
.ShowAddresses
392 ? WithColor(OS
, HighlightColor::Address
).get()
396 dumpSectionedAddress(AddrOS
, DumpOpts
, {Value
.uval
, Value
.SectionIndex
});
403 case DW_FORM_GNU_addr_index
: {
405 OS
<< "<invalid dwarf unit>";
408 Optional
<object::SectionedAddress
> A
= U
->getAddrOffsetSectionItem(UValue
);
409 if (!A
|| DumpOpts
.Verbose
)
410 AddrOS
<< format("indexed (%8.8x) address = ", (uint32_t)UValue
);
412 dumpSectionedAddress(AddrOS
, DumpOpts
, *A
);
414 OS
<< "<no .debug_addr section>";
417 case DW_FORM_flag_present
:
422 OS
<< format("0x%02x", (uint8_t)UValue
);
425 OS
<< format("0x%04x", (uint16_t)UValue
);
428 OS
<< format("0x%08x", (uint32_t)UValue
);
430 case DW_FORM_ref_sig8
:
431 AddrOS
<< format("0x%016" PRIx64
, UValue
);
434 OS
<< format("0x%016" PRIx64
, UValue
);
437 OS
<< format_bytes(ArrayRef
<uint8_t>(Value
.data
, 16), None
, 16, 16);
441 OS
.write_escaped(Value
.cstr
);
444 case DW_FORM_exprloc
:
451 case DW_FORM_exprloc
:
453 AddrOS
<< format("<0x%" PRIx64
"> ", UValue
);
456 AddrOS
<< format("<0x%2.2x> ", (uint8_t)UValue
);
459 AddrOS
<< format("<0x%4.4x> ", (uint16_t)UValue
);
462 AddrOS
<< format("<0x%8.8x> ", (uint32_t)UValue
);
468 const uint8_t *DataPtr
= Value
.data
;
470 // UValue contains size of block
471 const uint8_t *EndDataPtr
= DataPtr
+ UValue
;
472 while (DataPtr
< EndDataPtr
) {
473 AddrOS
<< format("%2.2x ", *DataPtr
);
488 if (DumpOpts
.Verbose
)
489 OS
<< format(" .debug_str[0x%8.8x] = ", (uint32_t)UValue
);
492 case DW_FORM_line_strp
:
493 if (DumpOpts
.Verbose
)
494 OS
<< format(" .debug_line_str[0x%8.8x] = ", (uint32_t)UValue
);
502 case DW_FORM_GNU_str_index
:
503 if (DumpOpts
.Verbose
)
504 OS
<< format("indexed (%8.8x) string = ", (uint32_t)UValue
);
507 case DW_FORM_GNU_strp_alt
:
508 if (DumpOpts
.Verbose
)
509 OS
<< format("alt indirect string, offset: 0x%" PRIx64
"", UValue
);
512 case DW_FORM_ref_addr
:
513 AddrOS
<< format("0x%016" PRIx64
, UValue
);
516 CURelativeOffset
= true;
517 if (DumpOpts
.Verbose
)
518 AddrOS
<< format("cu + 0x%2.2x", (uint8_t)UValue
);
521 CURelativeOffset
= true;
522 if (DumpOpts
.Verbose
)
523 AddrOS
<< format("cu + 0x%4.4x", (uint16_t)UValue
);
526 CURelativeOffset
= true;
527 if (DumpOpts
.Verbose
)
528 AddrOS
<< format("cu + 0x%4.4x", (uint32_t)UValue
);
531 CURelativeOffset
= true;
532 if (DumpOpts
.Verbose
)
533 AddrOS
<< format("cu + 0x%8.8" PRIx64
, UValue
);
535 case DW_FORM_ref_udata
:
536 CURelativeOffset
= true;
537 if (DumpOpts
.Verbose
)
538 AddrOS
<< format("cu + 0x%" PRIx64
, UValue
);
540 case DW_FORM_GNU_ref_alt
:
541 AddrOS
<< format("<alt 0x%" PRIx64
">", UValue
);
544 // All DW_FORM_indirect attributes should be resolved prior to calling
546 case DW_FORM_indirect
:
547 OS
<< "DW_FORM_indirect";
550 case DW_FORM_rnglistx
:
551 OS
<< format("indexed (0x%x) rangelist = ", (uint32_t)UValue
);
554 // Should be formatted to 64-bit for DWARF64.
555 case DW_FORM_sec_offset
:
556 AddrOS
<< format("0x%08x", (uint32_t)UValue
);
560 OS
<< format("DW_FORM(0x%4.4x)", Form
);
564 if (CURelativeOffset
) {
565 if (DumpOpts
.Verbose
)
567 if (DumpOpts
.ShowAddresses
)
568 WithColor(OS
, HighlightColor::Address
).get()
569 << format("0x%8.8" PRIx64
, UValue
+ (U
? U
->getOffset() : 0));
570 if (DumpOpts
.Verbose
)
575 void DWARFFormValue::dumpString(raw_ostream
&OS
) const {
576 Optional
<const char *> DbgStr
= getAsCString();
577 if (DbgStr
.hasValue()) {
578 auto COS
= WithColor(OS
, HighlightColor::String
);
580 COS
.get().write_escaped(DbgStr
.getValue());
585 Optional
<const char *> DWARFFormValue::getAsCString() const {
586 if (!isFormClass(FC_String
))
588 if (Form
== DW_FORM_string
)
590 // FIXME: Add support for DW_FORM_GNU_strp_alt
591 if (Form
== DW_FORM_GNU_strp_alt
|| C
== nullptr)
593 uint64_t Offset
= Value
.uval
;
594 if (Form
== DW_FORM_line_strp
) {
595 // .debug_line_str is tracked in the Context.
596 if (const char *Str
= C
->getLineStringExtractor().getCStr(&Offset
))
600 if (Form
== DW_FORM_GNU_str_index
|| Form
== DW_FORM_strx
||
601 Form
== DW_FORM_strx1
|| Form
== DW_FORM_strx2
|| Form
== DW_FORM_strx3
||
602 Form
== DW_FORM_strx4
) {
605 Optional
<uint64_t> StrOffset
= U
->getStringOffsetSectionItem(Offset
);
610 // Prefer the Unit's string extractor, because for .dwo it will point to
611 // .debug_str.dwo, while the Context's extractor always uses .debug_str.
613 if (const char *Str
= U
->getStringExtractor().getCStr(&Offset
))
617 if (const char *Str
= C
->getStringExtractor().getCStr(&Offset
))
622 Optional
<uint64_t> DWARFFormValue::getAsAddress() const {
623 if (auto SA
= getAsSectionedAddress())
628 Optional
<object::SectionedAddress
>
629 DWARFFormValue::getAsSectionedAddress() const {
630 if (!isFormClass(FC_Address
))
632 if (Form
== DW_FORM_GNU_addr_index
|| Form
== DW_FORM_addrx
) {
633 uint32_t Index
= Value
.uval
;
636 Optional
<object::SectionedAddress
> SA
= U
->getAddrOffsetSectionItem(Index
);
641 return {{Value
.uval
, Value
.SectionIndex
}};
644 Optional
<uint64_t> DWARFFormValue::getAsReference() const {
645 if (auto R
= getAsRelativeReference())
646 return R
->Unit
? R
->Unit
->getOffset() + R
->Offset
: R
->Offset
;
650 Optional
<DWARFFormValue::UnitOffset
> DWARFFormValue::getAsRelativeReference() const {
651 if (!isFormClass(FC_Reference
))
658 case DW_FORM_ref_udata
:
661 return UnitOffset
{const_cast<DWARFUnit
*>(U
), Value
.uval
};
662 case DW_FORM_ref_addr
:
663 case DW_FORM_ref_sig8
:
664 case DW_FORM_GNU_ref_alt
:
665 return UnitOffset
{nullptr, Value
.uval
};
671 Optional
<uint64_t> DWARFFormValue::getAsSectionOffset() const {
672 if (!isFormClass(FC_SectionOffset
))
677 Optional
<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
678 if ((!isFormClass(FC_Constant
) && !isFormClass(FC_Flag
)) ||
679 Form
== DW_FORM_sdata
)
684 Optional
<int64_t> DWARFFormValue::getAsSignedConstant() const {
685 if ((!isFormClass(FC_Constant
) && !isFormClass(FC_Flag
)) ||
686 (Form
== DW_FORM_udata
&&
687 uint64_t(std::numeric_limits
<int64_t>::max()) < Value
.uval
))
691 return int32_t(Value
.uval
);
693 return int16_t(Value
.uval
);
695 return int8_t(Value
.uval
);
703 Optional
<ArrayRef
<uint8_t>> DWARFFormValue::getAsBlock() const {
704 if (!isFormClass(FC_Block
) && !isFormClass(FC_Exprloc
) &&
705 Form
!= DW_FORM_data16
)
707 return makeArrayRef(Value
.data
, Value
.uval
);
710 Optional
<uint64_t> DWARFFormValue::getAsCStringOffset() const {
711 if (!isFormClass(FC_String
) && Form
== DW_FORM_string
)
716 Optional
<uint64_t> DWARFFormValue::getAsReferenceUVal() const {
717 if (!isFormClass(FC_Reference
))