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/DenseMap.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
14 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
15 #include "llvm/DebugInfo/CodeView/EnumTables.h"
16 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
17 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
18 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
19 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
20 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
21 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/ScopedPrinter.h"
25 #include <system_error>
28 using namespace llvm::codeview;
31 /// Use this private dumper implementation to keep implementation details about
32 /// the visitor out of SymbolDumper.h.
33 class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
35 CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate,
36 ScopedPrinter &W, bool PrintRecordBytes)
37 : Types(Types), ObjDelegate(ObjDelegate), W(W),
38 PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
40 /// CVSymbolVisitor overrides.
41 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
42 Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
43 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
44 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
46 Error visitSymbolBegin(CVSymbol &Record) override;
47 Error visitSymbolEnd(CVSymbol &Record) override;
48 Error visitUnknownSymbol(CVSymbol &Record) override;
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 bool PrintRecordBytes;
65 static StringRef getSymbolKindName(SymbolKind Kind) {
67 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
70 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
77 void CVSymbolDumperImpl::printLocalVariableAddrRange(
78 const LocalVariableAddrRange &Range, uint32_t RelocationOffset) {
79 DictScope S(W, "LocalVariableAddrRange");
81 ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset,
83 W.printHex("ISectStart", Range.ISectStart);
84 W.printHex("Range", Range.Range);
87 void CVSymbolDumperImpl::printLocalVariableAddrGap(
88 ArrayRef<LocalVariableAddrGap> Gaps) {
89 for (auto &Gap : Gaps) {
90 ListScope S(W, "LocalVariableAddrGap");
91 W.printHex("GapStartOffset", Gap.GapStartOffset);
92 W.printHex("Range", Gap.Range);
96 void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) {
97 codeview::printTypeIndex(W, FieldName, TI, Types);
100 Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
101 W.startLine() << getSymbolKindName(CVR.Type);
102 W.getOStream() << " {\n";
104 W.printEnum("Kind", unsigned(CVR.Type), getSymbolTypeNames());
105 return Error::success();
108 Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) {
109 if (PrintRecordBytes && ObjDelegate)
110 ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content());
113 W.startLine() << "}\n";
114 return Error::success();
117 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
118 StringRef LinkageName;
119 W.printHex("PtrParent", Block.Parent);
120 W.printHex("PtrEnd", Block.End);
121 W.printHex("CodeSize", Block.CodeSize);
123 ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(),
124 Block.CodeOffset, &LinkageName);
126 W.printHex("Segment", Block.Segment);
127 W.printString("BlockName", Block.Name);
128 W.printString("LinkageName", LinkageName);
129 return Error::success();
132 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
133 W.printNumber("Parent", Thunk.Parent);
134 W.printNumber("End", Thunk.End);
135 W.printNumber("Next", Thunk.Next);
136 W.printNumber("Off", Thunk.Offset);
137 W.printNumber("Seg", Thunk.Segment);
138 W.printNumber("Len", Thunk.Length);
139 W.printEnum("Ordinal", uint8_t(Thunk.Thunk), getThunkOrdinalNames());
140 return Error::success();
143 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
144 TrampolineSym &Tramp) {
145 W.printEnum("Type", uint16_t(Tramp.Type), getTrampolineNames());
146 W.printNumber("Size", Tramp.Size);
147 W.printNumber("ThunkOff", Tramp.ThunkOffset);
148 W.printNumber("TargetOff", Tramp.TargetOffset);
149 W.printNumber("ThunkSection", Tramp.ThunkSection);
150 W.printNumber("TargetSection", Tramp.TargetSection);
151 return Error::success();
154 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) {
155 W.printNumber("SectionNumber", Section.SectionNumber);
156 W.printNumber("Alignment", Section.Alignment);
157 W.printNumber("Rva", Section.Rva);
158 W.printNumber("Length", Section.Length);
159 W.printFlags("Characteristics", Section.Characteristics,
160 getImageSectionCharacteristicNames(),
161 COFF::SectionCharacteristics(0x00F00000));
163 W.printString("Name", Section.Name);
164 return Error::success();
167 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
168 CoffGroupSym &CoffGroup) {
169 W.printNumber("Size", CoffGroup.Size);
170 W.printFlags("Characteristics", CoffGroup.Characteristics,
171 getImageSectionCharacteristicNames(),
172 COFF::SectionCharacteristics(0x00F00000));
173 W.printNumber("Offset", CoffGroup.Offset);
174 W.printNumber("Segment", CoffGroup.Segment);
175 W.printString("Name", CoffGroup.Name);
176 return Error::success();
179 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
180 BPRelativeSym &BPRel) {
181 W.printNumber("Offset", BPRel.Offset);
182 printTypeIndex("Type", BPRel.Type);
183 W.printString("VarName", BPRel.Name);
184 return Error::success();
187 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
188 BuildInfoSym &BuildInfo) {
189 printTypeIndex("BuildId", BuildInfo.BuildId);
190 return Error::success();
193 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
194 CallSiteInfoSym &CallSiteInfo) {
195 StringRef LinkageName;
197 ObjDelegate->printRelocatedField("CodeOffset",
198 CallSiteInfo.getRelocationOffset(),
199 CallSiteInfo.CodeOffset, &LinkageName);
201 W.printHex("Segment", CallSiteInfo.Segment);
202 printTypeIndex("Type", CallSiteInfo.Type);
203 if (!LinkageName.empty())
204 W.printString("LinkageName", LinkageName);
205 return Error::success();
208 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
209 EnvBlockSym &EnvBlock) {
210 ListScope L(W, "Entries");
211 for (auto Entry : EnvBlock.Fields) {
212 W.printString(Entry);
214 return Error::success();
217 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
218 FileStaticSym &FileStatic) {
219 printTypeIndex("Index", FileStatic.Index);
220 W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset);
221 W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames());
222 W.printString("Name", FileStatic.Name);
223 return Error::success();
226 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
227 W.printNumber("Ordinal", Export.Ordinal);
228 W.printFlags("Flags", uint16_t(Export.Flags), getExportSymFlagNames());
229 W.printString("Name", Export.Name);
230 return Error::success();
233 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
234 Compile2Sym &Compile2) {
235 W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames());
236 W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames());
237 W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames());
238 std::string FrontendVersion;
240 raw_string_ostream Out(FrontendVersion);
241 Out << Compile2.VersionFrontendMajor << '.' << Compile2.VersionFrontendMinor
242 << '.' << Compile2.VersionFrontendBuild;
244 std::string BackendVersion;
246 raw_string_ostream Out(BackendVersion);
247 Out << Compile2.VersionBackendMajor << '.' << Compile2.VersionBackendMinor
248 << '.' << Compile2.VersionBackendBuild;
250 W.printString("FrontendVersion", FrontendVersion);
251 W.printString("BackendVersion", BackendVersion);
252 W.printString("VersionName", Compile2.Version);
253 return Error::success();
256 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
257 Compile3Sym &Compile3) {
258 W.printEnum("Language", Compile3.getLanguage(), getSourceLanguageNames());
259 W.printFlags("Flags", Compile3.getFlags(), getCompileSym3FlagNames());
260 W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames());
261 std::string FrontendVersion;
263 raw_string_ostream Out(FrontendVersion);
264 Out << Compile3.VersionFrontendMajor << '.' << Compile3.VersionFrontendMinor
265 << '.' << Compile3.VersionFrontendBuild << '.'
266 << Compile3.VersionFrontendQFE;
268 std::string BackendVersion;
270 raw_string_ostream Out(BackendVersion);
271 Out << Compile3.VersionBackendMajor << '.' << Compile3.VersionBackendMinor
272 << '.' << Compile3.VersionBackendBuild << '.'
273 << Compile3.VersionBackendQFE;
275 W.printString("FrontendVersion", FrontendVersion);
276 W.printString("BackendVersion", BackendVersion);
277 W.printString("VersionName", Compile3.Version);
278 return Error::success();
281 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
282 ConstantSym &Constant) {
283 printTypeIndex("Type", Constant.Type);
284 W.printNumber("Value", Constant.Value);
285 W.printString("Name", Constant.Name);
286 return Error::success();
289 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
290 StringRef LinkageName;
292 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
293 Data.DataOffset, &LinkageName);
295 printTypeIndex("Type", Data.Type);
296 W.printString("DisplayName", Data.Name);
297 if (!LinkageName.empty())
298 W.printString("LinkageName", LinkageName);
299 return Error::success();
302 Error CVSymbolDumperImpl::visitKnownRecord(
304 DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
305 W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset);
306 return Error::success();
309 Error CVSymbolDumperImpl::visitKnownRecord(
310 CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
311 W.printNumber("Offset", DefRangeFramePointerRel.Offset);
312 printLocalVariableAddrRange(DefRangeFramePointerRel.Range,
313 DefRangeFramePointerRel.getRelocationOffset());
314 printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
315 return Error::success();
318 Error CVSymbolDumperImpl::visitKnownRecord(
319 CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
320 W.printNumber("BaseRegister", DefRangeRegisterRel.Hdr.Register);
321 W.printBoolean("HasSpilledUDTMember",
322 DefRangeRegisterRel.hasSpilledUDTMember());
323 W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
324 W.printNumber("BasePointerOffset", DefRangeRegisterRel.Hdr.BasePointerOffset);
325 printLocalVariableAddrRange(DefRangeRegisterRel.Range,
326 DefRangeRegisterRel.getRelocationOffset());
327 printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
328 return Error::success();
331 Error CVSymbolDumperImpl::visitKnownRecord(
332 CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
333 W.printNumber("Register", DefRangeRegister.Hdr.Register);
334 W.printNumber("MayHaveNoName", DefRangeRegister.Hdr.MayHaveNoName);
335 printLocalVariableAddrRange(DefRangeRegister.Range,
336 DefRangeRegister.getRelocationOffset());
337 printLocalVariableAddrGap(DefRangeRegister.Gaps);
338 return Error::success();
341 Error CVSymbolDumperImpl::visitKnownRecord(
342 CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
343 W.printNumber("Register", DefRangeSubfieldRegister.Hdr.Register);
344 W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Hdr.MayHaveNoName);
345 W.printNumber("OffsetInParent", DefRangeSubfieldRegister.Hdr.OffsetInParent);
346 printLocalVariableAddrRange(DefRangeSubfieldRegister.Range,
347 DefRangeSubfieldRegister.getRelocationOffset());
348 printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
349 return Error::success();
352 Error CVSymbolDumperImpl::visitKnownRecord(
353 CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
355 DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable();
356 auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program);
357 if (!ExpectedProgram) {
358 consumeError(ExpectedProgram.takeError());
359 return llvm::make_error<CodeViewError>(
360 "String table offset outside of bounds of String Table!");
362 W.printString("Program", *ExpectedProgram);
364 W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent);
365 printLocalVariableAddrRange(DefRangeSubfield.Range,
366 DefRangeSubfield.getRelocationOffset());
367 printLocalVariableAddrGap(DefRangeSubfield.Gaps);
368 return Error::success();
371 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
372 DefRangeSym &DefRange) {
374 DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable();
375 auto ExpectedProgram = Strings.getString(DefRange.Program);
376 if (!ExpectedProgram) {
377 consumeError(ExpectedProgram.takeError());
378 return llvm::make_error<CodeViewError>(
379 "String table offset outside of bounds of String Table!");
381 W.printString("Program", *ExpectedProgram);
383 printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset());
384 printLocalVariableAddrGap(DefRange.Gaps);
385 return Error::success();
388 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
389 FrameCookieSym &FrameCookie) {
390 StringRef LinkageName;
392 ObjDelegate->printRelocatedField("CodeOffset",
393 FrameCookie.getRelocationOffset(),
394 FrameCookie.CodeOffset, &LinkageName);
396 W.printHex("Register", FrameCookie.Register);
397 W.printEnum("CookieKind", uint16_t(FrameCookie.CookieKind),
398 getFrameCookieKindNames());
399 W.printHex("Flags", FrameCookie.Flags);
400 return Error::success();
403 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
404 FrameProcSym &FrameProc) {
405 W.printHex("TotalFrameBytes", FrameProc.TotalFrameBytes);
406 W.printHex("PaddingFrameBytes", FrameProc.PaddingFrameBytes);
407 W.printHex("OffsetToPadding", FrameProc.OffsetToPadding);
408 W.printHex("BytesOfCalleeSavedRegisters",
409 FrameProc.BytesOfCalleeSavedRegisters);
410 W.printHex("OffsetOfExceptionHandler", FrameProc.OffsetOfExceptionHandler);
411 W.printHex("SectionIdOfExceptionHandler",
412 FrameProc.SectionIdOfExceptionHandler);
413 W.printFlags("Flags", static_cast<uint32_t>(FrameProc.Flags),
414 getFrameProcSymFlagNames());
415 return Error::success();
418 Error CVSymbolDumperImpl::visitKnownRecord(
419 CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
420 StringRef LinkageName;
422 ObjDelegate->printRelocatedField("CodeOffset",
423 HeapAllocSite.getRelocationOffset(),
424 HeapAllocSite.CodeOffset, &LinkageName);
426 W.printHex("Segment", HeapAllocSite.Segment);
427 W.printHex("CallInstructionSize", HeapAllocSite.CallInstructionSize);
428 printTypeIndex("Type", HeapAllocSite.Type);
429 if (!LinkageName.empty())
430 W.printString("LinkageName", LinkageName);
431 return Error::success();
434 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
435 InlineSiteSym &InlineSite) {
436 W.printHex("PtrParent", InlineSite.Parent);
437 W.printHex("PtrEnd", InlineSite.End);
438 printTypeIndex("Inlinee", InlineSite.Inlinee);
440 ListScope BinaryAnnotations(W, "BinaryAnnotations");
441 for (auto &Annotation : InlineSite.annotations()) {
442 switch (Annotation.OpCode) {
443 case BinaryAnnotationsOpCode::Invalid:
444 W.printString("(Annotation Padding)");
446 case BinaryAnnotationsOpCode::CodeOffset:
447 case BinaryAnnotationsOpCode::ChangeCodeOffset:
448 case BinaryAnnotationsOpCode::ChangeCodeLength:
449 W.printHex(Annotation.Name, Annotation.U1);
451 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
452 case BinaryAnnotationsOpCode::ChangeLineEndDelta:
453 case BinaryAnnotationsOpCode::ChangeRangeKind:
454 case BinaryAnnotationsOpCode::ChangeColumnStart:
455 case BinaryAnnotationsOpCode::ChangeColumnEnd:
456 W.printNumber(Annotation.Name, Annotation.U1);
458 case BinaryAnnotationsOpCode::ChangeLineOffset:
459 case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
460 W.printNumber(Annotation.Name, Annotation.S1);
462 case BinaryAnnotationsOpCode::ChangeFile:
464 W.printHex("ChangeFile",
465 ObjDelegate->getFileNameForFileOffset(Annotation.U1),
468 W.printHex("ChangeFile", Annotation.U1);
472 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
473 W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
474 << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1
478 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
479 W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
480 << W.hex(Annotation.U2)
481 << ", Length: " << W.hex(Annotation.U1) << "}\n";
486 return Error::success();
489 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
490 RegisterSym &Register) {
491 printTypeIndex("Type", Register.Index);
492 W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames());
493 W.printString("Name", Register.Name);
494 return Error::success();
497 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
498 W.printFlags("Flags", uint32_t(Public.Flags), getPublicSymFlagNames());
499 W.printNumber("Seg", Public.Segment);
500 W.printNumber("Off", Public.Offset);
501 W.printString("Name", Public.Name);
502 return Error::success();
505 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) {
506 W.printNumber("SumName", ProcRef.SumName);
507 W.printNumber("SymOffset", ProcRef.SymOffset);
508 W.printNumber("Mod", ProcRef.Module);
509 W.printString("Name", ProcRef.Name);
510 return Error::success();
513 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
514 StringRef LinkageName;
516 ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
517 Label.CodeOffset, &LinkageName);
519 W.printHex("Segment", Label.Segment);
520 W.printHex("Flags", uint8_t(Label.Flags));
521 W.printFlags("Flags", uint8_t(Label.Flags), getProcSymFlagNames());
522 W.printString("DisplayName", Label.Name);
523 if (!LinkageName.empty())
524 W.printString("LinkageName", LinkageName);
525 return Error::success();
528 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
529 printTypeIndex("Type", Local.Type);
530 W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames());
531 W.printString("VarName", Local.Name);
532 return Error::success();
535 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) {
536 W.printHex("Signature", ObjName.Signature);
537 W.printString("ObjectName", ObjName.Name);
538 return Error::success();
541 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
543 return llvm::make_error<CodeViewError>(
544 "Visiting a ProcSym while inside function scope!");
546 InFunctionScope = true;
548 StringRef LinkageName;
549 W.printHex("PtrParent", Proc.Parent);
550 W.printHex("PtrEnd", Proc.End);
551 W.printHex("PtrNext", Proc.Next);
552 W.printHex("CodeSize", Proc.CodeSize);
553 W.printHex("DbgStart", Proc.DbgStart);
554 W.printHex("DbgEnd", Proc.DbgEnd);
555 printTypeIndex("FunctionType", Proc.FunctionType);
557 ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
558 Proc.CodeOffset, &LinkageName);
560 W.printHex("Segment", Proc.Segment);
561 W.printFlags("Flags", static_cast<uint8_t>(Proc.Flags),
562 getProcSymFlagNames());
563 W.printString("DisplayName", Proc.Name);
564 if (!LinkageName.empty())
565 W.printString("LinkageName", LinkageName);
566 return Error::success();
569 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
570 ScopeEndSym &ScopeEnd) {
571 InFunctionScope = false;
572 return Error::success();
575 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
576 ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers");
577 for (auto FuncID : Caller.Indices)
578 printTypeIndex("FuncID", FuncID);
579 return Error::success();
582 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
583 RegRelativeSym &RegRel) {
584 W.printHex("Offset", RegRel.Offset);
585 printTypeIndex("Type", RegRel.Type);
586 W.printEnum("Register", uint16_t(RegRel.Register), getRegisterNames());
587 W.printString("VarName", RegRel.Name);
588 return Error::success();
591 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
592 ThreadLocalDataSym &Data) {
593 StringRef LinkageName;
595 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
596 Data.DataOffset, &LinkageName);
598 printTypeIndex("Type", Data.Type);
599 W.printString("DisplayName", Data.Name);
600 if (!LinkageName.empty())
601 W.printString("LinkageName", LinkageName);
602 return Error::success();
605 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
606 printTypeIndex("Type", UDT.Type);
607 W.printString("UDTName", UDT.Name);
608 return Error::success();
611 Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
612 W.printNumber("Length", CVR.length());
613 return Error::success();
616 Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
617 SymbolVisitorCallbackPipeline Pipeline;
618 SymbolDeserializer Deserializer(ObjDelegate.get(), Container);
619 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
621 Pipeline.addCallbackToPipeline(Deserializer);
622 Pipeline.addCallbackToPipeline(Dumper);
623 CVSymbolVisitor Visitor(Pipeline);
624 return Visitor.visitSymbolRecord(Record);
627 Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
628 SymbolVisitorCallbackPipeline Pipeline;
629 SymbolDeserializer Deserializer(ObjDelegate.get(), Container);
630 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
632 Pipeline.addCallbackToPipeline(Deserializer);
633 Pipeline.addCallbackToPipeline(Dumper);
634 CVSymbolVisitor Visitor(Pipeline);
635 return Visitor.visitSymbolStream(Symbols);