[llvm] d1d5f0b - [DebugInfo][DWARF64] Fix dumping pre-standard .debug_str_offsets.dwo sections.
Igor Kudrin via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 25 05:00:07 PDT 2020
Author: Igor Kudrin
Date: 2020-04-25T18:59:41+07:00
New Revision: d1d5f0b10341fbc26c2907241124ffc2585b8ea1
URL: https://github.com/llvm/llvm-project/commit/d1d5f0b10341fbc26c2907241124ffc2585b8ea1
DIFF: https://github.com/llvm/llvm-project/commit/d1d5f0b10341fbc26c2907241124ffc2585b8ea1.diff
LOG: [DebugInfo][DWARF64] Fix dumping pre-standard .debug_str_offsets.dwo sections.
The sizes of offsets in the `.debug_str_offsets.dwo` section depend on
the format of compilation or type units referencing them: 4 bytes for
DWARF32 units and 8 bytes for DWARF64 ones. The fix uses parsed units
to determine the actual size of offsets in the corresponding part of
the `.debug_str_offsets.dwo` section.
Differential Revision: https://reviews.llvm.org/D78555
Added:
llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwo.s
llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwp.s
Modified:
llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s
Removed:
################################################################################
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index fe00baab9093..052b693f2167 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -133,11 +133,21 @@ collectContributionData(DWARFContext::unit_iterator_range Units) {
return Contributions;
}
-static void dumpDWARFv5StringOffsetsSection(
- raw_ostream &OS, DIDumpOptions DumpOpts, StringRef SectionName,
- const DWARFObject &Obj, const DWARFSection &StringOffsetsSection,
- StringRef StringSection, DWARFContext::unit_iterator_range Units,
- bool LittleEndian) {
+// Dump a DWARF string offsets section. This may be a DWARF v5 formatted
+// string offsets section, where each compile or type unit contributes a
+// number of entries (string offsets), with each contribution preceded by
+// a header containing size and version number. Alternatively, it may be a
+// monolithic series of string offsets, as generated by the pre-DWARF v5
+// implementation of split DWARF; however, in that case we still need to
+// collect contributions of units because the size of the offsets (4 or 8
+// bytes) depends on the format of the referencing unit (DWARF32 or DWARF64).
+static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
+ StringRef SectionName,
+ const DWARFObject &Obj,
+ const DWARFSection &StringOffsetsSection,
+ StringRef StringSection,
+ DWARFContext::unit_iterator_range Units,
+ bool LittleEndian) {
auto Contributions = collectContributionData(Units);
DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
DataExtractor StrData(StringSection, LittleEndian, 0);
@@ -202,49 +212,6 @@ static void dumpDWARFv5StringOffsetsSection(
}
}
-// Dump a DWARF string offsets section. This may be a DWARF v5 formatted
-// string offsets section, where each compile or type unit contributes a
-// number of entries (string offsets), with each contribution preceded by
-// a header containing size and version number. Alternatively, it may be a
-// monolithic series of string offsets, as generated by the pre-DWARF v5
-// implementation of split DWARF.
-static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
- StringRef SectionName,
- const DWARFObject &Obj,
- const DWARFSection &StringOffsetsSection,
- StringRef StringSection,
- DWARFContext::unit_iterator_range Units,
- bool LittleEndian, unsigned MaxVersion) {
- // If we have at least one (compile or type) unit with DWARF v5 or greater,
- // we assume that the section is formatted like a DWARF v5 string offsets
- // section.
- if (MaxVersion >= 5)
- dumpDWARFv5StringOffsetsSection(OS, DumpOpts, SectionName, Obj,
- StringOffsetsSection, StringSection, Units,
- LittleEndian);
- else {
- DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0);
- uint64_t offset = 0;
- uint64_t size = StringOffsetsSection.Data.size();
- // Ensure that size is a multiple of the size of an entry.
- if (size & ((uint64_t)(sizeof(uint32_t) - 1))) {
- OS << "error: size of ." << SectionName << " is not a multiple of "
- << sizeof(uint32_t) << ".\n";
- size &= -(uint64_t)sizeof(uint32_t);
- }
- DataExtractor StrData(StringSection, LittleEndian, 0);
- while (offset < size) {
- OS << format("0x%8.8" PRIx64 ": ", offset);
- uint64_t StringOffset = strOffsetExt.getU32(&offset);
- OS << format("%8.8" PRIx64 " ", StringOffset);
- const char *S = StrData.getCStr(&StringOffset);
- if (S)
- OS << format("\"%s\"", S);
- OS << "\n";
- }
- }
-}
-
// Dump the .debug_addr section.
static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
DIDumpOptions DumpOpts, uint16_t Version,
@@ -660,16 +627,15 @@ void DWARFContext::dump(
if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
DObj->getStrOffsetsSection().Data))
- dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets", *DObj,
- DObj->getStrOffsetsSection(),
- DObj->getStrSection(), normal_units(),
- isLittleEndian(), getMaxVersion());
+ dumpStringOffsetsSection(
+ OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(),
+ DObj->getStrSection(), normal_units(), isLittleEndian());
if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,
DObj->getStrOffsetsDWOSection().Data))
dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj,
DObj->getStrOffsetsDWOSection(),
DObj->getStrDWOSection(), dwo_units(),
- isLittleEndian(), getMaxDWOVersion());
+ isLittleEndian());
if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,
DObj->getGdbIndexSection())) {
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index fb24576620f4..f90204167050 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -996,11 +996,10 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
// index table (in a package file). In a .dwo file it is simply
// the length of the string offsets section.
if (!IndexEntry)
- return {
- Optional<StrOffsetsContributionDescriptor>(
- {0, StringOffsetSection.Data.size(), 4, DWARF32})};
+ return {Optional<StrOffsetsContributionDescriptor>(
+ {0, StringOffsetSection.Data.size(), 4, Header.getFormat()})};
if (C)
return {Optional<StrOffsetsContributionDescriptor>(
- {C->Offset, C->Length, 4, DWARF32})};
+ {C->Offset, C->Length, 4, Header.getFormat()})};
return None;
}
diff --git a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s
index 718b0f5b672c..3eccd7731f92 100644
--- a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s
+++ b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s
@@ -9,6 +9,5 @@
# A degenerate section, not enough for a single entry.
.byte 2
-# INVALIDSECTIONLENGTH: .debug_str_offsets contents:
-# INVALIDSECTIONLENGTH-NOT: contents:
-# INVALIDSECTIONLENGTH: error: size of .debug_str_offsets is not a multiple of 4.
+# INVALIDSECTIONLENGTH: .debug_str_offsets contents:
+# INVALIDSECTIONLENGTH: 0x00000000: Gap, length = 1
diff --git a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwo.s b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwo.s
new file mode 100644
index 000000000000..427a90429dc7
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwo.s
@@ -0,0 +1,95 @@
+## This tests dumping a .debug_str_offsets.dwo section which is referenced by
+## DWARF64 pre-v5 units and dumping attributes in such units which use the
+## DW_FORM_strx form.
+
+# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o - | \
+# RUN: llvm-dwarfdump -v - | \
+# RUN: FileCheck %s
+
+# CHECK: .debug_info.dwo contents:
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit [1]
+# CHECK-NEXT: DW_AT_name [DW_FORM_strx] (indexed (00000000) string = "Compilation Unit")
+
+# CHECK: .debug_types.dwo contents:
+# CHECK: Type Unit:
+# CHECK: DW_TAG_type_unit [2] *
+# CHECK-NEXT: DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "Type Unit")
+# CHECK: DW_TAG_structure_type [3]
+# CHECK-NEXT: DW_AT_name [DW_FORM_strx] (indexed (00000002) string = "Structure")
+
+# CHECK: .debug_str.dwo contents:
+# CHECK-NEXT: 0x00000000: "Compilation Unit"
+# CHECK-NEXT: 0x00000011: "Type Unit"
+# CHECK-NEXT: 0x0000001b: "Structure"
+
+# CHECK: .debug_str_offsets.dwo contents:
+# CHECK-NEXT: 0x00000000: Contribution size = 24, Format = DWARF64, Version = 4
+# CHECK-NEXT: 0x00000000: 00000000 "Compilation Unit"
+# CHECK-NEXT: 0x00000008: 00000011 "Type Unit"
+# CHECK-NEXT: 0x00000010: 0000001b "Structure"
+
+ .section .debug_str.dwo, "MSe", @progbits, 1
+.LStr0:
+ .asciz "Compilation Unit"
+.LStr1:
+ .asciz "Type Unit"
+.LStr2:
+ .asciz "Structure"
+
+ .section .debug_str_offsets.dwo, "e", @progbits
+ .quad .LStr0-.debug_str.dwo # 0: "Compilation Unit"
+ .quad .LStr1-.debug_str.dwo # 1: "Type Unit"
+ .quad .LStr2-.debug_str.dwo # 2: "Structure"
+
+ .section .debug_abbrev.dwo, "e", @progbits
+ .uleb128 0x01 # Abbrev code
+ .uleb128 0x11 # DW_TAG_compile_unit
+ .byte 0x00 # DW_CHILDREN_no
+ .uleb128 0x03 # DW_AT_name
+ .uleb128 0x1a # DW_FORM_strx
+ .byte 0x00 # EOM(1)
+ .byte 0x00 # EOM(2)
+ .uleb128 0x02 # Abbrev code
+ .uleb128 0x41 # DW_TAG_type_unit
+ .byte 0x01 # DW_CHILDREN_yes
+ .uleb128 0x03 # DW_AT_name
+ .uleb128 0x1a # DW_FORM_strx
+ .byte 0x00 # EOM(1)
+ .byte 0x00 # EOM(2)
+ .uleb128 0x03 # Abbrev code
+ .uleb128 0x13 # DW_TAG_structure_type
+ .byte 0x00 # DW_CHILDREN_no (no members)
+ .uleb128 0x03 # DW_AT_name
+ .uleb128 0x1a # DW_FORM_strx
+ .byte 0x00 # EOM(1)
+ .byte 0x00 # EOM(2)
+ .byte 0x00 # EOM(3)
+
+ .section .debug_info.dwo, "e", @progbits
+ .long 0xffffffff # DWARF64 mark
+ .quad .LCUEnd-.LCUVer # Length
+.LCUVer:
+ .short 4 # Version
+ .quad 0 # Abbrev. offset
+ .byte 8 # Address size
+ .uleb128 1 # Abbrev [1] DW_TAG_compile_unit
+ .uleb128 0 # DW_AT_name ("Compilation Unit")
+.LCUEnd:
+
+ .section .debug_types.dwo, "e", @progbits
+.LTU:
+ .long 0xffffffff # DWARF64 mark
+ .quad .LTUEnd-.LTUVer # Length
+.LTUVer:
+ .short 4 # Version
+ .quad 0 # Abbrev. offset
+ .byte 8 # Address size
+ .quad 0x11110022ffffffff # Type Signature
+ .quad .LTUType-.LTU # Type offset
+ .uleb128 2 # Abbrev [2] DW_TAG_type_unit
+ .uleb128 1 # DW_AT_name ("Type Unit")
+.LTUType:
+ .uleb128 3 # Abbrev [3] DW_TAG_structure_type
+ .uleb128 2 # DW_AT_name ("Structure")
+.LTUEnd:
diff --git a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwp.s b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwp.s
new file mode 100644
index 000000000000..ac2d0cfa1c05
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwp.s
@@ -0,0 +1,140 @@
+## This tests dumping a .debug_str_offsets.dwo section in a DWP file when it is
+## referenced by units in
diff erent formats: one unit is DWARF32 and another
+## is DWARF64, thus the .debug_str_offsets.dwo section has contributions with
+##
diff erent sizes of offsets.
+## This also checks that attributes in the units which use the DW_FORM_strx form
+## are dumped correctly.
+
+# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o - | \
+# RUN: llvm-dwarfdump -v - | \
+# RUN: FileCheck %s
+
+# CHECK: .debug_info.dwo contents:
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit [1]
+# CHECK-NEXT: DW_AT_producer [DW_FORM_strx] (indexed (00000000) string = "CU0 Producer")
+# CHECK-NEXT: DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "CU0 Name")
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit [1]
+# CHECK-NEXT: DW_AT_producer [DW_FORM_strx] (indexed (00000000) string = "CU1 Producer")
+# CHECK-NEXT: DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "CU1 Name")
+
+# CHECK: .debug_str.dwo contents:
+# CHECK-NEXT: 0x00000000: "CU0 Producer"
+# CHECK-NEXT: 0x0000000d: "CU0 Name"
+# CHECK-NEXT: 0x00000016: "CU1 Producer"
+# CHECK-NEXT: 0x00000023: "CU1 Name"
+
+# CHECK: .debug_str_offsets.dwo contents:
+# CHECK-NEXT: 0x00000000: Contribution size = 8, Format = DWARF32, Version = 4
+# CHECK-NEXT: 0x00000000: 00000000 "CU0 Producer"
+# CHECK-NEXT: 0x00000004: 0000000d "CU0 Name"
+# CHECK-NEXT: 0x00000008: Contribution size = 16, Format = DWARF64, Version = 4
+# CHECK-NEXT: 0x00000008: 00000016 "CU1 Producer"
+# CHECK-NEXT: 0x00000010: 00000023 "CU1 Name"
+
+ .section .debug_str.dwo, "MSe", @progbits, 1
+.LStr0:
+ .asciz "CU0 Producer"
+.LStr1:
+ .asciz "CU0 Name"
+.LStr2:
+ .asciz "CU1 Producer"
+.LStr3:
+ .asciz "CU1 Name"
+
+ .section .debug_str_offsets.dwo, "e", @progbits
+## The contribution of CU0 (DWARF32)
+.LSO0:
+ .long .LStr0-.debug_str.dwo # 0: "CU0 Producer"
+ .long .LStr1-.debug_str.dwo # 1: "CU0 Name"
+.LSO0End:
+## The contribution of CU1 (DWARF64)
+.LSO1:
+ .quad .LStr2-.debug_str.dwo # 0: "CU1 Producer"
+ .quad .LStr3-.debug_str.dwo # 1: "CU1 Name"
+.LSO1End:
+
+ .section .debug_abbrev.dwo, "e", @progbits
+## For simplicity and to make the test shorter, both compilation units share
+## the same abbreviations table.
+.LAbbr:
+ .uleb128 0x01 # Abbrev code
+ .uleb128 0x11 # DW_TAG_compile_unit
+ .byte 0x00 # DW_CHILDREN_no
+ .uleb128 0x25 # DW_AT_producer
+ .uleb128 0x1a # DW_FORM_strx
+ .uleb128 0x03 # DW_AT_name
+ .uleb128 0x1a # DW_FORM_strx
+ .uleb128 0x2131 # DW_AT_GNU_dwo_id
+ .uleb128 0x07 # DW_FORM_data8
+ .byte 0x00 # EOM(1)
+ .byte 0x00 # EOM(2)
+ .byte 0x00 # EOM(3)
+.LAbbrEnd:
+
+ .section .debug_info.dwo, "e", @progbits
+## CU0 uses the 32-bit DWARF format.
+.LCU0:
+ .long .LCU0End-.LCU0Ver # Length
+.LCU0Ver:
+ .short 4 # Version
+ .long 0 # Abbrev. offset
+ .byte 8 # Address size
+ .uleb128 1 # Abbrev [1] DW_TAG_compile_unit
+ .uleb128 0 # DW_AT_producer ("CU0 Producer")
+ .uleb128 1 # DW_AT_name ("CU0 Name")
+ .quad 0x1100001122222222 # DW_AT_GNU_dwo_id
+.LCU0End:
+## CU1 uses the 64-bit DWARF format.
+.LCU1:
+ .long 0xffffffff # DWARF64 mark
+ .quad .LCU1End-.LCU1Ver # Length
+.LCU1Ver:
+ .short 4 # Version
+ .quad 0 # Abbrev. offset
+ .byte 8 # Address size
+ .uleb128 1 # Abbrev [1] DW_TAG_compile_unit
+ .uleb128 0 # DW_AT_producer ("CU1 Producer")
+ .uleb128 1 # DW_AT_name ("CU1 Name")
+ .quad 0x1100001133333333 # DW_AT_GNU_dwo_id
+.LCU1End:
+
+ .section .debug_cu_index, "", @progbits
+## Header:
+ .long 2 # Version
+ .long 3 # Section count
+ .long 2 # Unit count
+ .long 4 # Slot count
+## Hash Table of Signatures:
+ .quad 0
+ .quad 0
+ .quad 0x1100001122222222 # DWO Id of CU0
+ .quad 0x1100001133333333 # DWO Id of CU1
+## Parallel Table of Indexes:
+ .long 0
+ .long 0
+ .long 1
+ .long 2
+## Table of Section Offsets:
+## Row 0:
+ .long 1 # DW_SECT_INFO
+ .long 3 # DW_SECT_ABBREV
+ .long 6 # DW_SECT_STR_OFFSETS
+## Row 1, offsets of contributions of CU0:
+ .long .LCU0-.debug_info.dwo
+ .long .LAbbr-.debug_abbrev.dwo
+ .long .LSO0-.debug_str_offsets.dwo
+## Row 2, offsets of contributions of CU1:
+ .long .LCU1-.debug_info.dwo
+ .long .LAbbr-.debug_abbrev.dwo
+ .long .LSO1-.debug_str_offsets.dwo
+## Table of Section Sizes:
+## Row 1, sizes of contributions of CU0:
+ .long .LCU0End-.LCU0
+ .long .LAbbrEnd-.LAbbr
+ .long .LSO0End-.LSO0
+## Row 2, sizes of contributions of CU1:
+ .long .LCU1End-.LCU1
+ .long .LAbbrEnd-.LAbbr
+ .long .LSO1End-.LSO1
More information about the llvm-commits
mailing list