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
.Type
);
105 W
.getOStream() << " {\n";
107 W
.printEnum("Kind", unsigned(CVR
.Type
), 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
.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
),
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
),
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
),
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
), getRegisterNames());
407 W
.printEnum("CookieKind", uint16_t(FrameCookie
.CookieKind
),
408 getFrameCookieKindNames());
409 W
.printHex("Flags", FrameCookie
.Flags
);
410 return Error::success();
413 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
414 FrameProcSym
&FrameProc
) {
415 W
.printHex("TotalFrameBytes", FrameProc
.TotalFrameBytes
);
416 W
.printHex("PaddingFrameBytes", FrameProc
.PaddingFrameBytes
);
417 W
.printHex("OffsetToPadding", FrameProc
.OffsetToPadding
);
418 W
.printHex("BytesOfCalleeSavedRegisters",
419 FrameProc
.BytesOfCalleeSavedRegisters
);
420 W
.printHex("OffsetOfExceptionHandler", FrameProc
.OffsetOfExceptionHandler
);
421 W
.printHex("SectionIdOfExceptionHandler",
422 FrameProc
.SectionIdOfExceptionHandler
);
423 W
.printFlags("Flags", static_cast<uint32_t>(FrameProc
.Flags
),
424 getFrameProcSymFlagNames());
425 W
.printEnum("LocalFramePtrReg",
426 uint16_t(FrameProc
.getLocalFramePtrReg(CompilationCPUType
)),
428 W
.printEnum("ParamFramePtrReg",
429 uint16_t(FrameProc
.getParamFramePtrReg(CompilationCPUType
)),
431 return Error::success();
434 Error
CVSymbolDumperImpl::visitKnownRecord(
435 CVSymbol
&CVR
, HeapAllocationSiteSym
&HeapAllocSite
) {
436 StringRef LinkageName
;
438 ObjDelegate
->printRelocatedField("CodeOffset",
439 HeapAllocSite
.getRelocationOffset(),
440 HeapAllocSite
.CodeOffset
, &LinkageName
);
442 W
.printHex("Segment", HeapAllocSite
.Segment
);
443 W
.printHex("CallInstructionSize", HeapAllocSite
.CallInstructionSize
);
444 printTypeIndex("Type", HeapAllocSite
.Type
);
445 if (!LinkageName
.empty())
446 W
.printString("LinkageName", LinkageName
);
447 return Error::success();
450 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
451 InlineSiteSym
&InlineSite
) {
452 W
.printHex("PtrParent", InlineSite
.Parent
);
453 W
.printHex("PtrEnd", InlineSite
.End
);
454 printTypeIndex("Inlinee", InlineSite
.Inlinee
);
456 ListScope
BinaryAnnotations(W
, "BinaryAnnotations");
457 for (auto &Annotation
: InlineSite
.annotations()) {
458 switch (Annotation
.OpCode
) {
459 case BinaryAnnotationsOpCode::Invalid
:
460 W
.printString("(Annotation Padding)");
462 case BinaryAnnotationsOpCode::CodeOffset
:
463 case BinaryAnnotationsOpCode::ChangeCodeOffset
:
464 case BinaryAnnotationsOpCode::ChangeCodeLength
:
465 W
.printHex(Annotation
.Name
, Annotation
.U1
);
467 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase
:
468 case BinaryAnnotationsOpCode::ChangeLineEndDelta
:
469 case BinaryAnnotationsOpCode::ChangeRangeKind
:
470 case BinaryAnnotationsOpCode::ChangeColumnStart
:
471 case BinaryAnnotationsOpCode::ChangeColumnEnd
:
472 W
.printNumber(Annotation
.Name
, Annotation
.U1
);
474 case BinaryAnnotationsOpCode::ChangeLineOffset
:
475 case BinaryAnnotationsOpCode::ChangeColumnEndDelta
:
476 W
.printNumber(Annotation
.Name
, Annotation
.S1
);
478 case BinaryAnnotationsOpCode::ChangeFile
:
480 W
.printHex("ChangeFile",
481 ObjDelegate
->getFileNameForFileOffset(Annotation
.U1
),
484 W
.printHex("ChangeFile", Annotation
.U1
);
488 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset
: {
489 W
.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
490 << W
.hex(Annotation
.U1
) << ", LineOffset: " << Annotation
.S1
494 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset
: {
495 W
.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
496 << W
.hex(Annotation
.U2
)
497 << ", Length: " << W
.hex(Annotation
.U1
) << "}\n";
502 return Error::success();
505 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
506 RegisterSym
&Register
) {
507 printTypeIndex("Type", Register
.Index
);
508 W
.printEnum("Seg", uint16_t(Register
.Register
), getRegisterNames());
509 W
.printString("Name", Register
.Name
);
510 return Error::success();
513 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, PublicSym32
&Public
) {
514 W
.printFlags("Flags", uint32_t(Public
.Flags
), getPublicSymFlagNames());
515 W
.printNumber("Seg", Public
.Segment
);
516 W
.printNumber("Off", Public
.Offset
);
517 W
.printString("Name", Public
.Name
);
518 return Error::success();
521 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ProcRefSym
&ProcRef
) {
522 W
.printNumber("SumName", ProcRef
.SumName
);
523 W
.printNumber("SymOffset", ProcRef
.SymOffset
);
524 W
.printNumber("Mod", ProcRef
.Module
);
525 W
.printString("Name", ProcRef
.Name
);
526 return Error::success();
529 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, LabelSym
&Label
) {
530 StringRef LinkageName
;
532 ObjDelegate
->printRelocatedField("CodeOffset", Label
.getRelocationOffset(),
533 Label
.CodeOffset
, &LinkageName
);
535 W
.printHex("Segment", Label
.Segment
);
536 W
.printHex("Flags", uint8_t(Label
.Flags
));
537 W
.printFlags("Flags", uint8_t(Label
.Flags
), getProcSymFlagNames());
538 W
.printString("DisplayName", Label
.Name
);
539 if (!LinkageName
.empty())
540 W
.printString("LinkageName", LinkageName
);
541 return Error::success();
544 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, LocalSym
&Local
) {
545 printTypeIndex("Type", Local
.Type
);
546 W
.printFlags("Flags", uint16_t(Local
.Flags
), getLocalFlagNames());
547 W
.printString("VarName", Local
.Name
);
548 return Error::success();
551 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ObjNameSym
&ObjName
) {
552 W
.printHex("Signature", ObjName
.Signature
);
553 W
.printString("ObjectName", ObjName
.Name
);
554 return Error::success();
557 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ProcSym
&Proc
) {
559 return llvm::make_error
<CodeViewError
>(
560 "Visiting a ProcSym while inside function scope!");
562 InFunctionScope
= true;
564 StringRef LinkageName
;
565 W
.printHex("PtrParent", Proc
.Parent
);
566 W
.printHex("PtrEnd", Proc
.End
);
567 W
.printHex("PtrNext", Proc
.Next
);
568 W
.printHex("CodeSize", Proc
.CodeSize
);
569 W
.printHex("DbgStart", Proc
.DbgStart
);
570 W
.printHex("DbgEnd", Proc
.DbgEnd
);
571 printTypeIndex("FunctionType", Proc
.FunctionType
);
573 ObjDelegate
->printRelocatedField("CodeOffset", Proc
.getRelocationOffset(),
574 Proc
.CodeOffset
, &LinkageName
);
576 W
.printHex("Segment", Proc
.Segment
);
577 W
.printFlags("Flags", static_cast<uint8_t>(Proc
.Flags
),
578 getProcSymFlagNames());
579 W
.printString("DisplayName", Proc
.Name
);
580 if (!LinkageName
.empty())
581 W
.printString("LinkageName", LinkageName
);
582 return Error::success();
585 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
586 ScopeEndSym
&ScopeEnd
) {
587 InFunctionScope
= false;
588 return Error::success();
591 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, CallerSym
&Caller
) {
592 ListScope
S(W
, CVR
.kind() == S_CALLEES
? "Callees" : "Callers");
593 for (auto FuncID
: Caller
.Indices
)
594 printTypeIndex("FuncID", FuncID
);
595 return Error::success();
598 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
599 RegRelativeSym
&RegRel
) {
600 W
.printHex("Offset", RegRel
.Offset
);
601 printTypeIndex("Type", RegRel
.Type
);
602 W
.printEnum("Register", uint16_t(RegRel
.Register
), getRegisterNames());
603 W
.printString("VarName", RegRel
.Name
);
604 return Error::success();
607 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
608 ThreadLocalDataSym
&Data
) {
609 StringRef LinkageName
;
611 ObjDelegate
->printRelocatedField("DataOffset", Data
.getRelocationOffset(),
612 Data
.DataOffset
, &LinkageName
);
614 printTypeIndex("Type", Data
.Type
);
615 W
.printString("DisplayName", Data
.Name
);
616 if (!LinkageName
.empty())
617 W
.printString("LinkageName", LinkageName
);
618 return Error::success();
621 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, UDTSym
&UDT
) {
622 printTypeIndex("Type", UDT
.Type
);
623 W
.printString("UDTName", UDT
.Name
);
624 return Error::success();
627 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
628 UsingNamespaceSym
&UN
) {
629 W
.printString("Namespace", UN
.Name
);
630 return Error::success();
633 Error
CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol
&CVR
) {
634 W
.printNumber("Length", CVR
.length());
635 return Error::success();
638 Error
CVSymbolDumper::dump(CVRecord
<SymbolKind
> &Record
) {
639 SymbolVisitorCallbackPipeline Pipeline
;
640 SymbolDeserializer
Deserializer(ObjDelegate
.get(), Container
);
641 CVSymbolDumperImpl
Dumper(Types
, ObjDelegate
.get(), W
, CompilationCPUType
,
644 Pipeline
.addCallbackToPipeline(Deserializer
);
645 Pipeline
.addCallbackToPipeline(Dumper
);
646 CVSymbolVisitor
Visitor(Pipeline
);
647 auto Err
= Visitor
.visitSymbolRecord(Record
);
648 CompilationCPUType
= Dumper
.getCompilationCPUType();
652 Error
CVSymbolDumper::dump(const CVSymbolArray
&Symbols
) {
653 SymbolVisitorCallbackPipeline Pipeline
;
654 SymbolDeserializer
Deserializer(ObjDelegate
.get(), Container
);
655 CVSymbolDumperImpl
Dumper(Types
, ObjDelegate
.get(), W
, CompilationCPUType
,
658 Pipeline
.addCallbackToPipeline(Deserializer
);
659 Pipeline
.addCallbackToPipeline(Dumper
);
660 CVSymbolVisitor
Visitor(Pipeline
);
661 auto Err
= Visitor
.visitSymbolStream(Symbols
);
662 CompilationCPUType
= Dumper
.getCompilationCPUType();