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