#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
/// Visits the type records in Data. Sets the error flag on parse failures.
Error visitTypeStream(const CVTypeArray &Types);
- Error skipPadding(ArrayRef<uint8_t> &Data);
-
- /// Visits individual member records of a field list record. Member records do
- /// not describe their own length, and need special handling.
- Error visitFieldList(const CVRecord<TypeLeafKind> &Record);
-
private:
/// The interface to the class that gets notified of each visitation.
TypeVisitorCallbacks &Callbacks;
enum class TypeRecordKind : uint16_t {
#define TYPE_RECORD(lf_ename, value, name) name = value,
#include "TypeRecords.def"
- // FIXME: Add serialization support
- FieldList = 0x1203,
};
/// Duplicate copy of the above enum, but using the official CV names. Useful
insufficient_buffer,
operation_unsupported,
corrupt_record,
+ unknown_member_record,
};
/// Base class for errors originating when parsing raw PDB files
void reset() { ListRecordBuilder::reset(); }
- void writeBaseClass(const BaseClassRecord &Record);
- void writeEnumerator(const EnumeratorRecord &Record);
- void writeDataMember(const DataMemberRecord &Record);
- void writeOneMethod(const OneMethodRecord &Record);
- void writeOverloadedMethod(const OverloadedMethodRecord &Record);
- void writeNestedType(const NestedTypeRecord &Record);
- void writeStaticDataMember(const StaticDataMemberRecord &Record);
- void writeVirtualBaseClass(const VirtualBaseClassRecord &Record);
- void writeVFPtr(const VFPtrRecord &Type);
+ void writeMemberType(const BaseClassRecord &Record);
+ void writeMemberType(const EnumeratorRecord &Record);
+ void writeMemberType(const DataMemberRecord &Record);
+ void writeMemberType(const OneMethodRecord &Record);
+ void writeMemberType(const OverloadedMethodRecord &Record);
+ void writeMemberType(const NestedTypeRecord &Record);
+ void writeMemberType(const StaticDataMemberRecord &Record);
+ void writeMemberType(const VirtualBaseClassRecord &Record);
+ void writeMemberType(const VFPtrRecord &Type);
+
+ using ListRecordBuilder::writeMemberType;
};
}
}
SubrecordStart = 0;
}
- void writeListContinuation(const ListContinuationRecord &R);
+ void writeMemberType(const ListContinuationRecord &R);
/// Writes this list record as a possible sequence of records.
TypeIndex writeListRecord(TypeTableBuilder &Table);
if (Data.size() < sizeof(*Res))
return make_error<CodeViewError>(
cv_error_code::insufficient_buffer,
- "Error consuming object. Not enough data for requested object size.");
+ "Insufficient bytes for expected object type");
Res = reinterpret_cast<const T *>(Data.data());
Data = Data.drop_front(sizeof(*Res));
return Error::success();
Error deserialize(ArrayRef<uint8_t> &Data) const {
if (Data.empty())
- return make_error<CodeViewError>(
- cv_error_code::insufficient_buffer,
- "Null terminated string buffer is empty!");
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer,
+ "Null terminated string is empty!");
StringRef Field;
// Stop when we run out of bytes or we hit record padding bytes.
if (Data.empty())
return make_error<CodeViewError>(
cv_error_code::insufficient_buffer,
- "Null terminated string buffer is empty!");
+ "Null terminated string has no null terminator!");
}
Data = Data.drop_front(1);
return Error::success();
--- /dev/null
+//===- TypeDeserializer.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_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
+
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+class TypeDeserializerBase : public TypeVisitorCallbacks {
+public:
+ explicit TypeDeserializerBase(TypeVisitorCallbacks &Recipient)
+ : Recipient(Recipient) {}
+
+ Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override {
+ return Recipient.visitTypeBegin(Record);
+ }
+
+ Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override {
+ return Recipient.visitTypeEnd(Record);
+ }
+
+#define TYPE_RECORD(EnumName, EnumVal, Name) \
+ Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \
+ Name##Record &Record) override { \
+ return defaultVisitKnownRecord(CVR, Record); \
+ }
+#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 "TypeRecords.def"
+
+protected:
+ TypeVisitorCallbacks &Recipient;
+
+ template <typename T>
+ Error deserializeRecord(ArrayRef<uint8_t> &Data, TypeLeafKind Kind,
+ T &Record) const {
+ TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
+ auto ExpectedRecord = T::deserialize(RK, Data);
+ if (!ExpectedRecord)
+ return ExpectedRecord.takeError();
+ Record = std::move(*ExpectedRecord);
+ return Error::success();
+ }
+
+private:
+ template <typename T>
+ Error defaultVisitKnownRecord(const CVRecord<TypeLeafKind> &CVR, T &Record) {
+ ArrayRef<uint8_t> RD = CVR.Data;
+ if (auto EC = deserializeRecord(RD, CVR.Type, Record))
+ return EC;
+ 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<TypeLeafKind> &CVR,
+ FieldListRecord &Record) override;
+
+private:
+ template <typename T>
+ Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Kind,
+ T &Record) {
+ ArrayRef<uint8_t> OldData = Data;
+ if (auto EC = deserializeRecord(Data, Kind, Record))
+ return EC;
+ assert(Data.size() < OldData.size());
+
+ CVRecord<TypeLeafKind> 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<uint8_t> &Data);
+};
+}
+}
+
+#endif
Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
#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)
// LF_MODIFIER
class ModifierRecord : public TypeRecord {
public:
+ explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
: TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
Modifiers(Modifiers) {}
// LF_PROCEDURE
class ProcedureRecord : public TypeRecord {
public:
+ explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
FunctionOptions Options, uint16_t ParameterCount,
TypeIndex ArgumentList)
// LF_MFUNCTION
class MemberFunctionRecord : public TypeRecord {
public:
+ explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
TypeIndex ThisType, CallingConvention CallConv,
FunctionOptions Options, uint16_t ParameterCount,
// LF_MFUNC_ID
class MemberFuncIdRecord : public TypeRecord {
public:
+ explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
StringRef Name)
: TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType),
// LF_ARGLIST, LF_SUBSTR_LIST
class ArgListRecord : public TypeRecord {
public:
+ explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
: TypeRecord(Kind), StringIndices(Indices) {}
static const uint32_t PointerSizeShift = 13;
static const uint32_t PointerSizeMask = 0xFF;
+ explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
PointerOptions Options, uint8_t Size)
: PointerRecord(ReferentType, Kind, Mode, Options, Size,
// LF_NESTTYPE
class NestedTypeRecord : public TypeRecord {
public:
+ explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
NestedTypeRecord(TypeIndex Type, StringRef Name)
: TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
StringRef Name;
};
+// LF_FIELDLIST
+class FieldListRecord : public TypeRecord {
+public:
+ explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+ FieldListRecord(ArrayRef<uint8_t> ListData)
+ : TypeRecord(TypeRecordKind::FieldList), ListData(ListData) {}
+
+ /// Rewrite member type indices with IndexMap. Returns false if a type index
+ /// is not in the map.
+ bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { return false; }
+
+ static Expected<FieldListRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data);
+
+ ArrayRef<uint8_t> getFieldListData() const { return ListData; }
+
+private:
+ ArrayRef<uint8_t> ListData;
+};
+
// LF_ARRAY
class ArrayRecord : public TypeRecord {
public:
+ explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
StringRef Name)
: TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
class TagRecord : public TypeRecord {
protected:
+ explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
TypeIndex FieldList, StringRef Name, StringRef UniqueName)
: TypeRecord(Kind), MemberCount(MemberCount), Options(Options),
// LF_CLASS, LF_STRUCTURE, LF_INTERFACE
class ClassRecord : public TagRecord {
public:
+ explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
HfaKind Hfa, WindowsRTClassKind WinRTKind, TypeIndex FieldList,
TypeIndex DerivationList, TypeIndex VTableShape, uint64_t Size,
// LF_UNION
struct UnionRecord : public TagRecord {
+ explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
UnionRecord(uint16_t MemberCount, ClassOptions Options, HfaKind Hfa,
TypeIndex FieldList, uint64_t Size, StringRef Name,
StringRef UniqueName)
// LF_ENUM
class EnumRecord : public TagRecord {
public:
+ explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
: TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name,
// LF_BITFIELD
class BitFieldRecord : public TypeRecord {
public:
+ explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
: TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
BitOffset(BitOffset) {}
// LF_VTSHAPE
class VFTableShapeRecord : public TypeRecord {
public:
+ explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)
: TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)
// LF_TYPESERVER2
class TypeServer2Record : public TypeRecord {
public:
+ explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {}
TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name)
: TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age),
Name(Name) {}
// LF_STRING_ID
class StringIdRecord : public TypeRecord {
public:
+ explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StringIdRecord(TypeIndex Id, StringRef String)
: TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
// LF_FUNC_ID
class FuncIdRecord : public TypeRecord {
public:
+ explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
: TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
FunctionType(FunctionType), Name(Name) {}
// LF_UDT_SRC_LINE
class UdtSourceLineRecord : public TypeRecord {
public:
+ explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
: TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
SourceFile(SourceFile), LineNumber(LineNumber) {}
// LF_UDT_MOD_SRC_LINE
class UdtModSourceLineRecord : public TypeRecord {
public:
+ explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile,
uint32_t LineNumber, uint16_t Module)
: TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
// LF_BUILDINFO
class BuildInfoRecord : public TypeRecord {
public:
+ explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
: TypeRecord(TypeRecordKind::BuildInfo),
ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
// LF_VFTABLE
class VFTableRecord : public TypeRecord {
public:
+ explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
uint32_t VFPtrOffset, StringRef Name,
ArrayRef<StringRef> Methods)
// LF_ONEMETHOD
class OneMethodRecord : public TypeRecord {
public:
+ explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
OneMethodRecord(TypeIndex Type, MethodKind Kind, MethodOptions Options,
MemberAccess Access, int32_t VFTableOffset, StringRef Name)
: TypeRecord(TypeRecordKind::OneMethod), Type(Type), Kind(Kind),
// LF_METHODLIST
class MethodOverloadListRecord : public TypeRecord {
public:
+ explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)
: TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
/// For method overload sets. LF_METHOD
class OverloadedMethodRecord : public TypeRecord {
public:
+ explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
StringRef Name)
: TypeRecord(TypeRecordKind::OverloadedMethod),
// LF_MEMBER
class DataMemberRecord : public TypeRecord {
public:
+ explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset,
StringRef Name)
: TypeRecord(TypeRecordKind::DataMember), Access(Access), Type(Type),
// LF_STMEMBER
class StaticDataMemberRecord : public TypeRecord {
public:
+ explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name)
: TypeRecord(TypeRecordKind::StaticDataMember), Access(Access),
Type(Type), Name(Name) {}
// LF_ENUMERATE
class EnumeratorRecord : public TypeRecord {
public:
+ explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name)
: TypeRecord(TypeRecordKind::Enumerator), Access(Access),
Value(std::move(Value)), Name(Name) {}
// LF_VFUNCTAB
class VFPtrRecord : public TypeRecord {
public:
+ explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VFPtrRecord(TypeIndex Type)
: TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
// LF_BCLASS, LF_BINTERFACE
class BaseClassRecord : public TypeRecord {
public:
+ explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset)
: TypeRecord(TypeRecordKind::BaseClass), Access(Access), Type(Type),
Offset(Offset) {}
// LF_VBCLASS, LF_IVBCLASS
class VirtualBaseClassRecord : public TypeRecord {
public:
+ explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VirtualBaseClassRecord(MemberAccess Access, TypeIndex BaseType,
TypeIndex VBPtrType, uint64_t Offset, uint64_t Index)
: TypeRecord(TypeRecordKind::VirtualBaseClass), Access(Access),
/// together. The first will end in an LF_INDEX record that points to the next.
class ListContinuationRecord : public TypeRecord {
public:
+ explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ListContinuationRecord(TypeIndex ContinuationIndex)
: TypeRecord(TypeRecordKind::ListContinuation),
ContinuationIndex(ContinuationIndex) {}
TYPE_RECORD(LF_MFUNCTION, 0x1009, MemberFunction)
TYPE_RECORD(LF_ARGLIST, 0x1201, ArgList)
+TYPE_RECORD(LF_FIELDLIST, 0x1203, FieldList)
+
TYPE_RECORD(LF_ARRAY, 0x1503, Array)
TYPE_RECORD(LF_CLASS, 0x1504, Class)
TYPE_RECORD_ALIAS(LF_STRUCTURE, 0x1505, Struct, Class)
CV_TYPE(LF_SKIP, 0x1200)
CV_TYPE(LF_DEFARG_ST, 0x1202)
-CV_TYPE(LF_FIELDLIST, 0x1203)
CV_TYPE(LF_DERIVED, 0x1204)
CV_TYPE(LF_DIMCONU, 0x1207)
CV_TYPE(LF_DIMCONLU, 0x1208)
virtual ~TypeTableBuilder();
public:
- TypeIndex writeModifier(const ModifierRecord &Record);
- TypeIndex writeProcedure(const ProcedureRecord &Record);
- TypeIndex writeMemberFunction(const MemberFunctionRecord &Record);
- TypeIndex writeArgList(const ArgListRecord &Record);
- TypeIndex writePointer(const PointerRecord &Record);
- TypeIndex writeArray(const ArrayRecord &Record);
- TypeIndex writeClass(const ClassRecord &Record);
- TypeIndex writeUnion(const UnionRecord &Record);
- TypeIndex writeEnum(const EnumRecord &Record);
- TypeIndex writeBitField(const BitFieldRecord &Record);
- TypeIndex writeVFTableShape(const VFTableShapeRecord &Record);
- TypeIndex writeStringId(const StringIdRecord &Record);
- TypeIndex writeVFTable(const VFTableRecord &Record);
- TypeIndex writeUdtSourceLine(const UdtSourceLineRecord &Record);
- TypeIndex writeUdtModSourceLine(const UdtModSourceLineRecord &Record);
- TypeIndex writeFuncId(const FuncIdRecord &Record);
- TypeIndex writeMemberFuncId(const MemberFuncIdRecord &Record);
- TypeIndex writeBuildInfo(const BuildInfoRecord &Record);
- TypeIndex writeMethodOverloadList(const MethodOverloadListRecord &Record);
- TypeIndex writeTypeServer2(const TypeServer2Record &Record);
+ TypeIndex writeKnownType(const ModifierRecord &Record);
+ TypeIndex writeKnownType(const ProcedureRecord &Record);
+ TypeIndex writeKnownType(const MemberFunctionRecord &Record);
+ TypeIndex writeKnownType(const ArgListRecord &Record);
+ TypeIndex writeKnownType(const PointerRecord &Record);
+ TypeIndex writeKnownType(const ArrayRecord &Record);
+ TypeIndex writeKnownType(const ClassRecord &Record);
+ TypeIndex writeKnownType(const UnionRecord &Record);
+ TypeIndex writeKnownType(const EnumRecord &Record);
+ TypeIndex writeKnownType(const BitFieldRecord &Record);
+ TypeIndex writeKnownType(const VFTableShapeRecord &Record);
+ TypeIndex writeKnownType(const StringIdRecord &Record);
+ TypeIndex writeKnownType(const VFTableRecord &Record);
+ TypeIndex writeKnownType(const UdtSourceLineRecord &Record);
+ TypeIndex writeKnownType(const UdtModSourceLineRecord &Record);
+ TypeIndex writeKnownType(const FuncIdRecord &Record);
+ TypeIndex writeKnownType(const MemberFuncIdRecord &Record);
+ TypeIndex writeKnownType(const BuildInfoRecord &Record);
+ TypeIndex writeKnownType(const MethodOverloadListRecord &Record);
+ TypeIndex writeKnownType(const TypeServer2Record &Record);
TypeIndex writeFieldList(FieldListRecordBuilder &FieldList);
return Error::success();
}
- virtual Error visitFieldListBegin(const CVRecord<TypeLeafKind> &Record) {
- return Error::success();
- }
-
- virtual Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) {
- return Error::success();
- }
-
#define TYPE_RECORD(EnumName, EnumVal, Name) \
- virtual Error visit##Name(Name##Record &Record) { return Error::success(); }
+ virtual Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR, \
+ Name##Record &Record) { \
+ return Error::success(); \
+ }
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
TYPE_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
// 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);
}
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);
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));
}
// do.
PointerOptions PO = PointerOptions::None;
PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8);
- return TypeTable.writePointer(PR);
+ return TypeTable.writeKnownType(PR);
}
static PointerToMemberRepresentation
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
return I->second;
ModifierRecord MR(ModifiedTI, Mods);
- return TypeTable.writeModifier(MR);
+ return TypeTable.writeKnownType(MR);
}
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,
}
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));
// 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++;
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())));
}
//===----------------------------------------------------------------------===//
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())
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()));
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;
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()));
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));
}
translateAccessFlags(Ty->getTag(), Member->getFlags());
if (Member->isStaticMember()) {
- Fields.writeStaticDataMember(
+ Fields.writeMemberType(
StaticDataMemberRecord(Access, MemberBaseType, MemberName));
MemberCount++;
continue;
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++;
}
}
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));
}
}
// Create nested classes.
for (const DICompositeType *Nested : Info.NestedClasses) {
NestedTypeRecord R(getTypeIndex(DITypeRef(Nested)), Nested->getName());
- Fields.writeNestedType(R);
+ Fields.writeMemberType(R);
MemberCount++;
}
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;
PointerOptions PO = PointerOptions::None;
PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
- VBPType = TypeTable.writePointer(PR);
+ VBPType = TypeTable.writeKnownType(PR);
}
return VBPType;
ModuleSubstreamVisitor.cpp
RecordSerialization.cpp
SymbolDumper.cpp
+ TypeDeserializer.cpp
TypeDumper.cpp
TypeRecord.cpp
TypeRecordBuilder.cpp
//===----------------------------------------------------------------------===//
#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; \
}
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
+
if (auto EC = Callbacks.visitTypeEnd(Record))
return EC;
+
return Error::success();
}
}
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();
-}
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");
}
FieldListRecordBuilder::FieldListRecordBuilder()
: ListRecordBuilder(TypeRecordKind::FieldList) {}
-void FieldListRecordBuilder::writeBaseClass(const BaseClassRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const BaseClassRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(TypeRecordKind::BaseClass);
finishSubRecord();
}
-void FieldListRecordBuilder::writeEnumerator(const EnumeratorRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const EnumeratorRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(TypeRecordKind::Enumerator);
finishSubRecord();
}
-void FieldListRecordBuilder::writeDataMember(const DataMemberRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const DataMemberRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(Record.getKind());
finishSubRecord();
}
-void FieldListRecordBuilder::writeOverloadedMethod(
+void FieldListRecordBuilder::writeMemberType(
const OverloadedMethodRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
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());
finishSubRecord();
}
-void FieldListRecordBuilder::writeNestedType(const NestedTypeRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const NestedTypeRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(Record.getKind());
finishSubRecord();
}
-void FieldListRecordBuilder::writeStaticDataMember(
+void FieldListRecordBuilder::writeMemberType(
const StaticDataMemberRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
finishSubRecord();
}
-void FieldListRecordBuilder::writeVirtualBaseClass(
+void FieldListRecordBuilder::writeMemberType(
const VirtualBaseClassRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
finishSubRecord();
}
-void FieldListRecordBuilder::writeVFPtr(const VFPtrRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const VFPtrRecord &Record) {
TypeRecordBuilder &Builder = getBuilder();
Builder.writeTypeRecordKind(TypeRecordKind::VFPtr);
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");
--- /dev/null
+//===- 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();
+}
#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"
case ename: \
return #name;
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- case LF_FIELDLIST:
- return "FieldList";
default:
break;
}
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.
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);
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));
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));
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()),
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());
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());
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());
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));
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());
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());
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());
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());
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()),
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));
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());
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");
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());
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());
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());
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);
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);
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);
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);
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);
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();
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;
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();
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;
#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"
/// 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)
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;
} // 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"
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;
TypeTableBuilder::~TypeTableBuilder() {}
-TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ModifierRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getModifiedType());
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ProcedureRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getReturnType());
return writeRecord(Builder);
}
-TypeIndex
-TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const MemberFunctionRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getReturnType());
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeArgList(const ArgListRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ArgListRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeUInt32(Record.getIndices().size());
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const PointerRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getReferentType());
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ArrayRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getElementType());
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));
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 =
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const EnumRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeUInt16(Record.getMemberCount());
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const BitFieldRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getType());
return writeRecord(Builder);
}
-TypeIndex
-TypeTableBuilder::writeVFTableShape(const VFTableShapeRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const VFTableShapeRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
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());
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());
}
TypeIndex
-TypeTableBuilder::writeUdtModSourceLine(const UdtModSourceLineRecord &Record) {
+TypeTableBuilder::writeKnownType(const UdtModSourceLineRecord &Record) {
TypeRecordBuilder Builder(Record.getKind());
Builder.writeTypeIndex(Record.getUDT());
Builder.writeTypeIndex(Record.getSourceFile());
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());
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());
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());
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());
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());
#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"
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;
// 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);
}
}
LLVMOutputStyle::LLVMOutputStyle(PDBFile &File)
- : File(File), P(outs()), TD(&P, false) {}
+ : File(File), P(outs()), Dumper(&P, false) {}
Error LLVMOutputStyle::dump() {
if (auto EC = dumpFileHeaders())
DictScope DD(P, "");
if (DumpRecords) {
- if (auto EC = TD.dump(Type))
+ if (auto EC = Dumper.dump(Type))
return EC;
}
// iterate them in order to build the list of types so that we can print
// them when dumping module symbols. So when they want to dump symbols
// but not types, use a null output stream.
- ScopedPrinter *OldP = TD.getPrinter();
- TD.setPrinter(nullptr);
+ ScopedPrinter *OldP = Dumper.getPrinter();
+ Dumper.setPrinter(nullptr);
bool HadError = false;
for (auto &Type : Tpi->types(&HadError)) {
- if (auto EC = TD.dump(Type))
+ if (auto EC = Dumper.dump(Type))
return EC;
}
- TD.setPrinter(OldP);
+ Dumper.setPrinter(OldP);
dumpTpiHash(P, *Tpi);
if (HadError)
return make_error<RawError>(raw_error_code::corrupt_file,
if (ShouldDumpSymbols) {
ListScope SS(P, "Symbols");
- codeview::CVSymbolDumper SD(P, TD, nullptr, false);
+ codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
bool HadError = false;
for (const auto &S : ModS.symbols(&HadError)) {
DictScope DD(P, "");
P.printList("Section Offsets", Publics->getSectionOffsets(),
printSectionOffset);
ListScope L(P, "Symbols");
- codeview::CVSymbolDumper SD(P, TD, nullptr, false);
+ codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
bool HadError = false;
for (auto S : Publics->getSymbols(&HadError)) {
DictScope DD(P, "");
PDBFile &File;
ScopedPrinter P;
- codeview::CVTypeDumper TD;
+ codeview::CVTypeDumper Dumper;
};
}
}
exit(1);
}
-void error(llvm::Error EC) {
+void error(Error EC) {
if (!EC)
return;
-
handleAllErrors(std::move(EC),
- [&](ErrorInfoBase &EI) { reportError(EI.message()); });
+ [&](const ErrorInfoBase &EI) { reportError(EI.message()); });
}
void error(std::error_code EC) {
if (!EC)
return;
-
reportError(EC.message());
}
// Various helper functions.
LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
- void error(std::error_code ec);
+ void error(std::error_code EC);
void error(llvm::Error EC);
template <class T> T unwrapOrError(ErrorOr<T> EO) {
if (EO)