[llvm] [llvm][dwarf][rfc][donotcommit] Enable print of ranges addresses from .debug_info.dwo (PR #65516)
Alexander Yermolovich via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 6 11:52:30 PDT 2023
https://github.com/ayermolo created https://github.com/llvm/llvm-project/pull/65516:
Summary:
For split dwarf some of the sections remain in the main binary. For DWARF4 it's
.debug_ranges, .debug_addr. For DWARF5 it's .debug_addr. When using
llvm-dwarfdump on .dwo/.dwp files this results in not being able to see what ranges
and addresses for DW_AT_low_pc are used in DIEs, and output having "Error: " in it.
I added a new option --main-binary=<binary> that will create a link in
DWARFContext between DWO context and main binary. This allows tool to display
addresses for DW_AT_ranges and DW_AT_low_pc.
Example (DWARF5):
DW_TAG_inlined_subroutine
DW_AT_abstract_origin (0x00000b21 "flush_RL")
DW_AT_ranges (indexed (0x0) rangelist = 0x00000054
[0x0000000000403fe2, 0x0000000000403ff3)
[0x0000000000403ff6, 0x0000000000403ffe))
DW_TAG_subprogram
DW_AT_low_pc (0x0000000000403940)
>From 6707fd3038b13d6884896dd2b4603e7c55d159ef Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Fri, 1 Sep 2023 13:36:43 -0700
Subject: [PATCH] [llvm][dwarf][rfc][donotcommit] Enable print of ranges
addresses from .debug_info.dwo
Summary:
For split dwarf some of the sections remain in the main binary. For DWARF4 it's
.debug_ranges, .debug_addr. For DWARF5 it's .debug_addr. When using
llvm-dwarfdump on .dwo/.dwp files this results in not being able to see what ranges
and addresses for DW_AT_low_pc are used in DIEs, and output having "Error: " in it.
I added a new option --main-binary=<binary> that will create a link in
DWARFContext between DWO context and main binary. This allows tool to display
addresses for DW_AT_ranges and DW_AT_low_pc.
Example (DWARF5):
DW_TAG_inlined_subroutine
DW_AT_abstract_origin (0x00000b21 "flush_RL")
DW_AT_ranges (indexed (0x0) rangelist = 0x00000054
[0x0000000000403fe2, 0x0000000000403ff3)
[0x0000000000403ff6, 0x0000000000403ffe))
DW_TAG_subprogram
DW_AT_low_pc (0x0000000000403940)
---
.../llvm/DebugInfo/DWARF/DWARFContext.h | 24 ++++++++++
llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 48 +++++++++++++++++--
llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 7 ++-
llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 21 ++++++++
4 files changed, 94 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 4bd8394e6b4ec82..f05106522c4b554 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -125,6 +125,12 @@ class DWARFContext : public DIContext {
DWARFUnitVector &getDWOUnits(bool Lazy = false);
std::unique_ptr<const DWARFObject> 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<const DWARFObject> MainBinaryDObj = nullptr;
+ /// DWARFContext for main binary.
+ std::unique_ptr<DWARFContext> MainBinaryDICtx = nullptr;
// When set parses debug_info.dwo/debug_abbrev.dwo manually and populates CU
// Index, and TU Index for DWARF5.
@@ -145,6 +151,13 @@ class DWARFContext : public DIContext {
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;
}
@@ -478,6 +491,17 @@ class DWARFContext : public DIContext {
/// 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<void(Error)> RecoverableErrorHandler =
+ WithColor::defaultErrorHandler,
+ std::function<void(Error)> WarningHandler =
+ WithColor::defaultWarningHandler);
+
private:
void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
std::vector<DILocal> &Result);
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index a45ed0e56553d4e..42e414bb9fa6896 100644
--- 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 <cstdint>
#include <deque>
#include <map>
+#include <optional>
#include <string>
+#include <unordered_map>
#include <utility>
#include <vector>
@@ -1004,21 +1006,47 @@ void DWARFContext::dump(
DObj->getAbbrevDWOSection()))
getDebugAbbrevDWO()->dump(OS);
+ std::unordered_map<uint64_t, DWARFUnit *> DwoIDToDUMap;
+ auto SetSections = [&](DWARFUnit &U) -> void {
+ std::optional<uint64_t> DWOID = U.getDWOId();
+ if (U.isDWOUnit() && DWOID) {
+ auto MapIter = DwoIDToDUMap.find(*DWOID);
+ if (MapIter != DwoIDToDUMap.end()) {
+ DWARFDie UnitDie = MapIter->second->getUnitDIE();
+ std::optional<uint64_t> RangeBase = UnitDie.getRangesBaseAttribute();
+ if (U.getVersion() < 5 && RangeBase)
+ U.setRangesSection(&MainBinaryDObj->getRangesSection(), *RangeBase);
+ if (std::optional<uint64_t> 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<uint64_t> 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) {
@@ -2428,3 +2456,15 @@ uint8_t DWARFContext::getCUAddrSize() {
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<void(Error)> RecoverableErrorHandler,
+ std::function<void(Error)> WarningHandler) {
+ MainBinaryDObj = std::make_unique<DWARFObjInMemory>(
+ 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
index 387345a4ac2d601..6d6759d892d9396 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -366,8 +366,11 @@ Error DWARFUnit::extractRangeList(uint64_t RangeListOffset,
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
index 156e10c84dddec9..9e9b258b4758112 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -154,6 +154,11 @@ static std::array<std::optional<uint64_t>, (unsigned)DIDT_ID_Count> DumpOffsets;
static alias DumpDebugFrameAlias("eh-frame", desc("Alias for --debug-frame"),
NotHidden, cat(SectionCategory),
aliasopt(DumpDebugFrame));
+static cl::opt<std::string>
+ MainBinary("main-binary",
+ desc("Specifies the main binary for cases when .dwo/.dwp file "
+ "is processed."),
+ cl::init(""), cat(DwarfDumpCategory));
static list<std::string>
ArchFilters("arch",
desc("Dump debug information for the specified CPU "
@@ -714,6 +719,9 @@ static bool handleArchive(StringRef Filename, Archive &Arch,
static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
HandlerFn HandleObj, raw_ostream &OS) {
Expected<std::unique_ptr<Binary>> BinOrErr = object::createBinary(Buffer);
+ std::unique_ptr<MemoryBuffer> MainBuffer = nullptr;
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MainBuffOrErr = nullptr;
+ std::unique_ptr<Binary> MainBin = nullptr;
error(Filename, BinOrErr.takeError());
bool Result = true;
@@ -727,6 +735,19 @@ static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
*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<std::unique_ptr<Binary>> MainBinOrErr =
+ object::createBinary(*MainBuffer);
+ error(MainBinary, MainBinOrErr.takeError());
+ MainBin = std::move(MainBinOrErr.get());
+ if (auto *Obj = dyn_cast<ObjectFile>(MainBin.get()))
+ DICtx->setMainBinaryObjAndCreateContext(
+ *Obj, DWARFContext::ProcessDebugRelocations::Process, nullptr,
+ RecoverableErrorHandler);
+ }
if (!HandleObj(*Obj, *DICtx, Filename, OS))
Result = false;
}
More information about the llvm-commits
mailing list