Skip to content

Commit

Permalink
[Symbolize] Teach symbolizer to work directly on object file.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
slinder1 committed Feb 12, 2021
1 parent 4841a22 commit 12999d7
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 36 deletions.
24 changes: 23 additions & 1 deletion llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
Expand Up @@ -58,16 +58,25 @@ class LLVMSymbolizer {
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();
Expand All @@ -81,16 +90,29 @@ class LLVMSymbolizer {
// 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
/// only reported once. Subsequent calls to get module info for a module that
/// 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,
Expand Down
114 changes: 79 additions & 35 deletions llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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();
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 12999d7

Please sign in to comment.