1 //===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the DIPrinter class, which is responsible for printing
11 // structures defined in DebugInfo/DIContext.h
13 //===----------------------------------------------------------------------===//
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"
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
[] = "??";
38 // Prints source code around in the FileName the Line.
39 void DIPrinter::printContext(const std::string
&FileName
, int64_t Line
) {
40 if (PrintSourceContext
<= 0)
43 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> BufOrErr
=
44 MemoryBuffer::getFile(FileName
);
48 std::unique_ptr
<MemoryBuffer
> Buf
= std::move(BufOrErr
.get());
50 std::max(static_cast<int64_t>(1), Line
- PrintSourceContext
/ 2);
51 int64_t LastLine
= FirstLine
+ PrintSourceContext
;
52 size_t MaxLineNumberWidth
= std::ceil(std::log10(LastLine
));
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
);
68 void DIPrinter::print(const DILineInfo
&Info
, bool Inlined
) {
69 if (PrintFunctionNames
) {
70 std::string FunctionName
= Info
.FunctionName
;
71 if (FunctionName
== kDILineInfoBadString
)
72 FunctionName
= kBadString
;
74 StringRef Delimiter
= PrintPretty
? " at " : "\n";
75 StringRef Prefix
= (PrintPretty
&& Inlined
) ? " (inlined by) " : "";
76 OS
<< Prefix
<< FunctionName
<< Delimiter
;
78 std::string Filename
= Info
.FileName
;
79 if (Filename
== kDILineInfoBadString
)
80 Filename
= kBadString
;
82 OS
<< Filename
<< ":" << Info
.Line
<< ":" << Info
.Column
<< "\n";
83 printContext(Filename
, Info
.Line
);
86 OS
<< " Filename: " << Filename
<< "\n";
88 OS
<< "Function start line: " << Info
.StartLine
<< "\n";
89 OS
<< " Line: " << Info
.Line
<< "\n";
90 OS
<< " Column: " << Info
.Column
<< "\n";
91 if (Info
.Discriminator
)
92 OS
<< " Discriminator: " << Info
.Discriminator
<< "\n";
95 DIPrinter
&DIPrinter::operator<<(const DILineInfo
&Info
) {
100 DIPrinter
&DIPrinter::operator<<(const DIInliningInfo
&Info
) {
101 uint32_t FramesNum
= Info
.getNumberOfFrames();
102 if (FramesNum
== 0) {
103 print(DILineInfo(), false);
106 for (uint32_t i
= 0; i
< FramesNum
; i
++)
107 print(Info
.getFrame(i
), i
> 0);
111 DIPrinter
&DIPrinter::operator<<(const DIGlobal
&Global
) {
112 std::string Name
= Global
.Name
;
113 if (Name
== kDILineInfoBadString
)
116 OS
<< Global
.Start
<< " " << Global
.Size
<< "\n";
120 } // end namespace symbolize
121 } // end namespace llvm