1 //===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DebugInfo/CodeView/SymbolDumper.h" 10 #include "llvm/ADT/StringRef.h" 11 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" 12 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 13 #include "llvm/DebugInfo/CodeView/EnumTables.h" 14 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 15 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" 16 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 17 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h" 18 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" 19 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 20 #include "llvm/Support/Error.h" 21 #include "llvm/Support/ScopedPrinter.h" 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 SymbolVisitorCallbacks { 30 public: 31 CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate, 32 ScopedPrinter &W, CPUType CPU, bool PrintRecordBytes) 33 : Types(Types), ObjDelegate(ObjDelegate), W(W), CompilationCPUType(CPU), 34 PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {} 35 36 /// CVSymbolVisitor overrides. 37 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 38 Error visitKnownRecord(CVSymbol &CVR, Name &Record) override; 39 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 40 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 41 42 Error visitSymbolBegin(CVSymbol &Record) override; 43 Error visitSymbolEnd(CVSymbol &Record) override; 44 Error visitUnknownSymbol(CVSymbol &Record) override; 45 46 CPUType getCompilationCPUType() const { return CompilationCPUType; } 47 48 private: 49 void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, 50 uint32_t RelocationOffset); 51 void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps); 52 void printTypeIndex(StringRef FieldName, TypeIndex TI); 53 54 TypeCollection &Types; 55 SymbolDumpDelegate *ObjDelegate; 56 ScopedPrinter &W; 57 58 /// Save the machine or CPU type when dumping a compile symbols. 59 CPUType CompilationCPUType = CPUType::X64; 60 61 bool PrintRecordBytes; 62 bool InFunctionScope; 63 }; 64 } 65 66 static StringRef getSymbolKindName(SymbolKind Kind) { 67 switch (Kind) { 68 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 69 case EnumName: \ 70 return #Name; 71 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 72 default: 73 break; 74 } 75 return "UnknownSym"; 76 } 77 78 void CVSymbolDumperImpl::printLocalVariableAddrRange( 79 const LocalVariableAddrRange &Range, uint32_t RelocationOffset) { 80 DictScope S(W, "LocalVariableAddrRange"); 81 if (ObjDelegate) 82 ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset, 83 Range.OffsetStart); 84 W.printHex("ISectStart", Range.ISectStart); 85 W.printHex("Range", Range.Range); 86 } 87 88 void CVSymbolDumperImpl::printLocalVariableAddrGap( 89 ArrayRef<LocalVariableAddrGap> Gaps) { 90 for (auto &Gap : Gaps) { 91 ListScope S(W, "LocalVariableAddrGap"); 92 W.printHex("GapStartOffset", Gap.GapStartOffset); 93 W.printHex("Range", Gap.Range); 94 } 95 } 96 97 void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) { 98 codeview::printTypeIndex(W, FieldName, TI, Types); 99 } 100 101 Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) { 102 W.startLine() << getSymbolKindName(CVR.kind()); 103 W.getOStream() << " {\n"; 104 W.indent(); 105 W.printEnum("Kind", unsigned(CVR.kind()), getSymbolTypeNames()); 106 return Error::success(); 107 } 108 109 Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) { 110 if (PrintRecordBytes && ObjDelegate) 111 ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content()); 112 113 W.unindent(); 114 W.startLine() << "}\n"; 115 return Error::success(); 116 } 117 118 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) { 119 StringRef LinkageName; 120 W.printHex("PtrParent", Block.Parent); 121 W.printHex("PtrEnd", Block.End); 122 W.printHex("CodeSize", Block.CodeSize); 123 if (ObjDelegate) { 124 ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(), 125 Block.CodeOffset, &LinkageName); 126 } 127 W.printHex("Segment", Block.Segment); 128 W.printString("BlockName", Block.Name); 129 W.printString("LinkageName", LinkageName); 130 return Error::success(); 131 } 132 133 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) { 134 W.printString("Name", Thunk.Name); 135 W.printNumber("Parent", Thunk.Parent); 136 W.printNumber("End", Thunk.End); 137 W.printNumber("Next", Thunk.Next); 138 W.printNumber("Off", Thunk.Offset); 139 W.printNumber("Seg", Thunk.Segment); 140 W.printNumber("Len", Thunk.Length); 141 W.printEnum("Ordinal", uint8_t(Thunk.Thunk), getThunkOrdinalNames()); 142 return Error::success(); 143 } 144 145 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 146 TrampolineSym &Tramp) { 147 W.printEnum("Type", uint16_t(Tramp.Type), getTrampolineNames()); 148 W.printNumber("Size", Tramp.Size); 149 W.printNumber("ThunkOff", Tramp.ThunkOffset); 150 W.printNumber("TargetOff", Tramp.TargetOffset); 151 W.printNumber("ThunkSection", Tramp.ThunkSection); 152 W.printNumber("TargetSection", Tramp.TargetSection); 153 return Error::success(); 154 } 155 156 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) { 157 W.printNumber("SectionNumber", Section.SectionNumber); 158 W.printNumber("Alignment", Section.Alignment); 159 W.printNumber("Rva", Section.Rva); 160 W.printNumber("Length", Section.Length); 161 W.printFlags("Characteristics", Section.Characteristics, 162 getImageSectionCharacteristicNames(), 163 COFF::SectionCharacteristics(0x00F00000)); 164 165 W.printString("Name", Section.Name); 166 return Error::success(); 167 } 168 169 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 170 CoffGroupSym &CoffGroup) { 171 W.printNumber("Size", CoffGroup.Size); 172 W.printFlags("Characteristics", CoffGroup.Characteristics, 173 getImageSectionCharacteristicNames(), 174 COFF::SectionCharacteristics(0x00F00000)); 175 W.printNumber("Offset", CoffGroup.Offset); 176 W.printNumber("Segment", CoffGroup.Segment); 177 W.printString("Name", CoffGroup.Name); 178 return Error::success(); 179 } 180 181 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 182 BPRelativeSym &BPRel) { 183 W.printNumber("Offset", BPRel.Offset); 184 printTypeIndex("Type", BPRel.Type); 185 W.printString("VarName", BPRel.Name); 186 return Error::success(); 187 } 188 189 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 190 BuildInfoSym &BuildInfo) { 191 printTypeIndex("BuildId", BuildInfo.BuildId); 192 return Error::success(); 193 } 194 195 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 196 CallSiteInfoSym &CallSiteInfo) { 197 StringRef LinkageName; 198 if (ObjDelegate) { 199 ObjDelegate->printRelocatedField("CodeOffset", 200 CallSiteInfo.getRelocationOffset(), 201 CallSiteInfo.CodeOffset, &LinkageName); 202 } 203 W.printHex("Segment", CallSiteInfo.Segment); 204 printTypeIndex("Type", CallSiteInfo.Type); 205 if (!LinkageName.empty()) 206 W.printString("LinkageName", LinkageName); 207 return Error::success(); 208 } 209 210 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 211 EnvBlockSym &EnvBlock) { 212 ListScope L(W, "Entries"); 213 for (auto Entry : EnvBlock.Fields) { 214 W.printString(Entry); 215 } 216 return Error::success(); 217 } 218 219 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 220 FileStaticSym &FileStatic) { 221 printTypeIndex("Index", FileStatic.Index); 222 W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset); 223 W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames()); 224 W.printString("Name", FileStatic.Name); 225 return Error::success(); 226 } 227 228 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) { 229 W.printNumber("Ordinal", Export.Ordinal); 230 W.printFlags("Flags", uint16_t(Export.Flags), getExportSymFlagNames()); 231 W.printString("Name", Export.Name); 232 return Error::success(); 233 } 234 235 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 236 Compile2Sym &Compile2) { 237 W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames()); 238 W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames()); 239 W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames()); 240 CompilationCPUType = Compile2.Machine; 241 std::string FrontendVersion; 242 { 243 raw_string_ostream Out(FrontendVersion); 244 Out << Compile2.VersionFrontendMajor << '.' << Compile2.VersionFrontendMinor 245 << '.' << Compile2.VersionFrontendBuild; 246 } 247 std::string BackendVersion; 248 { 249 raw_string_ostream Out(BackendVersion); 250 Out << Compile2.VersionBackendMajor << '.' << Compile2.VersionBackendMinor 251 << '.' << Compile2.VersionBackendBuild; 252 } 253 W.printString("FrontendVersion", FrontendVersion); 254 W.printString("BackendVersion", BackendVersion); 255 W.printString("VersionName", Compile2.Version); 256 return Error::success(); 257 } 258 259 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 260 Compile3Sym &Compile3) { 261 W.printEnum("Language", uint8_t(Compile3.getLanguage()), getSourceLanguageNames()); 262 W.printFlags("Flags", uint32_t(Compile3.getFlags()), 263 getCompileSym3FlagNames()); 264 W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames()); 265 CompilationCPUType = Compile3.Machine; 266 std::string FrontendVersion; 267 { 268 raw_string_ostream Out(FrontendVersion); 269 Out << Compile3.VersionFrontendMajor << '.' << Compile3.VersionFrontendMinor 270 << '.' << Compile3.VersionFrontendBuild << '.' 271 << Compile3.VersionFrontendQFE; 272 } 273 std::string BackendVersion; 274 { 275 raw_string_ostream Out(BackendVersion); 276 Out << Compile3.VersionBackendMajor << '.' << Compile3.VersionBackendMinor 277 << '.' << Compile3.VersionBackendBuild << '.' 278 << Compile3.VersionBackendQFE; 279 } 280 W.printString("FrontendVersion", FrontendVersion); 281 W.printString("BackendVersion", BackendVersion); 282 W.printString("VersionName", Compile3.Version); 283 return Error::success(); 284 } 285 286 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 287 ConstantSym &Constant) { 288 printTypeIndex("Type", Constant.Type); 289 W.printNumber("Value", Constant.Value); 290 W.printString("Name", Constant.Name); 291 return Error::success(); 292 } 293 294 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) { 295 StringRef LinkageName; 296 if (ObjDelegate) { 297 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 298 Data.DataOffset, &LinkageName); 299 } 300 printTypeIndex("Type", Data.Type); 301 W.printString("DisplayName", Data.Name); 302 if (!LinkageName.empty()) 303 W.printString("LinkageName", LinkageName); 304 return Error::success(); 305 } 306 307 Error CVSymbolDumperImpl::visitKnownRecord( 308 CVSymbol &CVR, 309 DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { 310 W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset); 311 return Error::success(); 312 } 313 314 Error CVSymbolDumperImpl::visitKnownRecord( 315 CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { 316 W.printNumber("Offset", DefRangeFramePointerRel.Hdr.Offset); 317 printLocalVariableAddrRange(DefRangeFramePointerRel.Range, 318 DefRangeFramePointerRel.getRelocationOffset()); 319 printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); 320 return Error::success(); 321 } 322 323 Error CVSymbolDumperImpl::visitKnownRecord( 324 CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) { 325 W.printEnum("BaseRegister", uint16_t(DefRangeRegisterRel.Hdr.Register), 326 getRegisterNames(CompilationCPUType)); 327 W.printBoolean("HasSpilledUDTMember", 328 DefRangeRegisterRel.hasSpilledUDTMember()); 329 W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent()); 330 W.printNumber("BasePointerOffset", DefRangeRegisterRel.Hdr.BasePointerOffset); 331 printLocalVariableAddrRange(DefRangeRegisterRel.Range, 332 DefRangeRegisterRel.getRelocationOffset()); 333 printLocalVariableAddrGap(DefRangeRegisterRel.Gaps); 334 return Error::success(); 335 } 336 337 Error CVSymbolDumperImpl::visitKnownRecord( 338 CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) { 339 W.printEnum("Register", uint16_t(DefRangeRegister.Hdr.Register), 340 getRegisterNames(CompilationCPUType)); 341 W.printNumber("MayHaveNoName", DefRangeRegister.Hdr.MayHaveNoName); 342 printLocalVariableAddrRange(DefRangeRegister.Range, 343 DefRangeRegister.getRelocationOffset()); 344 printLocalVariableAddrGap(DefRangeRegister.Gaps); 345 return Error::success(); 346 } 347 348 Error CVSymbolDumperImpl::visitKnownRecord( 349 CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) { 350 W.printEnum("Register", uint16_t(DefRangeSubfieldRegister.Hdr.Register), 351 getRegisterNames(CompilationCPUType)); 352 W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Hdr.MayHaveNoName); 353 W.printNumber("OffsetInParent", DefRangeSubfieldRegister.Hdr.OffsetInParent); 354 printLocalVariableAddrRange(DefRangeSubfieldRegister.Range, 355 DefRangeSubfieldRegister.getRelocationOffset()); 356 printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps); 357 return Error::success(); 358 } 359 360 Error CVSymbolDumperImpl::visitKnownRecord( 361 CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) { 362 if (ObjDelegate) { 363 DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); 364 auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program); 365 if (!ExpectedProgram) { 366 consumeError(ExpectedProgram.takeError()); 367 return llvm::make_error<CodeViewError>( 368 "String table offset outside of bounds of String Table!"); 369 } 370 W.printString("Program", *ExpectedProgram); 371 } 372 W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent); 373 printLocalVariableAddrRange(DefRangeSubfield.Range, 374 DefRangeSubfield.getRelocationOffset()); 375 printLocalVariableAddrGap(DefRangeSubfield.Gaps); 376 return Error::success(); 377 } 378 379 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 380 DefRangeSym &DefRange) { 381 if (ObjDelegate) { 382 DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); 383 auto ExpectedProgram = Strings.getString(DefRange.Program); 384 if (!ExpectedProgram) { 385 consumeError(ExpectedProgram.takeError()); 386 return llvm::make_error<CodeViewError>( 387 "String table offset outside of bounds of String Table!"); 388 } 389 W.printString("Program", *ExpectedProgram); 390 } 391 printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset()); 392 printLocalVariableAddrGap(DefRange.Gaps); 393 return Error::success(); 394 } 395 396 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 397 FrameCookieSym &FrameCookie) { 398 StringRef LinkageName; 399 if (ObjDelegate) { 400 ObjDelegate->printRelocatedField("CodeOffset", 401 FrameCookie.getRelocationOffset(), 402 FrameCookie.CodeOffset, &LinkageName); 403 } 404 W.printEnum("Register", uint16_t(FrameCookie.Register), 405 getRegisterNames(CompilationCPUType)); 406 W.printEnum("CookieKind", uint16_t(FrameCookie.CookieKind), 407 getFrameCookieKindNames()); 408 W.printHex("Flags", FrameCookie.Flags); 409 return Error::success(); 410 } 411 412 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 413 FrameProcSym &FrameProc) { 414 W.printHex("TotalFrameBytes", FrameProc.TotalFrameBytes); 415 W.printHex("PaddingFrameBytes", FrameProc.PaddingFrameBytes); 416 W.printHex("OffsetToPadding", FrameProc.OffsetToPadding); 417 W.printHex("BytesOfCalleeSavedRegisters", 418 FrameProc.BytesOfCalleeSavedRegisters); 419 W.printHex("OffsetOfExceptionHandler", FrameProc.OffsetOfExceptionHandler); 420 W.printHex("SectionIdOfExceptionHandler", 421 FrameProc.SectionIdOfExceptionHandler); 422 W.printFlags("Flags", static_cast<uint32_t>(FrameProc.Flags), 423 getFrameProcSymFlagNames()); 424 W.printEnum("LocalFramePtrReg", 425 uint16_t(FrameProc.getLocalFramePtrReg(CompilationCPUType)), 426 getRegisterNames(CompilationCPUType)); 427 W.printEnum("ParamFramePtrReg", 428 uint16_t(FrameProc.getParamFramePtrReg(CompilationCPUType)), 429 getRegisterNames(CompilationCPUType)); 430 return Error::success(); 431 } 432 433 Error CVSymbolDumperImpl::visitKnownRecord( 434 CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) { 435 StringRef LinkageName; 436 if (ObjDelegate) { 437 ObjDelegate->printRelocatedField("CodeOffset", 438 HeapAllocSite.getRelocationOffset(), 439 HeapAllocSite.CodeOffset, &LinkageName); 440 } 441 W.printHex("Segment", HeapAllocSite.Segment); 442 W.printHex("CallInstructionSize", HeapAllocSite.CallInstructionSize); 443 printTypeIndex("Type", HeapAllocSite.Type); 444 if (!LinkageName.empty()) 445 W.printString("LinkageName", LinkageName); 446 return Error::success(); 447 } 448 449 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 450 InlineSiteSym &InlineSite) { 451 W.printHex("PtrParent", InlineSite.Parent); 452 W.printHex("PtrEnd", InlineSite.End); 453 printTypeIndex("Inlinee", InlineSite.Inlinee); 454 455 ListScope BinaryAnnotations(W, "BinaryAnnotations"); 456 for (auto &Annotation : InlineSite.annotations()) { 457 switch (Annotation.OpCode) { 458 case BinaryAnnotationsOpCode::Invalid: 459 W.printString("(Annotation Padding)"); 460 break; 461 case BinaryAnnotationsOpCode::CodeOffset: 462 case BinaryAnnotationsOpCode::ChangeCodeOffset: 463 case BinaryAnnotationsOpCode::ChangeCodeLength: 464 W.printHex(Annotation.Name, Annotation.U1); 465 break; 466 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: 467 case BinaryAnnotationsOpCode::ChangeLineEndDelta: 468 case BinaryAnnotationsOpCode::ChangeRangeKind: 469 case BinaryAnnotationsOpCode::ChangeColumnStart: 470 case BinaryAnnotationsOpCode::ChangeColumnEnd: 471 W.printNumber(Annotation.Name, Annotation.U1); 472 break; 473 case BinaryAnnotationsOpCode::ChangeLineOffset: 474 case BinaryAnnotationsOpCode::ChangeColumnEndDelta: 475 W.printNumber(Annotation.Name, Annotation.S1); 476 break; 477 case BinaryAnnotationsOpCode::ChangeFile: 478 if (ObjDelegate) { 479 W.printHex("ChangeFile", 480 ObjDelegate->getFileNameForFileOffset(Annotation.U1), 481 Annotation.U1); 482 } else { 483 W.printHex("ChangeFile", Annotation.U1); 484 } 485 486 break; 487 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: { 488 W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: " 489 << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1 490 << "}\n"; 491 break; 492 } 493 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: { 494 W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: " 495 << W.hex(Annotation.U2) 496 << ", Length: " << W.hex(Annotation.U1) << "}\n"; 497 break; 498 } 499 } 500 } 501 return Error::success(); 502 } 503 504 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 505 RegisterSym &Register) { 506 printTypeIndex("Type", Register.Index); 507 W.printEnum("Seg", uint16_t(Register.Register), 508 getRegisterNames(CompilationCPUType)); 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 llvm::StringRef ScopeName; 593 switch (CVR.kind()) { 594 case S_CALLEES: 595 ScopeName = "Callees"; 596 break; 597 case S_CALLERS: 598 ScopeName = "Callers"; 599 break; 600 case S_INLINEES: 601 ScopeName = "Inlinees"; 602 break; 603 default: 604 return llvm::make_error<CodeViewError>( 605 "Unknown CV Record type for a CallerSym object!"); 606 } 607 ListScope S(W, ScopeName); 608 for (auto FuncID : Caller.Indices) 609 printTypeIndex("FuncID", FuncID); 610 return Error::success(); 611 } 612 613 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 614 RegRelativeSym &RegRel) { 615 W.printHex("Offset", RegRel.Offset); 616 printTypeIndex("Type", RegRel.Type); 617 W.printEnum("Register", uint16_t(RegRel.Register), 618 getRegisterNames(CompilationCPUType)); 619 W.printString("VarName", RegRel.Name); 620 return Error::success(); 621 } 622 623 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 624 ThreadLocalDataSym &Data) { 625 StringRef LinkageName; 626 if (ObjDelegate) { 627 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 628 Data.DataOffset, &LinkageName); 629 } 630 printTypeIndex("Type", Data.Type); 631 W.printString("DisplayName", Data.Name); 632 if (!LinkageName.empty()) 633 W.printString("LinkageName", LinkageName); 634 return Error::success(); 635 } 636 637 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) { 638 printTypeIndex("Type", UDT.Type); 639 W.printString("UDTName", UDT.Name); 640 return Error::success(); 641 } 642 643 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 644 UsingNamespaceSym &UN) { 645 W.printString("Namespace", UN.Name); 646 return Error::success(); 647 } 648 649 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 650 AnnotationSym &Annot) { 651 W.printHex("Offset", Annot.CodeOffset); 652 W.printHex("Segment", Annot.Segment); 653 654 ListScope S(W, "Strings"); 655 for (StringRef Str : Annot.Strings) 656 W.printString(Str); 657 658 return Error::success(); 659 } 660 661 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 662 JumpTableSym &JumpTable) { 663 W.printHex("BaseOffset", JumpTable.BaseOffset); 664 W.printNumber("BaseSegment", JumpTable.BaseSegment); 665 W.printEnum("SwitchType", static_cast<uint16_t>(JumpTable.SwitchType), 666 getJumpTableEntrySizeNames()); 667 W.printHex("BranchOffset", JumpTable.BranchOffset); 668 W.printHex("TableOffset", JumpTable.TableOffset); 669 W.printNumber("BranchSegment", JumpTable.BranchSegment); 670 W.printNumber("TableSegment", JumpTable.TableSegment); 671 W.printNumber("EntriesCount", JumpTable.EntriesCount); 672 return Error::success(); 673 } 674 675 Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { 676 W.printNumber("Length", CVR.length()); 677 return Error::success(); 678 } 679 680 Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) { 681 SymbolVisitorCallbackPipeline Pipeline; 682 SymbolDeserializer Deserializer(ObjDelegate.get(), Container); 683 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, 684 PrintRecordBytes); 685 686 Pipeline.addCallbackToPipeline(Deserializer); 687 Pipeline.addCallbackToPipeline(Dumper); 688 CVSymbolVisitor Visitor(Pipeline); 689 auto Err = Visitor.visitSymbolRecord(Record); 690 CompilationCPUType = Dumper.getCompilationCPUType(); 691 return Err; 692 } 693 694 Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) { 695 SymbolVisitorCallbackPipeline Pipeline; 696 SymbolDeserializer Deserializer(ObjDelegate.get(), Container); 697 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, 698 PrintRecordBytes); 699 700 Pipeline.addCallbackToPipeline(Deserializer); 701 Pipeline.addCallbackToPipeline(Dumper); 702 CVSymbolVisitor Visitor(Pipeline); 703 auto Err = Visitor.visitSymbolStream(Symbols); 704 CompilationCPUType = Dumper.getCompilationCPUType(); 705 return Err; 706 } 707