1 | //===-- SymbolDumper.cpp - CodeView symbol info 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 "llvm/DebugInfo/CodeView/SymbolDumper.h" |
10 | #include "llvm/ADT/StringRef.h" |
11 | #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" |
12 | #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" |
13 | #include "llvm/DebugInfo/CodeView/EnumTables.h" |
14 | #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" |
15 | #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" |
16 | #include "llvm/DebugInfo/CodeView/SymbolRecord.h" |
17 | #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h" |
18 | #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" |
19 | #include "llvm/DebugInfo/CodeView/TypeIndex.h" |
20 | #include "llvm/Support/Error.h" |
21 | #include "llvm/Support/ScopedPrinter.h" |
22 | |
23 | using namespace llvm; |
24 | using namespace llvm::codeview; |
25 | |
26 | namespace { |
27 | /// Use this private dumper implementation to keep implementation details about |
28 | /// the visitor out of SymbolDumper.h. |
29 | class CVSymbolDumperImpl : public SymbolVisitorCallbacks { |
30 | public: |
31 | CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate, |
32 | ScopedPrinter &W, CPUType CPU, bool PrintRecordBytes) |
33 | : Types(Types), ObjDelegate(ObjDelegate), W(W), CompilationCPUType(CPU), |
34 | PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {} |
35 | |
36 | /// CVSymbolVisitor overrides. |
37 | #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ |
38 | Error visitKnownRecord(CVSymbol &CVR, Name &Record) override; |
39 | #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) |
40 | #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" |
41 | |
42 | Error visitSymbolBegin(CVSymbol &Record) override; |
43 | Error visitSymbolEnd(CVSymbol &Record) override; |
44 | Error visitUnknownSymbol(CVSymbol &Record) override; |
45 | |
46 | CPUType getCompilationCPUType() const { return CompilationCPUType; } |
47 | |
48 | private: |
49 | void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, |
50 | uint32_t RelocationOffset); |
51 | void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps); |
52 | void printTypeIndex(StringRef FieldName, TypeIndex TI); |
53 | |
54 | TypeCollection &Types; |
55 | SymbolDumpDelegate *ObjDelegate; |
56 | ScopedPrinter &W; |
57 | |
58 | /// Save the machine or CPU type when dumping a compile symbols. |
59 | CPUType CompilationCPUType = CPUType::X64; |
60 | |
61 | bool PrintRecordBytes; |
62 | bool InFunctionScope; |
63 | }; |
64 | } |
65 | |
66 | static StringRef getSymbolKindName(SymbolKind Kind) { |
67 | switch (Kind) { |
68 | #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ |
69 | case EnumName: \ |
70 | return #Name; |
71 | #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" |
72 | default: |
73 | break; |
74 | } |
75 | return "UnknownSym" ; |
76 | } |
77 | |
78 | void CVSymbolDumperImpl::printLocalVariableAddrRange( |
79 | const LocalVariableAddrRange &Range, uint32_t RelocationOffset) { |
80 | DictScope S(W, "LocalVariableAddrRange" ); |
81 | if (ObjDelegate) |
82 | ObjDelegate->printRelocatedField(Label: "OffsetStart" , RelocOffset: RelocationOffset, |
83 | Offset: Range.OffsetStart); |
84 | W.printHex(Label: "ISectStart" , Value: Range.ISectStart); |
85 | W.printHex(Label: "Range" , Value: Range.Range); |
86 | } |
87 | |
88 | void CVSymbolDumperImpl::printLocalVariableAddrGap( |
89 | ArrayRef<LocalVariableAddrGap> Gaps) { |
90 | for (auto &Gap : Gaps) { |
91 | ListScope S(W, "LocalVariableAddrGap" ); |
92 | W.printHex(Label: "GapStartOffset" , Value: Gap.GapStartOffset); |
93 | W.printHex(Label: "Range" , Value: Gap.Range); |
94 | } |
95 | } |
96 | |
97 | void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) { |
98 | codeview::printTypeIndex(Printer&: W, FieldName, TI, Types); |
99 | } |
100 | |
101 | Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) { |
102 | W.startLine() << getSymbolKindName(Kind: CVR.kind()); |
103 | W.getOStream() << " {\n" ; |
104 | W.indent(); |
105 | W.printEnum(Label: "Kind" , Value: unsigned(CVR.kind()), EnumValues: getSymbolTypeNames()); |
106 | return Error::success(); |
107 | } |
108 | |
109 | Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) { |
110 | if (PrintRecordBytes && ObjDelegate) |
111 | ObjDelegate->printBinaryBlockWithRelocs(Label: "SymData" , Block: CVR.content()); |
112 | |
113 | W.unindent(); |
114 | W.startLine() << "}\n" ; |
115 | return Error::success(); |
116 | } |
117 | |
118 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) { |
119 | StringRef LinkageName; |
120 | W.printHex(Label: "PtrParent" , Value: Block.Parent); |
121 | W.printHex(Label: "PtrEnd" , Value: Block.End); |
122 | W.printHex(Label: "CodeSize" , Value: Block.CodeSize); |
123 | if (ObjDelegate) { |
124 | ObjDelegate->printRelocatedField(Label: "CodeOffset" , RelocOffset: Block.getRelocationOffset(), |
125 | Offset: Block.CodeOffset, RelocSym: &LinkageName); |
126 | } |
127 | W.printHex(Label: "Segment" , Value: Block.Segment); |
128 | W.printString(Label: "BlockName" , Value: Block.Name); |
129 | W.printString(Label: "LinkageName" , Value: LinkageName); |
130 | return Error::success(); |
131 | } |
132 | |
133 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) { |
134 | W.printString(Label: "Name" , Value: Thunk.Name); |
135 | W.printNumber(Label: "Parent" , Value: Thunk.Parent); |
136 | W.printNumber(Label: "End" , Value: Thunk.End); |
137 | W.printNumber(Label: "Next" , Value: Thunk.Next); |
138 | W.printNumber(Label: "Off" , Value: Thunk.Offset); |
139 | W.printNumber(Label: "Seg" , Value: Thunk.Segment); |
140 | W.printNumber(Label: "Len" , Value: Thunk.Length); |
141 | W.printEnum(Label: "Ordinal" , Value: uint8_t(Thunk.Thunk), EnumValues: getThunkOrdinalNames()); |
142 | return Error::success(); |
143 | } |
144 | |
145 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
146 | TrampolineSym &Tramp) { |
147 | W.printEnum(Label: "Type" , Value: uint16_t(Tramp.Type), EnumValues: getTrampolineNames()); |
148 | W.printNumber(Label: "Size" , Value: Tramp.Size); |
149 | W.printNumber(Label: "ThunkOff" , Value: Tramp.ThunkOffset); |
150 | W.printNumber(Label: "TargetOff" , Value: Tramp.TargetOffset); |
151 | W.printNumber(Label: "ThunkSection" , Value: Tramp.ThunkSection); |
152 | W.printNumber(Label: "TargetSection" , Value: Tramp.TargetSection); |
153 | return Error::success(); |
154 | } |
155 | |
156 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) { |
157 | W.printNumber(Label: "SectionNumber" , Value: Section.SectionNumber); |
158 | W.printNumber(Label: "Alignment" , Value: Section.Alignment); |
159 | W.printNumber(Label: "Rva" , Value: Section.Rva); |
160 | W.printNumber(Label: "Length" , Value: Section.Length); |
161 | W.printFlags(Label: "Characteristics" , Value: Section.Characteristics, |
162 | Flags: getImageSectionCharacteristicNames(), |
163 | EnumMask1: COFF::SectionCharacteristics(0x00F00000)); |
164 | |
165 | W.printString(Label: "Name" , Value: Section.Name); |
166 | return Error::success(); |
167 | } |
168 | |
169 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
170 | CoffGroupSym &CoffGroup) { |
171 | W.printNumber(Label: "Size" , Value: CoffGroup.Size); |
172 | W.printFlags(Label: "Characteristics" , Value: CoffGroup.Characteristics, |
173 | Flags: getImageSectionCharacteristicNames(), |
174 | EnumMask1: COFF::SectionCharacteristics(0x00F00000)); |
175 | W.printNumber(Label: "Offset" , Value: CoffGroup.Offset); |
176 | W.printNumber(Label: "Segment" , Value: CoffGroup.Segment); |
177 | W.printString(Label: "Name" , Value: CoffGroup.Name); |
178 | return Error::success(); |
179 | } |
180 | |
181 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
182 | BPRelativeSym &BPRel) { |
183 | W.printNumber(Label: "Offset" , Value: BPRel.Offset); |
184 | printTypeIndex(FieldName: "Type" , TI: BPRel.Type); |
185 | W.printString(Label: "VarName" , Value: BPRel.Name); |
186 | return Error::success(); |
187 | } |
188 | |
189 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
190 | BuildInfoSym &BuildInfo) { |
191 | printTypeIndex(FieldName: "BuildId" , TI: BuildInfo.BuildId); |
192 | return Error::success(); |
193 | } |
194 | |
195 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
196 | CallSiteInfoSym &CallSiteInfo) { |
197 | StringRef LinkageName; |
198 | if (ObjDelegate) { |
199 | ObjDelegate->printRelocatedField(Label: "CodeOffset" , |
200 | RelocOffset: CallSiteInfo.getRelocationOffset(), |
201 | Offset: CallSiteInfo.CodeOffset, RelocSym: &LinkageName); |
202 | } |
203 | W.printHex(Label: "Segment" , Value: CallSiteInfo.Segment); |
204 | printTypeIndex(FieldName: "Type" , TI: CallSiteInfo.Type); |
205 | if (!LinkageName.empty()) |
206 | W.printString(Label: "LinkageName" , Value: LinkageName); |
207 | return Error::success(); |
208 | } |
209 | |
210 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
211 | EnvBlockSym &EnvBlock) { |
212 | ListScope L(W, "Entries" ); |
213 | for (auto Entry : EnvBlock.Fields) { |
214 | W.printString(Value: Entry); |
215 | } |
216 | return Error::success(); |
217 | } |
218 | |
219 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
220 | FileStaticSym &FileStatic) { |
221 | printTypeIndex(FieldName: "Index" , TI: FileStatic.Index); |
222 | W.printNumber(Label: "ModFilenameOffset" , Value: FileStatic.ModFilenameOffset); |
223 | W.printFlags(Label: "Flags" , Value: uint16_t(FileStatic.Flags), Flags: getLocalFlagNames()); |
224 | W.printString(Label: "Name" , Value: FileStatic.Name); |
225 | return Error::success(); |
226 | } |
227 | |
228 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) { |
229 | W.printNumber(Label: "Ordinal" , Value: Export.Ordinal); |
230 | W.printFlags(Label: "Flags" , Value: uint16_t(Export.Flags), Flags: getExportSymFlagNames()); |
231 | W.printString(Label: "Name" , Value: Export.Name); |
232 | return Error::success(); |
233 | } |
234 | |
235 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
236 | Compile2Sym &Compile2) { |
237 | W.printEnum(Label: "Language" , Value: Compile2.getLanguage(), EnumValues: getSourceLanguageNames()); |
238 | W.printFlags(Label: "Flags" , Value: Compile2.getFlags(), Flags: getCompileSym2FlagNames()); |
239 | W.printEnum(Label: "Machine" , Value: unsigned(Compile2.Machine), EnumValues: getCPUTypeNames()); |
240 | CompilationCPUType = Compile2.Machine; |
241 | std::string FrontendVersion; |
242 | { |
243 | raw_string_ostream Out(FrontendVersion); |
244 | Out << Compile2.VersionFrontendMajor << '.' << Compile2.VersionFrontendMinor |
245 | << '.' << Compile2.VersionFrontendBuild; |
246 | } |
247 | std::string BackendVersion; |
248 | { |
249 | raw_string_ostream Out(BackendVersion); |
250 | Out << Compile2.VersionBackendMajor << '.' << Compile2.VersionBackendMinor |
251 | << '.' << Compile2.VersionBackendBuild; |
252 | } |
253 | W.printString(Label: "FrontendVersion" , Value: FrontendVersion); |
254 | W.printString(Label: "BackendVersion" , Value: BackendVersion); |
255 | W.printString(Label: "VersionName" , Value: Compile2.Version); |
256 | return Error::success(); |
257 | } |
258 | |
259 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
260 | Compile3Sym &Compile3) { |
261 | W.printEnum(Label: "Language" , Value: uint8_t(Compile3.getLanguage()), EnumValues: getSourceLanguageNames()); |
262 | W.printFlags(Label: "Flags" , Value: uint32_t(Compile3.getFlags()), |
263 | Flags: getCompileSym3FlagNames()); |
264 | W.printEnum(Label: "Machine" , Value: unsigned(Compile3.Machine), EnumValues: getCPUTypeNames()); |
265 | CompilationCPUType = Compile3.Machine; |
266 | std::string FrontendVersion; |
267 | { |
268 | raw_string_ostream Out(FrontendVersion); |
269 | Out << Compile3.VersionFrontendMajor << '.' << Compile3.VersionFrontendMinor |
270 | << '.' << Compile3.VersionFrontendBuild << '.' |
271 | << Compile3.VersionFrontendQFE; |
272 | } |
273 | std::string BackendVersion; |
274 | { |
275 | raw_string_ostream Out(BackendVersion); |
276 | Out << Compile3.VersionBackendMajor << '.' << Compile3.VersionBackendMinor |
277 | << '.' << Compile3.VersionBackendBuild << '.' |
278 | << Compile3.VersionBackendQFE; |
279 | } |
280 | W.printString(Label: "FrontendVersion" , Value: FrontendVersion); |
281 | W.printString(Label: "BackendVersion" , Value: BackendVersion); |
282 | W.printString(Label: "VersionName" , Value: Compile3.Version); |
283 | return Error::success(); |
284 | } |
285 | |
286 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
287 | ConstantSym &Constant) { |
288 | printTypeIndex(FieldName: "Type" , TI: Constant.Type); |
289 | W.printNumber(Label: "Value" , Value: Constant.Value); |
290 | W.printString(Label: "Name" , Value: Constant.Name); |
291 | return Error::success(); |
292 | } |
293 | |
294 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) { |
295 | StringRef LinkageName; |
296 | if (ObjDelegate) { |
297 | ObjDelegate->printRelocatedField(Label: "DataOffset" , RelocOffset: Data.getRelocationOffset(), |
298 | Offset: Data.DataOffset, RelocSym: &LinkageName); |
299 | } |
300 | printTypeIndex(FieldName: "Type" , TI: Data.Type); |
301 | W.printString(Label: "DisplayName" , Value: Data.Name); |
302 | if (!LinkageName.empty()) |
303 | W.printString(Label: "LinkageName" , Value: LinkageName); |
304 | return Error::success(); |
305 | } |
306 | |
307 | Error CVSymbolDumperImpl::visitKnownRecord( |
308 | CVSymbol &CVR, |
309 | DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { |
310 | W.printNumber(Label: "Offset" , Value: DefRangeFramePointerRelFullScope.Offset); |
311 | return Error::success(); |
312 | } |
313 | |
314 | Error CVSymbolDumperImpl::visitKnownRecord( |
315 | CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { |
316 | W.printNumber(Label: "Offset" , Value: DefRangeFramePointerRel.Hdr.Offset); |
317 | printLocalVariableAddrRange(Range: DefRangeFramePointerRel.Range, |
318 | RelocationOffset: DefRangeFramePointerRel.getRelocationOffset()); |
319 | printLocalVariableAddrGap(Gaps: DefRangeFramePointerRel.Gaps); |
320 | return Error::success(); |
321 | } |
322 | |
323 | Error CVSymbolDumperImpl::visitKnownRecord( |
324 | CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) { |
325 | W.printEnum(Label: "BaseRegister" , Value: uint16_t(DefRangeRegisterRel.Hdr.Register), |
326 | EnumValues: getRegisterNames(Cpu: CompilationCPUType)); |
327 | W.printBoolean(Label: "HasSpilledUDTMember" , |
328 | Value: DefRangeRegisterRel.hasSpilledUDTMember()); |
329 | W.printNumber(Label: "OffsetInParent" , Value: DefRangeRegisterRel.offsetInParent()); |
330 | W.printNumber(Label: "BasePointerOffset" , Value: DefRangeRegisterRel.Hdr.BasePointerOffset); |
331 | printLocalVariableAddrRange(Range: DefRangeRegisterRel.Range, |
332 | RelocationOffset: DefRangeRegisterRel.getRelocationOffset()); |
333 | printLocalVariableAddrGap(Gaps: DefRangeRegisterRel.Gaps); |
334 | return Error::success(); |
335 | } |
336 | |
337 | Error CVSymbolDumperImpl::visitKnownRecord( |
338 | CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) { |
339 | W.printEnum(Label: "Register" , Value: uint16_t(DefRangeRegister.Hdr.Register), |
340 | EnumValues: getRegisterNames(Cpu: CompilationCPUType)); |
341 | W.printNumber(Label: "MayHaveNoName" , Value: DefRangeRegister.Hdr.MayHaveNoName); |
342 | printLocalVariableAddrRange(Range: DefRangeRegister.Range, |
343 | RelocationOffset: DefRangeRegister.getRelocationOffset()); |
344 | printLocalVariableAddrGap(Gaps: DefRangeRegister.Gaps); |
345 | return Error::success(); |
346 | } |
347 | |
348 | Error CVSymbolDumperImpl::visitKnownRecord( |
349 | CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) { |
350 | W.printEnum(Label: "Register" , Value: uint16_t(DefRangeSubfieldRegister.Hdr.Register), |
351 | EnumValues: getRegisterNames(Cpu: CompilationCPUType)); |
352 | W.printNumber(Label: "MayHaveNoName" , Value: DefRangeSubfieldRegister.Hdr.MayHaveNoName); |
353 | W.printNumber(Label: "OffsetInParent" , Value: DefRangeSubfieldRegister.Hdr.OffsetInParent); |
354 | printLocalVariableAddrRange(Range: DefRangeSubfieldRegister.Range, |
355 | RelocationOffset: DefRangeSubfieldRegister.getRelocationOffset()); |
356 | printLocalVariableAddrGap(Gaps: DefRangeSubfieldRegister.Gaps); |
357 | return Error::success(); |
358 | } |
359 | |
360 | Error CVSymbolDumperImpl::visitKnownRecord( |
361 | CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) { |
362 | if (ObjDelegate) { |
363 | DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); |
364 | auto ExpectedProgram = Strings.getString(Offset: DefRangeSubfield.Program); |
365 | if (!ExpectedProgram) { |
366 | consumeError(Err: ExpectedProgram.takeError()); |
367 | return llvm::make_error<CodeViewError>( |
368 | Args: "String table offset outside of bounds of String Table!" ); |
369 | } |
370 | W.printString(Label: "Program" , Value: *ExpectedProgram); |
371 | } |
372 | W.printNumber(Label: "OffsetInParent" , Value: DefRangeSubfield.OffsetInParent); |
373 | printLocalVariableAddrRange(Range: DefRangeSubfield.Range, |
374 | RelocationOffset: DefRangeSubfield.getRelocationOffset()); |
375 | printLocalVariableAddrGap(Gaps: DefRangeSubfield.Gaps); |
376 | return Error::success(); |
377 | } |
378 | |
379 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
380 | DefRangeSym &DefRange) { |
381 | if (ObjDelegate) { |
382 | DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); |
383 | auto ExpectedProgram = Strings.getString(Offset: DefRange.Program); |
384 | if (!ExpectedProgram) { |
385 | consumeError(Err: ExpectedProgram.takeError()); |
386 | return llvm::make_error<CodeViewError>( |
387 | Args: "String table offset outside of bounds of String Table!" ); |
388 | } |
389 | W.printString(Label: "Program" , Value: *ExpectedProgram); |
390 | } |
391 | printLocalVariableAddrRange(Range: DefRange.Range, RelocationOffset: DefRange.getRelocationOffset()); |
392 | printLocalVariableAddrGap(Gaps: DefRange.Gaps); |
393 | return Error::success(); |
394 | } |
395 | |
396 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
397 | FrameCookieSym &FrameCookie) { |
398 | StringRef LinkageName; |
399 | if (ObjDelegate) { |
400 | ObjDelegate->printRelocatedField(Label: "CodeOffset" , |
401 | RelocOffset: FrameCookie.getRelocationOffset(), |
402 | Offset: FrameCookie.CodeOffset, RelocSym: &LinkageName); |
403 | } |
404 | W.printEnum(Label: "Register" , Value: uint16_t(FrameCookie.Register), |
405 | EnumValues: getRegisterNames(Cpu: CompilationCPUType)); |
406 | W.printEnum(Label: "CookieKind" , Value: uint16_t(FrameCookie.CookieKind), |
407 | EnumValues: getFrameCookieKindNames()); |
408 | W.printHex(Label: "Flags" , Value: FrameCookie.Flags); |
409 | return Error::success(); |
410 | } |
411 | |
412 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
413 | FrameProcSym &FrameProc) { |
414 | W.printHex(Label: "TotalFrameBytes" , Value: FrameProc.TotalFrameBytes); |
415 | W.printHex(Label: "PaddingFrameBytes" , Value: FrameProc.PaddingFrameBytes); |
416 | W.printHex(Label: "OffsetToPadding" , Value: FrameProc.OffsetToPadding); |
417 | W.printHex(Label: "BytesOfCalleeSavedRegisters" , |
418 | Value: FrameProc.BytesOfCalleeSavedRegisters); |
419 | W.printHex(Label: "OffsetOfExceptionHandler" , Value: FrameProc.OffsetOfExceptionHandler); |
420 | W.printHex(Label: "SectionIdOfExceptionHandler" , |
421 | Value: FrameProc.SectionIdOfExceptionHandler); |
422 | W.printFlags(Label: "Flags" , Value: static_cast<uint32_t>(FrameProc.Flags), |
423 | Flags: getFrameProcSymFlagNames()); |
424 | W.printEnum(Label: "LocalFramePtrReg" , |
425 | Value: uint16_t(FrameProc.getLocalFramePtrReg(CPU: CompilationCPUType)), |
426 | EnumValues: getRegisterNames(Cpu: CompilationCPUType)); |
427 | W.printEnum(Label: "ParamFramePtrReg" , |
428 | Value: uint16_t(FrameProc.getParamFramePtrReg(CPU: CompilationCPUType)), |
429 | EnumValues: getRegisterNames(Cpu: CompilationCPUType)); |
430 | return Error::success(); |
431 | } |
432 | |
433 | Error CVSymbolDumperImpl::visitKnownRecord( |
434 | CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) { |
435 | StringRef LinkageName; |
436 | if (ObjDelegate) { |
437 | ObjDelegate->printRelocatedField(Label: "CodeOffset" , |
438 | RelocOffset: HeapAllocSite.getRelocationOffset(), |
439 | Offset: HeapAllocSite.CodeOffset, RelocSym: &LinkageName); |
440 | } |
441 | W.printHex(Label: "Segment" , Value: HeapAllocSite.Segment); |
442 | W.printHex(Label: "CallInstructionSize" , Value: HeapAllocSite.CallInstructionSize); |
443 | printTypeIndex(FieldName: "Type" , TI: HeapAllocSite.Type); |
444 | if (!LinkageName.empty()) |
445 | W.printString(Label: "LinkageName" , Value: LinkageName); |
446 | return Error::success(); |
447 | } |
448 | |
449 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
450 | InlineSiteSym &InlineSite) { |
451 | W.printHex(Label: "PtrParent" , Value: InlineSite.Parent); |
452 | W.printHex(Label: "PtrEnd" , Value: InlineSite.End); |
453 | printTypeIndex(FieldName: "Inlinee" , TI: InlineSite.Inlinee); |
454 | |
455 | ListScope BinaryAnnotations(W, "BinaryAnnotations" ); |
456 | for (auto &Annotation : InlineSite.annotations()) { |
457 | switch (Annotation.OpCode) { |
458 | case BinaryAnnotationsOpCode::Invalid: |
459 | W.printString(Value: "(Annotation Padding)" ); |
460 | break; |
461 | case BinaryAnnotationsOpCode::CodeOffset: |
462 | case BinaryAnnotationsOpCode::ChangeCodeOffset: |
463 | case BinaryAnnotationsOpCode::ChangeCodeLength: |
464 | W.printHex(Label: Annotation.Name, Value: Annotation.U1); |
465 | break; |
466 | case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: |
467 | case BinaryAnnotationsOpCode::ChangeLineEndDelta: |
468 | case BinaryAnnotationsOpCode::ChangeRangeKind: |
469 | case BinaryAnnotationsOpCode::ChangeColumnStart: |
470 | case BinaryAnnotationsOpCode::ChangeColumnEnd: |
471 | W.printNumber(Label: Annotation.Name, Value: Annotation.U1); |
472 | break; |
473 | case BinaryAnnotationsOpCode::ChangeLineOffset: |
474 | case BinaryAnnotationsOpCode::ChangeColumnEndDelta: |
475 | W.printNumber(Label: Annotation.Name, Value: Annotation.S1); |
476 | break; |
477 | case BinaryAnnotationsOpCode::ChangeFile: |
478 | if (ObjDelegate) { |
479 | W.printHex(Label: "ChangeFile" , |
480 | Str: ObjDelegate->getFileNameForFileOffset(FileOffset: Annotation.U1), |
481 | Value: Annotation.U1); |
482 | } else { |
483 | W.printHex(Label: "ChangeFile" , Value: Annotation.U1); |
484 | } |
485 | |
486 | break; |
487 | case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: { |
488 | W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: " |
489 | << W.hex(Value: Annotation.U1) << ", LineOffset: " << Annotation.S1 |
490 | << "}\n" ; |
491 | break; |
492 | } |
493 | case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: { |
494 | W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: " |
495 | << W.hex(Value: Annotation.U2) |
496 | << ", Length: " << W.hex(Value: Annotation.U1) << "}\n" ; |
497 | break; |
498 | } |
499 | } |
500 | } |
501 | return Error::success(); |
502 | } |
503 | |
504 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
505 | RegisterSym &Register) { |
506 | printTypeIndex(FieldName: "Type" , TI: Register.Index); |
507 | W.printEnum(Label: "Seg" , Value: uint16_t(Register.Register), |
508 | EnumValues: getRegisterNames(Cpu: CompilationCPUType)); |
509 | W.printString(Label: "Name" , Value: Register.Name); |
510 | return Error::success(); |
511 | } |
512 | |
513 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) { |
514 | W.printFlags(Label: "Flags" , Value: uint32_t(Public.Flags), Flags: getPublicSymFlagNames()); |
515 | W.printNumber(Label: "Seg" , Value: Public.Segment); |
516 | W.printNumber(Label: "Off" , Value: Public.Offset); |
517 | W.printString(Label: "Name" , Value: Public.Name); |
518 | return Error::success(); |
519 | } |
520 | |
521 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) { |
522 | W.printNumber(Label: "SumName" , Value: ProcRef.SumName); |
523 | W.printNumber(Label: "SymOffset" , Value: ProcRef.SymOffset); |
524 | W.printNumber(Label: "Mod" , Value: ProcRef.Module); |
525 | W.printString(Label: "Name" , Value: ProcRef.Name); |
526 | return Error::success(); |
527 | } |
528 | |
529 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) { |
530 | StringRef LinkageName; |
531 | if (ObjDelegate) { |
532 | ObjDelegate->printRelocatedField(Label: "CodeOffset" , RelocOffset: Label.getRelocationOffset(), |
533 | Offset: Label.CodeOffset, RelocSym: &LinkageName); |
534 | } |
535 | W.printHex(Label: "Segment" , Value: Label.Segment); |
536 | W.printHex(Label: "Flags" , Value: uint8_t(Label.Flags)); |
537 | W.printFlags(Label: "Flags" , Value: uint8_t(Label.Flags), Flags: getProcSymFlagNames()); |
538 | W.printString(Label: "DisplayName" , Value: Label.Name); |
539 | if (!LinkageName.empty()) |
540 | W.printString(Label: "LinkageName" , Value: LinkageName); |
541 | return Error::success(); |
542 | } |
543 | |
544 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) { |
545 | printTypeIndex(FieldName: "Type" , TI: Local.Type); |
546 | W.printFlags(Label: "Flags" , Value: uint16_t(Local.Flags), Flags: getLocalFlagNames()); |
547 | W.printString(Label: "VarName" , Value: Local.Name); |
548 | return Error::success(); |
549 | } |
550 | |
551 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) { |
552 | W.printHex(Label: "Signature" , Value: ObjName.Signature); |
553 | W.printString(Label: "ObjectName" , Value: ObjName.Name); |
554 | return Error::success(); |
555 | } |
556 | |
557 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) { |
558 | if (InFunctionScope) |
559 | return llvm::make_error<CodeViewError>( |
560 | Args: "Visiting a ProcSym while inside function scope!" ); |
561 | |
562 | InFunctionScope = true; |
563 | |
564 | StringRef LinkageName; |
565 | W.printHex(Label: "PtrParent" , Value: Proc.Parent); |
566 | W.printHex(Label: "PtrEnd" , Value: Proc.End); |
567 | W.printHex(Label: "PtrNext" , Value: Proc.Next); |
568 | W.printHex(Label: "CodeSize" , Value: Proc.CodeSize); |
569 | W.printHex(Label: "DbgStart" , Value: Proc.DbgStart); |
570 | W.printHex(Label: "DbgEnd" , Value: Proc.DbgEnd); |
571 | printTypeIndex(FieldName: "FunctionType" , TI: Proc.FunctionType); |
572 | if (ObjDelegate) { |
573 | ObjDelegate->printRelocatedField(Label: "CodeOffset" , RelocOffset: Proc.getRelocationOffset(), |
574 | Offset: Proc.CodeOffset, RelocSym: &LinkageName); |
575 | } |
576 | W.printHex(Label: "Segment" , Value: Proc.Segment); |
577 | W.printFlags(Label: "Flags" , Value: static_cast<uint8_t>(Proc.Flags), |
578 | Flags: getProcSymFlagNames()); |
579 | W.printString(Label: "DisplayName" , Value: Proc.Name); |
580 | if (!LinkageName.empty()) |
581 | W.printString(Label: "LinkageName" , Value: LinkageName); |
582 | return Error::success(); |
583 | } |
584 | |
585 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
586 | ScopeEndSym &ScopeEnd) { |
587 | InFunctionScope = false; |
588 | return Error::success(); |
589 | } |
590 | |
591 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) { |
592 | llvm::StringRef ScopeName; |
593 | switch (CVR.kind()) { |
594 | case S_CALLEES: |
595 | ScopeName = "Callees" ; |
596 | break; |
597 | case S_CALLERS: |
598 | ScopeName = "Callers" ; |
599 | break; |
600 | case S_INLINEES: |
601 | ScopeName = "Inlinees" ; |
602 | break; |
603 | default: |
604 | return llvm::make_error<CodeViewError>( |
605 | Args: "Unknown CV Record type for a CallerSym object!" ); |
606 | } |
607 | ListScope S(W, ScopeName); |
608 | for (auto FuncID : Caller.Indices) |
609 | printTypeIndex(FieldName: "FuncID" , TI: FuncID); |
610 | return Error::success(); |
611 | } |
612 | |
613 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
614 | RegRelativeSym &RegRel) { |
615 | W.printHex(Label: "Offset" , Value: RegRel.Offset); |
616 | printTypeIndex(FieldName: "Type" , TI: RegRel.Type); |
617 | W.printEnum(Label: "Register" , Value: uint16_t(RegRel.Register), |
618 | EnumValues: getRegisterNames(Cpu: CompilationCPUType)); |
619 | W.printString(Label: "VarName" , Value: RegRel.Name); |
620 | return Error::success(); |
621 | } |
622 | |
623 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
624 | ThreadLocalDataSym &Data) { |
625 | StringRef LinkageName; |
626 | if (ObjDelegate) { |
627 | ObjDelegate->printRelocatedField(Label: "DataOffset" , RelocOffset: Data.getRelocationOffset(), |
628 | Offset: Data.DataOffset, RelocSym: &LinkageName); |
629 | } |
630 | printTypeIndex(FieldName: "Type" , TI: Data.Type); |
631 | W.printString(Label: "DisplayName" , Value: Data.Name); |
632 | if (!LinkageName.empty()) |
633 | W.printString(Label: "LinkageName" , Value: LinkageName); |
634 | return Error::success(); |
635 | } |
636 | |
637 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) { |
638 | printTypeIndex(FieldName: "Type" , TI: UDT.Type); |
639 | W.printString(Label: "UDTName" , Value: UDT.Name); |
640 | return Error::success(); |
641 | } |
642 | |
643 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
644 | UsingNamespaceSym &UN) { |
645 | W.printString(Label: "Namespace" , Value: UN.Name); |
646 | return Error::success(); |
647 | } |
648 | |
649 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
650 | AnnotationSym &Annot) { |
651 | W.printHex(Label: "Offset" , Value: Annot.CodeOffset); |
652 | W.printHex(Label: "Segment" , Value: Annot.Segment); |
653 | |
654 | ListScope S(W, "Strings" ); |
655 | for (StringRef Str : Annot.Strings) |
656 | W.printString(Value: Str); |
657 | |
658 | return Error::success(); |
659 | } |
660 | |
661 | Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, |
662 | JumpTableSym &JumpTable) { |
663 | W.printHex(Label: "BaseOffset" , Value: JumpTable.BaseOffset); |
664 | W.printNumber(Label: "BaseSegment" , Value: JumpTable.BaseSegment); |
665 | W.printEnum(Label: "SwitchType" , Value: static_cast<uint16_t>(JumpTable.SwitchType), |
666 | EnumValues: getJumpTableEntrySizeNames()); |
667 | W.printHex(Label: "BranchOffset" , Value: JumpTable.BranchOffset); |
668 | W.printHex(Label: "TableOffset" , Value: JumpTable.TableOffset); |
669 | W.printNumber(Label: "BranchSegment" , Value: JumpTable.BranchSegment); |
670 | W.printNumber(Label: "TableSegment" , Value: JumpTable.TableSegment); |
671 | W.printNumber(Label: "EntriesCount" , Value: JumpTable.EntriesCount); |
672 | return Error::success(); |
673 | } |
674 | |
675 | Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { |
676 | W.printNumber(Label: "Length" , Value: CVR.length()); |
677 | return Error::success(); |
678 | } |
679 | |
680 | Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) { |
681 | SymbolVisitorCallbackPipeline Pipeline; |
682 | SymbolDeserializer Deserializer(ObjDelegate.get(), Container); |
683 | CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, |
684 | PrintRecordBytes); |
685 | |
686 | Pipeline.addCallbackToPipeline(Callbacks&: Deserializer); |
687 | Pipeline.addCallbackToPipeline(Callbacks&: Dumper); |
688 | CVSymbolVisitor Visitor(Pipeline); |
689 | auto Err = Visitor.visitSymbolRecord(Record); |
690 | CompilationCPUType = Dumper.getCompilationCPUType(); |
691 | return Err; |
692 | } |
693 | |
694 | Error CVSymbolDumper::(const CVSymbolArray &Symbols) { |
695 | SymbolVisitorCallbackPipeline Pipeline; |
696 | SymbolDeserializer Deserializer(ObjDelegate.get(), Container); |
697 | CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, |
698 | PrintRecordBytes); |
699 | |
700 | Pipeline.addCallbackToPipeline(Callbacks&: Deserializer); |
701 | Pipeline.addCallbackToPipeline(Callbacks&: Dumper); |
702 | CVSymbolVisitor Visitor(Pipeline); |
703 | auto Err = Visitor.visitSymbolStream(Symbols); |
704 | CompilationCPUType = Dumper.getCompilationCPUType(); |
705 | return Err; |
706 | } |
707 | |