1 //===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/DebugInfo/CodeView/SymbolDumper.h" 11 #include "llvm/ADT/DenseMap.h" 12 #include "llvm/ADT/SmallString.h" 13 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" 14 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" 15 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 16 #include "llvm/DebugInfo/CodeView/TypeDumper.h" 17 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 18 #include "llvm/Support/ScopedPrinter.h" 19 20 #include <system_error> 21 22 using namespace llvm; 23 using namespace llvm::codeview; 24 25 static const EnumEntry<SymbolKind> SymbolTypeNames[] = { 26 #define CV_SYMBOL(enum, val) {#enum, enum}, 27 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def" 28 }; 29 30 namespace { 31 #define CV_ENUM_CLASS_ENT(enum_class, enum) \ 32 { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) } 33 34 #define CV_ENUM_ENT(ns, enum) \ 35 { #enum, ns::enum } 36 37 static const EnumEntry<uint16_t> RegisterNames[] = { 38 CV_ENUM_CLASS_ENT(RegisterId, Unknown), 39 CV_ENUM_CLASS_ENT(RegisterId, VFrame), 40 CV_ENUM_CLASS_ENT(RegisterId, AL), 41 CV_ENUM_CLASS_ENT(RegisterId, CL), 42 CV_ENUM_CLASS_ENT(RegisterId, DL), 43 CV_ENUM_CLASS_ENT(RegisterId, BL), 44 CV_ENUM_CLASS_ENT(RegisterId, AH), 45 CV_ENUM_CLASS_ENT(RegisterId, CH), 46 CV_ENUM_CLASS_ENT(RegisterId, DH), 47 CV_ENUM_CLASS_ENT(RegisterId, BH), 48 CV_ENUM_CLASS_ENT(RegisterId, AX), 49 CV_ENUM_CLASS_ENT(RegisterId, CX), 50 CV_ENUM_CLASS_ENT(RegisterId, DX), 51 CV_ENUM_CLASS_ENT(RegisterId, BX), 52 CV_ENUM_CLASS_ENT(RegisterId, SP), 53 CV_ENUM_CLASS_ENT(RegisterId, BP), 54 CV_ENUM_CLASS_ENT(RegisterId, SI), 55 CV_ENUM_CLASS_ENT(RegisterId, DI), 56 CV_ENUM_CLASS_ENT(RegisterId, EAX), 57 CV_ENUM_CLASS_ENT(RegisterId, ECX), 58 CV_ENUM_CLASS_ENT(RegisterId, EDX), 59 CV_ENUM_CLASS_ENT(RegisterId, EBX), 60 CV_ENUM_CLASS_ENT(RegisterId, ESP), 61 CV_ENUM_CLASS_ENT(RegisterId, EBP), 62 CV_ENUM_CLASS_ENT(RegisterId, ESI), 63 CV_ENUM_CLASS_ENT(RegisterId, EDI), 64 CV_ENUM_CLASS_ENT(RegisterId, ES), 65 CV_ENUM_CLASS_ENT(RegisterId, CS), 66 CV_ENUM_CLASS_ENT(RegisterId, SS), 67 CV_ENUM_CLASS_ENT(RegisterId, DS), 68 CV_ENUM_CLASS_ENT(RegisterId, FS), 69 CV_ENUM_CLASS_ENT(RegisterId, GS), 70 CV_ENUM_CLASS_ENT(RegisterId, IP), 71 CV_ENUM_CLASS_ENT(RegisterId, RAX), 72 CV_ENUM_CLASS_ENT(RegisterId, RBX), 73 CV_ENUM_CLASS_ENT(RegisterId, RCX), 74 CV_ENUM_CLASS_ENT(RegisterId, RDX), 75 CV_ENUM_CLASS_ENT(RegisterId, RSI), 76 CV_ENUM_CLASS_ENT(RegisterId, RDI), 77 CV_ENUM_CLASS_ENT(RegisterId, RBP), 78 CV_ENUM_CLASS_ENT(RegisterId, RSP), 79 CV_ENUM_CLASS_ENT(RegisterId, R8), 80 CV_ENUM_CLASS_ENT(RegisterId, R9), 81 CV_ENUM_CLASS_ENT(RegisterId, R10), 82 CV_ENUM_CLASS_ENT(RegisterId, R11), 83 CV_ENUM_CLASS_ENT(RegisterId, R12), 84 CV_ENUM_CLASS_ENT(RegisterId, R13), 85 CV_ENUM_CLASS_ENT(RegisterId, R14), 86 CV_ENUM_CLASS_ENT(RegisterId, R15), 87 }; 88 89 static const EnumEntry<uint8_t> ProcSymFlagNames[] = { 90 CV_ENUM_CLASS_ENT(ProcSymFlags, HasFP), 91 CV_ENUM_CLASS_ENT(ProcSymFlags, HasIRET), 92 CV_ENUM_CLASS_ENT(ProcSymFlags, HasFRET), 93 CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoReturn), 94 CV_ENUM_CLASS_ENT(ProcSymFlags, IsUnreachable), 95 CV_ENUM_CLASS_ENT(ProcSymFlags, HasCustomCallingConv), 96 CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoInline), 97 CV_ENUM_CLASS_ENT(ProcSymFlags, HasOptimizedDebugInfo), 98 }; 99 100 static const EnumEntry<uint16_t> LocalFlags[] = { 101 CV_ENUM_CLASS_ENT(LocalSymFlags, IsParameter), 102 CV_ENUM_CLASS_ENT(LocalSymFlags, IsAddressTaken), 103 CV_ENUM_CLASS_ENT(LocalSymFlags, IsCompilerGenerated), 104 CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregate), 105 CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregated), 106 CV_ENUM_CLASS_ENT(LocalSymFlags, IsAliased), 107 CV_ENUM_CLASS_ENT(LocalSymFlags, IsAlias), 108 CV_ENUM_CLASS_ENT(LocalSymFlags, IsReturnValue), 109 CV_ENUM_CLASS_ENT(LocalSymFlags, IsOptimizedOut), 110 CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredGlobal), 111 CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredStatic), 112 }; 113 114 static const EnumEntry<uint32_t> FrameCookieKinds[] = { 115 CV_ENUM_CLASS_ENT(FrameCookieKind, Copy), 116 CV_ENUM_CLASS_ENT(FrameCookieKind, XorStackPointer), 117 CV_ENUM_CLASS_ENT(FrameCookieKind, XorFramePointer), 118 CV_ENUM_CLASS_ENT(FrameCookieKind, XorR13), 119 }; 120 121 static const EnumEntry<codeview::SourceLanguage> SourceLanguages[] = { 122 CV_ENUM_ENT(SourceLanguage, C), CV_ENUM_ENT(SourceLanguage, Cpp), 123 CV_ENUM_ENT(SourceLanguage, Fortran), CV_ENUM_ENT(SourceLanguage, Masm), 124 CV_ENUM_ENT(SourceLanguage, Pascal), CV_ENUM_ENT(SourceLanguage, Basic), 125 CV_ENUM_ENT(SourceLanguage, Cobol), CV_ENUM_ENT(SourceLanguage, Link), 126 CV_ENUM_ENT(SourceLanguage, Cvtres), CV_ENUM_ENT(SourceLanguage, Cvtpgd), 127 CV_ENUM_ENT(SourceLanguage, CSharp), CV_ENUM_ENT(SourceLanguage, VB), 128 CV_ENUM_ENT(SourceLanguage, ILAsm), CV_ENUM_ENT(SourceLanguage, Java), 129 CV_ENUM_ENT(SourceLanguage, JScript), CV_ENUM_ENT(SourceLanguage, MSIL), 130 CV_ENUM_ENT(SourceLanguage, HLSL), 131 }; 132 133 static const EnumEntry<uint32_t> CompileSym2FlagNames[] = { 134 CV_ENUM_CLASS_ENT(CompileSym2Flags, EC), 135 CV_ENUM_CLASS_ENT(CompileSym2Flags, NoDbgInfo), 136 CV_ENUM_CLASS_ENT(CompileSym2Flags, LTCG), 137 CV_ENUM_CLASS_ENT(CompileSym2Flags, NoDataAlign), 138 CV_ENUM_CLASS_ENT(CompileSym2Flags, ManagedPresent), 139 CV_ENUM_CLASS_ENT(CompileSym2Flags, SecurityChecks), 140 CV_ENUM_CLASS_ENT(CompileSym2Flags, HotPatch), 141 CV_ENUM_CLASS_ENT(CompileSym2Flags, CVTCIL), 142 CV_ENUM_CLASS_ENT(CompileSym2Flags, MSILModule), 143 }; 144 145 static const EnumEntry<uint32_t> CompileSym3FlagNames[] = { 146 CV_ENUM_CLASS_ENT(CompileSym3Flags, EC), 147 CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDbgInfo), 148 CV_ENUM_CLASS_ENT(CompileSym3Flags, LTCG), 149 CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDataAlign), 150 CV_ENUM_CLASS_ENT(CompileSym3Flags, ManagedPresent), 151 CV_ENUM_CLASS_ENT(CompileSym3Flags, SecurityChecks), 152 CV_ENUM_CLASS_ENT(CompileSym3Flags, HotPatch), 153 CV_ENUM_CLASS_ENT(CompileSym3Flags, CVTCIL), 154 CV_ENUM_CLASS_ENT(CompileSym3Flags, MSILModule), 155 CV_ENUM_CLASS_ENT(CompileSym3Flags, Sdl), 156 CV_ENUM_CLASS_ENT(CompileSym3Flags, PGO), 157 CV_ENUM_CLASS_ENT(CompileSym3Flags, Exp), 158 }; 159 160 static const EnumEntry<unsigned> CPUTypeNames[] = { 161 CV_ENUM_CLASS_ENT(CPUType, Intel8080), 162 CV_ENUM_CLASS_ENT(CPUType, Intel8086), 163 CV_ENUM_CLASS_ENT(CPUType, Intel80286), 164 CV_ENUM_CLASS_ENT(CPUType, Intel80386), 165 CV_ENUM_CLASS_ENT(CPUType, Intel80486), 166 CV_ENUM_CLASS_ENT(CPUType, Pentium), 167 CV_ENUM_CLASS_ENT(CPUType, PentiumPro), 168 CV_ENUM_CLASS_ENT(CPUType, Pentium3), 169 CV_ENUM_CLASS_ENT(CPUType, MIPS), 170 CV_ENUM_CLASS_ENT(CPUType, MIPS16), 171 CV_ENUM_CLASS_ENT(CPUType, MIPS32), 172 CV_ENUM_CLASS_ENT(CPUType, MIPS64), 173 CV_ENUM_CLASS_ENT(CPUType, MIPSI), 174 CV_ENUM_CLASS_ENT(CPUType, MIPSII), 175 CV_ENUM_CLASS_ENT(CPUType, MIPSIII), 176 CV_ENUM_CLASS_ENT(CPUType, MIPSIV), 177 CV_ENUM_CLASS_ENT(CPUType, MIPSV), 178 CV_ENUM_CLASS_ENT(CPUType, M68000), 179 CV_ENUM_CLASS_ENT(CPUType, M68010), 180 CV_ENUM_CLASS_ENT(CPUType, M68020), 181 CV_ENUM_CLASS_ENT(CPUType, M68030), 182 CV_ENUM_CLASS_ENT(CPUType, M68040), 183 CV_ENUM_CLASS_ENT(CPUType, Alpha), 184 CV_ENUM_CLASS_ENT(CPUType, Alpha21164), 185 CV_ENUM_CLASS_ENT(CPUType, Alpha21164A), 186 CV_ENUM_CLASS_ENT(CPUType, Alpha21264), 187 CV_ENUM_CLASS_ENT(CPUType, Alpha21364), 188 CV_ENUM_CLASS_ENT(CPUType, PPC601), 189 CV_ENUM_CLASS_ENT(CPUType, PPC603), 190 CV_ENUM_CLASS_ENT(CPUType, PPC604), 191 CV_ENUM_CLASS_ENT(CPUType, PPC620), 192 CV_ENUM_CLASS_ENT(CPUType, PPCFP), 193 CV_ENUM_CLASS_ENT(CPUType, PPCBE), 194 CV_ENUM_CLASS_ENT(CPUType, SH3), 195 CV_ENUM_CLASS_ENT(CPUType, SH3E), 196 CV_ENUM_CLASS_ENT(CPUType, SH3DSP), 197 CV_ENUM_CLASS_ENT(CPUType, SH4), 198 CV_ENUM_CLASS_ENT(CPUType, SHMedia), 199 CV_ENUM_CLASS_ENT(CPUType, ARM3), 200 CV_ENUM_CLASS_ENT(CPUType, ARM4), 201 CV_ENUM_CLASS_ENT(CPUType, ARM4T), 202 CV_ENUM_CLASS_ENT(CPUType, ARM5), 203 CV_ENUM_CLASS_ENT(CPUType, ARM5T), 204 CV_ENUM_CLASS_ENT(CPUType, ARM6), 205 CV_ENUM_CLASS_ENT(CPUType, ARM_XMAC), 206 CV_ENUM_CLASS_ENT(CPUType, ARM_WMMX), 207 CV_ENUM_CLASS_ENT(CPUType, ARM7), 208 CV_ENUM_CLASS_ENT(CPUType, Omni), 209 CV_ENUM_CLASS_ENT(CPUType, Ia64), 210 CV_ENUM_CLASS_ENT(CPUType, Ia64_2), 211 CV_ENUM_CLASS_ENT(CPUType, CEE), 212 CV_ENUM_CLASS_ENT(CPUType, AM33), 213 CV_ENUM_CLASS_ENT(CPUType, M32R), 214 CV_ENUM_CLASS_ENT(CPUType, TriCore), 215 CV_ENUM_CLASS_ENT(CPUType, X64), 216 CV_ENUM_CLASS_ENT(CPUType, EBC), 217 CV_ENUM_CLASS_ENT(CPUType, Thumb), 218 CV_ENUM_CLASS_ENT(CPUType, ARMNT), 219 CV_ENUM_CLASS_ENT(CPUType, D3D11_Shader), 220 }; 221 222 static const EnumEntry<uint32_t> FrameProcSymFlags[] = { 223 CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasAlloca), 224 CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasSetJmp), 225 CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasLongJmp), 226 CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasInlineAssembly), 227 CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasExceptionHandling), 228 CV_ENUM_CLASS_ENT(FrameProcedureOptions, MarkedInline), 229 CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasStructuredExceptionHandling), 230 CV_ENUM_CLASS_ENT(FrameProcedureOptions, Naked), 231 CV_ENUM_CLASS_ENT(FrameProcedureOptions, SecurityChecks), 232 CV_ENUM_CLASS_ENT(FrameProcedureOptions, AsynchronousExceptionHandling), 233 CV_ENUM_CLASS_ENT(FrameProcedureOptions, NoStackOrderingForSecurityChecks), 234 CV_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined), 235 CV_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks), 236 CV_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers), 237 CV_ENUM_CLASS_ENT(FrameProcedureOptions, ProfileGuidedOptimization), 238 CV_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts), 239 CV_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed), 240 CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfg), 241 CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfw), 242 }; 243 244 static const EnumEntry<uint16_t> ExportSymFlags[] = { 245 CV_ENUM_CLASS_ENT(ExportFlags, IsConstant), 246 CV_ENUM_CLASS_ENT(ExportFlags, IsData), 247 CV_ENUM_CLASS_ENT(ExportFlags, IsPrivate), 248 CV_ENUM_CLASS_ENT(ExportFlags, HasNoName), 249 CV_ENUM_CLASS_ENT(ExportFlags, HasExplicitOrdinal), 250 CV_ENUM_CLASS_ENT(ExportFlags, IsForwarder), 251 }; 252 253 static const EnumEntry<uint8_t> ThunkOrdinalNames[] = { 254 CV_ENUM_CLASS_ENT(ThunkOrdinal, Standard), 255 CV_ENUM_CLASS_ENT(ThunkOrdinal, ThisAdjustor), 256 CV_ENUM_CLASS_ENT(ThunkOrdinal, Vcall), 257 CV_ENUM_CLASS_ENT(ThunkOrdinal, Pcode), 258 CV_ENUM_CLASS_ENT(ThunkOrdinal, UnknownLoad), 259 CV_ENUM_CLASS_ENT(ThunkOrdinal, TrampIncremental), 260 CV_ENUM_CLASS_ENT(ThunkOrdinal, BranchIsland), 261 }; 262 263 static const EnumEntry<uint16_t> TrampolineNames[] = { 264 CV_ENUM_CLASS_ENT(TrampolineType, TrampIncremental), 265 CV_ENUM_CLASS_ENT(TrampolineType, BranchIsland), 266 }; 267 268 /// Use this private dumper implementation to keep implementation details about 269 /// the visitor out of SymbolDumper.h. 270 class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> { 271 public: 272 CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate, 273 ScopedPrinter &W, bool PrintRecordBytes) 274 : CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate), 275 W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {} 276 277 /// CVSymbolVisitor overrides. 278 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 279 void visit##Name(SymbolKind Kind, Name &Record); 280 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 281 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def" 282 283 void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data); 284 void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData); 285 void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data); 286 287 private: 288 void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, 289 uint32_t RelocationOffset); 290 void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps); 291 292 CVTypeDumper &CVTD; 293 SymbolDumpDelegate *ObjDelegate; 294 ScopedPrinter &W; 295 296 bool PrintRecordBytes; 297 bool InFunctionScope; 298 }; 299 } 300 301 void CVSymbolDumperImpl::printLocalVariableAddrRange( 302 const LocalVariableAddrRange &Range, uint32_t RelocationOffset) { 303 DictScope S(W, "LocalVariableAddrRange"); 304 if (ObjDelegate) 305 ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset, 306 Range.OffsetStart); 307 W.printHex("ISectStart", Range.ISectStart); 308 W.printHex("Range", Range.Range); 309 } 310 311 void CVSymbolDumperImpl::printLocalVariableAddrGap( 312 ArrayRef<LocalVariableAddrGap> Gaps) { 313 for (auto &Gap : Gaps) { 314 ListScope S(W, "LocalVariableAddrGap"); 315 W.printHex("GapStartOffset", Gap.GapStartOffset); 316 W.printHex("Range", Gap.Range); 317 } 318 } 319 320 void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind, 321 ArrayRef<uint8_t> Data) {} 322 323 void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind, 324 ArrayRef<uint8_t> OriginalSymData) { 325 if (PrintRecordBytes && ObjDelegate) 326 ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData); 327 } 328 329 void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) { 330 DictScope S(W, "BlockStart"); 331 332 StringRef LinkageName; 333 W.printHex("PtrParent", Block.Header.PtrParent); 334 W.printHex("PtrEnd", Block.Header.PtrEnd); 335 W.printHex("CodeSize", Block.Header.CodeSize); 336 if (ObjDelegate) { 337 ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(), 338 Block.Header.CodeOffset, &LinkageName); 339 } 340 W.printHex("Segment", Block.Header.Segment); 341 W.printString("BlockName", Block.Name); 342 W.printString("LinkageName", LinkageName); 343 } 344 345 void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) { 346 DictScope S(W, "Thunk32"); 347 W.printNumber("Parent", Thunk.Header.Parent); 348 W.printNumber("End", Thunk.Header.End); 349 W.printNumber("Next", Thunk.Header.Next); 350 W.printNumber("Off", Thunk.Header.Off); 351 W.printNumber("Seg", Thunk.Header.Seg); 352 W.printNumber("Len", Thunk.Header.Len); 353 W.printEnum("Ordinal", Thunk.Header.Ord, makeArrayRef(ThunkOrdinalNames)); 354 } 355 356 void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind, 357 TrampolineSym &Tramp) { 358 DictScope S(W, "Trampoline"); 359 W.printEnum("Type", Tramp.Header.Type, makeArrayRef(TrampolineNames)); 360 W.printNumber("Size", Tramp.Header.Size); 361 W.printNumber("ThunkOff", Tramp.Header.ThunkOff); 362 W.printNumber("TargetOff", Tramp.Header.TargetOff); 363 W.printNumber("ThunkSection", Tramp.Header.ThunkSection); 364 W.printNumber("TargetSection", Tramp.Header.TargetSection); 365 } 366 367 void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) { 368 DictScope S(W, "Section"); 369 W.printNumber("SectionNumber", Section.Header.SectionNumber); 370 W.printNumber("Alignment", Section.Header.Alignment); 371 W.printNumber("Reserved", Section.Header.Reserved); 372 W.printNumber("Rva", Section.Header.Rva); 373 W.printNumber("Length", Section.Header.Length); 374 W.printHex("Characteristics", Section.Header.Characteristics); 375 W.printString("Name", Section.Name); 376 } 377 378 void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind, 379 CoffGroupSym &CoffGroup) { 380 DictScope S(W, "COFF Group"); 381 W.printNumber("Size", CoffGroup.Header.Size); 382 W.printHex("Characteristics", CoffGroup.Header.Characteristics); 383 W.printNumber("Offset", CoffGroup.Header.Offset); 384 W.printNumber("Segment", CoffGroup.Header.Segment); 385 W.printString("Name", CoffGroup.Name); 386 } 387 388 void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind, 389 BPRelativeSym &BPRel) { 390 DictScope S(W, "BPRelativeSym"); 391 392 W.printNumber("Offset", BPRel.Header.Offset); 393 CVTD.printTypeIndex("Type", BPRel.Header.Type); 394 W.printString("VarName", BPRel.Name); 395 } 396 397 void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind, 398 BuildInfoSym &BuildInfo) { 399 DictScope S(W, "BuildInfo"); 400 401 W.printNumber("BuildId", BuildInfo.Header.BuildId); 402 } 403 404 void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind, 405 CallSiteInfoSym &CallSiteInfo) { 406 DictScope S(W, "CallSiteInfo"); 407 408 StringRef LinkageName; 409 if (ObjDelegate) { 410 ObjDelegate->printRelocatedField( 411 "CodeOffset", CallSiteInfo.getRelocationOffset(), 412 CallSiteInfo.Header.CodeOffset, &LinkageName); 413 } 414 W.printHex("Segment", CallSiteInfo.Header.Segment); 415 W.printHex("Reserved", CallSiteInfo.Header.Reserved); 416 CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type); 417 if (!LinkageName.empty()) 418 W.printString("LinkageName", LinkageName); 419 } 420 421 void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind, 422 EnvBlockSym &EnvBlock) { 423 DictScope S(W, "EnvBlock"); 424 425 W.printNumber("Reserved", EnvBlock.Header.Reserved); 426 ListScope L(W, "Entries"); 427 for (auto Entry : EnvBlock.Fields) { 428 W.printString(Entry); 429 } 430 } 431 432 void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind, 433 FileStaticSym &FileStatic) { 434 DictScope S(W, "FileStatic"); 435 W.printNumber("Index", FileStatic.Header.Index); 436 W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset); 437 W.printFlags("Flags", uint16_t(FileStatic.Header.Flags), 438 makeArrayRef(LocalFlags)); 439 W.printString("Name", FileStatic.Name); 440 } 441 442 void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) { 443 DictScope S(W, "Export"); 444 W.printNumber("Ordinal", Export.Header.Ordinal); 445 W.printFlags("Flags", Export.Header.Flags, makeArrayRef(ExportSymFlags)); 446 W.printString("Name", Export.Name); 447 } 448 449 void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind, 450 Compile2Sym &Compile2) { 451 DictScope S(W, "CompilerFlags2"); 452 453 W.printEnum("Language", Compile2.Header.getLanguage(), 454 makeArrayRef(SourceLanguages)); 455 W.printFlags("Flags", Compile2.Header.flags & ~0xff, 456 makeArrayRef(CompileSym2FlagNames)); 457 W.printEnum("Machine", unsigned(Compile2.Header.Machine), 458 makeArrayRef(CPUTypeNames)); 459 std::string FrontendVersion; 460 { 461 raw_string_ostream Out(FrontendVersion); 462 Out << Compile2.Header.VersionFrontendMajor << '.' 463 << Compile2.Header.VersionFrontendMinor << '.' 464 << Compile2.Header.VersionFrontendBuild; 465 } 466 std::string BackendVersion; 467 { 468 raw_string_ostream Out(BackendVersion); 469 Out << Compile2.Header.VersionBackendMajor << '.' 470 << Compile2.Header.VersionBackendMinor << '.' 471 << Compile2.Header.VersionBackendBuild; 472 } 473 W.printString("FrontendVersion", FrontendVersion); 474 W.printString("BackendVersion", BackendVersion); 475 W.printString("VersionName", Compile2.Version); 476 } 477 478 void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind, 479 Compile3Sym &Compile3) { 480 DictScope S(W, "CompilerFlags3"); 481 482 W.printEnum("Language", Compile3.Header.getLanguage(), 483 makeArrayRef(SourceLanguages)); 484 W.printFlags("Flags", Compile3.Header.flags & ~0xff, 485 makeArrayRef(CompileSym3FlagNames)); 486 W.printEnum("Machine", unsigned(Compile3.Header.Machine), 487 makeArrayRef(CPUTypeNames)); 488 std::string FrontendVersion; 489 { 490 raw_string_ostream Out(FrontendVersion); 491 Out << Compile3.Header.VersionFrontendMajor << '.' 492 << Compile3.Header.VersionFrontendMinor << '.' 493 << Compile3.Header.VersionFrontendBuild << '.' 494 << Compile3.Header.VersionFrontendQFE; 495 } 496 std::string BackendVersion; 497 { 498 raw_string_ostream Out(BackendVersion); 499 Out << Compile3.Header.VersionBackendMajor << '.' 500 << Compile3.Header.VersionBackendMinor << '.' 501 << Compile3.Header.VersionBackendBuild << '.' 502 << Compile3.Header.VersionBackendQFE; 503 } 504 W.printString("FrontendVersion", FrontendVersion); 505 W.printString("BackendVersion", BackendVersion); 506 W.printString("VersionName", Compile3.Version); 507 } 508 509 void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind, 510 ConstantSym &Constant) { 511 DictScope S(W, "Constant"); 512 513 CVTD.printTypeIndex("Type", Constant.Header.Type); 514 W.printNumber("Value", Constant.Value); 515 W.printString("Name", Constant.Name); 516 } 517 518 void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) { 519 DictScope S(W, "DataSym"); 520 521 StringRef LinkageName; 522 if (ObjDelegate) { 523 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 524 Data.Header.DataOffset, &LinkageName); 525 } 526 CVTD.printTypeIndex("Type", Data.Header.Type); 527 W.printString("DisplayName", Data.Name); 528 if (!LinkageName.empty()) 529 W.printString("LinkageName", LinkageName); 530 } 531 532 void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym( 533 SymbolKind Kind, 534 DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { 535 DictScope S(W, "DefRangeFramePointerRelFullScope"); 536 W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset); 537 } 538 539 void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym( 540 SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { 541 DictScope S(W, "DefRangeFramePointerRel"); 542 543 W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset); 544 printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range, 545 DefRangeFramePointerRel.getRelocationOffset()); 546 printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); 547 } 548 549 void CVSymbolDumperImpl::visitDefRangeRegisterRelSym( 550 SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) { 551 DictScope S(W, "DefRangeRegisterRel"); 552 553 W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister); 554 W.printBoolean("HasSpilledUDTMember", 555 DefRangeRegisterRel.hasSpilledUDTMember()); 556 W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent()); 557 W.printNumber("BasePointerOffset", 558 DefRangeRegisterRel.Header.BasePointerOffset); 559 printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range, 560 DefRangeRegisterRel.getRelocationOffset()); 561 printLocalVariableAddrGap(DefRangeRegisterRel.Gaps); 562 } 563 564 void CVSymbolDumperImpl::visitDefRangeRegisterSym( 565 SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) { 566 DictScope S(W, "DefRangeRegister"); 567 568 W.printNumber("Register", DefRangeRegister.Header.Register); 569 W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName); 570 printLocalVariableAddrRange(DefRangeRegister.Header.Range, 571 DefRangeRegister.getRelocationOffset()); 572 printLocalVariableAddrGap(DefRangeRegister.Gaps); 573 } 574 575 void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym( 576 SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) { 577 DictScope S(W, "DefRangeSubfieldRegister"); 578 579 W.printNumber("Register", DefRangeSubfieldRegister.Header.Register); 580 W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName); 581 W.printNumber("OffsetInParent", 582 DefRangeSubfieldRegister.Header.OffsetInParent); 583 printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range, 584 DefRangeSubfieldRegister.getRelocationOffset()); 585 printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps); 586 } 587 588 void CVSymbolDumperImpl::visitDefRangeSubfieldSym( 589 SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) { 590 DictScope S(W, "DefRangeSubfield"); 591 592 if (ObjDelegate) { 593 StringRef StringTable = ObjDelegate->getStringTable(); 594 auto ProgramStringTableOffset = DefRangeSubfield.Header.Program; 595 if (ProgramStringTableOffset >= StringTable.size()) 596 return parseError(); 597 StringRef Program = 598 StringTable.drop_front(ProgramStringTableOffset).split('\0').first; 599 W.printString("Program", Program); 600 } 601 W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent); 602 printLocalVariableAddrRange(DefRangeSubfield.Header.Range, 603 DefRangeSubfield.getRelocationOffset()); 604 printLocalVariableAddrGap(DefRangeSubfield.Gaps); 605 } 606 607 void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind, 608 DefRangeSym &DefRange) { 609 DictScope S(W, "DefRange"); 610 611 if (ObjDelegate) { 612 StringRef StringTable = ObjDelegate->getStringTable(); 613 auto ProgramStringTableOffset = DefRange.Header.Program; 614 if (ProgramStringTableOffset >= StringTable.size()) 615 return parseError(); 616 StringRef Program = 617 StringTable.drop_front(ProgramStringTableOffset).split('\0').first; 618 W.printString("Program", Program); 619 } 620 printLocalVariableAddrRange(DefRange.Header.Range, 621 DefRange.getRelocationOffset()); 622 printLocalVariableAddrGap(DefRange.Gaps); 623 } 624 625 void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind, 626 FrameCookieSym &FrameCookie) { 627 DictScope S(W, "FrameCookie"); 628 629 StringRef LinkageName; 630 if (ObjDelegate) { 631 ObjDelegate->printRelocatedField( 632 "CodeOffset", FrameCookie.getRelocationOffset(), 633 FrameCookie.Header.CodeOffset, &LinkageName); 634 } 635 W.printHex("Register", FrameCookie.Header.Register); 636 W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind), 637 makeArrayRef(FrameCookieKinds)); 638 } 639 640 void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind, 641 FrameProcSym &FrameProc) { 642 DictScope S(W, "FrameProc"); 643 644 W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes); 645 W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes); 646 W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding); 647 W.printHex("BytesOfCalleeSavedRegisters", 648 FrameProc.Header.BytesOfCalleeSavedRegisters); 649 W.printHex("OffsetOfExceptionHandler", 650 FrameProc.Header.OffsetOfExceptionHandler); 651 W.printHex("SectionIdOfExceptionHandler", 652 FrameProc.Header.SectionIdOfExceptionHandler); 653 W.printFlags("Flags", FrameProc.Header.Flags, 654 makeArrayRef(FrameProcSymFlags)); 655 } 656 657 void CVSymbolDumperImpl::visitHeapAllocationSiteSym( 658 SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) { 659 DictScope S(W, "HeapAllocationSite"); 660 661 StringRef LinkageName; 662 if (ObjDelegate) { 663 ObjDelegate->printRelocatedField( 664 "CodeOffset", HeapAllocSite.getRelocationOffset(), 665 HeapAllocSite.Header.CodeOffset, &LinkageName); 666 } 667 W.printHex("Segment", HeapAllocSite.Header.Segment); 668 W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize); 669 CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type); 670 if (!LinkageName.empty()) 671 W.printString("LinkageName", LinkageName); 672 } 673 674 void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind, 675 InlineSiteSym &InlineSite) { 676 DictScope S(W, "InlineSite"); 677 678 W.printHex("PtrParent", InlineSite.Header.PtrParent); 679 W.printHex("PtrEnd", InlineSite.Header.PtrEnd); 680 CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee); 681 682 ListScope BinaryAnnotations(W, "BinaryAnnotations"); 683 for (auto &Annotation : InlineSite.annotations()) { 684 switch (Annotation.OpCode) { 685 case BinaryAnnotationsOpCode::Invalid: 686 return parseError(); 687 case BinaryAnnotationsOpCode::CodeOffset: 688 case BinaryAnnotationsOpCode::ChangeCodeOffset: 689 case BinaryAnnotationsOpCode::ChangeCodeLength: 690 W.printHex(Annotation.Name, Annotation.U1); 691 break; 692 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: 693 case BinaryAnnotationsOpCode::ChangeLineEndDelta: 694 case BinaryAnnotationsOpCode::ChangeRangeKind: 695 case BinaryAnnotationsOpCode::ChangeColumnStart: 696 case BinaryAnnotationsOpCode::ChangeColumnEnd: 697 W.printNumber(Annotation.Name, Annotation.U1); 698 break; 699 case BinaryAnnotationsOpCode::ChangeLineOffset: 700 case BinaryAnnotationsOpCode::ChangeColumnEndDelta: 701 W.printNumber(Annotation.Name, Annotation.S1); 702 break; 703 case BinaryAnnotationsOpCode::ChangeFile: 704 if (ObjDelegate) { 705 W.printHex("ChangeFile", 706 ObjDelegate->getFileNameForFileOffset(Annotation.U1), 707 Annotation.U1); 708 } else { 709 W.printHex("ChangeFile", Annotation.U1); 710 } 711 712 break; 713 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: { 714 W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: " 715 << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1 716 << "}\n"; 717 break; 718 } 719 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: { 720 W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: " 721 << W.hex(Annotation.U2) 722 << ", Length: " << W.hex(Annotation.U1) << "}\n"; 723 break; 724 } 725 } 726 } 727 } 728 729 void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind, 730 RegisterSym &Register) { 731 DictScope S(W, "RegisterSym"); 732 W.printNumber("Type", Register.Header.Index); 733 W.printEnum("Seg", uint16_t(Register.Header.Register), 734 makeArrayRef(RegisterNames)); 735 W.printString("Name", Register.Name); 736 } 737 738 void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind, 739 PublicSym32 &Public) { 740 DictScope S(W, "PublicSym"); 741 W.printNumber("Type", Public.Header.Index); 742 W.printNumber("Seg", Public.Header.Seg); 743 W.printNumber("Off", Public.Header.Off); 744 W.printString("Name", Public.Name); 745 } 746 747 void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) { 748 DictScope S(W, "ProcRef"); 749 W.printNumber("SumName", ProcRef.Header.SumName); 750 W.printNumber("SymOffset", ProcRef.Header.SymOffset); 751 W.printNumber("Mod", ProcRef.Header.Mod); 752 W.printString("Name", ProcRef.Name); 753 } 754 755 void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) { 756 DictScope S(W, "Label"); 757 758 StringRef LinkageName; 759 if (ObjDelegate) { 760 ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(), 761 Label.Header.CodeOffset, &LinkageName); 762 } 763 W.printHex("Segment", Label.Header.Segment); 764 W.printHex("Flags", Label.Header.Flags); 765 W.printFlags("Flags", Label.Header.Flags, makeArrayRef(ProcSymFlagNames)); 766 W.printString("DisplayName", Label.Name); 767 if (!LinkageName.empty()) 768 W.printString("LinkageName", LinkageName); 769 } 770 771 void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) { 772 DictScope S(W, "Local"); 773 774 CVTD.printTypeIndex("Type", Local.Header.Type); 775 W.printFlags("Flags", uint16_t(Local.Header.Flags), makeArrayRef(LocalFlags)); 776 W.printString("VarName", Local.Name); 777 } 778 779 void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) { 780 DictScope S(W, "ObjectName"); 781 782 W.printHex("Signature", ObjName.Header.Signature); 783 W.printString("ObjectName", ObjName.Name); 784 } 785 786 void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) { 787 DictScope S(W, "ProcStart"); 788 789 if (InFunctionScope) 790 return parseError(); 791 792 InFunctionScope = true; 793 794 StringRef LinkageName; 795 W.printHex("PtrParent", Proc.Header.PtrParent); 796 W.printHex("PtrEnd", Proc.Header.PtrEnd); 797 W.printHex("PtrNext", Proc.Header.PtrNext); 798 W.printHex("CodeSize", Proc.Header.CodeSize); 799 W.printHex("DbgStart", Proc.Header.DbgStart); 800 W.printHex("DbgEnd", Proc.Header.DbgEnd); 801 CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType); 802 if (ObjDelegate) { 803 ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(), 804 Proc.Header.CodeOffset, &LinkageName); 805 } 806 W.printHex("Segment", Proc.Header.Segment); 807 W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags), 808 makeArrayRef(ProcSymFlagNames)); 809 W.printString("DisplayName", Proc.Name); 810 if (!LinkageName.empty()) 811 W.printString("LinkageName", LinkageName); 812 } 813 814 void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind, 815 ScopeEndSym &ScopeEnd) { 816 if (Kind == SymbolKind::S_END) 817 DictScope S(W, "BlockEnd"); 818 else if (Kind == SymbolKind::S_PROC_ID_END) 819 DictScope S(W, "ProcEnd"); 820 else if (Kind == SymbolKind::S_INLINESITE_END) 821 DictScope S(W, "InlineSiteEnd"); 822 823 InFunctionScope = false; 824 } 825 826 void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) { 827 ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers"); 828 for (auto FuncID : Caller.Indices) 829 CVTD.printTypeIndex("FuncID", FuncID); 830 } 831 832 void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind, 833 RegRelativeSym &RegRel) { 834 DictScope S(W, "RegRelativeSym"); 835 836 W.printHex("Offset", RegRel.Header.Offset); 837 CVTD.printTypeIndex("Type", RegRel.Header.Type); 838 W.printHex("Register", RegRel.Header.Register); 839 W.printString("VarName", RegRel.Name); 840 } 841 842 void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind, 843 ThreadLocalDataSym &Data) { 844 DictScope S(W, "ThreadLocalDataSym"); 845 846 StringRef LinkageName; 847 if (ObjDelegate) { 848 ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), 849 Data.Header.DataOffset, &LinkageName); 850 } 851 CVTD.printTypeIndex("Type", Data.Header.Type); 852 W.printString("DisplayName", Data.Name); 853 if (!LinkageName.empty()) 854 W.printString("LinkageName", LinkageName); 855 } 856 857 void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) { 858 DictScope S(W, "UDT"); 859 CVTD.printTypeIndex("Type", UDT.Header.Type); 860 W.printString("UDTName", UDT.Name); 861 } 862 863 void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind, 864 ArrayRef<uint8_t> Data) { 865 DictScope S(W, "UnknownSym"); 866 W.printEnum("Kind", uint16_t(Kind), makeArrayRef(SymbolTypeNames)); 867 W.printNumber("Length", uint32_t(Data.size())); 868 } 869 870 bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) { 871 CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); 872 Dumper.visitSymbolRecord(Record); 873 return !Dumper.hadError(); 874 } 875 876 bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) { 877 CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); 878 Dumper.visitSymbolStream(Symbols); 879 return !Dumper.hadError(); 880 } 881