[Symbolize] Teach symbolizer to work directly on object file.

This patch intended to provide additional interface to LLVMsymbolizer
such that they work directly on object files. There is an existing
method - symbolizecode which takes an object file, this patch provides
similar overloads for symbolizeInlinedCode, symbolizeData,
symbolizeFrame. This can be useful for clients who already have a
in-memory object files to symbolize for.

Patch By: pvellien (praveen velliengiri)

Reviewed By: scott.linder

Differential Revision: https://reviews.llvm.org/D95232
This commit is contained in:
Scott Linder 2021-02-12 18:14:44 +00:00
parent 4841a225b7
commit 12999d749d
2 changed files with 102 additions and 36 deletions

View File

@ -58,16 +58,25 @@ public:
flush();
}
// Overloads accepting ObjectFile does not support COFF currently
Expected<DILineInfo> symbolizeCode(const ObjectFile &Obj,
object::SectionedAddress ModuleOffset);
Expected<DILineInfo> symbolizeCode(const std::string &ModuleName,
object::SectionedAddress ModuleOffset);
Expected<DIInliningInfo>
symbolizeInlinedCode(const ObjectFile &Obj,
object::SectionedAddress ModuleOffset);
Expected<DIInliningInfo>
symbolizeInlinedCode(const std::string &ModuleName,
object::SectionedAddress ModuleOffset);
Expected<DIGlobal> symbolizeData(const ObjectFile &Obj,
object::SectionedAddress ModuleOffset);
Expected<DIGlobal> symbolizeData(const std::string &ModuleName,
object::SectionedAddress ModuleOffset);
Expected<std::vector<DILocal>>
symbolizeFrame(const ObjectFile &Obj, object::SectionedAddress ModuleOffset);
Expected<std::vector<DILocal>>
symbolizeFrame(const std::string &ModuleName,
object::SectionedAddress ModuleOffset);
void flush();
@ -81,9 +90,21 @@ private:
// corresponding debug info. These objects can be the same.
using ObjectPair = std::pair<const ObjectFile *, const ObjectFile *>;
template <typename T>
Expected<DILineInfo>
symbolizeCodeCommon(SymbolizableModule *Info,
symbolizeCodeCommon(const T &ModuleSpecifier,
object::SectionedAddress ModuleOffset);
template <typename T>
Expected<DIInliningInfo>
symbolizeInlinedCodeCommon(const T &ModuleSpecifier,
object::SectionedAddress ModuleOffset);
template <typename T>
Expected<DIGlobal> symbolizeDataCommon(const T &ModuleSpecifier,
object::SectionedAddress ModuleOffset);
template <typename T>
Expected<std::vector<DILocal>>
symbolizeFrameCommon(const T &ModuleSpecifier,
object::SectionedAddress ModuleOffset);
/// Returns a SymbolizableModule or an error if loading debug info failed.
/// Only one attempt is made to load a module, and errors during loading are
@ -91,6 +112,7 @@ private:
/// failed to load will return nullptr.
Expected<SymbolizableModule *>
getOrCreateModuleInfo(const std::string &ModuleName);
Expected<SymbolizableModule *> getOrCreateModuleInfo(const ObjectFile &Obj);
Expected<SymbolizableModule *>
createModuleInfo(const ObjectFile *Obj,

View File

@ -39,9 +39,17 @@
namespace llvm {
namespace symbolize {
template <typename T>
Expected<DILineInfo>
LLVMSymbolizer::symbolizeCodeCommon(SymbolizableModule *Info,
LLVMSymbolizer::symbolizeCodeCommon(const T &ModuleSpecifier,
object::SectionedAddress ModuleOffset) {
auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
if (!InfoOrErr)
return InfoOrErr.takeError();
SymbolizableModule *Info = *InfoOrErr;
// A null module means an error has already been reported. Return an empty
// result.
if (!Info)
@ -63,37 +71,24 @@ LLVMSymbolizer::symbolizeCodeCommon(SymbolizableModule *Info,
Expected<DILineInfo>
LLVMSymbolizer::symbolizeCode(const ObjectFile &Obj,
object::SectionedAddress ModuleOffset) {
StringRef ModuleName = Obj.getFileName();
auto I = Modules.find(ModuleName);
if (I != Modules.end())
return symbolizeCodeCommon(I->second.get(), ModuleOffset);
std::unique_ptr<DIContext> Context = DWARFContext::create(Obj);
Expected<SymbolizableModule *> InfoOrErr =
createModuleInfo(&Obj, std::move(Context), ModuleName);
if (!InfoOrErr)
return InfoOrErr.takeError();
return symbolizeCodeCommon(*InfoOrErr, ModuleOffset);
return symbolizeCodeCommon(Obj, ModuleOffset);
}
Expected<DILineInfo>
LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
object::SectionedAddress ModuleOffset) {
Expected<SymbolizableModule *> InfoOrErr = getOrCreateModuleInfo(ModuleName);
if (!InfoOrErr)
return InfoOrErr.takeError();
return symbolizeCodeCommon(*InfoOrErr, ModuleOffset);
return symbolizeCodeCommon(ModuleName, ModuleOffset);
}
Expected<DIInliningInfo>
LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
object::SectionedAddress ModuleOffset) {
SymbolizableModule *Info;
if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
Info = InfoOrErr.get();
else
template <typename T>
Expected<DIInliningInfo> LLVMSymbolizer::symbolizeInlinedCodeCommon(
const T &ModuleSpecifier, object::SectionedAddress ModuleOffset) {
auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
if (!InfoOrErr)
return InfoOrErr.takeError();
SymbolizableModule *Info = *InfoOrErr;
// A null module means an error has already been reported. Return an empty
// result.
if (!Info)
@ -116,15 +111,28 @@ LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
return InlinedContext;
}
Expected<DIInliningInfo>
LLVMSymbolizer::symbolizeInlinedCode(const ObjectFile &Obj,
object::SectionedAddress ModuleOffset) {
return symbolizeInlinedCodeCommon(Obj, ModuleOffset);
}
Expected<DIInliningInfo>
LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
object::SectionedAddress ModuleOffset) {
return symbolizeInlinedCodeCommon(ModuleName, ModuleOffset);
}
template <typename T>
Expected<DIGlobal>
LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
object::SectionedAddress ModuleOffset) {
SymbolizableModule *Info;
if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
Info = InfoOrErr.get();
else
LLVMSymbolizer::symbolizeDataCommon(const T &ModuleSpecifier,
object::SectionedAddress ModuleOffset) {
auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
if (!InfoOrErr)
return InfoOrErr.takeError();
SymbolizableModule *Info = *InfoOrErr;
// A null module means an error has already been reported. Return an empty
// result.
if (!Info)
@ -142,15 +150,27 @@ LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
return Global;
}
Expected<DIGlobal>
LLVMSymbolizer::symbolizeData(const ObjectFile &Obj,
object::SectionedAddress ModuleOffset) {
return symbolizeDataCommon(Obj, ModuleOffset);
}
Expected<DIGlobal>
LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
object::SectionedAddress ModuleOffset) {
return symbolizeDataCommon(ModuleName, ModuleOffset);
}
template <typename T>
Expected<std::vector<DILocal>>
LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName,
object::SectionedAddress ModuleOffset) {
SymbolizableModule *Info;
if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
Info = InfoOrErr.get();
else
LLVMSymbolizer::symbolizeFrameCommon(const T &ModuleSpecifier,
object::SectionedAddress ModuleOffset) {
auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
if (!InfoOrErr)
return InfoOrErr.takeError();
SymbolizableModule *Info = *InfoOrErr;
// A null module means an error has already been reported. Return an empty
// result.
if (!Info)
@ -165,6 +185,18 @@ LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName,
return Info->symbolizeFrame(ModuleOffset);
}
Expected<std::vector<DILocal>>
LLVMSymbolizer::symbolizeFrame(const ObjectFile &Obj,
object::SectionedAddress ModuleOffset) {
return symbolizeFrameCommon(Obj, ModuleOffset);
}
Expected<std::vector<DILocal>>
LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName,
object::SectionedAddress ModuleOffset) {
return symbolizeFrameCommon(ModuleName, ModuleOffset);
}
void LLVMSymbolizer::flush() {
ObjectForUBPathAndArch.clear();
BinaryForPath.clear();
@ -571,6 +603,18 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
return createModuleInfo(Objects.first, std::move(Context), ModuleName);
}
Expected<SymbolizableModule *>
LLVMSymbolizer::getOrCreateModuleInfo(const ObjectFile &Obj) {
StringRef ObjName = Obj.getFileName();
auto I = Modules.find(ObjName);
if (I != Modules.end())
return I->second.get();
std::unique_ptr<DIContext> Context = DWARFContext::create(Obj);
// FIXME: handle COFF object with PDB info to use PDBContext
return createModuleInfo(&Obj, std::move(Context), ObjName);
}
namespace {
// Undo these various manglings for Win32 extern "C" functions: