1 //===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the DIPrinter class, which is responsible for printing
10 // structures defined in DebugInfo/DIContext.h
12 //===----------------------------------------------------------------------===//
14 #include "llvm/DebugInfo/Symbolize/DIPrinter.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/DebugInfo/DIContext.h"
17 #include "llvm/Support/ErrorOr.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/LineIterator.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/Path.h"
22 #include "llvm/Support/raw_ostream.h"
33 // Prints source code around in the FileName the Line.
34 void DIPrinter::printContext(const std::string
&FileName
, int64_t Line
) {
35 if (PrintSourceContext
<= 0)
38 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> BufOrErr
=
39 MemoryBuffer::getFile(FileName
);
43 std::unique_ptr
<MemoryBuffer
> Buf
= std::move(BufOrErr
.get());
45 std::max(static_cast<int64_t>(1), Line
- PrintSourceContext
/ 2);
46 int64_t LastLine
= FirstLine
+ PrintSourceContext
;
47 size_t MaxLineNumberWidth
= std::ceil(std::log10(LastLine
));
49 for (line_iterator I
= line_iterator(*Buf
, false);
50 !I
.is_at_eof() && I
.line_number() <= LastLine
; ++I
) {
51 int64_t L
= I
.line_number();
52 if (L
>= FirstLine
&& L
<= LastLine
) {
53 OS
<< format_decimal(L
, MaxLineNumberWidth
);
63 void DIPrinter::print(const DILineInfo
&Info
, bool Inlined
) {
64 if (PrintFunctionNames
) {
65 std::string FunctionName
= Info
.FunctionName
;
66 if (FunctionName
== DILineInfo::BadString
)
67 FunctionName
= DILineInfo::Addr2LineBadString
;
69 StringRef Delimiter
= PrintPretty
? " at " : "\n";
70 StringRef Prefix
= (PrintPretty
&& Inlined
) ? " (inlined by) " : "";
71 OS
<< Prefix
<< FunctionName
<< Delimiter
;
73 std::string Filename
= Info
.FileName
;
74 if (Filename
== DILineInfo::BadString
)
75 Filename
= DILineInfo::Addr2LineBadString
;
77 Filename
= llvm::sys::path::filename(Filename
);
79 OS
<< Filename
<< ":" << Info
.Line
;
80 if (Style
== OutputStyle::LLVM
)
81 OS
<< ":" << Info
.Column
;
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
== DILineInfo::BadString
)
114 Name
= DILineInfo::Addr2LineBadString
;
116 OS
<< Global
.Start
<< " " << Global
.Size
<< "\n";
120 DIPrinter
&DIPrinter::operator<<(const DILocal
&Local
) {
121 OS
<< Local
.FunctionName
<< '\n';
122 OS
<< Local
.Name
<< '\n';
123 if (Local
.DeclFile
.empty())
126 OS
<< Local
.DeclFile
;
127 OS
<< ':' << Local
.DeclLine
<< '\n';
128 if (Local
.FrameOffset
)
129 OS
<< *Local
.FrameOffset
<< ' ';
133 OS
<< *Local
.Size
<< ' ';
137 OS
<< *Local
.TagOffset
<< '\n';
143 } // end namespace symbolize
144 } // end namespace llvm