Line data Source code
1 : //===- 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 : #include "llvm/ADT/StringRef.h"
17 : #include "llvm/DebugInfo/DIContext.h"
18 : #include "llvm/Support/ErrorOr.h"
19 : #include "llvm/Support/Format.h"
20 : #include "llvm/Support/LineIterator.h"
21 : #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>
29 :
30 : namespace llvm {
31 : namespace 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.
35 : static const char kDILineInfoBadString[] = "<invalid>";
36 : static const char kBadString[] = "??";
37 :
38 : // Prints source code around in the FileName the Line.
39 539 : void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
40 539 : if (PrintSourceContext <= 0)
41 538 : return;
42 :
43 : ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
44 1 : MemoryBuffer::getFile(FileName);
45 1 : if (!BufOrErr)
46 : return;
47 :
48 : std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
49 : int64_t FirstLine =
50 1 : std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2);
51 1 : int64_t LastLine = FirstLine + PrintSourceContext;
52 1 : size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
53 :
54 1 : for (line_iterator I = line_iterator(*Buf, false);
55 7 : !I.is_at_eof() && I.line_number() <= LastLine; ++I) {
56 : int64_t L = I.line_number();
57 6 : if (L >= FirstLine && L <= LastLine) {
58 12 : OS << format_decimal(L, MaxLineNumberWidth);
59 6 : if (L == Line)
60 1 : OS << " >: ";
61 : else
62 5 : OS << " : ";
63 6 : OS << *I << "\n";
64 : }
65 : }
66 : }
67 :
68 551 : void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
69 551 : if (PrintFunctionNames) {
70 : std::string FunctionName = Info.FunctionName;
71 551 : if (FunctionName == kDILineInfoBadString)
72 : FunctionName = kBadString;
73 :
74 551 : StringRef Delimiter = PrintPretty ? " at " : "\n";
75 551 : StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
76 1102 : OS << Prefix << FunctionName << Delimiter;
77 : }
78 : std::string Filename = Info.FileName;
79 551 : if (Filename == kDILineInfoBadString)
80 : Filename = kBadString;
81 551 : if (!Verbose) {
82 539 : OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n";
83 539 : printContext(Filename, Info.Line);
84 : return;
85 : }
86 24 : OS << " Filename: " << Filename << "\n";
87 12 : if (Info.StartLine)
88 12 : OS << "Function start line: " << Info.StartLine << "\n";
89 12 : OS << " Line: " << Info.Line << "\n";
90 12 : OS << " Column: " << Info.Column << "\n";
91 12 : if (Info.Discriminator)
92 7 : OS << " Discriminator: " << Info.Discriminator << "\n";
93 : }
94 :
95 0 : DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
96 0 : print(Info, false);
97 0 : return *this;
98 : }
99 :
100 496 : DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
101 : uint32_t FramesNum = Info.getNumberOfFrames();
102 496 : if (FramesNum == 0) {
103 3 : print(DILineInfo(), false);
104 3 : return *this;
105 : }
106 1041 : for (uint32_t i = 0; i < FramesNum; i++)
107 548 : print(Info.getFrame(i), i > 0);
108 : return *this;
109 : }
110 :
111 0 : DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
112 : std::string Name = Global.Name;
113 0 : if (Name == kDILineInfoBadString)
114 : Name = kBadString;
115 0 : OS << Name << "\n";
116 0 : OS << Global.Start << " " << Global.Size << "\n";
117 0 : return *this;
118 : }
119 :
120 : } // end namespace symbolize
121 : } // end namespace llvm
|