diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 71 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 88 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CodeViewError.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp | 18 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp | 81 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeDumper.cpp | 106 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeRecord.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp | 59 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp | 48 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp | 25 |
12 files changed, 299 insertions, 207 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 9d5d2127359..52d7b45d37b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -212,7 +212,7 @@ TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) { // Build the fully qualified name of the scope. std::string ScopeName = getFullyQualifiedName(Scope); TypeIndex TI = - TypeTable.writeStringId(StringIdRecord(TypeIndex(), ScopeName)); + TypeTable.writeKnownType(StringIdRecord(TypeIndex(), ScopeName)); return recordTypeIndexForDINode(Scope, TI); } @@ -237,12 +237,12 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) { TypeIndex ClassType = getTypeIndex(Class); MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class), DisplayName); - TI = TypeTable.writeMemberFuncId(MFuncId); + TI = TypeTable.writeKnownType(MFuncId); } else { // Otherwise, this must be a free function. TypeIndex ParentScope = getScopeIndex(Scope); FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName); - TI = TypeTable.writeFuncId(FuncId); + TI = TypeTable.writeKnownType(FuncId); } return recordTypeIndexForDINode(SP, TI); @@ -1030,7 +1030,7 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) { StringRef Name = (i == 0) ? Ty->getName() : ""; // Update the element size and element type index for subsequent subranges. ElementSize *= Count; - ElementTypeIndex = TypeTable.writeArray( + ElementTypeIndex = TypeTable.writeKnownType( ArrayRecord(ElementTypeIndex, IndexType, ElementSize, Name)); } @@ -1174,7 +1174,7 @@ TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty) { // do. PointerOptions PO = PointerOptions::None; PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8); - return TypeTable.writePointer(PR); + return TypeTable.writeKnownType(PR); } static PointerToMemberRepresentation @@ -1225,7 +1225,7 @@ TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) { MemberPointerInfo MPI( ClassTI, translatePtrToMemberRep(SizeInBytes, IsPMF, Ty->getFlags())); PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI); - return TypeTable.writePointer(PR); + return TypeTable.writeKnownType(PR); } /// Given a DWARF calling convention, get the CodeView equivalent. If we don't @@ -1272,7 +1272,7 @@ TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) { return I->second; ModifierRecord MR(ModifiedTI, Mods); - return TypeTable.writeModifier(MR); + return TypeTable.writeKnownType(MR); } TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) { @@ -1289,13 +1289,13 @@ TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) { } ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices); - TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec); + TypeIndex ArgListIndex = TypeTable.writeKnownType(ArgListRec); CallingConvention CC = dwarfCCToCodeView(Ty->getCC()); ProcedureRecord Procedure(ReturnTypeIndex, CC, FunctionOptions::None, ArgTypeIndices.size(), ArgListIndex); - return TypeTable.writeProcedure(Procedure); + return TypeTable.writeKnownType(Procedure); } TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty, @@ -1322,14 +1322,14 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty, } ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices); - TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec); + TypeIndex ArgListIndex = TypeTable.writeKnownType(ArgListRec); CallingConvention CC = dwarfCCToCodeView(Ty->getCC()); // TODO: Need to use the correct values for: // FunctionOptions // ThisPointerAdjustment. - TypeIndex TI = TypeTable.writeMemberFunction(MemberFunctionRecord( + TypeIndex TI = TypeTable.writeKnownType(MemberFunctionRecord( ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FunctionOptions::None, ArgTypeIndices.size(), ArgListIndex, ThisAdjustment)); @@ -1428,7 +1428,7 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) { // We assume that the frontend provides all members in source declaration // order, which is what MSVC does. if (auto *Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) { - Fields.writeEnumerator(EnumeratorRecord( + Fields.writeMemberType(EnumeratorRecord( MemberAccess::Public, APSInt::getUnsigned(Enumerator->getValue()), Enumerator->getName())); EnumeratorCount++; @@ -1439,9 +1439,9 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) { std::string FullName = getFullyQualifiedName(Ty); - return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, FullName, - Ty->getIdentifier(), - getTypeIndex(Ty->getBaseType()))); + return TypeTable.writeKnownType(EnumRecord(EnumeratorCount, CO, FTI, FullName, + Ty->getIdentifier(), + getTypeIndex(Ty->getBaseType()))); } //===----------------------------------------------------------------------===// @@ -1536,7 +1536,7 @@ TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) { ClassOptions CO = ClassOptions::ForwardReference | getCommonClassOptions(Ty); std::string FullName = getFullyQualifiedName(Ty); - TypeIndex FwdDeclTI = TypeTable.writeClass(ClassRecord( + TypeIndex FwdDeclTI = TypeTable.writeKnownType(ClassRecord( Kind, 0, CO, HfaKind::None, WindowsRTClassKind::None, TypeIndex(), TypeIndex(), TypeIndex(), 0, FullName, Ty->getIdentifier())); if (!Ty->isForwardDecl()) @@ -1562,12 +1562,12 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) { uint64_t SizeInBytes = Ty->getSizeInBits() / 8; - TypeIndex ClassTI = TypeTable.writeClass(ClassRecord( + TypeIndex ClassTI = TypeTable.writeKnownType(ClassRecord( Kind, FieldCount, CO, HfaKind::None, WindowsRTClassKind::None, FieldTI, TypeIndex(), VShapeTI, SizeInBytes, FullName, Ty->getIdentifier())); - TypeTable.writeUdtSourceLine(UdtSourceLineRecord( - ClassTI, TypeTable.writeStringId(StringIdRecord( + TypeTable.writeKnownType(UdtSourceLineRecord( + ClassTI, TypeTable.writeKnownType(StringIdRecord( TypeIndex(0x0), getFullFilepath(Ty->getFile()))), Ty->getLine())); @@ -1580,9 +1580,8 @@ TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) { ClassOptions CO = ClassOptions::ForwardReference | getCommonClassOptions(Ty); std::string FullName = getFullyQualifiedName(Ty); - TypeIndex FwdDeclTI = - TypeTable.writeUnion(UnionRecord(0, CO, HfaKind::None, TypeIndex(), 0, - FullName, Ty->getIdentifier())); + TypeIndex FwdDeclTI = TypeTable.writeKnownType(UnionRecord( + 0, CO, HfaKind::None, TypeIndex(), 0, FullName, Ty->getIdentifier())); if (!Ty->isForwardDecl()) DeferredCompleteTypes.push_back(Ty); return FwdDeclTI; @@ -1602,12 +1601,12 @@ TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) { uint64_t SizeInBytes = Ty->getSizeInBits() / 8; std::string FullName = getFullyQualifiedName(Ty); - TypeIndex UnionTI = TypeTable.writeUnion( + TypeIndex UnionTI = TypeTable.writeKnownType( UnionRecord(FieldCount, CO, HfaKind::None, FieldTI, SizeInBytes, FullName, Ty->getIdentifier())); - TypeTable.writeUdtSourceLine(UdtSourceLineRecord( - UnionTI, TypeTable.writeStringId(StringIdRecord( + TypeTable.writeKnownType(UdtSourceLineRecord( + UnionTI, TypeTable.writeKnownType(StringIdRecord( TypeIndex(0x0), getFullFilepath(Ty->getFile()))), Ty->getLine())); @@ -1634,14 +1633,14 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) { unsigned VBPtrOffset = 0; // FIXME: Despite the accessor name, the offset is really in bytes. unsigned VBTableIndex = I->getOffsetInBits() / 4; - Fields.writeVirtualBaseClass(VirtualBaseClassRecord( + Fields.writeMemberType(VirtualBaseClassRecord( translateAccessFlags(Ty->getTag(), I->getFlags()), getTypeIndex(I->getBaseType()), getVBPTypeIndex(), VBPtrOffset, VBTableIndex)); } else { assert(I->getOffsetInBits() % 8 == 0 && "bases must be on byte boundaries"); - Fields.writeBaseClass(BaseClassRecord( + Fields.writeMemberType(BaseClassRecord( translateAccessFlags(Ty->getTag(), I->getFlags()), getTypeIndex(I->getBaseType()), I->getOffsetInBits() / 8)); } @@ -1656,7 +1655,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) { translateAccessFlags(Ty->getTag(), Member->getFlags()); if (Member->isStaticMember()) { - Fields.writeStaticDataMember( + Fields.writeMemberType( StaticDataMemberRecord(Access, MemberBaseType, MemberName)); MemberCount++; continue; @@ -1672,11 +1671,11 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) { MemberOffsetInBits = CI->getZExtValue() + MemberInfo.BaseOffset; } StartBitOffset -= MemberOffsetInBits; - MemberBaseType = TypeTable.writeBitField(BitFieldRecord( + MemberBaseType = TypeTable.writeKnownType(BitFieldRecord( MemberBaseType, Member->getSizeInBits(), StartBitOffset)); } uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8; - Fields.writeDataMember(DataMemberRecord(Access, MemberBaseType, + Fields.writeMemberType(DataMemberRecord(Access, MemberBaseType, MemberOffsetInBytes, MemberName)); MemberCount++; } @@ -1703,11 +1702,11 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) { } assert(Methods.size() > 0 && "Empty methods map entry"); if (Methods.size() == 1) - Fields.writeOneMethod(Methods[0]); + Fields.writeMemberType(Methods[0]); else { TypeIndex MethodList = - TypeTable.writeMethodOverloadList(MethodOverloadListRecord(Methods)); - Fields.writeOverloadedMethod( + TypeTable.writeKnownType(MethodOverloadListRecord(Methods)); + Fields.writeMemberType( OverloadedMethodRecord(Methods.size(), MethodList, Name)); } } @@ -1715,7 +1714,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) { // Create nested classes. for (const DICompositeType *Nested : Info.NestedClasses) { NestedTypeRecord R(getTypeIndex(DITypeRef(Nested)), Nested->getName()); - Fields.writeNestedType(R); + Fields.writeMemberType(R); MemberCount++; } @@ -1728,7 +1727,7 @@ TypeIndex CodeViewDebug::getVBPTypeIndex() { if (!VBPType.getIndex()) { // Make a 'const int *' type. ModifierRecord MR(TypeIndex::Int32(), ModifierOptions::Const); - TypeIndex ModifiedTI = TypeTable.writeModifier(MR); + TypeIndex ModifiedTI = TypeTable.writeKnownType(MR); PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64 : PointerKind::Near32; @@ -1736,7 +1735,7 @@ TypeIndex CodeViewDebug::getVBPTypeIndex() { PointerOptions PO = PointerOptions::None; PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes()); - VBPType = TypeTable.writePointer(PR); + VBPType = TypeTable.writeKnownType(PR); } return VBPType; diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index d8c21953967..92ffd3d24d7 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -11,6 +11,7 @@ add_llvm_library(LLVMDebugInfoCodeView ModuleSubstreamVisitor.cpp RecordSerialization.cpp SymbolDumper.cpp + TypeDeserializer.cpp TypeDumper.cpp TypeRecord.cpp TypeRecordBuilder.cpp diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index a7b7f3a2793..01dd5d4591c 100644 --- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -8,47 +8,39 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" + #include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/Msf/ByteStream.h" using namespace llvm; using namespace llvm::codeview; +CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks) + : Callbacks(Callbacks) {} + template <typename T> -static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) { - if (Data.size() < sizeof(*Res)) - return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer); - Res = reinterpret_cast<const T *>(Data.data()); - Data = Data.drop_front(sizeof(*Res)); +static Error visitKnownRecord(const CVRecord<TypeLeafKind> &Record, + TypeVisitorCallbacks &Callbacks) { + TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type); + T KnownRecord(RK); + if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord)) + return EC; return Error::success(); } -CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks) - : Callbacks(Callbacks) {} - Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) { ArrayRef<uint8_t> LeafData = Record.Data; if (auto EC = Callbacks.visitTypeBegin(Record)) return EC; + switch (Record.Type) { default: if (auto EC = Callbacks.visitUnknownType(Record)) return EC; break; - case LF_FIELDLIST: - if (auto EC = Callbacks.visitFieldListBegin(Record)) - return EC; - if (auto EC = visitFieldList(Record)) - return EC; - if (auto EC = Callbacks.visitFieldListEnd(Record)) - return EC; - break; #define TYPE_RECORD(EnumName, EnumVal, Name) \ case EnumName: { \ - TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName); \ - auto ExpectedRecord = Name##Record::deserialize(RK, LeafData); \ - if (!ExpectedRecord) \ - return ExpectedRecord.takeError(); \ - if (auto EC = Callbacks.visit##Name(*ExpectedRecord)) \ + if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \ return EC; \ break; \ } @@ -57,8 +49,10 @@ Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) { #define MEMBER_RECORD(EnumName, EnumVal, Name) #include "llvm/DebugInfo/CodeView/TypeRecords.def" } + if (auto EC = Callbacks.visitTypeEnd(Record)) return EC; + return Error::success(); } @@ -70,55 +64,3 @@ Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) { } return Error::success(); } - -Error CVTypeVisitor::skipPadding(ArrayRef<uint8_t> &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<CodeViewError>(cv_error_code::corrupt_record, - "Invalid padding bytes!"); - } - Data = Data.drop_front(BytesToAdvance); - return Error::success(); -} - -/// Visits individual member records of a field list record. Member records do -/// not describe their own length, and need special handling. -Error CVTypeVisitor::visitFieldList(const CVRecord<TypeLeafKind> &Record) { - ArrayRef<uint8_t> RecordData = Record.Data; - while (!RecordData.empty()) { - const ulittle16_t *LeafPtr; - if (auto EC = takeObject(RecordData, 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 an unknown member type. - if (auto EC = Callbacks.visitUnknownMember(Record)) - return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - case EnumName: { \ - TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName); \ - auto ExpectedRecord = Name##Record::deserialize(RK, RecordData); \ - if (!ExpectedRecord) \ - return ExpectedRecord.takeError(); \ - if (auto EC = Callbacks.visit##Name(*ExpectedRecord)) \ - 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(RecordData)) - return EC; - } - return Error::success(); -} diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp index aad1d8b25cd..e9678db7a5b 100644 --- a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp @@ -33,6 +33,8 @@ public: return "The CodeView record is corrupted."; case cv_error_code::operation_unsupported: return "The requested operation is not supported."; + case cv_error_code::unknown_member_record: + return "The member record is of an unknown type."; } llvm_unreachable("Unrecognized cv_error_code"); } diff --git a/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp index 5f229e3d9f9..ac2ef3972b6 100644 --- a/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp +++ b/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp @@ -15,7 +15,7 @@ using namespace codeview; FieldListRecordBuilder::FieldListRecordBuilder() : ListRecordBuilder(TypeRecordKind::FieldList) {} -void FieldListRecordBuilder::writeBaseClass(const BaseClassRecord &Record) { +void FieldListRecordBuilder::writeMemberType(const BaseClassRecord &Record) { TypeRecordBuilder &Builder = getBuilder(); Builder.writeTypeRecordKind(TypeRecordKind::BaseClass); @@ -26,7 +26,7 @@ void FieldListRecordBuilder::writeBaseClass(const BaseClassRecord &Record) { finishSubRecord(); } -void FieldListRecordBuilder::writeEnumerator(const EnumeratorRecord &Record) { +void FieldListRecordBuilder::writeMemberType(const EnumeratorRecord &Record) { TypeRecordBuilder &Builder = getBuilder(); Builder.writeTypeRecordKind(TypeRecordKind::Enumerator); @@ -38,7 +38,7 @@ void FieldListRecordBuilder::writeEnumerator(const EnumeratorRecord &Record) { finishSubRecord(); } -void FieldListRecordBuilder::writeDataMember(const DataMemberRecord &Record) { +void FieldListRecordBuilder::writeMemberType(const DataMemberRecord &Record) { TypeRecordBuilder &Builder = getBuilder(); Builder.writeTypeRecordKind(Record.getKind()); @@ -50,7 +50,7 @@ void FieldListRecordBuilder::writeDataMember(const DataMemberRecord &Record) { finishSubRecord(); } -void FieldListRecordBuilder::writeOverloadedMethod( +void FieldListRecordBuilder::writeMemberType( const OverloadedMethodRecord &Record) { TypeRecordBuilder &Builder = getBuilder(); @@ -62,7 +62,7 @@ void FieldListRecordBuilder::writeOverloadedMethod( finishSubRecord(); } -void FieldListRecordBuilder::writeOneMethod(const OneMethodRecord &Record) { +void FieldListRecordBuilder::writeMemberType(const OneMethodRecord &Record) { TypeRecordBuilder &Builder = getBuilder(); uint16_t Flags = static_cast<uint16_t>(Record.getAccess()); @@ -84,7 +84,7 @@ void FieldListRecordBuilder::writeOneMethod(const OneMethodRecord &Record) { finishSubRecord(); } -void FieldListRecordBuilder::writeNestedType(const NestedTypeRecord &Record) { +void FieldListRecordBuilder::writeMemberType(const NestedTypeRecord &Record) { TypeRecordBuilder &Builder = getBuilder(); Builder.writeTypeRecordKind(Record.getKind()); @@ -95,7 +95,7 @@ void FieldListRecordBuilder::writeNestedType(const NestedTypeRecord &Record) { finishSubRecord(); } -void FieldListRecordBuilder::writeStaticDataMember( +void FieldListRecordBuilder::writeMemberType( const StaticDataMemberRecord &Record) { TypeRecordBuilder &Builder = getBuilder(); @@ -107,7 +107,7 @@ void FieldListRecordBuilder::writeStaticDataMember( finishSubRecord(); } -void FieldListRecordBuilder::writeVirtualBaseClass( +void FieldListRecordBuilder::writeMemberType( const VirtualBaseClassRecord &Record) { TypeRecordBuilder &Builder = getBuilder(); @@ -121,7 +121,7 @@ void FieldListRecordBuilder::writeVirtualBaseClass( finishSubRecord(); } -void FieldListRecordBuilder::writeVFPtr(const VFPtrRecord &Record) { +void FieldListRecordBuilder::writeMemberType(const VFPtrRecord &Record) { TypeRecordBuilder &Builder = getBuilder(); Builder.writeTypeRecordKind(TypeRecordKind::VFPtr); diff --git a/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp index eb79e8ac9a3..ab019c44c5b 100644 --- a/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp +++ b/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp @@ -17,7 +17,7 @@ using namespace codeview; ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind) : Kind(Kind), Builder(Kind) {} -void ListRecordBuilder::writeListContinuation(const ListContinuationRecord &R) { +void ListRecordBuilder::writeMemberType(const ListContinuationRecord &R) { TypeRecordBuilder &Builder = getBuilder(); assert(getLastContinuationSize() < 65535 - 8 && "continuation won't fit"); diff --git a/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp b/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp new file mode 100644 index 00000000000..3593458565f --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp @@ -0,0 +1,81 @@ +//===- TypeDeserializer.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" + +using namespace llvm; +using namespace llvm::codeview; + +template <typename T> +static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) { + if (Data.size() < sizeof(*Res)) + return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer); + Res = reinterpret_cast<const T *>(Data.data()); + Data = Data.drop_front(sizeof(*Res)); + return Error::success(); +} + +Error TypeDeserializer::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + FieldListRecord &Record) { + ArrayRef<uint8_t> FieldListRecordData = CVR.Data; + auto ExpectedRecord = FieldListRecord::deserialize(TypeRecordKind::FieldList, + FieldListRecordData); + if (!ExpectedRecord) + return ExpectedRecord.takeError(); + + Record = *ExpectedRecord; + ArrayRef<uint8_t> 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<CodeViewError>( + cv_error_code::unknown_member_record); +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + case EnumName: { \ + TypeRecordKind RK = static_cast<TypeRecordKind>(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<uint8_t> &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<CodeViewError>(cv_error_code::corrupt_record, + "Invalid padding bytes!"); + } + Data = Data.drop_front(BytesToAdvance); + return Error::success(); +} diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp index 5ceaa59a79e..e1ec5ce9802 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/CodeView/TypeDumper.h" #include "llvm/ADT/SmallString.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/MSF/ByteStream.h" @@ -195,8 +196,6 @@ static StringRef getLeafTypeName(TypeLeafKind LT) { case ename: \ return #name; #include "llvm/DebugInfo/CodeView/TypeRecords.def" - case LF_FIELDLIST: - return "FieldList"; default: break; } @@ -231,7 +230,13 @@ Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) { return Error::success(); } -Error CVTypeDumper::visitStringId(StringIdRecord &String) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + FieldListRecord &FieldList) { + return Error::success(); +} + +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + StringIdRecord &String) { printTypeIndex("Id", String.getId()); W->printString("StringData", String.getString()); // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE. @@ -239,7 +244,8 @@ Error CVTypeDumper::visitStringId(StringIdRecord &String) { return Error::success(); } -Error CVTypeDumper::visitArgList(ArgListRecord &Args) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + ArgListRecord &Args) { auto Indices = Args.getIndices(); uint32_t Size = Indices.size(); W->printNumber("NumArgs", Size); @@ -257,7 +263,8 @@ Error CVTypeDumper::visitArgList(ArgListRecord &Args) { return Error::success(); } -Error CVTypeDumper::visitClass(ClassRecord &Class) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + ClassRecord &Class) { uint16_t Props = static_cast<uint16_t>(Class.getOptions()); W->printNumber("MemberCount", Class.getMemberCount()); W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); @@ -272,7 +279,8 @@ Error CVTypeDumper::visitClass(ClassRecord &Class) { return Error::success(); } -Error CVTypeDumper::visitUnion(UnionRecord &Union) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + UnionRecord &Union) { uint16_t Props = static_cast<uint16_t>(Union.getOptions()); W->printNumber("MemberCount", Union.getMemberCount()); W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); @@ -285,7 +293,8 @@ Error CVTypeDumper::visitUnion(UnionRecord &Union) { return Error::success(); } -Error CVTypeDumper::visitEnum(EnumRecord &Enum) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + EnumRecord &Enum) { uint16_t Props = static_cast<uint16_t>(Enum.getOptions()); W->printNumber("NumEnumerators", Enum.getMemberCount()); W->printFlags("Properties", uint16_t(Enum.getOptions()), @@ -299,7 +308,8 @@ Error CVTypeDumper::visitEnum(EnumRecord &Enum) { return Error::success(); } -Error CVTypeDumper::visitArray(ArrayRecord &AT) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + ArrayRecord &AT) { printTypeIndex("ElementType", AT.getElementType()); printTypeIndex("IndexType", AT.getIndexType()); W->printNumber("SizeOf", AT.getSize()); @@ -308,7 +318,8 @@ Error CVTypeDumper::visitArray(ArrayRecord &AT) { return Error::success(); } -Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + VFTableRecord &VFT) { printTypeIndex("CompleteClass", VFT.getCompleteClass()); printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable()); W->printHex("VFPtrOffset", VFT.getVFPtrOffset()); @@ -319,7 +330,8 @@ Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) { return Error::success(); } -Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + MemberFuncIdRecord &Id) { printTypeIndex("ClassType", Id.getClassType()); printTypeIndex("FunctionType", Id.getFunctionType()); W->printString("Name", Id.getName()); @@ -327,7 +339,8 @@ Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) { return Error::success(); } -Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + ProcedureRecord &Proc) { printTypeIndex("ReturnType", Proc.getReturnType()); W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()), makeArrayRef(CallingConventions)); @@ -345,7 +358,8 @@ Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) { return Error::success(); } -Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + MemberFunctionRecord &MF) { printTypeIndex("ReturnType", MF.getReturnType()); printTypeIndex("ClassType", MF.getClassType()); printTypeIndex("ThisType", MF.getThisType()); @@ -369,8 +383,8 @@ Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) { return Error::success(); } -Error CVTypeDumper::visitMethodOverloadList( - MethodOverloadListRecord &MethodList) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + MethodOverloadListRecord &MethodList) { for (auto &M : MethodList.getMethods()) { ListScope S(*W, "Method"); printMemberAttributes(M.getAccess(), M.getKind(), M.getOptions()); @@ -381,7 +395,8 @@ Error CVTypeDumper::visitMethodOverloadList( return Error::success(); } -Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + FuncIdRecord &Func) { printTypeIndex("ParentScope", Func.getParentScope()); printTypeIndex("FunctionType", Func.getFunctionType()); W->printString("Name", Func.getName()); @@ -389,7 +404,8 @@ Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) { return Error::success(); } -Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + TypeServer2Record &TS) { W->printBinary("Signature", TS.getGuid()); W->printNumber("Age", TS.getAge()); W->printString("Name", TS.getName()); @@ -397,7 +413,8 @@ Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) { return Error::success(); } -Error CVTypeDumper::visitPointer(PointerRecord &Ptr) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + PointerRecord &Ptr) { printTypeIndex("PointeeType", Ptr.getReferentType()); W->printHex("PointerAttributes", uint32_t(Ptr.getOptions())); W->printEnum("PtrType", unsigned(Ptr.getPointerKind()), @@ -448,7 +465,8 @@ Error CVTypeDumper::visitPointer(PointerRecord &Ptr) { return Error::success(); } -Error CVTypeDumper::visitModifier(ModifierRecord &Mod) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + ModifierRecord &Mod) { uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); printTypeIndex("ModifiedType", Mod.getModifiedType()); W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames)); @@ -466,26 +484,30 @@ Error CVTypeDumper::visitModifier(ModifierRecord &Mod) { return Error::success(); } -Error CVTypeDumper::visitBitField(BitFieldRecord &BitField) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + BitFieldRecord &BitField) { printTypeIndex("Type", BitField.getType()); W->printNumber("BitSize", BitField.getBitSize()); W->printNumber("BitOffset", BitField.getBitOffset()); return Error::success(); } -Error CVTypeDumper::visitVFTableShape(VFTableShapeRecord &Shape) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + VFTableShapeRecord &Shape) { W->printNumber("VFEntryCount", Shape.getEntryCount()); return Error::success(); } -Error CVTypeDumper::visitUdtSourceLine(UdtSourceLineRecord &Line) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + UdtSourceLineRecord &Line) { printTypeIndex("UDT", Line.getUDT()); printTypeIndex("SourceFile", Line.getSourceFile()); W->printNumber("LineNumber", Line.getLineNumber()); return Error::success(); } -Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + UdtModSourceLineRecord &Line) { printTypeIndex("UDT", Line.getUDT()); printTypeIndex("SourceFile", Line.getSourceFile()); W->printNumber("LineNumber", Line.getLineNumber()); @@ -493,7 +515,8 @@ Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) { return Error::success(); } -Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + BuildInfoRecord &Args) { W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size())); ListScope Arguments(*W, "Arguments"); @@ -533,7 +556,8 @@ Error CVTypeDumper::visitUnknownType(const CVRecord<TypeLeafKind> &Record) { return Error::success(); } -Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + NestedTypeRecord &Nested) { DictScope S(*W, "NestedType"); printTypeIndex("Type", Nested.getNestedType()); W->printString("Name", Nested.getName()); @@ -541,7 +565,8 @@ Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) { return Error::success(); } -Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + OneMethodRecord &Method) { DictScope S(*W, "OneMethod"); MethodKind K = Method.getKind(); printMemberAttributes(Method.getAccess(), K, Method.getOptions()); @@ -554,7 +579,8 @@ Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) { return Error::success(); } -Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + OverloadedMethodRecord &Method) { DictScope S(*W, "OverloadedMethod"); W->printHex("MethodCount", Method.getNumOverloads()); printTypeIndex("MethodListIndex", Method.getMethodList()); @@ -563,7 +589,8 @@ Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) { return Error::success(); } -Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + DataMemberRecord &Field) { DictScope S(*W, "DataMember"); printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, MethodOptions::None); @@ -574,7 +601,8 @@ Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) { return Error::success(); } -Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + StaticDataMemberRecord &Field) { DictScope S(*W, "StaticDataMember"); printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, MethodOptions::None); @@ -584,13 +612,15 @@ Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) { return Error::success(); } -Error CVTypeDumper::visitVFPtr(VFPtrRecord &VFTable) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + VFPtrRecord &VFTable) { DictScope S(*W, "VFPtr"); printTypeIndex("Type", VFTable.getType()); return Error::success(); } -Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + EnumeratorRecord &Enum) { DictScope S(*W, "Enumerator"); printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla, MethodOptions::None); @@ -600,7 +630,8 @@ Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) { return Error::success(); } -Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + BaseClassRecord &Base) { DictScope S(*W, "BaseClass"); printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, MethodOptions::None); @@ -609,7 +640,8 @@ Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) { return Error::success(); } -Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + VirtualBaseClassRecord &Base) { DictScope S(*W, "VirtualBaseClass"); printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, MethodOptions::None); @@ -620,7 +652,8 @@ Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) { return Error::success(); } -Error CVTypeDumper::visitListContinuation(ListContinuationRecord &Cont) { +Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + ListContinuationRecord &Cont) { DictScope S(*W, "ListContinuation"); printTypeIndex("ContinuationIndex", Cont.getContinuationIndex()); return Error::success(); @@ -665,7 +698,8 @@ void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) { Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) { assert(W && "printer should not be null"); - CVTypeVisitor Visitor(*this); + TypeDeserializer Deserializer(*this); + CVTypeVisitor Visitor(Deserializer); if (auto EC = Visitor.visitTypeRecord(Record)) return EC; @@ -674,7 +708,9 @@ Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) { Error CVTypeDumper::dump(const CVTypeArray &Types) { assert(W && "printer should not be null"); - CVTypeVisitor Visitor(*this); + TypeDeserializer Deserializer(*this); + CVTypeVisitor Visitor(Deserializer); + if (auto EC = Visitor.visitTypeStream(Types)) return EC; return Error::success(); diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp index 4bbd2616bb5..e630be87345 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp @@ -114,6 +114,11 @@ NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { return NestedTypeRecord(L->Type, Name); } +Expected<FieldListRecord> +FieldListRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { + return FieldListRecord(Data); +} + Expected<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { const Layout *L = nullptr; diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 8c2bc072cd9..58c8c3fecb4 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" @@ -58,7 +59,8 @@ public: /// TypeVisitorCallbacks overrides. #define TYPE_RECORD(EnumName, EnumVal, Name) \ - Error visit##Name(Name##Record &Record) override; + Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \ + Name##Record &Record) override; #define MEMBER_RECORD(EnumName, EnumVal, Name) \ TYPE_RECORD(EnumName, EnumVal, Name) #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) @@ -70,11 +72,28 @@ public: Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override; Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override; - Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) override; - bool mergeStream(const CVTypeArray &Types); private: + template <typename RecordType> + Error visitKnownRecordImpl(RecordType &Record) { + FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); + IndexMap.push_back(DestStream.writeKnownType(Record)); + return Error::success(); + } + + Error visitKnownRecordImpl(FieldListRecord &Record) { + // Don't do anything, this will get written in the call to visitTypeEnd(). + return Error::success(); + } + + template <typename RecordType> + Error visitKnownMemberRecordImpl(RecordType &Record) { + FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); + FieldBuilder.writeMemberType(Record); + return Error::success(); + } + bool hadError() { return FoundBadTypeIndex; } bool FoundBadTypeIndex = false; @@ -93,33 +112,31 @@ private: } // end anonymous namespace Error TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) { - BeginIndexMapSize = IndexMap.size(); + if (Rec.Type != TypeLeafKind::LF_FIELDLIST) + BeginIndexMapSize = IndexMap.size(); return Error::success(); } Error TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) { - assert(IndexMap.size() == BeginIndexMapSize + 1); - return Error::success(); -} - -Error TypeStreamMerger::visitFieldListEnd(const CVRecord<TypeLeafKind> &Rec) { - IndexMap.push_back(DestStream.writeFieldList(FieldBuilder)); - FieldBuilder.reset(); + if (Rec.Type == TypeLeafKind::LF_FIELDLIST) { + IndexMap.push_back(DestStream.writeFieldList(FieldBuilder)); + FieldBuilder.reset(); + } else { + assert(IndexMap.size() == BeginIndexMapSize + 1); + } return Error::success(); } #define TYPE_RECORD(EnumName, EnumVal, Name) \ - Error TypeStreamMerger::visit##Name(Name##Record &Record) { \ - FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ - IndexMap.push_back(DestStream.write##Name(Record)); \ - return Error::success(); \ + Error TypeStreamMerger::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \ + Name##Record &Record) { \ + return visitKnownRecordImpl(Record); \ } #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #define MEMBER_RECORD(EnumName, EnumVal, Name) \ - Error TypeStreamMerger::visit##Name(Name##Record &Record) { \ - FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ - FieldBuilder.write##Name(Record); \ - return Error::success(); \ + Error TypeStreamMerger::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \ + Name##Record &Record) { \ + return visitKnownMemberRecordImpl(Record); \ } #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "llvm/DebugInfo/CodeView/TypeRecords.def" @@ -133,7 +150,9 @@ Error TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) { bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) { assert(IndexMap.empty()); - CVTypeVisitor Visitor(*this); + TypeDeserializer Deserializer(*this); + CVTypeVisitor Visitor(Deserializer); + if (auto EC = Visitor.visitTypeStream(Types)) { consumeError(std::move(EC)); return false; diff --git a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp index 647538ee8ce..0fcf4f92d43 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp @@ -21,7 +21,7 @@ TypeTableBuilder::TypeTableBuilder() {} TypeTableBuilder::~TypeTableBuilder() {} -TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const ModifierRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getModifiedType()); @@ -30,7 +30,7 @@ TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const ProcedureRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getReturnType()); @@ -42,8 +42,7 @@ TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) { return writeRecord(Builder); } -TypeIndex -TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const MemberFunctionRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getReturnType()); @@ -58,7 +57,7 @@ TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeArgList(const ArgListRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const ArgListRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeUInt32(Record.getIndices().size()); @@ -69,7 +68,7 @@ TypeIndex TypeTableBuilder::writeArgList(const ArgListRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const PointerRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getReferentType()); @@ -90,7 +89,7 @@ TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const ArrayRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getElementType()); @@ -101,7 +100,7 @@ TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const ClassRecord &Record) { assert((Record.getKind() == TypeRecordKind::Struct) || (Record.getKind() == TypeRecordKind::Class) || (Record.getKind() == TypeRecordKind::Interface)); @@ -128,7 +127,7 @@ TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeUnion(const UnionRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const UnionRecord &Record) { TypeRecordBuilder Builder(TypeRecordKind::Union); Builder.writeUInt16(Record.getMemberCount()); uint16_t Flags = @@ -145,7 +144,7 @@ TypeIndex TypeTableBuilder::writeUnion(const UnionRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const EnumRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeUInt16(Record.getMemberCount()); @@ -161,7 +160,7 @@ TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const BitFieldRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getType()); @@ -171,8 +170,7 @@ TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) { return writeRecord(Builder); } -TypeIndex -TypeTableBuilder::writeVFTableShape(const VFTableShapeRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const VFTableShapeRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); ArrayRef<VFTableSlotKind> Slots = Record.getSlots(); @@ -189,8 +187,7 @@ TypeTableBuilder::writeVFTableShape(const VFTableShapeRecord &Record) { return writeRecord(Builder); } -TypeIndex -TypeTableBuilder::writeVFTable(const VFTableRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const VFTableRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getCompleteClass()); Builder.writeTypeIndex(Record.getOverriddenVTable()); @@ -209,15 +206,14 @@ TypeTableBuilder::writeVFTable(const VFTableRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeStringId(const StringIdRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const StringIdRecord &Record) { TypeRecordBuilder Builder(TypeRecordKind::StringId); Builder.writeTypeIndex(Record.getId()); Builder.writeNullTerminatedString(Record.getString()); return writeRecord(Builder); } -TypeIndex -TypeTableBuilder::writeUdtSourceLine(const UdtSourceLineRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const UdtSourceLineRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getUDT()); Builder.writeTypeIndex(Record.getSourceFile()); @@ -226,7 +222,7 @@ TypeTableBuilder::writeUdtSourceLine(const UdtSourceLineRecord &Record) { } TypeIndex -TypeTableBuilder::writeUdtModSourceLine(const UdtModSourceLineRecord &Record) { +TypeTableBuilder::writeKnownType(const UdtModSourceLineRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getUDT()); Builder.writeTypeIndex(Record.getSourceFile()); @@ -235,7 +231,7 @@ TypeTableBuilder::writeUdtModSourceLine(const UdtModSourceLineRecord &Record) { return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeFuncId(const FuncIdRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const FuncIdRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getParentScope()); Builder.writeTypeIndex(Record.getFunctionType()); @@ -243,8 +239,7 @@ TypeIndex TypeTableBuilder::writeFuncId(const FuncIdRecord &Record) { return writeRecord(Builder); } -TypeIndex -TypeTableBuilder::writeMemberFuncId(const MemberFuncIdRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const MemberFuncIdRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeTypeIndex(Record.getClassType()); Builder.writeTypeIndex(Record.getFunctionType()); @@ -252,8 +247,7 @@ TypeTableBuilder::writeMemberFuncId(const MemberFuncIdRecord &Record) { return writeRecord(Builder); } -TypeIndex -TypeTableBuilder::writeBuildInfo(const BuildInfoRecord &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const BuildInfoRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); assert(Record.getArgs().size() <= UINT16_MAX); Builder.writeUInt16(Record.getArgs().size()); @@ -270,8 +264,8 @@ TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) { return FieldList.writeListRecord(*this); } -TypeIndex TypeTableBuilder::writeMethodOverloadList( - const MethodOverloadListRecord &Record) { +TypeIndex +TypeTableBuilder::writeKnownType(const MethodOverloadListRecord &Record) { TypeRecordBuilder Builder(Record.getKind()); for (const OneMethodRecord &Method : Record.getMethods()) { uint16_t Flags = static_cast<uint16_t>(Method.getAccess()); @@ -294,7 +288,7 @@ TypeIndex TypeTableBuilder::writeMethodOverloadList( return writeRecord(Builder); } -TypeIndex TypeTableBuilder::writeTypeServer2(const TypeServer2Record &Record) { +TypeIndex TypeTableBuilder::writeKnownType(const TypeServer2Record &Record) { TypeRecordBuilder Builder(Record.getKind()); Builder.writeGuid(Record.getGuid()); Builder.writeUInt32(Record.getAge()); diff --git a/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp index 1398628f231..424ef0ef441 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp @@ -11,6 +11,7 @@ #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" @@ -96,17 +97,28 @@ public: uint32_t NumHashBuckets) : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {} - Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override { + Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + UdtSourceLineRecord &Rec) override { return verifySourceLine(Rec); } - Error visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override { + Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + UdtModSourceLineRecord &Rec) override { return verifySourceLine(Rec); } - Error visitClass(ClassRecord &Rec) override { return verify(Rec); } - Error visitEnum(EnumRecord &Rec) override { return verify(Rec); } - Error visitUnion(UnionRecord &Rec) override { return verify(Rec); } + Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + ClassRecord &Rec) override { + return verify(Rec); + } + Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + EnumRecord &Rec) override { + return verify(Rec); + } + Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, + UnionRecord &Rec) override { + return verify(Rec); + } Error visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) override { ++Index; @@ -148,7 +160,8 @@ private: // Currently we only verify SRC_LINE records. Error TpiStream::verifyHashValues() { TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets); - CVTypeVisitor Visitor(Verifier); + TypeDeserializer Deserializer(Verifier); + CVTypeVisitor Visitor(Deserializer); return Visitor.visitTypeStream(TypeRecords); } |