blob: 0d4eb5c167a68ab7a719bf1e0adb75286b10ed3f [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());
NAKAMURA Takumi0929fcf2016-01-09 00:28:50 +000039 int64_t FirstLine = std::max((int64_t)1, Line - PrintSourceContext / 2);
Mike Aizatsky17dbc282016-01-09 00:14:35 +000040 int64_t LastLine = FirstLine + PrintSourceContext;
41 size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
42
43 for (line_iterator I = line_iterator(*Buf, false);
44 !I.is_at_eof() && I.line_number() <= LastLine; ++I) {
45 int64_t L = I.line_number();
46 if (L >= FirstLine && L <= LastLine) {
47 OS << format_decimal(L, MaxLineNumberWidth);
48 if (L == Line)
49 OS << " >: ";
50 else
51 OS << " : ";
52 OS << *I << "\n";
53 }
54 }
55}
56
57void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000058 if (PrintFunctionNames) {
59 std::string FunctionName = Info.FunctionName;
60 if (FunctionName == kDILineInfoBadString)
61 FunctionName = kBadString;
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000062
63 StringRef Delimiter = (PrintPretty == true) ? " at " : "\n";
64 StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
65 OS << Prefix << FunctionName << Delimiter;
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000066 }
67 std::string Filename = Info.FileName;
68 if (Filename == kDILineInfoBadString)
69 Filename = kBadString;
70 OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n";
Mike Aizatsky17dbc282016-01-09 00:14:35 +000071 printContext(Filename, Info.Line);
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000072}
73
74DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
Mike Aizatsky17dbc282016-01-09 00:14:35 +000075 print(Info, false);
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000076 return *this;
77}
78
79DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
80 uint32_t FramesNum = Info.getNumberOfFrames();
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000081 if (FramesNum == 0) {
Mike Aizatsky17dbc282016-01-09 00:14:35 +000082 print(DILineInfo(), false);
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000083 return *this;
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000084 }
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000085 for (uint32_t i = 0; i < FramesNum; i++)
Mike Aizatsky17dbc282016-01-09 00:14:35 +000086 print(Info.getFrame(i), i > 0);
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000087 return *this;
88}
89
90DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
91 std::string Name = Global.Name;
92 if (Name == kDILineInfoBadString)
93 Name = kBadString;
94 OS << Name << "\n";
95 OS << Global.Start << " " << Global.Size << "\n";
96 return *this;
97}
98
99}
100}