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 @@ -98,6 +98,12 @@ void parseDWOUnits(bool Lazy = false); std::unique_ptr DObj; + /// Can be optionally set by tools that work with .dwo/.dwp files to reference + /// main binary debug information. Usefull for accessing .debug_ranges and + /// .debug_addr section. + std::unique_ptr MainBinaryDObj = nullptr; + /// DWARFContext for main binary. + std::unique_ptr MainBinaryDICtx = nullptr; /// Helper enum to distinguish between macro[.dwo] and macinfo[.dwo] /// section. @@ -126,6 +132,13 @@ const DWARFObject &getDWARFObj() const { return *DObj; } + const DWARFObject *getMainBinaryDWARFObj() const { + return MainBinaryDObj.get(); + } + const DWARFContext *getDWARFContextMainBinary() const { + return MainBinaryDICtx.get(); + } + static bool classof(const DIContext *DICtx) { return DICtx->getKind() == CK_DWARF; } @@ -465,6 +478,17 @@ /// manually only for DWARF5. void setParseCUTUIndexManually(bool PCUTU) { ParseCUTUIndexManually = PCUTU; } + /// Sets the object corresponding to the main binary to which the .dwo/.dwp + /// file belongs. + void setMainBinaryObjAndCreateContext( + const object::ObjectFile &Obj, + ProcessDebugRelocations RelocAction = ProcessDebugRelocations::Process, + const LoadedObjectInfo *L = nullptr, + std::function RecoverableErrorHandler = + WithColor::defaultErrorHandler, + std::function WarningHandler = + WithColor::defaultWarningHandler); + private: /// Parse a macro[.dwo] or macinfo[.dwo] section. std::unique_ptr 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 @@ -47,8 +47,8 @@ #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" #include "llvm/Support/Format.h" -#include "llvm/Support/LEB128.h" #include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -56,7 +56,9 @@ #include #include #include +#include #include +#include #include #include @@ -383,21 +385,47 @@ DObj->getAbbrevDWOSection())) getDebugAbbrevDWO()->dump(OS); + std::unordered_map DwoIDToDUMap; + auto SetSections = [&](DWARFUnit &U) -> void { + std::optional DWOID = U.getDWOId(); + if (U.isDWOUnit() && DWOID) { + auto MapIter = DwoIDToDUMap.find(*DWOID); + if (MapIter != DwoIDToDUMap.end()) { + DWARFDie UnitDie = MapIter->second->getUnitDIE(); + std::optional RangeBase = UnitDie.getRangesBaseAttribute(); + if (U.getVersion() < 5 && RangeBase) + U.setRangesSection(&MainBinaryDObj->getRangesSection(), *RangeBase); + if (std::optional AddrBase = + MapIter->second->getAddrOffsetSectionBase()) + U.setAddrOffsetSection(&MainBinaryDObj->getAddrSection(), *AddrBase); + } + } + }; auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) { OS << '\n' << Name << " contents:\n"; if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo]) - for (const auto &U : Units) + for (const auto &U : Units) { + SetSections(*U); U->getDIEForOffset(*DumpOffset) .dump(OS, 0, DumpOpts.noImplicitRecursion()); + } else - for (const auto &U : Units) + for (const auto &U : Units) { + SetSections(*U); U->dump(OS, DumpOpts); + } }; if ((DumpType & DIDT_DebugInfo)) { if (Explicit || getNumCompileUnits()) dumpDebugInfo(".debug_info", info_section_units()); - if (ExplicitDWO || getNumDWOCompileUnits()) + if (ExplicitDWO || getNumDWOCompileUnits()) { + if (MainBinaryDObj) { + for (const auto &U : MainBinaryDICtx->compile_units()) + if (std::optional DWOID = U->getDWOId()) + DwoIDToDUMap.insert({*DWOID, U.get()}); + } dumpDebugInfo(".debug_info.dwo", dwo_info_section_units()); + } } auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) { @@ -2143,3 +2171,15 @@ auto CUs = compile_units(); return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize(); } + +void DWARFContext::setMainBinaryObjAndCreateContext( + const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction, + const LoadedObjectInfo *L, + std::function RecoverableErrorHandler, + std::function WarningHandler) { + MainBinaryDObj = std::make_unique( + Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction); + MainBinaryDICtx = + DWARFContext::create(Obj, DWARFContext::ProcessDebugRelocations::Process, + nullptr, "", RecoverableErrorHandler); +} diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -366,8 +366,11 @@ DWARFDebugRangeList &RangeList) const { // Require that compile unit is extracted. assert(!DieArray.empty()); - DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, - IsLittleEndian, getAddressByteSize()); + DWARFDataExtractor RangesData(isDWOUnit() && Context.getMainBinaryDWARFObj() + ? *Context.getMainBinaryDWARFObj() + : Context.getDWARFObj(), + *RangeSection, IsLittleEndian, + getAddressByteSize()); uint64_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; return RangeList.extract(RangesData, &ActualRangeListOffset); } 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 @@ -154,6 +154,11 @@ static alias DumpDebugFrameAlias("eh-frame", desc("Alias for --debug-frame"), NotHidden, cat(SectionCategory), aliasopt(DumpDebugFrame)); +static cl::opt + MainBinary("main-binary", + desc("Specifies the main binary for cases when .dwo/.dwp file " + "is processed."), + cl::init(""), cat(DwarfDumpCategory)); static list ArchFilters("arch", desc("Dump debug information for the specified CPU " @@ -714,6 +719,9 @@ static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, HandlerFn HandleObj, raw_ostream &OS) { Expected> BinOrErr = object::createBinary(Buffer); + std::unique_ptr MainBuffer = nullptr; + ErrorOr> MainBuffOrErr = nullptr; + std::unique_ptr MainBin = nullptr; error(Filename, BinOrErr.takeError()); bool Result = true; @@ -727,6 +735,19 @@ *Obj, DWARFContext::ProcessDebugRelocations::Process, nullptr, "", RecoverableErrorHandler); DICtx->setParseCUTUIndexManually(ManuallyGenerateUnitIndex); + if (!MainBinary.empty()) { + MainBuffOrErr = MemoryBuffer::getFileOrSTDIN(MainBinary); + error(MainBinary, MainBuffOrErr.getError()); + MainBuffer = std::move(MainBuffOrErr.get()); + Expected> MainBinOrErr = + object::createBinary(*MainBuffer); + error(MainBinary, MainBinOrErr.takeError()); + MainBin = std::move(MainBinOrErr.get()); + if (auto *Obj = dyn_cast(MainBin.get())) + DICtx->setMainBinaryObjAndCreateContext( + *Obj, DWARFContext::ProcessDebugRelocations::Process, nullptr, + RecoverableErrorHandler); + } if (!HandleObj(*Obj, *DICtx, Filename, OS)) Result = false; }