diff --git a/llvm/test/tools/llvm-dwp/Inputs/type_dedup_v5/a.s b/llvm/test/tools/llvm-dwp/Inputs/type_dedup_v5/a.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwp/Inputs/type_dedup_v5/a.s @@ -0,0 +1,39 @@ +## Note: For the purpose of checking the de-duplication of type units +## it is not necessary to have the DIEs for the structure type, that +## are referenced by the type unit. + + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 6 # DWARF Unit Type (DW_UT_split_type) + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 5657452045627120676 # Type Signature + .long 25 # Type DIE Offset + .byte 2 # Abbrev [2] DW_TAG_type_unit + .byte 3 # Abbrev [3] DW_TAG_structure_type + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit +.Ldebug_info_dwo_start2: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type (DW_UT_split_compile) + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 0 + .byte 1 # Abbrev [1] DW_TAG_compile_unit +.Ldebug_info_dwo_end2: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 0 # EOM + .byte 0 # EOM + .byte 0 # EOM diff --git a/llvm/test/tools/llvm-dwp/X86/cu_and_tu_info_section_v5.s b/llvm/test/tools/llvm-dwp/Inputs/type_dedup_v5/b.s copy from llvm/test/tools/llvm-dwp/X86/cu_and_tu_info_section_v5.s copy to llvm/test/tools/llvm-dwp/Inputs/type_dedup_v5/b.s --- a/llvm/test/tools/llvm-dwp/X86/cu_and_tu_info_section_v5.s +++ b/llvm/test/tools/llvm-dwp/Inputs/type_dedup_v5/b.s @@ -1,16 +1,7 @@ -# This test checks if llvm-dwp can find the compilation unit if -# both type and compile units are available in the debug info section (v5) +## Note: For the purpose of checking the de-duplication of type units +## it is not necessary to have the DIEs for the structure type, that +## are referenced by the type unit. -# RUN: llvm-mc --triple=x86_64-unknown-linux --filetype=obj --split-dwarf-file=%t.dwo -dwarf-version=5 %s -o %t.o -# RUN: llvm-dwp %t.dwo -o %t.dwp -# RUN: llvm-dwarfdump -debug-info -debug-tu-index %t.dwp | FileCheck %s - -## Note: For this test we do not need to define the DIE for the structure type, as we only want to -## have the info on the type and compile units. - -# CHECK-DAG: .debug_info.dwo contents -# CHECK-NOT: Type Unit: -# CHECK: 0x00000000: Compile Unit: length = 0x00000011, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_compile, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = {{.*}} (next unit at 0x00000015) .section .debug_info.dwo,"e",@progbits .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit .Ldebug_info_dwo_start0: @@ -20,29 +11,29 @@ .long 0 # Offset Into Abbrev. Section .quad 5657452045627120676 # Type Signature .long 25 # Type DIE Offset - .byte 1 # Abbrev [1] DW_TAG_type_unit - .byte 2 # Abbrev [2] DW_TAG_structure_type + .byte 2 # Abbrev [2] DW_TAG_type_unit + .byte 3 # Abbrev [3] DW_TAG_structure_type .byte 0 # End Of Children Mark .Ldebug_info_dwo_end0: .section .debug_info.dwo,"e",@progbits - .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit -.Ldebug_info_dwo_start1: + .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit +.Ldebug_info_dwo_start2: .short 5 # DWARF version number .byte 5 # DWARF Unit Type (DW_UT_split_compile) .byte 8 # Address Size (in bytes) .long 0 # Offset Into Abbrev. Section - .quad -1506010254921578184 - .byte 3 # Abbrev [3] DW_TAG_compile_unit -.Ldebug_info_dwo_end1: + .quad -1709724327721109161 + .byte 1 # Abbrev [1] DW_TAG_compile_unit +.Ldebug_info_dwo_end2: .section .debug_abbrev.dwo,"e",@progbits .byte 1 # Abbreviation Code - .byte 65 # DW_TAG_type_unit - .byte 1 # DW_CHILDREN_yes - .byte 0 # EOM(1) - .byte 0 # EOM(2) - .byte 3 # Abbreviation Code .byte 17 # DW_TAG_compile_unit .byte 0 # DW_CHILDREN_no .byte 0 # EOM(1) .byte 0 # EOM(2) - .byte 0 # EOM(3) + .byte 2 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 0 # EOM + .byte 0 # EOM + .byte 0 # EOM diff --git a/llvm/test/tools/llvm-dwp/X86/cu_and_tu_info_section_v5.s b/llvm/test/tools/llvm-dwp/X86/cu_and_tu_info_section_v5.s --- a/llvm/test/tools/llvm-dwp/X86/cu_and_tu_info_section_v5.s +++ b/llvm/test/tools/llvm-dwp/X86/cu_and_tu_info_section_v5.s @@ -9,8 +9,8 @@ ## have the info on the type and compile units. # CHECK-DAG: .debug_info.dwo contents -# CHECK-NOT: Type Unit: -# CHECK: 0x00000000: Compile Unit: length = 0x00000011, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_compile, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = {{.*}} (next unit at 0x00000015) +# CHECK: 0x00000000: Type Unit: length = 0x00000017, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_type, abbr_offset = 0x0000, addr_size = 0x08, name = '', type_signature = {{.*}}, type_offset = 0x0019 (next unit at 0x0000001b) +# CHECK: 0x0000001b: Compile Unit: length = 0x00000011, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_compile, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = {{.*}} (next unit at 0x00000030) .section .debug_info.dwo,"e",@progbits .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit .Ldebug_info_dwo_start0: diff --git a/llvm/test/tools/llvm-dwp/X86/unsupported_tu_index_version.s b/llvm/test/tools/llvm-dwp/X86/incompatible_tu_index_version.s rename from llvm/test/tools/llvm-dwp/X86/unsupported_tu_index_version.s rename to llvm/test/tools/llvm-dwp/X86/incompatible_tu_index_version.s --- a/llvm/test/tools/llvm-dwp/X86/unsupported_tu_index_version.s +++ b/llvm/test/tools/llvm-dwp/X86/incompatible_tu_index_version.s @@ -5,7 +5,7 @@ ## of version 2 and a TU index of version 5. A valid TU is not required, but ## the .debug_types.dwo section should not be empty. -# CHECK: error: expected index version 2, but got: 5 +# CHECK: error: incompatible tu_index versions, found 5 and expecting 2 .section .debug_abbrev.dwo, "e", @progbits .LAbbrevBegin: diff --git a/llvm/test/tools/llvm-dwp/X86/missing_tu_index.test b/llvm/test/tools/llvm-dwp/X86/missing_tu_index.test --- a/llvm/test/tools/llvm-dwp/X86/missing_tu_index.test +++ b/llvm/test/tools/llvm-dwp/X86/missing_tu_index.test @@ -1,3 +1,61 @@ -RUN: not llvm-dwp %p/../Inputs/missing_tu_index/x.dwp -o %t 2>&1 | FileCheck %s +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.dwp +# RUN: not llvm-dwp %t.dwp -o %t 2>&1 | FileCheck %s -CHECK: error: failed to parse tu_index +## Note: To reach the test point, we need a DWP file with a CU, a CU index +## and a broken TU index. + +# CHECK: error: failed to parse tu_index + +.section .debug_abbrev.dwo, "e", @progbits +.LAbbrevBegin: + .uleb128 1 # Abbreviation Code + .uleb128 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_no + .uleb128 0x2131 # DW_AT_GNU_dwo_id + .uleb128 7 # DW_FORM_data8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) +.LAbbrevEnd: + + .section .debug_info.dwo, "e", @progbits +.LCUBegin: + .long .LCUEnd-.LCUVersion # Length of Unit +.LCUVersion: + .short 4 # Version + .long 0 # Abbrev offset + .byte 8 # Address size + .uleb128 1 # Abbrev [1] DW_TAG_compile_unit + .quad 0x1100001122222222 # DW_AT_GNU_dwo_id +.LCUEnd: + + .section .debug_types.dwo, "e", @progbits + .space 1 + + .section .debug_cu_index, "", @progbits + +## Header: + .long 2 # Version + .long 2 # Section count + .long 1 # Unit count + .long 2 # Slot count +## Hash Table of Signatures: + .quad 0x1100001122222222 + .quad 0 +## Parallel Table of Indexes: + .long 1 + .long 0 +## Table of Section Offsets: +## Row 0: + .long 1 # DW_SECT_INFO + .long 3 # DW_SECT_ABBREV +## Row 1: + .long 0 # Offset in .debug_info.dwo + .long 0 # Offset in .debug_abbrev.dwo +## Table of Section Sizes: + .long .LCUEnd-.LCUBegin # Size in .debug_info.dwo + .long .LAbbrevEnd-.LAbbrevBegin # Size in .debug_abbrev.dwo + + .section .debug_tu_index, "", @progbits +## Header: + .short 2 # Version diff --git a/llvm/test/tools/llvm-dwp/X86/tu_units_v5.s b/llvm/test/tools/llvm-dwp/X86/tu_units_v5.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwp/X86/tu_units_v5.s @@ -0,0 +1,72 @@ +# This test checks if llvm-dwp can correctly generate the tu index section (v5). + +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o \ +# RUN: -split-dwarf-file=%t.dwo -dwarf-version=5 +# RUN: llvm-dwp %t.dwo -o %t.dwp +# RUN: llvm-dwarfdump -debug-info -debug-tu-index %t.dwp | FileCheck %s + +## Note: In order to check whether the type unit index is generated +## there is no need to add the missing DIEs for the structure type of the type unit. + +# CHECK-DAG: .debug_info.dwo contents: +# CHECK: 0x00000000: Type Unit: length = 0x00000017, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_type, abbr_offset = 0x0000, addr_size = 0x08, name = '', type_signature = [[TUID1:.*]], type_offset = 0x0019 (next unit at 0x0000001b) +# CHECK: 0x0000001b: Type Unit: length = 0x00000017, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_type, abbr_offset = 0x0000, addr_size = 0x08, name = '', type_signature = [[TUID2:.*]], type_offset = 0x0019 (next unit at 0x00000036) +# CHECK_DAG: .debug_tu_index contents: +# CHECK: version = 5, units = 2, slots = 4 +# CHECK: Index Signature INFO ABBREV +# CHECK: 1 [[TUID1]] [0x00000000, 0x0000001b) [0x00000000, 0x00000010) +# CHECK: 4 [[TUID2]] [0x0000001b, 0x00000036) [0x00000000, 0x00000010) + + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 6 # DWARF Unit Type (DW_UT_split_type) + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 5657452045627120676 # Type Signature + .long 25 # Type DIE Offset + .byte 2 # Abbrev [2] DW_TAG_type_unit + .byte 3 # Abbrev [3] DW_TAG_structure_type + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit +.Ldebug_info_dwo_start1: + .short 5 # DWARF version number + .byte 6 # DWARF Unit Type (DW_UT_split_type) + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad -8528522068957683993 # Type Signature + .long 25 # Type DIE Offset + .byte 4 # Abbrev [4] DW_TAG_type_unit + .byte 5 # Abbrev [5] DW_TAG_structure_type + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end1: + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit +.Ldebug_info_dwo_start2: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type (DW_UT_split_compile) + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 0 + .byte 1 # Abbrev [1] DW_TAG_compile_unit +.Ldebug_info_dwo_end2: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 0 # EOM + .byte 0 # EOM + .byte 4 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 0 # EOM + .byte 0 # EOM + .byte 0 # EOM diff --git a/llvm/test/tools/llvm-dwp/X86/type_dedup_v5.test b/llvm/test/tools/llvm-dwp/X86/type_dedup_v5.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwp/X86/type_dedup_v5.test @@ -0,0 +1,11 @@ +# This test checks if llvm-dwp can deduplicate tu units (v5). + +# RUN: llvm-mc -triple x86_64-unknown-linux %p/../Inputs/type_dedup_v5/a.s -filetype=obj -o a.o \ +# RUN: -split-dwarf-file=a.dwo -dwarf-version=5 +# RUN: llvm-mc -triple x86_64-unknown-linux %p/../Inputs/type_dedup_v5/b.s -filetype=obj -o b.o \ +# RUN: -split-dwarf-file=b.dwo -dwarf-version=5 +# RUN: llvm-dwp a.dwo b.dwo -o %t.dwp +# RUN: llvm-dwarfdump -debug-tu-index %t.dwp | FileCheck %s + +# CHECK_DAG: .debug_tu_index contents: +# CHECK: version = 5, units = 1, slots = 2 diff --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp --- a/llvm/tools/llvm-dwp/llvm-dwp.cpp +++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -361,10 +361,12 @@ return Section.substr(Off->Offset, Off->Length); } -static void addAllTypesFromDWP( - MCStreamer &Out, MapVector &TypeIndexEntries, - const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types, - const UnitIndexEntry &TUEntry, uint32_t &TypesOffset) { +static void +addAllTypesFromDWP(MCStreamer &Out, + MapVector &TypeIndexEntries, + const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, + StringRef Types, const UnitIndexEntry &TUEntry, + uint32_t &TypesOffset, unsigned TypesContributionIndex) { Out.SwitchSection(OutputTypes); for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) { auto *I = E.getContributions(); @@ -385,21 +387,19 @@ C.Length = I->Length; ++I; } - unsigned TypesIndex = - getContributionIndex(DW_SECT_EXT_TYPES, TUIndex.getVersion()); - auto &C = Entry.Contributions[TypesIndex]; + auto &C = Entry.Contributions[TypesContributionIndex]; Out.emitBytes(Types.substr( - C.Offset - TUEntry.Contributions[TypesIndex].Offset, C.Length)); + C.Offset - TUEntry.Contributions[TypesContributionIndex].Offset, + C.Length)); C.Offset = TypesOffset; TypesOffset += C.Length; } } -static void addAllTypes(MCStreamer &Out, - MapVector &TypeIndexEntries, - MCSection *OutputTypes, - const std::vector &TypesSections, - const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) { +static void addAllTypesFromTypesSection( + MCStreamer &Out, MapVector &TypeIndexEntries, + MCSection *OutputTypes, const std::vector &TypesSections, + const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) { for (StringRef Types : TypesSections) { Out.SwitchSection(OutputTypes); uint64_t Offset = 0; @@ -748,8 +748,6 @@ bool FoundCUUnit = false; Out.SwitchSection(InfoSection); for (StringRef Info : CurInfoSection) { - if (FoundCUUnit) - break; uint64_t UnitOffset = 0; while (Info.size() > UnitOffset) { Expected HeaderOrError = @@ -763,12 +761,13 @@ IndexVersion)]; C.Offset = InfoSectionOffset; C.Length = Header.Length + 4; - + UnitOffset += C.Length; if (Header.Version < 5 || Header.UnitType == dwarf::DW_UT_split_compile) { - Expected EID = getCUIdentifiers( - Header, AbbrevSection, Info.substr(UnitOffset, C.Length), - CurStrOffsetSection, CurStrSection); + Expected EID = + getCUIdentifiers(Header, AbbrevSection, + Info.substr(UnitOffset - C.Length, C.Length), + CurStrOffsetSection, CurStrSection); if (!EID) return createFileError(Input, EID.takeError()); @@ -779,12 +778,15 @@ P.first->second.Name = ID.Name; P.first->second.DWOName = ID.DWOName; - Out.emitBytes(Info.substr(UnitOffset, C.Length)); - InfoSectionOffset += C.Length; FoundCUUnit = true; - break; + } else if (Header.UnitType == dwarf::DW_UT_split_type) { + auto P = TypeIndexEntries.insert( + std::make_pair(Header.Signature.getValue(), Entry)); + if (!P.second) + continue; } - UnitOffset += Header.Length + 4; + Out.emitBytes(Info.substr(UnitOffset - C.Length, C.Length)); + InfoSectionOffset += C.Length; } } @@ -793,7 +795,7 @@ if (IndexVersion == 2) { // Add types from the .debug_types section from DWARF < 5. - addAllTypes( + addAllTypesFromTypesSection( Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry, ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)]); } @@ -858,21 +860,41 @@ InfoSectionOffset += C.Length; } - if (!CurTypesSection.empty()) { - if (CurTypesSection.size() != 1) - return make_error("multiple type unit sections in .dwp file"); - DWARFUnitIndex TUIndex(DW_SECT_EXT_TYPES); + if (!CurTUIndexSection.empty()) { + llvm::DWARFSectionKind TUSectionKind; + MCSection *OutSection; + StringRef TypeInputSection; + // Write type units into debug info section for DWARFv5. + if (Version >= 5) { + TUSectionKind = DW_SECT_INFO; + OutSection = InfoSection; + TypeInputSection = DwpSingleInfoSection; + } else { + // Write type units into debug types section for DWARF < 5. + if (CurTypesSection.size() != 1) + return make_error( + "multiple type unit sections in .dwp file"); + + TUSectionKind = DW_SECT_EXT_TYPES; + OutSection = TypesSection; + TypeInputSection = CurTypesSection.front(); + } + + DWARFUnitIndex TUIndex(TUSectionKind); DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0); if (!TUIndex.parse(TUIndexData)) return make_error("failed to parse tu_index"); - if (TUIndex.getVersion() != 2) - return make_error("expected index version 2, but got: " + - utostr(TUIndex.getVersion())); - - addAllTypesFromDWP( - Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(), - CurEntry, - ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)]); + if (TUIndex.getVersion() != IndexVersion) + return make_error("incompatible tu_index versions, found " + + utostr(TUIndex.getVersion()) + + " and expecting " + utostr(IndexVersion)); + + unsigned TypesContributionIndex = + getContributionIndex(TUSectionKind, IndexVersion); + addAllTypesFromDWP(Out, TypeIndexEntries, TUIndex, OutSection, + TypeInputSection, CurEntry, + ContributionOffsets[TypesContributionIndex], + TypesContributionIndex); } }