1 //===-- TypeDumpVisitor.cpp - CodeView type 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/TypeDumpVisitor.h" 10 11 #include "llvm/ADT/ArrayRef.h" 12 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" 13 #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 14 #include "llvm/DebugInfo/CodeView/TypeCollection.h" 15 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 16 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 17 #include "llvm/Support/FormatVariadic.h" 18 #include "llvm/Support/ScopedPrinter.h" 19 #include "llvm/Support/raw_ostream.h" 20 21 using namespace llvm; 22 using namespace llvm::codeview; 23 24 static const EnumEntry<TypeLeafKind> LeafTypeNames[] = { 25 #define CV_TYPE(enum, val) {#enum, enum}, 26 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" 27 }; 28 29 #define ENUM_ENTRY(enum_class, enum) \ 30 { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) } 31 32 static const EnumEntry<uint16_t> ClassOptionNames[] = { 33 ENUM_ENTRY(ClassOptions, Packed), 34 ENUM_ENTRY(ClassOptions, HasConstructorOrDestructor), 35 ENUM_ENTRY(ClassOptions, HasOverloadedOperator), 36 ENUM_ENTRY(ClassOptions, Nested), 37 ENUM_ENTRY(ClassOptions, ContainsNestedClass), 38 ENUM_ENTRY(ClassOptions, HasOverloadedAssignmentOperator), 39 ENUM_ENTRY(ClassOptions, HasConversionOperator), 40 ENUM_ENTRY(ClassOptions, ForwardReference), 41 ENUM_ENTRY(ClassOptions, Scoped), 42 ENUM_ENTRY(ClassOptions, HasUniqueName), 43 ENUM_ENTRY(ClassOptions, Sealed), 44 ENUM_ENTRY(ClassOptions, Intrinsic), 45 }; 46 47 static const EnumEntry<uint8_t> MemberAccessNames[] = { 48 ENUM_ENTRY(MemberAccess, None), ENUM_ENTRY(MemberAccess, Private), 49 ENUM_ENTRY(MemberAccess, Protected), ENUM_ENTRY(MemberAccess, Public), 50 }; 51 52 static const EnumEntry<uint16_t> MethodOptionNames[] = { 53 ENUM_ENTRY(MethodOptions, Pseudo), 54 ENUM_ENTRY(MethodOptions, NoInherit), 55 ENUM_ENTRY(MethodOptions, NoConstruct), 56 ENUM_ENTRY(MethodOptions, CompilerGenerated), 57 ENUM_ENTRY(MethodOptions, Sealed), 58 }; 59 60 static const EnumEntry<uint16_t> MemberKindNames[] = { 61 ENUM_ENTRY(MethodKind, Vanilla), 62 ENUM_ENTRY(MethodKind, Virtual), 63 ENUM_ENTRY(MethodKind, Static), 64 ENUM_ENTRY(MethodKind, Friend), 65 ENUM_ENTRY(MethodKind, IntroducingVirtual), 66 ENUM_ENTRY(MethodKind, PureVirtual), 67 ENUM_ENTRY(MethodKind, PureIntroducingVirtual), 68 }; 69 70 static const EnumEntry<uint8_t> PtrKindNames[] = { 71 ENUM_ENTRY(PointerKind, Near16), 72 ENUM_ENTRY(PointerKind, Far16), 73 ENUM_ENTRY(PointerKind, Huge16), 74 ENUM_ENTRY(PointerKind, BasedOnSegment), 75 ENUM_ENTRY(PointerKind, BasedOnValue), 76 ENUM_ENTRY(PointerKind, BasedOnSegmentValue), 77 ENUM_ENTRY(PointerKind, BasedOnAddress), 78 ENUM_ENTRY(PointerKind, BasedOnSegmentAddress), 79 ENUM_ENTRY(PointerKind, BasedOnType), 80 ENUM_ENTRY(PointerKind, BasedOnSelf), 81 ENUM_ENTRY(PointerKind, Near32), 82 ENUM_ENTRY(PointerKind, Far32), 83 ENUM_ENTRY(PointerKind, Near64), 84 }; 85 86 static const EnumEntry<uint8_t> PtrModeNames[] = { 87 ENUM_ENTRY(PointerMode, Pointer), 88 ENUM_ENTRY(PointerMode, LValueReference), 89 ENUM_ENTRY(PointerMode, PointerToDataMember), 90 ENUM_ENTRY(PointerMode, PointerToMemberFunction), 91 ENUM_ENTRY(PointerMode, RValueReference), 92 }; 93 94 static const EnumEntry<uint16_t> PtrMemberRepNames[] = { 95 ENUM_ENTRY(PointerToMemberRepresentation, Unknown), 96 ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceData), 97 ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceData), 98 ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceData), 99 ENUM_ENTRY(PointerToMemberRepresentation, GeneralData), 100 ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceFunction), 101 ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceFunction), 102 ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceFunction), 103 ENUM_ENTRY(PointerToMemberRepresentation, GeneralFunction), 104 }; 105 106 static const EnumEntry<uint16_t> TypeModifierNames[] = { 107 ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile), 108 ENUM_ENTRY(ModifierOptions, Unaligned), 109 }; 110 111 static const EnumEntry<uint8_t> CallingConventions[] = { 112 ENUM_ENTRY(CallingConvention, NearC), 113 ENUM_ENTRY(CallingConvention, FarC), 114 ENUM_ENTRY(CallingConvention, NearPascal), 115 ENUM_ENTRY(CallingConvention, FarPascal), 116 ENUM_ENTRY(CallingConvention, NearFast), 117 ENUM_ENTRY(CallingConvention, FarFast), 118 ENUM_ENTRY(CallingConvention, NearStdCall), 119 ENUM_ENTRY(CallingConvention, FarStdCall), 120 ENUM_ENTRY(CallingConvention, NearSysCall), 121 ENUM_ENTRY(CallingConvention, FarSysCall), 122 ENUM_ENTRY(CallingConvention, ThisCall), 123 ENUM_ENTRY(CallingConvention, MipsCall), 124 ENUM_ENTRY(CallingConvention, Generic), 125 ENUM_ENTRY(CallingConvention, AlphaCall), 126 ENUM_ENTRY(CallingConvention, PpcCall), 127 ENUM_ENTRY(CallingConvention, SHCall), 128 ENUM_ENTRY(CallingConvention, ArmCall), 129 ENUM_ENTRY(CallingConvention, AM33Call), 130 ENUM_ENTRY(CallingConvention, TriCall), 131 ENUM_ENTRY(CallingConvention, SH5Call), 132 ENUM_ENTRY(CallingConvention, M32RCall), 133 ENUM_ENTRY(CallingConvention, ClrCall), 134 ENUM_ENTRY(CallingConvention, Inline), 135 ENUM_ENTRY(CallingConvention, NearVector), 136 }; 137 138 static const EnumEntry<uint8_t> FunctionOptionEnum[] = { 139 ENUM_ENTRY(FunctionOptions, CxxReturnUdt), 140 ENUM_ENTRY(FunctionOptions, Constructor), 141 ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases), 142 }; 143 144 static const EnumEntry<uint16_t> LabelTypeEnum[] = { 145 ENUM_ENTRY(LabelType, Near), ENUM_ENTRY(LabelType, Far), 146 }; 147 148 #undef ENUM_ENTRY 149 150 static StringRef getLeafTypeName(TypeLeafKind LT) { 151 switch (LT) { 152 #define TYPE_RECORD(ename, value, name) \ 153 case ename: \ 154 return #name; 155 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" 156 default: 157 break; 158 } 159 return "UnknownLeaf"; 160 } 161 162 void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const { 163 codeview::printTypeIndex(*W, FieldName, TI, TpiTypes); 164 } 165 166 void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const { 167 codeview::printTypeIndex(*W, FieldName, TI, getSourceTypes()); 168 } 169 170 Error TypeDumpVisitor::visitTypeBegin(CVType &Record) { 171 return visitTypeBegin(Record, TypeIndex::fromArrayIndex(TpiTypes.size())); 172 } 173 174 Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) { 175 W->startLine() << getLeafTypeName(Record.kind()); 176 W->getOStream() << " (" << HexNumber(Index.getIndex()) << ")"; 177 W->getOStream() << " {\n"; 178 W->indent(); 179 W->printEnum("TypeLeafKind", unsigned(Record.kind()), 180 makeArrayRef(LeafTypeNames)); 181 return Error::success(); 182 } 183 184 Error TypeDumpVisitor::visitTypeEnd(CVType &Record) { 185 if (PrintRecordBytes) 186 W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content())); 187 188 W->unindent(); 189 W->startLine() << "}\n"; 190 return Error::success(); 191 } 192 193 Error TypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) { 194 W->startLine() << getLeafTypeName(Record.Kind); 195 W->getOStream() << " {\n"; 196 W->indent(); 197 W->printEnum("TypeLeafKind", unsigned(Record.Kind), 198 makeArrayRef(LeafTypeNames)); 199 return Error::success(); 200 } 201 202 Error TypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) { 203 if (PrintRecordBytes) 204 W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data)); 205 206 W->unindent(); 207 W->startLine() << "}\n"; 208 return Error::success(); 209 } 210 211 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 212 FieldListRecord &FieldList) { 213 if (auto EC = codeview::visitMemberRecordStream(FieldList.Data, *this)) 214 return EC; 215 216 return Error::success(); 217 } 218 219 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringIdRecord &String) { 220 printItemIndex("Id", String.getId()); 221 W->printString("StringData", String.getString()); 222 return Error::success(); 223 } 224 225 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { 226 auto Indices = Args.getIndices(); 227 uint32_t Size = Indices.size(); 228 W->printNumber("NumArgs", Size); 229 ListScope Arguments(*W, "Arguments"); 230 for (uint32_t I = 0; I < Size; ++I) { 231 printTypeIndex("ArgType", Indices[I]); 232 } 233 return Error::success(); 234 } 235 236 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringListRecord &Strs) { 237 auto Indices = Strs.getIndices(); 238 uint32_t Size = Indices.size(); 239 W->printNumber("NumStrings", Size); 240 ListScope Arguments(*W, "Strings"); 241 for (uint32_t I = 0; I < Size; ++I) { 242 printItemIndex("String", Indices[I]); 243 } 244 return Error::success(); 245 } 246 247 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) { 248 uint16_t Props = static_cast<uint16_t>(Class.getOptions()); 249 W->printNumber("MemberCount", Class.getMemberCount()); 250 W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); 251 printTypeIndex("FieldList", Class.getFieldList()); 252 printTypeIndex("DerivedFrom", Class.getDerivationList()); 253 printTypeIndex("VShape", Class.getVTableShape()); 254 W->printNumber("SizeOf", Class.getSize()); 255 W->printString("Name", Class.getName()); 256 if (Props & uint16_t(ClassOptions::HasUniqueName)) 257 W->printString("LinkageName", Class.getUniqueName()); 258 return Error::success(); 259 } 260 261 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) { 262 uint16_t Props = static_cast<uint16_t>(Union.getOptions()); 263 W->printNumber("MemberCount", Union.getMemberCount()); 264 W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); 265 printTypeIndex("FieldList", Union.getFieldList()); 266 W->printNumber("SizeOf", Union.getSize()); 267 W->printString("Name", Union.getName()); 268 if (Props & uint16_t(ClassOptions::HasUniqueName)) 269 W->printString("LinkageName", Union.getUniqueName()); 270 return Error::success(); 271 } 272 273 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) { 274 uint16_t Props = static_cast<uint16_t>(Enum.getOptions()); 275 W->printNumber("NumEnumerators", Enum.getMemberCount()); 276 W->printFlags("Properties", uint16_t(Enum.getOptions()), 277 makeArrayRef(ClassOptionNames)); 278 printTypeIndex("UnderlyingType", Enum.getUnderlyingType()); 279 printTypeIndex("FieldListType", Enum.getFieldList()); 280 W->printString("Name", Enum.getName()); 281 if (Props & uint16_t(ClassOptions::HasUniqueName)) 282 W->printString("LinkageName", Enum.getUniqueName()); 283 return Error::success(); 284 } 285 286 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) { 287 printTypeIndex("ElementType", AT.getElementType()); 288 printTypeIndex("IndexType", AT.getIndexType()); 289 W->printNumber("SizeOf", AT.getSize()); 290 W->printString("Name", AT.getName()); 291 return Error::success(); 292 } 293 294 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) { 295 printTypeIndex("CompleteClass", VFT.getCompleteClass()); 296 printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable()); 297 W->printHex("VFPtrOffset", VFT.getVFPtrOffset()); 298 W->printString("VFTableName", VFT.getName()); 299 for (auto N : VFT.getMethodNames()) 300 W->printString("MethodName", N); 301 return Error::success(); 302 } 303 304 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) { 305 printTypeIndex("ClassType", Id.getClassType()); 306 printTypeIndex("FunctionType", Id.getFunctionType()); 307 W->printString("Name", Id.getName()); 308 return Error::success(); 309 } 310 311 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) { 312 printTypeIndex("ReturnType", Proc.getReturnType()); 313 W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()), 314 makeArrayRef(CallingConventions)); 315 W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()), 316 makeArrayRef(FunctionOptionEnum)); 317 W->printNumber("NumParameters", Proc.getParameterCount()); 318 printTypeIndex("ArgListType", Proc.getArgumentList()); 319 return Error::success(); 320 } 321 322 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFunctionRecord &MF) { 323 printTypeIndex("ReturnType", MF.getReturnType()); 324 printTypeIndex("ClassType", MF.getClassType()); 325 printTypeIndex("ThisType", MF.getThisType()); 326 W->printEnum("CallingConvention", uint8_t(MF.getCallConv()), 327 makeArrayRef(CallingConventions)); 328 W->printFlags("FunctionOptions", uint8_t(MF.getOptions()), 329 makeArrayRef(FunctionOptionEnum)); 330 W->printNumber("NumParameters", MF.getParameterCount()); 331 printTypeIndex("ArgListType", MF.getArgumentList()); 332 W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment()); 333 return Error::success(); 334 } 335 336 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 337 MethodOverloadListRecord &MethodList) { 338 for (auto &M : MethodList.getMethods()) { 339 ListScope S(*W, "Method"); 340 printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions()); 341 printTypeIndex("Type", M.getType()); 342 if (M.isIntroducingVirtual()) 343 W->printHex("VFTableOffset", M.getVFTableOffset()); 344 } 345 return Error::success(); 346 } 347 348 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) { 349 printItemIndex("ParentScope", Func.getParentScope()); 350 printTypeIndex("FunctionType", Func.getFunctionType()); 351 W->printString("Name", Func.getName()); 352 return Error::success(); 353 } 354 355 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) { 356 W->printString("Guid", formatv("{0}", TS.getGuid()).str()); 357 W->printNumber("Age", TS.getAge()); 358 W->printString("Name", TS.getName()); 359 return Error::success(); 360 } 361 362 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { 363 printTypeIndex("PointeeType", Ptr.getReferentType()); 364 W->printEnum("PtrType", unsigned(Ptr.getPointerKind()), 365 makeArrayRef(PtrKindNames)); 366 W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames)); 367 368 W->printNumber("IsFlat", Ptr.isFlat()); 369 W->printNumber("IsConst", Ptr.isConst()); 370 W->printNumber("IsVolatile", Ptr.isVolatile()); 371 W->printNumber("IsUnaligned", Ptr.isUnaligned()); 372 W->printNumber("IsRestrict", Ptr.isRestrict()); 373 W->printNumber("IsThisPtr&", Ptr.isLValueReferenceThisPtr()); 374 W->printNumber("IsThisPtr&&", Ptr.isRValueReferenceThisPtr()); 375 W->printNumber("SizeOf", Ptr.getSize()); 376 377 if (Ptr.isPointerToMember()) { 378 const MemberPointerInfo &MI = Ptr.getMemberInfo(); 379 380 printTypeIndex("ClassType", MI.getContainingType()); 381 W->printEnum("Representation", uint16_t(MI.getRepresentation()), 382 makeArrayRef(PtrMemberRepNames)); 383 } 384 385 return Error::success(); 386 } 387 388 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { 389 uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); 390 printTypeIndex("ModifiedType", Mod.getModifiedType()); 391 W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames)); 392 393 return Error::success(); 394 } 395 396 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) { 397 printTypeIndex("Type", BitField.getType()); 398 W->printNumber("BitSize", BitField.getBitSize()); 399 W->printNumber("BitOffset", BitField.getBitOffset()); 400 return Error::success(); 401 } 402 403 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 404 VFTableShapeRecord &Shape) { 405 W->printNumber("VFEntryCount", Shape.getEntryCount()); 406 return Error::success(); 407 } 408 409 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 410 UdtSourceLineRecord &Line) { 411 printTypeIndex("UDT", Line.getUDT()); 412 printItemIndex("SourceFile", Line.getSourceFile()); 413 W->printNumber("LineNumber", Line.getLineNumber()); 414 return Error::success(); 415 } 416 417 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 418 UdtModSourceLineRecord &Line) { 419 printTypeIndex("UDT", Line.getUDT()); 420 printItemIndex("SourceFile", Line.getSourceFile()); 421 W->printNumber("LineNumber", Line.getLineNumber()); 422 W->printNumber("Module", Line.getModule()); 423 return Error::success(); 424 } 425 426 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) { 427 W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size())); 428 429 ListScope Arguments(*W, "Arguments"); 430 for (auto Arg : Args.getArgs()) { 431 printItemIndex("ArgType", Arg); 432 } 433 return Error::success(); 434 } 435 436 void TypeDumpVisitor::printMemberAttributes(MemberAttributes Attrs) { 437 return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(), 438 Attrs.getFlags()); 439 } 440 441 void TypeDumpVisitor::printMemberAttributes(MemberAccess Access, 442 MethodKind Kind, 443 MethodOptions Options) { 444 W->printEnum("AccessSpecifier", uint8_t(Access), 445 makeArrayRef(MemberAccessNames)); 446 // Data members will be vanilla. Don't try to print a method kind for them. 447 if (Kind != MethodKind::Vanilla) 448 W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames)); 449 if (Options != MethodOptions::None) { 450 W->printFlags("MethodOptions", unsigned(Options), 451 makeArrayRef(MethodOptionNames)); 452 } 453 } 454 455 Error TypeDumpVisitor::visitUnknownMember(CVMemberRecord &Record) { 456 W->printHex("UnknownMember", unsigned(Record.Kind)); 457 return Error::success(); 458 } 459 460 Error TypeDumpVisitor::visitUnknownType(CVType &Record) { 461 W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames)); 462 W->printNumber("Length", uint32_t(Record.content().size())); 463 return Error::success(); 464 } 465 466 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 467 NestedTypeRecord &Nested) { 468 printTypeIndex("Type", Nested.getNestedType()); 469 W->printString("Name", Nested.getName()); 470 return Error::success(); 471 } 472 473 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 474 OneMethodRecord &Method) { 475 MethodKind K = Method.getMethodKind(); 476 printMemberAttributes(Method.getAccess(), K, Method.getOptions()); 477 printTypeIndex("Type", Method.getType()); 478 // If virtual, then read the vftable offset. 479 if (Method.isIntroducingVirtual()) 480 W->printHex("VFTableOffset", Method.getVFTableOffset()); 481 W->printString("Name", Method.getName()); 482 return Error::success(); 483 } 484 485 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 486 OverloadedMethodRecord &Method) { 487 W->printHex("MethodCount", Method.getNumOverloads()); 488 printTypeIndex("MethodListIndex", Method.getMethodList()); 489 W->printString("Name", Method.getName()); 490 return Error::success(); 491 } 492 493 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 494 DataMemberRecord &Field) { 495 printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, 496 MethodOptions::None); 497 printTypeIndex("Type", Field.getType()); 498 W->printHex("FieldOffset", Field.getFieldOffset()); 499 W->printString("Name", Field.getName()); 500 return Error::success(); 501 } 502 503 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 504 StaticDataMemberRecord &Field) { 505 printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, 506 MethodOptions::None); 507 printTypeIndex("Type", Field.getType()); 508 W->printString("Name", Field.getName()); 509 return Error::success(); 510 } 511 512 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 513 VFPtrRecord &VFTable) { 514 printTypeIndex("Type", VFTable.getType()); 515 return Error::success(); 516 } 517 518 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 519 EnumeratorRecord &Enum) { 520 printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla, 521 MethodOptions::None); 522 W->printNumber("EnumValue", Enum.getValue()); 523 W->printString("Name", Enum.getName()); 524 return Error::success(); 525 } 526 527 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 528 BaseClassRecord &Base) { 529 printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, 530 MethodOptions::None); 531 printTypeIndex("BaseType", Base.getBaseType()); 532 W->printHex("BaseOffset", Base.getBaseOffset()); 533 return Error::success(); 534 } 535 536 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 537 VirtualBaseClassRecord &Base) { 538 printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, 539 MethodOptions::None); 540 printTypeIndex("BaseType", Base.getBaseType()); 541 printTypeIndex("VBPtrType", Base.getVBPtrType()); 542 W->printHex("VBPtrOffset", Base.getVBPtrOffset()); 543 W->printHex("VBTableIndex", Base.getVTableIndex()); 544 return Error::success(); 545 } 546 547 Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, 548 ListContinuationRecord &Cont) { 549 printTypeIndex("ContinuationIndex", Cont.getContinuationIndex()); 550 return Error::success(); 551 } 552 553 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &LR) { 554 W->printEnum("Mode", uint16_t(LR.Mode), makeArrayRef(LabelTypeEnum)); 555 return Error::success(); 556 } 557 558 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 559 PrecompRecord &Precomp) { 560 W->printHex("StartIndex", Precomp.getStartTypeIndex()); 561 W->printHex("Count", Precomp.getTypesCount()); 562 W->printHex("Signature", Precomp.getSignature()); 563 W->printString("PrecompFile", Precomp.getPrecompFilePath()); 564 return Error::success(); 565 } 566 567 Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, 568 EndPrecompRecord &EndPrecomp) { 569 W->printHex("Signature", EndPrecomp.getSignature()); 570 return Error::success(); 571 } 572