diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -133,11 +133,21 @@ 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 @@ } } -// 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 @@ 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 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -996,11 +996,10 @@ // index table (in a package file). In a .dwo file it is simply // the length of the string offsets section. if (!IndexEntry) - return { - Optional( - {0, StringOffsetSection.Data.size(), 4, DWARF32})}; + return {Optional( + {0, StringOffsetSection.Data.size(), 4, Header.getFormat()})}; if (C) return {Optional( - {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 --- 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 --- /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 --- /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 different formats: one unit is DWARF32 and another +## is DWARF64, thus the .debug_str_offsets.dwo section has contributions with +## different 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