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: 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 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 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 79 void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind, 80 ArrayRef<uint8_t> Data) {} 81 82 void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind, 83 ArrayRef<uint8_t> OriginalSymData) { 84 if (PrintRecordBytes && ObjDelegate) 85 ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData); 86 } 87 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 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 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 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 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 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 161 void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind, 162 BuildInfoSym &BuildInfo) { 163 DictScope S(W, "BuildInfo"); 164 165 W.printNumber("BuildId", BuildInfo.Header.BuildId); 166 } 167 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 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 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 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 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 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 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 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 294 void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym( 295 SymbolKind Kind, 296 DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { 297 DictScope S(W, "DefRangeFramePointerRelFullScope"); 298 W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset); 299 } 300 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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