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 W.printHex("Flags", FrameCookie.Header.Flags); 400 } 401 402 void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind, 403 FrameProcSym &FrameProc) { 404 DictScope S(W, "FrameProc"); 405 406 W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes); 407 W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes); 408 W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding); 409 W.printHex("BytesOfCalleeSavedRegisters", 410 FrameProc.Header.BytesOfCalleeSavedRegisters); 411 W.printHex("OffsetOfExceptionHandler", 412 FrameProc.Header.OffsetOfExceptionHandler); 413 W.printHex("SectionIdOfExceptionHandler", 414 FrameProc.Header.SectionIdOfExceptionHandler); 415 W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames()); 416 } 417 418 void CVSymbolDumperImpl::visitHeapAllocationSiteSym( 419 SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) { 420 DictScope S(W, "HeapAllocationSite"); 421 422 StringRef LinkageName; 423 if (ObjDelegate) { 424 ObjDelegate->printRelocatedField( 425 "CodeOffset", HeapAllocSite.getRelocationOffset(), 426 HeapAllocSite.Header.CodeOffset, &LinkageName); 427 } 428 W.printHex("Segment", HeapAllocSite.Header.Segment); 429 W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize); 430 CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type); 431 if (!LinkageName.empty()) 432 W.printString("LinkageName", LinkageName); 433 } 434 435 void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind, 436 InlineSiteSym &InlineSite) { 437 DictScope S(W, "InlineSite"); 438 439 W.printHex("PtrParent", InlineSite.Header.PtrParent); 440 W.printHex("PtrEnd", InlineSite.Header.PtrEnd); 441 CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee); 442 443 ListScope BinaryAnnotations(W, "BinaryAnnotations"); 444 for (auto &Annotation : InlineSite.annotations()) { 445 switch (Annotation.OpCode) { 446 case BinaryAnnotationsOpCode::Invalid: 447 return parseError(); 448 case BinaryAnnotationsOpCode::CodeOffset: 449 case BinaryAnnotationsOpCode::ChangeCodeOffset: 450 case BinaryAnnotationsOpCode::ChangeCodeLength: 451 W.printHex(Annotation.Name, Annotation.U1); 452 break; 453 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: 454 case BinaryAnnotationsOpCode::ChangeLineEndDelta: 455 case BinaryAnnotationsOpCode::ChangeRangeKind: 456 case BinaryAnnotationsOpCode::ChangeColumnStart: 457 case BinaryAnnotationsOpCode::ChangeColumnEnd: 458 W.printNumber(Annotation.Name, Annotation.U1); 459 break; 460 case BinaryAnnotationsOpCode::ChangeLineOffset: 461 case BinaryAnnotationsOpCode::ChangeColumnEndDelta: 462 W.printNumber(Annotation.Name, Annotation.S1); 463 break; 464 case BinaryAnnotationsOpCode::ChangeFile: 465 if (ObjDelegate) { 466 W.printHex("ChangeFile", 467 ObjDelegate->getFileNameForFileOffset(Annotation.U1), 468 Annotation.U1); 469 } else { 470 W.printHex("ChangeFile", Annotation.U1); 471 } 472 473 break; 474 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: { 475 W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: " 476 << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1 477 << "}\n"; 478 break; 479 } 480 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: { 481 W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: " 482 << W.hex(Annotation.U2) 483 << ", Length: " << W.hex(Annotation.U1) << "}\n"; 484 break; 485 } 486 } 487 } 488 } 489 490 void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind, 491 RegisterSym &Register) { 492 DictScope S(W, "RegisterSym"); 493 W.printNumber("Type", Register.Header.Index); 494 W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames()); 495 W.printString("Name", Register.Name); 496 } 497 498 void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind, 499 PublicSym32 &Public) { 500 DictScope S(W, "PublicSym"); 501 W.printNumber("Type", Public.Header.Index); 502 W.printNumber("Seg", Public.Header.Seg); 503 W.printNumber("Off", Public.Header.Off); 504 W.printString("Name", Public.Name); 505 } 506 507 void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) { 508 DictScope S(W, "ProcRef"); 509 W.printNumber("SumName", ProcRef.Header.SumName); 510 W.printNumber("SymOffset", ProcRef.Header.SymOffset); 511 W.printNumber("Mod", ProcRef.Header.Mod); 512 W.printString("Name", ProcRef.Name); 513 } 514 515 void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) { 516 DictScope S(W, "Label"); 517 518 StringRef LinkageName; 519 if (ObjDelegate) { 520 ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(), 521 Label.Header.CodeOffset, &LinkageName); 522 } 523 W.printHex("Segment", Label.Header.Segment); 524 W.printHex("Flags", Label.Header.Flags); 525 W.printFlags("Flags", Label.Header.Flags, getProcSymFlagNames()); 526 W.printString("DisplayName", Label.Name); 527 if (!LinkageName.empty()) 528 W.printString("LinkageName", LinkageName); 529 } 530 531 void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) { 532 DictScope S(W, "Local"); 533 534 CVTD.printTypeIndex("Type", Local.Header.Type); 535 W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames()); 536 W.printString("VarName", Local.Name); 537 } 538 539 void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) { 540 DictScope S(W, "ObjectName"); 541 542 W.printHex("Signature", ObjName.Header.Signature); 543 W.printString("ObjectName", ObjName.Name); 544 } 545 546 void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) { 547 DictScope S(W, "ProcStart"); 548 549 if (InFunctionScope) 550 return parseError(); 551 552 InFunctionScope = true; 553 554 StringRef LinkageName; 555 W.printHex("PtrParent", Proc.Header.PtrParent); 556 W.printHex("PtrEnd", Proc.Header.PtrEnd); 557 W.printHex("PtrNext", Proc.Header.PtrNext); 558 W.printHex("CodeSize", Proc.Header.CodeSize); 559 W.printHex("DbgStart", Proc.Header.DbgStart); 560 W.printHex("DbgEnd", Proc.Header.DbgEnd); 561 CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType); 562 if (ObjDelegate) { 563 ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(), 564 Proc.Header.CodeOffset, &LinkageName); 565 } 566 W.printHex("Segment", Proc.Header.Segment); 567 W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags), 568 getProcSymFlagNames()); 569 W.printString("DisplayName", Proc.Name); 570 if (!LinkageName.empty()) 571 W.printString("LinkageName", LinkageName); 572 } 573 574 void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind, 575 ScopeEndSym &ScopeEnd) { 576 if (Kind == SymbolKind::S_END) 577 DictScope S(W, "BlockEnd"); 578 else if (Kind == SymbolKind::S_PROC_ID_END) 579 DictScope S(W, "ProcEnd"); 580 else if (Kind == SymbolKind::S_INLINESITE_END) 581 DictScope S(W, "InlineSiteEnd"); 582 583 InFunctionScope = false; 584 } 585 586 void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) { 587 ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers"); 588 for (auto FuncID : Caller.Indices) 589 CVTD.printTypeIndex("FuncID", FuncID); 590 } 591 592 void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind, 593 RegRelativeSym &RegRel) { 594 DictScope S(W, "RegRelativeSym"); 595 596 W.printHex("Offset", RegRel.Header.Offset); 597 CVTD.printTypeIndex("Type", RegRel.Header.Type); 598 W.printHex("Register", RegRel.Header.Register); 599 W.printString("VarName", RegRel.Name); 600 } 601 602 void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind, 603 ThreadLocalDataSym &Data) { 604 DictScope S(W, "ThreadLocalDataSym"); 605 606 StringRef LinkageName; 607 if (ObjDelegate) { 608 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 609 Data.Header.DataOffset, &LinkageName); 610 } 611 CVTD.printTypeIndex("Type", Data.Header.Type); 612 W.printString("DisplayName", Data.Name); 613 if (!LinkageName.empty()) 614 W.printString("LinkageName", LinkageName); 615 } 616 617 void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) { 618 DictScope S(W, "UDT"); 619 CVTD.printTypeIndex("Type", UDT.Header.Type); 620 W.printString("UDTName", UDT.Name); 621 } 622 623 void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind, 624 ArrayRef<uint8_t> Data) { 625 DictScope S(W, "UnknownSym"); 626 W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames()); 627 W.printNumber("Length", uint32_t(Data.size())); 628 } 629 630 bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) { 631 CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); 632 Dumper.visitSymbolRecord(Record); 633 return !Dumper.hadError(); 634 } 635 636 bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) { 637 CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); 638 Dumper.visitSymbolStream(Symbols); 639 return !Dumper.hadError(); 640 } 641