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 StringRef LinkageName; 283 if (ObjDelegate) { 284 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 285 Data.Header.DataOffset, &LinkageName); 286 } 287 CVTD.printTypeIndex("Type", Data.Header.Type); 288 W.printString("DisplayName", Data.Name); 289 if (!LinkageName.empty()) 290 W.printString("LinkageName", LinkageName); 291 } 292 293 void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym( 294 SymbolKind Kind, 295 DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { 296 DictScope S(W, "DefRangeFramePointerRelFullScope"); 297 W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset); 298 } 299 300 void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym( 301 SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { 302 DictScope S(W, "DefRangeFramePointerRel"); 303 304 W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset); 305 printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range, 306 DefRangeFramePointerRel.getRelocationOffset()); 307 printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); 308 } 309 310 void CVSymbolDumperImpl::visitDefRangeRegisterRelSym( 311 SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) { 312 DictScope S(W, "DefRangeRegisterRel"); 313 314 W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister); 315 W.printBoolean("HasSpilledUDTMember", 316 DefRangeRegisterRel.hasSpilledUDTMember()); 317 W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent()); 318 W.printNumber("BasePointerOffset", 319 DefRangeRegisterRel.Header.BasePointerOffset); 320 printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range, 321 DefRangeRegisterRel.getRelocationOffset()); 322 printLocalVariableAddrGap(DefRangeRegisterRel.Gaps); 323 } 324 325 void CVSymbolDumperImpl::visitDefRangeRegisterSym( 326 SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) { 327 DictScope S(W, "DefRangeRegister"); 328 329 W.printNumber("Register", DefRangeRegister.Header.Register); 330 W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName); 331 printLocalVariableAddrRange(DefRangeRegister.Header.Range, 332 DefRangeRegister.getRelocationOffset()); 333 printLocalVariableAddrGap(DefRangeRegister.Gaps); 334 } 335 336 void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym( 337 SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) { 338 DictScope S(W, "DefRangeSubfieldRegister"); 339 340 W.printNumber("Register", DefRangeSubfieldRegister.Header.Register); 341 W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName); 342 W.printNumber("OffsetInParent", 343 DefRangeSubfieldRegister.Header.OffsetInParent); 344 printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range, 345 DefRangeSubfieldRegister.getRelocationOffset()); 346 printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps); 347 } 348 349 void CVSymbolDumperImpl::visitDefRangeSubfieldSym( 350 SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) { 351 DictScope S(W, "DefRangeSubfield"); 352 353 if (ObjDelegate) { 354 StringRef StringTable = ObjDelegate->getStringTable(); 355 auto ProgramStringTableOffset = DefRangeSubfield.Header.Program; 356 if (ProgramStringTableOffset >= StringTable.size()) 357 return parseError(); 358 StringRef Program = 359 StringTable.drop_front(ProgramStringTableOffset).split('\0').first; 360 W.printString("Program", Program); 361 } 362 W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent); 363 printLocalVariableAddrRange(DefRangeSubfield.Header.Range, 364 DefRangeSubfield.getRelocationOffset()); 365 printLocalVariableAddrGap(DefRangeSubfield.Gaps); 366 } 367 368 void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind, 369 DefRangeSym &DefRange) { 370 DictScope S(W, "DefRange"); 371 372 if (ObjDelegate) { 373 StringRef StringTable = ObjDelegate->getStringTable(); 374 auto ProgramStringTableOffset = DefRange.Header.Program; 375 if (ProgramStringTableOffset >= StringTable.size()) 376 return parseError(); 377 StringRef Program = 378 StringTable.drop_front(ProgramStringTableOffset).split('\0').first; 379 W.printString("Program", Program); 380 } 381 printLocalVariableAddrRange(DefRange.Header.Range, 382 DefRange.getRelocationOffset()); 383 printLocalVariableAddrGap(DefRange.Gaps); 384 } 385 386 void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind, 387 FrameCookieSym &FrameCookie) { 388 DictScope S(W, "FrameCookie"); 389 390 StringRef LinkageName; 391 if (ObjDelegate) { 392 ObjDelegate->printRelocatedField( 393 "CodeOffset", FrameCookie.getRelocationOffset(), 394 FrameCookie.Header.CodeOffset, &LinkageName); 395 } 396 W.printHex("Register", FrameCookie.Header.Register); 397 W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind), 398 getFrameCookieKindNames()); 399 } 400 401 void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind, 402 FrameProcSym &FrameProc) { 403 DictScope S(W, "FrameProc"); 404 405 W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes); 406 W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes); 407 W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding); 408 W.printHex("BytesOfCalleeSavedRegisters", 409 FrameProc.Header.BytesOfCalleeSavedRegisters); 410 W.printHex("OffsetOfExceptionHandler", 411 FrameProc.Header.OffsetOfExceptionHandler); 412 W.printHex("SectionIdOfExceptionHandler", 413 FrameProc.Header.SectionIdOfExceptionHandler); 414 W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames()); 415 } 416 417 void CVSymbolDumperImpl::visitHeapAllocationSiteSym( 418 SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) { 419 DictScope S(W, "HeapAllocationSite"); 420 421 StringRef LinkageName; 422 if (ObjDelegate) { 423 ObjDelegate->printRelocatedField( 424 "CodeOffset", HeapAllocSite.getRelocationOffset(), 425 HeapAllocSite.Header.CodeOffset, &LinkageName); 426 } 427 W.printHex("Segment", HeapAllocSite.Header.Segment); 428 W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize); 429 CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type); 430 if (!LinkageName.empty()) 431 W.printString("LinkageName", LinkageName); 432 } 433 434 void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind, 435 InlineSiteSym &InlineSite) { 436 DictScope S(W, "InlineSite"); 437 438 W.printHex("PtrParent", InlineSite.Header.PtrParent); 439 W.printHex("PtrEnd", InlineSite.Header.PtrEnd); 440 CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee); 441 442 ListScope BinaryAnnotations(W, "BinaryAnnotations"); 443 for (auto &Annotation : InlineSite.annotations()) { 444 switch (Annotation.OpCode) { 445 case BinaryAnnotationsOpCode::Invalid: 446 return parseError(); 447 case BinaryAnnotationsOpCode::CodeOffset: 448 case BinaryAnnotationsOpCode::ChangeCodeOffset: 449 case BinaryAnnotationsOpCode::ChangeCodeLength: 450 W.printHex(Annotation.Name, Annotation.U1); 451 break; 452 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: 453 case BinaryAnnotationsOpCode::ChangeLineEndDelta: 454 case BinaryAnnotationsOpCode::ChangeRangeKind: 455 case BinaryAnnotationsOpCode::ChangeColumnStart: 456 case BinaryAnnotationsOpCode::ChangeColumnEnd: 457 W.printNumber(Annotation.Name, Annotation.U1); 458 break; 459 case BinaryAnnotationsOpCode::ChangeLineOffset: 460 case BinaryAnnotationsOpCode::ChangeColumnEndDelta: 461 W.printNumber(Annotation.Name, Annotation.S1); 462 break; 463 case BinaryAnnotationsOpCode::ChangeFile: 464 if (ObjDelegate) { 465 W.printHex("ChangeFile", 466 ObjDelegate->getFileNameForFileOffset(Annotation.U1), 467 Annotation.U1); 468 } else { 469 W.printHex("ChangeFile", Annotation.U1); 470 } 471 472 break; 473 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: { 474 W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: " 475 << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1 476 << "}\n"; 477 break; 478 } 479 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: { 480 W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: " 481 << W.hex(Annotation.U2) 482 << ", Length: " << W.hex(Annotation.U1) << "}\n"; 483 break; 484 } 485 } 486 } 487 } 488 489 void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind, 490 RegisterSym &Register) { 491 DictScope S(W, "RegisterSym"); 492 W.printNumber("Type", Register.Header.Index); 493 W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames()); 494 W.printString("Name", Register.Name); 495 } 496 497 void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind, 498 PublicSym32 &Public) { 499 DictScope S(W, "PublicSym"); 500 W.printNumber("Type", Public.Header.Index); 501 W.printNumber("Seg", Public.Header.Seg); 502 W.printNumber("Off", Public.Header.Off); 503 W.printString("Name", Public.Name); 504 } 505 506 void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) { 507 DictScope S(W, "ProcRef"); 508 W.printNumber("SumName", ProcRef.Header.SumName); 509 W.printNumber("SymOffset", ProcRef.Header.SymOffset); 510 W.printNumber("Mod", ProcRef.Header.Mod); 511 W.printString("Name", ProcRef.Name); 512 } 513 514 void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) { 515 DictScope S(W, "Label"); 516 517 StringRef LinkageName; 518 if (ObjDelegate) { 519 ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(), 520 Label.Header.CodeOffset, &LinkageName); 521 } 522 W.printHex("Segment", Label.Header.Segment); 523 W.printHex("Flags", Label.Header.Flags); 524 W.printFlags("Flags", Label.Header.Flags, getProcSymFlagNames()); 525 W.printString("DisplayName", Label.Name); 526 if (!LinkageName.empty()) 527 W.printString("LinkageName", LinkageName); 528 } 529 530 void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) { 531 DictScope S(W, "Local"); 532 533 CVTD.printTypeIndex("Type", Local.Header.Type); 534 W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames()); 535 W.printString("VarName", Local.Name); 536 } 537 538 void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) { 539 DictScope S(W, "ObjectName"); 540 541 W.printHex("Signature", ObjName.Header.Signature); 542 W.printString("ObjectName", ObjName.Name); 543 } 544 545 void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) { 546 DictScope S(W, "ProcStart"); 547 548 if (InFunctionScope) 549 return parseError(); 550 551 InFunctionScope = true; 552 553 StringRef LinkageName; 554 W.printHex("PtrParent", Proc.Header.PtrParent); 555 W.printHex("PtrEnd", Proc.Header.PtrEnd); 556 W.printHex("PtrNext", Proc.Header.PtrNext); 557 W.printHex("CodeSize", Proc.Header.CodeSize); 558 W.printHex("DbgStart", Proc.Header.DbgStart); 559 W.printHex("DbgEnd", Proc.Header.DbgEnd); 560 CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType); 561 if (ObjDelegate) { 562 ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(), 563 Proc.Header.CodeOffset, &LinkageName); 564 } 565 W.printHex("Segment", Proc.Header.Segment); 566 W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags), 567 getProcSymFlagNames()); 568 W.printString("DisplayName", Proc.Name); 569 if (!LinkageName.empty()) 570 W.printString("LinkageName", LinkageName); 571 } 572 573 void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind, 574 ScopeEndSym &ScopeEnd) { 575 if (Kind == SymbolKind::S_END) 576 DictScope S(W, "BlockEnd"); 577 else if (Kind == SymbolKind::S_PROC_ID_END) 578 DictScope S(W, "ProcEnd"); 579 else if (Kind == SymbolKind::S_INLINESITE_END) 580 DictScope S(W, "InlineSiteEnd"); 581 582 InFunctionScope = false; 583 } 584 585 void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) { 586 ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers"); 587 for (auto FuncID : Caller.Indices) 588 CVTD.printTypeIndex("FuncID", FuncID); 589 } 590 591 void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind, 592 RegRelativeSym &RegRel) { 593 DictScope S(W, "RegRelativeSym"); 594 595 W.printHex("Offset", RegRel.Header.Offset); 596 CVTD.printTypeIndex("Type", RegRel.Header.Type); 597 W.printHex("Register", RegRel.Header.Register); 598 W.printString("VarName", RegRel.Name); 599 } 600 601 void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind, 602 ThreadLocalDataSym &Data) { 603 DictScope S(W, "ThreadLocalDataSym"); 604 605 StringRef LinkageName; 606 if (ObjDelegate) { 607 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 608 Data.Header.DataOffset, &LinkageName); 609 } 610 CVTD.printTypeIndex("Type", Data.Header.Type); 611 W.printString("DisplayName", Data.Name); 612 if (!LinkageName.empty()) 613 W.printString("LinkageName", LinkageName); 614 } 615 616 void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) { 617 DictScope S(W, "UDT"); 618 CVTD.printTypeIndex("Type", UDT.Header.Type); 619 W.printString("UDTName", UDT.Name); 620 } 621 622 void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind, 623 ArrayRef<uint8_t> Data) { 624 DictScope S(W, "UnknownSym"); 625 W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames()); 626 W.printNumber("Length", uint32_t(Data.size())); 627 } 628 629 bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) { 630 CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); 631 Dumper.visitSymbolRecord(Record); 632 return !Dumper.hadError(); 633 } 634 635 bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) { 636 CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); 637 Dumper.visitSymbolStream(Symbols); 638 return !Dumper.hadError(); 639 } 640