libDebugInfo: Support symbolizing using DWP files

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303609 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Blaikie 2017-05-23 06:48:53 +00:00
parent 013125cca7
commit 893c346e0c
6 changed files with 59 additions and 13 deletions

View File

@ -76,6 +76,8 @@ class DWARFContext : public DIContext {
std::unique_ptr<DWARFContext> Context;
};
StringMap<std::weak_ptr<DWOFile>> DWOFiles;
std::weak_ptr<DWOFile> DWP;
bool CheckedForDWP = false;
/// Read compile units from the debug_info section (if necessary)
/// and store them in CUs.
@ -171,6 +173,8 @@ public:
return DWOCUs[index].get();
}
DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
/// Get a DIE given an exact offset.
DWARFDie getDIEForOffset(uint32_t Offset);
@ -212,6 +216,7 @@ public:
DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
virtual StringRef getFileName() const = 0;
virtual bool isLittleEndian() const = 0;
virtual uint8_t getAddressSize() const = 0;
virtual const DWARFSection &getInfoSection() = 0;
@ -271,6 +276,7 @@ private:
class DWARFContextInMemory : public DWARFContext {
virtual void anchor();
StringRef FileName;
bool IsLittleEndian;
uint8_t AddressSize;
DWARFSection InfoSection;
@ -324,6 +330,7 @@ public:
uint8_t AddrSize,
bool isLittleEndian = sys::IsLittleEndianHost);
StringRef getFileName() const override { return FileName; }
bool isLittleEndian() const override { return IsLittleEndian; }
uint8_t getAddressSize() const override { return AddressSize; }
const DWARFSection &getInfoSection() override { return InfoSection; }

View File

@ -287,6 +287,15 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
getStringSection(), isLittleEndian());
}
DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
// FIXME: Improve this for the case where this DWO file is really a DWP file
// with an index - use the index for lookup instead of a linear search.
for (const auto &DWOCU : dwo_compile_units())
if (DWOCU->getDWOId() == Hash)
return DWOCU.get();
return nullptr;
}
DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) {
parseCompileUnits();
if (auto *CU = CUs.getUnitForOffset(Offset))
@ -899,22 +908,47 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
std::shared_ptr<DWARFContext>
DWARFContext::getDWOContext(StringRef AbsolutePath) {
auto &Entry = DWOFiles[AbsolutePath];
if (auto S = Entry.lock()) {
if (auto S = DWP.lock()) {
DWARFContext *Ctxt = S->Context.get();
return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
}
auto S = std::make_shared<DWOFile>();
auto Obj = object::ObjectFile::createObjectFile(AbsolutePath);
std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];
if (auto S = Entry->lock()) {
DWARFContext *Ctxt = S->Context.get();
return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
}
SmallString<128> DWPName;
Expected<OwningBinary<ObjectFile>> Obj = [&] {
if (!CheckedForDWP) {
(getFileName() + ".dwp").toVector(DWPName);
auto Obj = object::ObjectFile::createObjectFile(DWPName);
if (Obj) {
Entry = &DWP;
return Obj;
} else {
CheckedForDWP = true;
// TODO: Should this error be handled (maybe in a high verbosity mode)
// before falling back to .dwo files?
consumeError(Obj.takeError());
}
}
return object::ObjectFile::createObjectFile(AbsolutePath);
}();
if (!Obj) {
// TODO: Actually report errors helpfully.
consumeError(Obj.takeError());
return nullptr;
}
auto S = std::make_shared<DWOFile>();
S->File = std::move(Obj.get());
S->Context = llvm::make_unique<DWARFContextInMemory>(*S->File.getBinary());
Entry = S;
*Entry = S;
auto *Ctxt = S->Context.get();
return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
}
@ -1011,8 +1045,8 @@ Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec,
}
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
const LoadedObjectInfo *L)
: IsLittleEndian(Obj.isLittleEndian()),
const LoadedObjectInfo *L)
: FileName(Obj.getFileName()), IsLittleEndian(Obj.isLittleEndian()),
AddressSize(Obj.getBytesInAddress()) {
for (const SectionRef &Section : Obj.sections()) {
StringRef name;

View File

@ -274,13 +274,10 @@ bool DWARFUnit::parseDWO() {
if (!DWOContext)
return false;
for (const auto &DWOCU : DWOContext->dwo_compile_units())
if (DWOCU->getDWOId() == DWOId) {
DWO = std::shared_ptr<DWARFUnit>(std::move(DWOContext), DWOCU.get());
break;
}
if (!DWO)
DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId);
if (!DWOCU)
return false;
DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU);
// Share .debug_addr and .debug_ranges section with compile unit in .dwo
DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
auto DWORangesBase = UnitDie.getRangesBaseAttribute();

Binary file not shown.

Binary file not shown.

View File

@ -27,6 +27,9 @@ RUN: cp %p/Inputs/split-dwarf-multiple-cu.dwo %T
RUN: echo "%p/Inputs/split-dwarf-multiple-cu.o 0x4" >> %t.input
RUN: cp %p/Inputs/split-dwarf-addr-object-relocation.dwo %T
RUN: echo "%p/Inputs/split-dwarf-addr-object-relocation.o 0x14" >> %t.input
RUN: cp %p/Inputs/split-dwarf-dwp.o %T
RUN: cp %p/Inputs/split-dwarf-dwp.o.dwp %T
RUN: echo "%T/split-dwarf-dwp.o 0x4" >> %t.input
RUN: llvm-symbolizer --functions=linkage --inlining --demangle=false \
RUN: --default-arch=i386 < %t.input | FileCheck --check-prefix=CHECK --check-prefix=SPLIT --check-prefix=DWO %s
@ -147,6 +150,11 @@ CHECK-NEXT: split-dwarf-addr-object-relocation.cpp:3:3
CHECK-NEXT: f3
CHECK-NEXT: split-dwarf-addr-object-relocation.cpp:6:0
CHECK: f2
CHECK-NEXT: split-dwarf-dwp.cpp:3:3
CHECK-NEXT: f3
CHECK-NEXT: split-dwarf-dwp.cpp:6:0
RUN: echo "unexisting-file 0x1234" > %t.input2
RUN: llvm-symbolizer < %t.input2 2>&1 | FileCheck %s --check-prefix=MISSING-FILE