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/SmallString.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 #include <system_error> 24 25 using namespace llvm; 26 using namespace llvm::codeview; 27 28 namespace { 29 /// Use this private dumper implementation to keep implementation details about 30 /// the visitor out of SymbolDumper.h. 31 class CVSymbolDumperImpl : public SymbolVisitorCallbacks { 32 public: 33 CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate, 34 ScopedPrinter &W, CPUType CPU, bool PrintRecordBytes) 35 : Types(Types), ObjDelegate(ObjDelegate), W(W), CompilationCPUType(CPU), 36 PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {} 37 38 /// CVSymbolVisitor overrides. 39 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 40 Error visitKnownRecord(CVSymbol &CVR, Name &Record) override; 41 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 42 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 43 44 Error visitSymbolBegin(CVSymbol &Record) override; 45 Error visitSymbolEnd(CVSymbol &Record) override; 46 Error visitUnknownSymbol(CVSymbol &Record) override; 47 48 CPUType getCompilationCPUType() const { return CompilationCPUType; } 49 50 private: 51 void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, 52 uint32_t RelocationOffset); 53 void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps); 54 void printTypeIndex(StringRef FieldName, TypeIndex TI); 55 56 TypeCollection &Types; 57 SymbolDumpDelegate *ObjDelegate; 58 ScopedPrinter &W; 59 60 /// Save the machine or CPU type when dumping a compile symbols. 61 CPUType CompilationCPUType = CPUType::X64; 62 63 bool PrintRecordBytes; 64 bool InFunctionScope; 65 }; 66 } 67 68 static StringRef getSymbolKindName(SymbolKind Kind) { 69 switch (Kind) { 70 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 71 case EnumName: \ 72 return #Name; 73 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 74 default: 75 break; 76 } 77 return "UnknownSym"; 78 } 79 80 void CVSymbolDumperImpl::printLocalVariableAddrRange( 81 const LocalVariableAddrRange &Range, uint32_t RelocationOffset) { 82 DictScope S(W, "LocalVariableAddrRange"); 83 if (ObjDelegate) 84 ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset, 85 Range.OffsetStart); 86 W.printHex("ISectStart", Range.ISectStart); 87 W.printHex("Range", Range.Range); 88 } 89 90 void CVSymbolDumperImpl::printLocalVariableAddrGap( 91 ArrayRef<LocalVariableAddrGap> Gaps) { 92 for (auto &Gap : Gaps) { 93 ListScope S(W, "LocalVariableAddrGap"); 94 W.printHex("GapStartOffset", Gap.GapStartOffset); 95 W.printHex("Range", Gap.Range); 96 } 97 } 98 99 void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) { 100 codeview::printTypeIndex(W, FieldName, TI, Types); 101 } 102 103 Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) { 104 W.startLine() << getSymbolKindName(CVR.kind()); 105 W.getOStream() << " {\n"; 106 W.indent(); 107 W.printEnum("Kind", unsigned(CVR.kind()), getSymbolTypeNames()); 108 return Error::success(); 109 } 110 111 Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) { 112 if (PrintRecordBytes && ObjDelegate) 113 ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content()); 114 115 W.unindent(); 116 W.startLine() << "}\n"; 117 return Error::success(); 118 } 119 120 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) { 121 StringRef LinkageName; 122 W.printHex("PtrParent", Block.Parent); 123 W.printHex("PtrEnd", Block.End); 124 W.printHex("CodeSize", Block.CodeSize); 125 if (ObjDelegate) { 126 ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(), 127 Block.CodeOffset, &LinkageName); 128 } 129 W.printHex("Segment", Block.Segment); 130 W.printString("BlockName", Block.Name); 131 W.printString("LinkageName", LinkageName); 132 return Error::success(); 133 } 134 135 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) { 136 W.printString("Name", Thunk.Name); 137 W.printNumber("Parent", Thunk.Parent); 138 W.printNumber("End", Thunk.End); 139 W.printNumber("Next", Thunk.Next); 140 W.printNumber("Off", Thunk.Offset); 141 W.printNumber("Seg", Thunk.Segment); 142 W.printNumber("Len", Thunk.Length); 143 W.printEnum("Ordinal", uint8_t(Thunk.Thunk), getThunkOrdinalNames()); 144 return Error::success(); 145 } 146 147 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 148 TrampolineSym &Tramp) { 149 W.printEnum("Type", uint16_t(Tramp.Type), getTrampolineNames()); 150 W.printNumber("Size", Tramp.Size); 151 W.printNumber("ThunkOff", Tramp.ThunkOffset); 152 W.printNumber("TargetOff", Tramp.TargetOffset); 153 W.printNumber("ThunkSection", Tramp.ThunkSection); 154 W.printNumber("TargetSection", Tramp.TargetSection); 155 return Error::success(); 156 } 157 158 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) { 159 W.printNumber("SectionNumber", Section.SectionNumber); 160 W.printNumber("Alignment", Section.Alignment); 161 W.printNumber("Rva", Section.Rva); 162 W.printNumber("Length", Section.Length); 163 W.printFlags("Characteristics", Section.Characteristics, 164 getImageSectionCharacteristicNames(), 165 COFF::SectionCharacteristics(0x00F00000)); 166 167 W.printString("Name", Section.Name); 168 return Error::success(); 169 } 170 171 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 172 CoffGroupSym &CoffGroup) { 173 W.printNumber("Size", CoffGroup.Size); 174 W.printFlags("Characteristics", CoffGroup.Characteristics, 175 getImageSectionCharacteristicNames(), 176 COFF::SectionCharacteristics(0x00F00000)); 177 W.printNumber("Offset", CoffGroup.Offset); 178 W.printNumber("Segment", CoffGroup.Segment); 179 W.printString("Name", CoffGroup.Name); 180 return Error::success(); 181 } 182 183 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 184 BPRelativeSym &BPRel) { 185 W.printNumber("Offset", BPRel.Offset); 186 printTypeIndex("Type", BPRel.Type); 187 W.printString("VarName", BPRel.Name); 188 return Error::success(); 189 } 190 191 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 192 BuildInfoSym &BuildInfo) { 193 printTypeIndex("BuildId", BuildInfo.BuildId); 194 return Error::success(); 195 } 196 197 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 198 CallSiteInfoSym &CallSiteInfo) { 199 StringRef LinkageName; 200 if (ObjDelegate) { 201 ObjDelegate->printRelocatedField("CodeOffset", 202 CallSiteInfo.getRelocationOffset(), 203 CallSiteInfo.CodeOffset, &LinkageName); 204 } 205 W.printHex("Segment", CallSiteInfo.Segment); 206 printTypeIndex("Type", CallSiteInfo.Type); 207 if (!LinkageName.empty()) 208 W.printString("LinkageName", LinkageName); 209 return Error::success(); 210 } 211 212 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 213 EnvBlockSym &EnvBlock) { 214 ListScope L(W, "Entries"); 215 for (auto Entry : EnvBlock.Fields) { 216 W.printString(Entry); 217 } 218 return Error::success(); 219 } 220 221 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 222 FileStaticSym &FileStatic) { 223 printTypeIndex("Index", FileStatic.Index); 224 W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset); 225 W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames()); 226 W.printString("Name", FileStatic.Name); 227 return Error::success(); 228 } 229 230 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) { 231 W.printNumber("Ordinal", Export.Ordinal); 232 W.printFlags("Flags", uint16_t(Export.Flags), getExportSymFlagNames()); 233 W.printString("Name", Export.Name); 234 return Error::success(); 235 } 236 237 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 238 Compile2Sym &Compile2) { 239 W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames()); 240 W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames()); 241 W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames()); 242 CompilationCPUType = Compile2.Machine; 243 std::string FrontendVersion; 244 { 245 raw_string_ostream Out(FrontendVersion); 246 Out << Compile2.VersionFrontendMajor << '.' << Compile2.VersionFrontendMinor 247 << '.' << Compile2.VersionFrontendBuild; 248 } 249 std::string BackendVersion; 250 { 251 raw_string_ostream Out(BackendVersion); 252 Out << Compile2.VersionBackendMajor << '.' << Compile2.VersionBackendMinor 253 << '.' << Compile2.VersionBackendBuild; 254 } 255 W.printString("FrontendVersion", FrontendVersion); 256 W.printString("BackendVersion", BackendVersion); 257 W.printString("VersionName", Compile2.Version); 258 return Error::success(); 259 } 260 261 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 262 Compile3Sym &Compile3) { 263 W.printEnum("Language", uint8_t(Compile3.getLanguage()), getSourceLanguageNames()); 264 W.printFlags("Flags", uint32_t(Compile3.getFlags()), 265 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(CompilationCPUType)); 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(CompilationCPUType)); 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(CompilationCPUType)); 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), 407 getRegisterNames(CompilationCPUType)); 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(CompilationCPUType)); 429 W.printEnum("ParamFramePtrReg", 430 uint16_t(FrameProc.getParamFramePtrReg(CompilationCPUType)), 431 getRegisterNames(CompilationCPUType)); 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), 510 getRegisterNames(CompilationCPUType)); 511 W.printString("Name", Register.Name); 512 return Error::success(); 513 } 514 515 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) { 516 W.printFlags("Flags", uint32_t(Public.Flags), getPublicSymFlagNames()); 517 W.printNumber("Seg", Public.Segment); 518 W.printNumber("Off", Public.Offset); 519 W.printString("Name", Public.Name); 520 return Error::success(); 521 } 522 523 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) { 524 W.printNumber("SumName", ProcRef.SumName); 525 W.printNumber("SymOffset", ProcRef.SymOffset); 526 W.printNumber("Mod", ProcRef.Module); 527 W.printString("Name", ProcRef.Name); 528 return Error::success(); 529 } 530 531 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) { 532 StringRef LinkageName; 533 if (ObjDelegate) { 534 ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(), 535 Label.CodeOffset, &LinkageName); 536 } 537 W.printHex("Segment", Label.Segment); 538 W.printHex("Flags", uint8_t(Label.Flags)); 539 W.printFlags("Flags", uint8_t(Label.Flags), getProcSymFlagNames()); 540 W.printString("DisplayName", Label.Name); 541 if (!LinkageName.empty()) 542 W.printString("LinkageName", LinkageName); 543 return Error::success(); 544 } 545 546 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) { 547 printTypeIndex("Type", Local.Type); 548 W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames()); 549 W.printString("VarName", Local.Name); 550 return Error::success(); 551 } 552 553 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) { 554 W.printHex("Signature", ObjName.Signature); 555 W.printString("ObjectName", ObjName.Name); 556 return Error::success(); 557 } 558 559 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) { 560 if (InFunctionScope) 561 return llvm::make_error<CodeViewError>( 562 "Visiting a ProcSym while inside function scope!"); 563 564 InFunctionScope = true; 565 566 StringRef LinkageName; 567 W.printHex("PtrParent", Proc.Parent); 568 W.printHex("PtrEnd", Proc.End); 569 W.printHex("PtrNext", Proc.Next); 570 W.printHex("CodeSize", Proc.CodeSize); 571 W.printHex("DbgStart", Proc.DbgStart); 572 W.printHex("DbgEnd", Proc.DbgEnd); 573 printTypeIndex("FunctionType", Proc.FunctionType); 574 if (ObjDelegate) { 575 ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(), 576 Proc.CodeOffset, &LinkageName); 577 } 578 W.printHex("Segment", Proc.Segment); 579 W.printFlags("Flags", static_cast<uint8_t>(Proc.Flags), 580 getProcSymFlagNames()); 581 W.printString("DisplayName", Proc.Name); 582 if (!LinkageName.empty()) 583 W.printString("LinkageName", LinkageName); 584 return Error::success(); 585 } 586 587 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 588 ScopeEndSym &ScopeEnd) { 589 InFunctionScope = false; 590 return Error::success(); 591 } 592 593 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) { 594 ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers"); 595 for (auto FuncID : Caller.Indices) 596 printTypeIndex("FuncID", FuncID); 597 return Error::success(); 598 } 599 600 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 601 RegRelativeSym &RegRel) { 602 W.printHex("Offset", RegRel.Offset); 603 printTypeIndex("Type", RegRel.Type); 604 W.printEnum("Register", uint16_t(RegRel.Register), 605 getRegisterNames(CompilationCPUType)); 606 W.printString("VarName", RegRel.Name); 607 return Error::success(); 608 } 609 610 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 611 ThreadLocalDataSym &Data) { 612 StringRef LinkageName; 613 if (ObjDelegate) { 614 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 615 Data.DataOffset, &LinkageName); 616 } 617 printTypeIndex("Type", Data.Type); 618 W.printString("DisplayName", Data.Name); 619 if (!LinkageName.empty()) 620 W.printString("LinkageName", LinkageName); 621 return Error::success(); 622 } 623 624 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) { 625 printTypeIndex("Type", UDT.Type); 626 W.printString("UDTName", UDT.Name); 627 return Error::success(); 628 } 629 630 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 631 UsingNamespaceSym &UN) { 632 W.printString("Namespace", UN.Name); 633 return Error::success(); 634 } 635 636 Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, 637 AnnotationSym &Annot) { 638 W.printHex("Offset", Annot.CodeOffset); 639 W.printHex("Segment", Annot.Segment); 640 641 ListScope S(W, "Strings"); 642 for (StringRef Str : Annot.Strings) 643 W.printString(Str); 644 645 return Error::success(); 646 } 647 648 Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { 649 W.printNumber("Length", CVR.length()); 650 return Error::success(); 651 } 652 653 Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) { 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.visitSymbolRecord(Record); 663 CompilationCPUType = Dumper.getCompilationCPUType(); 664 return Err; 665 } 666 667 Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) { 668 SymbolVisitorCallbackPipeline Pipeline; 669 SymbolDeserializer Deserializer(ObjDelegate.get(), Container); 670 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, 671 PrintRecordBytes); 672 673 Pipeline.addCallbackToPipeline(Deserializer); 674 Pipeline.addCallbackToPipeline(Dumper); 675 CVSymbolVisitor Visitor(Pipeline); 676 auto Err = Visitor.visitSymbolStream(Symbols); 677 CompilationCPUType = Dumper.getCompilationCPUType(); 678 return Err; 679 } 680