diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
commit | eb11fae6d08f479c0799db45860a98af528fa6e7 (patch) | |
tree | 44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/DebugInfo/DWARF/DWARFContext.cpp | |
parent | b8a2042aa938069e862750553db0e4d82d25822c (diff) |
Notes
Diffstat (limited to 'lib/DebugInfo/DWARF/DWARFContext.cpp')
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFContext.cpp | 267 |
1 files changed, 168 insertions, 99 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index eb23ca8229a3..da13c5047f77 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -25,6 +25,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" @@ -43,9 +44,11 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstdint> +#include <deque> #include <map> #include <string> #include <utility> @@ -82,7 +85,8 @@ static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) { OS << "UUID: "; memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID)); OS.write_uuid(UUID); - OS << ' ' << MachO->getFileFormatName(); + Triple T = MachO->getArchTriple(); + OS << " (" << T.getArchName() << ')'; OS << ' ' << MachO->getFileName() << '\n'; } } @@ -106,12 +110,12 @@ collectContributionData(DWARFContext::cu_iterator_range CUs, // Sort the contributions so that any invalid ones are placed at // the start of the contributions vector. This way they are reported // first. - std::sort(Contributions.begin(), Contributions.end(), - [](const Optional<StrOffsetsContributionDescriptor> &L, - const Optional<StrOffsetsContributionDescriptor> &R) { - if (L && R) return L->Base < R->Base; - return R.hasValue(); - }); + llvm::sort(Contributions.begin(), Contributions.end(), + [](const Optional<StrOffsetsContributionDescriptor> &L, + const Optional<StrOffsetsContributionDescriptor> &R) { + if (L && R) return L->Base < R->Base; + return R.hasValue(); + }); // Uniquify contributions, as it is possible that units (specifically // type units in dwo or dwp files) share contributions. We don't want @@ -169,7 +173,11 @@ static void dumpDWARFv5StringOffsetsSection( OS << (ContributionHeader - Offset) << "\n"; } OS << format("0x%8.8x: ", (uint32_t)ContributionHeader); - OS << "Contribution size = " << Contribution->Size + // In DWARF v5 the contribution size in the descriptor does not equal + // the originally encoded length (it does not contain the length of the + // version field and the padding, a total of 4 bytes). Add them back in + // for reporting. + OS << "Contribution size = " << (Contribution->Size + (Version < 5 ? 0 : 4)) << ", Format = " << (Format == DWARF32 ? "DWARF32" : "DWARF64") << ", Version = " << Version << "\n"; @@ -241,26 +249,26 @@ static void dumpStringOffsetsSection( } } -// We want to supply the Unit associated with a .debug_line[.dwo] table when -// we dump it, if possible, but still dump the table even if there isn't a Unit. -// Therefore, collect up handles on all the Units that point into the -// line-table section. -typedef std::map<uint64_t, DWARFUnit *> LineToUnitMap; - -static LineToUnitMap -buildLineToUnitMap(DWARFContext::cu_iterator_range CUs, - DWARFContext::tu_section_iterator_range TUSections) { - LineToUnitMap LineToUnit; - for (const auto &CU : CUs) - if (auto CUDIE = CU->getUnitDIE()) - if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) - LineToUnit.insert(std::make_pair(*StmtOffset, &*CU)); - for (const auto &TUS : TUSections) - for (const auto &TU : TUS) - if (auto TUDIE = TU->getUnitDIE()) - if (auto StmtOffset = toSectionOffset(TUDIE.find(DW_AT_stmt_list))) - LineToUnit.insert(std::make_pair(*StmtOffset, &*TU)); - return LineToUnit; +// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). +static void dumpRnglistsSection(raw_ostream &OS, + DWARFDataExtractor &rnglistData, + DIDumpOptions DumpOpts) { + uint32_t Offset = 0; + while (rnglistData.isValidOffset(Offset)) { + llvm::DWARFDebugRnglistTable Rnglists; + uint32_t TableOffset = Offset; + if (Error Err = Rnglists.extract(rnglistData, &Offset)) { + WithColor::error() << toString(std::move(Err)) << '\n'; + uint64_t Length = Rnglists.length(); + // Keep going after an error, if we can, assuming that the length field + // could be read. If it couldn't, stop reading the section. + if (Length == 0) + break; + Offset = TableOffset + Length; + } else { + Rnglists.dump(OS, DumpOpts); + } + } } void DWARFContext::dump( @@ -347,11 +355,11 @@ void DWARFContext::dump( if (shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, DObj->getDebugFrameSection())) - getDebugFrame()->dump(OS, DumpOffset); + getDebugFrame()->dump(OS, getRegisterInfo(), DumpOffset); if (shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame, DObj->getEHFrameSection())) - getEHFrame()->dump(OS, DumpOffset); + getEHFrame()->dump(OS, getRegisterInfo(), DumpOffset); if (DumpType & DIDT_DebugMacro) { if (Explicit || !getDebugMacro()->empty()) { @@ -369,63 +377,39 @@ void DWARFContext::dump( set.dump(OS); } - if (shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine, - DObj->getLineSection().Data)) { - LineToUnitMap LineToUnit = - buildLineToUnitMap(compile_units(), type_unit_sections()); - unsigned Offset = 0; - DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(), - 0); - while (Offset < LineData.getData().size()) { - DWARFUnit *U = nullptr; - auto It = LineToUnit.find(Offset); - if (It != LineToUnit.end()) - U = It->second; - LineData.setAddressSize(U ? U->getAddressByteSize() : 0); - DWARFDebugLine::LineTable LineTable; - if (DumpOffset && Offset != *DumpOffset) { - // Find the size of this part of the line table section and skip it. - unsigned OldOffset = Offset; - LineTable.Prologue.parse(LineData, &Offset, U); - Offset = OldOffset + LineTable.Prologue.TotalLength + - LineTable.Prologue.sizeofTotalLength(); + auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser, + DIDumpOptions DumpOpts) { + while (!Parser.done()) { + if (DumpOffset && Parser.getOffset() != *DumpOffset) { + Parser.skip(); continue; } - // Verbose dumping is done during parsing and not on the intermediate - // representation. - OS << "debug_line[" << format("0x%8.8x", Offset) << "]\n"; - unsigned OldOffset = Offset; + OS << "debug_line[" << format("0x%8.8x", Parser.getOffset()) << "]\n"; if (DumpOpts.Verbose) { - LineTable.parse(LineData, &Offset, U, &OS); + Parser.parseNext(DWARFDebugLine::warn, DWARFDebugLine::warn, &OS); } else { - LineTable.parse(LineData, &Offset, U); - LineTable.dump(OS); + DWARFDebugLine::LineTable LineTable = Parser.parseNext(); + LineTable.dump(OS, DumpOpts); } - // Check for unparseable prologue, to avoid infinite loops. - if (OldOffset == Offset) - break; } + }; + + if (shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine, + DObj->getLineSection().Data)) { + DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(), + 0); + DWARFDebugLine::SectionParser Parser(LineData, *this, compile_units(), + type_unit_sections()); + DumpLineSection(Parser, DumpOpts); } if (shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine, DObj->getLineDWOSection().Data)) { - LineToUnitMap LineToUnit = - buildLineToUnitMap(dwo_compile_units(), dwo_type_unit_sections()); - unsigned Offset = 0; DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(), isLittleEndian(), 0); - while (Offset < LineData.getData().size()) { - DWARFUnit *U = nullptr; - auto It = LineToUnit.find(Offset); - if (It != LineToUnit.end()) - U = It->second; - DWARFDebugLine::LineTable LineTable; - unsigned OldOffset = Offset; - if (!LineTable.Prologue.parse(LineData, &Offset, U)) - break; - if (!DumpOffset || OldOffset == *DumpOffset) - LineTable.dump(OS); - } + DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_compile_units(), + dwo_type_unit_sections()); + DumpLineSection(Parser, DumpOpts); } if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex, @@ -458,6 +442,18 @@ void DWARFContext::dump( strDWOOffset = offset; } } + if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr, + DObj->getLineStringSection())) { + DataExtractor strData(DObj->getLineStringSection(), isLittleEndian(), 0); + uint32_t offset = 0; + uint32_t strOffset = 0; + while (const char *s = strData.getCStr(&offset)) { + OS << format("0x%8.8x: \"", strOffset); + OS.write_escaped(s); + OS << "\"\n"; + strOffset = offset; + } + } if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges, DObj->getRangeSection().Data)) { @@ -475,8 +471,27 @@ void DWARFContext::dump( isLittleEndian(), savedAddressByteSize); uint32_t offset = 0; DWARFDebugRangeList rangeList; - while (rangeList.extract(rangesData, &offset)) + while (rangesData.isValidOffset(offset)) { + if (Error E = rangeList.extract(rangesData, &offset)) { + WithColor::error() << toString(std::move(E)) << '\n'; + break; + } rangeList.dump(OS); + } + } + + if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists, + DObj->getRnglistsSection().Data)) { + DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(), + isLittleEndian(), 0); + dumpRnglistsSection(OS, RnglistData, DumpOpts); + } + + if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists, + DObj->getRnglistsDWOSection().Data)) { + DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(), + isLittleEndian(), 0); + dumpRnglistsSection(OS, RnglistData, DumpOpts); } if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames, @@ -534,6 +549,9 @@ void DWARFContext::dump( if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC, DObj->getAppleObjCSection().Data)) getAppleObjC().dump(OS); + if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames, + DObj->getDebugNamesSection().Data)) + getDebugNames().dump(OS); } DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { @@ -549,9 +567,19 @@ DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { // probably only one unless this is something like LTO - though an in-process // built/cached lookup table could be used in that case to improve repeated // lookups of different CUs in the DWO. - for (const auto &DWOCU : dwo_compile_units()) + for (const auto &DWOCU : dwo_compile_units()) { + // Might not have parsed DWO ID yet. + if (!DWOCU->getDWOId()) { + if (Optional<uint64_t> DWOId = + toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id))) + DWOCU->setDWOId(*DWOId); + else + // No DWO ID? + continue; + } if (DWOCU->getDWOId() == Hash) return DWOCU.get(); + } return nullptr; } @@ -633,7 +661,7 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() { return Loc.get(); Loc.reset(new DWARFDebugLoc); - // assume all compile units have the same address byte size + // Assume all compile units have the same address byte size. if (getNumCompileUnits()) { DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(), getCompileUnitAtIndex(0)->getAddressByteSize()); @@ -646,9 +674,13 @@ const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() { if (LocDWO) return LocDWO.get(); - DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 0); LocDWO.reset(new DWARFDebugLocDWO()); - LocDWO->parse(LocData); + // Assume all compile units have the same address byte size. + if (getNumCompileUnits()) { + DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), + getCompileUnitAtIndex(0)->getAddressByteSize()); + LocDWO->parse(LocData); + } return LocDWO.get(); } @@ -674,8 +706,8 @@ const DWARFDebugFrame *DWARFContext::getDebugFrame() { // provides this information). This problem is fixed in DWARFv4 // See this dwarf-discuss discussion for more details: // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html - DataExtractor debugFrameData(DObj->getDebugFrameSection(), isLittleEndian(), - DObj->getAddressSize()); + DWARFDataExtractor debugFrameData(DObj->getDebugFrameSection(), + isLittleEndian(), DObj->getAddressSize()); DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */)); DebugFrame->parse(debugFrameData); return DebugFrame.get(); @@ -685,8 +717,8 @@ const DWARFDebugFrame *DWARFContext::getEHFrame() { if (EHFrame) return EHFrame.get(); - DataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(), - DObj->getAddressSize()); + DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(), + DObj->getAddressSize()); DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */)); DebugFrame->parse(debugFrameData); return DebugFrame.get(); @@ -702,43 +734,59 @@ const DWARFDebugMacro *DWARFContext::getDebugMacro() { return Macro.get(); } -static DWARFAcceleratorTable & -getAccelTable(std::unique_ptr<DWARFAcceleratorTable> &Cache, - const DWARFObject &Obj, const DWARFSection &Section, - StringRef StringSection, bool IsLittleEndian) { +template <typename T> +static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj, + const DWARFSection &Section, StringRef StringSection, + bool IsLittleEndian) { if (Cache) return *Cache; DWARFDataExtractor AccelSection(Obj, Section, IsLittleEndian, 0); DataExtractor StrData(StringSection, IsLittleEndian, 0); - Cache.reset(new DWARFAcceleratorTable(AccelSection, StrData)); + Cache.reset(new T(AccelSection, StrData)); if (Error E = Cache->extract()) llvm::consumeError(std::move(E)); return *Cache; } -const DWARFAcceleratorTable &DWARFContext::getAppleNames() { +const DWARFDebugNames &DWARFContext::getDebugNames() { + return getAccelTable(Names, *DObj, DObj->getDebugNamesSection(), + DObj->getStringSection(), isLittleEndian()); +} + +const AppleAcceleratorTable &DWARFContext::getAppleNames() { return getAccelTable(AppleNames, *DObj, DObj->getAppleNamesSection(), DObj->getStringSection(), isLittleEndian()); } -const DWARFAcceleratorTable &DWARFContext::getAppleTypes() { +const AppleAcceleratorTable &DWARFContext::getAppleTypes() { return getAccelTable(AppleTypes, *DObj, DObj->getAppleTypesSection(), DObj->getStringSection(), isLittleEndian()); } -const DWARFAcceleratorTable &DWARFContext::getAppleNamespaces() { +const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() { return getAccelTable(AppleNamespaces, *DObj, DObj->getAppleNamespacesSection(), DObj->getStringSection(), isLittleEndian()); } -const DWARFAcceleratorTable &DWARFContext::getAppleObjC() { +const AppleAcceleratorTable &DWARFContext::getAppleObjC() { return getAccelTable(AppleObjC, *DObj, DObj->getAppleObjCSection(), DObj->getStringSection(), isLittleEndian()); } -const DWARFLineTable * +const DWARFDebugLine::LineTable * DWARFContext::getLineTableForUnit(DWARFUnit *U) { + Expected<const DWARFDebugLine::LineTable *> ExpectedLineTable = + getLineTableForUnit(U, DWARFDebugLine::warn); + if (!ExpectedLineTable) { + DWARFDebugLine::warn(ExpectedLineTable.takeError()); + return nullptr; + } + return *ExpectedLineTable; +} + +Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit( + DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) { if (!Line) Line.reset(new DWARFDebugLine); @@ -762,7 +810,8 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) { // We have to parse it first. DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(), U->getAddressByteSize()); - return Line->getOrParseLineTable(lineData, stmtOffset, U); + return Line->getOrParseLineTable(lineData, stmtOffset, *this, U, + RecoverableErrorCallback); } void DWARFContext::parseCompileUnits() { @@ -1119,7 +1168,7 @@ static bool isRelocScattered(const object::ObjectFile &Obj, } ErrorPolicy DWARFContext::defaultErrorHandler(Error E) { - errs() << "error: " + toString(std::move(E)) << '\n'; + WithColor::error() << toString(std::move(E)) << '\n'; return ErrorPolicy::Continue; } @@ -1145,17 +1194,20 @@ class DWARFObjInMemory final : public DWARFObject { DWARFSectionMap LocSection; DWARFSectionMap LineSection; DWARFSectionMap RangeSection; + DWARFSectionMap RnglistsSection; DWARFSectionMap StringOffsetSection; DWARFSectionMap InfoDWOSection; DWARFSectionMap LineDWOSection; DWARFSectionMap LocDWOSection; DWARFSectionMap StringOffsetDWOSection; DWARFSectionMap RangeDWOSection; + DWARFSectionMap RnglistsDWOSection; DWARFSectionMap AddrSection; DWARFSectionMap AppleNamesSection; DWARFSectionMap AppleTypesSection; DWARFSectionMap AppleNamespacesSection; DWARFSectionMap AppleObjCSection; + DWARFSectionMap DebugNamesSection; DWARFSectionMap *mapNameToDWARFSection(StringRef Name) { return StringSwitch<DWARFSectionMap *>(Name) @@ -1164,9 +1216,12 @@ class DWARFObjInMemory final : public DWARFObject { .Case("debug_line", &LineSection) .Case("debug_str_offsets", &StringOffsetSection) .Case("debug_ranges", &RangeSection) + .Case("debug_rnglists", &RnglistsSection) .Case("debug_info.dwo", &InfoDWOSection) .Case("debug_loc.dwo", &LocDWOSection) .Case("debug_line.dwo", &LineDWOSection) + .Case("debug_names", &DebugNamesSection) + .Case("debug_rnglists.dwo", &RnglistsDWOSection) .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) .Case("debug_addr", &AddrSection) .Case("apple_names", &AppleNamesSection) @@ -1192,8 +1247,11 @@ class DWARFObjInMemory final : public DWARFObject { StringRef CUIndexSection; StringRef GdbIndexSection; StringRef TUIndexSection; + StringRef LineStringSection; - SmallVector<SmallString<32>, 4> UncompressedSections; + // A deque holding section data whose iterators are not invalidated when + // new decompressed sections are inserted at the end. + std::deque<SmallString<0>> UncompressedSections; StringRef *mapSectionToMember(StringRef Name) { if (DWARFSection *Sec = mapNameToDWARFSection(Name)) @@ -1214,6 +1272,7 @@ class DWARFObjInMemory final : public DWARFObject { .Case("debug_cu_index", &CUIndexSection) .Case("debug_tu_index", &TUIndexSection) .Case("gdb_index", &GdbIndexSection) + .Case("debug_line_str", &LineStringSection) // Any more debug info sections go here. .Default(nullptr); } @@ -1230,11 +1289,11 @@ class DWARFObjInMemory final : public DWARFObject { if (!Decompressor) return Decompressor.takeError(); - SmallString<32> Out; + SmallString<0> Out; if (auto Err = Decompressor->resizeAndDecompress(Out)) return Err; - UncompressedSections.emplace_back(std::move(Out)); + UncompressedSections.push_back(std::move(Out)); Data = UncompressedSections.back(); return Error::success(); @@ -1423,6 +1482,9 @@ public: const DWARFSection &getRangeDWOSection() const override { return RangeDWOSection; } + const DWARFSection &getRnglistsDWOSection() const override { + return RnglistsDWOSection; + } const DWARFSection &getAddrSection() const override { return AddrSection; } StringRef getCUIndexSection() const override { return CUIndexSection; } StringRef getGdbIndexSection() const override { return GdbIndexSection; } @@ -1432,6 +1494,7 @@ public: const DWARFSection &getStringOffsetSection() const override { return StringOffsetSection; } + StringRef getLineStringSection() const override { return LineStringSection; } // Sections for DWARF5 split dwarf proposal. const DWARFSection &getInfoDWOSection() const override { @@ -1451,6 +1514,9 @@ public: const DWARFSection &getLineSection() const override { return LineSection; } StringRef getStringSection() const override { return StringSection; } const DWARFSection &getRangeSection() const override { return RangeSection; } + const DWARFSection &getRnglistsSection() const override { + return RnglistsSection; + } StringRef getMacinfoSection() const override { return MacinfoSection; } StringRef getPubNamesSection() const override { return PubNamesSection; } StringRef getPubTypesSection() const override { return PubTypesSection; } @@ -1472,6 +1538,9 @@ public: const DWARFSection &getAppleObjCSection() const override { return AppleObjCSection; } + const DWARFSection &getDebugNamesSection() const override { + return DebugNamesSection; + } StringRef getFileName() const override { return FileName; } uint8_t getAddressSize() const override { return AddressSize; } |