1 | //===- MinimalSymbolDumper.cpp -------------------------------- *- 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 "MinimalSymbolDumper.h" |
10 | |
11 | #include "llvm/ADT/StringExtras.h" |
12 | #include "llvm/DebugInfo/CodeView/CVRecord.h" |
13 | #include "llvm/DebugInfo/CodeView/CodeView.h" |
14 | #include "llvm/DebugInfo/CodeView/Formatters.h" |
15 | #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" |
16 | #include "llvm/DebugInfo/CodeView/SymbolRecord.h" |
17 | #include "llvm/DebugInfo/CodeView/TypeRecord.h" |
18 | #include "llvm/DebugInfo/PDB/Native/FormatUtil.h" |
19 | #include "llvm/DebugInfo/PDB/Native/InputFile.h" |
20 | #include "llvm/DebugInfo/PDB/Native/LinePrinter.h" |
21 | #include "llvm/DebugInfo/PDB/Native/NativeSession.h" |
22 | #include "llvm/DebugInfo/PDB/Native/PDBFile.h" |
23 | #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" |
24 | #include "llvm/Object/COFF.h" |
25 | #include "llvm/Support/FormatVariadic.h" |
26 | |
27 | using namespace llvm; |
28 | using namespace llvm::codeview; |
29 | using namespace llvm::pdb; |
30 | |
31 | static std::string formatLocalSymFlags(uint32_t IndentLevel, |
32 | LocalSymFlags Flags) { |
33 | std::vector<std::string> Opts; |
34 | if (Flags == LocalSymFlags::None) |
35 | return "none" ; |
36 | |
37 | PUSH_FLAG(LocalSymFlags, IsParameter, Flags, "param" ); |
38 | PUSH_FLAG(LocalSymFlags, IsAddressTaken, Flags, "address is taken" ); |
39 | PUSH_FLAG(LocalSymFlags, IsCompilerGenerated, Flags, "compiler generated" ); |
40 | PUSH_FLAG(LocalSymFlags, IsAggregate, Flags, "aggregate" ); |
41 | PUSH_FLAG(LocalSymFlags, IsAggregated, Flags, "aggregated" ); |
42 | PUSH_FLAG(LocalSymFlags, IsAliased, Flags, "aliased" ); |
43 | PUSH_FLAG(LocalSymFlags, IsAlias, Flags, "alias" ); |
44 | PUSH_FLAG(LocalSymFlags, IsReturnValue, Flags, "return val" ); |
45 | PUSH_FLAG(LocalSymFlags, IsOptimizedOut, Flags, "optimized away" ); |
46 | PUSH_FLAG(LocalSymFlags, IsEnregisteredGlobal, Flags, "enreg global" ); |
47 | PUSH_FLAG(LocalSymFlags, IsEnregisteredStatic, Flags, "enreg static" ); |
48 | return typesetItemList(Opts, IndentLevel: 4, GroupSize: IndentLevel, Sep: " | " ); |
49 | } |
50 | |
51 | static std::string formatExportFlags(uint32_t IndentLevel, ExportFlags Flags) { |
52 | std::vector<std::string> Opts; |
53 | if (Flags == ExportFlags::None) |
54 | return "none" ; |
55 | |
56 | PUSH_FLAG(ExportFlags, IsConstant, Flags, "constant" ); |
57 | PUSH_FLAG(ExportFlags, IsData, Flags, "data" ); |
58 | PUSH_FLAG(ExportFlags, IsPrivate, Flags, "private" ); |
59 | PUSH_FLAG(ExportFlags, HasNoName, Flags, "no name" ); |
60 | PUSH_FLAG(ExportFlags, HasExplicitOrdinal, Flags, "explicit ord" ); |
61 | PUSH_FLAG(ExportFlags, IsForwarder, Flags, "forwarder" ); |
62 | |
63 | return typesetItemList(Opts, IndentLevel: 4, GroupSize: IndentLevel, Sep: " | " ); |
64 | } |
65 | |
66 | static std::string formatCompileSym2Flags(uint32_t IndentLevel, |
67 | CompileSym2Flags Flags) { |
68 | std::vector<std::string> Opts; |
69 | Flags &= ~CompileSym2Flags::SourceLanguageMask; |
70 | if (Flags == CompileSym2Flags::None) |
71 | return "none" ; |
72 | |
73 | PUSH_FLAG(CompileSym2Flags, EC, Flags, "edit and continue" ); |
74 | PUSH_FLAG(CompileSym2Flags, NoDbgInfo, Flags, "no dbg info" ); |
75 | PUSH_FLAG(CompileSym2Flags, LTCG, Flags, "ltcg" ); |
76 | PUSH_FLAG(CompileSym2Flags, NoDataAlign, Flags, "no data align" ); |
77 | PUSH_FLAG(CompileSym2Flags, ManagedPresent, Flags, "has managed code" ); |
78 | PUSH_FLAG(CompileSym2Flags, SecurityChecks, Flags, "security checks" ); |
79 | PUSH_FLAG(CompileSym2Flags, HotPatch, Flags, "hot patchable" ); |
80 | PUSH_FLAG(CompileSym2Flags, CVTCIL, Flags, "cvtcil" ); |
81 | PUSH_FLAG(CompileSym2Flags, MSILModule, Flags, "msil module" ); |
82 | return typesetItemList(Opts, IndentLevel: 4, GroupSize: IndentLevel, Sep: " | " ); |
83 | } |
84 | |
85 | static std::string formatCompileSym3Flags(uint32_t IndentLevel, |
86 | CompileSym3Flags Flags) { |
87 | std::vector<std::string> Opts; |
88 | Flags &= ~CompileSym3Flags::SourceLanguageMask; |
89 | |
90 | if (Flags == CompileSym3Flags::None) |
91 | return "none" ; |
92 | |
93 | PUSH_FLAG(CompileSym3Flags, EC, Flags, "edit and continue" ); |
94 | PUSH_FLAG(CompileSym3Flags, NoDbgInfo, Flags, "no dbg info" ); |
95 | PUSH_FLAG(CompileSym3Flags, LTCG, Flags, "ltcg" ); |
96 | PUSH_FLAG(CompileSym3Flags, NoDataAlign, Flags, "no data align" ); |
97 | PUSH_FLAG(CompileSym3Flags, ManagedPresent, Flags, "has managed code" ); |
98 | PUSH_FLAG(CompileSym3Flags, SecurityChecks, Flags, "security checks" ); |
99 | PUSH_FLAG(CompileSym3Flags, HotPatch, Flags, "hot patchable" ); |
100 | PUSH_FLAG(CompileSym3Flags, CVTCIL, Flags, "cvtcil" ); |
101 | PUSH_FLAG(CompileSym3Flags, MSILModule, Flags, "msil module" ); |
102 | PUSH_FLAG(CompileSym3Flags, Sdl, Flags, "sdl" ); |
103 | PUSH_FLAG(CompileSym3Flags, PGO, Flags, "pgo" ); |
104 | PUSH_FLAG(CompileSym3Flags, Exp, Flags, "exp" ); |
105 | return typesetItemList(Opts, IndentLevel: 4, GroupSize: IndentLevel, Sep: " | " ); |
106 | } |
107 | |
108 | static std::string formatFrameProcedureOptions(uint32_t IndentLevel, |
109 | FrameProcedureOptions FPO) { |
110 | std::vector<std::string> Opts; |
111 | if (FPO == FrameProcedureOptions::None) |
112 | return "none" ; |
113 | |
114 | PUSH_FLAG(FrameProcedureOptions, HasAlloca, FPO, "has alloca" ); |
115 | PUSH_FLAG(FrameProcedureOptions, HasSetJmp, FPO, "has setjmp" ); |
116 | PUSH_FLAG(FrameProcedureOptions, HasLongJmp, FPO, "has longjmp" ); |
117 | PUSH_FLAG(FrameProcedureOptions, HasInlineAssembly, FPO, "has inline asm" ); |
118 | PUSH_FLAG(FrameProcedureOptions, HasExceptionHandling, FPO, "has eh" ); |
119 | PUSH_FLAG(FrameProcedureOptions, MarkedInline, FPO, "marked inline" ); |
120 | PUSH_FLAG(FrameProcedureOptions, HasStructuredExceptionHandling, FPO, |
121 | "has seh" ); |
122 | PUSH_FLAG(FrameProcedureOptions, Naked, FPO, "naked" ); |
123 | PUSH_FLAG(FrameProcedureOptions, SecurityChecks, FPO, "secure checks" ); |
124 | PUSH_FLAG(FrameProcedureOptions, AsynchronousExceptionHandling, FPO, |
125 | "has async eh" ); |
126 | PUSH_FLAG(FrameProcedureOptions, NoStackOrderingForSecurityChecks, FPO, |
127 | "no stack order" ); |
128 | PUSH_FLAG(FrameProcedureOptions, Inlined, FPO, "inlined" ); |
129 | PUSH_FLAG(FrameProcedureOptions, StrictSecurityChecks, FPO, |
130 | "strict secure checks" ); |
131 | PUSH_FLAG(FrameProcedureOptions, SafeBuffers, FPO, "safe buffers" ); |
132 | PUSH_FLAG(FrameProcedureOptions, ProfileGuidedOptimization, FPO, "pgo" ); |
133 | PUSH_FLAG(FrameProcedureOptions, ValidProfileCounts, FPO, |
134 | "has profile counts" ); |
135 | PUSH_FLAG(FrameProcedureOptions, OptimizedForSpeed, FPO, "opt speed" ); |
136 | PUSH_FLAG(FrameProcedureOptions, GuardCfg, FPO, "guard cfg" ); |
137 | PUSH_FLAG(FrameProcedureOptions, GuardCfw, FPO, "guard cfw" ); |
138 | return typesetItemList(Opts, IndentLevel: 4, GroupSize: IndentLevel, Sep: " | " ); |
139 | } |
140 | |
141 | static std::string formatPublicSymFlags(uint32_t IndentLevel, |
142 | PublicSymFlags Flags) { |
143 | std::vector<std::string> Opts; |
144 | if (Flags == PublicSymFlags::None) |
145 | return "none" ; |
146 | |
147 | PUSH_FLAG(PublicSymFlags, Code, Flags, "code" ); |
148 | PUSH_FLAG(PublicSymFlags, Function, Flags, "function" ); |
149 | PUSH_FLAG(PublicSymFlags, Managed, Flags, "managed" ); |
150 | PUSH_FLAG(PublicSymFlags, MSIL, Flags, "msil" ); |
151 | return typesetItemList(Opts, IndentLevel: 4, GroupSize: IndentLevel, Sep: " | " ); |
152 | } |
153 | |
154 | static std::string formatProcSymFlags(uint32_t IndentLevel, |
155 | ProcSymFlags Flags) { |
156 | std::vector<std::string> Opts; |
157 | if (Flags == ProcSymFlags::None) |
158 | return "none" ; |
159 | |
160 | PUSH_FLAG(ProcSymFlags, HasFP, Flags, "has fp" ); |
161 | PUSH_FLAG(ProcSymFlags, HasIRET, Flags, "has iret" ); |
162 | PUSH_FLAG(ProcSymFlags, HasFRET, Flags, "has fret" ); |
163 | PUSH_FLAG(ProcSymFlags, IsNoReturn, Flags, "noreturn" ); |
164 | PUSH_FLAG(ProcSymFlags, IsUnreachable, Flags, "unreachable" ); |
165 | PUSH_FLAG(ProcSymFlags, HasCustomCallingConv, Flags, "custom calling conv" ); |
166 | PUSH_FLAG(ProcSymFlags, IsNoInline, Flags, "noinline" ); |
167 | PUSH_FLAG(ProcSymFlags, HasOptimizedDebugInfo, Flags, "opt debuginfo" ); |
168 | return typesetItemList(Opts, IndentLevel: 4, GroupSize: IndentLevel, Sep: " | " ); |
169 | } |
170 | |
171 | static std::string formatThunkOrdinal(ThunkOrdinal Ordinal) { |
172 | switch (Ordinal) { |
173 | RETURN_CASE(ThunkOrdinal, Standard, "thunk" ); |
174 | RETURN_CASE(ThunkOrdinal, ThisAdjustor, "this adjustor" ); |
175 | RETURN_CASE(ThunkOrdinal, Vcall, "vcall" ); |
176 | RETURN_CASE(ThunkOrdinal, Pcode, "pcode" ); |
177 | RETURN_CASE(ThunkOrdinal, UnknownLoad, "unknown load" ); |
178 | RETURN_CASE(ThunkOrdinal, TrampIncremental, "tramp incremental" ); |
179 | RETURN_CASE(ThunkOrdinal, BranchIsland, "branch island" ); |
180 | } |
181 | return formatUnknownEnum(Value: Ordinal); |
182 | } |
183 | |
184 | static std::string formatTrampolineType(TrampolineType Tramp) { |
185 | switch (Tramp) { |
186 | RETURN_CASE(TrampolineType, TrampIncremental, "tramp incremental" ); |
187 | RETURN_CASE(TrampolineType, BranchIsland, "branch island" ); |
188 | } |
189 | return formatUnknownEnum(Value: Tramp); |
190 | } |
191 | |
192 | static std::string formatSourceLanguage(SourceLanguage Lang) { |
193 | switch (Lang) { |
194 | RETURN_CASE(SourceLanguage, C, "c" ); |
195 | RETURN_CASE(SourceLanguage, Cpp, "c++" ); |
196 | RETURN_CASE(SourceLanguage, Fortran, "fortran" ); |
197 | RETURN_CASE(SourceLanguage, Masm, "masm" ); |
198 | RETURN_CASE(SourceLanguage, Pascal, "pascal" ); |
199 | RETURN_CASE(SourceLanguage, Basic, "basic" ); |
200 | RETURN_CASE(SourceLanguage, Cobol, "cobol" ); |
201 | RETURN_CASE(SourceLanguage, Link, "link" ); |
202 | RETURN_CASE(SourceLanguage, VB, "vb" ); |
203 | RETURN_CASE(SourceLanguage, Cvtres, "cvtres" ); |
204 | RETURN_CASE(SourceLanguage, Cvtpgd, "cvtpgd" ); |
205 | RETURN_CASE(SourceLanguage, CSharp, "c#" ); |
206 | RETURN_CASE(SourceLanguage, ILAsm, "il asm" ); |
207 | RETURN_CASE(SourceLanguage, Java, "java" ); |
208 | RETURN_CASE(SourceLanguage, JScript, "javascript" ); |
209 | RETURN_CASE(SourceLanguage, MSIL, "msil" ); |
210 | RETURN_CASE(SourceLanguage, HLSL, "hlsl" ); |
211 | RETURN_CASE(SourceLanguage, D, "d" ); |
212 | RETURN_CASE(SourceLanguage, Swift, "swift" ); |
213 | RETURN_CASE(SourceLanguage, Rust, "rust" ); |
214 | RETURN_CASE(SourceLanguage, ObjC, "objc" ); |
215 | RETURN_CASE(SourceLanguage, ObjCpp, "objc++" ); |
216 | RETURN_CASE(SourceLanguage, AliasObj, "aliasobj" ); |
217 | RETURN_CASE(SourceLanguage, Go, "go" ); |
218 | RETURN_CASE(SourceLanguage, OldSwift, "swift" ); |
219 | } |
220 | return formatUnknownEnum(Value: Lang); |
221 | } |
222 | |
223 | static std::string formatMachineType(CPUType Cpu) { |
224 | switch (Cpu) { |
225 | RETURN_CASE(CPUType, Intel8080, "intel 8080" ); |
226 | RETURN_CASE(CPUType, Intel8086, "intel 8086" ); |
227 | RETURN_CASE(CPUType, Intel80286, "intel 80286" ); |
228 | RETURN_CASE(CPUType, Intel80386, "intel 80386" ); |
229 | RETURN_CASE(CPUType, Intel80486, "intel 80486" ); |
230 | RETURN_CASE(CPUType, Pentium, "intel pentium" ); |
231 | RETURN_CASE(CPUType, PentiumPro, "intel pentium pro" ); |
232 | RETURN_CASE(CPUType, Pentium3, "intel pentium 3" ); |
233 | RETURN_CASE(CPUType, MIPS, "mips" ); |
234 | RETURN_CASE(CPUType, MIPS16, "mips-16" ); |
235 | RETURN_CASE(CPUType, MIPS32, "mips-32" ); |
236 | RETURN_CASE(CPUType, MIPS64, "mips-64" ); |
237 | RETURN_CASE(CPUType, MIPSI, "mips i" ); |
238 | RETURN_CASE(CPUType, MIPSII, "mips ii" ); |
239 | RETURN_CASE(CPUType, MIPSIII, "mips iii" ); |
240 | RETURN_CASE(CPUType, MIPSIV, "mips iv" ); |
241 | RETURN_CASE(CPUType, MIPSV, "mips v" ); |
242 | RETURN_CASE(CPUType, M68000, "motorola 68000" ); |
243 | RETURN_CASE(CPUType, M68010, "motorola 68010" ); |
244 | RETURN_CASE(CPUType, M68020, "motorola 68020" ); |
245 | RETURN_CASE(CPUType, M68030, "motorola 68030" ); |
246 | RETURN_CASE(CPUType, M68040, "motorola 68040" ); |
247 | RETURN_CASE(CPUType, Alpha, "alpha" ); |
248 | RETURN_CASE(CPUType, Alpha21164, "alpha 21164" ); |
249 | RETURN_CASE(CPUType, Alpha21164A, "alpha 21164a" ); |
250 | RETURN_CASE(CPUType, Alpha21264, "alpha 21264" ); |
251 | RETURN_CASE(CPUType, Alpha21364, "alpha 21364" ); |
252 | RETURN_CASE(CPUType, PPC601, "powerpc 601" ); |
253 | RETURN_CASE(CPUType, PPC603, "powerpc 603" ); |
254 | RETURN_CASE(CPUType, PPC604, "powerpc 604" ); |
255 | RETURN_CASE(CPUType, PPC620, "powerpc 620" ); |
256 | RETURN_CASE(CPUType, PPCFP, "powerpc fp" ); |
257 | RETURN_CASE(CPUType, PPCBE, "powerpc be" ); |
258 | RETURN_CASE(CPUType, SH3, "sh3" ); |
259 | RETURN_CASE(CPUType, SH3E, "sh3e" ); |
260 | RETURN_CASE(CPUType, SH3DSP, "sh3 dsp" ); |
261 | RETURN_CASE(CPUType, SH4, "sh4" ); |
262 | RETURN_CASE(CPUType, SHMedia, "shmedia" ); |
263 | RETURN_CASE(CPUType, ARM3, "arm 3" ); |
264 | RETURN_CASE(CPUType, ARM4, "arm 4" ); |
265 | RETURN_CASE(CPUType, ARM4T, "arm 4t" ); |
266 | RETURN_CASE(CPUType, ARM5, "arm 5" ); |
267 | RETURN_CASE(CPUType, ARM5T, "arm 5t" ); |
268 | RETURN_CASE(CPUType, ARM6, "arm 6" ); |
269 | RETURN_CASE(CPUType, ARM_XMAC, "arm xmac" ); |
270 | RETURN_CASE(CPUType, ARM_WMMX, "arm wmmx" ); |
271 | RETURN_CASE(CPUType, ARM7, "arm 7" ); |
272 | RETURN_CASE(CPUType, ARM64, "arm64" ); |
273 | RETURN_CASE(CPUType, ARM64EC, "arm64ec" ); |
274 | RETURN_CASE(CPUType, ARM64X, "arm64x" ); |
275 | RETURN_CASE(CPUType, HybridX86ARM64, "hybrid x86 arm64" ); |
276 | RETURN_CASE(CPUType, Omni, "omni" ); |
277 | RETURN_CASE(CPUType, Ia64, "intel itanium ia64" ); |
278 | RETURN_CASE(CPUType, Ia64_2, "intel itanium ia64 2" ); |
279 | RETURN_CASE(CPUType, CEE, "cee" ); |
280 | RETURN_CASE(CPUType, AM33, "am33" ); |
281 | RETURN_CASE(CPUType, M32R, "m32r" ); |
282 | RETURN_CASE(CPUType, TriCore, "tri-core" ); |
283 | RETURN_CASE(CPUType, X64, "intel x86-x64" ); |
284 | RETURN_CASE(CPUType, EBC, "ebc" ); |
285 | RETURN_CASE(CPUType, Thumb, "thumb" ); |
286 | RETURN_CASE(CPUType, ARMNT, "arm nt" ); |
287 | RETURN_CASE(CPUType, D3D11_Shader, "d3d11 shader" ); |
288 | RETURN_CASE(CPUType, Unknown, "unknown" ); |
289 | } |
290 | return formatUnknownEnum(Value: Cpu); |
291 | } |
292 | |
293 | static std::string formatCookieKind(FrameCookieKind Kind) { |
294 | switch (Kind) { |
295 | RETURN_CASE(FrameCookieKind, Copy, "copy" ); |
296 | RETURN_CASE(FrameCookieKind, XorStackPointer, "xor stack ptr" ); |
297 | RETURN_CASE(FrameCookieKind, XorFramePointer, "xor frame ptr" ); |
298 | RETURN_CASE(FrameCookieKind, XorR13, "xor rot13" ); |
299 | } |
300 | return formatUnknownEnum(Value: Kind); |
301 | } |
302 | |
303 | static std::string formatRegisterId(RegisterId Id, CPUType Cpu) { |
304 | if (Cpu == CPUType::ARMNT) { |
305 | switch (Id) { |
306 | #define CV_REGISTERS_ARM |
307 | #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name) |
308 | #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" |
309 | #undef CV_REGISTER |
310 | #undef CV_REGISTERS_ARM |
311 | |
312 | default: |
313 | break; |
314 | } |
315 | } else if (Cpu == CPUType::ARM64) { |
316 | switch (Id) { |
317 | #define CV_REGISTERS_ARM64 |
318 | #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name) |
319 | #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" |
320 | #undef CV_REGISTER |
321 | #undef CV_REGISTERS_ARM64 |
322 | |
323 | default: |
324 | break; |
325 | } |
326 | } else { |
327 | switch (Id) { |
328 | #define CV_REGISTERS_X86 |
329 | #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name) |
330 | #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" |
331 | #undef CV_REGISTER |
332 | #undef CV_REGISTERS_X86 |
333 | |
334 | default: |
335 | break; |
336 | } |
337 | } |
338 | return formatUnknownEnum(Value: Id); |
339 | } |
340 | |
341 | static std::string formatRegisterId(uint16_t Reg16, CPUType Cpu) { |
342 | return formatRegisterId(Id: RegisterId(Reg16), Cpu); |
343 | } |
344 | |
345 | static std::string formatRegisterId(ulittle16_t &Reg16, CPUType Cpu) { |
346 | return formatRegisterId(Reg16: uint16_t(Reg16), Cpu); |
347 | } |
348 | |
349 | static std::string formatRange(LocalVariableAddrRange Range) { |
350 | return formatv(Fmt: "[{0},+{1})" , |
351 | Vals: formatSegmentOffset(Segment: Range.ISectStart, Offset: Range.OffsetStart), |
352 | Vals&: Range.Range) |
353 | .str(); |
354 | } |
355 | |
356 | static std::string formatGaps(uint32_t IndentLevel, |
357 | ArrayRef<LocalVariableAddrGap> Gaps) { |
358 | std::vector<std::string> GapStrs; |
359 | for (const auto &G : Gaps) { |
360 | GapStrs.push_back(x: formatv(Fmt: "({0},{1})" , Vals: G.GapStartOffset, Vals: G.Range).str()); |
361 | } |
362 | return typesetItemList(Opts: GapStrs, IndentLevel: 7, GroupSize: IndentLevel, Sep: ", " ); |
363 | } |
364 | |
365 | static std::string formatJumpTableEntrySize(JumpTableEntrySize EntrySize) { |
366 | switch (EntrySize) { |
367 | RETURN_CASE(JumpTableEntrySize, Int8, "int8" ); |
368 | RETURN_CASE(JumpTableEntrySize, UInt8, "uin8" ); |
369 | RETURN_CASE(JumpTableEntrySize, Int16, "int16" ); |
370 | RETURN_CASE(JumpTableEntrySize, UInt16, "uint16" ); |
371 | RETURN_CASE(JumpTableEntrySize, Int32, "int32" ); |
372 | RETURN_CASE(JumpTableEntrySize, UInt32, "uint32" ); |
373 | RETURN_CASE(JumpTableEntrySize, Pointer, "pointer" ); |
374 | RETURN_CASE(JumpTableEntrySize, UInt8ShiftLeft, "uint8shl" ); |
375 | RETURN_CASE(JumpTableEntrySize, UInt16ShiftLeft, "uint16shl" ); |
376 | RETURN_CASE(JumpTableEntrySize, Int8ShiftLeft, "int8shl" ); |
377 | RETURN_CASE(JumpTableEntrySize, Int16ShiftLeft, "int16shl" ); |
378 | } |
379 | return formatUnknownEnum(Value: EntrySize); |
380 | } |
381 | |
382 | Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record) { |
383 | return visitSymbolBegin(Record, Offset: 0); |
384 | } |
385 | |
386 | Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record, |
387 | uint32_t Offset) { |
388 | // formatLine puts the newline at the beginning, so we use formatLine here |
389 | // to start a new line, and then individual visit methods use format to |
390 | // append to the existing line. |
391 | P.formatLine(Fmt: "{0} | {1} [size = {2}]" , |
392 | Items: fmt_align(Item&: Offset, Where: AlignStyle::Right, Amount: 6), |
393 | Items: formatSymbolKind(K: Record.kind()), Items: Record.length()); |
394 | P.Indent(); |
395 | return Error::success(); |
396 | } |
397 | |
398 | Error MinimalSymbolDumper::visitSymbolEnd(CVSymbol &Record) { |
399 | if (RecordBytes) { |
400 | AutoIndent Indent(P, 7); |
401 | P.formatBinary(Label: "bytes" , Data: Record.content(), StartOffset: 0); |
402 | } |
403 | P.Unindent(); |
404 | return Error::success(); |
405 | } |
406 | |
407 | std::string MinimalSymbolDumper::typeOrIdIndex(codeview::TypeIndex TI, |
408 | bool IsType) const { |
409 | if (TI.isSimple() || TI.isDecoratedItemId()) |
410 | return formatv(Fmt: "{0}" , Vals&: TI).str(); |
411 | auto &Container = IsType ? Types : Ids; |
412 | StringRef Name = Container.getTypeName(Index: TI); |
413 | if (Name.size() > 32) { |
414 | Name = Name.take_front(N: 32); |
415 | return std::string(formatv(Fmt: "{0} ({1}...)" , Vals&: TI, Vals&: Name)); |
416 | } else |
417 | return std::string(formatv(Fmt: "{0} ({1})" , Vals&: TI, Vals&: Name)); |
418 | } |
419 | |
420 | std::string MinimalSymbolDumper::idIndex(codeview::TypeIndex TI) const { |
421 | return typeOrIdIndex(TI, IsType: false); |
422 | } |
423 | |
424 | std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const { |
425 | return typeOrIdIndex(TI, IsType: true); |
426 | } |
427 | |
428 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) { |
429 | P.format(Fmt: " `{0}`" , Items&: Block.Name); |
430 | AutoIndent Indent(P, 7); |
431 | P.formatLine(Fmt: "parent = {0}, end = {1}" , Items&: Block.Parent, Items&: Block.End); |
432 | P.formatLine(Fmt: "code size = {0}, addr = {1}" , Items&: Block.CodeSize, |
433 | Items: formatSegmentOffset(Segment: Block.Segment, Offset: Block.CodeOffset)); |
434 | return Error::success(); |
435 | } |
436 | |
437 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) { |
438 | P.format(Fmt: " `{0}`" , Items&: Thunk.Name); |
439 | AutoIndent Indent(P, 7); |
440 | P.formatLine(Fmt: "parent = {0}, end = {1}, next = {2}" , Items&: Thunk.Parent, Items&: Thunk.End, |
441 | Items&: Thunk.Next); |
442 | P.formatLine(Fmt: "kind = {0}, size = {1}, addr = {2}" , |
443 | Items: formatThunkOrdinal(Ordinal: Thunk.Thunk), Items&: Thunk.Length, |
444 | Items: formatSegmentOffset(Segment: Thunk.Segment, Offset: Thunk.Offset)); |
445 | |
446 | return Error::success(); |
447 | } |
448 | |
449 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
450 | TrampolineSym &Tramp) { |
451 | AutoIndent Indent(P, 7); |
452 | P.formatLine(Fmt: "type = {0}, size = {1}, source = {2}, target = {3}" , |
453 | Items: formatTrampolineType(Tramp: Tramp.Type), Items&: Tramp.Size, |
454 | Items: formatSegmentOffset(Segment: Tramp.ThunkSection, Offset: Tramp.ThunkOffset), |
455 | Items: formatSegmentOffset(Segment: Tramp.TargetSection, Offset: Tramp.ThunkOffset)); |
456 | |
457 | return Error::success(); |
458 | } |
459 | |
460 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
461 | SectionSym &Section) { |
462 | P.format(Fmt: " `{0}`" , Items&: Section.Name); |
463 | AutoIndent Indent(P, 7); |
464 | P.formatLine(Fmt: "length = {0}, alignment = {1}, rva = {2}, section # = {3}" , |
465 | Items&: Section.Length, Items&: Section.Alignment, Items&: Section.Rva, |
466 | Items&: Section.SectionNumber); |
467 | P.printLine(T: "characteristics =" ); |
468 | AutoIndent Indent2(P, 2); |
469 | P.printLine(T: formatSectionCharacteristics(IndentLevel: P.getIndentLevel(), |
470 | C: Section.Characteristics, FlagsPerLine: 1, Separator: "" , |
471 | Style: CharacteristicStyle::Descriptive)); |
472 | return Error::success(); |
473 | } |
474 | |
475 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CoffGroupSym &CG) { |
476 | P.format(Fmt: " `{0}`" , Items&: CG.Name); |
477 | AutoIndent Indent(P, 7); |
478 | P.formatLine(Fmt: "length = {0}, addr = {1}" , Items&: CG.Size, |
479 | Items: formatSegmentOffset(Segment: CG.Segment, Offset: CG.Offset)); |
480 | P.printLine(T: "characteristics =" ); |
481 | AutoIndent Indent2(P, 2); |
482 | P.printLine(T: formatSectionCharacteristics(IndentLevel: P.getIndentLevel(), |
483 | C: CG.Characteristics, FlagsPerLine: 1, Separator: "" , |
484 | Style: CharacteristicStyle::Descriptive)); |
485 | return Error::success(); |
486 | } |
487 | |
488 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
489 | BPRelativeSym &BPRel) { |
490 | P.format(Fmt: " `{0}`" , Items&: BPRel.Name); |
491 | AutoIndent Indent(P, 7); |
492 | P.formatLine(Fmt: "type = {0}, offset = {1}" , Items: typeIndex(TI: BPRel.Type), Items&: BPRel.Offset); |
493 | return Error::success(); |
494 | } |
495 | |
496 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
497 | BuildInfoSym &BuildInfo) { |
498 | P.format(Fmt: " BuildId = `{0}`" , Items&: BuildInfo.BuildId); |
499 | return Error::success(); |
500 | } |
501 | |
502 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
503 | CallSiteInfoSym &CSI) { |
504 | AutoIndent Indent(P, 7); |
505 | P.formatLine(Fmt: "type = {0}, addr = {1}" , Items: typeIndex(TI: CSI.Type), |
506 | Items: formatSegmentOffset(Segment: CSI.Segment, Offset: CSI.CodeOffset)); |
507 | return Error::success(); |
508 | } |
509 | |
510 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
511 | EnvBlockSym &EnvBlock) { |
512 | AutoIndent Indent(P, 7); |
513 | for (const auto &Entry : EnvBlock.Fields) { |
514 | P.formatLine(Fmt: "- {0}" , Items: Entry); |
515 | } |
516 | return Error::success(); |
517 | } |
518 | |
519 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FileStaticSym &FS) { |
520 | P.format(Fmt: " `{0}`" , Items&: FS.Name); |
521 | AutoIndent Indent(P, 7); |
522 | if (SymGroup) { |
523 | Expected<StringRef> FileName = |
524 | SymGroup->getNameFromStringTable(Offset: FS.ModFilenameOffset); |
525 | if (FileName) { |
526 | P.formatLine(Fmt: "type = {0}, file name = {1} ({2}), flags = {3}" , |
527 | Items: typeIndex(TI: FS.Index), Items&: FS.ModFilenameOffset, Items&: *FileName, |
528 | Items: formatLocalSymFlags(IndentLevel: P.getIndentLevel() + 9, Flags: FS.Flags)); |
529 | } |
530 | return Error::success(); |
531 | } |
532 | |
533 | P.formatLine(Fmt: "type = {0}, file name offset = {1}, flags = {2}" , |
534 | Items: typeIndex(TI: FS.Index), Items&: FS.ModFilenameOffset, |
535 | Items: formatLocalSymFlags(IndentLevel: P.getIndentLevel() + 9, Flags: FS.Flags)); |
536 | return Error::success(); |
537 | } |
538 | |
539 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) { |
540 | P.format(Fmt: " `{0}`" , Items&: Export.Name); |
541 | AutoIndent Indent(P, 7); |
542 | P.formatLine(Fmt: "ordinal = {0}, flags = {1}" , Items&: Export.Ordinal, |
543 | Items: formatExportFlags(IndentLevel: P.getIndentLevel() + 9, Flags: Export.Flags)); |
544 | return Error::success(); |
545 | } |
546 | |
547 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
548 | Compile2Sym &Compile2) { |
549 | AutoIndent Indent(P, 7); |
550 | SourceLanguage Lang = static_cast<SourceLanguage>( |
551 | Compile2.Flags & CompileSym2Flags::SourceLanguageMask); |
552 | CompilationCPU = Compile2.Machine; |
553 | P.formatLine(Fmt: "machine = {0}, ver = {1}, language = {2}" , |
554 | Items: formatMachineType(Cpu: Compile2.Machine), Items&: Compile2.Version, |
555 | Items: formatSourceLanguage(Lang)); |
556 | P.formatLine(Fmt: "frontend = {0}.{1}.{2}, backend = {3}.{4}.{5}" , |
557 | Items&: Compile2.VersionFrontendMajor, Items&: Compile2.VersionFrontendMinor, |
558 | Items&: Compile2.VersionFrontendBuild, Items&: Compile2.VersionBackendMajor, |
559 | Items&: Compile2.VersionBackendMinor, Items&: Compile2.VersionBackendBuild); |
560 | P.formatLine(Fmt: "flags = {0}" , |
561 | Items: formatCompileSym2Flags(IndentLevel: P.getIndentLevel() + 9, Flags: Compile2.Flags)); |
562 | P.formatLine( |
563 | Fmt: "extra strings = {0}" , |
564 | Items: typesetStringList(IndentLevel: P.getIndentLevel() + 9 + 2, Strings: Compile2.ExtraStrings)); |
565 | return Error::success(); |
566 | } |
567 | |
568 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
569 | Compile3Sym &Compile3) { |
570 | AutoIndent Indent(P, 7); |
571 | SourceLanguage Lang = static_cast<SourceLanguage>( |
572 | Compile3.Flags & CompileSym3Flags::SourceLanguageMask); |
573 | CompilationCPU = Compile3.Machine; |
574 | P.formatLine(Fmt: "machine = {0}, Ver = {1}, language = {2}" , |
575 | Items: formatMachineType(Cpu: Compile3.Machine), Items&: Compile3.Version, |
576 | Items: formatSourceLanguage(Lang)); |
577 | P.formatLine(Fmt: "frontend = {0}.{1}.{2}.{3}, backend = {4}.{5}.{6}.{7}" , |
578 | Items&: Compile3.VersionFrontendMajor, Items&: Compile3.VersionFrontendMinor, |
579 | Items&: Compile3.VersionFrontendBuild, Items&: Compile3.VersionFrontendQFE, |
580 | Items&: Compile3.VersionBackendMajor, Items&: Compile3.VersionBackendMinor, |
581 | Items&: Compile3.VersionBackendBuild, Items&: Compile3.VersionBackendQFE); |
582 | P.formatLine(Fmt: "flags = {0}" , |
583 | Items: formatCompileSym3Flags(IndentLevel: P.getIndentLevel() + 9, Flags: Compile3.Flags)); |
584 | return Error::success(); |
585 | } |
586 | |
587 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
588 | ConstantSym &Constant) { |
589 | P.format(Fmt: " `{0}`" , Items&: Constant.Name); |
590 | AutoIndent Indent(P, 7); |
591 | P.formatLine(Fmt: "type = {0}, value = {1}" , Items: typeIndex(TI: Constant.Type), |
592 | Items: toString(I: Constant.Value, Radix: 10)); |
593 | return Error::success(); |
594 | } |
595 | |
596 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DataSym &Data) { |
597 | P.format(Fmt: " `{0}`" , Items&: Data.Name); |
598 | AutoIndent Indent(P, 7); |
599 | P.formatLine(Fmt: "type = {0}, addr = {1}" , Items: typeIndex(TI: Data.Type), |
600 | Items: formatSegmentOffset(Segment: Data.Segment, Offset: Data.DataOffset)); |
601 | return Error::success(); |
602 | } |
603 | |
604 | Error MinimalSymbolDumper::visitKnownRecord( |
605 | CVSymbol &CVR, DefRangeFramePointerRelFullScopeSym &Def) { |
606 | P.format(Fmt: " offset = {0}" , Items&: Def.Offset); |
607 | return Error::success(); |
608 | } |
609 | |
610 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
611 | DefRangeFramePointerRelSym &Def) { |
612 | AutoIndent Indent(P, 7); |
613 | P.formatLine(Fmt: "offset = {0}, range = {1}" , Items&: Def.Hdr.Offset, |
614 | Items: formatRange(Range: Def.Range)); |
615 | P.formatLine(Fmt: "gaps = [{0}]" , Items: formatGaps(IndentLevel: P.getIndentLevel() + 9, Gaps: Def.Gaps)); |
616 | return Error::success(); |
617 | } |
618 | |
619 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
620 | DefRangeRegisterRelSym &Def) { |
621 | AutoIndent Indent(P, 7); |
622 | P.formatLine(Fmt: "register = {0}, offset = {1}, offset in parent = {2}, has " |
623 | "spilled udt = {3}" , |
624 | Items: formatRegisterId(Reg16&: Def.Hdr.Register, Cpu: CompilationCPU), |
625 | Items: int32_t(Def.Hdr.BasePointerOffset), Items: Def.offsetInParent(), |
626 | Items: Def.hasSpilledUDTMember()); |
627 | P.formatLine(Fmt: "range = {0}, gaps = [{1}]" , Items: formatRange(Range: Def.Range), |
628 | Items: formatGaps(IndentLevel: P.getIndentLevel() + 9, Gaps: Def.Gaps)); |
629 | return Error::success(); |
630 | } |
631 | |
632 | Error MinimalSymbolDumper::visitKnownRecord( |
633 | CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) { |
634 | AutoIndent Indent(P, 7); |
635 | P.formatLine(Fmt: "register = {0}, may have no name = {1}, range start = " |
636 | "{2}, length = {3}" , |
637 | Items: formatRegisterId(Reg16&: DefRangeRegister.Hdr.Register, Cpu: CompilationCPU), |
638 | Items: bool(DefRangeRegister.Hdr.MayHaveNoName), |
639 | Items: formatSegmentOffset(Segment: DefRangeRegister.Range.ISectStart, |
640 | Offset: DefRangeRegister.Range.OffsetStart), |
641 | Items&: DefRangeRegister.Range.Range); |
642 | P.formatLine(Fmt: "gaps = [{0}]" , |
643 | Items: formatGaps(IndentLevel: P.getIndentLevel() + 9, Gaps: DefRangeRegister.Gaps)); |
644 | return Error::success(); |
645 | } |
646 | |
647 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
648 | DefRangeSubfieldRegisterSym &Def) { |
649 | AutoIndent Indent(P, 7); |
650 | bool NoName = !!(Def.Hdr.MayHaveNoName == 0); |
651 | P.formatLine(Fmt: "register = {0}, may have no name = {1}, offset in parent = {2}" , |
652 | Items: formatRegisterId(Reg16&: Def.Hdr.Register, Cpu: CompilationCPU), Items&: NoName, |
653 | Items: uint32_t(Def.Hdr.OffsetInParent)); |
654 | P.formatLine(Fmt: "range = {0}, gaps = [{1}]" , Items: formatRange(Range: Def.Range), |
655 | Items: formatGaps(IndentLevel: P.getIndentLevel() + 9, Gaps: Def.Gaps)); |
656 | return Error::success(); |
657 | } |
658 | |
659 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
660 | DefRangeSubfieldSym &Def) { |
661 | AutoIndent Indent(P, 7); |
662 | P.formatLine(Fmt: "program = {0}, offset in parent = {1}, range = {2}" , |
663 | Items&: Def.Program, Items&: Def.OffsetInParent, Items: formatRange(Range: Def.Range)); |
664 | P.formatLine(Fmt: "gaps = [{0}]" , Items: formatGaps(IndentLevel: P.getIndentLevel() + 9, Gaps: Def.Gaps)); |
665 | return Error::success(); |
666 | } |
667 | |
668 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DefRangeSym &Def) { |
669 | AutoIndent Indent(P, 7); |
670 | P.formatLine(Fmt: "program = {0}, range = {1}" , Items&: Def.Program, |
671 | Items: formatRange(Range: Def.Range)); |
672 | P.formatLine(Fmt: "gaps = [{0}]" , Items: formatGaps(IndentLevel: P.getIndentLevel() + 9, Gaps: Def.Gaps)); |
673 | return Error::success(); |
674 | } |
675 | |
676 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameCookieSym &FC) { |
677 | AutoIndent Indent(P, 7); |
678 | P.formatLine(Fmt: "code offset = {0}, Register = {1}, kind = {2}, flags = {3}" , |
679 | Items&: FC.CodeOffset, Items: formatRegisterId(Reg16: FC.Register, Cpu: CompilationCPU), |
680 | Items: formatCookieKind(Kind: FC.CookieKind), Items&: FC.Flags); |
681 | return Error::success(); |
682 | } |
683 | |
684 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameProcSym &FP) { |
685 | AutoIndent Indent(P, 7); |
686 | P.formatLine(Fmt: "size = {0}, padding size = {1}, offset to padding = {2}" , |
687 | Items&: FP.TotalFrameBytes, Items&: FP.PaddingFrameBytes, Items&: FP.OffsetToPadding); |
688 | P.formatLine(Fmt: "bytes of callee saved registers = {0}, exception handler addr " |
689 | "= {1}" , |
690 | Items&: FP.BytesOfCalleeSavedRegisters, |
691 | Items: formatSegmentOffset(Segment: FP.SectionIdOfExceptionHandler, |
692 | Offset: FP.OffsetOfExceptionHandler)); |
693 | P.formatLine( |
694 | Fmt: "local fp reg = {0}, param fp reg = {1}" , |
695 | Items: formatRegisterId(Id: FP.getLocalFramePtrReg(CPU: CompilationCPU), Cpu: CompilationCPU), |
696 | Items: formatRegisterId(Id: FP.getParamFramePtrReg(CPU: CompilationCPU), Cpu: CompilationCPU)); |
697 | P.formatLine(Fmt: "flags = {0}" , |
698 | Items: formatFrameProcedureOptions(IndentLevel: P.getIndentLevel() + 9, FPO: FP.Flags)); |
699 | return Error::success(); |
700 | } |
701 | |
702 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
703 | HeapAllocationSiteSym &HAS) { |
704 | AutoIndent Indent(P, 7); |
705 | P.formatLine(Fmt: "type = {0}, addr = {1} call size = {2}" , Items: typeIndex(TI: HAS.Type), |
706 | Items: formatSegmentOffset(Segment: HAS.Segment, Offset: HAS.CodeOffset), |
707 | Items&: HAS.CallInstructionSize); |
708 | return Error::success(); |
709 | } |
710 | |
711 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, InlineSiteSym &IS) { |
712 | AutoIndent Indent(P, 7); |
713 | P.formatLine(Fmt: "inlinee = {0}, parent = {1}, end = {2}" , Items: idIndex(TI: IS.Inlinee), |
714 | Items&: IS.Parent, Items&: IS.End); |
715 | |
716 | // Break down the annotation byte code and calculate code and line offsets. |
717 | // FIXME: It would be helpful if we could look up the initial file and inlinee |
718 | // lines offset using the inlinee index above. |
719 | uint32_t CodeOffset = 0; |
720 | int32_t LineOffset = 0; |
721 | for (auto &Annot : IS.annotations()) { |
722 | P.formatLine(Fmt: " {0}" , Items: fmt_align(Item: toHex(Input: Annot.Bytes), Where: AlignStyle::Left, Amount: 9)); |
723 | |
724 | auto formatCodeOffset = [&](uint32_t Delta) { |
725 | CodeOffset += Delta; |
726 | P.format(Fmt: " code 0x{0} (+0x{1})" , Items: utohexstr(X: CodeOffset), Items: utohexstr(X: Delta)); |
727 | }; |
728 | auto formatCodeLength = [&](uint32_t Length) { |
729 | // Notably, changing the code length does not affect the code offset. |
730 | P.format(Fmt: " code end 0x{0} (+0x{1})" , Items: utohexstr(X: CodeOffset + Length), |
731 | Items: utohexstr(X: Length)); |
732 | }; |
733 | auto formatLineOffset = [&](int32_t Delta) { |
734 | LineOffset += Delta; |
735 | char Sign = Delta > 0 ? '+' : '-'; |
736 | P.format(Fmt: " line {0} ({1}{2})" , Items&: LineOffset, Items&: Sign, Items: std::abs(x: Delta)); |
737 | }; |
738 | |
739 | // Use the opcode to interpret the integer values. |
740 | switch (Annot.OpCode) { |
741 | case BinaryAnnotationsOpCode::Invalid: |
742 | break; |
743 | case BinaryAnnotationsOpCode::CodeOffset: |
744 | case BinaryAnnotationsOpCode::ChangeCodeOffset: |
745 | formatCodeOffset(Annot.U1); |
746 | break; |
747 | case BinaryAnnotationsOpCode::ChangeLineOffset: |
748 | formatLineOffset(Annot.S1); |
749 | break; |
750 | case BinaryAnnotationsOpCode::ChangeCodeLength: |
751 | formatCodeLength(Annot.U1); |
752 | // Apparently this annotation updates the code offset. It's hard to make |
753 | // MSVC produce this opcode, but clang uses it, and debuggers seem to use |
754 | // this interpretation. |
755 | CodeOffset += Annot.U1; |
756 | break; |
757 | case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: |
758 | formatCodeOffset(Annot.U1); |
759 | formatLineOffset(Annot.S1); |
760 | break; |
761 | case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: |
762 | formatCodeOffset(Annot.U2); |
763 | formatCodeLength(Annot.U1); |
764 | break; |
765 | |
766 | case BinaryAnnotationsOpCode::ChangeFile: { |
767 | uint32_t FileOffset = Annot.U1; |
768 | StringRef Filename = "<unknown>" ; |
769 | if (SymGroup) { |
770 | if (Expected<StringRef> MaybeFile = |
771 | SymGroup->getNameFromStringTable(Offset: FileOffset)) |
772 | Filename = *MaybeFile; |
773 | else |
774 | return MaybeFile.takeError(); |
775 | } |
776 | P.format(Fmt: " setfile {0} 0x{1}" , Items: utohexstr(X: FileOffset)); |
777 | break; |
778 | } |
779 | |
780 | // The rest of these are hard to convince MSVC to emit, so they are not as |
781 | // well understood. |
782 | case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: |
783 | formatCodeOffset(Annot.U1); |
784 | break; |
785 | case BinaryAnnotationsOpCode::ChangeLineEndDelta: |
786 | case BinaryAnnotationsOpCode::ChangeRangeKind: |
787 | case BinaryAnnotationsOpCode::ChangeColumnStart: |
788 | case BinaryAnnotationsOpCode::ChangeColumnEnd: |
789 | P.format(Fmt: " {0} {1}" , Items: Annot.Name, Items: Annot.U1); |
790 | break; |
791 | case BinaryAnnotationsOpCode::ChangeColumnEndDelta: |
792 | P.format(Fmt: " {0} {1}" , Items: Annot.Name, Items: Annot.S1); |
793 | break; |
794 | } |
795 | } |
796 | return Error::success(); |
797 | } |
798 | |
799 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
800 | RegisterSym &Register) { |
801 | P.format(Fmt: " `{0}`" , Items&: Register.Name); |
802 | AutoIndent Indent(P, 7); |
803 | P.formatLine(Fmt: "register = {0}, type = {1}" , |
804 | Items: formatRegisterId(Id: Register.Register, Cpu: CompilationCPU), |
805 | Items: typeIndex(TI: Register.Index)); |
806 | return Error::success(); |
807 | } |
808 | |
809 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
810 | PublicSym32 &Public) { |
811 | P.format(Fmt: " `{0}`" , Items&: Public.Name); |
812 | AutoIndent Indent(P, 7); |
813 | P.formatLine(Fmt: "flags = {0}, addr = {1}" , |
814 | Items: formatPublicSymFlags(IndentLevel: P.getIndentLevel() + 9, Flags: Public.Flags), |
815 | Items: formatSegmentOffset(Segment: Public.Segment, Offset: Public.Offset)); |
816 | return Error::success(); |
817 | } |
818 | |
819 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcRefSym &PR) { |
820 | P.format(Fmt: " `{0}`" , Items&: PR.Name); |
821 | AutoIndent Indent(P, 7); |
822 | P.formatLine(Fmt: "module = {0}, sum name = {1}, offset = {2}" , Items&: PR.Module, |
823 | Items&: PR.SumName, Items&: PR.SymOffset); |
824 | return Error::success(); |
825 | } |
826 | |
827 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) { |
828 | P.format(Fmt: " `{0}` (addr = {1})" , Items&: Label.Name, |
829 | Items: formatSegmentOffset(Segment: Label.Segment, Offset: Label.CodeOffset)); |
830 | AutoIndent Indent(P, 7); |
831 | P.formatLine(Fmt: "flags = {0}" , |
832 | Items: formatProcSymFlags(IndentLevel: P.getIndentLevel() + 9, Flags: Label.Flags)); |
833 | return Error::success(); |
834 | } |
835 | |
836 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) { |
837 | P.format(Fmt: " `{0}`" , Items&: Local.Name); |
838 | AutoIndent Indent(P, 7); |
839 | |
840 | std::string FlagStr = |
841 | formatLocalSymFlags(IndentLevel: P.getIndentLevel() + 9, Flags: Local.Flags); |
842 | P.formatLine(Fmt: "type={0}, flags = {1}" , Items: typeIndex(TI: Local.Type), Items&: FlagStr); |
843 | return Error::success(); |
844 | } |
845 | |
846 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
847 | ObjNameSym &ObjName) { |
848 | P.format(Fmt: " sig={0}, `{1}`" , Items&: ObjName.Signature, Items&: ObjName.Name); |
849 | return Error::success(); |
850 | } |
851 | |
852 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) { |
853 | P.format(Fmt: " `{0}`" , Items&: Proc.Name); |
854 | AutoIndent Indent(P, 7); |
855 | P.formatLine(Fmt: "parent = {0}, end = {1}, addr = {2}, code size = {3}" , |
856 | Items&: Proc.Parent, Items&: Proc.End, |
857 | Items: formatSegmentOffset(Segment: Proc.Segment, Offset: Proc.CodeOffset), |
858 | Items&: Proc.CodeSize); |
859 | bool IsType = true; |
860 | switch (Proc.getKind()) { |
861 | case SymbolRecordKind::GlobalProcIdSym: |
862 | case SymbolRecordKind::ProcIdSym: |
863 | case SymbolRecordKind::DPCProcIdSym: |
864 | IsType = false; |
865 | break; |
866 | default: |
867 | break; |
868 | } |
869 | P.formatLine(Fmt: "type = `{0}`, debug start = {1}, debug end = {2}, flags = {3}" , |
870 | Items: typeOrIdIndex(TI: Proc.FunctionType, IsType), Items&: Proc.DbgStart, |
871 | Items&: Proc.DbgEnd, |
872 | Items: formatProcSymFlags(IndentLevel: P.getIndentLevel() + 9, Flags: Proc.Flags)); |
873 | return Error::success(); |
874 | } |
875 | |
876 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
877 | ScopeEndSym &ScopeEnd) { |
878 | return Error::success(); |
879 | } |
880 | |
881 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) { |
882 | const char *Format; |
883 | switch (CVR.kind()) { |
884 | case S_CALLEES: |
885 | Format = "callee: {0}" ; |
886 | break; |
887 | case S_CALLERS: |
888 | Format = "caller: {0}" ; |
889 | break; |
890 | case S_INLINEES: |
891 | Format = "inlinee: {0}" ; |
892 | break; |
893 | default: |
894 | return llvm::make_error<CodeViewError>( |
895 | Args: "Unknown CV Record type for a CallerSym object!" ); |
896 | } |
897 | AutoIndent Indent(P, 7); |
898 | for (const auto &I : Caller.Indices) { |
899 | P.formatLine(Fmt: Format, Items: idIndex(TI: I)); |
900 | } |
901 | return Error::success(); |
902 | } |
903 | |
904 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
905 | RegRelativeSym &RegRel) { |
906 | P.format(Fmt: " `{0}`" , Items&: RegRel.Name); |
907 | AutoIndent Indent(P, 7); |
908 | P.formatLine( |
909 | Fmt: "type = {0}, register = {1}, offset = {2}" , Items: typeIndex(TI: RegRel.Type), |
910 | Items: formatRegisterId(Id: RegRel.Register, Cpu: CompilationCPU), Items&: RegRel.Offset); |
911 | return Error::success(); |
912 | } |
913 | |
914 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
915 | ThreadLocalDataSym &Data) { |
916 | P.format(Fmt: " `{0}`" , Items&: Data.Name); |
917 | AutoIndent Indent(P, 7); |
918 | P.formatLine(Fmt: "type = {0}, addr = {1}" , Items: typeIndex(TI: Data.Type), |
919 | Items: formatSegmentOffset(Segment: Data.Segment, Offset: Data.DataOffset)); |
920 | return Error::success(); |
921 | } |
922 | |
923 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) { |
924 | P.format(Fmt: " `{0}`" , Items&: UDT.Name); |
925 | AutoIndent Indent(P, 7); |
926 | P.formatLine(Fmt: "original type = {0}" , Items&: UDT.Type); |
927 | return Error::success(); |
928 | } |
929 | |
930 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
931 | UsingNamespaceSym &UN) { |
932 | P.format(Fmt: " `{0}`" , Items&: UN.Name); |
933 | return Error::success(); |
934 | } |
935 | |
936 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
937 | AnnotationSym &Annot) { |
938 | AutoIndent Indent(P, 7); |
939 | P.formatLine(Fmt: "addr = {0}" , Items: formatSegmentOffset(Segment: Annot.Segment, Offset: Annot.CodeOffset)); |
940 | P.formatLine(Fmt: "strings = {0}" , Items: typesetStringList(IndentLevel: P.getIndentLevel() + 9 + 2, |
941 | Strings: Annot.Strings)); |
942 | return Error::success(); |
943 | } |
944 | |
945 | Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, |
946 | JumpTableSym &JumpTable) { |
947 | AutoIndent Indent(P, 7); |
948 | P.formatLine( |
949 | Fmt: "base = {0}, switchtype = {1}, branch = {2}, table = {3}, entriescount = " |
950 | "{4}" , |
951 | Items: formatSegmentOffset(Segment: JumpTable.BaseSegment, Offset: JumpTable.BaseOffset), |
952 | Items: formatJumpTableEntrySize(EntrySize: JumpTable.SwitchType), |
953 | Items: formatSegmentOffset(Segment: JumpTable.BranchSegment, Offset: JumpTable.BranchOffset), |
954 | Items: formatSegmentOffset(Segment: JumpTable.TableSegment, Offset: JumpTable.TableOffset), |
955 | Items&: JumpTable.EntriesCount); |
956 | return Error::success(); |
957 | } |
958 | |