mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Add support for DWARF embedded source to llvm-symbolizer.
This patch adds DWARF embedded source printout to llvm-symbolizer. Reviewed By: jhenderson, dblaikie Differential Revision: https://reviews.llvm.org/D102355
This commit is contained in:
parent
7cef6d55d4
commit
5487f701b4
@ -82,6 +82,29 @@ public:
|
||||
FirstLine(std::max(static_cast<int64_t>(1), Line - Lines / 2)),
|
||||
LastLine(FirstLine + Lines - 1),
|
||||
PrunedSource(pruneSource(load(FileName, EmbeddedSource))) {}
|
||||
|
||||
void format(raw_ostream &OS) {
|
||||
if (!PrunedSource)
|
||||
return;
|
||||
size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
|
||||
int64_t L = FirstLine;
|
||||
for (size_t Pos = 0; Pos < PrunedSource->size(); ++L) {
|
||||
size_t PosEnd = PrunedSource->find('\n', Pos);
|
||||
StringRef String = PrunedSource->substr(
|
||||
Pos, (PosEnd == StringRef::npos) ? StringRef::npos : (PosEnd - Pos));
|
||||
if (String.endswith("\r"))
|
||||
String = String.drop_back(1);
|
||||
OS << format_decimal(L, MaxLineNumberWidth);
|
||||
if (L == Line)
|
||||
OS << " >: ";
|
||||
else
|
||||
OS << " : ";
|
||||
OS << String << '\n';
|
||||
if (PosEnd == StringRef::npos)
|
||||
break;
|
||||
Pos = PosEnd + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void PlainPrinterBase::printHeader(uint64_t Address) {
|
||||
@ -95,27 +118,7 @@ void PlainPrinterBase::printHeader(uint64_t Address) {
|
||||
|
||||
// Prints source code around in the FileName the Line.
|
||||
void PlainPrinterBase::printContext(SourceCode SourceCode) {
|
||||
if (!SourceCode.PrunedSource)
|
||||
return;
|
||||
|
||||
StringRef Source = *SourceCode.PrunedSource;
|
||||
std::string SourceCopy;
|
||||
if (*Source.end() != '\0') {
|
||||
SourceCopy = Source.str();
|
||||
Source = SourceCopy;
|
||||
}
|
||||
|
||||
size_t MaxLineNumberWidth = std::ceil(std::log10(SourceCode.LastLine));
|
||||
for (line_iterator I = line_iterator(MemoryBufferRef(Source, ""), false);
|
||||
!I.is_at_eof(); ++I) {
|
||||
int64_t L = SourceCode.FirstLine + I.line_number() - 1;
|
||||
OS << format_decimal(L, MaxLineNumberWidth);
|
||||
if (L == SourceCode.Line)
|
||||
OS << " >: ";
|
||||
else
|
||||
OS << " : ";
|
||||
OS << *I << '\n';
|
||||
}
|
||||
SourceCode.format(OS);
|
||||
}
|
||||
|
||||
void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) {
|
||||
@ -131,7 +134,8 @@ void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) {
|
||||
void LLVMPrinter::printSimpleLocation(StringRef Filename,
|
||||
const DILineInfo &Info) {
|
||||
OS << Filename << ':' << Info.Line << ':' << Info.Column << '\n';
|
||||
printContext(SourceCode(Filename, Info.Line, Config.SourceContextLines));
|
||||
printContext(
|
||||
SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source));
|
||||
}
|
||||
|
||||
void GNUPrinter::printSimpleLocation(StringRef Filename,
|
||||
@ -140,7 +144,8 @@ void GNUPrinter::printSimpleLocation(StringRef Filename,
|
||||
if (Info.Discriminator)
|
||||
OS << " (discriminator " << Info.Discriminator << ')';
|
||||
OS << '\n';
|
||||
printContext(SourceCode(Filename, Info.Line, Config.SourceContextLines));
|
||||
printContext(
|
||||
SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source));
|
||||
}
|
||||
|
||||
void PlainPrinterBase::printVerbose(StringRef Filename,
|
||||
@ -291,7 +296,7 @@ void JSONPrinter::print(const Request &Request, const DIInliningInfo &Info) {
|
||||
json::Array Array;
|
||||
for (uint32_t I = 0, N = Info.getNumberOfFrames(); I < N; ++I) {
|
||||
const DILineInfo &LineInfo = Info.getFrame(I);
|
||||
Array.push_back(json::Object(
|
||||
json::Object Object(
|
||||
{{"FunctionName", LineInfo.FunctionName != DILineInfo::BadString
|
||||
? LineInfo.FunctionName
|
||||
: ""},
|
||||
@ -305,7 +310,15 @@ void JSONPrinter::print(const Request &Request, const DIInliningInfo &Info) {
|
||||
LineInfo.FileName != DILineInfo::BadString ? LineInfo.FileName : ""},
|
||||
{"Line", LineInfo.Line},
|
||||
{"Column", LineInfo.Column},
|
||||
{"Discriminator", LineInfo.Discriminator}}));
|
||||
{"Discriminator", LineInfo.Discriminator}});
|
||||
SourceCode SourceCode(LineInfo.FileName, LineInfo.Line,
|
||||
Config.SourceContextLines, LineInfo.Source);
|
||||
std::string FormattedSource;
|
||||
raw_string_ostream Stream(FormattedSource);
|
||||
SourceCode.format(Stream);
|
||||
if (!FormattedSource.empty())
|
||||
Object["Source"] = std::move(FormattedSource);
|
||||
Array.push_back(std::move(Object));
|
||||
}
|
||||
json::Object Json = toJSON(Request);
|
||||
Json["Symbol"] = std::move(Array);
|
||||
|
57
test/tools/llvm-symbolizer/source.ll
Normal file
57
test/tools/llvm-symbolizer/source.ll
Normal file
@ -0,0 +1,57 @@
|
||||
;; This test checks output of the DWARF embedded source.
|
||||
|
||||
; REQUIRES: x86-registered-target
|
||||
|
||||
; RUN: llc -filetype=obj -o %t.o %s
|
||||
|
||||
;; Check LLVM style output.
|
||||
; RUN: llvm-symbolizer --print-source-context-lines=3 --obj=%t.o 0 | \
|
||||
; RUN: FileCheck %s --check-prefixes=COMMON,LLVM --strict-whitespace --match-full-lines --implicit-check-not={{.}}
|
||||
|
||||
;; Check GNU output style.
|
||||
; RUN: llvm-symbolizer --print-source-context-lines=3 --obj=%t.o 0 --output-style=GNU | \
|
||||
; RUN: FileCheck %s --check-prefixes=COMMON,GNU --strict-whitespace --match-full-lines --implicit-check-not={{.}}
|
||||
|
||||
; COMMON:foo
|
||||
; LLVM-NEXT:/source.c:3:13
|
||||
; GNU-NEXT:/source.c:3
|
||||
; COMMON-NEXT:2 : // Line 2
|
||||
; COMMON-NEXT:3 >: void foo() {}
|
||||
; COMMON-NEXT:4 : // Line 4
|
||||
|
||||
;; Check JSON style output.
|
||||
; RUN: llvm-symbolizer --print-source-context-lines=3 --obj=%t.o 0 --output-style=JSON | \
|
||||
; RUN: FileCheck %s --check-prefix=JSON --strict-whitespace --match-full-lines --implicit-check-not={{.}}
|
||||
; JSON:[{"Address":"0x0","ModuleName":"{{.*}}.o","Symbol":[{"Column":13,"Discriminator":0,"FileName":"/source.c","FunctionName":"foo","Line":3,"Source":"2 : // Line 2\n3 >: void foo() {}\n4 : // Line 4\n","StartAddress":"0x0","StartFileName":"/source.c","StartLine":3}]}]
|
||||
|
||||
;; Generated from the following source:
|
||||
;; // Line 1
|
||||
;; // Line 2
|
||||
;; void foo() {}
|
||||
;; // Line 4
|
||||
;; // Line 5
|
||||
;; clang --target=x86_64-pc-linux -gdwarf-5 -gembed-source -g -emit-llvm -S source.c -o source.ll
|
||||
|
||||
source_filename = "source.c"
|
||||
target triple = "x86_64-pc-linux"
|
||||
|
||||
define dso_local void @foo() #0 !dbg !7 {
|
||||
entry:
|
||||
ret void, !dbg !10
|
||||
}
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5}
|
||||
!llvm.ident = !{!6}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "source.c", directory: "/", source: "// Line 1\0A// Line 2\0Avoid foo() {}\0A// Line 4\0A// Line 5\0A")
|
||||
!2 = !{}
|
||||
!3 = !{i32 7, !"Dwarf Version", i32 5}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||
!6 = !{!"clang version 12.0.0"}
|
||||
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
|
||||
!8 = !DISubroutineType(types: !9)
|
||||
!9 = !{null}
|
||||
!10 = !DILocation(line: 3, column: 13, scope: !7)
|
Loading…
x
Reference in New Issue
Block a user