blob: a9dee7abeed1eca4c04c1acfa763fc3a0f437d6a [file] [log] [blame]
Alexey Samsonovd6aa8202015-11-03 22:20:52 +00001//===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the DIPrinter class, which is responsible for printing
11// structures defined in DebugInfo/DIContext.h
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
16
17#include "llvm/DebugInfo/DIContext.h"
Mike Aizatsky17dbc282016-01-09 00:14:35 +000018#include "llvm/Support/LineIterator.h"
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000019
20namespace llvm {
21namespace symbolize {
22
23// By default, DILineInfo contains "<invalid>" for function/filename it
24// cannot fetch. We replace it to "??" to make our output closer to addr2line.
25static const char kDILineInfoBadString[] = "<invalid>";
26static const char kBadString[] = "??";
27
Mike Aizatsky17dbc282016-01-09 00:14:35 +000028// Prints source code around in the FileName the Line.
29void DIPrinter::printContext(std::string FileName, int64_t Line) {
30 if (PrintSourceContext <= 0)
31 return;
32
33 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
34 MemoryBuffer::getFile(FileName);
35 if (!BufOrErr)
36 return;
37
38 std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
Mike Aizatsky6129dac2016-01-09 00:31:56 +000039 int64_t FirstLine =
40 std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2);
Mike Aizatsky17dbc282016-01-09 00:14:35 +000041 int64_t LastLine = FirstLine + PrintSourceContext;
42 size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
43
44 for (line_iterator I = line_iterator(*Buf, false);
45 !I.is_at_eof() && I.line_number() <= LastLine; ++I) {
46 int64_t L = I.line_number();
47 if (L >= FirstLine && L <= LastLine) {
48 OS << format_decimal(L, MaxLineNumberWidth);
49 if (L == Line)
50 OS << " >: ";
51 else
52 OS << " : ";
53 OS << *I << "\n";
54 }
55 }
56}
57
58void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000059 if (PrintFunctionNames) {
60 std::string FunctionName = Info.FunctionName;
61 if (FunctionName == kDILineInfoBadString)
62 FunctionName = kBadString;
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000063
64 StringRef Delimiter = (PrintPretty == true) ? " at " : "\n";
65 StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
66 OS << Prefix << FunctionName << Delimiter;
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000067 }
68 std::string Filename = Info.FileName;
69 if (Filename == kDILineInfoBadString)
70 Filename = kBadString;
71 OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n";
Mike Aizatsky17dbc282016-01-09 00:14:35 +000072 printContext(Filename, Info.Line);
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000073}
74
75DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
Mike Aizatsky17dbc282016-01-09 00:14:35 +000076 print(Info, false);
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000077 return *this;
78}
79
80DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
81 uint32_t FramesNum = Info.getNumberOfFrames();
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000082 if (FramesNum == 0) {
Mike Aizatsky17dbc282016-01-09 00:14:35 +000083 print(DILineInfo(), false);
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000084 return *this;
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000085 }
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000086 for (uint32_t i = 0; i < FramesNum; i++)
Mike Aizatsky17dbc282016-01-09 00:14:35 +000087 print(Info.getFrame(i), i > 0);
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000088 return *this;
89}
90
91DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
92 std::string Name = Global.Name;
93 if (Name == kDILineInfoBadString)
94 Name = kBadString;
95 OS << Name << "\n";
96 OS << Global.Start << " " << Global.Size << "\n";
97 return *this;
98}
99
100}
101}