Index: llvm/trunk/docs/CommandGuide/llvm-symbolizer.rst =================================================================== --- llvm/trunk/docs/CommandGuide/llvm-symbolizer.rst +++ llvm/trunk/docs/CommandGuide/llvm-symbolizer.rst @@ -56,6 +56,14 @@ foo(int) /tmp/a.cc:12 + $cat addr.txt + 0x40054d + $llvm-symbolizer -inlining -print-address -pretty-print -obj=addr.exe < addr.txt + 0x40054d: inc at /tmp/x.c:3:3 + (inlined by) main at /tmp/x.c:9:0 + $llvm-symbolizer -inlining -pretty-print -obj=addr.exe < addr.txt + inc at /tmp/x.c:3:3 + (inlined by) main at /tmp/x.c:9:0 OPTIONS ------- @@ -101,6 +109,10 @@ .. option:: -print-address Print address before the source code location. Defaults to false. +.. option:: -pretty-print + Print human readable output. If ``-inlining`` is specified, enclosing scope is + prefixed by (inlined by). Refer to listed examples. + EXIT STATUS ----------- Index: llvm/trunk/include/llvm/DebugInfo/Symbolize/DIPrinter.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/Symbolize/DIPrinter.h +++ llvm/trunk/include/llvm/DebugInfo/Symbolize/DIPrinter.h @@ -27,10 +27,14 @@ class DIPrinter { raw_ostream &OS; bool PrintFunctionNames; + bool PrintPretty; + void printName(const DILineInfo &Info, bool Inlined); public: - DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true) - : OS(OS), PrintFunctionNames(PrintFunctionNames) {} + DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true, + bool PrintPretty = false) + : OS(OS), PrintFunctionNames(PrintFunctionNames), + PrintPretty(PrintPretty) {} DIPrinter &operator<<(const DILineInfo &Info); DIPrinter &operator<<(const DIInliningInfo &Info); Index: llvm/trunk/lib/DebugInfo/Symbolize/DIPrinter.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/Symbolize/DIPrinter.cpp +++ llvm/trunk/lib/DebugInfo/Symbolize/DIPrinter.cpp @@ -24,27 +24,35 @@ static const char kDILineInfoBadString[] = ""; static const char kBadString[] = "??"; -DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) { +void DIPrinter::printName(const DILineInfo &Info, bool Inlined) { if (PrintFunctionNames) { std::string FunctionName = Info.FunctionName; if (FunctionName == kDILineInfoBadString) FunctionName = kBadString; - OS << FunctionName << "\n"; + + StringRef Delimiter = (PrintPretty == true) ? " at " : "\n"; + StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : ""; + OS << Prefix << FunctionName << Delimiter; } std::string Filename = Info.FileName; if (Filename == kDILineInfoBadString) Filename = kBadString; OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n"; +} + +DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) { + printName(Info, false); 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); + if (FramesNum == 0) { + printName(DILineInfo(), false); + return *this; } + for (uint32_t i = 0; i < FramesNum; i++) + printName(Info.getFrame(i), i > 0); return *this; } Index: llvm/trunk/test/tools/llvm-symbolizer/sym.test =================================================================== --- llvm/trunk/test/tools/llvm-symbolizer/sym.test +++ llvm/trunk/test/tools/llvm-symbolizer/sym.test @@ -1,19 +1,30 @@ #Source: ##include -#static inline int inc (int *a) { +#static inline int inctwo (int *a) { # printf ("%d\n",(*a)++); # return (*a)++; #} +#static inline int inc (int *a) { +# printf ("%d\n",inctwo(a)); +# return (*a)++; +#} +# # #int main () { # int x = 1; # return inc(&x); #} +# #Build as : clang -g -O2 addr.c -RUN: llvm-symbolizer -inlining -print-address -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck %s +RUN: llvm-symbolizer -print-address -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck %s +RUN: llvm-symbolizer -inlining -print-address -pretty-print -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck --check-prefix="PRETTY" %s #CHECK: 0x40054d #CHECK: main -#CHECK: {{[/\]+}}tmp{{[/\]+}}x.c:9:0 +#CHECK: {{[/\]+}}tmp{{[/\]+}}x.c:14:0 +# +#PRETTY: {{[0x]+}}40054d: inctwo at {{[/\]+}}tmp{{[/\]+}}x.c:3:3 +#PRETTY: (inlined by) inc at {{[/\]+}}tmp{{[/\]+}}x.c:7:0 +#PRETTY (inlined by) main at {{[/\]+}}tmp{{[/\]+}}x.c:14:0 Index: llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp =================================================================== --- llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ llvm/trunk/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -78,6 +78,10 @@ ClPrintAddress("print-address", cl::init(false), cl::desc("Show address before line information")); +static cl::opt + ClPrettyPrint("pretty-print", cl::init(false), + cl::desc("Make the output more human friendly")); + static bool error(std::error_code ec) { if (!ec) return false; @@ -143,6 +147,7 @@ cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n"); LLVMSymbolizer::Options Opts(ClPrintFunctions, ClUseSymbolTable, ClDemangle, ClUseRelativeAddress, ClDefaultArch); + for (const auto &hint : ClDsymHint) { if (sys::path::extension(hint) == ".dSYM") { Opts.DsymHints.push_back(hint); @@ -156,13 +161,15 @@ bool IsData = false; std::string ModuleName; uint64_t ModuleOffset; - DIPrinter Printer(outs(), ClPrintFunctions != FunctionNameKind::None); + DIPrinter Printer(outs(), ClPrintFunctions != FunctionNameKind::None, + ClPrettyPrint); while (parseCommand(IsData, ModuleName, ModuleOffset)) { if (ClPrintAddress) { outs() << "0x"; outs().write_hex(ModuleOffset); - outs() << "\n"; + StringRef Delimiter = (ClPrettyPrint == true) ? ": " : "\n"; + outs() << Delimiter; } if (IsData) { auto ResOrErr = Symbolizer.symbolizeData(ModuleName, ModuleOffset);