1 //===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
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/EnumTables.h"
15 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
16 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
17 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
18 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
19 #include "llvm/Support/ScopedPrinter.h"
20
21 #include <system_error>
22
23 using namespace llvm;
24 using namespace llvm::codeview;
25
26 namespace {
27 /// Use this private dumper implementation to keep implementation details about
28 /// the visitor out of SymbolDumper.h.
29 class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> {
30 public:
CVSymbolDumperImpl(CVTypeDumper & CVTD,SymbolDumpDelegate * ObjDelegate,ScopedPrinter & W,bool PrintRecordBytes)31 CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate,
32 ScopedPrinter &W, bool PrintRecordBytes)
33 : CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate),
34 W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
35
36 /// CVSymbolVisitor overrides.
37 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
38 void visit##Name(SymbolKind Kind, Name &Record);
39 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
40 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
41
42 void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data);
43 void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData);
44 void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data);
45
46 private:
47 void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
48 uint32_t RelocationOffset);
49 void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
50
51 CVTypeDumper &CVTD;
52 SymbolDumpDelegate *ObjDelegate;
53 ScopedPrinter &W;
54
55 bool PrintRecordBytes;
56 bool InFunctionScope;
57 };
58 }
59
printLocalVariableAddrRange(const LocalVariableAddrRange & Range,uint32_t RelocationOffset)60 void CVSymbolDumperImpl::printLocalVariableAddrRange(
61 const LocalVariableAddrRange &Range, uint32_t RelocationOffset) {
62 DictScope S(W, "LocalVariableAddrRange");
63 if (ObjDelegate)
64 ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset,
65 Range.OffsetStart);
66 W.printHex("ISectStart", Range.ISectStart);
67 W.printHex("Range", Range.Range);
68 }
69
printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps)70 void CVSymbolDumperImpl::printLocalVariableAddrGap(
71 ArrayRef<LocalVariableAddrGap> Gaps) {
72 for (auto &Gap : Gaps) {
73 ListScope S(W, "LocalVariableAddrGap");
74 W.printHex("GapStartOffset", Gap.GapStartOffset);
75 W.printHex("Range", Gap.Range);
76 }
77 }
78
visitSymbolBegin(SymbolKind Kind,ArrayRef<uint8_t> Data)79 void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind,
80 ArrayRef<uint8_t> Data) {}
81
visitSymbolEnd(SymbolKind Kind,ArrayRef<uint8_t> OriginalSymData)82 void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind,
83 ArrayRef<uint8_t> OriginalSymData) {
84 if (PrintRecordBytes && ObjDelegate)
85 ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData);
86 }
87
visitBlockSym(SymbolKind Kind,BlockSym & Block)88 void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
89 DictScope S(W, "BlockStart");
90
91 StringRef LinkageName;
92 W.printHex("PtrParent", Block.Header.PtrParent);
93 W.printHex("PtrEnd", Block.Header.PtrEnd);
94 W.printHex("CodeSize", Block.Header.CodeSize);
95 if (ObjDelegate) {
96 ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(),
97 Block.Header.CodeOffset, &LinkageName);
98 }
99 W.printHex("Segment", Block.Header.Segment);
100 W.printString("BlockName", Block.Name);
101 W.printString("LinkageName", LinkageName);
102 }
103
visitThunk32Sym(SymbolKind Kind,Thunk32Sym & Thunk)104 void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
105 DictScope S(W, "Thunk32");
106 W.printNumber("Parent", Thunk.Header.Parent);
107 W.printNumber("End", Thunk.Header.End);
108 W.printNumber("Next", Thunk.Header.Next);
109 W.printNumber("Off", Thunk.Header.Off);
110 W.printNumber("Seg", Thunk.Header.Seg);
111 W.printNumber("Len", Thunk.Header.Len);
112 W.printEnum("Ordinal", Thunk.Header.Ord, getThunkOrdinalNames());
113 }
114
visitTrampolineSym(SymbolKind Kind,TrampolineSym & Tramp)115 void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
116 TrampolineSym &Tramp) {
117 DictScope S(W, "Trampoline");
118 W.printEnum("Type", Tramp.Header.Type, getTrampolineNames());
119 W.printNumber("Size", Tramp.Header.Size);
120 W.printNumber("ThunkOff", Tramp.Header.ThunkOff);
121 W.printNumber("TargetOff", Tramp.Header.TargetOff);
122 W.printNumber("ThunkSection", Tramp.Header.ThunkSection);
123 W.printNumber("TargetSection", Tramp.Header.TargetSection);
124 }
125
visitSectionSym(SymbolKind Kind,SectionSym & Section)126 void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
127 DictScope S(W, "Section");
128 W.printNumber("SectionNumber", Section.Header.SectionNumber);
129 W.printNumber("Alignment", Section.Header.Alignment);
130 W.printNumber("Reserved", Section.Header.Reserved);
131 W.printNumber("Rva", Section.Header.Rva);
132 W.printNumber("Length", Section.Header.Length);
133 W.printFlags("Characteristics", Section.Header.Characteristics,
134 getImageSectionCharacteristicNames(),
135 COFF::SectionCharacteristics(0x00F00000));
136
137 W.printString("Name", Section.Name);
138 }
139
visitCoffGroupSym(SymbolKind Kind,CoffGroupSym & CoffGroup)140 void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
141 CoffGroupSym &CoffGroup) {
142 DictScope S(W, "COFF Group");
143 W.printNumber("Size", CoffGroup.Header.Size);
144 W.printFlags("Characteristics", CoffGroup.Header.Characteristics,
145 getImageSectionCharacteristicNames(),
146 COFF::SectionCharacteristics(0x00F00000));
147 W.printNumber("Offset", CoffGroup.Header.Offset);
148 W.printNumber("Segment", CoffGroup.Header.Segment);
149 W.printString("Name", CoffGroup.Name);
150 }
151
visitBPRelativeSym(SymbolKind Kind,BPRelativeSym & BPRel)152 void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind,
153 BPRelativeSym &BPRel) {
154 DictScope S(W, "BPRelativeSym");
155
156 W.printNumber("Offset", BPRel.Header.Offset);
157 CVTD.printTypeIndex("Type", BPRel.Header.Type);
158 W.printString("VarName", BPRel.Name);
159 }
160
visitBuildInfoSym(SymbolKind Kind,BuildInfoSym & BuildInfo)161 void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind,
162 BuildInfoSym &BuildInfo) {
163 DictScope S(W, "BuildInfo");
164
165 W.printNumber("BuildId", BuildInfo.Header.BuildId);
166 }
167
visitCallSiteInfoSym(SymbolKind Kind,CallSiteInfoSym & CallSiteInfo)168 void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
169 CallSiteInfoSym &CallSiteInfo) {
170 DictScope S(W, "CallSiteInfo");
171
172 StringRef LinkageName;
173 if (ObjDelegate) {
174 ObjDelegate->printRelocatedField(
175 "CodeOffset", CallSiteInfo.getRelocationOffset(),
176 CallSiteInfo.Header.CodeOffset, &LinkageName);
177 }
178 W.printHex("Segment", CallSiteInfo.Header.Segment);
179 W.printHex("Reserved", CallSiteInfo.Header.Reserved);
180 CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type);
181 if (!LinkageName.empty())
182 W.printString("LinkageName", LinkageName);
183 }
184
visitEnvBlockSym(SymbolKind Kind,EnvBlockSym & EnvBlock)185 void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
186 EnvBlockSym &EnvBlock) {
187 DictScope S(W, "EnvBlock");
188
189 W.printNumber("Reserved", EnvBlock.Header.Reserved);
190 ListScope L(W, "Entries");
191 for (auto Entry : EnvBlock.Fields) {
192 W.printString(Entry);
193 }
194 }
195
visitFileStaticSym(SymbolKind Kind,FileStaticSym & FileStatic)196 void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind,
197 FileStaticSym &FileStatic) {
198 DictScope S(W, "FileStatic");
199 W.printNumber("Index", FileStatic.Header.Index);
200 W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset);
201 W.printFlags("Flags", uint16_t(FileStatic.Header.Flags), getLocalFlagNames());
202 W.printString("Name", FileStatic.Name);
203 }
204
visitExportSym(SymbolKind Kind,ExportSym & Export)205 void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) {
206 DictScope S(W, "Export");
207 W.printNumber("Ordinal", Export.Header.Ordinal);
208 W.printFlags("Flags", Export.Header.Flags, getExportSymFlagNames());
209 W.printString("Name", Export.Name);
210 }
211
visitCompile2Sym(SymbolKind Kind,Compile2Sym & Compile2)212 void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
213 Compile2Sym &Compile2) {
214 DictScope S(W, "CompilerFlags2");
215
216 W.printEnum("Language", Compile2.Header.getLanguage(),
217 getSourceLanguageNames());
218 W.printFlags("Flags", Compile2.Header.flags & ~0xff,
219 getCompileSym2FlagNames());
220 W.printEnum("Machine", unsigned(Compile2.Header.Machine), getCPUTypeNames());
221 std::string FrontendVersion;
222 {
223 raw_string_ostream Out(FrontendVersion);
224 Out << Compile2.Header.VersionFrontendMajor << '.'
225 << Compile2.Header.VersionFrontendMinor << '.'
226 << Compile2.Header.VersionFrontendBuild;
227 }
228 std::string BackendVersion;
229 {
230 raw_string_ostream Out(BackendVersion);
231 Out << Compile2.Header.VersionBackendMajor << '.'
232 << Compile2.Header.VersionBackendMinor << '.'
233 << Compile2.Header.VersionBackendBuild;
234 }
235 W.printString("FrontendVersion", FrontendVersion);
236 W.printString("BackendVersion", BackendVersion);
237 W.printString("VersionName", Compile2.Version);
238 }
239
visitCompile3Sym(SymbolKind Kind,Compile3Sym & Compile3)240 void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
241 Compile3Sym &Compile3) {
242 DictScope S(W, "CompilerFlags3");
243
244 W.printEnum("Language", Compile3.Header.getLanguage(),
245 getSourceLanguageNames());
246 W.printFlags("Flags", Compile3.Header.flags & ~0xff,
247 getCompileSym3FlagNames());
248 W.printEnum("Machine", unsigned(Compile3.Header.Machine), getCPUTypeNames());
249 std::string FrontendVersion;
250 {
251 raw_string_ostream Out(FrontendVersion);
252 Out << Compile3.Header.VersionFrontendMajor << '.'
253 << Compile3.Header.VersionFrontendMinor << '.'
254 << Compile3.Header.VersionFrontendBuild << '.'
255 << Compile3.Header.VersionFrontendQFE;
256 }
257 std::string BackendVersion;
258 {
259 raw_string_ostream Out(BackendVersion);
260 Out << Compile3.Header.VersionBackendMajor << '.'
261 << Compile3.Header.VersionBackendMinor << '.'
262 << Compile3.Header.VersionBackendBuild << '.'
263 << Compile3.Header.VersionBackendQFE;
264 }
265 W.printString("FrontendVersion", FrontendVersion);
266 W.printString("BackendVersion", BackendVersion);
267 W.printString("VersionName", Compile3.Version);
268 }
269
visitConstantSym(SymbolKind Kind,ConstantSym & Constant)270 void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind,
271 ConstantSym &Constant) {
272 DictScope S(W, "Constant");
273
274 CVTD.printTypeIndex("Type", Constant.Header.Type);
275 W.printNumber("Value", Constant.Value);
276 W.printString("Name", Constant.Name);
277 }
278
visitDataSym(SymbolKind Kind,DataSym & Data)279 void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
280 DictScope S(W, "DataSym");
281
282 W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
283 StringRef LinkageName;
284 if (ObjDelegate) {
285 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
286 Data.Header.DataOffset, &LinkageName);
287 }
288 CVTD.printTypeIndex("Type", Data.Header.Type);
289 W.printString("DisplayName", Data.Name);
290 if (!LinkageName.empty())
291 W.printString("LinkageName", LinkageName);
292 }
293
visitDefRangeFramePointerRelFullScopeSym(SymbolKind Kind,DefRangeFramePointerRelFullScopeSym & DefRangeFramePointerRelFullScope)294 void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
295 SymbolKind Kind,
296 DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
297 DictScope S(W, "DefRangeFramePointerRelFullScope");
298 W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
299 }
300
visitDefRangeFramePointerRelSym(SymbolKind Kind,DefRangeFramePointerRelSym & DefRangeFramePointerRel)301 void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
302 SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
303 DictScope S(W, "DefRangeFramePointerRel");
304
305 W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
306 printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
307 DefRangeFramePointerRel.getRelocationOffset());
308 printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
309 }
310
visitDefRangeRegisterRelSym(SymbolKind Kind,DefRangeRegisterRelSym & DefRangeRegisterRel)311 void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
312 SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
313 DictScope S(W, "DefRangeRegisterRel");
314
315 W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
316 W.printBoolean("HasSpilledUDTMember",
317 DefRangeRegisterRel.hasSpilledUDTMember());
318 W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
319 W.printNumber("BasePointerOffset",
320 DefRangeRegisterRel.Header.BasePointerOffset);
321 printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
322 DefRangeRegisterRel.getRelocationOffset());
323 printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
324 }
325
visitDefRangeRegisterSym(SymbolKind Kind,DefRangeRegisterSym & DefRangeRegister)326 void CVSymbolDumperImpl::visitDefRangeRegisterSym(
327 SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
328 DictScope S(W, "DefRangeRegister");
329
330 W.printNumber("Register", DefRangeRegister.Header.Register);
331 W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName);
332 printLocalVariableAddrRange(DefRangeRegister.Header.Range,
333 DefRangeRegister.getRelocationOffset());
334 printLocalVariableAddrGap(DefRangeRegister.Gaps);
335 }
336
visitDefRangeSubfieldRegisterSym(SymbolKind Kind,DefRangeSubfieldRegisterSym & DefRangeSubfieldRegister)337 void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
338 SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
339 DictScope S(W, "DefRangeSubfieldRegister");
340
341 W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
342 W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName);
343 W.printNumber("OffsetInParent",
344 DefRangeSubfieldRegister.Header.OffsetInParent);
345 printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
346 DefRangeSubfieldRegister.getRelocationOffset());
347 printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
348 }
349
visitDefRangeSubfieldSym(SymbolKind Kind,DefRangeSubfieldSym & DefRangeSubfield)350 void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
351 SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
352 DictScope S(W, "DefRangeSubfield");
353
354 if (ObjDelegate) {
355 StringRef StringTable = ObjDelegate->getStringTable();
356 auto ProgramStringTableOffset = DefRangeSubfield.Header.Program;
357 if (ProgramStringTableOffset >= StringTable.size())
358 return parseError();
359 StringRef Program =
360 StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
361 W.printString("Program", Program);
362 }
363 W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent);
364 printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
365 DefRangeSubfield.getRelocationOffset());
366 printLocalVariableAddrGap(DefRangeSubfield.Gaps);
367 }
368
visitDefRangeSym(SymbolKind Kind,DefRangeSym & DefRange)369 void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
370 DefRangeSym &DefRange) {
371 DictScope S(W, "DefRange");
372
373 if (ObjDelegate) {
374 StringRef StringTable = ObjDelegate->getStringTable();
375 auto ProgramStringTableOffset = DefRange.Header.Program;
376 if (ProgramStringTableOffset >= StringTable.size())
377 return parseError();
378 StringRef Program =
379 StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
380 W.printString("Program", Program);
381 }
382 printLocalVariableAddrRange(DefRange.Header.Range,
383 DefRange.getRelocationOffset());
384 printLocalVariableAddrGap(DefRange.Gaps);
385 }
386
visitFrameCookieSym(SymbolKind Kind,FrameCookieSym & FrameCookie)387 void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
388 FrameCookieSym &FrameCookie) {
389 DictScope S(W, "FrameCookie");
390
391 StringRef LinkageName;
392 if (ObjDelegate) {
393 ObjDelegate->printRelocatedField(
394 "CodeOffset", FrameCookie.getRelocationOffset(),
395 FrameCookie.Header.CodeOffset, &LinkageName);
396 }
397 W.printHex("Register", FrameCookie.Header.Register);
398 W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
399 getFrameCookieKindNames());
400 W.printHex("Flags", FrameCookie.Header.Flags);
401 }
402
visitFrameProcSym(SymbolKind Kind,FrameProcSym & FrameProc)403 void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
404 FrameProcSym &FrameProc) {
405 DictScope S(W, "FrameProc");
406
407 W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes);
408 W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes);
409 W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding);
410 W.printHex("BytesOfCalleeSavedRegisters",
411 FrameProc.Header.BytesOfCalleeSavedRegisters);
412 W.printHex("OffsetOfExceptionHandler",
413 FrameProc.Header.OffsetOfExceptionHandler);
414 W.printHex("SectionIdOfExceptionHandler",
415 FrameProc.Header.SectionIdOfExceptionHandler);
416 W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames());
417 }
418
visitHeapAllocationSiteSym(SymbolKind Kind,HeapAllocationSiteSym & HeapAllocSite)419 void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
420 SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
421 DictScope S(W, "HeapAllocationSite");
422
423 StringRef LinkageName;
424 if (ObjDelegate) {
425 ObjDelegate->printRelocatedField(
426 "CodeOffset", HeapAllocSite.getRelocationOffset(),
427 HeapAllocSite.Header.CodeOffset, &LinkageName);
428 }
429 W.printHex("Segment", HeapAllocSite.Header.Segment);
430 W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize);
431 CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
432 if (!LinkageName.empty())
433 W.printString("LinkageName", LinkageName);
434 }
435
visitInlineSiteSym(SymbolKind Kind,InlineSiteSym & InlineSite)436 void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
437 InlineSiteSym &InlineSite) {
438 DictScope S(W, "InlineSite");
439
440 W.printHex("PtrParent", InlineSite.Header.PtrParent);
441 W.printHex("PtrEnd", InlineSite.Header.PtrEnd);
442 CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee);
443
444 ListScope BinaryAnnotations(W, "BinaryAnnotations");
445 for (auto &Annotation : InlineSite.annotations()) {
446 switch (Annotation.OpCode) {
447 case BinaryAnnotationsOpCode::Invalid:
448 return parseError();
449 case BinaryAnnotationsOpCode::CodeOffset:
450 case BinaryAnnotationsOpCode::ChangeCodeOffset:
451 case BinaryAnnotationsOpCode::ChangeCodeLength:
452 W.printHex(Annotation.Name, Annotation.U1);
453 break;
454 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
455 case BinaryAnnotationsOpCode::ChangeLineEndDelta:
456 case BinaryAnnotationsOpCode::ChangeRangeKind:
457 case BinaryAnnotationsOpCode::ChangeColumnStart:
458 case BinaryAnnotationsOpCode::ChangeColumnEnd:
459 W.printNumber(Annotation.Name, Annotation.U1);
460 break;
461 case BinaryAnnotationsOpCode::ChangeLineOffset:
462 case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
463 W.printNumber(Annotation.Name, Annotation.S1);
464 break;
465 case BinaryAnnotationsOpCode::ChangeFile:
466 if (ObjDelegate) {
467 W.printHex("ChangeFile",
468 ObjDelegate->getFileNameForFileOffset(Annotation.U1),
469 Annotation.U1);
470 } else {
471 W.printHex("ChangeFile", Annotation.U1);
472 }
473
474 break;
475 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
476 W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
477 << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1
478 << "}\n";
479 break;
480 }
481 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
482 W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
483 << W.hex(Annotation.U2)
484 << ", Length: " << W.hex(Annotation.U1) << "}\n";
485 break;
486 }
487 }
488 }
489 }
490
visitRegisterSym(SymbolKind Kind,RegisterSym & Register)491 void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind,
492 RegisterSym &Register) {
493 DictScope S(W, "RegisterSym");
494 W.printNumber("Type", Register.Header.Index);
495 W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames());
496 W.printString("Name", Register.Name);
497 }
498
visitPublicSym32(SymbolKind Kind,PublicSym32 & Public)499 void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind,
500 PublicSym32 &Public) {
501 DictScope S(W, "PublicSym");
502 W.printNumber("Type", Public.Header.Index);
503 W.printNumber("Seg", Public.Header.Seg);
504 W.printNumber("Off", Public.Header.Off);
505 W.printString("Name", Public.Name);
506 }
507
visitProcRefSym(SymbolKind Kind,ProcRefSym & ProcRef)508 void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) {
509 DictScope S(W, "ProcRef");
510 W.printNumber("SumName", ProcRef.Header.SumName);
511 W.printNumber("SymOffset", ProcRef.Header.SymOffset);
512 W.printNumber("Mod", ProcRef.Header.Mod);
513 W.printString("Name", ProcRef.Name);
514 }
515
visitLabelSym(SymbolKind Kind,LabelSym & Label)516 void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
517 DictScope S(W, "Label");
518
519 StringRef LinkageName;
520 if (ObjDelegate) {
521 ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
522 Label.Header.CodeOffset, &LinkageName);
523 }
524 W.printHex("Segment", Label.Header.Segment);
525 W.printHex("Flags", Label.Header.Flags);
526 W.printFlags("Flags", Label.Header.Flags, getProcSymFlagNames());
527 W.printString("DisplayName", Label.Name);
528 if (!LinkageName.empty())
529 W.printString("LinkageName", LinkageName);
530 }
531
visitLocalSym(SymbolKind Kind,LocalSym & Local)532 void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
533 DictScope S(W, "Local");
534
535 CVTD.printTypeIndex("Type", Local.Header.Type);
536 W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames());
537 W.printString("VarName", Local.Name);
538 }
539
visitObjNameSym(SymbolKind Kind,ObjNameSym & ObjName)540 void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
541 DictScope S(W, "ObjectName");
542
543 W.printHex("Signature", ObjName.Header.Signature);
544 W.printString("ObjectName", ObjName.Name);
545 }
546
visitProcSym(SymbolKind Kind,ProcSym & Proc)547 void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
548 DictScope S(W, "ProcStart");
549
550 if (InFunctionScope)
551 return parseError();
552
553 InFunctionScope = true;
554
555 StringRef LinkageName;
556 W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
557 W.printHex("PtrParent", Proc.Header.PtrParent);
558 W.printHex("PtrEnd", Proc.Header.PtrEnd);
559 W.printHex("PtrNext", Proc.Header.PtrNext);
560 W.printHex("CodeSize", Proc.Header.CodeSize);
561 W.printHex("DbgStart", Proc.Header.DbgStart);
562 W.printHex("DbgEnd", Proc.Header.DbgEnd);
563 CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType);
564 if (ObjDelegate) {
565 ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
566 Proc.Header.CodeOffset, &LinkageName);
567 }
568 W.printHex("Segment", Proc.Header.Segment);
569 W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags),
570 getProcSymFlagNames());
571 W.printString("DisplayName", Proc.Name);
572 if (!LinkageName.empty())
573 W.printString("LinkageName", LinkageName);
574 }
575
visitScopeEndSym(SymbolKind Kind,ScopeEndSym & ScopeEnd)576 void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
577 ScopeEndSym &ScopeEnd) {
578 if (Kind == SymbolKind::S_END)
579 DictScope S(W, "BlockEnd");
580 else if (Kind == SymbolKind::S_PROC_ID_END)
581 DictScope S(W, "ProcEnd");
582 else if (Kind == SymbolKind::S_INLINESITE_END)
583 DictScope S(W, "InlineSiteEnd");
584
585 InFunctionScope = false;
586 }
587
visitCallerSym(SymbolKind Kind,CallerSym & Caller)588 void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
589 ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
590 for (auto FuncID : Caller.Indices)
591 CVTD.printTypeIndex("FuncID", FuncID);
592 }
593
visitRegRelativeSym(SymbolKind Kind,RegRelativeSym & RegRel)594 void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
595 RegRelativeSym &RegRel) {
596 DictScope S(W, "RegRelativeSym");
597
598 W.printHex("Offset", RegRel.Header.Offset);
599 CVTD.printTypeIndex("Type", RegRel.Header.Type);
600 W.printHex("Register", RegRel.Header.Register);
601 W.printString("VarName", RegRel.Name);
602 }
603
visitThreadLocalDataSym(SymbolKind Kind,ThreadLocalDataSym & Data)604 void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
605 ThreadLocalDataSym &Data) {
606 DictScope S(W, "ThreadLocalDataSym");
607
608 StringRef LinkageName;
609 if (ObjDelegate) {
610 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
611 Data.Header.DataOffset, &LinkageName);
612 }
613 CVTD.printTypeIndex("Type", Data.Header.Type);
614 W.printString("DisplayName", Data.Name);
615 if (!LinkageName.empty())
616 W.printString("LinkageName", LinkageName);
617 }
618
visitUDTSym(SymbolKind Kind,UDTSym & UDT)619 void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
620 DictScope S(W, "UDT");
621 CVTD.printTypeIndex("Type", UDT.Header.Type);
622 W.printString("UDTName", UDT.Name);
623 }
624
visitUnknownSymbol(SymbolKind Kind,ArrayRef<uint8_t> Data)625 void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
626 ArrayRef<uint8_t> Data) {
627 DictScope S(W, "UnknownSym");
628 W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
629 W.printNumber("Length", uint32_t(Data.size()));
630 }
631
dump(const CVRecord<SymbolKind> & Record)632 bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
633 CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
634 Dumper.visitSymbolRecord(Record);
635 return !Dumper.hadError();
636 }
637
dump(const CVSymbolArray & Symbols)638 bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
639 CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
640 Dumper.visitSymbolStream(Symbols);
641 return !Dumper.hadError();
642 }
643