Index: include/llvm/DebugInfo/CodeView/CVTypeVisitor.h =================================================================== --- include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -28,6 +28,8 @@ /// Visits the type records in Data. Sets the error flag on parse failures. Error visitTypeStream(const CVTypeArray &Types); + Error visitFieldListMemberStream(ArrayRef FieldList); + private: /// The interface to the class that gets notified of each visitation. TypeVisitorCallbacks &Callbacks; Index: include/llvm/DebugInfo/CodeView/EnumTables.h =================================================================== --- include/llvm/DebugInfo/CodeView/EnumTables.h +++ include/llvm/DebugInfo/CodeView/EnumTables.h @@ -20,6 +20,7 @@ namespace llvm { namespace codeview { ArrayRef> getSymbolTypeNames(); +ArrayRef> getTypeLeafNames(); ArrayRef> getRegisterNames(); ArrayRef> getProcSymFlagNames(); ArrayRef> getLocalFlagNames(); Index: include/llvm/DebugInfo/CodeView/TypeDeserializer.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeDeserializer.h +++ include/llvm/DebugInfo/CodeView/TypeDeserializer.h @@ -15,9 +15,9 @@ namespace llvm { namespace codeview { -class TypeDeserializerBase : public TypeVisitorCallbacks { +class TypeDeserializer : public TypeVisitorCallbacks { public: - explicit TypeDeserializerBase(TypeVisitorCallbacks &Recipient) + explicit TypeDeserializer(TypeVisitorCallbacks &Recipient) : Recipient(Recipient) {} Error visitTypeBegin(const CVRecord &Record) override { @@ -62,39 +62,6 @@ return Recipient.visitKnownRecord(CVR, Record); } }; - -class TypeDeserializer : public TypeDeserializerBase { -public: - explicit TypeDeserializer(TypeVisitorCallbacks &Recipient) - : TypeDeserializerBase(Recipient) {} - - /// FieldList records need special handling. For starters, they do not - /// describe their own length, so a different extraction algorithm is - /// necessary. Secondly, a single FieldList record will result in the - /// deserialization of many records. So even though the top level visitor - /// calls visitFieldBegin() on a single record, multiple records get visited - /// through the callback interface. - Error visitKnownRecord(const CVRecord &CVR, - FieldListRecord &Record) override; - -private: - template - Error visitKnownMember(ArrayRef &Data, TypeLeafKind Kind, - T &Record) { - ArrayRef OldData = Data; - if (auto EC = deserializeRecord(Data, Kind, Record)) - return EC; - assert(Data.size() < OldData.size()); - - CVRecord CVR; - CVR.Length = OldData.size() - Data.size(); - CVR.Data = OldData.slice(0, CVR.Length); - CVR.RawData = CVR.Data; - return Recipient.visitKnownRecord(CVR, Record); - } - - Error skipPadding(ArrayRef &Data); -}; } } Index: include/llvm/DebugInfo/CodeView/TypeDumper.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeDumper.h +++ include/llvm/DebugInfo/CodeView/TypeDumper.h @@ -87,6 +87,7 @@ ScopedPrinter *W; + bool IsInFieldList = false; bool PrintRecordBytes = false; /// Name of the current type. Only valid before visitTypeEnd. Index: include/llvm/DebugInfo/CodeView/TypeRecord.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeRecord.h +++ include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -12,6 +12,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" @@ -27,6 +28,9 @@ using llvm::support::ulittle16_t; using llvm::support::ulittle32_t; +typedef CVRecord CVType; +typedef msf::VarStreamArray CVTypeArray; + /// Equvalent to CV_fldattr_t in cvinfo.h. struct MemberAttributes { ulittle16_t Attrs; @@ -90,18 +94,19 @@ return Representation; } + TypeIndex ContainingType; + PointerToMemberRepresentation Representation; + private: struct Layout { TypeIndex ClassType; ulittle16_t Representation; // PointerToMemberRepresentation }; - - TypeIndex ContainingType; - PointerToMemberRepresentation Representation; }; class TypeRecord { protected: + TypeRecord() {} explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {} public: @@ -129,14 +134,14 @@ TypeIndex getModifiedType() const { return ModifiedType; } ModifierOptions getModifiers() const { return Modifiers; } + TypeIndex ModifiedType; + ModifierOptions Modifiers; + private: struct Layout { TypeIndex ModifiedType; ulittle16_t Modifiers; // ModifierOptions }; - - TypeIndex ModifiedType; - ModifierOptions Modifiers; }; // LF_PROCEDURE @@ -165,6 +170,12 @@ uint16_t getParameterCount() const { return ParameterCount; } TypeIndex getArgumentList() const { return ArgumentList; } + TypeIndex ReturnType; + CallingConvention CallConv; + FunctionOptions Options; + uint16_t ParameterCount; + TypeIndex ArgumentList; + private: struct Layout { TypeIndex ReturnType; @@ -173,12 +184,6 @@ ulittle16_t NumParameters; TypeIndex ArgListType; }; - - TypeIndex ReturnType; - CallingConvention CallConv; - FunctionOptions Options; - uint16_t ParameterCount; - TypeIndex ArgumentList; }; // LF_MFUNCTION @@ -212,6 +217,15 @@ TypeIndex getArgumentList() const { return ArgumentList; } int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; } + TypeIndex ReturnType; + TypeIndex ClassType; + TypeIndex ThisType; + CallingConvention CallConv; + FunctionOptions Options; + uint16_t ParameterCount; + TypeIndex ArgumentList; + int32_t ThisPointerAdjustment; + private: struct Layout { TypeIndex ReturnType; @@ -223,15 +237,6 @@ TypeIndex ArgListType; little32_t ThisAdjustment; }; - - TypeIndex ReturnType; - TypeIndex ClassType; - TypeIndex ThisType; - CallingConvention CallConv; - FunctionOptions Options; - uint16_t ParameterCount; - TypeIndex ArgumentList; - int32_t ThisPointerAdjustment; }; // LF_MFUNC_ID @@ -252,6 +257,9 @@ TypeIndex getClassType() const { return ClassType; } TypeIndex getFunctionType() const { return FunctionType; } StringRef getName() const { return Name; } + TypeIndex ClassType; + TypeIndex FunctionType; + StringRef Name; private: struct Layout { @@ -259,9 +267,6 @@ TypeIndex FunctionType; // Name: The null-terminated name follows. }; - TypeIndex ClassType; - TypeIndex FunctionType; - StringRef Name; }; // LF_ARGLIST, LF_SUBSTR_LIST @@ -283,13 +288,13 @@ static uint32_t getLayoutSize() { return 2 + sizeof(Layout); } + std::vector StringIndices; + private: struct Layout { ulittle32_t NumArgs; // Number of arguments // ArgTypes[]: Type indicies of arguments }; - - std::vector StringIndices; }; // LF_POINTER @@ -308,8 +313,8 @@ PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode, PointerOptions Options, uint8_t Size) - : PointerRecord(ReferentType, Kind, Mode, Options, Size, - MemberPointerInfo()) {} + : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), + PtrKind(Kind), Mode(Mode), Options(Options), Size(Size) {} PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode, PointerOptions Options, uint8_t Size, @@ -330,7 +335,7 @@ PointerMode getMode() const { return Mode; } PointerOptions getOptions() const { return Options; } uint8_t getSize() const { return Size; } - MemberPointerInfo getMemberInfo() const { return MemberInfo; } + MemberPointerInfo getMemberInfo() const { return *MemberInfo; } bool isPointerToMember() const { return Mode == PointerMode::PointerToDataMember || @@ -349,6 +354,13 @@ return !!(uint32_t(Options) & uint32_t(PointerOptions::Unaligned)); } + TypeIndex ReferentType; + PointerKind PtrKind; + PointerMode Mode; + PointerOptions Options; + uint8_t Size; + Optional MemberInfo; + private: struct Layout { TypeIndex PointeeType; @@ -379,13 +391,6 @@ return isPointerToMemberFunction() || isPointerToDataMember(); } }; - - TypeIndex ReferentType; - PointerKind PtrKind; - PointerMode Mode; - PointerOptions Options; - uint8_t Size; - MemberPointerInfo MemberInfo; }; // LF_NESTTYPE @@ -405,23 +410,23 @@ TypeIndex getNestedType() const { return Type; } StringRef getName() const { return Name; } + TypeIndex Type; + StringRef Name; + private: struct Layout { ulittle16_t Pad0; // Should be zero TypeIndex Type; // Type index of nested type // Name: Null-terminated string }; - - TypeIndex Type; - StringRef Name; }; // LF_FIELDLIST class FieldListRecord : public TypeRecord { public: explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} - FieldListRecord(ArrayRef ListData) - : TypeRecord(TypeRecordKind::FieldList), ListData(ListData) {} + explicit FieldListRecord(ArrayRef Data) + : TypeRecord(TypeRecordKind::FieldList), Data(Data) {} /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. @@ -430,10 +435,7 @@ static Expected deserialize(TypeRecordKind Kind, ArrayRef &Data); - ArrayRef getFieldListData() const { return ListData; } - -private: - ArrayRef ListData; + ArrayRef Data; }; // LF_ARRAY @@ -457,6 +459,11 @@ uint64_t getSize() const { return Size; } llvm::StringRef getName() const { return Name; } + TypeIndex ElementType; + TypeIndex IndexType; + uint64_t Size; + llvm::StringRef Name; + private: struct Layout { TypeIndex ElementType; @@ -464,11 +471,6 @@ // SizeOf: LF_NUMERIC encoded size in bytes. Not element count! // Name: The null-terminated name follows. }; - - TypeIndex ElementType; - TypeIndex IndexType; - uint64_t Size; - llvm::StringRef Name; }; class TagRecord : public TypeRecord { @@ -495,7 +497,6 @@ StringRef getName() const { return Name; } StringRef getUniqueName() const { return UniqueName; } -private: uint16_t MemberCount; ClassOptions Options; TypeIndex FieldList; @@ -528,6 +529,12 @@ TypeIndex getVTableShape() const { return VTableShape; } uint64_t getSize() const { return Size; } + HfaKind Hfa; + WindowsRTClassKind WinRTKind; + TypeIndex DerivationList; + TypeIndex VTableShape; + uint64_t Size; + private: struct Layout { ulittle16_t MemberCount; // Number of members in FieldList. @@ -543,12 +550,6 @@ return Properties & uint16_t(ClassOptions::HasUniqueName); } }; - - HfaKind Hfa; - WindowsRTClassKind WinRTKind; - TypeIndex DerivationList; - TypeIndex VTableShape; - uint64_t Size; }; // LF_UNION @@ -567,6 +568,9 @@ HfaKind getHfa() const { return Hfa; } uint64_t getSize() const { return Size; } + HfaKind Hfa; + uint64_t Size; + private: struct Layout { ulittle16_t MemberCount; // Number of members in FieldList. @@ -580,9 +584,6 @@ return Properties & uint16_t(ClassOptions::HasUniqueName); } }; - - HfaKind Hfa; - uint64_t Size; }; // LF_ENUM @@ -602,6 +603,7 @@ ArrayRef &Data); TypeIndex getUnderlyingType() const { return UnderlyingType; } + TypeIndex UnderlyingType; private: struct Layout { @@ -616,7 +618,6 @@ } }; - TypeIndex UnderlyingType; }; // LF_BITFIELD @@ -637,6 +638,9 @@ TypeIndex getType() const { return Type; } uint8_t getBitOffset() const { return BitOffset; } uint8_t getBitSize() const { return BitSize; } + TypeIndex Type; + uint8_t BitSize; + uint8_t BitOffset; private: struct Layout { @@ -645,9 +649,6 @@ uint8_t BitOffset; }; - TypeIndex Type; - uint8_t BitSize; - uint8_t BitOffset; }; // LF_VTSHAPE @@ -672,6 +673,8 @@ return Slots; } uint32_t getEntryCount() const { return getSlots().size(); } + ArrayRef SlotsRef; + std::vector Slots; private: struct Layout { @@ -682,9 +685,6 @@ // Descriptors[]: 4-bit virtual method descriptors of type CV_VTS_desc_e. }; -private: - ArrayRef SlotsRef; - std::vector Slots; }; // LF_TYPESERVER2 @@ -707,6 +707,9 @@ uint32_t getAge() const { return Age; } StringRef getName() const { return Name; } + StringRef Guid; + uint32_t Age; + StringRef Name; private: struct Layout { @@ -714,10 +717,6 @@ ulittle32_t Age; // Name: Name of the PDB as a null-terminated string }; - - StringRef Guid; - uint32_t Age; - StringRef Name; }; // LF_STRING_ID @@ -737,15 +736,14 @@ TypeIndex getId() const { return Id; } StringRef getString() const { return String; } + TypeIndex Id; + StringRef String; private: struct Layout { TypeIndex id; // Name: Name of the PDB as a null-terminated string }; - - TypeIndex Id; - StringRef String; }; // LF_FUNC_ID @@ -768,6 +766,9 @@ TypeIndex getFunctionType() const { return FunctionType; } StringRef getName() const { return Name; } + TypeIndex ParentScope; + TypeIndex FunctionType; + StringRef Name; private: struct Layout { @@ -776,9 +777,6 @@ // Name: The null-terminated name follows. }; - TypeIndex ParentScope; - TypeIndex FunctionType; - StringRef Name; }; // LF_UDT_SRC_LINE @@ -799,6 +797,9 @@ TypeIndex getUDT() const { return UDT; } TypeIndex getSourceFile() const { return SourceFile; } uint32_t getLineNumber() const { return LineNumber; } + TypeIndex UDT; + TypeIndex SourceFile; + uint32_t LineNumber; private: struct Layout { @@ -807,9 +808,6 @@ ulittle32_t LineNumber; }; - TypeIndex UDT; - TypeIndex SourceFile; - uint32_t LineNumber; }; // LF_UDT_MOD_SRC_LINE @@ -836,6 +834,10 @@ TypeIndex getSourceFile() const { return SourceFile; } uint32_t getLineNumber() const { return LineNumber; } uint16_t getModule() const { return Module; } + TypeIndex UDT; + TypeIndex SourceFile; + uint32_t LineNumber; + uint16_t Module; private: struct Layout { @@ -845,10 +847,6 @@ ulittle16_t Module; // Module that contributes this UDT definition }; - TypeIndex UDT; - TypeIndex SourceFile; - uint32_t LineNumber; - uint16_t Module; }; // LF_BUILDINFO @@ -867,13 +865,13 @@ ArrayRef &Data); ArrayRef getArgs() const { return ArgIndices; } + SmallVector ArgIndices; private: struct Layout { ulittle16_t NumArgs; // Number of arguments // ArgTypes[]: Type indicies of arguments }; - SmallVector ArgIndices; }; // LF_VFTABLE @@ -909,6 +907,12 @@ return MethodNamesRef; return MethodNames; } + TypeIndex CompleteClass; + TypeIndex OverriddenVFTable; + ulittle32_t VFPtrOffset; + StringRef Name; + ArrayRef MethodNamesRef; + std::vector MethodNames; private: struct Layout { @@ -920,17 +924,12 @@ // names. }; - TypeIndex CompleteClass; - TypeIndex OverriddenVFTable; - ulittle32_t VFPtrOffset; - StringRef Name; - ArrayRef MethodNamesRef; - std::vector MethodNames; }; // LF_ONEMETHOD class OneMethodRecord : public TypeRecord { public: + OneMethodRecord() : TypeRecord(TypeRecordKind::OneMethod) {} explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} OneMethodRecord(TypeIndex Type, MethodKind Kind, MethodOptions Options, MemberAccess Access, int32_t VFTableOffset, StringRef Name) @@ -956,6 +955,12 @@ return Kind == MethodKind::IntroducingVirtual || Kind == MethodKind::PureIntroducingVirtual; } + TypeIndex Type; + MethodKind Kind; + MethodOptions Options; + MemberAccess Access; + int32_t VFTableOffset; + StringRef Name; private: struct Layout { @@ -966,12 +971,6 @@ // Name: Null-terminated string }; - TypeIndex Type; - MethodKind Kind; - MethodOptions Options; - MemberAccess Access; - int32_t VFTableOffset; - StringRef Name; }; // LF_METHODLIST @@ -989,6 +988,7 @@ deserialize(TypeRecordKind Kind, ArrayRef &Data); ArrayRef getMethods() const { return Methods; } + std::vector Methods; private: struct Layout { @@ -1000,7 +1000,6 @@ // VFTableOffset: int32_t offset in vftable }; - std::vector Methods; }; /// For method overload sets. LF_METHOD @@ -1022,6 +1021,9 @@ uint16_t getNumOverloads() const { return NumOverloads; } TypeIndex getMethodList() const { return MethodList; } StringRef getName() const { return Name; } + uint16_t NumOverloads; + TypeIndex MethodList; + StringRef Name; private: struct Layout { @@ -1030,9 +1032,6 @@ // Name: Null-terminated string }; - uint16_t NumOverloads; - TypeIndex MethodList; - StringRef Name; }; // LF_MEMBER @@ -1055,6 +1054,10 @@ TypeIndex getType() const { return Type; } uint64_t getFieldOffset() const { return FieldOffset; } StringRef getName() const { return Name; } + MemberAccess Access; + TypeIndex Type; + uint64_t FieldOffset; + StringRef Name; private: struct Layout { @@ -1064,10 +1067,6 @@ // Name: Null-terminated string }; - MemberAccess Access; - TypeIndex Type; - uint64_t FieldOffset; - StringRef Name; }; // LF_STMEMBER @@ -1088,6 +1087,9 @@ MemberAccess getAccess() const { return Access; } TypeIndex getType() const { return Type; } StringRef getName() const { return Name; } + MemberAccess Access; + TypeIndex Type; + StringRef Name; private: struct Layout { @@ -1096,9 +1098,6 @@ // Name: Null-terminated string }; - MemberAccess Access; - TypeIndex Type; - StringRef Name; }; // LF_ENUMERATE @@ -1119,6 +1118,9 @@ MemberAccess getAccess() const { return Access; } APSInt getValue() const { return Value; } StringRef getName() const { return Name; } + MemberAccess Access; + APSInt Value; + StringRef Name; private: struct Layout { @@ -1127,9 +1129,6 @@ // Name: Null-terminated string }; - MemberAccess Access; - APSInt Value; - StringRef Name; }; // LF_VFUNCTAB @@ -1147,13 +1146,13 @@ ArrayRef &Data); TypeIndex getType() const { return Type; } + TypeIndex Type; private: struct Layout { ulittle16_t Pad0; TypeIndex Type; // Type of vfptr }; - TypeIndex Type; }; // LF_BCLASS, LF_BINTERFACE @@ -1174,6 +1173,9 @@ MemberAccess getAccess() const { return Access; } TypeIndex getBaseType() const { return Type; } uint64_t getBaseOffset() const { return Offset; } + MemberAccess Access; + TypeIndex Type; + uint64_t Offset; private: struct Layout { @@ -1181,9 +1183,6 @@ TypeIndex BaseType; // Base class type // BaseOffset: LF_NUMERIC encoded byte offset of base from derived. }; - MemberAccess Access; - TypeIndex Type; - uint64_t Offset; }; // LF_VBCLASS, LF_IVBCLASS @@ -1208,6 +1207,11 @@ TypeIndex getVBPtrType() const { return VBPtrType; } uint64_t getVBPtrOffset() const { return VBPtrOffset; } uint64_t getVTableIndex() const { return VTableIndex; } + MemberAccess Access; + TypeIndex BaseType; + TypeIndex VBPtrType; + uint64_t VBPtrOffset; + uint64_t VTableIndex; private: struct Layout { @@ -1217,11 +1221,6 @@ // VBPtrOffset: Offset of vbptr from vfptr encoded as LF_NUMERIC. // VBTableIndex: Index of vbase within vbtable encoded as LF_NUMERIC. }; - MemberAccess Access; - TypeIndex BaseType; - TypeIndex VBPtrType; - uint64_t VBPtrOffset; - uint64_t VTableIndex; }; /// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records @@ -1239,17 +1238,15 @@ static Expected deserialize(TypeRecordKind Kind, ArrayRef &Data); + TypeIndex ContinuationIndex; private: struct Layout { ulittle16_t Pad0; TypeIndex ContinuationIndex; }; - TypeIndex ContinuationIndex; }; -typedef CVRecord CVType; -typedef msf::VarStreamArray CVTypeArray; } } Index: include/llvm/DebugInfo/MSF/StreamReader.h =================================================================== --- include/llvm/DebugInfo/MSF/StreamReader.h +++ include/llvm/DebugInfo/MSF/StreamReader.h @@ -95,6 +95,7 @@ return Error::success(); } + bool empty() const { return bytesRemaining() == 0; } void setOffset(uint32_t Off) { Offset = Off; } uint32_t getOffset() const { return Offset; } uint32_t getLength() const { return Stream.getLength(); } Index: lib/DebugInfo/CodeView/CVTypeVisitor.cpp =================================================================== --- lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -15,6 +15,52 @@ using namespace llvm; using namespace llvm::codeview; +template +static Error takeObject(ArrayRef &Data, const T *&Res) { + if (Data.size() < sizeof(*Res)) + return llvm::make_error(cv_error_code::insufficient_buffer); + Res = reinterpret_cast(Data.data()); + Data = Data.drop_front(sizeof(*Res)); + return Error::success(); +} + +template +static Expected deserializeMemberRecord(ArrayRef &Data, + TypeLeafKind Kind) { + ArrayRef OldData = Data; + TypeRecordKind RK = static_cast(Kind); + auto ExpectedRecord = T::deserialize(RK, Data); + if (!ExpectedRecord) + return ExpectedRecord.takeError(); + assert(Data.size() < OldData.size()); + if (auto EC = skipPadding(Data)) + return std::move(EC); + + CVType CVR; + CVR.Type = Kind; + CVR.Length = OldData.size() - Data.size(); + CVR.Data = OldData.slice(0, CVR.Length); + CVR.RawData = CVR.Data; + return CVR; +} + +static Error skipPadding(ArrayRef &Data) { + if (Data.empty()) + return Error::success(); + uint8_t Leaf = Data.front(); + if (Leaf < LF_PAD0) + return Error::success(); + // Leaf is greater than 0xf0. We should advance by the number of bytes in + // the low 4 bits. + unsigned BytesToAdvance = Leaf & 0x0F; + if (Data.size() < BytesToAdvance) { + return llvm::make_error(cv_error_code::corrupt_record, + "Invalid padding bytes!"); + } + Data = Data.drop_front(BytesToAdvance); + return Error::success(); +} + CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks) : Callbacks(Callbacks) {} @@ -45,7 +91,10 @@ } #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ TYPE_RECORD(EnumVal, EnumVal, AliasName) -#define MEMBER_RECORD(EnumName, EnumVal, Name) +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + TYPE_RECORD(EnumName, EnumVal, Name) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ + MEMBER_RECORD(EnumName, EnumVal, AliasName) #include "llvm/DebugInfo/CodeView/TypeRecords.def" } @@ -63,3 +112,39 @@ } return Error::success(); } + +Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef Data) { + while (!Data.empty()) { + const support::ulittle16_t *LeafValue; + if (auto EC = takeObject(Data, LeafValue)) + return std::move(EC); + + TypeLeafKind Leaf = static_cast(uint16_t(*LeafValue)); + CVType Record; + switch (Leaf) { + default: + // Field list records do not describe their own length, so we cannot + // continue parsing past a type that we don't know how to deserialize. + return llvm::make_error( + cv_error_code::unknown_member_record); +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + case EnumName: { \ + auto ExpectedRecord = deserializeMemberRecord(Data, Leaf); \ + if (!ExpectedRecord) \ + return ExpectedRecord.takeError(); \ + auto &Record = *ExpectedRecord; \ + if (auto EC = Callbacks.visitTypeBegin(Record)) \ + return EC; \ + if (auto EC = visitKnownRecord(Record, Callbacks)) \ + return EC; \ + if (auto EC = Callbacks.visitTypeEnd(Record)) \ + return EC; \ + break; \ + } +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ + MEMBER_RECORD(EnumVal, EnumVal, AliasName) +#include "llvm/DebugInfo/CodeView/TypeRecords.def" + } + } + return Error::success(); +} Index: lib/DebugInfo/CodeView/EnumTables.cpp =================================================================== --- lib/DebugInfo/CodeView/EnumTables.cpp +++ lib/DebugInfo/CodeView/EnumTables.cpp @@ -24,6 +24,12 @@ #undef CV_SYMBOL }; +static const EnumEntry TypeLeafNames[] = { +#define CV_TYPE(name, val) {#name, name}, +#include "llvm/DebugInfo/CodeView/TypeRecords.def" +#undef CV_TYPE +}; + static const EnumEntry RegisterNames[] = { CV_ENUM_CLASS_ENT(RegisterId, Unknown), CV_ENUM_CLASS_ENT(RegisterId, VFrame), @@ -324,6 +330,10 @@ return makeArrayRef(SymbolTypeNames); } +ArrayRef> getTypeLeafNames() { + return makeArrayRef(TypeLeafNames); +} + ArrayRef> getRegisterNames() { return makeArrayRef(RegisterNames); } Index: lib/DebugInfo/CodeView/TypeDeserializer.cpp =================================================================== --- lib/DebugInfo/CodeView/TypeDeserializer.cpp +++ lib/DebugInfo/CodeView/TypeDeserializer.cpp @@ -11,71 +11,3 @@ using namespace llvm; using namespace llvm::codeview; - -template -static Error takeObject(ArrayRef &Data, const T *&Res) { - if (Data.size() < sizeof(*Res)) - return llvm::make_error(cv_error_code::insufficient_buffer); - Res = reinterpret_cast(Data.data()); - Data = Data.drop_front(sizeof(*Res)); - return Error::success(); -} - -Error TypeDeserializer::visitKnownRecord(const CVRecord &CVR, - FieldListRecord &Record) { - ArrayRef FieldListRecordData = CVR.Data; - auto ExpectedRecord = FieldListRecord::deserialize(TypeRecordKind::FieldList, - FieldListRecordData); - if (!ExpectedRecord) - return ExpectedRecord.takeError(); - - Record = *ExpectedRecord; - ArrayRef MemberData = Record.getFieldListData(); - - while (!MemberData.empty()) { - const ulittle16_t *LeafPtr; - if (auto EC = takeObject(MemberData, LeafPtr)) - return EC; - TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr)); - switch (Leaf) { - default: - // Field list records do not describe their own length, so we cannot - // continue parsing past a type that we don't know how to deserialize. - if (auto EC = Recipient.visitUnknownMember(CVR)) - return EC; - return llvm::make_error( - cv_error_code::unknown_member_record); -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - case EnumName: { \ - TypeRecordKind RK = static_cast(Leaf); \ - Name##Record Member(RK); \ - if (auto EC = visitKnownMember(MemberData, Leaf, Member)) \ - return EC; \ - break; \ - } -#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ - MEMBER_RECORD(EnumVal, EnumVal, AliasName) -#include "llvm/DebugInfo/CodeView/TypeRecords.def" - } - if (auto EC = skipPadding(MemberData)) - return EC; - } - return Error::success(); -} - -Error TypeDeserializer::skipPadding(ArrayRef &Data) { - if (Data.empty()) - return Error::success(); - uint8_t Leaf = Data.front(); - if (Leaf < LF_PAD0) - return Error::success(); - // Leaf is greater than 0xf0. We should advance by the number of bytes in - // the low 4 bits. - unsigned BytesToAdvance = Leaf & 0x0F; - if (Data.size() < BytesToAdvance) { - return llvm::make_error(cv_error_code::corrupt_record, - "Invalid padding bytes!"); - } - Data = Data.drop_front(BytesToAdvance); - return Error::success(); -} Index: lib/DebugInfo/CodeView/TypeDumper.cpp =================================================================== --- lib/DebugInfo/CodeView/TypeDumper.cpp +++ lib/DebugInfo/CodeView/TypeDumper.cpp @@ -206,21 +206,38 @@ // Reset Name to the empty string. If the visitor sets it, we know it. Name = ""; - W->startLine() << getLeafTypeName(Record.Type) << " (" - << HexNumber(getNextTypeIndex()) << ") {\n"; + W->startLine() << getLeafTypeName(Record.Type); + if (!IsInFieldList) { + // If this is a field list member, don't record its type index because it + // doesn't have one. Only the outer field list has a type index. + W->getOStream() << " (" << HexNumber(getNextTypeIndex()) << ")"; + } + W->getOStream() << " {\n"; W->indent(); W->printEnum("TypeLeafKind", unsigned(Record.Type), makeArrayRef(LeafTypeNames)); + if (Record.Type == LF_FIELDLIST) { + // Record that we're in a field list so that members do not get assigned + // type indices. + assert(!IsInFieldList); + IsInFieldList = true; + } return Error::success(); } Error CVTypeDumper::visitTypeEnd(const CVRecord &Record) { - if (Record.Type == LF_FIELDLIST) - Name = ""; + if (Record.Type == LF_FIELDLIST) { + assert(IsInFieldList); + IsInFieldList = false; + } - // Always record some name for every type, even if Name is empty. CVUDTNames - // is indexed by type index, and must have one entry for every type. - recordType(Name); + if (!IsInFieldList) { + // Record every type that is not a field list member, even if Name is empty. + // CVUDTNames is indexed by type index, and must have one entry for every + // type. Field list members are not recorded, and are only referenced by + // their containing field list record. + recordType(Name); + } if (PrintRecordBytes) W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data)); @@ -232,6 +249,12 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, FieldListRecord &FieldList) { + TypeDeserializer Deserializer(*this); + CVTypeVisitor Visitor(Deserializer); + if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data)) + return EC; + + Name = ""; return Error::success(); } @@ -550,7 +573,6 @@ } Error CVTypeDumper::visitUnknownType(const CVRecord &Record) { - DictScope S(*W, "UnknownType"); W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames)); W->printNumber("Length", uint32_t(Record.Data.size())); return Error::success(); @@ -558,7 +580,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, NestedTypeRecord &Nested) { - DictScope S(*W, "NestedType"); printTypeIndex("Type", Nested.getNestedType()); W->printString("Name", Nested.getName()); Name = Nested.getName(); @@ -567,7 +588,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, OneMethodRecord &Method) { - DictScope S(*W, "OneMethod"); MethodKind K = Method.getKind(); printMemberAttributes(Method.getAccess(), K, Method.getOptions()); printTypeIndex("Type", Method.getType()); @@ -581,7 +601,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, OverloadedMethodRecord &Method) { - DictScope S(*W, "OverloadedMethod"); W->printHex("MethodCount", Method.getNumOverloads()); printTypeIndex("MethodListIndex", Method.getMethodList()); W->printString("Name", Method.getName()); @@ -591,7 +610,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, DataMemberRecord &Field) { - DictScope S(*W, "DataMember"); printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("Type", Field.getType()); @@ -603,7 +621,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, StaticDataMemberRecord &Field) { - DictScope S(*W, "StaticDataMember"); printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("Type", Field.getType()); @@ -614,14 +631,12 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, VFPtrRecord &VFTable) { - DictScope S(*W, "VFPtr"); printTypeIndex("Type", VFTable.getType()); return Error::success(); } Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, EnumeratorRecord &Enum) { - DictScope S(*W, "Enumerator"); printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla, MethodOptions::None); W->printNumber("EnumValue", Enum.getValue()); @@ -632,7 +647,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, BaseClassRecord &Base) { - DictScope S(*W, "BaseClass"); printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("BaseType", Base.getBaseType()); @@ -642,7 +656,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, VirtualBaseClassRecord &Base) { - DictScope S(*W, "VirtualBaseClass"); printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("BaseType", Base.getBaseType()); @@ -654,7 +667,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord &CVR, ListContinuationRecord &Cont) { - DictScope S(*W, "ListContinuation"); printTypeIndex("ContinuationIndex", Cont.getContinuationIndex()); return Error::success(); } Index: lib/DebugInfo/CodeView/TypeRecord.cpp =================================================================== --- lib/DebugInfo/CodeView/TypeRecord.cpp +++ lib/DebugInfo/CodeView/TypeRecord.cpp @@ -8,8 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/MSF/ByteStream.h" using namespace llvm; using namespace llvm::codeview; @@ -116,7 +117,9 @@ Expected FieldListRecord::deserialize(TypeRecordKind Kind, ArrayRef &Data) { - return FieldListRecord(Data); + auto FieldListData = Data; + Data = ArrayRef(); + return FieldListRecord(FieldListData); } Expected ArrayRecord::deserialize(TypeRecordKind Kind, @@ -448,7 +451,7 @@ bool Success = true; Success &= remapIndex(IndexMap, ReferentType); if (isPointerToMember()) - Success &= MemberInfo.remapTypeIndices(IndexMap); + Success &= MemberInfo->remapTypeIndices(IndexMap); return Success; } Index: test/DebugInfo/PDB/pdbdump-headers.test =================================================================== --- test/DebugInfo/PDB/pdbdump-headers.test +++ test/DebugInfo/PDB/pdbdump-headers.test @@ -111,26 +111,31 @@ ; EMPTY-NEXT: FieldList (0x1002) { ; EMPTY-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203) ; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) ; EMPTY-NEXT: AccessSpecifier: Public (0x3) ; EMPTY-NEXT: EnumValue: 1 ; EMPTY-NEXT: Name: apartment ; EMPTY-NEXT: } ; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) ; EMPTY-NEXT: AccessSpecifier: Public (0x3) ; EMPTY-NEXT: EnumValue: 2 ; EMPTY-NEXT: Name: single ; EMPTY-NEXT: } ; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) ; EMPTY-NEXT: AccessSpecifier: Public (0x3) ; EMPTY-NEXT: EnumValue: 3 ; EMPTY-NEXT: Name: free ; EMPTY-NEXT: } ; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) ; EMPTY-NEXT: AccessSpecifier: Public (0x3) ; EMPTY-NEXT: EnumValue: 4 ; EMPTY-NEXT: Name: neutral ; EMPTY-NEXT: } ; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) ; EMPTY-NEXT: AccessSpecifier: Public (0x3) ; EMPTY-NEXT: EnumValue: 5 ; EMPTY-NEXT: Name: both Index: test/DebugInfo/PDB/pdbdump-yaml-types.test =================================================================== --- /dev/null +++ test/DebugInfo/PDB/pdbdump-yaml-types.test @@ -0,0 +1,1087 @@ +; RUN: llvm-pdbdump pdb2yaml -tpi-stream %p/Inputs/empty.pdb \ +; RUN: | FileCheck -check-prefix=YAML %s + +YAML: --- +YAML: MSF: +YAML: SuperBlock: +YAML: BlockSize: 4096 +YAML: FreeBlockMap: 2 +YAML: NumBlocks: 25 +YAML: NumDirectoryBytes: 136 +YAML: Unknown1: 0 +YAML: BlockMapAddr: 24 +YAML: NumDirectoryBlocks: 1 +YAML: DirectoryBlocks: [ 23 ] +YAML: NumStreams: 0 +YAML: FileSize: 102400 +YAML: TpiStream: +YAML: Version: VC80 +YAML: Records: +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ ] +YAML: - Kind: LF_PROCEDURE +YAML: Procedure: +YAML: ReturnType: 116 +YAML: CallConv: NearC +YAML: Options: [ None ] +YAML: ParameterCount: 0 +YAML: ArgumentList: 4096 +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 1 +YAML: Name: apartment +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 2 +YAML: Name: single +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 3 +YAML: Name: free +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 4 +YAML: Name: neutral +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 5 +YAML: Name: both +YAML: - Kind: LF_ENUM +YAML: Enum: +YAML: NumEnumerators: 5 +YAML: Options: [ None, Nested, HasUniqueName ] +YAML: FieldList: 4098 +YAML: Name: '__vc_attributes::threadingAttribute::threading_e' +YAML: UniqueName: '.?AW4threading_e@threadingAttribute@__vc_attributes@@' +YAML: UnderlyingType: 116 +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 0 +YAML: Options: [ None, ForwardReference, HasUniqueName ] +YAML: FieldList: 0 +YAML: Name: '__vc_attributes::threadingAttribute' +YAML: UniqueName: '.?AUthreadingAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 0 +YAML: - Kind: LF_POINTER +YAML: Pointer: +YAML: ReferentType: 4100 +YAML: PtrKind: Near32 +YAML: Mode: Pointer +YAML: Options: [ None, Const ] +YAML: Size: 4 +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ 4099 ] +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4100 +YAML: ThisType: 4101 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 1 +YAML: ArgumentList: 4102 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4100 +YAML: ThisType: 4101 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 0 +YAML: ArgumentList: 4096 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_METHODLIST +YAML: MethodOverloadList: +YAML: Methods: +YAML: - Type: 4103 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Type: 4104 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_NESTTYPE +YAML: NestedType: +YAML: Type: 4099 +YAML: Name: threading_e +YAML: Kind: LF_METHOD +YAML: OverloadedMethod: +YAML: NumOverloads: 2 +YAML: MethodList: 4105 +YAML: Name: threadingAttribute +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4099 +YAML: FieldOffset: 0 +YAML: Name: value +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 4 +YAML: Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] +YAML: FieldList: 4106 +YAML: Name: '__vc_attributes::threadingAttribute' +YAML: UniqueName: '.?AUthreadingAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 4 +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 0 +YAML: Name: native +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 1 +YAML: Name: com +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 2 +YAML: Name: managed +YAML: - Kind: LF_ENUM +YAML: Enum: +YAML: NumEnumerators: 3 +YAML: Options: [ None, Nested, HasUniqueName ] +YAML: FieldList: 4108 +YAML: Name: '__vc_attributes::event_receiverAttribute::type_e' +YAML: UniqueName: '.?AW4type_e@event_receiverAttribute@__vc_attributes@@' +YAML: UnderlyingType: 116 +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 0 +YAML: Options: [ None, ForwardReference, HasUniqueName ] +YAML: FieldList: 0 +YAML: Name: '__vc_attributes::event_receiverAttribute' +YAML: UniqueName: '.?AUevent_receiverAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 0 +YAML: - Kind: LF_POINTER +YAML: Pointer: +YAML: ReferentType: 4110 +YAML: PtrKind: Near32 +YAML: Mode: Pointer +YAML: Options: [ None, Const ] +YAML: Size: 4 +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ 4109, 48 ] +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4110 +YAML: ThisType: 4111 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 2 +YAML: ArgumentList: 4112 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ 4109 ] +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4110 +YAML: ThisType: 4111 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 1 +YAML: ArgumentList: 4114 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4110 +YAML: ThisType: 4111 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 0 +YAML: ArgumentList: 4096 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_METHODLIST +YAML: MethodOverloadList: +YAML: Methods: +YAML: - Type: 4113 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Type: 4115 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Type: 4116 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_NESTTYPE +YAML: NestedType: +YAML: Type: 4109 +YAML: Name: type_e +YAML: Kind: LF_METHOD +YAML: OverloadedMethod: +YAML: NumOverloads: 3 +YAML: MethodList: 4117 +YAML: Name: event_receiverAttribute +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4109 +YAML: FieldOffset: 0 +YAML: Name: type +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 48 +YAML: FieldOffset: 4 +YAML: Name: layout_dependent +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 6 +YAML: Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] +YAML: FieldList: 4118 +YAML: Name: '__vc_attributes::event_receiverAttribute' +YAML: UniqueName: '.?AUevent_receiverAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 8 +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 0 +YAML: Name: never +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 1 +YAML: Name: allowed +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 2 +YAML: Name: always +YAML: - Kind: LF_ENUM +YAML: Enum: +YAML: NumEnumerators: 3 +YAML: Options: [ None, Nested, HasUniqueName ] +YAML: FieldList: 4120 +YAML: Name: '__vc_attributes::aggregatableAttribute::type_e' +YAML: UniqueName: '.?AW4type_e@aggregatableAttribute@__vc_attributes@@' +YAML: UnderlyingType: 116 +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 0 +YAML: Options: [ None, ForwardReference, HasUniqueName ] +YAML: FieldList: 0 +YAML: Name: '__vc_attributes::aggregatableAttribute' +YAML: UniqueName: '.?AUaggregatableAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 0 +YAML: - Kind: LF_POINTER +YAML: Pointer: +YAML: ReferentType: 4122 +YAML: PtrKind: Near32 +YAML: Mode: Pointer +YAML: Options: [ None, Const ] +YAML: Size: 4 +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ 4121 ] +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4122 +YAML: ThisType: 4123 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 1 +YAML: ArgumentList: 4124 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4122 +YAML: ThisType: 4123 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 0 +YAML: ArgumentList: 4096 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_METHODLIST +YAML: MethodOverloadList: +YAML: Methods: +YAML: - Type: 4125 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Type: 4126 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_NESTTYPE +YAML: NestedType: +YAML: Type: 4121 +YAML: Name: type_e +YAML: Kind: LF_METHOD +YAML: OverloadedMethod: +YAML: NumOverloads: 2 +YAML: MethodList: 4127 +YAML: Name: aggregatableAttribute +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4121 +YAML: FieldOffset: 0 +YAML: Name: type +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 4 +YAML: Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] +YAML: FieldList: 4128 +YAML: Name: '__vc_attributes::aggregatableAttribute' +YAML: UniqueName: '.?AUaggregatableAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 4 +YAML: - Kind: LF_ENUM +YAML: Enum: +YAML: NumEnumerators: 3 +YAML: Options: [ None, Nested, HasUniqueName ] +YAML: FieldList: 4108 +YAML: Name: '__vc_attributes::event_sourceAttribute::type_e' +YAML: UniqueName: '.?AW4type_e@event_sourceAttribute@__vc_attributes@@' +YAML: UnderlyingType: 116 +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 0 +YAML: Name: speed +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 1 +YAML: Name: size +YAML: - Kind: LF_ENUM +YAML: Enum: +YAML: NumEnumerators: 2 +YAML: Options: [ None, Nested, HasUniqueName ] +YAML: FieldList: 4131 +YAML: Name: '__vc_attributes::event_sourceAttribute::optimize_e' +YAML: UniqueName: '.?AW4optimize_e@event_sourceAttribute@__vc_attributes@@' +YAML: UnderlyingType: 116 +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 0 +YAML: Options: [ None, ForwardReference, HasUniqueName ] +YAML: FieldList: 0 +YAML: Name: '__vc_attributes::event_sourceAttribute' +YAML: UniqueName: '.?AUevent_sourceAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 0 +YAML: - Kind: LF_POINTER +YAML: Pointer: +YAML: ReferentType: 4133 +YAML: PtrKind: Near32 +YAML: Mode: Pointer +YAML: Options: [ None, Const ] +YAML: Size: 4 +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ 4130 ] +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4133 +YAML: ThisType: 4134 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 1 +YAML: ArgumentList: 4135 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4133 +YAML: ThisType: 4134 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 0 +YAML: ArgumentList: 4096 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_METHODLIST +YAML: MethodOverloadList: +YAML: Methods: +YAML: - Type: 4136 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Type: 4137 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_NESTTYPE +YAML: NestedType: +YAML: Type: 4130 +YAML: Name: type_e +YAML: Kind: LF_NESTTYPE +YAML: NestedType: +YAML: Type: 4132 +YAML: Name: optimize_e +YAML: Kind: LF_METHOD +YAML: OverloadedMethod: +YAML: NumOverloads: 2 +YAML: MethodList: 4138 +YAML: Name: event_sourceAttribute +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4130 +YAML: FieldOffset: 0 +YAML: Name: type +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4132 +YAML: FieldOffset: 4 +YAML: Name: optimize +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 48 +YAML: FieldOffset: 8 +YAML: Name: decorate +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 7 +YAML: Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] +YAML: FieldList: 4139 +YAML: Name: '__vc_attributes::event_sourceAttribute' +YAML: UniqueName: '.?AUevent_sourceAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 12 +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 1 +YAML: Name: dll +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 2 +YAML: Name: exe +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 3 +YAML: Name: service +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 4 +YAML: Name: unspecified +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 2 +YAML: Name: EXE +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 3 +YAML: Name: SERVICE +YAML: - Kind: LF_ENUM +YAML: Enum: +YAML: NumEnumerators: 6 +YAML: Options: [ None, Nested, HasUniqueName ] +YAML: FieldList: 4141 +YAML: Name: '__vc_attributes::moduleAttribute::type_e' +YAML: UniqueName: '.?AW4type_e@moduleAttribute@__vc_attributes@@' +YAML: UnderlyingType: 116 +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 0 +YAML: Options: [ None, ForwardReference, HasUniqueName ] +YAML: FieldList: 0 +YAML: Name: '__vc_attributes::moduleAttribute' +YAML: UniqueName: '.?AUmoduleAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 0 +YAML: - Kind: LF_POINTER +YAML: Pointer: +YAML: ReferentType: 4143 +YAML: PtrKind: Near32 +YAML: Mode: Pointer +YAML: Options: [ None, Const ] +YAML: Size: 4 +YAML: - Kind: LF_MODIFIER +YAML: Modifier: +YAML: ModifiedType: 112 +YAML: Modifiers: [ None, Const ] +YAML: - Kind: LF_POINTER +YAML: Pointer: +YAML: ReferentType: 4145 +YAML: PtrKind: Near32 +YAML: Mode: Pointer +YAML: Options: [ None ] +YAML: Size: 4 +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ 4142, 4146, 4146, 4146, 116, 48, 4146, 116, +YAML: 4146, 4146, 116, 48, 48, 4146, 4146 ] +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4143 +YAML: ThisType: 4144 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 15 +YAML: ArgumentList: 4147 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ 4142 ] +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4143 +YAML: ThisType: 4144 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 1 +YAML: ArgumentList: 4149 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4143 +YAML: ThisType: 4144 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 0 +YAML: ArgumentList: 4096 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_METHODLIST +YAML: MethodOverloadList: +YAML: Methods: +YAML: - Type: 4148 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Type: 4150 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Type: 4151 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: '' +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_NESTTYPE +YAML: NestedType: +YAML: Type: 4142 +YAML: Name: type_e +YAML: Kind: LF_METHOD +YAML: OverloadedMethod: +YAML: NumOverloads: 3 +YAML: MethodList: 4152 +YAML: Name: moduleAttribute +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4142 +YAML: FieldOffset: 0 +YAML: Name: type +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4146 +YAML: FieldOffset: 4 +YAML: Name: name +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4146 +YAML: FieldOffset: 8 +YAML: Name: version +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4146 +YAML: FieldOffset: 12 +YAML: Name: uuid +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 116 +YAML: FieldOffset: 16 +YAML: Name: lcid +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 48 +YAML: FieldOffset: 20 +YAML: Name: control +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4146 +YAML: FieldOffset: 24 +YAML: Name: helpstring +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 116 +YAML: FieldOffset: 28 +YAML: Name: helpstringcontext +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4146 +YAML: FieldOffset: 32 +YAML: Name: helpstringdll +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4146 +YAML: FieldOffset: 36 +YAML: Name: helpfile +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 116 +YAML: FieldOffset: 40 +YAML: Name: helpcontext +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 48 +YAML: FieldOffset: 44 +YAML: Name: hidden +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 48 +YAML: FieldOffset: 45 +YAML: Name: restricted +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4146 +YAML: FieldOffset: 48 +YAML: Name: custom +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4146 +YAML: FieldOffset: 52 +YAML: Name: resource_name +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 19 +YAML: Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] +YAML: FieldList: 4153 +YAML: Name: '__vc_attributes::moduleAttribute' +YAML: UniqueName: '.?AUmoduleAttribute@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 56 +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 0 +YAML: Name: eAnyUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 1 +YAML: Name: eCoClassUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 2 +YAML: Name: eCOMInterfaceUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 6 +YAML: Name: eInterfaceUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 8 +YAML: Name: eMemberUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 16 +YAML: Name: eMethodUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 32 +YAML: Name: eInterfaceMethodUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 64 +YAML: Name: eInterfaceMemberUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 128 +YAML: Name: eCoClassMemberUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 256 +YAML: Name: eCoClassMethodUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 768 +YAML: Name: eGlobalMethodUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 1024 +YAML: Name: eGlobalDataUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 2048 +YAML: Name: eClassUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 4096 +YAML: Name: eInterfaceParameterUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 12288 +YAML: Name: eMethodParameterUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 16384 +YAML: Name: eIDLModuleUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: -32768 +YAML: Name: eAnonymousUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 65536 +YAML: Name: eTypedefUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 131072 +YAML: Name: eUnionUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 262144 +YAML: Name: eEnumUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 524288 +YAML: Name: eDefineTagUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 1048576 +YAML: Name: eStructUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 2097152 +YAML: Name: eLocalUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 4194304 +YAML: Name: ePropertyUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 8388608 +YAML: Name: eEventUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 16777216 +YAML: Name: eTemplateUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 16777216 +YAML: Name: eModuleUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 33554432 +YAML: Name: eIllegalUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 67108864 +YAML: Name: eAsynchronousUsage +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 4161535 +YAML: Name: eAnyIDLUsage +YAML: - Kind: LF_ENUM +YAML: Enum: +YAML: NumEnumerators: 30 +YAML: Options: [ None, Nested, HasUniqueName ] +YAML: FieldList: 4155 +YAML: Name: '__vc_attributes::helper_attributes::usageAttribute::usage_e' +YAML: UniqueName: '.?AW4usage_e@usageAttribute@helper_attributes@__vc_attributes@@' +YAML: UnderlyingType: 116 +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 0 +YAML: Options: [ None, ForwardReference, HasUniqueName ] +YAML: FieldList: 0 +YAML: Name: '__vc_attributes::helper_attributes::usageAttribute' +YAML: UniqueName: '.?AUusageAttribute@helper_attributes@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 0 +YAML: - Kind: LF_POINTER +YAML: Pointer: +YAML: ReferentType: 4157 +YAML: PtrKind: Near32 +YAML: Mode: Pointer +YAML: Options: [ None, Const ] +YAML: Size: 4 +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ 117 ] +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4157 +YAML: ThisType: 4158 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 1 +YAML: ArgumentList: 4159 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_NESTTYPE +YAML: NestedType: +YAML: Type: 4156 +YAML: Name: usage_e +YAML: Kind: LF_ONEMETHOD +YAML: OneMethod: +YAML: Type: 4160 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: usageAttribute +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 117 +YAML: FieldOffset: 0 +YAML: Name: value +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 3 +YAML: Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] +YAML: FieldList: 4161 +YAML: Name: '__vc_attributes::helper_attributes::usageAttribute' +YAML: UniqueName: '.?AUusageAttribute@helper_attributes@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 4 +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 0 +YAML: Name: eBoolean +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 1 +YAML: Name: eInteger +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 2 +YAML: Name: eFloat +YAML: Kind: LF_ENUMERATE +YAML: Enumerator: +YAML: Access: Public +YAML: Value: 3 +YAML: Name: eDouble +YAML: - Kind: LF_ENUM +YAML: Enum: +YAML: NumEnumerators: 4 +YAML: Options: [ None, Nested, HasUniqueName ] +YAML: FieldList: 4163 +YAML: Name: '__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e' +YAML: UniqueName: '.?AW4type_e@v1_alttypeAttribute@helper_attributes@__vc_attributes@@' +YAML: UnderlyingType: 116 +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 0 +YAML: Options: [ None, ForwardReference, HasUniqueName ] +YAML: FieldList: 0 +YAML: Name: '__vc_attributes::helper_attributes::v1_alttypeAttribute' +YAML: UniqueName: '.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 0 +YAML: - Kind: LF_POINTER +YAML: Pointer: +YAML: ReferentType: 4165 +YAML: PtrKind: Near32 +YAML: Mode: Pointer +YAML: Options: [ None, Const ] +YAML: Size: 4 +YAML: - Kind: LF_ARGLIST +YAML: ArgList: +YAML: ArgIndices: [ 4164 ] +YAML: - Kind: LF_MFUNCTION +YAML: MemberFunction: +YAML: ReturnType: 3 +YAML: ClassType: 4165 +YAML: ThisType: 4166 +YAML: CallConv: ThisCall +YAML: Options: [ None, Constructor ] +YAML: ParameterCount: 1 +YAML: ArgumentList: 4167 +YAML: ThisPointerAdjustment: 0 +YAML: - Kind: LF_FIELDLIST +YAML: FieldList: +YAML: Kind: LF_NESTTYPE +YAML: NestedType: +YAML: Type: 4164 +YAML: Name: type_e +YAML: Kind: LF_ONEMETHOD +YAML: OneMethod: +YAML: Type: 4168 +YAML: Kind: Vanilla +YAML: Options: [ None ] +YAML: Access: Public +YAML: VFTableOffset: -1 +YAML: Name: v1_alttypeAttribute +YAML: Kind: LF_MEMBER +YAML: DataMember: +YAML: Access: Public +YAML: Type: 4164 +YAML: FieldOffset: 0 +YAML: Name: type +YAML: - Kind: LF_STRUCTURE +YAML: Class: +YAML: MemberCount: 3 +YAML: Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] +YAML: FieldList: 4169 +YAML: Name: '__vc_attributes::helper_attributes::v1_alttypeAttribute' +YAML: UniqueName: '.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@' +YAML: Hfa: None +YAML: WinRTKind: None +YAML: DerivationList: 0 +YAML: VTableShape: 0 +YAML: Size: 4 +YAML: ... Index: tools/llvm-pdbdump/CMakeLists.txt =================================================================== --- tools/llvm-pdbdump/CMakeLists.txt +++ tools/llvm-pdbdump/CMakeLists.txt @@ -10,6 +10,7 @@ llvm-pdbdump.cpp BuiltinDumper.cpp ClassDefinitionDumper.cpp + CodeViewYaml.cpp CompilandDumper.cpp EnumDumper.cpp ExternalSymbolDumper.cpp Index: tools/llvm-pdbdump/CodeViewYaml.h =================================================================== --- /dev/null +++ tools/llvm-pdbdump/CodeViewYaml.h @@ -0,0 +1,71 @@ +//===- PdbYAML.h ---------------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_CODEVIEWYAML_H +#define LLVM_TOOLS_LLVMPDBDUMP_CODEVIEWYAML_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { +namespace codeview { +namespace yaml { +class YamlTypeDumperCallbacks : public TypeVisitorCallbacks { +public: + YamlTypeDumperCallbacks(llvm::yaml::IO &IO) : YamlIO(IO) {} + + virtual Error visitTypeBegin(const CVRecord &Record) override; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(const CVRecord &CVR, \ + Name##Record &Record) override { \ + YamlIO.mapRequired(#Name, Record); \ + return Error::success(); \ + } +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + TYPE_RECORD(EnumName, EnumVal, Name) +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/TypeRecords.def" + +private: + llvm::yaml::IO &YamlIO; +}; +} +} +} + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &IO, codeview::MemberPointerInfo &Obj); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, codeview::CVType &Obj); +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, codeview::TypeLeafKind &Value); +}; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + template <> struct MappingTraits { \ + static void mapping(IO &IO, codeview::Name##Record &Obj); \ + }; +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + TYPE_RECORD(EnumName, EnumVal, Name) +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/TypeRecords.def" +} +} + +#endif Index: tools/llvm-pdbdump/CodeViewYaml.cpp =================================================================== --- /dev/null +++ tools/llvm-pdbdump/CodeViewYaml.cpp @@ -0,0 +1,506 @@ +//===- PdbYAML.cpp -------------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CodeViewYaml.h" + +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/EnumTables.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::codeview::yaml; + +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint64_t) +LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord) +LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind) +LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef) +LLVM_YAML_IS_SEQUENCE_VECTOR(CVType) + +namespace llvm { +namespace yaml { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, PointerToMemberRepresentation &Value) { + IO.enumCase(Value, "Unknown", PointerToMemberRepresentation::Unknown); + IO.enumCase(Value, "SingleInheritanceData", + PointerToMemberRepresentation::SingleInheritanceData); + IO.enumCase(Value, "MultipleInheritanceData", + PointerToMemberRepresentation::MultipleInheritanceData); + IO.enumCase(Value, "VirtualInheritanceData", + PointerToMemberRepresentation::VirtualInheritanceData); + IO.enumCase(Value, "GeneralData", + PointerToMemberRepresentation::GeneralData); + IO.enumCase(Value, "SingleInheritanceFunction", + PointerToMemberRepresentation::SingleInheritanceFunction); + IO.enumCase(Value, "MultipleInheritanceFunction", + PointerToMemberRepresentation::MultipleInheritanceFunction); + IO.enumCase(Value, "VirtualInheritanceFunction", + PointerToMemberRepresentation::VirtualInheritanceFunction); + IO.enumCase(Value, "GeneralFunction", + PointerToMemberRepresentation::GeneralFunction); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, VFTableSlotKind &Kind) { + IO.enumCase(Kind, "Near16", VFTableSlotKind::Near16); + IO.enumCase(Kind, "Far16", VFTableSlotKind::Far16); + IO.enumCase(Kind, "This", VFTableSlotKind::This); + IO.enumCase(Kind, "Outer", VFTableSlotKind::Outer); + IO.enumCase(Kind, "Meta", VFTableSlotKind::Meta); + IO.enumCase(Kind, "Near", VFTableSlotKind::Near); + IO.enumCase(Kind, "Far", VFTableSlotKind::Far); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, CallingConvention &Value) { + IO.enumCase(Value, "NearC", CallingConvention::NearC); + IO.enumCase(Value, "FarC", CallingConvention::FarC); + IO.enumCase(Value, "NearPascal", CallingConvention::NearPascal); + IO.enumCase(Value, "FarPascal", CallingConvention::FarPascal); + IO.enumCase(Value, "NearFast", CallingConvention::NearFast); + IO.enumCase(Value, "FarFast", CallingConvention::FarFast); + IO.enumCase(Value, "NearStdCall", CallingConvention::NearStdCall); + IO.enumCase(Value, "FarStdCall", CallingConvention::FarStdCall); + IO.enumCase(Value, "NearSysCall", CallingConvention::NearSysCall); + IO.enumCase(Value, "FarSysCall", CallingConvention::FarSysCall); + IO.enumCase(Value, "ThisCall", CallingConvention::ThisCall); + IO.enumCase(Value, "MipsCall", CallingConvention::MipsCall); + IO.enumCase(Value, "Generic", CallingConvention::Generic); + IO.enumCase(Value, "AlphaCall", CallingConvention::AlphaCall); + IO.enumCase(Value, "PpcCall", CallingConvention::PpcCall); + IO.enumCase(Value, "SHCall", CallingConvention::SHCall); + IO.enumCase(Value, "ArmCall", CallingConvention::ArmCall); + IO.enumCase(Value, "AM33Call", CallingConvention::AM33Call); + IO.enumCase(Value, "TriCall", CallingConvention::TriCall); + IO.enumCase(Value, "SH5Call", CallingConvention::SH5Call); + IO.enumCase(Value, "M32RCall", CallingConvention::M32RCall); + IO.enumCase(Value, "ClrCall", CallingConvention::ClrCall); + IO.enumCase(Value, "Inline", CallingConvention::Inline); + IO.enumCase(Value, "NearVector", CallingConvention::NearVector); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, PointerKind &Kind) { + IO.enumCase(Kind, "Near16", PointerKind::Near16); + IO.enumCase(Kind, "Far16", PointerKind::Far16); + IO.enumCase(Kind, "Huge16", PointerKind::Huge16); + IO.enumCase(Kind, "BasedOnSegment", PointerKind::BasedOnSegment); + IO.enumCase(Kind, "BasedOnValue", PointerKind::BasedOnValue); + IO.enumCase(Kind, "BasedOnSegmentValue", PointerKind::BasedOnSegmentValue); + IO.enumCase(Kind, "BasedOnAddress", PointerKind::BasedOnAddress); + IO.enumCase(Kind, "BasedOnSegmentAddress", + PointerKind::BasedOnSegmentAddress); + IO.enumCase(Kind, "BasedOnType", PointerKind::BasedOnType); + IO.enumCase(Kind, "BasedOnSelf", PointerKind::BasedOnSelf); + IO.enumCase(Kind, "Near32", PointerKind::Near32); + IO.enumCase(Kind, "Far32", PointerKind::Far32); + IO.enumCase(Kind, "Near64", PointerKind::Near64); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, PointerMode &Mode) { + IO.enumCase(Mode, "Pointer", PointerMode::Pointer); + IO.enumCase(Mode, "LValueReference", PointerMode::LValueReference); + IO.enumCase(Mode, "PointerToDataMember", PointerMode::PointerToDataMember); + IO.enumCase(Mode, "PointerToMemberFunction", + PointerMode::PointerToMemberFunction); + IO.enumCase(Mode, "RValueReference", PointerMode::RValueReference); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, HfaKind &Value) { + IO.enumCase(Value, "None", HfaKind::None); + IO.enumCase(Value, "Float", HfaKind::Float); + IO.enumCase(Value, "Double", HfaKind::Double); + IO.enumCase(Value, "Other", HfaKind::Other); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, MemberAccess &Access) { + IO.enumCase(Access, "None", MemberAccess::None); + IO.enumCase(Access, "Private", MemberAccess::Private); + IO.enumCase(Access, "Protected", MemberAccess::Protected); + IO.enumCase(Access, "Public", MemberAccess::Public); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, MethodKind &Kind) { + IO.enumCase(Kind, "Vanilla", MethodKind::Vanilla); + IO.enumCase(Kind, "Virtual", MethodKind::Virtual); + IO.enumCase(Kind, "Static", MethodKind::Static); + IO.enumCase(Kind, "Friend", MethodKind::Friend); + IO.enumCase(Kind, "IntroducingVirtual", MethodKind::IntroducingVirtual); + IO.enumCase(Kind, "PureVirtual", MethodKind::PureVirtual); + IO.enumCase(Kind, "PureIntroducingVirtual", + MethodKind::PureIntroducingVirtual); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, WindowsRTClassKind &Value) { + IO.enumCase(Value, "None", WindowsRTClassKind::None); + IO.enumCase(Value, "Ref", WindowsRTClassKind::RefClass); + IO.enumCase(Value, "Value", WindowsRTClassKind::ValueClass); + IO.enumCase(Value, "Interface", WindowsRTClassKind::Interface); + } +}; + +template <> struct ScalarBitSetTraits { + static void bitset(IO &IO, PointerOptions &Options) { + IO.bitSetCase(Options, "None", PointerOptions::None); + IO.bitSetCase(Options, "Flat32", PointerOptions::Flat32); + IO.bitSetCase(Options, "Volatile", PointerOptions::Volatile); + IO.bitSetCase(Options, "Const", PointerOptions::Const); + IO.bitSetCase(Options, "Unaligned", PointerOptions::Unaligned); + IO.bitSetCase(Options, "Restrict", PointerOptions::Restrict); + IO.bitSetCase(Options, "WinRTSmartPointer", + PointerOptions::WinRTSmartPointer); + } +}; + +template <> struct ScalarBitSetTraits { + static void bitset(IO &IO, ModifierOptions &Options) { + IO.bitSetCase(Options, "None", ModifierOptions::None); + IO.bitSetCase(Options, "Const", ModifierOptions::Const); + IO.bitSetCase(Options, "Volatile", ModifierOptions::Volatile); + IO.bitSetCase(Options, "Unaligned", ModifierOptions::Unaligned); + } +}; + +template <> struct ScalarBitSetTraits { + static void bitset(IO &IO, FunctionOptions &Options) { + IO.bitSetCase(Options, "None", FunctionOptions::None); + IO.bitSetCase(Options, "CxxReturnUdt", FunctionOptions::CxxReturnUdt); + IO.bitSetCase(Options, "Constructor", FunctionOptions::Constructor); + IO.bitSetCase(Options, "ConstructorWithVirtualBases", + FunctionOptions::ConstructorWithVirtualBases); + } +}; + +template <> struct ScalarBitSetTraits { + static void bitset(IO &IO, ClassOptions &Options) { + IO.bitSetCase(Options, "None", ClassOptions::None); + IO.bitSetCase(Options, "HasConstructorOrDestructor", + ClassOptions::HasConstructorOrDestructor); + IO.bitSetCase(Options, "HasOverloadedOperator", + ClassOptions::HasOverloadedOperator); + IO.bitSetCase(Options, "Nested", ClassOptions::Nested); + IO.bitSetCase(Options, "ContainsNestedClass", + ClassOptions::ContainsNestedClass); + IO.bitSetCase(Options, "HasOverloadedAssignmentOperator", + ClassOptions::HasOverloadedAssignmentOperator); + IO.bitSetCase(Options, "HasConversionOperator", + ClassOptions::HasConversionOperator); + IO.bitSetCase(Options, "ForwardReference", ClassOptions::ForwardReference); + IO.bitSetCase(Options, "Scoped", ClassOptions::Scoped); + IO.bitSetCase(Options, "HasUniqueName", ClassOptions::HasUniqueName); + IO.bitSetCase(Options, "Sealed", ClassOptions::Sealed); + IO.bitSetCase(Options, "Intrinsic", ClassOptions::Intrinsic); + } +}; + +template <> struct ScalarBitSetTraits { + static void bitset(IO &IO, MethodOptions &Options) { + IO.bitSetCase(Options, "None", MethodOptions::None); + IO.bitSetCase(Options, "Pseudo", MethodOptions::Pseudo); + IO.bitSetCase(Options, "NoInherit", MethodOptions::NoInherit); + IO.bitSetCase(Options, "NoConstruct", MethodOptions::NoConstruct); + IO.bitSetCase(Options, "CompilerGenerated", + MethodOptions::CompilerGenerated); + IO.bitSetCase(Options, "Sealed", MethodOptions::Sealed); + } +}; + +template <> struct ScalarTraits { + static void output(const APSInt &S, void *, llvm::raw_ostream &OS) { + S.print(OS, true); + } + static StringRef input(StringRef Scalar, void *Ctx, APSInt &S) { + S = APSInt(Scalar); + return ""; + } + + static bool mustQuote(StringRef Scalar) { return false; } +}; + +void MappingTraits::mapping(IO &IO, CVType &Record) { + if (IO.outputting()) { + codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO); + codeview::TypeDeserializer Deserializer(Callbacks); + + codeview::CVTypeVisitor Visitor(Deserializer); + consumeError(Visitor.visitTypeRecord(Record)); + } +} + +void MappingTraits::mapping(IO &IO, + FieldListRecord &FieldList) { + if (IO.outputting()) { + codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO); + codeview::TypeDeserializer Deserializer(Callbacks); + codeview::CVTypeVisitor Visitor(Deserializer); + consumeError(Visitor.visitFieldListMemberStream(FieldList.Data)); + } +} + +void MappingTraits::mapping(IO &IO, StringIdRecord &String) { + IO.mapRequired("Id", String.Id); + IO.mapRequired("String", String.String); +} + +void MappingTraits::mapping(IO &IO, ArgListRecord &Args) { + IO.mapRequired("ArgIndices", Args.StringIndices); +} + +void MappingTraits::mapping(IO &IO, ClassRecord &Class) { + IO.mapRequired("MemberCount", Class.MemberCount); + IO.mapRequired("Options", Class.Options); + IO.mapRequired("FieldList", Class.FieldList); + IO.mapRequired("Name", Class.Name); + IO.mapRequired("UniqueName", Class.UniqueName); + IO.mapRequired("Hfa", Class.Hfa); + IO.mapRequired("WinRTKind", Class.WinRTKind); + IO.mapRequired("DerivationList", Class.DerivationList); + IO.mapRequired("VTableShape", Class.VTableShape); + IO.mapRequired("Size", Class.Size); +} + +void MappingTraits::mapping(IO &IO, UnionRecord &Union) { + IO.mapRequired("MemberCount", Union.MemberCount); + IO.mapRequired("Options", Union.Options); + IO.mapRequired("FieldList", Union.FieldList); + IO.mapRequired("Name", Union.Name); + IO.mapRequired("UniqueName", Union.UniqueName); + IO.mapRequired("Hfa", Union.Hfa); + IO.mapRequired("Size", Union.Size); +} + +void MappingTraits::mapping(IO &IO, EnumRecord &Enum) { + IO.mapRequired("NumEnumerators", Enum.MemberCount); + IO.mapRequired("Options", Enum.Options); + IO.mapRequired("FieldList", Enum.FieldList); + IO.mapRequired("Name", Enum.Name); + IO.mapRequired("UniqueName", Enum.UniqueName); + IO.mapRequired("UnderlyingType", Enum.UnderlyingType); +} + +void MappingTraits::mapping(IO &IO, ArrayRecord &AT) { + IO.mapRequired("ElementType", AT.ElementType); + IO.mapRequired("IndexType", AT.IndexType); + IO.mapRequired("Size", AT.Size); + IO.mapRequired("Name", AT.Name); +} + +void MappingTraits::mapping(IO &IO, VFTableRecord &VFT) { + IO.mapRequired("CompleteClass", VFT.CompleteClass); + IO.mapRequired("OverriddenVFTable", VFT.OverriddenVFTable); + IO.mapRequired("VFPtrOffset", VFT.VFPtrOffset); + IO.mapRequired("Name", VFT.Name); + IO.mapRequired("MethodNames", VFT.MethodNames); +} + +void MappingTraits::mapping(IO &IO, + MemberFuncIdRecord &Id) { + IO.mapRequired("ClassType", Id.ClassType); + IO.mapRequired("FunctionType", Id.FunctionType); + IO.mapRequired("Name", Id.Name); +} + +void MappingTraits::mapping(IO &IO, ProcedureRecord &Proc) { + IO.mapRequired("ReturnType", Proc.ReturnType); + IO.mapRequired("CallConv", Proc.CallConv); + IO.mapRequired("Options", Proc.Options); + IO.mapRequired("ParameterCount", Proc.ParameterCount); + IO.mapRequired("ArgumentList", Proc.ArgumentList); +} + +void MappingTraits::mapping(IO &IO, + MemberFunctionRecord &MF) { + IO.mapRequired("ReturnType", MF.ReturnType); + IO.mapRequired("ClassType", MF.ClassType); + IO.mapRequired("ThisType", MF.ThisType); + IO.mapRequired("CallConv", MF.CallConv); + IO.mapRequired("Options", MF.Options); + IO.mapRequired("ParameterCount", MF.ParameterCount); + IO.mapRequired("ArgumentList", MF.ArgumentList); + IO.mapRequired("ThisPointerAdjustment", MF.ThisPointerAdjustment); +} + +void MappingTraits::mapping( + IO &IO, MethodOverloadListRecord &MethodList) { + IO.mapRequired("Methods", MethodList.Methods); +} + +void MappingTraits::mapping(IO &IO, FuncIdRecord &Func) { + IO.mapRequired("ParentScope", Func.ParentScope); + IO.mapRequired("FunctionType", Func.FunctionType); + IO.mapRequired("Name", Func.Name); +} + +void MappingTraits::mapping(IO &IO, TypeServer2Record &TS) { + IO.mapRequired("Guid", TS.Guid); + IO.mapRequired("Age", TS.Age); + IO.mapRequired("Name", TS.Name); +} + +void MappingTraits::mapping(IO &IO, PointerRecord &Ptr) { + IO.mapRequired("ReferentType", Ptr.ReferentType); + IO.mapRequired("PtrKind", Ptr.PtrKind); + IO.mapRequired("Mode", Ptr.Mode); + IO.mapRequired("Options", Ptr.Options); + IO.mapRequired("Size", Ptr.Size); + IO.mapOptional("MemberInfo", Ptr.MemberInfo); +} + +void MappingTraits::mapping(IO &IO, MemberPointerInfo &MPI) { + IO.mapRequired("ContainingType", MPI.ContainingType); + IO.mapRequired("Representation", MPI.Representation); +} + +void MappingTraits::mapping(IO &IO, ModifierRecord &Mod) { + IO.mapRequired("ModifiedType", Mod.ModifiedType); + IO.mapRequired("Modifiers", Mod.Modifiers); +} + +void MappingTraits::mapping(IO &IO, BitFieldRecord &BitField) { + IO.mapRequired("Type", BitField.Type); + IO.mapRequired("BitSize", BitField.BitSize); + IO.mapRequired("BitOffset", BitField.BitOffset); +} + +void MappingTraits::mapping(IO &IO, + VFTableShapeRecord &Shape) { + IO.mapRequired("Slots", Shape.Slots); +} + +void MappingTraits::mapping(IO &IO, + UdtSourceLineRecord &Line) { + IO.mapRequired("UDT", Line.UDT); + IO.mapRequired("SourceFile", Line.SourceFile); + IO.mapRequired("LineNumber", Line.LineNumber); +} + +void MappingTraits::mapping( + IO &IO, UdtModSourceLineRecord &Line) { + IO.mapRequired("UDT", Line.UDT); + IO.mapRequired("SourceFile", Line.SourceFile); + IO.mapRequired("LineNumber", Line.LineNumber); + IO.mapRequired("Module", Line.Module); +} + +void MappingTraits::mapping(IO &IO, BuildInfoRecord &Args) { + IO.mapRequired("ArgIndices", Args.ArgIndices); +} + +void MappingTraits::mapping(IO &IO, + NestedTypeRecord &Nested) { + IO.mapRequired("Type", Nested.Type); + IO.mapRequired("Name", Nested.Name); +} + +void MappingTraits::mapping(IO &IO, OneMethodRecord &Method) { + IO.mapRequired("Type", Method.Type); + IO.mapRequired("Kind", Method.Kind); + IO.mapRequired("Options", Method.Options); + IO.mapRequired("Access", Method.Access); + IO.mapRequired("VFTableOffset", Method.VFTableOffset); + IO.mapRequired("Name", Method.Name); +} + +void MappingTraits::mapping( + IO &IO, OverloadedMethodRecord &Method) { + IO.mapRequired("NumOverloads", Method.NumOverloads); + IO.mapRequired("MethodList", Method.MethodList); + IO.mapRequired("Name", Method.Name); +} + +void MappingTraits::mapping(IO &IO, DataMemberRecord &Field) { + IO.mapRequired("Access", Field.Access); + IO.mapRequired("Type", Field.Type); + IO.mapRequired("FieldOffset", Field.FieldOffset); + IO.mapRequired("Name", Field.Name); +} + +void MappingTraits::mapping( + IO &IO, StaticDataMemberRecord &Field) { + IO.mapRequired("Access", Field.Access); + IO.mapRequired("Type", Field.Type); + IO.mapRequired("Name", Field.Name); +} + +void MappingTraits::mapping(IO &IO, VFPtrRecord &VFTable) { + IO.mapRequired("Type", VFTable.Type); +} + +void MappingTraits::mapping(IO &IO, EnumeratorRecord &Enum) { + IO.mapRequired("Access", Enum.Access); + IO.mapRequired("Value", Enum.Value); + IO.mapRequired("Name", Enum.Name); +} + +void MappingTraits::mapping(IO &IO, BaseClassRecord &Base) { + IO.mapRequired("Access", Base.Access); + IO.mapRequired("Type", Base.Type); + IO.mapRequired("Offset", Base.Offset); +} + +void MappingTraits::mapping( + IO &IO, VirtualBaseClassRecord &Base) { + IO.mapRequired("Access", Base.Access); + IO.mapRequired("BaseType", Base.BaseType); + IO.mapRequired("VBPtrType", Base.VBPtrType); + IO.mapRequired("VBPtrOffset", Base.VBPtrOffset); + IO.mapRequired("VTableIndex", Base.VTableIndex); +} + +void MappingTraits::mapping( + IO &IO, ListContinuationRecord &Cont) { + IO.mapRequired("ContinuationIndex", Cont.ContinuationIndex); +} + +template <> struct ScalarTraits { + static void output(const codeview::TypeIndex &S, void *, + llvm::raw_ostream &OS) { + OS << S.getIndex(); + } + static StringRef input(StringRef Scalar, void *Ctx, codeview::TypeIndex &S) { + uint32_t I; + StringRef Result = ScalarTraits::input(Scalar, Ctx, I); + if (!Result.empty()) + return Result; + S = TypeIndex(I); + return ""; + } + static bool mustQuote(StringRef Scalar) { return false; } +}; + +void ScalarEnumerationTraits::enumeration(IO &io, + TypeLeafKind &Value) { + auto TypeLeafNames = getTypeLeafNames(); + for (const auto &E : TypeLeafNames) + io.enumCase(Value, E.Name.str().c_str(), E.Value); +} +} +} + +Error llvm::codeview::yaml::YamlTypeDumperCallbacks::visitTypeBegin( + const CVRecord &CVR) { + TypeLeafKind K = CVR.Type; + YamlIO.mapRequired("Kind", K); + return Error::success(); +} Index: tools/llvm-pdbdump/PdbYaml.h =================================================================== --- tools/llvm-pdbdump/PdbYaml.h +++ tools/llvm-pdbdump/PdbYaml.h @@ -69,12 +69,23 @@ std::vector ModInfos; }; +struct PdbTpiRecord { + std::vector RecordData; + codeview::CVType Record; +}; + +struct PdbTpiStream { + PdbRaw_TpiVer Version; + std::vector Records; +}; + struct PdbObject { Optional Headers; Optional> StreamSizes; Optional> StreamMap; Optional PdbStream; Optional DbiStream; + Optional TpiStream; }; } } @@ -107,6 +118,10 @@ static void mapping(IO &IO, pdb::yaml::PdbDbiStream &Obj); }; +template <> struct MappingTraits { + static void mapping(IO &IO, pdb::yaml::PdbTpiStream &Obj); +}; + template <> struct MappingTraits { static void mapping(IO &IO, pdb::yaml::NamedStreamMapping &Obj); }; @@ -114,13 +129,11 @@ template <> struct MappingTraits { static void mapping(IO &IO, pdb::yaml::PdbDbiModuleInfo &Obj); }; + +template <> struct MappingTraits { + static void mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj); +}; } } -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) - #endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H Index: tools/llvm-pdbdump/PdbYaml.cpp =================================================================== --- tools/llvm-pdbdump/PdbYaml.cpp +++ tools/llvm-pdbdump/PdbYaml.cpp @@ -8,18 +8,29 @@ //===----------------------------------------------------------------------===// #include "PdbYaml.h" +#include "CodeViewYaml.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" using namespace llvm; -using namespace llvm::msf; -using namespace llvm::yaml; using namespace llvm::pdb; using namespace llvm::pdb::yaml; +using namespace llvm::yaml; + +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiRecord) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) namespace llvm { namespace yaml { + template <> struct ScalarTraits { static void output(const llvm::pdb::PDB_UniqueId &S, void *, llvm::raw_ostream &OS) { @@ -102,6 +113,16 @@ io.enumCase(Value, "VC140", llvm::pdb::PdbRaw_ImplVer::PdbImplVC140); } }; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, llvm::pdb::PdbRaw_TpiVer &Value) { + io.enumCase(Value, "VC40", llvm::pdb::PdbRaw_TpiVer::PdbTpiV40); + io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_TpiVer::PdbTpiV41); + io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_TpiVer::PdbTpiV50); + io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_TpiVer::PdbTpiV70); + io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_TpiVer::PdbTpiV80); + } +}; } } @@ -111,6 +132,7 @@ IO.mapOptional("StreamMap", Obj.StreamMap); IO.mapOptional("PdbStream", Obj.PdbStream); IO.mapOptional("DbiStream", Obj.DbiStream); + IO.mapOptional("TpiStream", Obj.TpiStream); } void MappingTraits::mapping(IO &IO, MSFHeaders &Obj) { @@ -157,6 +179,12 @@ IO.mapOptional("Modules", Obj.ModInfos); } +void MappingTraits::mapping(IO &IO, + pdb::yaml::PdbTpiStream &Obj) { + IO.mapRequired("Version", Obj.Version); + IO.mapRequired("Records", Obj.Records); +} + void MappingTraits::mapping(IO &IO, NamedStreamMapping &Obj) { IO.mapRequired("Name", Obj.StreamName); @@ -168,3 +196,19 @@ IO.mapRequired("ObjFile", Obj.Obj); IO.mapOptional("SourceFiles", Obj.SourceFiles); } + +void MappingTraits::mapping(IO &IO, + pdb::yaml::PdbTpiRecord &Obj) { + if (IO.outputting()) { + // If we're going from Pdb To Yaml, deserialize the Pdb record + codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO); + codeview::TypeDeserializer Deserializer(Callbacks); + + codeview::CVTypeVisitor Visitor(Deserializer); + consumeError(Visitor.visitTypeRecord(Obj.Record)); + } else { + codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO); + codeview::CVTypeVisitor Visitor(Callbacks); + consumeError(Visitor.visitTypeRecord(Obj.Record)); + } +} Index: tools/llvm-pdbdump/YAMLOutputStyle.h =================================================================== --- tools/llvm-pdbdump/YAMLOutputStyle.h +++ tools/llvm-pdbdump/YAMLOutputStyle.h @@ -31,6 +31,7 @@ Error dumpStreamDirectory(); Error dumpPDBStream(); Error dumpDbiStream(); + Error dumpTpiStream(); void flush(); Index: tools/llvm-pdbdump/YAMLOutputStyle.cpp =================================================================== --- tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -16,6 +16,7 @@ #include "llvm/DebugInfo/PDB/Raw/InfoStream.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/TpiStream.h" using namespace llvm; using namespace llvm::pdb; @@ -45,6 +46,9 @@ if (auto EC = dumpDbiStream()) return EC; + if (auto EC = dumpTpiStream()) + return EC; + flush(); return Error::success(); } @@ -150,6 +154,30 @@ return Error::success(); } +Error YAMLOutputStyle::dumpTpiStream() { + if (!opts::pdb2yaml::TpiStream) + return Error::success(); + + auto TpiS = File.getPDBTpiStream(); + if (!TpiS) + return TpiS.takeError(); + + auto &TS = TpiS.get(); + Obj.TpiStream.emplace(); + Obj.TpiStream->Version = TS.getTpiVersion(); + for (auto &Record : TS.types(nullptr)) { + yaml::PdbTpiRecord R; + // It's not necessary to set R.RecordData here. That only exists as a + // way to have the `PdbTpiRecord` structure own the memory that `R.Record` + // references. In the case of reading an existing PDB though, that memory + // is owned by the backing stream. + R.Record = Record; + Obj.TpiStream->Records.push_back(R); + } + + return Error::success(); +} + void YAMLOutputStyle::flush() { Out << Obj; outs().flush(); Index: tools/llvm-pdbdump/llvm-pdbdump.h =================================================================== --- tools/llvm-pdbdump/llvm-pdbdump.h +++ tools/llvm-pdbdump/llvm-pdbdump.h @@ -65,6 +65,7 @@ extern llvm::cl::opt DbiStream; extern llvm::cl::opt DbiModuleInfo; extern llvm::cl::opt DbiModuleSourceFileInfo; +extern llvm::cl::opt TpiStream; extern llvm::cl::list InputFilename; } } Index: tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- tools/llvm-pdbdump/llvm-pdbdump.cpp +++ tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -281,6 +281,10 @@ "Dump DBI Module Source File Information (implies -dbi-module-info"), cl::sub(PdbToYamlSubcommand), cl::init(false)); +cl::opt TpiStream("tpi-stream", + cl::desc("Dump the TPI Stream (Stream 3)"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); + cl::list InputFilename(cl::Positional, cl::desc(""), cl::Required, cl::sub(PdbToYamlSubcommand)); @@ -537,8 +541,7 @@ cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n"); - // These options are shared by two subcommands. - if ((opts::PdbToYamlSubcommand || opts::RawSubcommand) && opts::raw::RawAll) { + if (opts::RawSubcommand && opts::raw::RawAll) { opts::raw::DumpHeaders = true; opts::raw::DumpModules = true; opts::raw::DumpModuleFiles = true;