Index: llvm/lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -133,7 +133,15 @@ return Contributions; } -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; 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, @@ -202,49 +210,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, @@ -663,13 +628,13 @@ dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(), DObj->getStrSection(), normal_units(), - isLittleEndian(), getMaxVersion()); + 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())) { Index: llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -1001,11 +1001,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; } Index: llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s =================================================================== --- llvm/test/DebugInfo/X86/dwarfdump-str-offsets-invalid-5.s +++ 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 Index: llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwo.s =================================================================== --- /dev/null +++ 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 = "foo") + +# 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 = "bar") +# CHECK: DW_TAG_structure_type [3] +# CHECK-NEXT: DW_AT_name [DW_FORM_strx] (indexed (00000002) string = "baz") + +# CHECK: .debug_str.dwo contents: +# CHECK-NEXT: 0x00000000: "foo" +# CHECK-NEXT: 0x00000004: "bar" +# CHECK-NEXT: 0x00000008: "baz" + +# CHECK: .debug_str_offsets.dwo contents: +# CHECK-NEXT: 0x00000000: Contribution size = 24, Format = DWARF64, Version = 4 +# CHECK-NEXT: 0x00000000: 00000000 "foo" +# CHECK-NEXT: 0x00000008: 00000004 "bar" +# CHECK-NEXT: 0x00000010: 00000008 "baz" + + .section .debug_str.dwo, "MSe", @progbits, 1 +.LStrFoo: + .asciz "foo" +.LStrBar: + .asciz "bar" +.LStrBaz: + .asciz "baz" + + .section .debug_str_offsets.dwo, "e", @progbits + .quad .LStrFoo-.debug_str.dwo # 0: "foo" + .quad .LStrBar-.debug_str.dwo # 1: "bar" + .quad .LStrBaz-.debug_str.dwo # 2: "baz" + + .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 ("foo") +.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 ("bar") +.LTUType: + .uleb128 3 # Abbrev [3] DW_TAG_structure_type + .uleb128 2 # DW_AT_name ("baz") +.LTUEnd: Index: llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-dwarf64-dwp.s =================================================================== --- /dev/null +++ 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 = "foo") +# CHECK-NEXT: DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "bar") +# CHECK: Compile Unit: +# CHECK: DW_TAG_compile_unit [1] +# CHECK-NEXT: DW_AT_producer [DW_FORM_strx] (indexed (00000000) string = "baz") +# CHECK-NEXT: DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "qux") + +# CHECK: .debug_str.dwo contents: +# CHECK-NEXT: 0x00000000: "foo" +# CHECK-NEXT: 0x00000004: "bar" +# CHECK-NEXT: 0x00000008: "baz" +# CHECK-NEXT: 0x0000000c: "qux" + +# CHECK: .debug_str_offsets.dwo contents: +# CHECK-NEXT: 0x00000000: Contribution size = 8, Format = DWARF32, Version = 4 +# CHECK-NEXT: 0x00000000: 00000000 "foo" +# CHECK-NEXT: 0x00000004: 00000004 "bar" +# CHECK-NEXT: 0x00000008: Contribution size = 16, Format = DWARF64, Version = 4 +# CHECK-NEXT: 0x00000008: 00000008 "baz" +# CHECK-NEXT: 0x00000010: 0000000c "qux" + + .section .debug_str.dwo, "MSe", @progbits, 1 +.LStrFoo: + .asciz "foo" +.LStrBar: + .asciz "bar" +.LStrBaz: + .asciz "baz" +.LStrQux: + .asciz "qux" + + .section .debug_str_offsets.dwo, "e", @progbits +## The contribution of CU0 (DWARF32) +.LSO0: + .long .LStrFoo-.debug_str.dwo # 0: "foo" + .long .LStrBar-.debug_str.dwo # 1: "bar" +.LSO0End: +## The contribution of CU1 (DWARF64) +.LSO1: + .quad .LStrBaz-.debug_str.dwo # 0: "baz" + .quad .LStrQux-.debug_str.dwo # 1: "qux" +.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 ("foo") + .uleb128 1 # DW_AT_name ("bar") + .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 ("baz") + .uleb128 1 # DW_AT_name ("qux") + .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