[llvm] [DWARFLinker] Point DW_AT_import at the unit root, not the unit header (PR #219721)
Arcadiy Ivanov via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 3 10:27:23 PDT 2026
https://github.com/arcivanov updated https://github.com/llvm/llvm-project/pull/219721
>From 4e18b5a2b3c997c1bfa70084b7104e9ab9486afb Mon Sep 17 00:00:00 2001
From: Arcadiy Ivanov <arcadiy at ivanov.biz>
Date: Fri, 28 Aug 2026 03:09:13 -0400
Subject: [PATCH 1/2] [DWARFLinker] Key str_offsets_base and unit_type on the
unit root
Fix DWARFv5 output for a unit whose root is DW_TAG_partial_unit, as
produced by dwz. The classic and parallel linkers rewrite strings into
DW_FORM_strx but add DW_AT_str_offsets_base only to a
DW_TAG_compile_unit root, so every string in a partial unit reads back
empty. Both also write DW_UT_compile into every unit header,
contradicting a partial unit root.
Add DW_AT_str_offsets_base to the unit root whatever its tag, and emit
DW_UT_partial for a DW_TAG_partial_unit root. Its header has the same
layout as DW_UT_compile.
The test links a partial unit with both linkers, with and without
garbage collection, and checks the unit type, the attribute, the strings
and --verify. The update mode runs pass --build-accelerator, because
--no-garbage-collection alone copies the file without linking it.
Fixes #219365.
Assisted-by: Claude Code
---
llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp | 4 +-
.../lib/DWARFLinker/Classic/DWARFStreamer.cpp | 4 +-
.../Parallel/DIEAttributeCloner.cpp | 6 +-
.../DWARFLinker/Parallel/DWARFEmitterImpl.cpp | 4 +-
.../ELF/X86/dwarf5-partial-unit.test | 120 ++++++++++++++++++
5 files changed, 131 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-partial-unit.test
diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
index 454143ec001209..9254a33dee60d8 100644
--- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
@@ -2013,8 +2013,8 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
}
}
- if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
- Die->getTag() == dwarf::DW_TAG_compile_unit) {
+ if (Die == Unit.getOutputUnitDIE() && Unit.getOrigUnit().getVersion() >= 5 &&
+ !AttrInfo.AttrStrOffsetBaseSeen) {
// No DW_AT_str_offsets_base seen, add it to the DIE.
Die->addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
dwarf::DW_FORM_sec_offset, DIEInteger(8));
diff --git a/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp
index c6ccc71889fc41..26c0bc00a73898 100644
--- a/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp
@@ -188,7 +188,9 @@ void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit,
Asm->emitInt16(DwarfVersion);
if (DwarfVersion >= 5) {
- Asm->emitInt8(dwarf::DW_UT_compile);
+ dwarf::Tag RootTag = Unit.getOutputUnitDIE()->getTag();
+ Asm->emitInt8(RootTag == dwarf::DW_TAG_partial_unit ? dwarf::DW_UT_partial
+ : dwarf::DW_UT_compile);
Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
// We share one abbreviations table across all units so it's always at the
// start of the section.
diff --git a/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp b/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp
index 68d7b9d72cf618..67545ee03d15b5 100644
--- a/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp
+++ b/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp
@@ -115,10 +115,10 @@ void DIEAttributeCloner::clone() {
}
// We convert source strings into the indexed form for DWARFv5.
- // Check if original compile unit already has DW_AT_str_offsets_base
+ // Check if original unit already has DW_AT_str_offsets_base
// attribute.
- if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
- InUnit.getVersion() >= 5 && !AttrInfo.HasStringOffsetBaseAttr) {
+ if (InputDIEIdx == 0 && InUnit.getVersion() >= 5 &&
+ !AttrInfo.HasStringOffsetBaseAttr && OutUnit.isCompileUnit()) {
DebugInfoOutputSection.notePatchWithOffsetUpdate(
DebugOffsetPatch{AttrOutOffset,
&OutUnit->getOrCreateSectionDescriptor(
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp
index 18d94ac2d834ee..efd70eaef0d266 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp
@@ -139,7 +139,9 @@ void DwarfEmitterImpl::emitCompileUnitHeader(DwarfUnit &Unit) {
Asm->emitInt16(Unit.getVersion());
if (Unit.getVersion() >= 5) {
- Asm->emitInt8(dwarf::DW_UT_compile);
+ dwarf::Tag RootTag = Unit.getTag();
+ Asm->emitInt8(RootTag == dwarf::DW_TAG_partial_unit ? dwarf::DW_UT_partial
+ : dwarf::DW_UT_compile);
Asm->emitInt8(Unit.getFormParams().AddrSize);
// Proper offset to the abbreviations table will be set later.
Asm->emitInt32(0);
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-partial-unit.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-partial-unit.test
new file mode 100644
index 00000000000000..6b9185defb2af6
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-partial-unit.test
@@ -0,0 +1,120 @@
+## Check that both linkers emit a DWARFv5 partial unit with a DW_UT_partial
+## header and a DW_AT_str_offsets_base.
+
+# RUN: yaml2obj %s -o %t.o
+
+# RUN: llvm-dwarfutil %t.o %t1
+# RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s
+# RUN: llvm-dwarfdump --verify %t1 | FileCheck %s --check-prefix=VERIFY
+
+# RUN: llvm-dwarfutil --linker parallel %t.o %t2
+# RUN: llvm-dwarfdump -a --verbose %t2 | FileCheck %s
+# RUN: llvm-dwarfdump --verify %t2 | FileCheck %s --check-prefix=VERIFY
+
+## Without --build-accelerator, --no-garbage-collection does not run the linker.
+# RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %t.o %t3
+# RUN: llvm-dwarfdump -a --verbose %t3 | FileCheck %s
+# RUN: llvm-dwarfdump --verify %t3 | FileCheck %s --check-prefix=VERIFY
+
+# RUN: llvm-dwarfutil --linker parallel --no-garbage-collection --build-accelerator=DWARF %t.o %t4
+# RUN: llvm-dwarfdump -a --verbose %t4 | FileCheck %s
+# RUN: llvm-dwarfdump --verify %t4 | FileCheck %s --check-prefix=VERIFY
+
+#CHECK: .debug_info contents:
+#CHECK: Compile Unit: {{.*}} version = 0x0005, unit_type = DW_UT_partial
+
+#CHECK: DW_TAG_partial_unit
+#CHECK: DW_AT_producer [DW_FORM_strx] {{.*}} "by_hand"
+#CHECK: DW_AT_name [DW_FORM_strx] {{.*}} "PU1"
+#CHECK: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008)
+
+#CHECK: DW_TAG_subprogram
+#CHECK: DW_AT_name [DW_FORM_strx] {{.*}} "foo1"
+#CHECK: DW_TAG_subprogram
+#CHECK: DW_AT_name [DW_FORM_strx] {{.*}} "foo2"
+
+#VERIFY: No errors.
+
+## DW_AT_ranges keeps the unit alive under garbage collection, and
+## DW_AT_addr_base resolves the ranges the linker rewrites.
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1130
+ Size: 0x30
+ - Name: .debug_rnglists
+ Type: SHT_PROGBITS
+ Flags: [ ]
+ Content: "1d0000000500080000000000073011000000000000100750110000000000001000"
+ - Name: .debug_addr
+ Type: SHT_PROGBITS
+ Flags: [ ]
+ Content: "0c000000050008003011000000000000"
+DWARF:
+ debug_abbrev:
+ - Table:
+ - Tag: DW_TAG_partial_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_producer
+ Form: DW_FORM_string
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_ranges
+ Form: DW_FORM_sec_offset
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_addr_base
+ Form: DW_FORM_sec_offset
+ - Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data8
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref4
+ - Tag: DW_TAG_base_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ debug_info:
+ - Version: 5
+ UnitType: DW_UT_partial
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - CStr: PU1
+ - Value: 0xc
+ - Value: 0x0
+ - Value: 0x8
+ - AbbrCode: 2
+ Values:
+ - CStr: foo1
+ - Value: 0x1130
+ - Value: 0x10
+## 0x5d is the offset of the DW_TAG_base_type DIE below.
+ - Value: 0x5d
+ - AbbrCode: 2
+ Values:
+ - CStr: foo2
+ - Value: 0x1150
+ - Value: 0x10
+ - Value: 0x5d
+ - AbbrCode: 3
+ Values:
+ - CStr: int
+ - AbbrCode: 0
+...
>From 1c0b06581e3fdcb7a1a7afcb897f5166ed8d41ed Mon Sep 17 00:00:00 2001
From: Arcadiy Ivanov <arcadiy at ivanov.biz>
Date: Sat, 29 Aug 2026 16:20:25 -0400
Subject: [PATCH 2/2] [DWARFLinker] Point DW_AT_import at the unit root, not
the unit header
The classic linker rewrote a reference to a unit root DIE, such as
DW_AT_import on DW_TAG_imported_unit, to the start of the referenced
unit's header. A unit root is cloned into its unit's output DIE and
never gets a DIEInfo::Clone, so cloneDieReferenceAttribute() created a
placeholder that never got an offset. llvm-dwarfdump --verify rejects
the result, and assertions builds abort.
Resolve a reference to a unit root through that unit's output DIE. A
unit can import one cloned after it, so create the output DIEs of all
emitted units before cloning starts. StartOffset is unset at that point,
so createOutputDIE() no longer copies it into the DIEUnit;
setStartOffset() already does.
The test imports one unit from units cloned before and after it. The
imported unit is a DWARFv5 or DWARFv4 compile unit or a partial unit
with no code, linked by both linkers with and without garbage
collection. Update mode omits --verify for the partial unit because of
#219720.
Fixes #219621.
Assisted-by: Claude Code
---
.../Classic/DWARFLinkerCompileUnit.h | 12 +-
llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp | 29 +-
.../llvm-dwarfutil/ELF/X86/imported-unit.test | 443 ++++++++++++++++++
3 files changed, 466 insertions(+), 18 deletions(-)
create mode 100644 llvm/test/tools/llvm-dwarfutil/ELF/X86/imported-unit.test
diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h
index 538572338dc8bc..c679219fcebe9e 100644
--- a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h
+++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h
@@ -131,13 +131,7 @@ class CompileUnit {
unsigned getUniqueID() const { return ID; }
- void createOutputDIE() {
- NewUnit.emplace(OrigUnit.getUnitDIE().getTag());
-
- // Propogate the section offset so that DIEntry can compute
- // correct absolute offsets for DW_FORM_ref_addr references
- NewUnit->setDebugSectionOffset(StartOffset);
- }
+ void createOutputDIE() { NewUnit.emplace(OrigUnit.getUnitDIE().getTag()); }
DIE *getOutputUnitDIE() const {
if (NewUnit)
@@ -295,8 +289,8 @@ class CompileUnit {
std::optional<BasicDIEUnit> NewUnit;
MCSymbol *LabelBegin = nullptr;
- uint64_t StartOffset;
- uint64_t NextUnitOffset;
+ uint64_t StartOffset = 0;
+ uint64_t NextUnitOffset = 0;
std::optional<uint64_t> LowPc;
uint64_t HighPc = 0;
diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
index 9254a33dee60d8..b8618fa69e20b1 100644
--- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
@@ -1204,13 +1204,19 @@ unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
return U.getRefAddrByteSize();
}
- if (!RefInfo.Clone) {
- // We haven't cloned this DIE yet. Just create an empty one and
- // store it. It'll get really cloned when we process it.
- RefInfo.UnclonedReference = true;
- RefInfo.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag()));
+ if (RefUnit->getOrigUnit().getDIEIndex(RefDie) == 0) {
+ // A unit root is cloned into the unit's output DIE, not a DIEInfo::Clone.
+ NewRefDie = RefUnit->getOutputUnitDIE();
+ assert(NewRefDie && "referenced unit root has no output DIE");
+ } else {
+ if (!RefInfo.Clone) {
+ // We haven't cloned this DIE yet. Just create an empty one and
+ // store it. It'll get really cloned when we process it.
+ RefInfo.UnclonedReference = true;
+ RefInfo.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag()));
+ }
+ NewRefDie = RefInfo.Clone;
}
- NewRefDie = RefInfo.Clone;
if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
(Unit.hasODR() && isODRAttribute(AttrSpec.Attr))) {
@@ -2900,6 +2906,12 @@ Expected<uint64_t> DWARFLinker::DIECloner::cloneAllCompileUnits(
(Emitter == nullptr) ? 0 : Emitter->getDebugInfoSectionSize();
const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
+ // A unit may refer to the root of a unit cloned after it, so create the
+ // output DIEs of all emitted units first.
+ for (auto &CurrentUnit : CompileUnits)
+ if (CurrentUnit->getOrigUnit().getUnitDIE() && CurrentUnit->getInfo(0).Keep)
+ CurrentUnit->createOutputDIE();
+
for (auto &CurrentUnit : CompileUnits) {
const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11;
@@ -2909,13 +2921,12 @@ Expected<uint64_t> DWARFLinker::DIECloner::cloneAllCompileUnits(
OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
continue;
}
- if (CurrentUnit->getInfo(0).Keep) {
+ if (DIE *OutputDIE = CurrentUnit->getOutputUnitDIE()) {
// Clone the InputDIE into your Unit DIE in our compile unit since it
// already has a DIE inside of it.
- CurrentUnit->createOutputDIE();
rememberUnitForMacroOffset(*CurrentUnit);
cloneDIE(InputDIE, File, *CurrentUnit, 0 /* PC offset */, UnitHeaderSize,
- 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE());
+ 0, IsLittleEndian, OutputDIE);
}
OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/imported-unit.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/imported-unit.test
new file mode 100644
index 00000000000000..94d7f8057d2ca5
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/imported-unit.test
@@ -0,0 +1,443 @@
+## Check that DW_AT_import is rewritten to the offset of the imported unit's
+## root DIE, not of its header. U01 imports U02, which is cloned after it, and
+## U03 imports U02, which is cloned before it.
+
+## DWARFv5 compile units.
+# RUN: yaml2obj --docnum=1 %s -o %t1.o
+
+# RUN: llvm-dwarfutil %t1.o %t1.classic
+# RUN: llvm-dwarfdump --debug-info %t1.classic | FileCheck %s -DU02TAG=compile_unit
+# RUN: llvm-dwarfdump --verify %t1.classic
+
+# RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %t1.o %t1.classic.upd
+# RUN: llvm-dwarfdump --debug-info %t1.classic.upd | FileCheck %s -DU02TAG=compile_unit
+# RUN: llvm-dwarfdump --verify %t1.classic.upd
+
+# RUN: llvm-dwarfutil --linker parallel %t1.o %t1.parallel
+# RUN: llvm-dwarfdump --debug-info %t1.parallel | FileCheck %s -DU02TAG=compile_unit
+# RUN: llvm-dwarfdump --verify %t1.parallel
+
+# RUN: llvm-dwarfutil --linker parallel --no-garbage-collection --build-accelerator=DWARF %t1.o %t1.parallel.upd
+# RUN: llvm-dwarfdump --debug-info %t1.parallel.upd | FileCheck %s -DU02TAG=compile_unit
+# RUN: llvm-dwarfdump --verify %t1.parallel.upd
+
+## DWARFv4 compile units, whose header is a byte shorter.
+# RUN: yaml2obj --docnum=2 %s -o %t2.o
+
+# RUN: llvm-dwarfutil %t2.o %t2.classic
+# RUN: llvm-dwarfdump --debug-info %t2.classic | FileCheck %s -DU02TAG=compile_unit
+# RUN: llvm-dwarfdump --verify %t2.classic
+
+# RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %t2.o %t2.classic.upd
+# RUN: llvm-dwarfdump --debug-info %t2.classic.upd | FileCheck %s -DU02TAG=compile_unit
+# RUN: llvm-dwarfdump --verify %t2.classic.upd
+
+# RUN: llvm-dwarfutil --linker parallel %t2.o %t2.parallel
+# RUN: llvm-dwarfdump --debug-info %t2.parallel | FileCheck %s -DU02TAG=compile_unit
+# RUN: llvm-dwarfdump --verify %t2.parallel
+
+# RUN: llvm-dwarfutil --linker parallel --no-garbage-collection --build-accelerator=DWARF %t2.o %t2.parallel.upd
+# RUN: llvm-dwarfdump --debug-info %t2.parallel.upd | FileCheck %s -DU02TAG=compile_unit
+# RUN: llvm-dwarfdump --verify %t2.parallel.upd
+
+## U02 is a partial unit with no code, as dwz emits, kept only by the imports.
+# RUN: yaml2obj --docnum=3 %s -o %t3.o
+
+# RUN: llvm-dwarfutil %t3.o %t3.classic
+# RUN: llvm-dwarfdump --debug-info %t3.classic | FileCheck %s -DU02TAG=partial_unit
+# RUN: llvm-dwarfdump --verify %t3.classic
+
+# RUN: llvm-dwarfutil --linker parallel %t3.o %t3.parallel
+# RUN: llvm-dwarfdump --debug-info %t3.parallel | FileCheck %s -DU02TAG=partial_unit
+# RUN: llvm-dwarfdump --verify %t3.parallel
+
+## FIXME: Add --verify to the update mode runs once the verifier stops requiring
+## a .debug_names entry for a named DW_TAG_partial_unit root (#219720).
+# RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %t3.o %t3.classic.upd
+# RUN: llvm-dwarfdump --debug-info %t3.classic.upd | FileCheck %s -DU02TAG=partial_unit
+
+# RUN: llvm-dwarfutil --linker parallel --no-garbage-collection --build-accelerator=DWARF %t3.o %t3.parallel.upd
+# RUN: llvm-dwarfdump --debug-info %t3.parallel.upd | FileCheck %s -DU02TAG=partial_unit
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"U01"
+
+## Forward reference: U02 is cloned after U01.
+# CHECK: DW_TAG_imported_unit
+# CHECK-NEXT: DW_AT_import{{.*}}(0x00000000[[U02ROOT:[0-9a-f]{8}]] "U02")
+
+# CHECK: 0x[[U02ROOT]]: DW_TAG_[[U02TAG]]
+# CHECK: DW_AT_name{{.*}}"U02"
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"U03"
+
+## Backward reference: U02 is cloned before U03.
+# CHECK: DW_TAG_imported_unit
+# CHECK-NEXT: DW_AT_import{{.*}}(0x00000000[[U02ROOT]] "U02")
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1130
+ Size: 0x30
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ Flags: [ ]
+ Content: "0400000005000000"
+DWARF:
+ debug_abbrev:
+ - ID: 0
+ Table:
+ - Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_producer
+ Form: DW_FORM_string
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_language
+ Form: DW_FORM_data2
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data8
+ - Attribute: DW_AT_str_offsets_base
+ Form: DW_FORM_sec_offset
+ - Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data8
+ - Tag: DW_TAG_imported_unit
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_import
+ Form: DW_FORM_ref_addr
+ - Tag: DW_TAG_namespace
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Tag: DW_TAG_structure_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_byte_size
+ Form: DW_FORM_data1
+ debug_info:
+ - Version: 5
+ UnitType: DW_UT_compile
+ AbbrevTableID: 0
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - CStr: U01
+ - Value: 0x04
+ - Value: 0x1130
+ - Value: 0x10
+ - Value: 0x8
+ - AbbrCode: 3
+ Values:
+ - Value: 0x57
+ - AbbrCode: 2
+ Values:
+ - CStr: foo1
+ - Value: 0x1130
+ - Value: 0x10
+ - AbbrCode: 0
+ - Version: 5
+ UnitType: DW_UT_compile
+ AbbrevTableID: 0
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - CStr: U02
+ - Value: 0x04
+ - Value: 0x1140
+ - Value: 0x10
+ - Value: 0x8
+ - AbbrCode: 2
+ Values:
+ - CStr: foo2
+ - Value: 0x1140
+ - Value: 0x10
+ - AbbrCode: 4
+ Values:
+ - CStr: ns
+ - AbbrCode: 5
+ Values:
+ - CStr: S
+ - Value: 0x8
+ - AbbrCode: 0
+ - AbbrCode: 0
+ - Version: 5
+ UnitType: DW_UT_compile
+ AbbrevTableID: 0
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - CStr: U03
+ - Value: 0x04
+ - Value: 0x1150
+ - Value: 0x10
+ - Value: 0x8
+ - AbbrCode: 3
+ Values:
+ - Value: 0x57
+ - AbbrCode: 2
+ Values:
+ - CStr: foo3
+ - Value: 0x1150
+ - Value: 0x10
+ - AbbrCode: 0
+...
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1130
+ Size: 0x30
+DWARF:
+ debug_abbrev:
+ - ID: 0
+ Table:
+ - Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_producer
+ Form: DW_FORM_string
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_language
+ Form: DW_FORM_data2
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data8
+ - Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data8
+ - Tag: DW_TAG_imported_unit
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_import
+ Form: DW_FORM_ref_addr
+ debug_info:
+ - Version: 4
+ AbbrevTableID: 0
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - CStr: U01
+ - Value: 0x04
+ - Value: 0x1130
+ - Value: 0x10
+ - AbbrCode: 3
+ Values:
+ - Value: 0x51
+ - AbbrCode: 2
+ Values:
+ - CStr: foo1
+ - Value: 0x1130
+ - Value: 0x10
+ - AbbrCode: 0
+ - Version: 4
+ AbbrevTableID: 0
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - CStr: U02
+ - Value: 0x04
+ - Value: 0x1140
+ - Value: 0x10
+ - AbbrCode: 2
+ Values:
+ - CStr: foo2
+ - Value: 0x1140
+ - Value: 0x10
+ - AbbrCode: 0
+ - Version: 4
+ AbbrevTableID: 0
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - CStr: U03
+ - Value: 0x04
+ - Value: 0x1150
+ - Value: 0x10
+ - AbbrCode: 3
+ Values:
+ - Value: 0x51
+ - AbbrCode: 2
+ Values:
+ - CStr: foo3
+ - Value: 0x1150
+ - Value: 0x10
+ - AbbrCode: 0
+...
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1130
+ Size: 0x30
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ Flags: [ ]
+ Content: "0400000005000000"
+DWARF:
+ debug_abbrev:
+ - ID: 0
+ Table:
+ - Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_producer
+ Form: DW_FORM_string
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_language
+ Form: DW_FORM_data2
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data8
+ - Attribute: DW_AT_str_offsets_base
+ Form: DW_FORM_sec_offset
+ - Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data8
+ - Tag: DW_TAG_imported_unit
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_import
+ Form: DW_FORM_ref_addr
+ - Tag: DW_TAG_namespace
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Tag: DW_TAG_structure_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_byte_size
+ Form: DW_FORM_data1
+ - Tag: DW_TAG_partial_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_producer
+ Form: DW_FORM_string
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_language
+ Form: DW_FORM_data2
+ - Attribute: DW_AT_str_offsets_base
+ Form: DW_FORM_sec_offset
+ debug_info:
+ - Version: 5
+ UnitType: DW_UT_compile
+ AbbrevTableID: 0
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - CStr: U01
+ - Value: 0x04
+ - Value: 0x1130
+ - Value: 0x10
+ - Value: 0x8
+ - AbbrCode: 3
+ Values:
+ - Value: 0x57
+ - AbbrCode: 2
+ Values:
+ - CStr: foo1
+ - Value: 0x1130
+ - Value: 0x10
+ - AbbrCode: 0
+ - Version: 5
+ UnitType: DW_UT_partial
+ AbbrevTableID: 0
+ Entries:
+ - AbbrCode: 6
+ Values:
+ - CStr: by_hand
+ - CStr: U02
+ - Value: 0x04
+ - Value: 0x8
+ - AbbrCode: 4
+ Values:
+ - CStr: ns
+ - AbbrCode: 5
+ Values:
+ - CStr: S
+ - Value: 0x8
+ - AbbrCode: 0
+ - AbbrCode: 0
+ - Version: 5
+ UnitType: DW_UT_compile
+ AbbrevTableID: 0
+ Entries:
+ - AbbrCode: 1
+ Values:
+ - CStr: by_hand
+ - CStr: U03
+ - Value: 0x04
+ - Value: 0x1150
+ - Value: 0x10
+ - Value: 0x8
+ - AbbrCode: 3
+ Values:
+ - Value: 0x57
+ - AbbrCode: 2
+ Values:
+ - CStr: foo3
+ - Value: 0x1150
+ - Value: 0x10
+ - AbbrCode: 0
+...
More information about the llvm-commits
mailing list