1 | //===- PrettyCompilandDumper.cpp - llvm-pdbutil compiland dumper -*- C++ *-===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "PrettyCompilandDumper.h" |
10 | |
11 | #include "PrettyFunctionDumper.h" |
12 | #include "llvm-pdbutil.h" |
13 | |
14 | #include "llvm/ADT/StringExtras.h" |
15 | #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" |
16 | #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" |
17 | #include "llvm/DebugInfo/PDB/IPDBSession.h" |
18 | #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" |
19 | #include "llvm/DebugInfo/PDB/PDBExtras.h" |
20 | #include "llvm/DebugInfo/PDB/PDBSymbol.h" |
21 | #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" |
22 | #include "llvm/DebugInfo/PDB/PDBSymbolData.h" |
23 | #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" |
24 | #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" |
25 | #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" |
26 | #include "llvm/DebugInfo/PDB/PDBSymbolLabel.h" |
27 | #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" |
28 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" |
29 | #include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h" |
30 | #include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h" |
31 | #include "llvm/Support/Format.h" |
32 | #include "llvm/Support/Path.h" |
33 | #include "llvm/Support/raw_ostream.h" |
34 | |
35 | #include <utility> |
36 | |
37 | using namespace llvm; |
38 | using namespace llvm::pdb; |
39 | |
40 | CompilandDumper::CompilandDumper(LinePrinter &P) |
41 | : PDBSymDumper(true), Printer(P) {} |
42 | |
43 | void CompilandDumper::dump(const PDBSymbolCompilandDetails &Symbol) {} |
44 | |
45 | void CompilandDumper::dump(const PDBSymbolCompilandEnv &Symbol) {} |
46 | |
47 | void CompilandDumper::start(const PDBSymbolCompiland &Symbol, |
48 | CompilandDumpFlags opts) { |
49 | std::string FullName = Symbol.getName(); |
50 | if (Printer.IsCompilandExcluded(CompilandName: FullName)) |
51 | return; |
52 | |
53 | Printer.NewLine(); |
54 | WithColor(Printer, PDB_ColorItem::Path).get() << FullName; |
55 | |
56 | if (opts & Flags::Lines) { |
57 | const IPDBSession &Session = Symbol.getSession(); |
58 | if (auto Files = Session.getSourceFilesForCompiland(Compiland: Symbol)) { |
59 | Printer.Indent(); |
60 | while (auto File = Files->getNext()) { |
61 | Printer.NewLine(); |
62 | WithColor(Printer, PDB_ColorItem::Path).get() << File->getFileName(); |
63 | if (File->getChecksumType() != PDB_Checksum::None) { |
64 | auto ChecksumType = File->getChecksumType(); |
65 | auto ChecksumHexString = toHex(Input: File->getChecksum()); |
66 | WithColor(Printer, PDB_ColorItem::Comment).get() |
67 | << " (" << ChecksumType << ": " << ChecksumHexString << ")" ; |
68 | } |
69 | |
70 | auto Lines = Session.findLineNumbers(Compiland: Symbol, File: *File); |
71 | if (!Lines) |
72 | continue; |
73 | |
74 | Printer.Indent(); |
75 | while (auto Line = Lines->getNext()) { |
76 | Printer.NewLine(); |
77 | uint32_t LineStart = Line->getLineNumber(); |
78 | uint32_t LineEnd = Line->getLineNumberEnd(); |
79 | |
80 | Printer << "Line " ; |
81 | PDB_ColorItem StatementColor = Line->isStatement() |
82 | ? PDB_ColorItem::Keyword |
83 | : PDB_ColorItem::LiteralValue; |
84 | WithColor(Printer, StatementColor).get() << LineStart; |
85 | if (LineStart != LineEnd) |
86 | WithColor(Printer, StatementColor).get() << " - " << LineEnd; |
87 | |
88 | uint32_t ColumnStart = Line->getColumnNumber(); |
89 | uint32_t ColumnEnd = Line->getColumnNumberEnd(); |
90 | if (ColumnStart != 0 || ColumnEnd != 0) { |
91 | Printer << ", Column: " ; |
92 | WithColor(Printer, StatementColor).get() << ColumnStart; |
93 | if (ColumnEnd != ColumnStart) |
94 | WithColor(Printer, StatementColor).get() << " - " << ColumnEnd; |
95 | } |
96 | |
97 | Printer << ", Address: " ; |
98 | if (Line->getLength() > 0) { |
99 | uint64_t AddrStart = Line->getVirtualAddress(); |
100 | uint64_t AddrEnd = AddrStart + Line->getLength() - 1; |
101 | WithColor(Printer, PDB_ColorItem::Address).get() |
102 | << "[" << format_hex(N: AddrStart, Width: 10) << " - " |
103 | << format_hex(N: AddrEnd, Width: 10) << "]" ; |
104 | Printer << " (" << Line->getLength() << " bytes)" ; |
105 | } else { |
106 | uint64_t AddrStart = Line->getVirtualAddress(); |
107 | WithColor(Printer, PDB_ColorItem::Address).get() |
108 | << "[" << format_hex(N: AddrStart, Width: 10) << "] " ; |
109 | Printer << "(0 bytes)" ; |
110 | } |
111 | } |
112 | Printer.Unindent(); |
113 | } |
114 | Printer.Unindent(); |
115 | } |
116 | } |
117 | |
118 | if (opts & Flags::Children) { |
119 | if (auto ChildrenEnum = Symbol.findAllChildren()) { |
120 | Printer.Indent(); |
121 | while (auto Child = ChildrenEnum->getNext()) |
122 | Child->dump(Dumper&: *this); |
123 | Printer.Unindent(); |
124 | } |
125 | } |
126 | } |
127 | |
128 | void CompilandDumper::dump(const PDBSymbolData &Symbol) { |
129 | if (!shouldDumpSymLevel(Level: opts::pretty::SymLevel::Data)) |
130 | return; |
131 | if (Printer.IsSymbolExcluded(SymbolName: Symbol.getName())) |
132 | return; |
133 | |
134 | Printer.NewLine(); |
135 | |
136 | switch (auto LocType = Symbol.getLocationType()) { |
137 | case PDB_LocType::Static: |
138 | Printer << "data: " ; |
139 | WithColor(Printer, PDB_ColorItem::Address).get() |
140 | << "[" << format_hex(N: Symbol.getVirtualAddress(), Width: 10) << "]" ; |
141 | |
142 | WithColor(Printer, PDB_ColorItem::Comment).get() |
143 | << " [sizeof = " << getTypeLength(Symbol) << "]" ; |
144 | |
145 | break; |
146 | case PDB_LocType::Constant: |
147 | Printer << "constant: " ; |
148 | WithColor(Printer, PDB_ColorItem::LiteralValue).get() |
149 | << "[" << Symbol.getValue() << "]" ; |
150 | WithColor(Printer, PDB_ColorItem::Comment).get() |
151 | << " [sizeof = " << getTypeLength(Symbol) << "]" ; |
152 | break; |
153 | default: |
154 | Printer << "data(unexpected type=" << LocType << ")" ; |
155 | } |
156 | |
157 | Printer << " " ; |
158 | WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); |
159 | } |
160 | |
161 | void CompilandDumper::dump(const PDBSymbolFunc &Symbol) { |
162 | if (!shouldDumpSymLevel(Level: opts::pretty::SymLevel::Functions)) |
163 | return; |
164 | if (Symbol.getLength() == 0) |
165 | return; |
166 | if (Printer.IsSymbolExcluded(SymbolName: Symbol.getName())) |
167 | return; |
168 | |
169 | Printer.NewLine(); |
170 | FunctionDumper Dumper(Printer); |
171 | Dumper.start(Symbol, Pointer: FunctionDumper::PointerType::None); |
172 | } |
173 | |
174 | void CompilandDumper::dump(const PDBSymbolLabel &Symbol) { |
175 | if (Printer.IsSymbolExcluded(SymbolName: Symbol.getName())) |
176 | return; |
177 | |
178 | Printer.NewLine(); |
179 | Printer << "label " ; |
180 | WithColor(Printer, PDB_ColorItem::Address).get() |
181 | << "[" << format_hex(N: Symbol.getVirtualAddress(), Width: 10) << "] " ; |
182 | WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); |
183 | } |
184 | |
185 | void CompilandDumper::dump(const PDBSymbolThunk &Symbol) { |
186 | if (!shouldDumpSymLevel(Level: opts::pretty::SymLevel::Thunks)) |
187 | return; |
188 | if (Printer.IsSymbolExcluded(SymbolName: Symbol.getName())) |
189 | return; |
190 | |
191 | Printer.NewLine(); |
192 | Printer << "thunk " ; |
193 | codeview::ThunkOrdinal Ordinal = Symbol.getThunkOrdinal(); |
194 | uint64_t VA = Symbol.getVirtualAddress(); |
195 | if (Ordinal == codeview::ThunkOrdinal::TrampIncremental) { |
196 | uint64_t Target = Symbol.getTargetVirtualAddress(); |
197 | WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(N: VA, Width: 10); |
198 | Printer << " -> " ; |
199 | WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(N: Target, Width: 10); |
200 | } else { |
201 | WithColor(Printer, PDB_ColorItem::Address).get() |
202 | << "[" << format_hex(N: VA, Width: 10) << " - " |
203 | << format_hex(N: VA + Symbol.getLength(), Width: 10) << "]" ; |
204 | } |
205 | Printer << " (" ; |
206 | WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal; |
207 | Printer << ") " ; |
208 | std::string Name = Symbol.getName(); |
209 | if (!Name.empty()) |
210 | WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; |
211 | } |
212 | |
213 | void CompilandDumper::dump(const PDBSymbolTypeTypedef &Symbol) {} |
214 | |
215 | void CompilandDumper::dump(const PDBSymbolUnknown &Symbol) { |
216 | Printer.NewLine(); |
217 | Printer << "unknown (" << Symbol.getSymTag() << ")" ; |
218 | } |
219 | |
220 | void CompilandDumper::dump(const PDBSymbolUsingNamespace &Symbol) { |
221 | if (Printer.IsSymbolExcluded(SymbolName: Symbol.getName())) |
222 | return; |
223 | |
224 | Printer.NewLine(); |
225 | Printer << "using namespace " ; |
226 | std::string Name = Symbol.getName(); |
227 | WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; |
228 | } |
229 | |