blob: c1e2536d6e209eb0e54c140635dd2c321505ad25 [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"
Eugene Zelenko417d4c52016-05-09 23:11:38 +000016#include "llvm/ADT/StringRef.h"
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000017#include "llvm/DebugInfo/DIContext.h"
Eugene Zelenko417d4c52016-05-09 23:11:38 +000018#include "llvm/Support/ErrorOr.h"
19#include "llvm/Support/Format.h"
Mike Aizatsky17dbc282016-01-09 00:14:35 +000020#include "llvm/Support/LineIterator.h"
Eugene Zelenko417d4c52016-05-09 23:11:38 +000021#include "llvm/Support/MemoryBuffer.h"
22#include "llvm/Support/raw_ostream.h"
23#include <algorithm>
24#include <cmath>
25#include <cstddef>
26#include <cstdint>
27#include <memory>
28#include <string>
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000029
30namespace llvm {
31namespace symbolize {
32
33// By default, DILineInfo contains "<invalid>" for function/filename it
34// cannot fetch. We replace it to "??" to make our output closer to addr2line.
35static const char kDILineInfoBadString[] = "<invalid>";
36static const char kBadString[] = "??";
37
Mike Aizatsky17dbc282016-01-09 00:14:35 +000038// Prints source code around in the FileName the Line.
Benjamin Kramerc321e532016-06-08 19:09:22 +000039void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
Mike Aizatsky17dbc282016-01-09 00:14:35 +000040 if (PrintSourceContext <= 0)
41 return;
42
43 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
44 MemoryBuffer::getFile(FileName);
45 if (!BufOrErr)
46 return;
47
48 std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
Mike Aizatsky6129dac2016-01-09 00:31:56 +000049 int64_t FirstLine =
50 std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2);
Mike Aizatsky17dbc282016-01-09 00:14:35 +000051 int64_t LastLine = FirstLine + PrintSourceContext;
52 size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
53
54 for (line_iterator I = line_iterator(*Buf, false);
55 !I.is_at_eof() && I.line_number() <= LastLine; ++I) {
56 int64_t L = I.line_number();
57 if (L >= FirstLine && L <= LastLine) {
58 OS << format_decimal(L, MaxLineNumberWidth);
59 if (L == Line)
60 OS << " >: ";
61 else
62 OS << " : ";
63 OS << *I << "\n";
64 }
65 }
66}
67
68void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000069 if (PrintFunctionNames) {
70 std::string FunctionName = Info.FunctionName;
71 if (FunctionName == kDILineInfoBadString)
72 FunctionName = kBadString;
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000073
Eugene Zelenko417d4c52016-05-09 23:11:38 +000074 StringRef Delimiter = PrintPretty ? " at " : "\n";
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000075 StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
76 OS << Prefix << FunctionName << Delimiter;
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000077 }
78 std::string Filename = Info.FileName;
79 if (Filename == kDILineInfoBadString)
80 Filename = kBadString;
David Blaikie0012dd52017-01-31 22:19:38 +000081 if (!Verbose) {
82 OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n";
83 printContext(Filename, Info.Line);
84 return;
85 }
86 OS << " Filename: " << Filename << "\n";
David Blaikieefc4eba2017-02-06 20:19:02 +000087 if (Info.StartLine)
88 OS << "Function start line: " << Info.StartLine << "\n";
David Blaikie0012dd52017-01-31 22:19:38 +000089 OS << " Line: " << Info.Line << "\n";
90 OS << " Column: " << Info.Column << "\n";
91 if (Info.Discriminator)
92 OS << " Discriminator: " << Info.Discriminator << "\n";
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +000093}
94
95DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
Mike Aizatsky17dbc282016-01-09 00:14:35 +000096 print(Info, false);
Alexey Samsonovd6aa8202015-11-03 22:20:52 +000097 return *this;
98}
99
100DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
101 uint32_t FramesNum = Info.getNumberOfFrames();
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +0000102 if (FramesNum == 0) {
Mike Aizatsky17dbc282016-01-09 00:14:35 +0000103 print(DILineInfo(), false);
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +0000104 return *this;
Alexey Samsonovd6aa8202015-11-03 22:20:52 +0000105 }
Hemant Kulkarnibdce12a2015-11-11 20:41:43 +0000106 for (uint32_t i = 0; i < FramesNum; i++)
Mike Aizatsky17dbc282016-01-09 00:14:35 +0000107 print(Info.getFrame(i), i > 0);
Alexey Samsonovd6aa8202015-11-03 22:20:52 +0000108 return *this;
109}
110
111DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
112 std::string Name = Global.Name;
113 if (Name == kDILineInfoBadString)
114 Name = kBadString;
115 OS << Name << "\n";
116 OS << Global.Start << " " << Global.Size << "\n";
117 return *this;
118}
119
Eugene Zelenko417d4c52016-05-09 23:11:38 +0000120} // end namespace symbolize
121} // end namespace llvm