1 //===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
13 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
14 #include "llvm/DebugInfo/CodeView/EnumTables.h"
15 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
16 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
17 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
18 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
19 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
20 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
21 #include "llvm/Support/Error.h"
22 #include "llvm/Support/ScopedPrinter.h"
24 #include <system_error>
27 using namespace llvm::codeview
;
30 /// Use this private dumper implementation to keep implementation details about
31 /// the visitor out of SymbolDumper.h.
32 class CVSymbolDumperImpl
: public SymbolVisitorCallbacks
{
34 CVSymbolDumperImpl(TypeCollection
&Types
, SymbolDumpDelegate
*ObjDelegate
,
35 ScopedPrinter
&W
, CPUType CPU
, bool PrintRecordBytes
)
36 : Types(Types
), ObjDelegate(ObjDelegate
), W(W
), CompilationCPUType(CPU
),
37 PrintRecordBytes(PrintRecordBytes
), InFunctionScope(false) {}
39 /// CVSymbolVisitor overrides.
40 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
41 Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
42 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
43 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
45 Error
visitSymbolBegin(CVSymbol
&Record
) override
;
46 Error
visitSymbolEnd(CVSymbol
&Record
) override
;
47 Error
visitUnknownSymbol(CVSymbol
&Record
) override
;
49 CPUType
getCompilationCPUType() const { return CompilationCPUType
; }
52 void printLocalVariableAddrRange(const LocalVariableAddrRange
&Range
,
53 uint32_t RelocationOffset
);
54 void printLocalVariableAddrGap(ArrayRef
<LocalVariableAddrGap
> Gaps
);
55 void printTypeIndex(StringRef FieldName
, TypeIndex TI
);
57 TypeCollection
&Types
;
58 SymbolDumpDelegate
*ObjDelegate
;
61 /// Save the machine or CPU type when dumping a compile symbols.
62 CPUType CompilationCPUType
= CPUType::X64
;
64 bool PrintRecordBytes
;
69 static StringRef
getSymbolKindName(SymbolKind Kind
) {
71 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
74 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
81 void CVSymbolDumperImpl::printLocalVariableAddrRange(
82 const LocalVariableAddrRange
&Range
, uint32_t RelocationOffset
) {
83 DictScope
S(W
, "LocalVariableAddrRange");
85 ObjDelegate
->printRelocatedField("OffsetStart", RelocationOffset
,
87 W
.printHex("ISectStart", Range
.ISectStart
);
88 W
.printHex("Range", Range
.Range
);
91 void CVSymbolDumperImpl::printLocalVariableAddrGap(
92 ArrayRef
<LocalVariableAddrGap
> Gaps
) {
93 for (auto &Gap
: Gaps
) {
94 ListScope
S(W
, "LocalVariableAddrGap");
95 W
.printHex("GapStartOffset", Gap
.GapStartOffset
);
96 W
.printHex("Range", Gap
.Range
);
100 void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName
, TypeIndex TI
) {
101 codeview::printTypeIndex(W
, FieldName
, TI
, Types
);
104 Error
CVSymbolDumperImpl::visitSymbolBegin(CVSymbol
&CVR
) {
105 W
.startLine() << getSymbolKindName(CVR
.Type
);
106 W
.getOStream() << " {\n";
108 W
.printEnum("Kind", unsigned(CVR
.Type
), getSymbolTypeNames());
109 return Error::success();
112 Error
CVSymbolDumperImpl::visitSymbolEnd(CVSymbol
&CVR
) {
113 if (PrintRecordBytes
&& ObjDelegate
)
114 ObjDelegate
->printBinaryBlockWithRelocs("SymData", CVR
.content());
117 W
.startLine() << "}\n";
118 return Error::success();
121 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, BlockSym
&Block
) {
122 StringRef LinkageName
;
123 W
.printHex("PtrParent", Block
.Parent
);
124 W
.printHex("PtrEnd", Block
.End
);
125 W
.printHex("CodeSize", Block
.CodeSize
);
127 ObjDelegate
->printRelocatedField("CodeOffset", Block
.getRelocationOffset(),
128 Block
.CodeOffset
, &LinkageName
);
130 W
.printHex("Segment", Block
.Segment
);
131 W
.printString("BlockName", Block
.Name
);
132 W
.printString("LinkageName", LinkageName
);
133 return Error::success();
136 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, Thunk32Sym
&Thunk
) {
137 W
.printString("Name", Thunk
.Name
);
138 W
.printNumber("Parent", Thunk
.Parent
);
139 W
.printNumber("End", Thunk
.End
);
140 W
.printNumber("Next", Thunk
.Next
);
141 W
.printNumber("Off", Thunk
.Offset
);
142 W
.printNumber("Seg", Thunk
.Segment
);
143 W
.printNumber("Len", Thunk
.Length
);
144 W
.printEnum("Ordinal", uint8_t(Thunk
.Thunk
), getThunkOrdinalNames());
145 return Error::success();
148 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
149 TrampolineSym
&Tramp
) {
150 W
.printEnum("Type", uint16_t(Tramp
.Type
), getTrampolineNames());
151 W
.printNumber("Size", Tramp
.Size
);
152 W
.printNumber("ThunkOff", Tramp
.ThunkOffset
);
153 W
.printNumber("TargetOff", Tramp
.TargetOffset
);
154 W
.printNumber("ThunkSection", Tramp
.ThunkSection
);
155 W
.printNumber("TargetSection", Tramp
.TargetSection
);
156 return Error::success();
159 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, SectionSym
&Section
) {
160 W
.printNumber("SectionNumber", Section
.SectionNumber
);
161 W
.printNumber("Alignment", Section
.Alignment
);
162 W
.printNumber("Rva", Section
.Rva
);
163 W
.printNumber("Length", Section
.Length
);
164 W
.printFlags("Characteristics", Section
.Characteristics
,
165 getImageSectionCharacteristicNames(),
166 COFF::SectionCharacteristics(0x00F00000));
168 W
.printString("Name", Section
.Name
);
169 return Error::success();
172 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
173 CoffGroupSym
&CoffGroup
) {
174 W
.printNumber("Size", CoffGroup
.Size
);
175 W
.printFlags("Characteristics", CoffGroup
.Characteristics
,
176 getImageSectionCharacteristicNames(),
177 COFF::SectionCharacteristics(0x00F00000));
178 W
.printNumber("Offset", CoffGroup
.Offset
);
179 W
.printNumber("Segment", CoffGroup
.Segment
);
180 W
.printString("Name", CoffGroup
.Name
);
181 return Error::success();
184 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
185 BPRelativeSym
&BPRel
) {
186 W
.printNumber("Offset", BPRel
.Offset
);
187 printTypeIndex("Type", BPRel
.Type
);
188 W
.printString("VarName", BPRel
.Name
);
189 return Error::success();
192 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
193 BuildInfoSym
&BuildInfo
) {
194 printTypeIndex("BuildId", BuildInfo
.BuildId
);
195 return Error::success();
198 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
199 CallSiteInfoSym
&CallSiteInfo
) {
200 StringRef LinkageName
;
202 ObjDelegate
->printRelocatedField("CodeOffset",
203 CallSiteInfo
.getRelocationOffset(),
204 CallSiteInfo
.CodeOffset
, &LinkageName
);
206 W
.printHex("Segment", CallSiteInfo
.Segment
);
207 printTypeIndex("Type", CallSiteInfo
.Type
);
208 if (!LinkageName
.empty())
209 W
.printString("LinkageName", LinkageName
);
210 return Error::success();
213 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
214 EnvBlockSym
&EnvBlock
) {
215 ListScope
L(W
, "Entries");
216 for (auto Entry
: EnvBlock
.Fields
) {
217 W
.printString(Entry
);
219 return Error::success();
222 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
223 FileStaticSym
&FileStatic
) {
224 printTypeIndex("Index", FileStatic
.Index
);
225 W
.printNumber("ModFilenameOffset", FileStatic
.ModFilenameOffset
);
226 W
.printFlags("Flags", uint16_t(FileStatic
.Flags
), getLocalFlagNames());
227 W
.printString("Name", FileStatic
.Name
);
228 return Error::success();
231 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ExportSym
&Export
) {
232 W
.printNumber("Ordinal", Export
.Ordinal
);
233 W
.printFlags("Flags", uint16_t(Export
.Flags
), getExportSymFlagNames());
234 W
.printString("Name", Export
.Name
);
235 return Error::success();
238 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
239 Compile2Sym
&Compile2
) {
240 W
.printEnum("Language", Compile2
.getLanguage(), getSourceLanguageNames());
241 W
.printFlags("Flags", Compile2
.getFlags(), getCompileSym2FlagNames());
242 W
.printEnum("Machine", unsigned(Compile2
.Machine
), getCPUTypeNames());
243 CompilationCPUType
= Compile2
.Machine
;
244 std::string FrontendVersion
;
246 raw_string_ostream
Out(FrontendVersion
);
247 Out
<< Compile2
.VersionFrontendMajor
<< '.' << Compile2
.VersionFrontendMinor
248 << '.' << Compile2
.VersionFrontendBuild
;
250 std::string BackendVersion
;
252 raw_string_ostream
Out(BackendVersion
);
253 Out
<< Compile2
.VersionBackendMajor
<< '.' << Compile2
.VersionBackendMinor
254 << '.' << Compile2
.VersionBackendBuild
;
256 W
.printString("FrontendVersion", FrontendVersion
);
257 W
.printString("BackendVersion", BackendVersion
);
258 W
.printString("VersionName", Compile2
.Version
);
259 return Error::success();
262 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
263 Compile3Sym
&Compile3
) {
264 W
.printEnum("Language", uint8_t(Compile3
.getLanguage()), getSourceLanguageNames());
265 W
.printFlags("Flags", uint32_t(Compile3
.getFlags()),
266 getCompileSym3FlagNames());
267 W
.printEnum("Machine", unsigned(Compile3
.Machine
), getCPUTypeNames());
268 CompilationCPUType
= Compile3
.Machine
;
269 std::string FrontendVersion
;
271 raw_string_ostream
Out(FrontendVersion
);
272 Out
<< Compile3
.VersionFrontendMajor
<< '.' << Compile3
.VersionFrontendMinor
273 << '.' << Compile3
.VersionFrontendBuild
<< '.'
274 << Compile3
.VersionFrontendQFE
;
276 std::string BackendVersion
;
278 raw_string_ostream
Out(BackendVersion
);
279 Out
<< Compile3
.VersionBackendMajor
<< '.' << Compile3
.VersionBackendMinor
280 << '.' << Compile3
.VersionBackendBuild
<< '.'
281 << Compile3
.VersionBackendQFE
;
283 W
.printString("FrontendVersion", FrontendVersion
);
284 W
.printString("BackendVersion", BackendVersion
);
285 W
.printString("VersionName", Compile3
.Version
);
286 return Error::success();
289 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
290 ConstantSym
&Constant
) {
291 printTypeIndex("Type", Constant
.Type
);
292 W
.printNumber("Value", Constant
.Value
);
293 W
.printString("Name", Constant
.Name
);
294 return Error::success();
297 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, DataSym
&Data
) {
298 StringRef LinkageName
;
300 ObjDelegate
->printRelocatedField("DataOffset", Data
.getRelocationOffset(),
301 Data
.DataOffset
, &LinkageName
);
303 printTypeIndex("Type", Data
.Type
);
304 W
.printString("DisplayName", Data
.Name
);
305 if (!LinkageName
.empty())
306 W
.printString("LinkageName", LinkageName
);
307 return Error::success();
310 Error
CVSymbolDumperImpl::visitKnownRecord(
312 DefRangeFramePointerRelFullScopeSym
&DefRangeFramePointerRelFullScope
) {
313 W
.printNumber("Offset", DefRangeFramePointerRelFullScope
.Offset
);
314 return Error::success();
317 Error
CVSymbolDumperImpl::visitKnownRecord(
318 CVSymbol
&CVR
, DefRangeFramePointerRelSym
&DefRangeFramePointerRel
) {
319 W
.printNumber("Offset", DefRangeFramePointerRel
.Offset
);
320 printLocalVariableAddrRange(DefRangeFramePointerRel
.Range
,
321 DefRangeFramePointerRel
.getRelocationOffset());
322 printLocalVariableAddrGap(DefRangeFramePointerRel
.Gaps
);
323 return Error::success();
326 Error
CVSymbolDumperImpl::visitKnownRecord(
327 CVSymbol
&CVR
, DefRangeRegisterRelSym
&DefRangeRegisterRel
) {
328 W
.printEnum("BaseRegister", uint16_t(DefRangeRegisterRel
.Hdr
.Register
),
330 W
.printBoolean("HasSpilledUDTMember",
331 DefRangeRegisterRel
.hasSpilledUDTMember());
332 W
.printNumber("OffsetInParent", DefRangeRegisterRel
.offsetInParent());
333 W
.printNumber("BasePointerOffset", DefRangeRegisterRel
.Hdr
.BasePointerOffset
);
334 printLocalVariableAddrRange(DefRangeRegisterRel
.Range
,
335 DefRangeRegisterRel
.getRelocationOffset());
336 printLocalVariableAddrGap(DefRangeRegisterRel
.Gaps
);
337 return Error::success();
340 Error
CVSymbolDumperImpl::visitKnownRecord(
341 CVSymbol
&CVR
, DefRangeRegisterSym
&DefRangeRegister
) {
342 W
.printEnum("Register", uint16_t(DefRangeRegister
.Hdr
.Register
),
344 W
.printNumber("MayHaveNoName", DefRangeRegister
.Hdr
.MayHaveNoName
);
345 printLocalVariableAddrRange(DefRangeRegister
.Range
,
346 DefRangeRegister
.getRelocationOffset());
347 printLocalVariableAddrGap(DefRangeRegister
.Gaps
);
348 return Error::success();
351 Error
CVSymbolDumperImpl::visitKnownRecord(
352 CVSymbol
&CVR
, DefRangeSubfieldRegisterSym
&DefRangeSubfieldRegister
) {
353 W
.printEnum("Register", uint16_t(DefRangeSubfieldRegister
.Hdr
.Register
),
355 W
.printNumber("MayHaveNoName", DefRangeSubfieldRegister
.Hdr
.MayHaveNoName
);
356 W
.printNumber("OffsetInParent", DefRangeSubfieldRegister
.Hdr
.OffsetInParent
);
357 printLocalVariableAddrRange(DefRangeSubfieldRegister
.Range
,
358 DefRangeSubfieldRegister
.getRelocationOffset());
359 printLocalVariableAddrGap(DefRangeSubfieldRegister
.Gaps
);
360 return Error::success();
363 Error
CVSymbolDumperImpl::visitKnownRecord(
364 CVSymbol
&CVR
, DefRangeSubfieldSym
&DefRangeSubfield
) {
366 DebugStringTableSubsectionRef Strings
= ObjDelegate
->getStringTable();
367 auto ExpectedProgram
= Strings
.getString(DefRangeSubfield
.Program
);
368 if (!ExpectedProgram
) {
369 consumeError(ExpectedProgram
.takeError());
370 return llvm::make_error
<CodeViewError
>(
371 "String table offset outside of bounds of String Table!");
373 W
.printString("Program", *ExpectedProgram
);
375 W
.printNumber("OffsetInParent", DefRangeSubfield
.OffsetInParent
);
376 printLocalVariableAddrRange(DefRangeSubfield
.Range
,
377 DefRangeSubfield
.getRelocationOffset());
378 printLocalVariableAddrGap(DefRangeSubfield
.Gaps
);
379 return Error::success();
382 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
383 DefRangeSym
&DefRange
) {
385 DebugStringTableSubsectionRef Strings
= ObjDelegate
->getStringTable();
386 auto ExpectedProgram
= Strings
.getString(DefRange
.Program
);
387 if (!ExpectedProgram
) {
388 consumeError(ExpectedProgram
.takeError());
389 return llvm::make_error
<CodeViewError
>(
390 "String table offset outside of bounds of String Table!");
392 W
.printString("Program", *ExpectedProgram
);
394 printLocalVariableAddrRange(DefRange
.Range
, DefRange
.getRelocationOffset());
395 printLocalVariableAddrGap(DefRange
.Gaps
);
396 return Error::success();
399 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
400 FrameCookieSym
&FrameCookie
) {
401 StringRef LinkageName
;
403 ObjDelegate
->printRelocatedField("CodeOffset",
404 FrameCookie
.getRelocationOffset(),
405 FrameCookie
.CodeOffset
, &LinkageName
);
407 W
.printEnum("Register", uint16_t(FrameCookie
.Register
), getRegisterNames());
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
)),
429 W
.printEnum("ParamFramePtrReg",
430 uint16_t(FrameProc
.getParamFramePtrReg(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
), getRegisterNames());
510 W
.printString("Name", Register
.Name
);
511 return Error::success();
514 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, PublicSym32
&Public
) {
515 W
.printFlags("Flags", uint32_t(Public
.Flags
), getPublicSymFlagNames());
516 W
.printNumber("Seg", Public
.Segment
);
517 W
.printNumber("Off", Public
.Offset
);
518 W
.printString("Name", Public
.Name
);
519 return Error::success();
522 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ProcRefSym
&ProcRef
) {
523 W
.printNumber("SumName", ProcRef
.SumName
);
524 W
.printNumber("SymOffset", ProcRef
.SymOffset
);
525 W
.printNumber("Mod", ProcRef
.Module
);
526 W
.printString("Name", ProcRef
.Name
);
527 return Error::success();
530 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, LabelSym
&Label
) {
531 StringRef LinkageName
;
533 ObjDelegate
->printRelocatedField("CodeOffset", Label
.getRelocationOffset(),
534 Label
.CodeOffset
, &LinkageName
);
536 W
.printHex("Segment", Label
.Segment
);
537 W
.printHex("Flags", uint8_t(Label
.Flags
));
538 W
.printFlags("Flags", uint8_t(Label
.Flags
), getProcSymFlagNames());
539 W
.printString("DisplayName", Label
.Name
);
540 if (!LinkageName
.empty())
541 W
.printString("LinkageName", LinkageName
);
542 return Error::success();
545 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, LocalSym
&Local
) {
546 printTypeIndex("Type", Local
.Type
);
547 W
.printFlags("Flags", uint16_t(Local
.Flags
), getLocalFlagNames());
548 W
.printString("VarName", Local
.Name
);
549 return Error::success();
552 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ObjNameSym
&ObjName
) {
553 W
.printHex("Signature", ObjName
.Signature
);
554 W
.printString("ObjectName", ObjName
.Name
);
555 return Error::success();
558 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ProcSym
&Proc
) {
560 return llvm::make_error
<CodeViewError
>(
561 "Visiting a ProcSym while inside function scope!");
563 InFunctionScope
= true;
565 StringRef LinkageName
;
566 W
.printHex("PtrParent", Proc
.Parent
);
567 W
.printHex("PtrEnd", Proc
.End
);
568 W
.printHex("PtrNext", Proc
.Next
);
569 W
.printHex("CodeSize", Proc
.CodeSize
);
570 W
.printHex("DbgStart", Proc
.DbgStart
);
571 W
.printHex("DbgEnd", Proc
.DbgEnd
);
572 printTypeIndex("FunctionType", Proc
.FunctionType
);
574 ObjDelegate
->printRelocatedField("CodeOffset", Proc
.getRelocationOffset(),
575 Proc
.CodeOffset
, &LinkageName
);
577 W
.printHex("Segment", Proc
.Segment
);
578 W
.printFlags("Flags", static_cast<uint8_t>(Proc
.Flags
),
579 getProcSymFlagNames());
580 W
.printString("DisplayName", Proc
.Name
);
581 if (!LinkageName
.empty())
582 W
.printString("LinkageName", LinkageName
);
583 return Error::success();
586 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
587 ScopeEndSym
&ScopeEnd
) {
588 InFunctionScope
= false;
589 return Error::success();
592 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, CallerSym
&Caller
) {
593 ListScope
S(W
, CVR
.kind() == S_CALLEES
? "Callees" : "Callers");
594 for (auto FuncID
: Caller
.Indices
)
595 printTypeIndex("FuncID", FuncID
);
596 return Error::success();
599 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
600 RegRelativeSym
&RegRel
) {
601 W
.printHex("Offset", RegRel
.Offset
);
602 printTypeIndex("Type", RegRel
.Type
);
603 W
.printEnum("Register", uint16_t(RegRel
.Register
), getRegisterNames());
604 W
.printString("VarName", RegRel
.Name
);
605 return Error::success();
608 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
609 ThreadLocalDataSym
&Data
) {
610 StringRef LinkageName
;
612 ObjDelegate
->printRelocatedField("DataOffset", Data
.getRelocationOffset(),
613 Data
.DataOffset
, &LinkageName
);
615 printTypeIndex("Type", Data
.Type
);
616 W
.printString("DisplayName", Data
.Name
);
617 if (!LinkageName
.empty())
618 W
.printString("LinkageName", LinkageName
);
619 return Error::success();
622 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, UDTSym
&UDT
) {
623 printTypeIndex("Type", UDT
.Type
);
624 W
.printString("UDTName", UDT
.Name
);
625 return Error::success();
628 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
629 UsingNamespaceSym
&UN
) {
630 W
.printString("Namespace", UN
.Name
);
631 return Error::success();
634 Error
CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol
&CVR
) {
635 W
.printNumber("Length", CVR
.length());
636 return Error::success();
639 Error
CVSymbolDumper::dump(CVRecord
<SymbolKind
> &Record
) {
640 SymbolVisitorCallbackPipeline Pipeline
;
641 SymbolDeserializer
Deserializer(ObjDelegate
.get(), Container
);
642 CVSymbolDumperImpl
Dumper(Types
, ObjDelegate
.get(), W
, CompilationCPUType
,
645 Pipeline
.addCallbackToPipeline(Deserializer
);
646 Pipeline
.addCallbackToPipeline(Dumper
);
647 CVSymbolVisitor
Visitor(Pipeline
);
648 auto Err
= Visitor
.visitSymbolRecord(Record
);
649 CompilationCPUType
= Dumper
.getCompilationCPUType();
653 Error
CVSymbolDumper::dump(const CVSymbolArray
&Symbols
) {
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
.visitSymbolStream(Symbols
);
663 CompilationCPUType
= Dumper
.getCompilationCPUType();