mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-12 06:06:32 +00:00
[llvm-symbolizer] -print-source-context-lines option to print source code around the line.
Differential Revision: http://reviews.llvm.org/D15909 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257236 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7b0ac13608
commit
d9750d38e1
@ -28,13 +28,16 @@ class DIPrinter {
|
||||
raw_ostream &OS;
|
||||
bool PrintFunctionNames;
|
||||
bool PrintPretty;
|
||||
void printName(const DILineInfo &Info, bool Inlined);
|
||||
int PrintSourceContext;
|
||||
|
||||
void print(const DILineInfo &Info, bool Inlined);
|
||||
void printContext(std::string FileName, int64_t Line);
|
||||
|
||||
public:
|
||||
DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true,
|
||||
bool PrintPretty = false)
|
||||
bool PrintPretty = false, int PrintSourceContext = 0)
|
||||
: OS(OS), PrintFunctionNames(PrintFunctionNames),
|
||||
PrintPretty(PrintPretty) {}
|
||||
PrintPretty(PrintPretty), PrintSourceContext(PrintSourceContext) {}
|
||||
|
||||
DIPrinter &operator<<(const DILineInfo &Info);
|
||||
DIPrinter &operator<<(const DIInliningInfo &Info);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
|
||||
|
||||
#include "llvm/DebugInfo/DIContext.h"
|
||||
#include "llvm/Support/LineIterator.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace symbolize {
|
||||
@ -24,7 +25,36 @@ namespace symbolize {
|
||||
static const char kDILineInfoBadString[] = "<invalid>";
|
||||
static const char kBadString[] = "??";
|
||||
|
||||
void DIPrinter::printName(const DILineInfo &Info, bool Inlined) {
|
||||
// Prints source code around in the FileName the Line.
|
||||
void DIPrinter::printContext(std::string FileName, int64_t Line) {
|
||||
if (PrintSourceContext <= 0)
|
||||
return;
|
||||
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
|
||||
MemoryBuffer::getFile(FileName);
|
||||
if (!BufOrErr)
|
||||
return;
|
||||
|
||||
std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
|
||||
int64_t FirstLine = std::max(1l, Line - PrintSourceContext / 2);
|
||||
int64_t LastLine = FirstLine + PrintSourceContext;
|
||||
size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
|
||||
|
||||
for (line_iterator I = line_iterator(*Buf, false);
|
||||
!I.is_at_eof() && I.line_number() <= LastLine; ++I) {
|
||||
int64_t L = I.line_number();
|
||||
if (L >= FirstLine && L <= LastLine) {
|
||||
OS << format_decimal(L, MaxLineNumberWidth);
|
||||
if (L == Line)
|
||||
OS << " >: ";
|
||||
else
|
||||
OS << " : ";
|
||||
OS << *I << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
|
||||
if (PrintFunctionNames) {
|
||||
std::string FunctionName = Info.FunctionName;
|
||||
if (FunctionName == kDILineInfoBadString)
|
||||
@ -38,21 +68,22 @@ void DIPrinter::printName(const DILineInfo &Info, bool Inlined) {
|
||||
if (Filename == kDILineInfoBadString)
|
||||
Filename = kBadString;
|
||||
OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n";
|
||||
printContext(Filename, Info.Line);
|
||||
}
|
||||
|
||||
DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
|
||||
printName(Info, false);
|
||||
print(Info, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
|
||||
uint32_t FramesNum = Info.getNumberOfFrames();
|
||||
if (FramesNum == 0) {
|
||||
printName(DILineInfo(), false);
|
||||
print(DILineInfo(), false);
|
||||
return *this;
|
||||
}
|
||||
for (uint32_t i = 0; i < FramesNum; i++)
|
||||
printName(Info.getFrame(i), i > 0);
|
||||
print(Info.getFrame(i), i > 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -194,6 +194,7 @@ config.substitutions.append( ('%llvmshlibdir', config.llvm_shlib_dir) )
|
||||
config.substitutions.append( ('%shlibext', config.llvm_shlib_ext) )
|
||||
config.substitutions.append( ('%exeext', config.llvm_exe_ext) )
|
||||
config.substitutions.append( ('%python', config.python_executable) )
|
||||
config.substitutions.append( ('%host_cc', config.host_cc) )
|
||||
|
||||
# OCaml substitutions.
|
||||
# Support tests for both native and bytecode builds.
|
||||
@ -276,6 +277,7 @@ for pattern in [r"\bbugpoint\b(?!-)",
|
||||
r"\bllvm-split\b",
|
||||
r"\bllvm-tblgen\b",
|
||||
r"\bllvm-c-test\b",
|
||||
NOJUNK + r"\bllvm-symbolizer\b",
|
||||
NOJUNK + r"\bopt\b",
|
||||
r"\bFileCheck\b",
|
||||
r"\bobj2yaml\b",
|
||||
|
22
test/tools/llvm-symbolizer/print_context.c
Normal file
22
test/tools/llvm-symbolizer/print_context.c
Normal file
@ -0,0 +1,22 @@
|
||||
// REQUIRES: x86_64-linux
|
||||
// RUN: %host_cc -O0 -g %s -o %t 2>&1
|
||||
// RUN: %t 2>&1 | llvm-symbolizer -print-source-context-lines=5 -obj=%t | FileCheck %s --check-prefix=CHECK
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int inc(int a) {
|
||||
return a + 1;
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("%p\n", inc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK: inc
|
||||
// CHECK: print_context.c:7
|
||||
// CHECK: 5 : #include
|
||||
// CHECK: 6 :
|
||||
// CHECK: 7 >: int inc
|
||||
// CHECK: 8 : return
|
||||
// CHECK: 9 : }
|
@ -82,6 +82,10 @@ static cl::opt<bool>
|
||||
ClPrettyPrint("pretty-print", cl::init(false),
|
||||
cl::desc("Make the output more human friendly"));
|
||||
|
||||
static cl::opt<int> ClPrintSourceContextLines(
|
||||
"print-source-context-lines", cl::init(0),
|
||||
cl::desc("Print N number of source file context"));
|
||||
|
||||
static bool error(std::error_code ec) {
|
||||
if (!ec)
|
||||
return false;
|
||||
@ -155,7 +159,7 @@ int main(int argc, char **argv) {
|
||||
LLVMSymbolizer Symbolizer(Opts);
|
||||
|
||||
DIPrinter Printer(outs(), ClPrintFunctions != FunctionNameKind::None,
|
||||
ClPrettyPrint);
|
||||
ClPrettyPrint, ClPrintSourceContextLines);
|
||||
|
||||
const int kMaxInputStringLength = 1024;
|
||||
char InputString[kMaxInputStringLength];
|
||||
|
Loading…
Reference in New Issue
Block a user