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", Compile3.getLanguage(), getSourceLanguageNames()); 265 W.printFlags("Flags", Compile3.getFlags(), getCompileSym3FlagNames()); 266 W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames()); 267 CompilationCPUType = Compile3.Machine; 268 std::string FrontendVersion; 269 { 270 raw_string_ostream Out(FrontendVersion); 271 Out << Compile3.VersionFrontendMajor << '.' << Compile3.VersionFrontendMinor 272 << '.' << Compile3.VersionFrontendBuild << '.' 273 << Compile3.VersionFrontendQFE; 274 } 275 std::string BackendVersion; 276 { 277 raw_string_ostream Out(BackendVersion); 278 Out << Compile3.VersionBackendMajor << '.' << Compile3.VersionBackendMinor 279 << '.' << Compile3.VersionBackendBuild << '.' 280 << Compile3.VersionBackendQFE; 281 } 282 W.printString("FrontendVersion", FrontendVersion); 283 W.printString("BackendVersion", BackendVersion); 284 W.printString("VersionName", Compile3.Version); 285 return Error::success(); 286 } 287 288 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 289 ConstantSym &Constant) { 290 printTypeIndex("Type", Constant.Type); 291 W.printNumber("Value", Constant.Value); 292 W.printString("Name", Constant.Name); 293 return Error::success(); 294 } 295 296 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) { 297 StringRef LinkageName; 298 if (ObjDelegate) { 299 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 300 Data.DataOffset, &LinkageName); 301 } 302 printTypeIndex("Type", Data.Type); 303 W.printString("DisplayName", Data.Name); 304 if (!LinkageName.empty()) 305 W.printString("LinkageName", LinkageName); 306 return Error::success(); 307 } 308 309 Error CVSymbolDumperImpl::visitKnownRecord( 310 CVSymbol &CVR, 311 DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { 312 W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset); 313 return Error::success(); 314 } 315 316 Error CVSymbolDumperImpl::visitKnownRecord( 317 CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { 318 W.printNumber("Offset", DefRangeFramePointerRel.Offset); 319 printLocalVariableAddrRange(DefRangeFramePointerRel.Range, 320 DefRangeFramePointerRel.getRelocationOffset()); 321 printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); 322 return Error::success(); 323 } 324 325 Error CVSymbolDumperImpl::visitKnownRecord( 326 CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) { 327 W.printEnum("BaseRegister", uint16_t(DefRangeRegisterRel.Hdr.Register), 328 getRegisterNames()); 329 W.printBoolean("HasSpilledUDTMember", 330 DefRangeRegisterRel.hasSpilledUDTMember()); 331 W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent()); 332 W.printNumber("BasePointerOffset", DefRangeRegisterRel.Hdr.BasePointerOffset); 333 printLocalVariableAddrRange(DefRangeRegisterRel.Range, 334 DefRangeRegisterRel.getRelocationOffset()); 335 printLocalVariableAddrGap(DefRangeRegisterRel.Gaps); 336 return Error::success(); 337 } 338 339 Error CVSymbolDumperImpl::visitKnownRecord( 340 CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) { 341 W.printEnum("Register", uint16_t(DefRangeRegister.Hdr.Register), 342 getRegisterNames()); 343 W.printNumber("MayHaveNoName", DefRangeRegister.Hdr.MayHaveNoName); 344 printLocalVariableAddrRange(DefRangeRegister.Range, 345 DefRangeRegister.getRelocationOffset()); 346 printLocalVariableAddrGap(DefRangeRegister.Gaps); 347 return Error::success(); 348 } 349 350 Error CVSymbolDumperImpl::visitKnownRecord( 351 CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) { 352 W.printEnum("Register", uint16_t(DefRangeSubfieldRegister.Hdr.Register), 353 getRegisterNames()); 354 W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Hdr.MayHaveNoName); 355 W.printNumber("OffsetInParent", DefRangeSubfieldRegister.Hdr.OffsetInParent); 356 printLocalVariableAddrRange(DefRangeSubfieldRegister.Range, 357 DefRangeSubfieldRegister.getRelocationOffset()); 358 printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps); 359 return Error::success(); 360 } 361 362 Error CVSymbolDumperImpl::visitKnownRecord( 363 CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) { 364 if (ObjDelegate) { 365 DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); 366 auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program); 367 if (!ExpectedProgram) { 368 consumeError(ExpectedProgram.takeError()); 369 return llvm::make_error<CodeViewError>( 370 "String table offset outside of bounds of String Table!"); 371 } 372 W.printString("Program", *ExpectedProgram); 373 } 374 W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent); 375 printLocalVariableAddrRange(DefRangeSubfield.Range, 376 DefRangeSubfield.getRelocationOffset()); 377 printLocalVariableAddrGap(DefRangeSubfield.Gaps); 378 return Error::success(); 379 } 380 381 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 382 DefRangeSym &DefRange) { 383 if (ObjDelegate) { 384 DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); 385 auto ExpectedProgram = Strings.getString(DefRange.Program); 386 if (!ExpectedProgram) { 387 consumeError(ExpectedProgram.takeError()); 388 return llvm::make_error<CodeViewError>( 389 "String table offset outside of bounds of String Table!"); 390 } 391 W.printString("Program", *ExpectedProgram); 392 } 393 printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset()); 394 printLocalVariableAddrGap(DefRange.Gaps); 395 return Error::success(); 396 } 397 398 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 399 FrameCookieSym &FrameCookie) { 400 StringRef LinkageName; 401 if (ObjDelegate) { 402 ObjDelegate->printRelocatedField("CodeOffset", 403 FrameCookie.getRelocationOffset(), 404 FrameCookie.CodeOffset, &LinkageName); 405 } 406 W.printEnum("Register", uint16_t(FrameCookie.Register), getRegisterNames()); 407 W.printEnum("CookieKind", uint16_t(FrameCookie.CookieKind), 408 getFrameCookieKindNames()); 409 W.printHex("Flags", FrameCookie.Flags); 410 return Error::success(); 411 } 412 413 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 414 FrameProcSym &FrameProc) { 415 W.printHex("TotalFrameBytes", FrameProc.TotalFrameBytes); 416 W.printHex("PaddingFrameBytes", FrameProc.PaddingFrameBytes); 417 W.printHex("OffsetToPadding", FrameProc.OffsetToPadding); 418 W.printHex("BytesOfCalleeSavedRegisters", 419 FrameProc.BytesOfCalleeSavedRegisters); 420 W.printHex("OffsetOfExceptionHandler", FrameProc.OffsetOfExceptionHandler); 421 W.printHex("SectionIdOfExceptionHandler", 422 FrameProc.SectionIdOfExceptionHandler); 423 W.printFlags("Flags", static_cast<uint32_t>(FrameProc.Flags), 424 getFrameProcSymFlagNames()); 425 W.printEnum("LocalFramePtrReg", 426 uint16_t(FrameProc.getLocalFramePtrReg(CompilationCPUType)), 427 getRegisterNames()); 428 W.printEnum("ParamFramePtrReg", 429 uint16_t(FrameProc.getParamFramePtrReg(CompilationCPUType)), 430 getRegisterNames()); 431 return Error::success(); 432 } 433 434 Error CVSymbolDumperImpl::visitKnownRecord( 435 CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) { 436 StringRef LinkageName; 437 if (ObjDelegate) { 438 ObjDelegate->printRelocatedField("CodeOffset", 439 HeapAllocSite.getRelocationOffset(), 440 HeapAllocSite.CodeOffset, &LinkageName); 441 } 442 W.printHex("Segment", HeapAllocSite.Segment); 443 W.printHex("CallInstructionSize", HeapAllocSite.CallInstructionSize); 444 printTypeIndex("Type", HeapAllocSite.Type); 445 if (!LinkageName.empty()) 446 W.printString("LinkageName", LinkageName); 447 return Error::success(); 448 } 449 450 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 451 InlineSiteSym &InlineSite) { 452 W.printHex("PtrParent", InlineSite.Parent); 453 W.printHex("PtrEnd", InlineSite.End); 454 printTypeIndex("Inlinee", InlineSite.Inlinee); 455 456 ListScope BinaryAnnotations(W, "BinaryAnnotations"); 457 for (auto &Annotation : InlineSite.annotations()) { 458 switch (Annotation.OpCode) { 459 case BinaryAnnotationsOpCode::Invalid: 460 W.printString("(Annotation Padding)"); 461 break; 462 case BinaryAnnotationsOpCode::CodeOffset: 463 case BinaryAnnotationsOpCode::ChangeCodeOffset: 464 case BinaryAnnotationsOpCode::ChangeCodeLength: 465 W.printHex(Annotation.Name, Annotation.U1); 466 break; 467 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: 468 case BinaryAnnotationsOpCode::ChangeLineEndDelta: 469 case BinaryAnnotationsOpCode::ChangeRangeKind: 470 case BinaryAnnotationsOpCode::ChangeColumnStart: 471 case BinaryAnnotationsOpCode::ChangeColumnEnd: 472 W.printNumber(Annotation.Name, Annotation.U1); 473 break; 474 case BinaryAnnotationsOpCode::ChangeLineOffset: 475 case BinaryAnnotationsOpCode::ChangeColumnEndDelta: 476 W.printNumber(Annotation.Name, Annotation.S1); 477 break; 478 case BinaryAnnotationsOpCode::ChangeFile: 479 if (ObjDelegate) { 480 W.printHex("ChangeFile", 481 ObjDelegate->getFileNameForFileOffset(Annotation.U1), 482 Annotation.U1); 483 } else { 484 W.printHex("ChangeFile", Annotation.U1); 485 } 486 487 break; 488 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: { 489 W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: " 490 << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1 491 << "}\n"; 492 break; 493 } 494 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: { 495 W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: " 496 << W.hex(Annotation.U2) 497 << ", Length: " << W.hex(Annotation.U1) << "}\n"; 498 break; 499 } 500 } 501 } 502 return Error::success(); 503 } 504 505 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 506 RegisterSym &Register) { 507 printTypeIndex("Type", Register.Index); 508 W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames()); 509 W.printString("Name", Register.Name); 510 return Error::success(); 511 } 512 513 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) { 514 W.printFlags("Flags", uint32_t(Public.Flags), getPublicSymFlagNames()); 515 W.printNumber("Seg", Public.Segment); 516 W.printNumber("Off", Public.Offset); 517 W.printString("Name", Public.Name); 518 return Error::success(); 519 } 520 521 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) { 522 W.printNumber("SumName", ProcRef.SumName); 523 W.printNumber("SymOffset", ProcRef.SymOffset); 524 W.printNumber("Mod", ProcRef.Module); 525 W.printString("Name", ProcRef.Name); 526 return Error::success(); 527 } 528 529 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) { 530 StringRef LinkageName; 531 if (ObjDelegate) { 532 ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(), 533 Label.CodeOffset, &LinkageName); 534 } 535 W.printHex("Segment", Label.Segment); 536 W.printHex("Flags", uint8_t(Label.Flags)); 537 W.printFlags("Flags", uint8_t(Label.Flags), getProcSymFlagNames()); 538 W.printString("DisplayName", Label.Name); 539 if (!LinkageName.empty()) 540 W.printString("LinkageName", LinkageName); 541 return Error::success(); 542 } 543 544 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) { 545 printTypeIndex("Type", Local.Type); 546 W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames()); 547 W.printString("VarName", Local.Name); 548 return Error::success(); 549 } 550 551 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) { 552 W.printHex("Signature", ObjName.Signature); 553 W.printString("ObjectName", ObjName.Name); 554 return Error::success(); 555 } 556 557 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) { 558 if (InFunctionScope) 559 return llvm::make_error<CodeViewError>( 560 "Visiting a ProcSym while inside function scope!"); 561 562 InFunctionScope = true; 563 564 StringRef LinkageName; 565 W.printHex("PtrParent", Proc.Parent); 566 W.printHex("PtrEnd", Proc.End); 567 W.printHex("PtrNext", Proc.Next); 568 W.printHex("CodeSize", Proc.CodeSize); 569 W.printHex("DbgStart", Proc.DbgStart); 570 W.printHex("DbgEnd", Proc.DbgEnd); 571 printTypeIndex("FunctionType", Proc.FunctionType); 572 if (ObjDelegate) { 573 ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(), 574 Proc.CodeOffset, &LinkageName); 575 } 576 W.printHex("Segment", Proc.Segment); 577 W.printFlags("Flags", static_cast<uint8_t>(Proc.Flags), 578 getProcSymFlagNames()); 579 W.printString("DisplayName", Proc.Name); 580 if (!LinkageName.empty()) 581 W.printString("LinkageName", LinkageName); 582 return Error::success(); 583 } 584 585 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 586 ScopeEndSym &ScopeEnd) { 587 InFunctionScope = false; 588 return Error::success(); 589 } 590 591 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) { 592 ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers"); 593 for (auto FuncID : Caller.Indices) 594 printTypeIndex("FuncID", FuncID); 595 return Error::success(); 596 } 597 598 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 599 RegRelativeSym &RegRel) { 600 W.printHex("Offset", RegRel.Offset); 601 printTypeIndex("Type", RegRel.Type); 602 W.printEnum("Register", uint16_t(RegRel.Register), getRegisterNames()); 603 W.printString("VarName", RegRel.Name); 604 return Error::success(); 605 } 606 607 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 608 ThreadLocalDataSym &Data) { 609 StringRef LinkageName; 610 if (ObjDelegate) { 611 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 612 Data.DataOffset, &LinkageName); 613 } 614 printTypeIndex("Type", Data.Type); 615 W.printString("DisplayName", Data.Name); 616 if (!LinkageName.empty()) 617 W.printString("LinkageName", LinkageName); 618 return Error::success(); 619 } 620 621 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) { 622 printTypeIndex("Type", UDT.Type); 623 W.printString("UDTName", UDT.Name); 624 return Error::success(); 625 } 626 627 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 628 UsingNamespaceSym &UN) { 629 W.printString("Namespace", UN.Name); 630 return Error::success(); 631 } 632 633 Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { 634 W.printNumber("Length", CVR.length()); 635 return Error::success(); 636 } 637 638 Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) { 639 SymbolVisitorCallbackPipeline Pipeline; 640 SymbolDeserializer Deserializer(ObjDelegate.get(), Container); 641 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, 642 PrintRecordBytes); 643 644 Pipeline.addCallbackToPipeline(Deserializer); 645 Pipeline.addCallbackToPipeline(Dumper); 646 CVSymbolVisitor Visitor(Pipeline); 647 auto Err = Visitor.visitSymbolRecord(Record); 648 CompilationCPUType = Dumper.getCompilationCPUType(); 649 return Err; 650 } 651 652 Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) { 653 SymbolVisitorCallbackPipeline Pipeline; 654 SymbolDeserializer Deserializer(ObjDelegate.get(), Container); 655 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, 656 PrintRecordBytes); 657 658 Pipeline.addCallbackToPipeline(Deserializer); 659 Pipeline.addCallbackToPipeline(Dumper); 660 CVSymbolVisitor Visitor(Pipeline); 661 auto Err = Visitor.visitSymbolStream(Symbols); 662 CompilationCPUType = Dumper.getCompilationCPUType(); 663 return Err; 664 } 665