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.
return DWOCUs[index].get();
}
+ DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
+
/// Get a DIE given an exact offset.
DWARFDie getDIEForOffset(uint32_t Offset);
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;
class DWARFContextInMemory : public DWARFContext {
virtual void anchor();
+ StringRef FileName;
bool IsLittleEndian;
uint8_t AddressSize;
DWARFSection InfoSection;
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; }
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))
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);
}
}
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;
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();
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
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