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 case DW_FORM_loclistx
:
316 Value
.uval
= Data
.getULEB128(OffsetPtr
);
319 Value
.cstr
= Data
.getCStr(OffsetPtr
);
321 case DW_FORM_indirect
:
322 Form
= static_cast<dwarf::Form
>(Data
.getULEB128(OffsetPtr
));
326 case DW_FORM_sec_offset
:
327 case DW_FORM_GNU_ref_alt
:
328 case DW_FORM_GNU_strp_alt
:
329 case DW_FORM_line_strp
:
330 case DW_FORM_strp_sup
: {
332 Data
.getRelocatedValue(FP
.getDwarfOffsetByteSize(), OffsetPtr
);
335 case DW_FORM_flag_present
:
338 case DW_FORM_ref_sig8
:
339 Value
.uval
= Data
.getU64(OffsetPtr
);
341 case DW_FORM_GNU_addr_index
:
342 case DW_FORM_GNU_str_index
:
345 Value
.uval
= Data
.getULEB128(OffsetPtr
);
348 // DWARFFormValue::skipValue() will have caught this and caused all
349 // DWARF DIEs to fail to be parsed, so this code is not be reachable.
350 llvm_unreachable("unsupported form");
355 StringRef Str
= Data
.getData().substr(*OffsetPtr
, Value
.uval
);
356 Value
.data
= nullptr;
358 Value
.data
= Str
.bytes_begin();
359 *OffsetPtr
+= Value
.uval
;
366 void DWARFFormValue::dumpSectionedAddress(raw_ostream
&OS
,
367 DIDumpOptions DumpOpts
,
368 object::SectionedAddress SA
) const {
369 OS
<< format("0x%016" PRIx64
, SA
.Address
);
370 dumpAddressSection(U
->getContext().getDWARFObj(), OS
, DumpOpts
,
374 void DWARFFormValue::dumpAddressSection(const DWARFObject
&Obj
, raw_ostream
&OS
,
375 DIDumpOptions DumpOpts
,
376 uint64_t SectionIndex
) {
377 if (!DumpOpts
.Verbose
|| SectionIndex
== -1ULL)
379 ArrayRef
<SectionName
> SectionNames
= Obj
.getSectionNames();
380 const auto &SecRef
= SectionNames
[SectionIndex
];
382 OS
<< " \"" << SecRef
.Name
<< '\"';
384 // Print section index if name is not unique.
385 if (!SecRef
.IsNameUnique
)
386 OS
<< format(" [%" PRIu64
"]", SectionIndex
);
389 void DWARFFormValue::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) const {
390 uint64_t UValue
= Value
.uval
;
391 bool CURelativeOffset
= false;
392 raw_ostream
&AddrOS
= DumpOpts
.ShowAddresses
393 ? WithColor(OS
, HighlightColor::Address
).get()
397 dumpSectionedAddress(AddrOS
, DumpOpts
, {Value
.uval
, Value
.SectionIndex
});
404 case DW_FORM_GNU_addr_index
: {
406 OS
<< "<invalid dwarf unit>";
409 Optional
<object::SectionedAddress
> A
= U
->getAddrOffsetSectionItem(UValue
);
410 if (!A
|| DumpOpts
.Verbose
)
411 AddrOS
<< format("indexed (%8.8x) address = ", (uint32_t)UValue
);
413 dumpSectionedAddress(AddrOS
, DumpOpts
, *A
);
415 OS
<< "<unresolved>";
418 case DW_FORM_flag_present
:
423 OS
<< format("0x%02x", (uint8_t)UValue
);
426 OS
<< format("0x%04x", (uint16_t)UValue
);
429 OS
<< format("0x%08x", (uint32_t)UValue
);
431 case DW_FORM_ref_sig8
:
432 AddrOS
<< format("0x%016" PRIx64
, UValue
);
435 OS
<< format("0x%016" PRIx64
, UValue
);
438 OS
<< format_bytes(ArrayRef
<uint8_t>(Value
.data
, 16), None
, 16, 16);
442 OS
.write_escaped(Value
.cstr
);
445 case DW_FORM_exprloc
:
452 case DW_FORM_exprloc
:
454 AddrOS
<< format("<0x%" PRIx64
"> ", UValue
);
457 AddrOS
<< format("<0x%2.2x> ", (uint8_t)UValue
);
460 AddrOS
<< format("<0x%4.4x> ", (uint16_t)UValue
);
463 AddrOS
<< format("<0x%8.8x> ", (uint32_t)UValue
);
469 const uint8_t *DataPtr
= Value
.data
;
471 // UValue contains size of block
472 const uint8_t *EndDataPtr
= DataPtr
+ UValue
;
473 while (DataPtr
< EndDataPtr
) {
474 AddrOS
<< format("%2.2x ", *DataPtr
);
489 if (DumpOpts
.Verbose
)
490 OS
<< format(" .debug_str[0x%8.8x] = ", (uint32_t)UValue
);
493 case DW_FORM_line_strp
:
494 if (DumpOpts
.Verbose
)
495 OS
<< format(" .debug_line_str[0x%8.8x] = ", (uint32_t)UValue
);
503 case DW_FORM_GNU_str_index
:
504 if (DumpOpts
.Verbose
)
505 OS
<< format("indexed (%8.8x) string = ", (uint32_t)UValue
);
508 case DW_FORM_GNU_strp_alt
:
509 if (DumpOpts
.Verbose
)
510 OS
<< format("alt indirect string, offset: 0x%" PRIx64
"", UValue
);
513 case DW_FORM_ref_addr
:
514 AddrOS
<< format("0x%016" PRIx64
, UValue
);
517 CURelativeOffset
= true;
518 if (DumpOpts
.Verbose
)
519 AddrOS
<< format("cu + 0x%2.2x", (uint8_t)UValue
);
522 CURelativeOffset
= true;
523 if (DumpOpts
.Verbose
)
524 AddrOS
<< format("cu + 0x%4.4x", (uint16_t)UValue
);
527 CURelativeOffset
= true;
528 if (DumpOpts
.Verbose
)
529 AddrOS
<< format("cu + 0x%4.4x", (uint32_t)UValue
);
532 CURelativeOffset
= true;
533 if (DumpOpts
.Verbose
)
534 AddrOS
<< format("cu + 0x%8.8" PRIx64
, UValue
);
536 case DW_FORM_ref_udata
:
537 CURelativeOffset
= true;
538 if (DumpOpts
.Verbose
)
539 AddrOS
<< format("cu + 0x%" PRIx64
, UValue
);
541 case DW_FORM_GNU_ref_alt
:
542 AddrOS
<< format("<alt 0x%" PRIx64
">", UValue
);
545 // All DW_FORM_indirect attributes should be resolved prior to calling
547 case DW_FORM_indirect
:
548 OS
<< "DW_FORM_indirect";
551 case DW_FORM_rnglistx
:
552 OS
<< format("indexed (0x%x) rangelist = ", (uint32_t)UValue
);
555 case DW_FORM_loclistx
:
556 OS
<< format("indexed (0x%x) loclist = ", (uint32_t)UValue
);
559 // Should be formatted to 64-bit for DWARF64.
560 case DW_FORM_sec_offset
:
561 AddrOS
<< format("0x%08x", (uint32_t)UValue
);
565 OS
<< format("DW_FORM(0x%4.4x)", Form
);
569 if (CURelativeOffset
) {
570 if (DumpOpts
.Verbose
)
572 if (DumpOpts
.ShowAddresses
)
573 WithColor(OS
, HighlightColor::Address
).get()
574 << format("0x%8.8" PRIx64
, UValue
+ (U
? U
->getOffset() : 0));
575 if (DumpOpts
.Verbose
)
580 void DWARFFormValue::dumpString(raw_ostream
&OS
) const {
581 Optional
<const char *> DbgStr
= getAsCString();
582 if (DbgStr
.hasValue()) {
583 auto COS
= WithColor(OS
, HighlightColor::String
);
585 COS
.get().write_escaped(DbgStr
.getValue());
590 Optional
<const char *> DWARFFormValue::getAsCString() const {
591 if (!isFormClass(FC_String
))
593 if (Form
== DW_FORM_string
)
595 // FIXME: Add support for DW_FORM_GNU_strp_alt
596 if (Form
== DW_FORM_GNU_strp_alt
|| C
== nullptr)
598 uint64_t Offset
= Value
.uval
;
599 if (Form
== DW_FORM_line_strp
) {
600 // .debug_line_str is tracked in the Context.
601 if (const char *Str
= C
->getLineStringExtractor().getCStr(&Offset
))
605 if (Form
== DW_FORM_GNU_str_index
|| Form
== DW_FORM_strx
||
606 Form
== DW_FORM_strx1
|| Form
== DW_FORM_strx2
|| Form
== DW_FORM_strx3
||
607 Form
== DW_FORM_strx4
) {
610 Optional
<uint64_t> StrOffset
= U
->getStringOffsetSectionItem(Offset
);
615 // Prefer the Unit's string extractor, because for .dwo it will point to
616 // .debug_str.dwo, while the Context's extractor always uses .debug_str.
618 if (const char *Str
= U
->getStringExtractor().getCStr(&Offset
))
622 if (const char *Str
= C
->getStringExtractor().getCStr(&Offset
))
627 Optional
<uint64_t> DWARFFormValue::getAsAddress() const {
628 if (auto SA
= getAsSectionedAddress())
633 Optional
<object::SectionedAddress
>
634 DWARFFormValue::getAsSectionedAddress() const {
635 if (!isFormClass(FC_Address
))
637 if (Form
== DW_FORM_GNU_addr_index
|| Form
== DW_FORM_addrx
) {
638 uint32_t Index
= Value
.uval
;
641 Optional
<object::SectionedAddress
> SA
= U
->getAddrOffsetSectionItem(Index
);
646 return {{Value
.uval
, Value
.SectionIndex
}};
649 Optional
<uint64_t> DWARFFormValue::getAsReference() const {
650 if (auto R
= getAsRelativeReference())
651 return R
->Unit
? R
->Unit
->getOffset() + R
->Offset
: R
->Offset
;
655 Optional
<DWARFFormValue::UnitOffset
> DWARFFormValue::getAsRelativeReference() const {
656 if (!isFormClass(FC_Reference
))
663 case DW_FORM_ref_udata
:
666 return UnitOffset
{const_cast<DWARFUnit
*>(U
), Value
.uval
};
667 case DW_FORM_ref_addr
:
668 case DW_FORM_ref_sig8
:
669 case DW_FORM_GNU_ref_alt
:
670 return UnitOffset
{nullptr, Value
.uval
};
676 Optional
<uint64_t> DWARFFormValue::getAsSectionOffset() const {
677 if (!isFormClass(FC_SectionOffset
))
682 Optional
<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
683 if ((!isFormClass(FC_Constant
) && !isFormClass(FC_Flag
)) ||
684 Form
== DW_FORM_sdata
)
689 Optional
<int64_t> DWARFFormValue::getAsSignedConstant() const {
690 if ((!isFormClass(FC_Constant
) && !isFormClass(FC_Flag
)) ||
691 (Form
== DW_FORM_udata
&&
692 uint64_t(std::numeric_limits
<int64_t>::max()) < Value
.uval
))
696 return int32_t(Value
.uval
);
698 return int16_t(Value
.uval
);
700 return int8_t(Value
.uval
);
708 Optional
<ArrayRef
<uint8_t>> DWARFFormValue::getAsBlock() const {
709 if (!isFormClass(FC_Block
) && !isFormClass(FC_Exprloc
) &&
710 Form
!= DW_FORM_data16
)
712 return makeArrayRef(Value
.data
, Value
.uval
);
715 Optional
<uint64_t> DWARFFormValue::getAsCStringOffset() const {
716 if (!isFormClass(FC_String
) && Form
== DW_FORM_string
)
721 Optional
<uint64_t> DWARFFormValue::getAsReferenceUVal() const {
722 if (!isFormClass(FC_Reference
))