1 //===- MinimalSymbolDumper.cpp -------------------------------- *- 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 "MinimalSymbolDumper.h" 10 11 #include "llvm/ADT/StringExtras.h" 12 #include "llvm/DebugInfo/CodeView/CVRecord.h" 13 #include "llvm/DebugInfo/CodeView/CodeView.h" 14 #include "llvm/DebugInfo/CodeView/Formatters.h" 15 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" 16 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 17 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 18 #include "llvm/DebugInfo/PDB/Native/FormatUtil.h" 19 #include "llvm/DebugInfo/PDB/Native/InputFile.h" 20 #include "llvm/DebugInfo/PDB/Native/LinePrinter.h" 21 #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 22 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 23 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" 24 #include "llvm/Object/COFF.h" 25 #include "llvm/Support/FormatVariadic.h" 26 27 using namespace llvm; 28 using namespace llvm::codeview; 29 using namespace llvm::pdb; 30 31 static std::string formatLocalSymFlags(uint32_t IndentLevel, 32 LocalSymFlags Flags) { 33 std::vector<std::string> Opts; 34 if (Flags == LocalSymFlags::None) 35 return "none"; 36 37 PUSH_FLAG(LocalSymFlags, IsParameter, Flags, "param"); 38 PUSH_FLAG(LocalSymFlags, IsAddressTaken, Flags, "address is taken"); 39 PUSH_FLAG(LocalSymFlags, IsCompilerGenerated, Flags, "compiler generated"); 40 PUSH_FLAG(LocalSymFlags, IsAggregate, Flags, "aggregate"); 41 PUSH_FLAG(LocalSymFlags, IsAggregated, Flags, "aggregated"); 42 PUSH_FLAG(LocalSymFlags, IsAliased, Flags, "aliased"); 43 PUSH_FLAG(LocalSymFlags, IsAlias, Flags, "alias"); 44 PUSH_FLAG(LocalSymFlags, IsReturnValue, Flags, "return val"); 45 PUSH_FLAG(LocalSymFlags, IsOptimizedOut, Flags, "optimized away"); 46 PUSH_FLAG(LocalSymFlags, IsEnregisteredGlobal, Flags, "enreg global"); 47 PUSH_FLAG(LocalSymFlags, IsEnregisteredStatic, Flags, "enreg static"); 48 return typesetItemList(Opts, 4, IndentLevel, " | "); 49 } 50 51 static std::string formatExportFlags(uint32_t IndentLevel, ExportFlags Flags) { 52 std::vector<std::string> Opts; 53 if (Flags == ExportFlags::None) 54 return "none"; 55 56 PUSH_FLAG(ExportFlags, IsConstant, Flags, "constant"); 57 PUSH_FLAG(ExportFlags, IsData, Flags, "data"); 58 PUSH_FLAG(ExportFlags, IsPrivate, Flags, "private"); 59 PUSH_FLAG(ExportFlags, HasNoName, Flags, "no name"); 60 PUSH_FLAG(ExportFlags, HasExplicitOrdinal, Flags, "explicit ord"); 61 PUSH_FLAG(ExportFlags, IsForwarder, Flags, "forwarder"); 62 63 return typesetItemList(Opts, 4, IndentLevel, " | "); 64 } 65 66 static std::string formatCompileSym2Flags(uint32_t IndentLevel, 67 CompileSym2Flags Flags) { 68 std::vector<std::string> Opts; 69 Flags &= ~CompileSym2Flags::SourceLanguageMask; 70 if (Flags == CompileSym2Flags::None) 71 return "none"; 72 73 PUSH_FLAG(CompileSym2Flags, EC, Flags, "edit and continue"); 74 PUSH_FLAG(CompileSym2Flags, NoDbgInfo, Flags, "no dbg info"); 75 PUSH_FLAG(CompileSym2Flags, LTCG, Flags, "ltcg"); 76 PUSH_FLAG(CompileSym2Flags, NoDataAlign, Flags, "no data align"); 77 PUSH_FLAG(CompileSym2Flags, ManagedPresent, Flags, "has managed code"); 78 PUSH_FLAG(CompileSym2Flags, SecurityChecks, Flags, "security checks"); 79 PUSH_FLAG(CompileSym2Flags, HotPatch, Flags, "hot patchable"); 80 PUSH_FLAG(CompileSym2Flags, CVTCIL, Flags, "cvtcil"); 81 PUSH_FLAG(CompileSym2Flags, MSILModule, Flags, "msil module"); 82 return typesetItemList(Opts, 4, IndentLevel, " | "); 83 } 84 85 static std::string formatCompileSym3Flags(uint32_t IndentLevel, 86 CompileSym3Flags Flags) { 87 std::vector<std::string> Opts; 88 Flags &= ~CompileSym3Flags::SourceLanguageMask; 89 90 if (Flags == CompileSym3Flags::None) 91 return "none"; 92 93 PUSH_FLAG(CompileSym3Flags, EC, Flags, "edit and continue"); 94 PUSH_FLAG(CompileSym3Flags, NoDbgInfo, Flags, "no dbg info"); 95 PUSH_FLAG(CompileSym3Flags, LTCG, Flags, "ltcg"); 96 PUSH_FLAG(CompileSym3Flags, NoDataAlign, Flags, "no data align"); 97 PUSH_FLAG(CompileSym3Flags, ManagedPresent, Flags, "has managed code"); 98 PUSH_FLAG(CompileSym3Flags, SecurityChecks, Flags, "security checks"); 99 PUSH_FLAG(CompileSym3Flags, HotPatch, Flags, "hot patchable"); 100 PUSH_FLAG(CompileSym3Flags, CVTCIL, Flags, "cvtcil"); 101 PUSH_FLAG(CompileSym3Flags, MSILModule, Flags, "msil module"); 102 PUSH_FLAG(CompileSym3Flags, Sdl, Flags, "sdl"); 103 PUSH_FLAG(CompileSym3Flags, PGO, Flags, "pgo"); 104 PUSH_FLAG(CompileSym3Flags, Exp, Flags, "exp"); 105 return typesetItemList(Opts, 4, IndentLevel, " | "); 106 } 107 108 static std::string formatFrameProcedureOptions(uint32_t IndentLevel, 109 FrameProcedureOptions FPO) { 110 std::vector<std::string> Opts; 111 if (FPO == FrameProcedureOptions::None) 112 return "none"; 113 114 PUSH_FLAG(FrameProcedureOptions, HasAlloca, FPO, "has alloca"); 115 PUSH_FLAG(FrameProcedureOptions, HasSetJmp, FPO, "has setjmp"); 116 PUSH_FLAG(FrameProcedureOptions, HasLongJmp, FPO, "has longjmp"); 117 PUSH_FLAG(FrameProcedureOptions, HasInlineAssembly, FPO, "has inline asm"); 118 PUSH_FLAG(FrameProcedureOptions, HasExceptionHandling, FPO, "has eh"); 119 PUSH_FLAG(FrameProcedureOptions, MarkedInline, FPO, "marked inline"); 120 PUSH_FLAG(FrameProcedureOptions, HasStructuredExceptionHandling, FPO, 121 "has seh"); 122 PUSH_FLAG(FrameProcedureOptions, Naked, FPO, "naked"); 123 PUSH_FLAG(FrameProcedureOptions, SecurityChecks, FPO, "secure checks"); 124 PUSH_FLAG(FrameProcedureOptions, AsynchronousExceptionHandling, FPO, 125 "has async eh"); 126 PUSH_FLAG(FrameProcedureOptions, NoStackOrderingForSecurityChecks, FPO, 127 "no stack order"); 128 PUSH_FLAG(FrameProcedureOptions, Inlined, FPO, "inlined"); 129 PUSH_FLAG(FrameProcedureOptions, StrictSecurityChecks, FPO, 130 "strict secure checks"); 131 PUSH_FLAG(FrameProcedureOptions, SafeBuffers, FPO, "safe buffers"); 132 PUSH_FLAG(FrameProcedureOptions, ProfileGuidedOptimization, FPO, "pgo"); 133 PUSH_FLAG(FrameProcedureOptions, ValidProfileCounts, FPO, 134 "has profile counts"); 135 PUSH_FLAG(FrameProcedureOptions, OptimizedForSpeed, FPO, "opt speed"); 136 PUSH_FLAG(FrameProcedureOptions, GuardCfg, FPO, "guard cfg"); 137 PUSH_FLAG(FrameProcedureOptions, GuardCfw, FPO, "guard cfw"); 138 return typesetItemList(Opts, 4, IndentLevel, " | "); 139 } 140 141 static std::string formatPublicSymFlags(uint32_t IndentLevel, 142 PublicSymFlags Flags) { 143 std::vector<std::string> Opts; 144 if (Flags == PublicSymFlags::None) 145 return "none"; 146 147 PUSH_FLAG(PublicSymFlags, Code, Flags, "code"); 148 PUSH_FLAG(PublicSymFlags, Function, Flags, "function"); 149 PUSH_FLAG(PublicSymFlags, Managed, Flags, "managed"); 150 PUSH_FLAG(PublicSymFlags, MSIL, Flags, "msil"); 151 return typesetItemList(Opts, 4, IndentLevel, " | "); 152 } 153 154 static std::string formatProcSymFlags(uint32_t IndentLevel, 155 ProcSymFlags Flags) { 156 std::vector<std::string> Opts; 157 if (Flags == ProcSymFlags::None) 158 return "none"; 159 160 PUSH_FLAG(ProcSymFlags, HasFP, Flags, "has fp"); 161 PUSH_FLAG(ProcSymFlags, HasIRET, Flags, "has iret"); 162 PUSH_FLAG(ProcSymFlags, HasFRET, Flags, "has fret"); 163 PUSH_FLAG(ProcSymFlags, IsNoReturn, Flags, "noreturn"); 164 PUSH_FLAG(ProcSymFlags, IsUnreachable, Flags, "unreachable"); 165 PUSH_FLAG(ProcSymFlags, HasCustomCallingConv, Flags, "custom calling conv"); 166 PUSH_FLAG(ProcSymFlags, IsNoInline, Flags, "noinline"); 167 PUSH_FLAG(ProcSymFlags, HasOptimizedDebugInfo, Flags, "opt debuginfo"); 168 return typesetItemList(Opts, 4, IndentLevel, " | "); 169 } 170 171 static std::string formatThunkOrdinal(ThunkOrdinal Ordinal) { 172 switch (Ordinal) { 173 RETURN_CASE(ThunkOrdinal, Standard, "thunk"); 174 RETURN_CASE(ThunkOrdinal, ThisAdjustor, "this adjustor"); 175 RETURN_CASE(ThunkOrdinal, Vcall, "vcall"); 176 RETURN_CASE(ThunkOrdinal, Pcode, "pcode"); 177 RETURN_CASE(ThunkOrdinal, UnknownLoad, "unknown load"); 178 RETURN_CASE(ThunkOrdinal, TrampIncremental, "tramp incremental"); 179 RETURN_CASE(ThunkOrdinal, BranchIsland, "branch island"); 180 } 181 return formatUnknownEnum(Ordinal); 182 } 183 184 static std::string formatTrampolineType(TrampolineType Tramp) { 185 switch (Tramp) { 186 RETURN_CASE(TrampolineType, TrampIncremental, "tramp incremental"); 187 RETURN_CASE(TrampolineType, BranchIsland, "branch island"); 188 } 189 return formatUnknownEnum(Tramp); 190 } 191 192 static std::string formatSourceLanguage(SourceLanguage Lang) { 193 switch (Lang) { 194 RETURN_CASE(SourceLanguage, C, "c"); 195 RETURN_CASE(SourceLanguage, Cpp, "c++"); 196 RETURN_CASE(SourceLanguage, Fortran, "fortran"); 197 RETURN_CASE(SourceLanguage, Masm, "masm"); 198 RETURN_CASE(SourceLanguage, Pascal, "pascal"); 199 RETURN_CASE(SourceLanguage, Basic, "basic"); 200 RETURN_CASE(SourceLanguage, Cobol, "cobol"); 201 RETURN_CASE(SourceLanguage, Link, "link"); 202 RETURN_CASE(SourceLanguage, VB, "vb"); 203 RETURN_CASE(SourceLanguage, Cvtres, "cvtres"); 204 RETURN_CASE(SourceLanguage, Cvtpgd, "cvtpgd"); 205 RETURN_CASE(SourceLanguage, CSharp, "c#"); 206 RETURN_CASE(SourceLanguage, ILAsm, "il asm"); 207 RETURN_CASE(SourceLanguage, Java, "java"); 208 RETURN_CASE(SourceLanguage, JScript, "javascript"); 209 RETURN_CASE(SourceLanguage, MSIL, "msil"); 210 RETURN_CASE(SourceLanguage, HLSL, "hlsl"); 211 RETURN_CASE(SourceLanguage, D, "d"); 212 RETURN_CASE(SourceLanguage, Swift, "swift"); 213 RETURN_CASE(SourceLanguage, Rust, "rust"); 214 RETURN_CASE(SourceLanguage, ObjC, "objc"); 215 RETURN_CASE(SourceLanguage, ObjCpp, "objc++"); 216 } 217 return formatUnknownEnum(Lang); 218 } 219 220 static std::string formatMachineType(CPUType Cpu) { 221 switch (Cpu) { 222 RETURN_CASE(CPUType, Intel8080, "intel 8080"); 223 RETURN_CASE(CPUType, Intel8086, "intel 8086"); 224 RETURN_CASE(CPUType, Intel80286, "intel 80286"); 225 RETURN_CASE(CPUType, Intel80386, "intel 80386"); 226 RETURN_CASE(CPUType, Intel80486, "intel 80486"); 227 RETURN_CASE(CPUType, Pentium, "intel pentium"); 228 RETURN_CASE(CPUType, PentiumPro, "intel pentium pro"); 229 RETURN_CASE(CPUType, Pentium3, "intel pentium 3"); 230 RETURN_CASE(CPUType, MIPS, "mips"); 231 RETURN_CASE(CPUType, MIPS16, "mips-16"); 232 RETURN_CASE(CPUType, MIPS32, "mips-32"); 233 RETURN_CASE(CPUType, MIPS64, "mips-64"); 234 RETURN_CASE(CPUType, MIPSI, "mips i"); 235 RETURN_CASE(CPUType, MIPSII, "mips ii"); 236 RETURN_CASE(CPUType, MIPSIII, "mips iii"); 237 RETURN_CASE(CPUType, MIPSIV, "mips iv"); 238 RETURN_CASE(CPUType, MIPSV, "mips v"); 239 RETURN_CASE(CPUType, M68000, "motorola 68000"); 240 RETURN_CASE(CPUType, M68010, "motorola 68010"); 241 RETURN_CASE(CPUType, M68020, "motorola 68020"); 242 RETURN_CASE(CPUType, M68030, "motorola 68030"); 243 RETURN_CASE(CPUType, M68040, "motorola 68040"); 244 RETURN_CASE(CPUType, Alpha, "alpha"); 245 RETURN_CASE(CPUType, Alpha21164, "alpha 21164"); 246 RETURN_CASE(CPUType, Alpha21164A, "alpha 21164a"); 247 RETURN_CASE(CPUType, Alpha21264, "alpha 21264"); 248 RETURN_CASE(CPUType, Alpha21364, "alpha 21364"); 249 RETURN_CASE(CPUType, PPC601, "powerpc 601"); 250 RETURN_CASE(CPUType, PPC603, "powerpc 603"); 251 RETURN_CASE(CPUType, PPC604, "powerpc 604"); 252 RETURN_CASE(CPUType, PPC620, "powerpc 620"); 253 RETURN_CASE(CPUType, PPCFP, "powerpc fp"); 254 RETURN_CASE(CPUType, PPCBE, "powerpc be"); 255 RETURN_CASE(CPUType, SH3, "sh3"); 256 RETURN_CASE(CPUType, SH3E, "sh3e"); 257 RETURN_CASE(CPUType, SH3DSP, "sh3 dsp"); 258 RETURN_CASE(CPUType, SH4, "sh4"); 259 RETURN_CASE(CPUType, SHMedia, "shmedia"); 260 RETURN_CASE(CPUType, ARM3, "arm 3"); 261 RETURN_CASE(CPUType, ARM4, "arm 4"); 262 RETURN_CASE(CPUType, ARM4T, "arm 4t"); 263 RETURN_CASE(CPUType, ARM5, "arm 5"); 264 RETURN_CASE(CPUType, ARM5T, "arm 5t"); 265 RETURN_CASE(CPUType, ARM6, "arm 6"); 266 RETURN_CASE(CPUType, ARM_XMAC, "arm xmac"); 267 RETURN_CASE(CPUType, ARM_WMMX, "arm wmmx"); 268 RETURN_CASE(CPUType, ARM7, "arm 7"); 269 RETURN_CASE(CPUType, ARM64, "arm64"); 270 RETURN_CASE(CPUType, ARM64EC, "arm64ec"); 271 RETURN_CASE(CPUType, ARM64X, "arm64x"); 272 RETURN_CASE(CPUType, HybridX86ARM64, "hybrid x86 arm64"); 273 RETURN_CASE(CPUType, Omni, "omni"); 274 RETURN_CASE(CPUType, Ia64, "intel itanium ia64"); 275 RETURN_CASE(CPUType, Ia64_2, "intel itanium ia64 2"); 276 RETURN_CASE(CPUType, CEE, "cee"); 277 RETURN_CASE(CPUType, AM33, "am33"); 278 RETURN_CASE(CPUType, M32R, "m32r"); 279 RETURN_CASE(CPUType, TriCore, "tri-core"); 280 RETURN_CASE(CPUType, X64, "intel x86-x64"); 281 RETURN_CASE(CPUType, EBC, "ebc"); 282 RETURN_CASE(CPUType, Thumb, "thumb"); 283 RETURN_CASE(CPUType, ARMNT, "arm nt"); 284 RETURN_CASE(CPUType, D3D11_Shader, "d3d11 shader"); 285 } 286 return formatUnknownEnum(Cpu); 287 } 288 289 static std::string formatCookieKind(FrameCookieKind Kind) { 290 switch (Kind) { 291 RETURN_CASE(FrameCookieKind, Copy, "copy"); 292 RETURN_CASE(FrameCookieKind, XorStackPointer, "xor stack ptr"); 293 RETURN_CASE(FrameCookieKind, XorFramePointer, "xor frame ptr"); 294 RETURN_CASE(FrameCookieKind, XorR13, "xor rot13"); 295 } 296 return formatUnknownEnum(Kind); 297 } 298 299 static std::string formatRegisterId(RegisterId Id, CPUType Cpu) { 300 if (Cpu == CPUType::ARMNT) { 301 switch (Id) { 302 #define CV_REGISTERS_ARM 303 #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name) 304 #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" 305 #undef CV_REGISTER 306 #undef CV_REGISTERS_ARM 307 308 default: 309 break; 310 } 311 } else if (Cpu == CPUType::ARM64) { 312 switch (Id) { 313 #define CV_REGISTERS_ARM64 314 #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name) 315 #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" 316 #undef CV_REGISTER 317 #undef CV_REGISTERS_ARM64 318 319 default: 320 break; 321 } 322 } else { 323 switch (Id) { 324 #define CV_REGISTERS_X86 325 #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name) 326 #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" 327 #undef CV_REGISTER 328 #undef CV_REGISTERS_X86 329 330 default: 331 break; 332 } 333 } 334 return formatUnknownEnum(Id); 335 } 336 337 static std::string formatRegisterId(uint16_t Reg16, CPUType Cpu) { 338 return formatRegisterId(RegisterId(Reg16), Cpu); 339 } 340 341 static std::string formatRegisterId(ulittle16_t &Reg16, CPUType Cpu) { 342 return formatRegisterId(uint16_t(Reg16), Cpu); 343 } 344 345 static std::string formatRange(LocalVariableAddrRange Range) { 346 return formatv("[{0},+{1})", 347 formatSegmentOffset(Range.ISectStart, Range.OffsetStart), 348 Range.Range) 349 .str(); 350 } 351 352 static std::string formatGaps(uint32_t IndentLevel, 353 ArrayRef<LocalVariableAddrGap> Gaps) { 354 std::vector<std::string> GapStrs; 355 for (const auto &G : Gaps) { 356 GapStrs.push_back(formatv("({0},{1})", G.GapStartOffset, G.Range).str()); 357 } 358 return typesetItemList(GapStrs, 7, IndentLevel, ", "); 359 } 360 361 static std::string formatJumpTableEntrySize(JumpTableEntrySize EntrySize) { 362 switch (EntrySize) { 363 RETURN_CASE(JumpTableEntrySize, Int8, "int8"); 364 RETURN_CASE(JumpTableEntrySize, UInt8, "uin8"); 365 RETURN_CASE(JumpTableEntrySize, Int16, "int16"); 366 RETURN_CASE(JumpTableEntrySize, UInt16, "uint16"); 367 RETURN_CASE(JumpTableEntrySize, Int32, "int32"); 368 RETURN_CASE(JumpTableEntrySize, UInt32, "uint32"); 369 RETURN_CASE(JumpTableEntrySize, Pointer, "pointer"); 370 RETURN_CASE(JumpTableEntrySize, UInt8ShiftLeft, "uint8shl"); 371 RETURN_CASE(JumpTableEntrySize, UInt16ShiftLeft, "uint16shl"); 372 RETURN_CASE(JumpTableEntrySize, Int8ShiftLeft, "int8shl"); 373 RETURN_CASE(JumpTableEntrySize, Int16ShiftLeft, "int16shl"); 374 } 375 return formatUnknownEnum(EntrySize); 376 } 377 378 Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record) { 379 return visitSymbolBegin(Record, 0); 380 } 381 382 Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record, 383 uint32_t Offset) { 384 // formatLine puts the newline at the beginning, so we use formatLine here 385 // to start a new line, and then individual visit methods use format to 386 // append to the existing line. 387 P.formatLine("{0} | {1} [size = {2}]", 388 fmt_align(Offset, AlignStyle::Right, 6), 389 formatSymbolKind(Record.kind()), Record.length()); 390 P.Indent(); 391 return Error::success(); 392 } 393 394 Error MinimalSymbolDumper::visitSymbolEnd(CVSymbol &Record) { 395 if (RecordBytes) { 396 AutoIndent Indent(P, 7); 397 P.formatBinary("bytes", Record.content(), 0); 398 } 399 P.Unindent(); 400 return Error::success(); 401 } 402 403 std::string MinimalSymbolDumper::typeOrIdIndex(codeview::TypeIndex TI, 404 bool IsType) const { 405 if (TI.isSimple() || TI.isDecoratedItemId()) 406 return formatv("{0}", TI).str(); 407 auto &Container = IsType ? Types : Ids; 408 StringRef Name = Container.getTypeName(TI); 409 if (Name.size() > 32) { 410 Name = Name.take_front(32); 411 return std::string(formatv("{0} ({1}...)", TI, Name)); 412 } else 413 return std::string(formatv("{0} ({1})", TI, Name)); 414 } 415 416 std::string MinimalSymbolDumper::idIndex(codeview::TypeIndex TI) const { 417 return typeOrIdIndex(TI, false); 418 } 419 420 std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const { 421 return typeOrIdIndex(TI, true); 422 } 423 424 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) { 425 P.format(" `{0}`", Block.Name); 426 AutoIndent Indent(P, 7); 427 P.formatLine("parent = {0}, end = {1}", Block.Parent, Block.End); 428 P.formatLine("code size = {0}, addr = {1}", Block.CodeSize, 429 formatSegmentOffset(Block.Segment, Block.CodeOffset)); 430 return Error::success(); 431 } 432 433 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) { 434 P.format(" `{0}`", Thunk.Name); 435 AutoIndent Indent(P, 7); 436 P.formatLine("parent = {0}, end = {1}, next = {2}", Thunk.Parent, Thunk.End, 437 Thunk.Next); 438 P.formatLine("kind = {0}, size = {1}, addr = {2}", 439 formatThunkOrdinal(Thunk.Thunk), Thunk.Length, 440 formatSegmentOffset(Thunk.Segment, Thunk.Offset)); 441 442 return Error::success(); 443 } 444 445 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 446 TrampolineSym &Tramp) { 447 AutoIndent Indent(P, 7); 448 P.formatLine("type = {0}, size = {1}, source = {2}, target = {3}", 449 formatTrampolineType(Tramp.Type), Tramp.Size, 450 formatSegmentOffset(Tramp.ThunkSection, Tramp.ThunkOffset), 451 formatSegmentOffset(Tramp.TargetSection, Tramp.ThunkOffset)); 452 453 return Error::success(); 454 } 455 456 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 457 SectionSym &Section) { 458 P.format(" `{0}`", Section.Name); 459 AutoIndent Indent(P, 7); 460 P.formatLine("length = {0}, alignment = {1}, rva = {2}, section # = {3}", 461 Section.Length, Section.Alignment, Section.Rva, 462 Section.SectionNumber); 463 P.printLine("characteristics ="); 464 AutoIndent Indent2(P, 2); 465 P.printLine(formatSectionCharacteristics(P.getIndentLevel(), 466 Section.Characteristics, 1, "", 467 CharacteristicStyle::Descriptive)); 468 return Error::success(); 469 } 470 471 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CoffGroupSym &CG) { 472 P.format(" `{0}`", CG.Name); 473 AutoIndent Indent(P, 7); 474 P.formatLine("length = {0}, addr = {1}", CG.Size, 475 formatSegmentOffset(CG.Segment, CG.Offset)); 476 P.printLine("characteristics ="); 477 AutoIndent Indent2(P, 2); 478 P.printLine(formatSectionCharacteristics(P.getIndentLevel(), 479 CG.Characteristics, 1, "", 480 CharacteristicStyle::Descriptive)); 481 return Error::success(); 482 } 483 484 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 485 BPRelativeSym &BPRel) { 486 P.format(" `{0}`", BPRel.Name); 487 AutoIndent Indent(P, 7); 488 P.formatLine("type = {0}, offset = {1}", typeIndex(BPRel.Type), BPRel.Offset); 489 return Error::success(); 490 } 491 492 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 493 BuildInfoSym &BuildInfo) { 494 P.format(" BuildId = `{0}`", BuildInfo.BuildId); 495 return Error::success(); 496 } 497 498 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 499 CallSiteInfoSym &CSI) { 500 AutoIndent Indent(P, 7); 501 P.formatLine("type = {0}, addr = {1}", typeIndex(CSI.Type), 502 formatSegmentOffset(CSI.Segment, CSI.CodeOffset)); 503 return Error::success(); 504 } 505 506 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 507 EnvBlockSym &EnvBlock) { 508 AutoIndent Indent(P, 7); 509 for (const auto &Entry : EnvBlock.Fields) { 510 P.formatLine("- {0}", Entry); 511 } 512 return Error::success(); 513 } 514 515 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FileStaticSym &FS) { 516 P.format(" `{0}`", FS.Name); 517 AutoIndent Indent(P, 7); 518 if (SymGroup) { 519 Expected<StringRef> FileName = 520 SymGroup->getNameFromStringTable(FS.ModFilenameOffset); 521 if (FileName) { 522 P.formatLine("type = {0}, file name = {1} ({2}), flags = {3}", 523 typeIndex(FS.Index), FS.ModFilenameOffset, *FileName, 524 formatLocalSymFlags(P.getIndentLevel() + 9, FS.Flags)); 525 } 526 return Error::success(); 527 } 528 529 P.formatLine("type = {0}, file name offset = {1}, flags = {2}", 530 typeIndex(FS.Index), FS.ModFilenameOffset, 531 formatLocalSymFlags(P.getIndentLevel() + 9, FS.Flags)); 532 return Error::success(); 533 } 534 535 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) { 536 P.format(" `{0}`", Export.Name); 537 AutoIndent Indent(P, 7); 538 P.formatLine("ordinal = {0}, flags = {1}", Export.Ordinal, 539 formatExportFlags(P.getIndentLevel() + 9, Export.Flags)); 540 return Error::success(); 541 } 542 543 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 544 Compile2Sym &Compile2) { 545 AutoIndent Indent(P, 7); 546 SourceLanguage Lang = static_cast<SourceLanguage>( 547 Compile2.Flags & CompileSym2Flags::SourceLanguageMask); 548 CompilationCPU = Compile2.Machine; 549 P.formatLine("machine = {0}, ver = {1}, language = {2}", 550 formatMachineType(Compile2.Machine), Compile2.Version, 551 formatSourceLanguage(Lang)); 552 P.formatLine("frontend = {0}.{1}.{2}, backend = {3}.{4}.{5}", 553 Compile2.VersionFrontendMajor, Compile2.VersionFrontendMinor, 554 Compile2.VersionFrontendBuild, Compile2.VersionBackendMajor, 555 Compile2.VersionBackendMinor, Compile2.VersionBackendBuild); 556 P.formatLine("flags = {0}", 557 formatCompileSym2Flags(P.getIndentLevel() + 9, Compile2.Flags)); 558 P.formatLine( 559 "extra strings = {0}", 560 typesetStringList(P.getIndentLevel() + 9 + 2, Compile2.ExtraStrings)); 561 return Error::success(); 562 } 563 564 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 565 Compile3Sym &Compile3) { 566 AutoIndent Indent(P, 7); 567 SourceLanguage Lang = static_cast<SourceLanguage>( 568 Compile3.Flags & CompileSym3Flags::SourceLanguageMask); 569 CompilationCPU = Compile3.Machine; 570 P.formatLine("machine = {0}, Ver = {1}, language = {2}", 571 formatMachineType(Compile3.Machine), Compile3.Version, 572 formatSourceLanguage(Lang)); 573 P.formatLine("frontend = {0}.{1}.{2}.{3}, backend = {4}.{5}.{6}.{7}", 574 Compile3.VersionFrontendMajor, Compile3.VersionFrontendMinor, 575 Compile3.VersionFrontendBuild, Compile3.VersionFrontendQFE, 576 Compile3.VersionBackendMajor, Compile3.VersionBackendMinor, 577 Compile3.VersionBackendBuild, Compile3.VersionBackendQFE); 578 P.formatLine("flags = {0}", 579 formatCompileSym3Flags(P.getIndentLevel() + 9, Compile3.Flags)); 580 return Error::success(); 581 } 582 583 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 584 ConstantSym &Constant) { 585 P.format(" `{0}`", Constant.Name); 586 AutoIndent Indent(P, 7); 587 P.formatLine("type = {0}, value = {1}", typeIndex(Constant.Type), 588 toString(Constant.Value, 10)); 589 return Error::success(); 590 } 591 592 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DataSym &Data) { 593 P.format(" `{0}`", Data.Name); 594 AutoIndent Indent(P, 7); 595 P.formatLine("type = {0}, addr = {1}", typeIndex(Data.Type), 596 formatSegmentOffset(Data.Segment, Data.DataOffset)); 597 return Error::success(); 598 } 599 600 Error MinimalSymbolDumper::visitKnownRecord( 601 CVSymbol &CVR, DefRangeFramePointerRelFullScopeSym &Def) { 602 P.format(" offset = {0}", Def.Offset); 603 return Error::success(); 604 } 605 606 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 607 DefRangeFramePointerRelSym &Def) { 608 AutoIndent Indent(P, 7); 609 P.formatLine("offset = {0}, range = {1}", Def.Hdr.Offset, 610 formatRange(Def.Range)); 611 P.formatLine("gaps = [{0}]", formatGaps(P.getIndentLevel() + 9, Def.Gaps)); 612 return Error::success(); 613 } 614 615 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 616 DefRangeRegisterRelSym &Def) { 617 AutoIndent Indent(P, 7); 618 P.formatLine("register = {0}, offset = {1}, offset in parent = {2}, has " 619 "spilled udt = {3}", 620 formatRegisterId(Def.Hdr.Register, CompilationCPU), 621 int32_t(Def.Hdr.BasePointerOffset), Def.offsetInParent(), 622 Def.hasSpilledUDTMember()); 623 P.formatLine("range = {0}, gaps = [{1}]", formatRange(Def.Range), 624 formatGaps(P.getIndentLevel() + 9, Def.Gaps)); 625 return Error::success(); 626 } 627 628 Error MinimalSymbolDumper::visitKnownRecord( 629 CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) { 630 AutoIndent Indent(P, 7); 631 P.formatLine("register = {0}, may have no name = {1}, range start = " 632 "{2}, length = {3}", 633 formatRegisterId(DefRangeRegister.Hdr.Register, CompilationCPU), 634 bool(DefRangeRegister.Hdr.MayHaveNoName), 635 formatSegmentOffset(DefRangeRegister.Range.ISectStart, 636 DefRangeRegister.Range.OffsetStart), 637 DefRangeRegister.Range.Range); 638 P.formatLine("gaps = [{0}]", 639 formatGaps(P.getIndentLevel() + 9, DefRangeRegister.Gaps)); 640 return Error::success(); 641 } 642 643 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 644 DefRangeSubfieldRegisterSym &Def) { 645 AutoIndent Indent(P, 7); 646 bool NoName = !!(Def.Hdr.MayHaveNoName == 0); 647 P.formatLine("register = {0}, may have no name = {1}, offset in parent = {2}", 648 formatRegisterId(Def.Hdr.Register, CompilationCPU), NoName, 649 uint32_t(Def.Hdr.OffsetInParent)); 650 P.formatLine("range = {0}, gaps = [{1}]", formatRange(Def.Range), 651 formatGaps(P.getIndentLevel() + 9, Def.Gaps)); 652 return Error::success(); 653 } 654 655 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 656 DefRangeSubfieldSym &Def) { 657 AutoIndent Indent(P, 7); 658 P.formatLine("program = {0}, offset in parent = {1}, range = {2}", 659 Def.Program, Def.OffsetInParent, formatRange(Def.Range)); 660 P.formatLine("gaps = [{0}]", formatGaps(P.getIndentLevel() + 9, Def.Gaps)); 661 return Error::success(); 662 } 663 664 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DefRangeSym &Def) { 665 AutoIndent Indent(P, 7); 666 P.formatLine("program = {0}, range = {1}", Def.Program, 667 formatRange(Def.Range)); 668 P.formatLine("gaps = [{0}]", formatGaps(P.getIndentLevel() + 9, Def.Gaps)); 669 return Error::success(); 670 } 671 672 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameCookieSym &FC) { 673 AutoIndent Indent(P, 7); 674 P.formatLine("code offset = {0}, Register = {1}, kind = {2}, flags = {3}", 675 FC.CodeOffset, formatRegisterId(FC.Register, CompilationCPU), 676 formatCookieKind(FC.CookieKind), FC.Flags); 677 return Error::success(); 678 } 679 680 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameProcSym &FP) { 681 AutoIndent Indent(P, 7); 682 P.formatLine("size = {0}, padding size = {1}, offset to padding = {2}", 683 FP.TotalFrameBytes, FP.PaddingFrameBytes, FP.OffsetToPadding); 684 P.formatLine("bytes of callee saved registers = {0}, exception handler addr " 685 "= {1}", 686 FP.BytesOfCalleeSavedRegisters, 687 formatSegmentOffset(FP.SectionIdOfExceptionHandler, 688 FP.OffsetOfExceptionHandler)); 689 P.formatLine( 690 "local fp reg = {0}, param fp reg = {1}", 691 formatRegisterId(FP.getLocalFramePtrReg(CompilationCPU), CompilationCPU), 692 formatRegisterId(FP.getParamFramePtrReg(CompilationCPU), CompilationCPU)); 693 P.formatLine("flags = {0}", 694 formatFrameProcedureOptions(P.getIndentLevel() + 9, FP.Flags)); 695 return Error::success(); 696 } 697 698 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 699 HeapAllocationSiteSym &HAS) { 700 AutoIndent Indent(P, 7); 701 P.formatLine("type = {0}, addr = {1} call size = {2}", typeIndex(HAS.Type), 702 formatSegmentOffset(HAS.Segment, HAS.CodeOffset), 703 HAS.CallInstructionSize); 704 return Error::success(); 705 } 706 707 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, InlineSiteSym &IS) { 708 AutoIndent Indent(P, 7); 709 P.formatLine("inlinee = {0}, parent = {1}, end = {2}", idIndex(IS.Inlinee), 710 IS.Parent, IS.End); 711 712 // Break down the annotation byte code and calculate code and line offsets. 713 // FIXME: It would be helpful if we could look up the initial file and inlinee 714 // lines offset using the inlinee index above. 715 uint32_t CodeOffset = 0; 716 int32_t LineOffset = 0; 717 for (auto &Annot : IS.annotations()) { 718 P.formatLine(" {0}", fmt_align(toHex(Annot.Bytes), AlignStyle::Left, 9)); 719 720 auto formatCodeOffset = [&](uint32_t Delta) { 721 CodeOffset += Delta; 722 P.format(" code 0x{0} (+0x{1})", utohexstr(CodeOffset), utohexstr(Delta)); 723 }; 724 auto formatCodeLength = [&](uint32_t Length) { 725 // Notably, changing the code length does not affect the code offset. 726 P.format(" code end 0x{0} (+0x{1})", utohexstr(CodeOffset + Length), 727 utohexstr(Length)); 728 }; 729 auto formatLineOffset = [&](int32_t Delta) { 730 LineOffset += Delta; 731 char Sign = Delta > 0 ? '+' : '-'; 732 P.format(" line {0} ({1}{2})", LineOffset, Sign, std::abs(Delta)); 733 }; 734 735 // Use the opcode to interpret the integer values. 736 switch (Annot.OpCode) { 737 case BinaryAnnotationsOpCode::Invalid: 738 break; 739 case BinaryAnnotationsOpCode::CodeOffset: 740 case BinaryAnnotationsOpCode::ChangeCodeOffset: 741 formatCodeOffset(Annot.U1); 742 break; 743 case BinaryAnnotationsOpCode::ChangeLineOffset: 744 formatLineOffset(Annot.S1); 745 break; 746 case BinaryAnnotationsOpCode::ChangeCodeLength: 747 formatCodeLength(Annot.U1); 748 // Apparently this annotation updates the code offset. It's hard to make 749 // MSVC produce this opcode, but clang uses it, and debuggers seem to use 750 // this interpretation. 751 CodeOffset += Annot.U1; 752 break; 753 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: 754 formatCodeOffset(Annot.U1); 755 formatLineOffset(Annot.S1); 756 break; 757 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: 758 formatCodeOffset(Annot.U2); 759 formatCodeLength(Annot.U1); 760 break; 761 762 case BinaryAnnotationsOpCode::ChangeFile: { 763 uint32_t FileOffset = Annot.U1; 764 StringRef Filename = "<unknown>"; 765 if (SymGroup) { 766 if (Expected<StringRef> MaybeFile = 767 SymGroup->getNameFromStringTable(FileOffset)) 768 Filename = *MaybeFile; 769 else 770 return MaybeFile.takeError(); 771 } 772 P.format(" setfile {0} 0x{1}", utohexstr(FileOffset)); 773 break; 774 } 775 776 // The rest of these are hard to convince MSVC to emit, so they are not as 777 // well understood. 778 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: 779 formatCodeOffset(Annot.U1); 780 break; 781 case BinaryAnnotationsOpCode::ChangeLineEndDelta: 782 case BinaryAnnotationsOpCode::ChangeRangeKind: 783 case BinaryAnnotationsOpCode::ChangeColumnStart: 784 case BinaryAnnotationsOpCode::ChangeColumnEnd: 785 P.format(" {0} {1}", Annot.Name, Annot.U1); 786 break; 787 case BinaryAnnotationsOpCode::ChangeColumnEndDelta: 788 P.format(" {0} {1}", Annot.Name, Annot.S1); 789 break; 790 } 791 } 792 return Error::success(); 793 } 794 795 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 796 RegisterSym &Register) { 797 P.format(" `{0}`", Register.Name); 798 AutoIndent Indent(P, 7); 799 P.formatLine("register = {0}, type = {1}", 800 formatRegisterId(Register.Register, CompilationCPU), 801 typeIndex(Register.Index)); 802 return Error::success(); 803 } 804 805 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 806 PublicSym32 &Public) { 807 P.format(" `{0}`", Public.Name); 808 AutoIndent Indent(P, 7); 809 P.formatLine("flags = {0}, addr = {1}", 810 formatPublicSymFlags(P.getIndentLevel() + 9, Public.Flags), 811 formatSegmentOffset(Public.Segment, Public.Offset)); 812 return Error::success(); 813 } 814 815 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcRefSym &PR) { 816 P.format(" `{0}`", PR.Name); 817 AutoIndent Indent(P, 7); 818 P.formatLine("module = {0}, sum name = {1}, offset = {2}", PR.Module, 819 PR.SumName, PR.SymOffset); 820 return Error::success(); 821 } 822 823 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) { 824 P.format(" `{0}` (addr = {1})", Label.Name, 825 formatSegmentOffset(Label.Segment, Label.CodeOffset)); 826 AutoIndent Indent(P, 7); 827 P.formatLine("flags = {0}", 828 formatProcSymFlags(P.getIndentLevel() + 9, Label.Flags)); 829 return Error::success(); 830 } 831 832 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) { 833 P.format(" `{0}`", Local.Name); 834 AutoIndent Indent(P, 7); 835 836 std::string FlagStr = 837 formatLocalSymFlags(P.getIndentLevel() + 9, Local.Flags); 838 P.formatLine("type={0}, flags = {1}", typeIndex(Local.Type), FlagStr); 839 return Error::success(); 840 } 841 842 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 843 ObjNameSym &ObjName) { 844 P.format(" sig={0}, `{1}`", ObjName.Signature, ObjName.Name); 845 return Error::success(); 846 } 847 848 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) { 849 P.format(" `{0}`", Proc.Name); 850 AutoIndent Indent(P, 7); 851 P.formatLine("parent = {0}, end = {1}, addr = {2}, code size = {3}", 852 Proc.Parent, Proc.End, 853 formatSegmentOffset(Proc.Segment, Proc.CodeOffset), 854 Proc.CodeSize); 855 bool IsType = true; 856 switch (Proc.getKind()) { 857 case SymbolRecordKind::GlobalProcIdSym: 858 case SymbolRecordKind::ProcIdSym: 859 case SymbolRecordKind::DPCProcIdSym: 860 IsType = false; 861 break; 862 default: 863 break; 864 } 865 P.formatLine("type = `{0}`, debug start = {1}, debug end = {2}, flags = {3}", 866 typeOrIdIndex(Proc.FunctionType, IsType), Proc.DbgStart, 867 Proc.DbgEnd, 868 formatProcSymFlags(P.getIndentLevel() + 9, Proc.Flags)); 869 return Error::success(); 870 } 871 872 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 873 ScopeEndSym &ScopeEnd) { 874 return Error::success(); 875 } 876 877 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) { 878 const char *Format; 879 switch (CVR.kind()) { 880 case S_CALLEES: 881 Format = "callee: {0}"; 882 break; 883 case S_CALLERS: 884 Format = "caller: {0}"; 885 break; 886 case S_INLINEES: 887 Format = "inlinee: {0}"; 888 break; 889 default: 890 return llvm::make_error<CodeViewError>( 891 "Unknown CV Record type for a CallerSym object!"); 892 } 893 AutoIndent Indent(P, 7); 894 for (const auto &I : Caller.Indices) { 895 P.formatLine(Format, idIndex(I)); 896 } 897 return Error::success(); 898 } 899 900 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 901 RegRelativeSym &RegRel) { 902 P.format(" `{0}`", RegRel.Name); 903 AutoIndent Indent(P, 7); 904 P.formatLine( 905 "type = {0}, register = {1}, offset = {2}", typeIndex(RegRel.Type), 906 formatRegisterId(RegRel.Register, CompilationCPU), RegRel.Offset); 907 return Error::success(); 908 } 909 910 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 911 ThreadLocalDataSym &Data) { 912 P.format(" `{0}`", Data.Name); 913 AutoIndent Indent(P, 7); 914 P.formatLine("type = {0}, addr = {1}", typeIndex(Data.Type), 915 formatSegmentOffset(Data.Segment, Data.DataOffset)); 916 return Error::success(); 917 } 918 919 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) { 920 P.format(" `{0}`", UDT.Name); 921 AutoIndent Indent(P, 7); 922 P.formatLine("original type = {0}", UDT.Type); 923 return Error::success(); 924 } 925 926 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 927 UsingNamespaceSym &UN) { 928 P.format(" `{0}`", UN.Name); 929 return Error::success(); 930 } 931 932 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 933 AnnotationSym &Annot) { 934 AutoIndent Indent(P, 7); 935 P.formatLine("addr = {0}", formatSegmentOffset(Annot.Segment, Annot.CodeOffset)); 936 P.formatLine("strings = {0}", typesetStringList(P.getIndentLevel() + 9 + 2, 937 Annot.Strings)); 938 return Error::success(); 939 } 940 941 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, 942 JumpTableSym &JumpTable) { 943 AutoIndent Indent(P, 7); 944 P.formatLine( 945 "base = {0}, switchtype = {1}, branch = {2}, table = {3}, entriescount = " 946 "{4}", 947 formatSegmentOffset(JumpTable.BaseSegment, JumpTable.BaseOffset), 948 formatJumpTableEntrySize(JumpTable.SwitchType), 949 formatSegmentOffset(JumpTable.BranchSegment, JumpTable.BranchOffset), 950 formatSegmentOffset(JumpTable.TableSegment, JumpTable.TableOffset), 951 JumpTable.EntriesCount); 952 return Error::success(); 953 } 954