diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -111,6 +111,10 @@ MacroDwoSection }; + // When set parses debug_info.dwo/debug_abbrev.dwo manually and populates CU + // Index, and TU Index for DWARF5. + bool ParseCUTUIndexManually; + public: DWARFContext(std::unique_ptr DObj, std::string DWPName = "", @@ -454,6 +458,14 @@ /// into "SectionedAddress Address" DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); + /// Returns whether CU/TU should be populated manually. TU Index populated + /// manually only for DWARF5. + bool getParseCUTUIndexManually() const { return ParseCUTUIndexManually; } + + /// Sets whether CU/TU should be populated manually. TU Index populated + /// manually only for DWARF5. + void setParseCUTUIndexManually(bool PCUTU) { ParseCUTUIndexManually = PCUTU; } + private: /// Parse a macro[.dwo] or macinfo[.dwo] section. std::unique_ptr diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -93,6 +93,7 @@ } uint64_t getLength() const { return Length; } uint64_t getAbbrOffset() const { return AbbrOffset; } + void setAbbrOffset(uint64_t Offset) { AbbrOffset = Offset; } Optional getDWOId() const { return DWOId; } void setDWOId(uint64_t Id) { assert((!DWOId || *DWOId == Id) && "setting DWOId to a different value"); diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h @@ -124,12 +124,14 @@ public: const SectionContribution *getContribution(DWARFSectionKind Sec) const; const SectionContribution *getContribution() const; + SectionContribution &getContribution(); const SectionContribution *getContributions() const { return Contributions.get(); } uint64_t getSignature() const { return Signature; } + bool isValid() { return Index; } }; private: @@ -170,6 +172,10 @@ ArrayRef getRows() const { return makeArrayRef(Rows.get(), Header.NumBuckets); } + + MutableArrayRef getMutableRows() { + return makeMutableArrayRef(Rows.get(), Header.NumBuckets); + } }; } // end namespace llvm 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 @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -781,14 +782,76 @@ return Success; } +enum class IndexType { CUIndex, TUIndex }; +using EntryType = DWARFUnitIndex::Entry::SectionContribution; +using EntryMap = std::unordered_map; +void fixupIndex(const DWARFObject &DObj, DWARFContext &C, + DWARFUnitIndex &Index) { + EntryMap Map; + if (DObj.getCUIndexSection().empty()) + return; + + uint64_t Offset = 0; + uint32_t TruncOffset = 0; + DObj.forEachInfoDWOSections([&](const DWARFSection &S) { + if (!(C.getParseCUTUIndexManually() || + S.Data.size() >= std::numeric_limits::max())) + return; + + DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0); + while (Data.isValidOffset(Offset)) { + DWARFUnitHeader Header; + if (!Header.extract(C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) { + logAllUnhandledErrors( + createError("Failed to parse CU header in DWP file"), errs()); + Map.clear(); + break; + } + + auto Iter = Map.insert( + {TruncOffset, + {(uint32_t)Header.getOffset(), + (uint32_t)(Header.getNextUnitOffset() - Header.getOffset())}}); + if (!Iter.second) { + logAllUnhandledErrors( + createError("Collision occured between two truncated offsets"), + errs()); + Map.clear(); + return; + } + + Offset = Header.getNextUnitOffset(); + TruncOffset = Offset; + } + }); + + if (Map.empty()) + return; + + for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) { + if (!E.isValid()) + continue; + DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution(); + auto Iter = Map.find(CUOff.Offset); + if (Iter == Map.end()) { + errs() << "Could not find CU Offset in the Map\n"; + break; + } + CUOff.Offset = Iter->second.Offset; + CUOff.Length = Iter->second.Length; + } + + return; +} + const DWARFUnitIndex &DWARFContext::getCUIndex() { if (CUIndex) return *CUIndex; DataExtractor CUIndexData(DObj->getCUIndexSection(), isLittleEndian(), 0); - CUIndex = std::make_unique(DW_SECT_INFO); CUIndex->parse(CUIndexData); + fixupIndex(*DObj, *this, *CUIndex.get()); return *CUIndex; } @@ -797,9 +860,12 @@ return *TUIndex; DataExtractor TUIndexData(DObj->getTUIndexSection(), isLittleEndian(), 0); - TUIndex = std::make_unique(DW_SECT_EXT_TYPES); TUIndex->parse(TUIndexData); + // If we are parsing TU-index and for .debug_types section we don't need + // to do anything. + if (CUIndex->getVersion() != 2) + fixupIndex(*DObj, *this, *TUIndex.get()); return *TUIndex; } @@ -1976,9 +2042,7 @@ const DWARFSection &getAppleObjCSection() const override { return AppleObjCSection; } - const DWARFSection &getNamesSection() const override { - return NamesSection; - } + const DWARFSection &getNamesSection() const override { return NamesSection; } StringRef getFileName() const override { return FileName; } uint8_t getAddressSize() const override { return AddressSize; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp @@ -253,6 +253,11 @@ return nullptr; } +DWARFUnitIndex::Entry::SectionContribution & +DWARFUnitIndex::Entry::getContribution() { + return Contributions[Index->InfoColumn]; +} + const DWARFUnitIndex::Entry::SectionContribution * DWARFUnitIndex::Entry::getContribution() const { return &Contributions[Index->InfoColumn]; diff --git a/llvm/test/tools/llvm-dwp/X86/debug_macro_v5.s b/llvm/test/tools/llvm-dwp/X86/debug_macro_v5.s --- a/llvm/test/tools/llvm-dwp/X86/debug_macro_v5.s +++ b/llvm/test/tools/llvm-dwp/X86/debug_macro_v5.s @@ -2,7 +2,8 @@ # 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 2>&1 -# RUN: llvm-dwarfdump -debug-macro -debug-cu-index %t.dwp | FileCheck %s +# RUN: llvm-dwarfdump -debug-macro -debug-cu-index %t.dwp | FileCheck -check-prefix=CHECK %s +# RUN: llvm-dwarfdump -debug-macro -debug-cu-index -manaully-generate-cu-tu-index %t.dwp | FileCheck -check-prefix=CHECK2 %s # CHECK-DAG: .debug_macro.dwo contents: # CHECK: macro header: version = 0x0005, flags = 0x00, format = DWARF32 @@ -15,6 +16,9 @@ # CHECK: Index Signature INFO ABBREV STR_OFFSETS MACRO # CHECK: 1 0x0000000000000000 [0x00000000, 0x00000019) [0x00000000, 0x00000008) [0x00000000, 0x0000000c) [0x00000000, 0x0000000b) +# CHECK2: Index Signature INFO ABBREV STR_OFFSETS MACRO +# CHECK2: 1 0x0000000000000000 [0x00000000, 0x00000019) [0x00000000, 0x00000008) [0x00000000, 0x0000000c) [0x00000000, 0x0000000b) + .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/info-v5.s b/llvm/test/tools/llvm-dwp/X86/info-v5.s --- a/llvm/test/tools/llvm-dwp/X86/info-v5.s +++ b/llvm/test/tools/llvm-dwp/X86/info-v5.s @@ -3,7 +3,8 @@ # 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 -v %t.dwp | FileCheck %s +# RUN: llvm-dwarfdump -v %t.dwp | FileCheck -check-prefix=CHECK %s +# RUN: llvm-dwarfdump -manaully-generate-cu-tu-index -v %t.dwp | FileCheck -check-prefix=CHECK2 %s #CHECK-DAG: .debug_info.dwo contents: #CHECK: 0x00000000: Compile Unit: length = 0x00000050, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_compile, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = [[DWOID:.*]] (next unit at 0x00000054) @@ -13,6 +14,14 @@ # CHECK: Index Signature INFO ABBREV # CHECK: 1 [[DWOID]] [0x00000000, 0x00000054) [0x00000000, 0x0000002a) +#CHECK2-DAG: .debug_info.dwo contents: +#CHECK2: 0x00000000: Compile Unit: length = 0x00000050, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_compile, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = [[DWOID2:.*]] (next unit at 0x00000054) + +# CHECK2-DAG: .debug_cu_index contents: +# CHECK2: version = 5, units = 1, slots = 2 +# CHECK2: Index Signature INFO +# CHECK21: 1 [[DWOID2]] [0x00000000, 0x00000054) [0x00000000, 0x0000002a) + .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/loclists.s b/llvm/test/tools/llvm-dwp/X86/loclists.s --- a/llvm/test/tools/llvm-dwp/X86/loclists.s +++ b/llvm/test/tools/llvm-dwp/X86/loclists.s @@ -3,7 +3,8 @@ # 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-loclists -debug-cu-index -debug-tu-index %t.dwp | FileCheck %s +# RUN: llvm-dwarfdump -debug-loclists -debug-cu-index -debug-tu-index %t.dwp | FileCheck -check-prefix=CHECK %s +# RUN: llvm-dwarfdump -debug-cu-index -debug-tu-index -manaully-generate-cu-tu-index %t.dwp | FileCheck -check-prefix=CHECK2 %s # CHECK-DAG: .debug_loclists.dwo contents: # CHECK: locations list header: length = 0x00000019, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000001 @@ -22,6 +23,14 @@ # CHECK: Index Signature INFO ABBREV LOCLISTS # CHECK: 2 {{.*}} [0x00000000, 0x00000018) [0x00000000, 0x00000004) [0x00000000, 0x0000001d) +# CHECK2-DAG: .debug_cu_index contents: +# CHECK2: Index Signature INFO ABBREV LOCLISTS +# CHECK2: 1 {{.*}} [0x00000018, 0x0000002d) [0x00000000, 0x00000004) [0x00000000, 0x0000001d) + +# CHECK2-DAG: .debug_tu_index contents: +# CHECK2: Index Signature INFO ABBREV LOCLISTS +# CHECK2: 2 {{.*}} [0x00000000, 0x00000018) [0x00000000, 0x00000004) [0x00000000, 0x0000001d) + .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/rnglists.s b/llvm/test/tools/llvm-dwp/X86/rnglists.s --- a/llvm/test/tools/llvm-dwp/X86/rnglists.s +++ b/llvm/test/tools/llvm-dwp/X86/rnglists.s @@ -3,7 +3,8 @@ # 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-rnglists -debug-cu-index -debug-tu-index %t.dwp | FileCheck %s +# RUN: llvm-dwarfdump -debug-rnglists -debug-cu-index -debug-tu-index %t.dwp | FileCheck -check-prefix=CHECK %s +# RUN: llvm-dwarfdump -debug-cu-index -debug-tu-index -manaully-generate-cu-tu-index %t.dwp | FileCheck -check-prefix=CHECK2 %s # CHECK-DAG: .debug_cu_index contents: # CHECK: Index Signature INFO ABBREV RNGLISTS @@ -22,6 +23,14 @@ # CHECK-NEXT: [0x0000000000000004, 0x0000000000000008) # CHECK-NEXT: [0x000000000000000c, 0x0000000000000010) +# CHECK2-DAG: .debug_cu_index contents: +# CHECK2: Index Signature INFO ABBREV RNGLISTS +# CHECK2: 1 {{.*}} [0x00000018, 0x0000002d) [0x00000000, 0x00000004) [0x00000000, 0x00000017) + +# CHECK2-DAG: .debug_tu_index contents: +# CHECK2: Index Signature INFO ABBREV RNGLISTS +# CHECK2: 2 {{.*}} [0x00000000, 0x00000018) [0x00000000, 0x00000004) [0x00000000, 0x00000017) + .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/tu_units_v5.s b/llvm/test/tools/llvm-dwp/X86/tu_units_v5.s --- a/llvm/test/tools/llvm-dwp/X86/tu_units_v5.s +++ b/llvm/test/tools/llvm-dwp/X86/tu_units_v5.s @@ -3,7 +3,8 @@ # 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 +# RUN: llvm-dwarfdump -debug-info -debug-tu-index %t.dwp | FileCheck -check-prefix=CHECK %s +# RUN2: llvm-dwarfdump -debug-info -debug-tu-index -manaully-generate-cu-tu-index %t.dwp | FileCheck -check-prefix=CHECK2 %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. @@ -17,6 +18,15 @@ # CHECK: 1 [[TUID1]] [0x00000000, 0x0000001b) [0x00000000, 0x00000010) # CHECK: 4 [[TUID2]] [0x0000001b, 0x00000036) [0x00000000, 0x00000010) +# CHECK2-DAG: .debug_info.dwo contents: +# CHECK2: 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) +# CHECK2: 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) +# CHECK2-DAG: .debug_tu_index contents: +# CHECK2: version = 5, units = 2, slots = 4 +# CHECK2: Index Signature INFO ABBREV +# CHECK2: 1 [[TUID1]] [0x00000000, 0x0000001b) [0x00000000, 0x00000010) +# CHECK2: 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: diff --git a/llvm/test/tools/llvm-dwp/X86/type_dedup.test b/llvm/test/tools/llvm-dwp/X86/type_dedup.test --- a/llvm/test/tools/llvm-dwp/X86/type_dedup.test +++ b/llvm/test/tools/llvm-dwp/X86/type_dedup.test @@ -1,8 +1,10 @@ RUN: llvm-dwp %p/../Inputs/type_dedup/a.dwo %p/../Inputs/type_dedup/b.dwo -o %t -RUN: llvm-dwarfdump -v %t | FileCheck %s +RUN: llvm-dwarfdump -v %t | FileCheck -check-prefix=CHECK %s +RUN: llvm-dwarfdump -v -manaully-generate-cu-tu-index %t | FileCheck -check-prefix=CHECK2 %s RUN: llvm-dwp %p/../Inputs/type_dedup/b.dwo -o %tb.dwp RUN: llvm-dwp %p/../Inputs/type_dedup/a.dwo %tb.dwp -o %t -RUN: llvm-dwarfdump -v %t | FileCheck %s +RUN: llvm-dwarfdump -v %t | FileCheck -check-prefix=CHECK %s +RUN: llvm-dwarfdump -v -manaully-generate-cu-tu-index %t | FileCheck -check-prefix=CHECK2 %s a.cpp: struct common { }; @@ -36,3 +38,24 @@ CHECK: 0x00000066: DW_TAG_structure_type CHECK: DW_AT_name {{.*}} "bdistinct" CHECK-NOT: Type Unit + +CHECK2-LABEL: .debug_types.dwo contents: +CHECK2: [[COMMONUOFF:0x[0-9a-f]*]]: +CHECK2-LABEL: Type Unit: length = 0x00000020, format = DWARF32, version = 0x0004, abbr_offset = +CHECK2: 0x0000, addr_size = 0x08, name = 'common', type_signature = [[COMMONSIG:0x[0-9a-f]*]], type_offset = 0x[[COMMONOFF:.*]] (next unit at [[AUOFF:.*]]) +CHECK2: DW_TAG_type_unit +CHECK2: [[COMMONOFF]]: DW_TAG_structure_type +CHECK2: DW_AT_name {{.*}} "common" +CHECK2: [[AUOFF]]: +CHECK2-LABEL: Type Unit: length = 0x00000020, format = DWARF32, version = 0x0004, abbr_offset = +CHECK2: 0x0000, addr_size = 0x08, name = 'adistinct', type_signature = [[ASIG:0x[0-9a-f]*]], type_offset = 0x[[AOFF:.*]] (next unit at [[BUOFF:.*]]) +CHECK2: DW_TAG_type_unit +CHECK2: 0x00000042: DW_TAG_structure_type +CHECK2: DW_AT_name {{.*}} "adistinct" +CHECK2: [[BUOFF]]: +CHECK2-LABEL: Type Unit: length = 0x00000020, format = DWARF32, version = 0x0004, abbr_offset = +CHECK2: 0x{{.*}}, addr_size = 0x08, name = 'bdistinct', type_signature = [[BSIG:0x[0-9a-f]*]], type_offset = 0x[[BOFF:.*]] (next unit at [[XUOFF:.*]]) +CHECK2: DW_TAG_type_unit +CHECK2: 0x00000066: DW_TAG_structure_type +CHECK2: DW_AT_name {{.*}} "bdistinct" +CHECK2-NOT: Type Unit diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -255,6 +255,13 @@ ShowSources("show-sources", cl::desc("Show the sources across all compilation units."), cat(DwarfDumpCategory)); +static cl::opt ManuallyGenerateUnitIndex( + "manaully-generate-unit-index", + cl::desc("if the input is dwp file, parse .debug_info " + "section and use it to populate " + "DW_SECT_INFO contributions in cu-index. " + "For DWARF5 it also populated TU Index."), + cl::init(false), cl::Hidden, cl::cat(DwarfDumpCategory)); // facebook begin D13311561 static cl::opt Analyze("analyze", @@ -669,6 +676,7 @@ std::unique_ptr DICtx = DWARFContext::create( *Obj, DWARFContext::ProcessDebugRelocations::Process, nullptr, "", RecoverableErrorHandler); + DICtx->setParseCUTUIndexManually(ManuallyGenerateUnitIndex); if (!HandleObj(*Obj, *DICtx, Filename, OS)) Result = false; }