forked from OSchip/llvm-project
[LLVMSymbolize] Factor out the logic for printing structs from DIContext. NFC.
Introduce DIPrinter which takes care of rendering DILineInfo and friends. This allows LLVMSymbolizer class to return a structured data instead of plain std::strings. llvm-svn: 251989
This commit is contained in:
parent
61362ce876
commit
d6aa820262
|
@ -0,0 +1,43 @@
|
|||
//===- llvm/DebugInfo/Symbolize/DIPrinter.h ---------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the DIPrinter class, which is responsible for printing
|
||||
// structures defined in DebugInfo/DIContext.h
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H
|
||||
#define LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
struct DILineInfo;
|
||||
class DIInliningInfo;
|
||||
struct DIGlobal;
|
||||
|
||||
namespace symbolize {
|
||||
|
||||
class DIPrinter {
|
||||
raw_ostream &OS;
|
||||
bool PrintFunctionNames;
|
||||
|
||||
public:
|
||||
DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true)
|
||||
: OS(OS), PrintFunctionNames(PrintFunctionNames) {}
|
||||
|
||||
DIPrinter &operator<<(const DILineInfo &Info);
|
||||
DIPrinter &operator<<(const DIInliningInfo &Info);
|
||||
DIPrinter &operator<<(const DIGlobal &Global);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -51,14 +51,11 @@ public:
|
|||
flush();
|
||||
}
|
||||
|
||||
// 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 symbolizeInlinedCode(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset);
|
||||
std::string
|
||||
symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset);
|
||||
DILineInfo symbolizeCode(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset);
|
||||
DIInliningInfo symbolizeInlinedCode(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset);
|
||||
DIGlobal symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset);
|
||||
void flush();
|
||||
static std::string DemangleName(const std::string &Name,
|
||||
const SymbolizableModule *ModInfo);
|
||||
|
@ -78,10 +75,6 @@ private:
|
|||
/// universal binary (or the binary itself if it is an object file).
|
||||
ObjectFile *getObjectFileFromBinary(Binary *Bin, const std::string &ArchName);
|
||||
|
||||
std::string printDILineInfo(DILineInfo LineInfo) const;
|
||||
std::string printDIInliningInfo(DIInliningInfo InlinedContext) const;
|
||||
std::string printDIGlobal(DIGlobal Global) const;
|
||||
|
||||
// Owns all the parsed binaries and object files.
|
||||
SmallVector<std::unique_ptr<Binary>, 4> ParsedBinariesAndObjects;
|
||||
SmallVector<std::unique_ptr<MemoryBuffer>, 4> MemoryBuffers;
|
||||
|
@ -100,7 +93,6 @@ private:
|
|||
ObjectPairForPathArch;
|
||||
|
||||
Options Opts;
|
||||
static const char kBadString[];
|
||||
};
|
||||
|
||||
} // namespace symbolize
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
add_llvm_library(LLVMSymbolize
|
||||
DIPrinter.cpp
|
||||
SymbolizableObjectFile.cpp
|
||||
Symbolize.cpp
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
//===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the DIPrinter class, which is responsible for printing
|
||||
// structures defined in DebugInfo/DIContext.h
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
|
||||
|
||||
#include "llvm/DebugInfo/DIContext.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace symbolize {
|
||||
|
||||
// By default, DILineInfo contains "<invalid>" for function/filename it
|
||||
// cannot fetch. We replace it to "??" to make our output closer to addr2line.
|
||||
static const char kDILineInfoBadString[] = "<invalid>";
|
||||
static const char kBadString[] = "??";
|
||||
|
||||
DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
|
||||
if (PrintFunctionNames) {
|
||||
std::string FunctionName = Info.FunctionName;
|
||||
if (FunctionName == kDILineInfoBadString)
|
||||
FunctionName = kBadString;
|
||||
OS << FunctionName << "\n";
|
||||
}
|
||||
std::string Filename = Info.FileName;
|
||||
if (Filename == kDILineInfoBadString)
|
||||
Filename = kBadString;
|
||||
OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n";
|
||||
return *this;
|
||||
}
|
||||
|
||||
DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
|
||||
uint32_t FramesNum = Info.getNumberOfFrames();
|
||||
if (FramesNum == 0)
|
||||
return (*this << DILineInfo());
|
||||
for (uint32_t i = 0; i < FramesNum; i++) {
|
||||
*this << Info.getFrame(i);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
|
||||
std::string Name = Global.Name;
|
||||
if (Name == kDILineInfoBadString)
|
||||
Name = kBadString;
|
||||
OS << Name << "\n";
|
||||
OS << Global.Start << " " << Global.Size << "\n";
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -30,7 +30,6 @@
|
|||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
@ -55,18 +54,11 @@ static bool error(std::error_code ec) {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
// By default, DILineInfo contains "<invalid>" for function/filename it
|
||||
// cannot fetch. We replace it to "??" to make our output closer to addr2line.
|
||||
static const char kDILineInfoBadString[] = "<invalid>";
|
||||
|
||||
const char LLVMSymbolizer::kBadString[] = "??";
|
||||
|
||||
std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset) {
|
||||
DILineInfo LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset) {
|
||||
SymbolizableModule *Info = getOrCreateModuleInfo(ModuleName);
|
||||
if (!Info)
|
||||
return printDILineInfo(DILineInfo());
|
||||
return DILineInfo();
|
||||
|
||||
// If the user is giving us relative addresses, add the preferred base of the
|
||||
// object to the offset before we do the query. It's what DIContext expects.
|
||||
|
@ -77,14 +69,15 @@ std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
|
|||
Opts.UseSymbolTable);
|
||||
if (Opts.Demangle)
|
||||
LineInfo.FunctionName = DemangleName(LineInfo.FunctionName, Info);
|
||||
return printDILineInfo(LineInfo);
|
||||
return LineInfo;
|
||||
}
|
||||
|
||||
std::string LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset) {
|
||||
DIInliningInfo
|
||||
LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset) {
|
||||
SymbolizableModule *Info = getOrCreateModuleInfo(ModuleName);
|
||||
if (!Info)
|
||||
return printDIInliningInfo(DIInliningInfo());
|
||||
return DIInliningInfo();
|
||||
|
||||
// If the user is giving us relative addresses, add the preferred base of the
|
||||
// object to the offset before we do the query. It's what DIContext expects.
|
||||
|
@ -99,16 +92,16 @@ std::string LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
|
|||
Frame->FunctionName = DemangleName(Frame->FunctionName, Info);
|
||||
}
|
||||
}
|
||||
return printDIInliningInfo(InlinedContext);
|
||||
return InlinedContext;
|
||||
}
|
||||
|
||||
std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset) {
|
||||
DIGlobal LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset) {
|
||||
if (!Opts.UseSymbolTable)
|
||||
return printDIGlobal(DIGlobal());
|
||||
return DIGlobal();
|
||||
SymbolizableModule *Info = getOrCreateModuleInfo(ModuleName);
|
||||
if (!Info)
|
||||
return printDIGlobal(DIGlobal());
|
||||
return DIGlobal();
|
||||
|
||||
// If the user is giving us relative addresses, add the preferred base of
|
||||
// the object to the offset before we do the query. It's what DIContext
|
||||
|
@ -119,7 +112,7 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
|
|||
DIGlobal Global = Info->symbolizeData(ModuleOffset);
|
||||
if (Opts.Demangle)
|
||||
Global.Name = DemangleName(Global.Name, Info);
|
||||
return printDIGlobal(Global);
|
||||
return Global;
|
||||
}
|
||||
|
||||
void LLVMSymbolizer::flush() {
|
||||
|
@ -371,46 +364,6 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
|
|||
return Res;
|
||||
}
|
||||
|
||||
std::string
|
||||
LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
|
||||
std::stringstream Result;
|
||||
if (Opts.PrintFunctions != FunctionNameKind::None) {
|
||||
std::string FunctionName = LineInfo.FunctionName;
|
||||
if (FunctionName == kDILineInfoBadString)
|
||||
FunctionName = kBadString;
|
||||
Result << FunctionName << "\n";
|
||||
}
|
||||
std::string Filename = LineInfo.FileName;
|
||||
if (Filename == kDILineInfoBadString)
|
||||
Filename = kBadString;
|
||||
Result << Filename << ":" << LineInfo.Line << ":" << LineInfo.Column << "\n";
|
||||
return Result.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
LLVMSymbolizer::printDIInliningInfo(DIInliningInfo InlinedContext) const {
|
||||
uint32_t FramesNum = InlinedContext.getNumberOfFrames();
|
||||
if (FramesNum == 0)
|
||||
return printDILineInfo(DILineInfo());
|
||||
std::string Result;
|
||||
for (uint32_t i = 0; i < FramesNum; i++) {
|
||||
DILineInfo LineInfo = InlinedContext.getFrame(i);
|
||||
Result += printDILineInfo(LineInfo);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::string
|
||||
LLVMSymbolizer::printDIGlobal(DIGlobal Global) const {
|
||||
std::stringstream Result;
|
||||
std::string Name = Global.Name;
|
||||
if (Name == kDILineInfoBadString)
|
||||
Name = kBadString;
|
||||
Result << Name << "\n";
|
||||
Result << Global.Start << " " << Global.Size << "\n";
|
||||
return Result.str();
|
||||
}
|
||||
|
||||
// Undo these various manglings for Win32 extern "C" functions:
|
||||
// cdecl - _foo
|
||||
// stdcall - _foo@12
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
|
||||
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
|
||||
#include "llvm/Support/COM.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
@ -148,18 +149,22 @@ int main(int argc, char **argv) {
|
|||
bool IsData = false;
|
||||
std::string ModuleName;
|
||||
uint64_t ModuleOffset;
|
||||
DIPrinter Printer(outs(), ClPrintFunctions != FunctionNameKind::None);
|
||||
|
||||
while (parseCommand(IsData, ModuleName, ModuleOffset)) {
|
||||
std::string Result =
|
||||
IsData ? Symbolizer.symbolizeData(ModuleName, ModuleOffset)
|
||||
: ClPrintInlining
|
||||
? Symbolizer.symbolizeInlinedCode(ModuleName, ModuleOffset)
|
||||
: Symbolizer.symbolizeCode(ModuleName, ModuleOffset);
|
||||
if (ClPrintAddress) {
|
||||
outs() << "0x";
|
||||
outs().write_hex(ModuleOffset);
|
||||
outs() << "\n";
|
||||
}
|
||||
outs() << Result << "\n";
|
||||
if (IsData) {
|
||||
Printer << Symbolizer.symbolizeData(ModuleName, ModuleOffset);
|
||||
} else if (ClPrintInlining) {
|
||||
Printer << Symbolizer.symbolizeInlinedCode(ModuleName, ModuleOffset);
|
||||
} else {
|
||||
Printer << Symbolizer.symbolizeCode(ModuleName, ModuleOffset);
|
||||
}
|
||||
outs() << "\n";
|
||||
outs().flush();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue