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