1 //===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- C++ -*-===//
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 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
10 #include "llvm/ADT/SmallString.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"
23 #include <system_error>
26 using namespace llvm::codeview
;
29 /// Use this private dumper implementation to keep implementation details about
30 /// the visitor out of SymbolDumper.h.
31 class CVSymbolDumperImpl
: public SymbolVisitorCallbacks
{
33 CVSymbolDumperImpl(TypeCollection
&Types
, SymbolDumpDelegate
*ObjDelegate
,
34 ScopedPrinter
&W
, CPUType CPU
, bool PrintRecordBytes
)
35 : Types(Types
), ObjDelegate(ObjDelegate
), W(W
), CompilationCPUType(CPU
),
36 PrintRecordBytes(PrintRecordBytes
), InFunctionScope(false) {}
38 /// CVSymbolVisitor overrides.
39 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
40 Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
41 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
42 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
44 Error
visitSymbolBegin(CVSymbol
&Record
) override
;
45 Error
visitSymbolEnd(CVSymbol
&Record
) override
;
46 Error
visitUnknownSymbol(CVSymbol
&Record
) override
;
48 CPUType
getCompilationCPUType() const { return CompilationCPUType
; }
51 void printLocalVariableAddrRange(const LocalVariableAddrRange
&Range
,
52 uint32_t RelocationOffset
);
53 void printLocalVariableAddrGap(ArrayRef
<LocalVariableAddrGap
> Gaps
);
54 void printTypeIndex(StringRef FieldName
, TypeIndex TI
);
56 TypeCollection
&Types
;
57 SymbolDumpDelegate
*ObjDelegate
;
60 /// Save the machine or CPU type when dumping a compile symbols.
61 CPUType CompilationCPUType
= CPUType::X64
;
63 bool PrintRecordBytes
;
68 static StringRef
getSymbolKindName(SymbolKind Kind
) {
70 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
73 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
80 void CVSymbolDumperImpl::printLocalVariableAddrRange(
81 const LocalVariableAddrRange
&Range
, uint32_t RelocationOffset
) {
82 DictScope
S(W
, "LocalVariableAddrRange");
84 ObjDelegate
->printRelocatedField("OffsetStart", RelocationOffset
,
86 W
.printHex("ISectStart", Range
.ISectStart
);
87 W
.printHex("Range", Range
.Range
);
90 void CVSymbolDumperImpl::printLocalVariableAddrGap(
91 ArrayRef
<LocalVariableAddrGap
> Gaps
) {
92 for (auto &Gap
: Gaps
) {
93 ListScope
S(W
, "LocalVariableAddrGap");
94 W
.printHex("GapStartOffset", Gap
.GapStartOffset
);
95 W
.printHex("Range", Gap
.Range
);
99 void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName
, TypeIndex TI
) {
100 codeview::printTypeIndex(W
, FieldName
, TI
, Types
);
103 Error
CVSymbolDumperImpl::visitSymbolBegin(CVSymbol
&CVR
) {
104 W
.startLine() << getSymbolKindName(CVR
.kind());
105 W
.getOStream() << " {\n";
107 W
.printEnum("Kind", unsigned(CVR
.kind()), getSymbolTypeNames());
108 return Error::success();
111 Error
CVSymbolDumperImpl::visitSymbolEnd(CVSymbol
&CVR
) {
112 if (PrintRecordBytes
&& ObjDelegate
)
113 ObjDelegate
->printBinaryBlockWithRelocs("SymData", CVR
.content());
116 W
.startLine() << "}\n";
117 return Error::success();
120 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, BlockSym
&Block
) {
121 StringRef LinkageName
;
122 W
.printHex("PtrParent", Block
.Parent
);
123 W
.printHex("PtrEnd", Block
.End
);
124 W
.printHex("CodeSize", Block
.CodeSize
);
126 ObjDelegate
->printRelocatedField("CodeOffset", Block
.getRelocationOffset(),
127 Block
.CodeOffset
, &LinkageName
);
129 W
.printHex("Segment", Block
.Segment
);
130 W
.printString("BlockName", Block
.Name
);
131 W
.printString("LinkageName", LinkageName
);
132 return Error::success();
135 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, Thunk32Sym
&Thunk
) {
136 W
.printString("Name", Thunk
.Name
);
137 W
.printNumber("Parent", Thunk
.Parent
);
138 W
.printNumber("End", Thunk
.End
);
139 W
.printNumber("Next", Thunk
.Next
);
140 W
.printNumber("Off", Thunk
.Offset
);
141 W
.printNumber("Seg", Thunk
.Segment
);
142 W
.printNumber("Len", Thunk
.Length
);
143 W
.printEnum("Ordinal", uint8_t(Thunk
.Thunk
), getThunkOrdinalNames());
144 return Error::success();
147 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
148 TrampolineSym
&Tramp
) {
149 W
.printEnum("Type", uint16_t(Tramp
.Type
), getTrampolineNames());
150 W
.printNumber("Size", Tramp
.Size
);
151 W
.printNumber("ThunkOff", Tramp
.ThunkOffset
);
152 W
.printNumber("TargetOff", Tramp
.TargetOffset
);
153 W
.printNumber("ThunkSection", Tramp
.ThunkSection
);
154 W
.printNumber("TargetSection", Tramp
.TargetSection
);
155 return Error::success();
158 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, SectionSym
&Section
) {
159 W
.printNumber("SectionNumber", Section
.SectionNumber
);
160 W
.printNumber("Alignment", Section
.Alignment
);
161 W
.printNumber("Rva", Section
.Rva
);
162 W
.printNumber("Length", Section
.Length
);
163 W
.printFlags("Characteristics", Section
.Characteristics
,
164 getImageSectionCharacteristicNames(),
165 COFF::SectionCharacteristics(0x00F00000));
167 W
.printString("Name", Section
.Name
);
168 return Error::success();
171 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
172 CoffGroupSym
&CoffGroup
) {
173 W
.printNumber("Size", CoffGroup
.Size
);
174 W
.printFlags("Characteristics", CoffGroup
.Characteristics
,
175 getImageSectionCharacteristicNames(),
176 COFF::SectionCharacteristics(0x00F00000));
177 W
.printNumber("Offset", CoffGroup
.Offset
);
178 W
.printNumber("Segment", CoffGroup
.Segment
);
179 W
.printString("Name", CoffGroup
.Name
);
180 return Error::success();
183 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
184 BPRelativeSym
&BPRel
) {
185 W
.printNumber("Offset", BPRel
.Offset
);
186 printTypeIndex("Type", BPRel
.Type
);
187 W
.printString("VarName", BPRel
.Name
);
188 return Error::success();
191 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
192 BuildInfoSym
&BuildInfo
) {
193 printTypeIndex("BuildId", BuildInfo
.BuildId
);
194 return Error::success();
197 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
198 CallSiteInfoSym
&CallSiteInfo
) {
199 StringRef LinkageName
;
201 ObjDelegate
->printRelocatedField("CodeOffset",
202 CallSiteInfo
.getRelocationOffset(),
203 CallSiteInfo
.CodeOffset
, &LinkageName
);
205 W
.printHex("Segment", CallSiteInfo
.Segment
);
206 printTypeIndex("Type", CallSiteInfo
.Type
);
207 if (!LinkageName
.empty())
208 W
.printString("LinkageName", LinkageName
);
209 return Error::success();
212 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
213 EnvBlockSym
&EnvBlock
) {
214 ListScope
L(W
, "Entries");
215 for (auto Entry
: EnvBlock
.Fields
) {
216 W
.printString(Entry
);
218 return Error::success();
221 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
222 FileStaticSym
&FileStatic
) {
223 printTypeIndex("Index", FileStatic
.Index
);
224 W
.printNumber("ModFilenameOffset", FileStatic
.ModFilenameOffset
);
225 W
.printFlags("Flags", uint16_t(FileStatic
.Flags
), getLocalFlagNames());
226 W
.printString("Name", FileStatic
.Name
);
227 return Error::success();
230 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ExportSym
&Export
) {
231 W
.printNumber("Ordinal", Export
.Ordinal
);
232 W
.printFlags("Flags", uint16_t(Export
.Flags
), getExportSymFlagNames());
233 W
.printString("Name", Export
.Name
);
234 return Error::success();
237 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
238 Compile2Sym
&Compile2
) {
239 W
.printEnum("Language", Compile2
.getLanguage(), getSourceLanguageNames());
240 W
.printFlags("Flags", Compile2
.getFlags(), getCompileSym2FlagNames());
241 W
.printEnum("Machine", unsigned(Compile2
.Machine
), getCPUTypeNames());
242 CompilationCPUType
= Compile2
.Machine
;
243 std::string FrontendVersion
;
245 raw_string_ostream
Out(FrontendVersion
);
246 Out
<< Compile2
.VersionFrontendMajor
<< '.' << Compile2
.VersionFrontendMinor
247 << '.' << Compile2
.VersionFrontendBuild
;
249 std::string BackendVersion
;
251 raw_string_ostream
Out(BackendVersion
);
252 Out
<< Compile2
.VersionBackendMajor
<< '.' << Compile2
.VersionBackendMinor
253 << '.' << Compile2
.VersionBackendBuild
;
255 W
.printString("FrontendVersion", FrontendVersion
);
256 W
.printString("BackendVersion", BackendVersion
);
257 W
.printString("VersionName", Compile2
.Version
);
258 return Error::success();
261 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
262 Compile3Sym
&Compile3
) {
263 W
.printEnum("Language", uint8_t(Compile3
.getLanguage()), getSourceLanguageNames());
264 W
.printFlags("Flags", uint32_t(Compile3
.getFlags()),
265 getCompileSym3FlagNames());
266 W
.printEnum("Machine", unsigned(Compile3
.Machine
), getCPUTypeNames());
267 CompilationCPUType
= Compile3
.Machine
;
268 std::string FrontendVersion
;
270 raw_string_ostream
Out(FrontendVersion
);
271 Out
<< Compile3
.VersionFrontendMajor
<< '.' << Compile3
.VersionFrontendMinor
272 << '.' << Compile3
.VersionFrontendBuild
<< '.'
273 << Compile3
.VersionFrontendQFE
;
275 std::string BackendVersion
;
277 raw_string_ostream
Out(BackendVersion
);
278 Out
<< Compile3
.VersionBackendMajor
<< '.' << Compile3
.VersionBackendMinor
279 << '.' << Compile3
.VersionBackendBuild
<< '.'
280 << Compile3
.VersionBackendQFE
;
282 W
.printString("FrontendVersion", FrontendVersion
);
283 W
.printString("BackendVersion", BackendVersion
);
284 W
.printString("VersionName", Compile3
.Version
);
285 return Error::success();
288 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
289 ConstantSym
&Constant
) {
290 printTypeIndex("Type", Constant
.Type
);
291 W
.printNumber("Value", Constant
.Value
);
292 W
.printString("Name", Constant
.Name
);
293 return Error::success();
296 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, DataSym
&Data
) {
297 StringRef LinkageName
;
299 ObjDelegate
->printRelocatedField("DataOffset", Data
.getRelocationOffset(),
300 Data
.DataOffset
, &LinkageName
);
302 printTypeIndex("Type", Data
.Type
);
303 W
.printString("DisplayName", Data
.Name
);
304 if (!LinkageName
.empty())
305 W
.printString("LinkageName", LinkageName
);
306 return Error::success();
309 Error
CVSymbolDumperImpl::visitKnownRecord(
311 DefRangeFramePointerRelFullScopeSym
&DefRangeFramePointerRelFullScope
) {
312 W
.printNumber("Offset", DefRangeFramePointerRelFullScope
.Offset
);
313 return Error::success();
316 Error
CVSymbolDumperImpl::visitKnownRecord(
317 CVSymbol
&CVR
, DefRangeFramePointerRelSym
&DefRangeFramePointerRel
) {
318 W
.printNumber("Offset", DefRangeFramePointerRel
.Hdr
.Offset
);
319 printLocalVariableAddrRange(DefRangeFramePointerRel
.Range
,
320 DefRangeFramePointerRel
.getRelocationOffset());
321 printLocalVariableAddrGap(DefRangeFramePointerRel
.Gaps
);
322 return Error::success();
325 Error
CVSymbolDumperImpl::visitKnownRecord(
326 CVSymbol
&CVR
, DefRangeRegisterRelSym
&DefRangeRegisterRel
) {
327 W
.printEnum("BaseRegister", uint16_t(DefRangeRegisterRel
.Hdr
.Register
),
328 getRegisterNames(CompilationCPUType
));
329 W
.printBoolean("HasSpilledUDTMember",
330 DefRangeRegisterRel
.hasSpilledUDTMember());
331 W
.printNumber("OffsetInParent", DefRangeRegisterRel
.offsetInParent());
332 W
.printNumber("BasePointerOffset", DefRangeRegisterRel
.Hdr
.BasePointerOffset
);
333 printLocalVariableAddrRange(DefRangeRegisterRel
.Range
,
334 DefRangeRegisterRel
.getRelocationOffset());
335 printLocalVariableAddrGap(DefRangeRegisterRel
.Gaps
);
336 return Error::success();
339 Error
CVSymbolDumperImpl::visitKnownRecord(
340 CVSymbol
&CVR
, DefRangeRegisterSym
&DefRangeRegister
) {
341 W
.printEnum("Register", uint16_t(DefRangeRegister
.Hdr
.Register
),
342 getRegisterNames(CompilationCPUType
));
343 W
.printNumber("MayHaveNoName", DefRangeRegister
.Hdr
.MayHaveNoName
);
344 printLocalVariableAddrRange(DefRangeRegister
.Range
,
345 DefRangeRegister
.getRelocationOffset());
346 printLocalVariableAddrGap(DefRangeRegister
.Gaps
);
347 return Error::success();
350 Error
CVSymbolDumperImpl::visitKnownRecord(
351 CVSymbol
&CVR
, DefRangeSubfieldRegisterSym
&DefRangeSubfieldRegister
) {
352 W
.printEnum("Register", uint16_t(DefRangeSubfieldRegister
.Hdr
.Register
),
353 getRegisterNames(CompilationCPUType
));
354 W
.printNumber("MayHaveNoName", DefRangeSubfieldRegister
.Hdr
.MayHaveNoName
);
355 W
.printNumber("OffsetInParent", DefRangeSubfieldRegister
.Hdr
.OffsetInParent
);
356 printLocalVariableAddrRange(DefRangeSubfieldRegister
.Range
,
357 DefRangeSubfieldRegister
.getRelocationOffset());
358 printLocalVariableAddrGap(DefRangeSubfieldRegister
.Gaps
);
359 return Error::success();
362 Error
CVSymbolDumperImpl::visitKnownRecord(
363 CVSymbol
&CVR
, DefRangeSubfieldSym
&DefRangeSubfield
) {
365 DebugStringTableSubsectionRef Strings
= ObjDelegate
->getStringTable();
366 auto ExpectedProgram
= Strings
.getString(DefRangeSubfield
.Program
);
367 if (!ExpectedProgram
) {
368 consumeError(ExpectedProgram
.takeError());
369 return llvm::make_error
<CodeViewError
>(
370 "String table offset outside of bounds of String Table!");
372 W
.printString("Program", *ExpectedProgram
);
374 W
.printNumber("OffsetInParent", DefRangeSubfield
.OffsetInParent
);
375 printLocalVariableAddrRange(DefRangeSubfield
.Range
,
376 DefRangeSubfield
.getRelocationOffset());
377 printLocalVariableAddrGap(DefRangeSubfield
.Gaps
);
378 return Error::success();
381 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
382 DefRangeSym
&DefRange
) {
384 DebugStringTableSubsectionRef Strings
= ObjDelegate
->getStringTable();
385 auto ExpectedProgram
= Strings
.getString(DefRange
.Program
);
386 if (!ExpectedProgram
) {
387 consumeError(ExpectedProgram
.takeError());
388 return llvm::make_error
<CodeViewError
>(
389 "String table offset outside of bounds of String Table!");
391 W
.printString("Program", *ExpectedProgram
);
393 printLocalVariableAddrRange(DefRange
.Range
, DefRange
.getRelocationOffset());
394 printLocalVariableAddrGap(DefRange
.Gaps
);
395 return Error::success();
398 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
399 FrameCookieSym
&FrameCookie
) {
400 StringRef LinkageName
;
402 ObjDelegate
->printRelocatedField("CodeOffset",
403 FrameCookie
.getRelocationOffset(),
404 FrameCookie
.CodeOffset
, &LinkageName
);
406 W
.printEnum("Register", uint16_t(FrameCookie
.Register
),
407 getRegisterNames(CompilationCPUType
));
408 W
.printEnum("CookieKind", uint16_t(FrameCookie
.CookieKind
),
409 getFrameCookieKindNames());
410 W
.printHex("Flags", FrameCookie
.Flags
);
411 return Error::success();
414 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
415 FrameProcSym
&FrameProc
) {
416 W
.printHex("TotalFrameBytes", FrameProc
.TotalFrameBytes
);
417 W
.printHex("PaddingFrameBytes", FrameProc
.PaddingFrameBytes
);
418 W
.printHex("OffsetToPadding", FrameProc
.OffsetToPadding
);
419 W
.printHex("BytesOfCalleeSavedRegisters",
420 FrameProc
.BytesOfCalleeSavedRegisters
);
421 W
.printHex("OffsetOfExceptionHandler", FrameProc
.OffsetOfExceptionHandler
);
422 W
.printHex("SectionIdOfExceptionHandler",
423 FrameProc
.SectionIdOfExceptionHandler
);
424 W
.printFlags("Flags", static_cast<uint32_t>(FrameProc
.Flags
),
425 getFrameProcSymFlagNames());
426 W
.printEnum("LocalFramePtrReg",
427 uint16_t(FrameProc
.getLocalFramePtrReg(CompilationCPUType
)),
428 getRegisterNames(CompilationCPUType
));
429 W
.printEnum("ParamFramePtrReg",
430 uint16_t(FrameProc
.getParamFramePtrReg(CompilationCPUType
)),
431 getRegisterNames(CompilationCPUType
));
432 return Error::success();
435 Error
CVSymbolDumperImpl::visitKnownRecord(
436 CVSymbol
&CVR
, HeapAllocationSiteSym
&HeapAllocSite
) {
437 StringRef LinkageName
;
439 ObjDelegate
->printRelocatedField("CodeOffset",
440 HeapAllocSite
.getRelocationOffset(),
441 HeapAllocSite
.CodeOffset
, &LinkageName
);
443 W
.printHex("Segment", HeapAllocSite
.Segment
);
444 W
.printHex("CallInstructionSize", HeapAllocSite
.CallInstructionSize
);
445 printTypeIndex("Type", HeapAllocSite
.Type
);
446 if (!LinkageName
.empty())
447 W
.printString("LinkageName", LinkageName
);
448 return Error::success();
451 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
452 InlineSiteSym
&InlineSite
) {
453 W
.printHex("PtrParent", InlineSite
.Parent
);
454 W
.printHex("PtrEnd", InlineSite
.End
);
455 printTypeIndex("Inlinee", InlineSite
.Inlinee
);
457 ListScope
BinaryAnnotations(W
, "BinaryAnnotations");
458 for (auto &Annotation
: InlineSite
.annotations()) {
459 switch (Annotation
.OpCode
) {
460 case BinaryAnnotationsOpCode::Invalid
:
461 W
.printString("(Annotation Padding)");
463 case BinaryAnnotationsOpCode::CodeOffset
:
464 case BinaryAnnotationsOpCode::ChangeCodeOffset
:
465 case BinaryAnnotationsOpCode::ChangeCodeLength
:
466 W
.printHex(Annotation
.Name
, Annotation
.U1
);
468 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase
:
469 case BinaryAnnotationsOpCode::ChangeLineEndDelta
:
470 case BinaryAnnotationsOpCode::ChangeRangeKind
:
471 case BinaryAnnotationsOpCode::ChangeColumnStart
:
472 case BinaryAnnotationsOpCode::ChangeColumnEnd
:
473 W
.printNumber(Annotation
.Name
, Annotation
.U1
);
475 case BinaryAnnotationsOpCode::ChangeLineOffset
:
476 case BinaryAnnotationsOpCode::ChangeColumnEndDelta
:
477 W
.printNumber(Annotation
.Name
, Annotation
.S1
);
479 case BinaryAnnotationsOpCode::ChangeFile
:
481 W
.printHex("ChangeFile",
482 ObjDelegate
->getFileNameForFileOffset(Annotation
.U1
),
485 W
.printHex("ChangeFile", Annotation
.U1
);
489 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset
: {
490 W
.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
491 << W
.hex(Annotation
.U1
) << ", LineOffset: " << Annotation
.S1
495 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset
: {
496 W
.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
497 << W
.hex(Annotation
.U2
)
498 << ", Length: " << W
.hex(Annotation
.U1
) << "}\n";
503 return Error::success();
506 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
507 RegisterSym
&Register
) {
508 printTypeIndex("Type", Register
.Index
);
509 W
.printEnum("Seg", uint16_t(Register
.Register
),
510 getRegisterNames(CompilationCPUType
));
511 W
.printString("Name", Register
.Name
);
512 return Error::success();
515 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, PublicSym32
&Public
) {
516 W
.printFlags("Flags", uint32_t(Public
.Flags
), getPublicSymFlagNames());
517 W
.printNumber("Seg", Public
.Segment
);
518 W
.printNumber("Off", Public
.Offset
);
519 W
.printString("Name", Public
.Name
);
520 return Error::success();
523 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ProcRefSym
&ProcRef
) {
524 W
.printNumber("SumName", ProcRef
.SumName
);
525 W
.printNumber("SymOffset", ProcRef
.SymOffset
);
526 W
.printNumber("Mod", ProcRef
.Module
);
527 W
.printString("Name", ProcRef
.Name
);
528 return Error::success();
531 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, LabelSym
&Label
) {
532 StringRef LinkageName
;
534 ObjDelegate
->printRelocatedField("CodeOffset", Label
.getRelocationOffset(),
535 Label
.CodeOffset
, &LinkageName
);
537 W
.printHex("Segment", Label
.Segment
);
538 W
.printHex("Flags", uint8_t(Label
.Flags
));
539 W
.printFlags("Flags", uint8_t(Label
.Flags
), getProcSymFlagNames());
540 W
.printString("DisplayName", Label
.Name
);
541 if (!LinkageName
.empty())
542 W
.printString("LinkageName", LinkageName
);
543 return Error::success();
546 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, LocalSym
&Local
) {
547 printTypeIndex("Type", Local
.Type
);
548 W
.printFlags("Flags", uint16_t(Local
.Flags
), getLocalFlagNames());
549 W
.printString("VarName", Local
.Name
);
550 return Error::success();
553 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ObjNameSym
&ObjName
) {
554 W
.printHex("Signature", ObjName
.Signature
);
555 W
.printString("ObjectName", ObjName
.Name
);
556 return Error::success();
559 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ProcSym
&Proc
) {
561 return llvm::make_error
<CodeViewError
>(
562 "Visiting a ProcSym while inside function scope!");
564 InFunctionScope
= true;
566 StringRef LinkageName
;
567 W
.printHex("PtrParent", Proc
.Parent
);
568 W
.printHex("PtrEnd", Proc
.End
);
569 W
.printHex("PtrNext", Proc
.Next
);
570 W
.printHex("CodeSize", Proc
.CodeSize
);
571 W
.printHex("DbgStart", Proc
.DbgStart
);
572 W
.printHex("DbgEnd", Proc
.DbgEnd
);
573 printTypeIndex("FunctionType", Proc
.FunctionType
);
575 ObjDelegate
->printRelocatedField("CodeOffset", Proc
.getRelocationOffset(),
576 Proc
.CodeOffset
, &LinkageName
);
578 W
.printHex("Segment", Proc
.Segment
);
579 W
.printFlags("Flags", static_cast<uint8_t>(Proc
.Flags
),
580 getProcSymFlagNames());
581 W
.printString("DisplayName", Proc
.Name
);
582 if (!LinkageName
.empty())
583 W
.printString("LinkageName", LinkageName
);
584 return Error::success();
587 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
588 ScopeEndSym
&ScopeEnd
) {
589 InFunctionScope
= false;
590 return Error::success();
593 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, CallerSym
&Caller
) {
594 ListScope
S(W
, CVR
.kind() == S_CALLEES
? "Callees" : "Callers");
595 for (auto FuncID
: Caller
.Indices
)
596 printTypeIndex("FuncID", FuncID
);
597 return Error::success();
600 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
601 RegRelativeSym
&RegRel
) {
602 W
.printHex("Offset", RegRel
.Offset
);
603 printTypeIndex("Type", RegRel
.Type
);
604 W
.printEnum("Register", uint16_t(RegRel
.Register
),
605 getRegisterNames(CompilationCPUType
));
606 W
.printString("VarName", RegRel
.Name
);
607 return Error::success();
610 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
611 ThreadLocalDataSym
&Data
) {
612 StringRef LinkageName
;
614 ObjDelegate
->printRelocatedField("DataOffset", Data
.getRelocationOffset(),
615 Data
.DataOffset
, &LinkageName
);
617 printTypeIndex("Type", Data
.Type
);
618 W
.printString("DisplayName", Data
.Name
);
619 if (!LinkageName
.empty())
620 W
.printString("LinkageName", LinkageName
);
621 return Error::success();
624 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, UDTSym
&UDT
) {
625 printTypeIndex("Type", UDT
.Type
);
626 W
.printString("UDTName", UDT
.Name
);
627 return Error::success();
630 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
631 UsingNamespaceSym
&UN
) {
632 W
.printString("Namespace", UN
.Name
);
633 return Error::success();
636 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
637 AnnotationSym
&Annot
) {
638 W
.printHex("Offset", Annot
.CodeOffset
);
639 W
.printHex("Segment", Annot
.Segment
);
641 ListScope
S(W
, "Strings");
642 for (StringRef Str
: Annot
.Strings
)
645 return Error::success();
648 Error
CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol
&CVR
) {
649 W
.printNumber("Length", CVR
.length());
650 return Error::success();
653 Error
CVSymbolDumper::dump(CVRecord
<SymbolKind
> &Record
) {
654 SymbolVisitorCallbackPipeline Pipeline
;
655 SymbolDeserializer
Deserializer(ObjDelegate
.get(), Container
);
656 CVSymbolDumperImpl
Dumper(Types
, ObjDelegate
.get(), W
, CompilationCPUType
,
659 Pipeline
.addCallbackToPipeline(Deserializer
);
660 Pipeline
.addCallbackToPipeline(Dumper
);
661 CVSymbolVisitor
Visitor(Pipeline
);
662 auto Err
= Visitor
.visitSymbolRecord(Record
);
663 CompilationCPUType
= Dumper
.getCompilationCPUType();
667 Error
CVSymbolDumper::dump(const CVSymbolArray
&Symbols
) {
668 SymbolVisitorCallbackPipeline Pipeline
;
669 SymbolDeserializer
Deserializer(ObjDelegate
.get(), Container
);
670 CVSymbolDumperImpl
Dumper(Types
, ObjDelegate
.get(), W
, CompilationCPUType
,
673 Pipeline
.addCallbackToPipeline(Deserializer
);
674 Pipeline
.addCallbackToPipeline(Dumper
);
675 CVSymbolVisitor
Visitor(Pipeline
);
676 auto Err
= Visitor
.visitSymbolStream(Symbols
);
677 CompilationCPUType
= Dumper
.getCompilationCPUType();