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/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"
24 using namespace llvm::codeview
;
27 /// Use this private dumper implementation to keep implementation details about
28 /// the visitor out of SymbolDumper.h.
29 class CVSymbolDumperImpl
: public SymbolVisitorCallbacks
{
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) {}
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"
42 Error
visitSymbolBegin(CVSymbol
&Record
) override
;
43 Error
visitSymbolEnd(CVSymbol
&Record
) override
;
44 Error
visitUnknownSymbol(CVSymbol
&Record
) override
;
46 CPUType
getCompilationCPUType() const { return CompilationCPUType
; }
49 void printLocalVariableAddrRange(const LocalVariableAddrRange
&Range
,
50 uint32_t RelocationOffset
);
51 void printLocalVariableAddrGap(ArrayRef
<LocalVariableAddrGap
> Gaps
);
52 void printTypeIndex(StringRef FieldName
, TypeIndex TI
);
54 TypeCollection
&Types
;
55 SymbolDumpDelegate
*ObjDelegate
;
58 /// Save the machine or CPU type when dumping a compile symbols.
59 CPUType CompilationCPUType
= CPUType::X64
;
61 bool PrintRecordBytes
;
66 static StringRef
getSymbolKindName(SymbolKind Kind
) {
68 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
71 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
78 void CVSymbolDumperImpl::printLocalVariableAddrRange(
79 const LocalVariableAddrRange
&Range
, uint32_t RelocationOffset
) {
80 DictScope
S(W
, "LocalVariableAddrRange");
82 ObjDelegate
->printRelocatedField("OffsetStart", RelocationOffset
,
84 W
.printHex("ISectStart", Range
.ISectStart
);
85 W
.printHex("Range", Range
.Range
);
88 void CVSymbolDumperImpl::printLocalVariableAddrGap(
89 ArrayRef
<LocalVariableAddrGap
> Gaps
) {
90 for (auto &Gap
: Gaps
) {
91 ListScope
S(W
, "LocalVariableAddrGap");
92 W
.printHex("GapStartOffset", Gap
.GapStartOffset
);
93 W
.printHex("Range", Gap
.Range
);
97 void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName
, TypeIndex TI
) {
98 codeview::printTypeIndex(W
, FieldName
, TI
, Types
);
101 Error
CVSymbolDumperImpl::visitSymbolBegin(CVSymbol
&CVR
) {
102 W
.startLine() << getSymbolKindName(CVR
.kind());
103 W
.getOStream() << " {\n";
105 W
.printEnum("Kind", unsigned(CVR
.kind()), getSymbolTypeNames());
106 return Error::success();
109 Error
CVSymbolDumperImpl::visitSymbolEnd(CVSymbol
&CVR
) {
110 if (PrintRecordBytes
&& ObjDelegate
)
111 ObjDelegate
->printBinaryBlockWithRelocs("SymData", CVR
.content());
114 W
.startLine() << "}\n";
115 return Error::success();
118 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, BlockSym
&Block
) {
119 StringRef LinkageName
;
120 W
.printHex("PtrParent", Block
.Parent
);
121 W
.printHex("PtrEnd", Block
.End
);
122 W
.printHex("CodeSize", Block
.CodeSize
);
124 ObjDelegate
->printRelocatedField("CodeOffset", Block
.getRelocationOffset(),
125 Block
.CodeOffset
, &LinkageName
);
127 W
.printHex("Segment", Block
.Segment
);
128 W
.printString("BlockName", Block
.Name
);
129 W
.printString("LinkageName", LinkageName
);
130 return Error::success();
133 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, Thunk32Sym
&Thunk
) {
134 W
.printString("Name", Thunk
.Name
);
135 W
.printNumber("Parent", Thunk
.Parent
);
136 W
.printNumber("End", Thunk
.End
);
137 W
.printNumber("Next", Thunk
.Next
);
138 W
.printNumber("Off", Thunk
.Offset
);
139 W
.printNumber("Seg", Thunk
.Segment
);
140 W
.printNumber("Len", Thunk
.Length
);
141 W
.printEnum("Ordinal", uint8_t(Thunk
.Thunk
), getThunkOrdinalNames());
142 return Error::success();
145 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
146 TrampolineSym
&Tramp
) {
147 W
.printEnum("Type", uint16_t(Tramp
.Type
), getTrampolineNames());
148 W
.printNumber("Size", Tramp
.Size
);
149 W
.printNumber("ThunkOff", Tramp
.ThunkOffset
);
150 W
.printNumber("TargetOff", Tramp
.TargetOffset
);
151 W
.printNumber("ThunkSection", Tramp
.ThunkSection
);
152 W
.printNumber("TargetSection", Tramp
.TargetSection
);
153 return Error::success();
156 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, SectionSym
&Section
) {
157 W
.printNumber("SectionNumber", Section
.SectionNumber
);
158 W
.printNumber("Alignment", Section
.Alignment
);
159 W
.printNumber("Rva", Section
.Rva
);
160 W
.printNumber("Length", Section
.Length
);
161 W
.printFlags("Characteristics", Section
.Characteristics
,
162 getImageSectionCharacteristicNames(),
163 COFF::SectionCharacteristics(0x00F00000));
165 W
.printString("Name", Section
.Name
);
166 return Error::success();
169 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
170 CoffGroupSym
&CoffGroup
) {
171 W
.printNumber("Size", CoffGroup
.Size
);
172 W
.printFlags("Characteristics", CoffGroup
.Characteristics
,
173 getImageSectionCharacteristicNames(),
174 COFF::SectionCharacteristics(0x00F00000));
175 W
.printNumber("Offset", CoffGroup
.Offset
);
176 W
.printNumber("Segment", CoffGroup
.Segment
);
177 W
.printString("Name", CoffGroup
.Name
);
178 return Error::success();
181 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
182 BPRelativeSym
&BPRel
) {
183 W
.printNumber("Offset", BPRel
.Offset
);
184 printTypeIndex("Type", BPRel
.Type
);
185 W
.printString("VarName", BPRel
.Name
);
186 return Error::success();
189 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
190 BuildInfoSym
&BuildInfo
) {
191 printTypeIndex("BuildId", BuildInfo
.BuildId
);
192 return Error::success();
195 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
196 CallSiteInfoSym
&CallSiteInfo
) {
197 StringRef LinkageName
;
199 ObjDelegate
->printRelocatedField("CodeOffset",
200 CallSiteInfo
.getRelocationOffset(),
201 CallSiteInfo
.CodeOffset
, &LinkageName
);
203 W
.printHex("Segment", CallSiteInfo
.Segment
);
204 printTypeIndex("Type", CallSiteInfo
.Type
);
205 if (!LinkageName
.empty())
206 W
.printString("LinkageName", LinkageName
);
207 return Error::success();
210 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
211 EnvBlockSym
&EnvBlock
) {
212 ListScope
L(W
, "Entries");
213 for (auto Entry
: EnvBlock
.Fields
) {
214 W
.printString(Entry
);
216 return Error::success();
219 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
220 FileStaticSym
&FileStatic
) {
221 printTypeIndex("Index", FileStatic
.Index
);
222 W
.printNumber("ModFilenameOffset", FileStatic
.ModFilenameOffset
);
223 W
.printFlags("Flags", uint16_t(FileStatic
.Flags
), getLocalFlagNames());
224 W
.printString("Name", FileStatic
.Name
);
225 return Error::success();
228 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, ExportSym
&Export
) {
229 W
.printNumber("Ordinal", Export
.Ordinal
);
230 W
.printFlags("Flags", uint16_t(Export
.Flags
), getExportSymFlagNames());
231 W
.printString("Name", Export
.Name
);
232 return Error::success();
235 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
236 Compile2Sym
&Compile2
) {
237 W
.printEnum("Language", Compile2
.getLanguage(), getSourceLanguageNames());
238 W
.printFlags("Flags", Compile2
.getFlags(), getCompileSym2FlagNames());
239 W
.printEnum("Machine", unsigned(Compile2
.Machine
), getCPUTypeNames());
240 CompilationCPUType
= Compile2
.Machine
;
241 std::string FrontendVersion
;
243 raw_string_ostream
Out(FrontendVersion
);
244 Out
<< Compile2
.VersionFrontendMajor
<< '.' << Compile2
.VersionFrontendMinor
245 << '.' << Compile2
.VersionFrontendBuild
;
247 std::string BackendVersion
;
249 raw_string_ostream
Out(BackendVersion
);
250 Out
<< Compile2
.VersionBackendMajor
<< '.' << Compile2
.VersionBackendMinor
251 << '.' << Compile2
.VersionBackendBuild
;
253 W
.printString("FrontendVersion", FrontendVersion
);
254 W
.printString("BackendVersion", BackendVersion
);
255 W
.printString("VersionName", Compile2
.Version
);
256 return Error::success();
259 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
260 Compile3Sym
&Compile3
) {
261 W
.printEnum("Language", uint8_t(Compile3
.getLanguage()), getSourceLanguageNames());
262 W
.printFlags("Flags", uint32_t(Compile3
.getFlags()),
263 getCompileSym3FlagNames());
264 W
.printEnum("Machine", unsigned(Compile3
.Machine
), getCPUTypeNames());
265 CompilationCPUType
= Compile3
.Machine
;
266 std::string FrontendVersion
;
268 raw_string_ostream
Out(FrontendVersion
);
269 Out
<< Compile3
.VersionFrontendMajor
<< '.' << Compile3
.VersionFrontendMinor
270 << '.' << Compile3
.VersionFrontendBuild
<< '.'
271 << Compile3
.VersionFrontendQFE
;
273 std::string BackendVersion
;
275 raw_string_ostream
Out(BackendVersion
);
276 Out
<< Compile3
.VersionBackendMajor
<< '.' << Compile3
.VersionBackendMinor
277 << '.' << Compile3
.VersionBackendBuild
<< '.'
278 << Compile3
.VersionBackendQFE
;
280 W
.printString("FrontendVersion", FrontendVersion
);
281 W
.printString("BackendVersion", BackendVersion
);
282 W
.printString("VersionName", Compile3
.Version
);
283 return Error::success();
286 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
287 ConstantSym
&Constant
) {
288 printTypeIndex("Type", Constant
.Type
);
289 W
.printNumber("Value", Constant
.Value
);
290 W
.printString("Name", Constant
.Name
);
291 return Error::success();
294 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, DataSym
&Data
) {
295 StringRef LinkageName
;
297 ObjDelegate
->printRelocatedField("DataOffset", Data
.getRelocationOffset(),
298 Data
.DataOffset
, &LinkageName
);
300 printTypeIndex("Type", Data
.Type
);
301 W
.printString("DisplayName", Data
.Name
);
302 if (!LinkageName
.empty())
303 W
.printString("LinkageName", LinkageName
);
304 return Error::success();
307 Error
CVSymbolDumperImpl::visitKnownRecord(
309 DefRangeFramePointerRelFullScopeSym
&DefRangeFramePointerRelFullScope
) {
310 W
.printNumber("Offset", DefRangeFramePointerRelFullScope
.Offset
);
311 return Error::success();
314 Error
CVSymbolDumperImpl::visitKnownRecord(
315 CVSymbol
&CVR
, DefRangeFramePointerRelSym
&DefRangeFramePointerRel
) {
316 W
.printNumber("Offset", DefRangeFramePointerRel
.Hdr
.Offset
);
317 printLocalVariableAddrRange(DefRangeFramePointerRel
.Range
,
318 DefRangeFramePointerRel
.getRelocationOffset());
319 printLocalVariableAddrGap(DefRangeFramePointerRel
.Gaps
);
320 return Error::success();
323 Error
CVSymbolDumperImpl::visitKnownRecord(
324 CVSymbol
&CVR
, DefRangeRegisterRelSym
&DefRangeRegisterRel
) {
325 W
.printEnum("BaseRegister", uint16_t(DefRangeRegisterRel
.Hdr
.Register
),
326 getRegisterNames(CompilationCPUType
));
327 W
.printBoolean("HasSpilledUDTMember",
328 DefRangeRegisterRel
.hasSpilledUDTMember());
329 W
.printNumber("OffsetInParent", DefRangeRegisterRel
.offsetInParent());
330 W
.printNumber("BasePointerOffset", DefRangeRegisterRel
.Hdr
.BasePointerOffset
);
331 printLocalVariableAddrRange(DefRangeRegisterRel
.Range
,
332 DefRangeRegisterRel
.getRelocationOffset());
333 printLocalVariableAddrGap(DefRangeRegisterRel
.Gaps
);
334 return Error::success();
337 Error
CVSymbolDumperImpl::visitKnownRecord(
338 CVSymbol
&CVR
, DefRangeRegisterSym
&DefRangeRegister
) {
339 W
.printEnum("Register", uint16_t(DefRangeRegister
.Hdr
.Register
),
340 getRegisterNames(CompilationCPUType
));
341 W
.printNumber("MayHaveNoName", DefRangeRegister
.Hdr
.MayHaveNoName
);
342 printLocalVariableAddrRange(DefRangeRegister
.Range
,
343 DefRangeRegister
.getRelocationOffset());
344 printLocalVariableAddrGap(DefRangeRegister
.Gaps
);
345 return Error::success();
348 Error
CVSymbolDumperImpl::visitKnownRecord(
349 CVSymbol
&CVR
, DefRangeSubfieldRegisterSym
&DefRangeSubfieldRegister
) {
350 W
.printEnum("Register", uint16_t(DefRangeSubfieldRegister
.Hdr
.Register
),
351 getRegisterNames(CompilationCPUType
));
352 W
.printNumber("MayHaveNoName", DefRangeSubfieldRegister
.Hdr
.MayHaveNoName
);
353 W
.printNumber("OffsetInParent", DefRangeSubfieldRegister
.Hdr
.OffsetInParent
);
354 printLocalVariableAddrRange(DefRangeSubfieldRegister
.Range
,
355 DefRangeSubfieldRegister
.getRelocationOffset());
356 printLocalVariableAddrGap(DefRangeSubfieldRegister
.Gaps
);
357 return Error::success();
360 Error
CVSymbolDumperImpl::visitKnownRecord(
361 CVSymbol
&CVR
, DefRangeSubfieldSym
&DefRangeSubfield
) {
363 DebugStringTableSubsectionRef Strings
= ObjDelegate
->getStringTable();
364 auto ExpectedProgram
= Strings
.getString(DefRangeSubfield
.Program
);
365 if (!ExpectedProgram
) {
366 consumeError(ExpectedProgram
.takeError());
367 return llvm::make_error
<CodeViewError
>(
368 "String table offset outside of bounds of String Table!");
370 W
.printString("Program", *ExpectedProgram
);
372 W
.printNumber("OffsetInParent", DefRangeSubfield
.OffsetInParent
);
373 printLocalVariableAddrRange(DefRangeSubfield
.Range
,
374 DefRangeSubfield
.getRelocationOffset());
375 printLocalVariableAddrGap(DefRangeSubfield
.Gaps
);
376 return Error::success();
379 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
380 DefRangeSym
&DefRange
) {
382 DebugStringTableSubsectionRef Strings
= ObjDelegate
->getStringTable();
383 auto ExpectedProgram
= Strings
.getString(DefRange
.Program
);
384 if (!ExpectedProgram
) {
385 consumeError(ExpectedProgram
.takeError());
386 return llvm::make_error
<CodeViewError
>(
387 "String table offset outside of bounds of String Table!");
389 W
.printString("Program", *ExpectedProgram
);
391 printLocalVariableAddrRange(DefRange
.Range
, DefRange
.getRelocationOffset());
392 printLocalVariableAddrGap(DefRange
.Gaps
);
393 return Error::success();
396 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
397 FrameCookieSym
&FrameCookie
) {
398 StringRef LinkageName
;
400 ObjDelegate
->printRelocatedField("CodeOffset",
401 FrameCookie
.getRelocationOffset(),
402 FrameCookie
.CodeOffset
, &LinkageName
);
404 W
.printEnum("Register", uint16_t(FrameCookie
.Register
),
405 getRegisterNames(CompilationCPUType
));
406 W
.printEnum("CookieKind", uint16_t(FrameCookie
.CookieKind
),
407 getFrameCookieKindNames());
408 W
.printHex("Flags", FrameCookie
.Flags
);
409 return Error::success();
412 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
413 FrameProcSym
&FrameProc
) {
414 W
.printHex("TotalFrameBytes", FrameProc
.TotalFrameBytes
);
415 W
.printHex("PaddingFrameBytes", FrameProc
.PaddingFrameBytes
);
416 W
.printHex("OffsetToPadding", FrameProc
.OffsetToPadding
);
417 W
.printHex("BytesOfCalleeSavedRegisters",
418 FrameProc
.BytesOfCalleeSavedRegisters
);
419 W
.printHex("OffsetOfExceptionHandler", FrameProc
.OffsetOfExceptionHandler
);
420 W
.printHex("SectionIdOfExceptionHandler",
421 FrameProc
.SectionIdOfExceptionHandler
);
422 W
.printFlags("Flags", static_cast<uint32_t>(FrameProc
.Flags
),
423 getFrameProcSymFlagNames());
424 W
.printEnum("LocalFramePtrReg",
425 uint16_t(FrameProc
.getLocalFramePtrReg(CompilationCPUType
)),
426 getRegisterNames(CompilationCPUType
));
427 W
.printEnum("ParamFramePtrReg",
428 uint16_t(FrameProc
.getParamFramePtrReg(CompilationCPUType
)),
429 getRegisterNames(CompilationCPUType
));
430 return Error::success();
433 Error
CVSymbolDumperImpl::visitKnownRecord(
434 CVSymbol
&CVR
, HeapAllocationSiteSym
&HeapAllocSite
) {
435 StringRef LinkageName
;
437 ObjDelegate
->printRelocatedField("CodeOffset",
438 HeapAllocSite
.getRelocationOffset(),
439 HeapAllocSite
.CodeOffset
, &LinkageName
);
441 W
.printHex("Segment", HeapAllocSite
.Segment
);
442 W
.printHex("CallInstructionSize", HeapAllocSite
.CallInstructionSize
);
443 printTypeIndex("Type", HeapAllocSite
.Type
);
444 if (!LinkageName
.empty())
445 W
.printString("LinkageName", LinkageName
);
446 return Error::success();
449 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
450 InlineSiteSym
&InlineSite
) {
451 W
.printHex("PtrParent", InlineSite
.Parent
);
452 W
.printHex("PtrEnd", InlineSite
.End
);
453 printTypeIndex("Inlinee", InlineSite
.Inlinee
);
455 ListScope
BinaryAnnotations(W
, "BinaryAnnotations");
456 for (auto &Annotation
: InlineSite
.annotations()) {
457 switch (Annotation
.OpCode
) {
458 case BinaryAnnotationsOpCode::Invalid
:
459 W
.printString("(Annotation Padding)");
461 case BinaryAnnotationsOpCode::CodeOffset
:
462 case BinaryAnnotationsOpCode::ChangeCodeOffset
:
463 case BinaryAnnotationsOpCode::ChangeCodeLength
:
464 W
.printHex(Annotation
.Name
, Annotation
.U1
);
466 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase
:
467 case BinaryAnnotationsOpCode::ChangeLineEndDelta
:
468 case BinaryAnnotationsOpCode::ChangeRangeKind
:
469 case BinaryAnnotationsOpCode::ChangeColumnStart
:
470 case BinaryAnnotationsOpCode::ChangeColumnEnd
:
471 W
.printNumber(Annotation
.Name
, Annotation
.U1
);
473 case BinaryAnnotationsOpCode::ChangeLineOffset
:
474 case BinaryAnnotationsOpCode::ChangeColumnEndDelta
:
475 W
.printNumber(Annotation
.Name
, Annotation
.S1
);
477 case BinaryAnnotationsOpCode::ChangeFile
:
479 W
.printHex("ChangeFile",
480 ObjDelegate
->getFileNameForFileOffset(Annotation
.U1
),
483 W
.printHex("ChangeFile", Annotation
.U1
);
487 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset
: {
488 W
.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
489 << W
.hex(Annotation
.U1
) << ", LineOffset: " << Annotation
.S1
493 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset
: {
494 W
.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
495 << W
.hex(Annotation
.U2
)
496 << ", Length: " << W
.hex(Annotation
.U1
) << "}\n";
501 return Error::success();
504 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
505 RegisterSym
&Register
) {
506 printTypeIndex("Type", Register
.Index
);
507 W
.printEnum("Seg", uint16_t(Register
.Register
),
508 getRegisterNames(CompilationCPUType
));
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 llvm::StringRef ScopeName
;
593 switch (CVR
.kind()) {
595 ScopeName
= "Callees";
598 ScopeName
= "Callers";
601 ScopeName
= "Inlinees";
604 return llvm::make_error
<CodeViewError
>(
605 "Unknown CV Record type for a CallerSym object!");
607 ListScope
S(W
, ScopeName
);
608 for (auto FuncID
: Caller
.Indices
)
609 printTypeIndex("FuncID", FuncID
);
610 return Error::success();
613 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
614 RegRelativeSym
&RegRel
) {
615 W
.printHex("Offset", RegRel
.Offset
);
616 printTypeIndex("Type", RegRel
.Type
);
617 W
.printEnum("Register", uint16_t(RegRel
.Register
),
618 getRegisterNames(CompilationCPUType
));
619 W
.printString("VarName", RegRel
.Name
);
620 return Error::success();
623 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
624 ThreadLocalDataSym
&Data
) {
625 StringRef LinkageName
;
627 ObjDelegate
->printRelocatedField("DataOffset", Data
.getRelocationOffset(),
628 Data
.DataOffset
, &LinkageName
);
630 printTypeIndex("Type", Data
.Type
);
631 W
.printString("DisplayName", Data
.Name
);
632 if (!LinkageName
.empty())
633 W
.printString("LinkageName", LinkageName
);
634 return Error::success();
637 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
, UDTSym
&UDT
) {
638 printTypeIndex("Type", UDT
.Type
);
639 W
.printString("UDTName", UDT
.Name
);
640 return Error::success();
643 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
644 UsingNamespaceSym
&UN
) {
645 W
.printString("Namespace", UN
.Name
);
646 return Error::success();
649 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
650 AnnotationSym
&Annot
) {
651 W
.printHex("Offset", Annot
.CodeOffset
);
652 W
.printHex("Segment", Annot
.Segment
);
654 ListScope
S(W
, "Strings");
655 for (StringRef Str
: Annot
.Strings
)
658 return Error::success();
661 Error
CVSymbolDumperImpl::visitKnownRecord(CVSymbol
&CVR
,
662 JumpTableSym
&JumpTable
) {
663 W
.printHex("BaseOffset", JumpTable
.BaseOffset
);
664 W
.printNumber("BaseSegment", JumpTable
.BaseSegment
);
665 W
.printEnum("SwitchType", static_cast<uint16_t>(JumpTable
.SwitchType
),
666 getJumpTableEntrySizeNames());
667 W
.printHex("BranchOffset", JumpTable
.BranchOffset
);
668 W
.printHex("TableOffset", JumpTable
.TableOffset
);
669 W
.printNumber("BranchSegment", JumpTable
.BranchSegment
);
670 W
.printNumber("TableSegment", JumpTable
.TableSegment
);
671 W
.printNumber("EntriesCount", JumpTable
.EntriesCount
);
672 return Error::success();
675 Error
CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol
&CVR
) {
676 W
.printNumber("Length", CVR
.length());
677 return Error::success();
680 Error
CVSymbolDumper::dump(CVRecord
<SymbolKind
> &Record
) {
681 SymbolVisitorCallbackPipeline Pipeline
;
682 SymbolDeserializer
Deserializer(ObjDelegate
.get(), Container
);
683 CVSymbolDumperImpl
Dumper(Types
, ObjDelegate
.get(), W
, CompilationCPUType
,
686 Pipeline
.addCallbackToPipeline(Deserializer
);
687 Pipeline
.addCallbackToPipeline(Dumper
);
688 CVSymbolVisitor
Visitor(Pipeline
);
689 auto Err
= Visitor
.visitSymbolRecord(Record
);
690 CompilationCPUType
= Dumper
.getCompilationCPUType();
694 Error
CVSymbolDumper::dump(const CVSymbolArray
&Symbols
) {
695 SymbolVisitorCallbackPipeline Pipeline
;
696 SymbolDeserializer
Deserializer(ObjDelegate
.get(), Container
);
697 CVSymbolDumperImpl
Dumper(Types
, ObjDelegate
.get(), W
, CompilationCPUType
,
700 Pipeline
.addCallbackToPipeline(Deserializer
);
701 Pipeline
.addCallbackToPipeline(Dumper
);
702 CVSymbolVisitor
Visitor(Pipeline
);
703 auto Err
= Visitor
.visitSymbolStream(Symbols
);
704 CompilationCPUType
= Dumper
.getCompilationCPUType();