From: David Blaikie Date: Tue, 17 Nov 2015 00:39:55 +0000 (+0000) Subject: dwarfdump: Use the index to find the right abbrev offset in DWP files X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=7cd8652959dda0b52548d3bbc3dab53e85cd45f9 dwarfdump: Use the index to find the right abbrev offset in DWP files git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253277 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h index 743f9c696e9..84f12a52062 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h @@ -19,9 +19,12 @@ public: DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, bool LE, - const DWARFUnitSectionBase &UnitSection) - : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + const DWARFUnitSectionBase &UnitSection, + const DWARFUnitIndex::Entry *Entry) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection, + Entry) {} void dump(raw_ostream &OS); + static const DWARFSectionKind Section = DW_SECT_INFO; // VTable anchor. ~DWARFCompileUnit() override; }; diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h index 32beeea45d6..ce253a05bf8 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -41,6 +41,8 @@ class DWARFContext : public DIContext { DWARFUnitSection CUs; std::vector> TUs; + std::unique_ptr CUIndex; + std::unique_ptr TUIndex; std::unique_ptr Abbrev; std::unique_ptr Loc; std::unique_ptr Aranges; @@ -145,6 +147,9 @@ public: return DWOCUs[index].get(); } + const DWARFUnitIndex &getCUIndex(); + const DWARFUnitIndex &getTUIndex(); + /// Get a pointer to the parsed DebugAbbrev object. const DWARFDebugAbbrev *getDebugAbbrev(); diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h index f24e27819da..5265ea49d68 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -22,12 +22,16 @@ public: DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, bool LE, - const DWARFUnitSectionBase &UnitSection) - : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + const DWARFUnitSectionBase &UnitSection, + const DWARFUnitIndex::Entry *Entry) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection, + Entry) {} uint32_t getHeaderSize() const override { return DWARFUnit::getHeaderSize() + 12; } void dump(raw_ostream &OS); + static const DWARFSectionKind Section = DW_SECT_TYPES; + protected: bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override; }; diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 2d05a520b50..4fb8ba07737 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -16,6 +16,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include namespace llvm { @@ -39,7 +40,8 @@ public: virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; void parse(DWARFContext &C, const DWARFSection &Section); - void parseDWO(DWARFContext &C, const DWARFSection &DWOSection); + void parseDWO(DWARFContext &C, const DWARFSection &DWOSection, + DWARFUnitIndex *Index = nullptr); protected: virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section, @@ -49,6 +51,9 @@ protected: ~DWARFUnitSectionBase() = default; }; +const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, + DWARFSectionKind Kind); + /// Concrete instance of DWARFUnitSection, specialized for one Unit type. template class DWARFUnitSection final : public SmallVector, 1>, @@ -81,11 +86,13 @@ private: StringRef SOS, StringRef AOS, bool LE) override { if (Parsed) return; + const auto &Index = getDWARFUnitIndex(Context, UnitType::Section); DataExtractor Data(Section.Data, LE, 0); uint32_t Offset = 0; while (Data.isValidOffset(Offset)) { - auto U = llvm::make_unique(Context, Section, DA, RS, SS, SOS, - AOS, LE, *this); + auto U = + llvm::make_unique(Context, Section, DA, RS, SS, SOS, AOS, + LE, *this, Index.getFromOffset(Offset)); if (!U->extract(Data, &Offset)) break; this->push_back(std::move(U)); @@ -129,6 +136,8 @@ class DWARFUnit { }; std::unique_ptr DWO; + const DWARFUnitIndex::Entry *IndexEntry; + protected: virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); /// Size in bytes of the unit header. @@ -138,7 +147,8 @@ public: DWARFUnit(DWARFContext &Context, const DWARFSection &Section, const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, bool LE, - const DWARFUnitSectionBase &UnitSection); + const DWARFUnitSectionBase &UnitSection, + const DWARFUnitIndex::Entry *IndexEntry = nullptr); virtual ~DWARFUnit(); diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h index dab7f2918c2..f2b3010e77b 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h @@ -17,6 +17,17 @@ namespace llvm { +enum DWARFSectionKind { + DW_SECT_INFO = 1, + DW_SECT_TYPES, + DW_SECT_ABBREV, + DW_SECT_LINE, + DW_SECT_LOC, + DW_SECT_STR_OFFSETS, + DW_SECT_MACINFO, + DW_SECT_MACRO, +}; + class DWARFUnitIndex { struct Header { uint32_t Version; @@ -28,36 +39,34 @@ class DWARFUnitIndex { void dump(raw_ostream &OS) const; }; - struct HashRow { +public: + class Entry { + const DWARFUnitIndex *Index; uint64_t Signature; struct SectionContribution { uint32_t Offset; - uint32_t Size; + uint32_t Length; }; std::unique_ptr Contributions; - }; + friend class DWARFUnitIndex; - enum DwarfSection { - DW_SECT_INFO = 1, - DW_SECT_TYPES, - DW_SECT_ABBREV, - DW_SECT_LINE, - DW_SECT_LOC, - DW_SECT_STR_OFFSETS, - DW_SECT_MACINFO, - DW_SECT_MACRO, + public: + const SectionContribution *getOffset(DWARFSectionKind Sec) const; + const SectionContribution *getOffset() const; }; struct Header Header; - std::unique_ptr ColumnKinds; - std::unique_ptr Rows; + int InfoColumn = -1; + std::unique_ptr ColumnKinds; + std::unique_ptr Rows; - static StringRef getColumnHeader(DwarfSection DS); + static StringRef getColumnHeader(DWARFSectionKind DS); public: bool parse(DataExtractor IndexData); void dump(raw_ostream &OS) const; + const Entry *getFromOffset(uint32_t Offset) const; }; } diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index f4624851737..8313cacb4f6 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -274,6 +274,28 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { getStringSection(), isLittleEndian()); } +const DWARFUnitIndex &DWARFContext::getCUIndex() { + if (CUIndex) + return *CUIndex; + + DataExtractor CUIndexData(getCUIndexSection(), isLittleEndian(), 0); + + CUIndex = llvm::make_unique(); + CUIndex->parse(CUIndexData); + return *CUIndex; +} + +const DWARFUnitIndex &DWARFContext::getTUIndex() { + if (TUIndex) + return *TUIndex; + + DataExtractor TUIndexData(getTUIndexSection(), isLittleEndian(), 0); + + TUIndex = llvm::make_unique(); + TUIndex->parse(TUIndexData); + return *TUIndex; +} + const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { if (Abbrev) return Abbrev.get(); diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index 348476d72b6..169acee62d7 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -14,7 +14,7 @@ #include "llvm/Support/Path.h" #include -using namespace llvm; +namespace llvm { using namespace dwarf; void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { @@ -24,7 +24,8 @@ void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { } void DWARFUnitSectionBase::parseDWO(DWARFContext &C, - const DWARFSection &DWOSection) { + const DWARFSection &DWOSection, + DWARFUnitIndex *Index) { parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(), C.getStringDWOSection(), C.getStringOffsetDWOSection(), C.getAddrSection(), C.isLittleEndian()); @@ -33,10 +34,11 @@ void DWARFUnitSectionBase::parseDWO(DWARFContext &C, DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, bool LE, - const DWARFUnitSectionBase &UnitSection) + const DWARFUnitSectionBase &UnitSection, + const DWARFUnitIndex::Entry *IndexEntry) : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS), StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), - isLittleEndian(LE), UnitSection(UnitSection) { + isLittleEndian(LE), UnitSection(UnitSection), IndexEntry(IndexEntry) { clear(); } @@ -69,6 +71,17 @@ bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { Length = debug_info.getU32(offset_ptr); Version = debug_info.getU16(offset_ptr); uint64_t AbbrOffset = debug_info.getU32(offset_ptr); + if (IndexEntry) { + if (AbbrOffset) + return false; + auto *UnitContrib = IndexEntry->getOffset(); + if (!UnitContrib || UnitContrib->Length != (Length + 4)) + return false; + auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV); + if (!AbbrEntry) + return false; + AbbrOffset = AbbrEntry->Offset; + } AddrSize = debug_info.getU8(offset_ptr); bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); @@ -375,3 +388,12 @@ DWARFUnit::getInlinedChainForAddress(uint64_t Address) { return DWARFDebugInfoEntryInlinedChain(); return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); } + +const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, + DWARFSectionKind Kind) { + if (Kind == DW_SECT_INFO) + return Context.getCUIndex(); + assert(Kind == DW_SECT_TYPES); + return Context.getTUIndex(); +} +} diff --git a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp index 37d78313af9..baefed30f36 100644 --- a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp @@ -39,10 +39,10 @@ bool DWARFUnitIndex::parse(DataExtractor IndexData) { (2 * Header.NumUnits + 1) * 4 * Header.NumColumns)) return false; - Rows = llvm::make_unique(Header.NumBuckets); + Rows = llvm::make_unique(Header.NumBuckets); auto Contribs = - llvm::make_unique(Header.NumUnits); - ColumnKinds = llvm::make_unique(Header.NumColumns); + llvm::make_unique(Header.NumUnits); + ColumnKinds = llvm::make_unique(Header.NumColumns); // Read Hash Table of Signatures for (unsigned i = 0; i != Header.NumBuckets; ++i) @@ -53,35 +53,43 @@ bool DWARFUnitIndex::parse(DataExtractor IndexData) { auto Index = IndexData.getU32(&Offset); if (!Index) continue; + Rows[i].Index = this; Rows[i].Contributions = - llvm::make_unique(Header.NumColumns); + llvm::make_unique(Header.NumColumns); Contribs[Index - 1] = Rows[i].Contributions.get(); } // Read the Column Headers - for (unsigned i = 0; i != Header.NumColumns; ++i) - ColumnKinds[i] = static_cast(IndexData.getU32(&Offset)); + for (unsigned i = 0; i != Header.NumColumns; ++i) { + ColumnKinds[i] = static_cast(IndexData.getU32(&Offset)); + if (ColumnKinds[i] == DW_SECT_INFO || ColumnKinds[i] == DW_SECT_TYPES) { + if (InfoColumn != -1) + return false; + InfoColumn = i; + } + } + + if (InfoColumn == -1) + return false; // Read Table of Section Offsets for (unsigned i = 0; i != Header.NumUnits; ++i) { auto *Contrib = Contribs[i]; - for (unsigned i = 0; i != Header.NumColumns; ++i) { + for (unsigned i = 0; i != Header.NumColumns; ++i) Contrib[i].Offset = IndexData.getU32(&Offset); - } } // Read Table of Section Sizes for (unsigned i = 0; i != Header.NumUnits; ++i) { auto *Contrib = Contribs[i]; - for (unsigned i = 0; i != Header.NumColumns; ++i) { - Contrib[i].Size = IndexData.getU32(&Offset); - } + for (unsigned i = 0; i != Header.NumColumns; ++i) + Contrib[i].Length = IndexData.getU32(&Offset); } return true; } -StringRef DWARFUnitIndex::getColumnHeader(DwarfSection DS) { +StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) { #define CASE(DS) \ case DW_SECT_##DS: \ return #DS; @@ -95,7 +103,7 @@ StringRef DWARFUnitIndex::getColumnHeader(DwarfSection DS) { CASE(MACINFO); CASE(MACRO); } - llvm_unreachable("unknown DwarfSection"); + llvm_unreachable("unknown DWARFSectionKind"); } void DWARFUnitIndex::dump(raw_ostream &OS) const { @@ -113,11 +121,33 @@ void DWARFUnitIndex::dump(raw_ostream &OS) const { OS << format("%5u 0x%016" PRIx64 " ", i, Row.Signature); for (unsigned i = 0; i != Header.NumColumns; ++i) { auto &Contrib = Contribs[i]; - OS << format("[0x%08u, 0x%08u) ", Contrib.Offset, - Contrib.Offset + Contrib.Size); + OS << format("[0x%08x, 0x%08x) ", Contrib.Offset, + Contrib.Offset + Contrib.Length); } OS << '\n'; } } } + +const DWARFUnitIndex::Entry::SectionContribution * +DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const { + uint32_t i = 0; + for (; i != Index->Header.NumColumns; ++i) + if (Index->ColumnKinds[i] == Sec) + return &Contributions[i]; + return nullptr; +} +const DWARFUnitIndex::Entry::SectionContribution * +DWARFUnitIndex::Entry::getOffset() const { + return &Contributions[Index->InfoColumn]; +} + +const DWARFUnitIndex::Entry * +DWARFUnitIndex::getFromOffset(uint32_t Offset) const { + for (uint32_t i = 0; i != Header.NumBuckets; ++i) + if (const auto &Contribs = Rows[i].Contributions) + if (Contribs[InfoColumn].Offset == Offset) + return &Rows[i]; + return nullptr; +} } diff --git a/test/DebugInfo/Inputs/dwarfdump-dwp.x86_64.o b/test/DebugInfo/Inputs/dwarfdump-dwp.x86_64.o index 2b7ed526ca9..da059f73b9f 100644 Binary files a/test/DebugInfo/Inputs/dwarfdump-dwp.x86_64.o and b/test/DebugInfo/Inputs/dwarfdump-dwp.x86_64.o differ diff --git a/test/DebugInfo/dwarfdump-dwp.test b/test/DebugInfo/dwarfdump-dwp.test index 953a58cb4af..0dbe1edf246 100644 --- a/test/DebugInfo/dwarfdump-dwp.test +++ b/test/DebugInfo/dwarfdump-dwp.test @@ -6,20 +6,37 @@ RUN: llvm-dwarfdump %p/Inputs/dwarfdump-dwp.x86_64.o | FileCheck %s ; foo a; ; b.cpp: ; struct bar { }; -; bar b; +; bar b() { +; } + +; CHECK: .debug_info.dwo contents: +; CHECK: Compile Unit + +; Verify that the second CU uses the index for its abbrev offset +; CHECK: Compile Unit +; CHECK-SAME: abbr_offset = 0x0043 +; CHECK: DW_TAG_compile_unit +; CHECK-NOT: DW_TAG +; FIXME: Implement str_offsets support so we find b.cpp here \/ +; CHECK: DW_AT_name {{.*}} "a.cpp" + +; Verify that abbreviations are decoded using the abbrev offset in the index +; CHECK: DW_TAG_subprogram +; CHECK: DW_TAG_structure_type ; CHECK: .debug_cu_index contents: ; CHECK-NEXT: version = 2 slots = 16 -; CHECK: Index Signature INFO ABBREV LINE STR_OFFSETS +; CHECK: Index Signature INFO ABBREV LINE STR_OFFSETS ; CHECK-NEXT: ----- ------------------ ------------------------ ------------------------ ------------------------ ------------------------ -; CHECK-NEXT: 8 0x03c30756e2d45008 [0x00000000, 0x00000045) [0x00000000, 0x00000067) [0x00000000, 0x00000026) [0x00000000, 0x00000016) -; CHECK-NEXT: 12 0x9aeb3a61ed48510c [0x00000045, 0x00000090) [0x00000067, 0x00000134) [0x00000026, 0x00000052) [0x00000016, 0x00000032) +; CHECK-NEXT: 2 0xfef104c25502f092 [0x0000002d, 0x0000005f) [0x00000043, 0x0000008e) [0x0000001a, 0x00000034) [0x00000010, 0x00000024) +; CHECK-NEXT: 8 0x03c30756e2d45008 [0x00000000, 0x0000002d) [0x00000000, 0x00000043) [0x00000000, 0x0000001a) [0x00000000, 0x00000010) ; CHECK: .debug_tu_index contents: ; CHECK-NEXT: version = 2 slots = 16 ; CHECK: Index Signature TYPES ABBREV LINE STR_OFFSETS ; CHECK-NEXT: ----- ------------------ ------------------------ ------------------------ ------------------------ ------------------------ -; CHECK-NEXT: 8 0x1d02f3be30cc5688 [0x00000036, 0x00000072) [0x00000067, 0x00000134) [0x00000026, 0x00000052) [0x00000016, 0x00000032) -; CHECK-NEXT: 12 0x3875c0e21cda63fc [0x00000000, 0x00000036) [0x00000000, 0x00000067) [0x00000000, 0x00000026) [0x00000000, 0x00000016) +; CHECK-NEXT: 8 0x1d02f3be30cc5688 [0x00000024, 0x00000048) [0x00000043, 0x0000008e) [0x0000001a, 0x00000034) [0x00000010, 0x00000024) +; CHECK-NEXT: 12 0x3875c0e21cda63fc [0x00000000, 0x00000024) [0x00000000, 0x00000043) [0x00000000, 0x0000001a) [0x00000000, 0x00000010) -; TODO: use the index section offset info to correctly dump debug_info +; TODO: use the index section offset info to correctly dump strings in debug info +; TODO: use the index section offset info to correctly dump file names in debug info