diff options
author | Alexey Samsonov <samsonov@google.com> | 2013-01-22 14:21:19 +0000 |
---|---|---|
committer | Alexey Samsonov <samsonov@google.com> | 2013-01-22 14:21:19 +0000 |
commit | c4c7ea3184335259da63d973acbed2043e8a6523 (patch) | |
tree | 965a21f78cc71764eae9ce6fddad6fd28aa75568 /tools | |
parent | be0008a4df72bf9da3246707cdec2766ace75d32 (diff) |
llvm-symbolizer: factor out bits of the tool into separate LLVMSymbolize.{h,cpp} files. No functionality change.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173159 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r-- | tools/llvm-symbolizer/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tools/llvm-symbolizer/LLVMSymbolize.cpp | 272 | ||||
-rw-r--r-- | tools/llvm-symbolizer/LLVMSymbolize.h | 88 | ||||
-rw-r--r-- | tools/llvm-symbolizer/llvm-symbolizer.cpp | 308 |
4 files changed, 381 insertions, 288 deletions
diff --git a/tools/llvm-symbolizer/CMakeLists.txt b/tools/llvm-symbolizer/CMakeLists.txt index 5e274630c8..5967b891f4 100644 --- a/tools/llvm-symbolizer/CMakeLists.txt +++ b/tools/llvm-symbolizer/CMakeLists.txt @@ -9,5 +9,6 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_tool(llvm-symbolizer + LLVMSymbolize.cpp llvm-symbolizer.cpp ) diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp new file mode 100644 index 0000000000..1b0ece5fc5 --- /dev/null +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -0,0 +1,272 @@ +//===-- LLVMSymbolize.cpp -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation for LLVM symbolization library. +// +//===----------------------------------------------------------------------===// + +#include "LLVMSymbolize.h" +#include "llvm/Object/MachO.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Path.h" + +#include <sstream> + +namespace llvm { +namespace symbolize { + +static uint32_t getDILineInfoSpecifierFlags( + const LLVMSymbolizer::Options &Opts) { + uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo | + llvm::DILineInfoSpecifier::AbsoluteFilePath; + if (Opts.PrintFunctions) + Flags |= llvm::DILineInfoSpecifier::FunctionName; + return Flags; +} + +static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName, + DILineInfo &LineInfo) { + std::string FileName = LineInfo.getFileName(); + LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName), + LineInfo.getLine(), LineInfo.getColumn()); +} + +DILineInfo ModuleInfo::symbolizeCode(uint64_t ModuleOffset, + const LLVMSymbolizer::Options& Opts) const { + DILineInfo LineInfo; + if (DebugInfoContext) { + LineInfo = DebugInfoContext->getLineInfoForAddress( + ModuleOffset, getDILineInfoSpecifierFlags(Opts)); + } + // Override function name from symbol table if necessary. + if (Opts.PrintFunctions && Opts.UseSymbolTable) { + std::string FunctionName; + uint64_t Start, Size; + if (getNameFromSymbolTable(SymbolRef::ST_Function, + ModuleOffset, FunctionName, Start, Size)) { + patchFunctionNameInDILineInfo(FunctionName, LineInfo); + } + } + return LineInfo; +} + +DIInliningInfo ModuleInfo::symbolizeInlinedCode(uint64_t ModuleOffset, + const LLVMSymbolizer::Options& Opts) const { + DIInliningInfo InlinedContext; + if (DebugInfoContext) { + InlinedContext = DebugInfoContext->getInliningInfoForAddress( + ModuleOffset, getDILineInfoSpecifierFlags(Opts)); + } + // Make sure there is at least one frame in context. + if (InlinedContext.getNumberOfFrames() == 0) { + InlinedContext.addFrame(DILineInfo()); + } + // Override the function name in lower frame with name from symbol table. + if (Opts.PrintFunctions && Opts.UseSymbolTable) { + DIInliningInfo PatchedInlinedContext; + for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); + i < n; i++) { + DILineInfo LineInfo = InlinedContext.getFrame(i); + if (i == n - 1) { + std::string FunctionName; + uint64_t Start, Size; + if (getNameFromSymbolTable(SymbolRef::ST_Function, + ModuleOffset, FunctionName, Start, Size)) { + patchFunctionNameInDILineInfo(FunctionName, LineInfo); + } + } + PatchedInlinedContext.addFrame(LineInfo); + } + InlinedContext = PatchedInlinedContext; + } + return InlinedContext; +} + +bool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name, + uint64_t &Start, uint64_t &Size) const { + return getNameFromSymbolTable(SymbolRef::ST_Data, + ModuleOffset, Name, Start, Size); +} + +static bool error(error_code ec) { + if (!ec) return false; + errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n"; + return true; +} + +bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address, + std::string &Name, uint64_t &Addr, + uint64_t &Size) const { + assert(Module); + error_code ec; + for (symbol_iterator si = Module->begin_symbols(), + se = Module->end_symbols(); + si != se; si.increment(ec)) { + if (error(ec)) return false; + uint64_t SymbolAddress; + uint64_t SymbolSize; + SymbolRef::Type SymbolType; + if (error(si->getAddress(SymbolAddress)) || + SymbolAddress == UnknownAddressOrSize) continue; + if (error(si->getSize(SymbolSize)) || + SymbolSize == UnknownAddressOrSize) continue; + if (error(si->getType(SymbolType))) continue; + // FIXME: If a function has alias, there are two entries in symbol table + // with same address size. Make sure we choose the correct one. + if (SymbolAddress <= Address && Address < SymbolAddress + SymbolSize && + SymbolType == Type) { + StringRef SymbolName; + if (error(si->getName(SymbolName))) continue; + Name = SymbolName.str(); + Addr = SymbolAddress; + Size = SymbolSize; + return true; + } + } + return false; +} + +const std::string LLVMSymbolizer::kBadString = "??"; + +std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, + uint64_t ModuleOffset) { + ModuleInfo *Info = getOrCreateModuleInfo(ModuleName); + if (Info == 0) + return printDILineInfo(DILineInfo()); + if (Opts.PrintInlining) { + DIInliningInfo InlinedContext = Info->symbolizeInlinedCode( + ModuleOffset, Opts); + uint32_t FramesNum = InlinedContext.getNumberOfFrames(); + assert(FramesNum > 0); + std::string Result; + for (uint32_t i = 0; i < FramesNum; i++) { + DILineInfo LineInfo = InlinedContext.getFrame(i); + Result += printDILineInfo(LineInfo); + } + return Result; + } + DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts); + return printDILineInfo(LineInfo); +} + +std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName, + uint64_t ModuleOffset) { + std::string Name = kBadString; + uint64_t Start = 0; + uint64_t Size = 0; + if (Opts.UseSymbolTable) { + if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) { + if (Info->symbolizeData(ModuleOffset, Name, Start, Size)) + DemangleName(Name); + } + } + std::stringstream ss; + ss << Name << "\n" << Start << " " << Size << "\n"; + return ss.str(); +} + +// Returns true if the object endianness is known. +static bool getObjectEndianness(const ObjectFile *Obj, + bool &IsLittleEndian) { + // FIXME: Implement this when libLLVMObject allows to do it easily. + IsLittleEndian = true; + return true; +} + +static ObjectFile *getObjectFile(const std::string &Path) { + OwningPtr<MemoryBuffer> Buff; + MemoryBuffer::getFile(Path, Buff); + return ObjectFile::createObjectFile(Buff.take()); +} + +static std::string getDarwinDWARFResourceForModule(const std::string &Path) { + StringRef Basename = sys::path::filename(Path); + const std::string &DSymDirectory = Path + ".dSYM"; + SmallString<16> ResourceName = StringRef(DSymDirectory); + sys::path::append(ResourceName, "Contents", "Resources", "DWARF"); + sys::path::append(ResourceName, Basename); + return ResourceName.str(); +} + +ModuleInfo *LLVMSymbolizer::getOrCreateModuleInfo( + const std::string &ModuleName) { + ModuleMapTy::iterator I = Modules.find(ModuleName); + if (I != Modules.end()) + return I->second; + + ObjectFile *Obj = getObjectFile(ModuleName); + ObjectFile *DbgObj = Obj; + if (Obj == 0) { + // Module name doesn't point to a valid object file. + Modules.insert(make_pair(ModuleName, (ModuleInfo*)0)); + return 0; + } + + DIContext *Context = 0; + bool IsLittleEndian; + if (getObjectEndianness(Obj, IsLittleEndian)) { + // On Darwin we may find DWARF in separate object file in + // resource directory. + if (isa<MachOObjectFile>(Obj)) { + const std::string &ResourceName = getDarwinDWARFResourceForModule( + ModuleName); + ObjectFile *ResourceObj = getObjectFile(ResourceName); + if (ResourceObj != 0) + DbgObj = ResourceObj; + } + Context = DIContext::getDWARFContext(DbgObj); + assert(Context); + } + + ModuleInfo *Info = new ModuleInfo(Obj, Context); + Modules.insert(make_pair(ModuleName, Info)); + return Info; +} + +std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const { + // By default, DILineInfo contains "<invalid>" for function/filename it + // cannot fetch. We replace it to "??" to make our output closer to addr2line. + static const std::string kDILineInfoBadString = "<invalid>"; + std::stringstream Result; + if (Opts.PrintFunctions) { + std::string FunctionName = LineInfo.getFunctionName(); + if (FunctionName == kDILineInfoBadString) + FunctionName = kBadString; + DemangleName(FunctionName); + Result << FunctionName << "\n"; + } + std::string Filename = LineInfo.getFileName(); + if (Filename == kDILineInfoBadString) + Filename = kBadString; + Result << Filename << ":" << LineInfo.getLine() + << ":" << LineInfo.getColumn() << "\n"; + return Result.str(); +} + +#if !defined(_MSC_VER) +// Assume that __cxa_demangle is provided by libcxxabi (except for Windows). +extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer, + size_t *length, int *status); +#endif + +void LLVMSymbolizer::DemangleName(std::string &Name) const { +#if !defined(_MSC_VER) + if (!Opts.Demangle) + return; + int status = 0; + char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status); + if (status != 0) + return; + Name = DemangledName; + free(DemangledName); +#endif +} + +} // namespace symbolize +} // namespace llvm diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h new file mode 100644 index 0000000000..aae6f00206 --- /dev/null +++ b/tools/llvm-symbolizer/LLVMSymbolize.h @@ -0,0 +1,88 @@ +//===-- LLVMSymbolize.h ----------------------------------------- C++ -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Header for LLVM symbolization library. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_SYMBOLIZE_H +#define LLVM_SYMBOLIZE_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/MemoryBuffer.h" +#include <map> +#include <string> + +namespace llvm { + +using namespace object; + +namespace symbolize { + +class ModuleInfo; + +class LLVMSymbolizer { +public: + struct Options { + bool UseSymbolTable : 1; + bool PrintFunctions : 1; + bool PrintInlining : 1; + bool Demangle : 1; + Options(bool UseSymbolTable = true, bool PrintFunctions = true, + bool PrintInlining = true, bool Demangle = true) + : UseSymbolTable(UseSymbolTable), + PrintFunctions(PrintFunctions), + PrintInlining(PrintInlining), + Demangle(Demangle) { } + }; + + LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) { } + + // Returns the result of symbolization for module name/offset as + // a string (possibly containing newlines). + std::string symbolizeCode(const std::string &ModuleName, + uint64_t ModuleOffset); + std::string symbolizeData(const std::string &ModuleName, + uint64_t ModuleOffset); +private: + ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName); + std::string printDILineInfo(DILineInfo LineInfo) const; + void DemangleName(std::string &Name) const; + + typedef std::map<std::string, ModuleInfo*> ModuleMapTy; + ModuleMapTy Modules; + Options Opts; + static const std::string kBadString; +}; + +class ModuleInfo { + OwningPtr<ObjectFile> Module; + OwningPtr<DIContext> DebugInfoContext; + public: + ModuleInfo(ObjectFile *Obj, DIContext *DICtx) + : Module(Obj), DebugInfoContext(DICtx) {} + + DILineInfo symbolizeCode( + uint64_t ModuleOffset, const LLVMSymbolizer::Options& Opts) const; + DIInliningInfo symbolizeInlinedCode( + uint64_t ModuleOffset, const LLVMSymbolizer::Options& Opts) const; + bool symbolizeData(uint64_t ModuleOffset, std::string &Name, + uint64_t &Start, uint64_t &Size) const; + + private: + bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address, + std::string &Name, uint64_t &Addr, + uint64_t &Size) const; +}; + +} // namespace symbolize +} // namespace llvm + +#endif // LLVM_SYMBOLIZE_H diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp index c404eea892..819f1f8475 100644 --- a/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -15,315 +15,42 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/OwningPtr.h" +#include "LLVMSymbolize.h" #include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/DIContext.h" -#include "llvm/Object/MachO.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" #include <cstdio> #include <cstring> -#include <map> #include <string> using namespace llvm; -using namespace object; +using namespace symbolize; static cl::opt<bool> -UseSymbolTable("use-symbol-table", cl::init(true), +ClUseSymbolTable("use-symbol-table", cl::init(true), cl::desc("Prefer names in symbol table to names " "in debug info")); static cl::opt<bool> -PrintFunctions("functions", cl::init(true), +ClPrintFunctions("functions", cl::init(true), cl::desc("Print function names as well as line " "information for a given address")); static cl::opt<bool> -PrintInlining("inlining", cl::init(true), +ClPrintInlining("inlining", cl::init(true), cl::desc("Print all inlined frames for a given address")); static cl::opt<bool> -Demangle("demangle", cl::init(true), +ClDemangle("demangle", cl::init(true), cl::desc("Demangle function names")); -static const std::string kSymbolizerBadString = "??"; - -static StringRef ToolInvocationPath; - -static bool error(error_code ec) { - if (!ec) return false; - errs() << ToolInvocationPath << ": error reading file: " - << ec.message() << ".\n"; - return true; -} - -static uint32_t getDILineInfoSpecifierFlags() { - uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo | - llvm::DILineInfoSpecifier::AbsoluteFilePath; - if (PrintFunctions) - Flags |= llvm::DILineInfoSpecifier::FunctionName; - return Flags; -} - -static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName, - DILineInfo &LineInfo) { - std::string FileName = LineInfo.getFileName(); - LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName), - LineInfo.getLine(), LineInfo.getColumn()); -} - -namespace { -class ModuleInfo { - OwningPtr<ObjectFile> Module; - OwningPtr<DIContext> DebugInfoContext; - public: - ModuleInfo(ObjectFile *Obj, DIContext *DICtx) - : Module(Obj), DebugInfoContext(DICtx) {} - - DILineInfo symbolizeCode(uint64_t ModuleOffset) const { - DILineInfo LineInfo; - if (DebugInfoContext) { - LineInfo = DebugInfoContext->getLineInfoForAddress( - ModuleOffset, getDILineInfoSpecifierFlags()); - } - // Override function name from symbol table if necessary. - if (PrintFunctions && UseSymbolTable) { - std::string Function; - uint64_t Start, Size; - if (getNameFromSymbolTable(SymbolRef::ST_Function, - ModuleOffset, Function, Start, Size)) { - patchFunctionNameInDILineInfo(Function, LineInfo); - } - } - return LineInfo; - } - - DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset) const { - DIInliningInfo InlinedContext; - if (DebugInfoContext) { - InlinedContext = DebugInfoContext->getInliningInfoForAddress( - ModuleOffset, getDILineInfoSpecifierFlags()); - } - // Make sure there is at least one frame in context. - if (InlinedContext.getNumberOfFrames() == 0) { - InlinedContext.addFrame(DILineInfo()); - } - // Override the function name in lower frame with name from symbol table. - if (PrintFunctions && UseSymbolTable) { - DIInliningInfo PatchedInlinedContext; - for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); - i != n; i++) { - DILineInfo LineInfo = InlinedContext.getFrame(i); - if (i == n - 1) { - std::string Function; - uint64_t Start, Size; - if (getNameFromSymbolTable(SymbolRef::ST_Function, - ModuleOffset, Function, Start, Size)) { - patchFunctionNameInDILineInfo(Function, LineInfo); - } - } - PatchedInlinedContext.addFrame(LineInfo); - } - InlinedContext = PatchedInlinedContext; - } - return InlinedContext; - } - - bool symbolizeData(uint64_t ModuleOffset, std::string &Name, - uint64_t &Start, uint64_t &Size) const { - return getNameFromSymbolTable(SymbolRef::ST_Data, - ModuleOffset, Name, Start, Size); - } - - private: - bool getNameFromSymbolTable(SymbolRef::Type Type, - uint64_t Address, - std::string &Name, - uint64_t &Addr, - uint64_t &Size) const { - assert(Module); - error_code ec; - for (symbol_iterator si = Module->begin_symbols(), - se = Module->end_symbols(); - si != se; si.increment(ec)) { - if (error(ec)) return false; - uint64_t SymbolAddress; - uint64_t SymbolSize; - SymbolRef::Type SymbolType; - if (error(si->getAddress(SymbolAddress)) || - SymbolAddress == UnknownAddressOrSize) continue; - if (error(si->getSize(SymbolSize)) || - SymbolSize == UnknownAddressOrSize) continue; - if (error(si->getType(SymbolType))) continue; - // FIXME: If a function has alias, there are two entries in symbol table - // with same address size. Make sure we choose the correct one. - if (SymbolAddress <= Address && Address < SymbolAddress + SymbolSize && - SymbolType == Type) { - StringRef SymbolName; - if (error(si->getName(SymbolName))) continue; - Name = SymbolName.str(); - Addr = SymbolAddress; - Size = SymbolSize; - return true; - } - } - return false; - } -}; - -#if !defined(_MSC_VER) -// Assume that __cxa_demangle is provided by libcxxabi (except for Windows). -extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer, - size_t *length, int *status); -#endif - -void DemangleName(std::string &Name) { -#if !defined(_MSC_VER) - if (!Demangle) - return; - int status = 0; - char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status); - if (status != 0) - return; - Name = DemangledName; - free(DemangledName); -#endif -} - -typedef std::map<std::string, ModuleInfo*> ModuleMapTy; -typedef ModuleMapTy::iterator ModuleMapIter; -} // namespace - -static ModuleMapTy Modules; - -// Returns true if the object endianness is known. -static bool getObjectEndianness(const ObjectFile *Obj, - bool &IsLittleEndian) { - // FIXME: Implement this when libLLVMObject allows to do it easily. - IsLittleEndian = true; - return true; -} - -static ObjectFile *getObjectFile(const std::string &Path) { - OwningPtr<MemoryBuffer> Buff; - MemoryBuffer::getFile(Path, Buff); - return ObjectFile::createObjectFile(Buff.take()); -} - -static std::string getDarwinDWARFResourceForModule(const std::string &Path) { - StringRef Basename = sys::path::filename(Path); - const std::string &DSymDirectory = Path + ".dSYM"; - SmallString<16> ResourceName = StringRef(DSymDirectory); - sys::path::append(ResourceName, "Contents", "Resources", "DWARF"); - sys::path::append(ResourceName, Basename); - return ResourceName.str(); -} - -static ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName) { - ModuleMapIter I = Modules.find(ModuleName); - if (I != Modules.end()) - return I->second; - - ObjectFile *Obj = getObjectFile(ModuleName); - ObjectFile *DbgObj = Obj; - if (Obj == 0) { - // Module name doesn't point to a valid object file. - Modules.insert(make_pair(ModuleName, (ModuleInfo*)0)); - return 0; - } - - DIContext *Context = 0; - bool IsLittleEndian; - if (getObjectEndianness(Obj, IsLittleEndian)) { - // On Darwin we may find DWARF in separate object file in - // resource directory. - if (isa<MachOObjectFile>(Obj)) { - const std::string &ResourceName = getDarwinDWARFResourceForModule( - ModuleName); - ObjectFile *ResourceObj = getObjectFile(ResourceName); - if (ResourceObj != 0) - DbgObj = ResourceObj; - } - Context = DIContext::getDWARFContext(DbgObj); - assert(Context); - } - - ModuleInfo *Info = new ModuleInfo(Obj, Context); - Modules.insert(make_pair(ModuleName, Info)); - return Info; -} - -static void printDILineInfo(DILineInfo LineInfo) { - // By default, DILineInfo contains "<invalid>" for function/filename it - // cannot fetch. We replace it to "??" to make our output closer to addr2line. - static const std::string kDILineInfoBadString = "<invalid>"; - if (PrintFunctions) { - std::string FunctionName = LineInfo.getFunctionName(); - if (FunctionName == kDILineInfoBadString) - FunctionName = kSymbolizerBadString; - DemangleName(FunctionName); - outs() << FunctionName << "\n"; - } - std::string Filename = LineInfo.getFileName(); - if (Filename == kDILineInfoBadString) - Filename = kSymbolizerBadString; - outs() << Filename << - ":" << LineInfo.getLine() << - ":" << LineInfo.getColumn() << - "\n"; -} - -static void symbolizeCode(std::string ModuleName, std::string ModuleOffsetStr) { - ModuleInfo *Info = getOrCreateModuleInfo(ModuleName); - uint64_t Offset = 0; - if (Info == 0 || - StringRef(ModuleOffsetStr).getAsInteger(0, Offset)) { - printDILineInfo(DILineInfo()); - } else if (PrintInlining) { - DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(Offset); - uint32_t FramesNum = InlinedContext.getNumberOfFrames(); - assert(FramesNum > 0); - for (uint32_t i = 0; i < FramesNum; i++) { - DILineInfo LineInfo = InlinedContext.getFrame(i); - printDILineInfo(LineInfo); - } - } else { - DILineInfo LineInfo = Info->symbolizeCode(Offset); - printDILineInfo(LineInfo); - } - - outs() << "\n"; // Print extra empty line to mark the end of output. - outs().flush(); -} - -static void symbolizeData(std::string ModuleName, std::string ModuleOffsetStr) { - std::string Name = kSymbolizerBadString; - uint64_t Start = 0; - uint64_t Size = 0; - uint64_t Offset = 0; - if (UseSymbolTable) { - ModuleInfo *Info = getOrCreateModuleInfo(ModuleName); - if (Info && !StringRef(ModuleOffsetStr).getAsInteger(0, Offset)) { - if (Info->symbolizeData(Offset, Name, Start, Size)) - DemangleName(Name); - } - } - outs() << Name << "\n" << Start << " " << Size << "\n\n"; - outs().flush(); -} - static bool parseCommand(bool &IsData, std::string &ModuleName, - std::string &ModuleOffsetStr) { + uint64_t &ModuleOffset) { const char *kDataCmd = "DATA "; const char *kCodeCmd = "CODE "; const int kMaxInputStringLength = 1024; @@ -333,7 +60,7 @@ static bool parseCommand(bool &IsData, return false; IsData = false; ModuleName = ""; - ModuleOffsetStr = ""; + std::string ModuleOffsetStr = ""; char *pos = InputString; if (strncmp(pos, kDataCmd, strlen(kDataCmd)) == 0) { IsData = true; @@ -351,6 +78,8 @@ static bool parseCommand(bool &IsData, if (char *OffsetStr = strtok((char*)0, kDelimiters)) ModuleOffsetStr = OffsetStr; } + if (StringRef(ModuleOffsetStr).getAsInteger(0, ModuleOffset)) + return false; return true; } @@ -361,16 +90,19 @@ int main(int argc, char **argv) { llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm symbolizer for compiler-rt\n"); - ToolInvocationPath = argv[0]; + LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions, + ClPrintInlining, ClDemangle); + LLVMSymbolizer Symbolizer(Opts); bool IsData = false; std::string ModuleName; - std::string ModuleOffsetStr; - while (parseCommand(IsData, ModuleName, ModuleOffsetStr)) { - if (IsData) - symbolizeData(ModuleName, ModuleOffsetStr); - else - symbolizeCode(ModuleName, ModuleOffsetStr); + uint64_t ModuleOffset; + while (parseCommand(IsData, ModuleName, ModuleOffset)) { + std::string Result = + IsData ? Symbolizer.symbolizeData(ModuleName, ModuleOffset) + : Symbolizer.symbolizeCode(ModuleName, ModuleOffset); + outs() << Result << "\n"; + outs().flush(); } return 0; } |