diff options
author | Zachary Turner <zturner@google.com> | 2016-06-16 18:09:04 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2016-06-16 18:09:04 +0000 |
commit | 73b0b2f55503e6b72e6525a115965a184e1a1dd7 (patch) | |
tree | 8496dfc19ffd91b805c68a4f0c32d193bab454aa /llvm/lib/DebugInfo | |
parent | 1f6372c429ce6b85a572c213d53f0ed8d293ff38 (diff) | |
download | llvm-73b0b2f55503e6b72e6525a115965a184e1a1dd7.zip llvm-73b0b2f55503e6b72e6525a115965a184e1a1dd7.tar.gz llvm-73b0b2f55503e6b72e6525a115965a184e1a1dd7.tar.bz2 |
Revert "[pdb] Change type visitor pattern to be dynamic."
This reverts commit fb0dd311e1ad945827b8ffd5354f4810e2be1579.
This breaks some llvm-readobj tests.
llvm-svn: 272927
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 119 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeDumper.cpp | 392 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp | 51 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/RawError.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp | 40 |
6 files changed, 247 insertions, 358 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 47297a9..4393f9c 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -1,7 +1,6 @@ add_llvm_library(LLVMDebugInfoCodeView ByteStream.cpp CodeViewError.cpp - CVTypeVisitor.cpp EnumTables.cpp FieldListRecordBuilder.cpp Line.cpp diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp deleted file mode 100644 index a22d963..0000000 --- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ /dev/null @@ -1,119 +0,0 @@ -//===- CVTypeVisitor.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/CVTypeVisitor.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(); -} - -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 = visitFieldList(Record)) - return EC; - break; -#define TYPE_RECORD(EnumName, EnumVal, Name) \ - case EnumName: { \ - TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName); \ - auto Result = Name##Record::deserialize(RK, LeafData); \ - if (Result.getError()) \ - return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); \ - if (auto EC = Callbacks.visit##Name(*Result)) \ - return EC; \ - break; \ - } -#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ - TYPE_RECORD(EnumVal, EnumVal, AliasName) -#define MEMBER_RECORD(EnumName, EnumVal, Name) -#include "llvm/DebugInfo/CodeView/TypeRecords.def" - } - if (auto EC = Callbacks.visitTypeEnd(Record)) - return EC; - return Error::success(); -} - -/// Visits the type records in Data. Sets the error flag on parse failures. -Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) { - for (const auto &I : Types) { - if (auto EC = visitTypeRecord(I)) - return EC; - } - 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 Result = Name##Record::deserialize(RK, RecordData); \ - if (Result.getError()) \ - return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); \ - if (auto EC = Callbacks.visit##Name(*Result)) \ - 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/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp index 0653d81..b181ffb 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp @@ -189,6 +189,55 @@ static const EnumEntry<uint8_t> FunctionOptionEnum[] = { #undef ENUM_ENTRY + +namespace { + +/// Use this private dumper implementation to keep implementation details about +/// the visitor out of TypeDumper.h. +class CVTypeDumperImpl : public CVTypeVisitor<CVTypeDumperImpl> { +public: + CVTypeDumperImpl(CVTypeDumper &CVTD, ScopedPrinter &W, bool PrintRecordBytes) + : CVTD(CVTD), W(W), PrintRecordBytes(PrintRecordBytes) {} + + /// CVTypeVisitor overrides. +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + void visit##Name(Name##Record &Record); +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + void visit##Name(Name##Record &Record); +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/TypeRecords.def" + + void visitUnknownMember(TypeLeafKind Leaf); + void visitUnknownType(const CVRecord<TypeLeafKind> &Record); + + void visitTypeBegin(const CVRecord<TypeLeafKind> &Record); + void visitTypeEnd(const CVRecord<TypeLeafKind> &Record); + + void printMemberAttributes(MemberAttributes Attrs); + void printMemberAttributes(MemberAccess Access, MethodKind Kind, + MethodOptions Options); + +private: + /// Forwards to the dumper, which holds the persistent state from visitation. + StringRef getTypeName(TypeIndex TI) { + return CVTD.getTypeName(TI); + } + + void printTypeIndex(StringRef FieldName, TypeIndex TI) { + CVTD.printTypeIndex(FieldName, TI); + } + + CVTypeDumper &CVTD; + ScopedPrinter &W; + bool PrintRecordBytes = false; + + /// Name of the current type. Only valid before visitTypeEnd. + StringRef Name; +}; + +} // end anonymous namespace + static StringRef getLeafTypeName(TypeLeafKind LT) { switch (LT) { #define TYPE_RECORD(ename, value, name) \ @@ -201,44 +250,39 @@ static StringRef getLeafTypeName(TypeLeafKind LT) { return "UnknownLeaf"; } -Error CVTypeDumper::visitTypeBegin(const CVRecord<TypeLeafKind> &Record) { +void CVTypeDumperImpl::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) { // Reset Name to the empty string. If the visitor sets it, we know it. Name = ""; - W->startLine() << getLeafTypeName(Record.Type) << " (" - << HexNumber(getNextTypeIndex()) << ") {\n"; - W->indent(); - W->printEnum("TypeLeafKind", unsigned(Record.Type), - makeArrayRef(LeafTypeNames)); - return Error::success(); + W.startLine() << getLeafTypeName(Rec.Type) << " (" + << HexNumber(CVTD.getNextTypeIndex()) << ") {\n"; + W.indent(); + W.printEnum("TypeLeafKind", unsigned(Rec.Type), makeArrayRef(LeafTypeNames)); } -Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) { +void CVTypeDumperImpl::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) { // Always record some name for every type, even if Name is empty. CVUDTNames // is indexed by type index, and must have one entry for every type. - recordType(Name); - + CVTD.recordType(Name); if (PrintRecordBytes) - W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data)); + W.printBinaryBlock("LeafData", getBytesAsCharacters(Rec.Data)); - W->unindent(); - W->startLine() << "}\n"; - return Error::success(); + W.unindent(); + W.startLine() << "}\n"; } -Error CVTypeDumper::visitStringId(StringIdRecord &String) { +void CVTypeDumperImpl::visitStringId(StringIdRecord &String) { printTypeIndex("Id", String.getId()); - W->printString("StringData", String.getString()); + W.printString("StringData", String.getString()); // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE. Name = String.getString(); - return Error::success(); } -Error CVTypeDumper::visitArgList(ArgListRecord &Args) { +void CVTypeDumperImpl::visitArgList(ArgListRecord &Args) { auto Indices = Args.getIndices(); uint32_t Size = Indices.size(); - W->printNumber("NumArgs", Size); - ListScope Arguments(*W, "Arguments"); + W.printNumber("NumArgs", Size); + ListScope Arguments(W, "Arguments"); SmallString<256> TypeName("("); for (uint32_t I = 0; I < Size; ++I) { printTypeIndex("ArgType", Indices[I]); @@ -248,84 +292,77 @@ Error CVTypeDumper::visitArgList(ArgListRecord &Args) { TypeName.append(", "); } TypeName.push_back(')'); - Name = saveName(TypeName); - return Error::success(); + Name = CVTD.saveName(TypeName); } -Error CVTypeDumper::visitClass(ClassRecord &Class) { +void CVTypeDumperImpl::visitClass(ClassRecord &Class) { uint16_t Props = static_cast<uint16_t>(Class.getOptions()); - W->printNumber("MemberCount", Class.getMemberCount()); - W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); + W.printNumber("MemberCount", Class.getMemberCount()); + W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); printTypeIndex("FieldList", Class.getFieldList()); printTypeIndex("DerivedFrom", Class.getDerivationList()); printTypeIndex("VShape", Class.getVTableShape()); - W->printNumber("SizeOf", Class.getSize()); - W->printString("Name", Class.getName()); + W.printNumber("SizeOf", Class.getSize()); + W.printString("Name", Class.getName()); if (Props & uint16_t(ClassOptions::HasUniqueName)) - W->printString("LinkageName", Class.getUniqueName()); + W.printString("LinkageName", Class.getUniqueName()); Name = Class.getName(); - return Error::success(); } -Error CVTypeDumper::visitUnion(UnionRecord &Union) { +void CVTypeDumperImpl::visitUnion(UnionRecord &Union) { uint16_t Props = static_cast<uint16_t>(Union.getOptions()); - W->printNumber("MemberCount", Union.getMemberCount()); - W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); + W.printNumber("MemberCount", Union.getMemberCount()); + W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames)); printTypeIndex("FieldList", Union.getFieldList()); - W->printNumber("SizeOf", Union.getSize()); - W->printString("Name", Union.getName()); + W.printNumber("SizeOf", Union.getSize()); + W.printString("Name", Union.getName()); if (Props & uint16_t(ClassOptions::HasUniqueName)) - W->printString("LinkageName", Union.getUniqueName()); + W.printString("LinkageName", Union.getUniqueName()); Name = Union.getName(); - return Error::success(); } -Error CVTypeDumper::visitEnum(EnumRecord &Enum) { - W->printNumber("NumEnumerators", Enum.getMemberCount()); - W->printFlags("Properties", uint16_t(Enum.getOptions()), - makeArrayRef(ClassOptionNames)); +void CVTypeDumperImpl::visitEnum(EnumRecord &Enum) { + W.printNumber("NumEnumerators", Enum.getMemberCount()); + W.printFlags("Properties", uint16_t(Enum.getOptions()), + makeArrayRef(ClassOptionNames)); printTypeIndex("UnderlyingType", Enum.getUnderlyingType()); printTypeIndex("FieldListType", Enum.getFieldList()); - W->printString("Name", Enum.getName()); + W.printString("Name", Enum.getName()); Name = Enum.getName(); - return Error::success(); } -Error CVTypeDumper::visitArray(ArrayRecord &AT) { +void CVTypeDumperImpl::visitArray(ArrayRecord &AT) { printTypeIndex("ElementType", AT.getElementType()); printTypeIndex("IndexType", AT.getIndexType()); - W->printNumber("SizeOf", AT.getSize()); - W->printString("Name", AT.getName()); + W.printNumber("SizeOf", AT.getSize()); + W.printString("Name", AT.getName()); Name = AT.getName(); - return Error::success(); } -Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) { +void CVTypeDumperImpl::visitVFTable(VFTableRecord &VFT) { printTypeIndex("CompleteClass", VFT.getCompleteClass()); printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable()); - W->printHex("VFPtrOffset", VFT.getVFPtrOffset()); - W->printString("VFTableName", VFT.getName()); + W.printHex("VFPtrOffset", VFT.getVFPtrOffset()); + W.printString("VFTableName", VFT.getName()); for (auto N : VFT.getMethodNames()) - W->printString("MethodName", N); + W.printString("MethodName", N); Name = VFT.getName(); - return Error::success(); } -Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) { +void CVTypeDumperImpl::visitMemberFuncId(MemberFuncIdRecord &Id) { printTypeIndex("ClassType", Id.getClassType()); printTypeIndex("FunctionType", Id.getFunctionType()); - W->printString("Name", Id.getName()); + W.printString("Name", Id.getName()); Name = Id.getName(); - return Error::success(); } -Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) { +void CVTypeDumperImpl::visitProcedure(ProcedureRecord &Proc) { printTypeIndex("ReturnType", Proc.getReturnType()); - W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()), - makeArrayRef(CallingConventions)); - W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()), - makeArrayRef(FunctionOptionEnum)); - W->printNumber("NumParameters", Proc.getParameterCount()); + W.printEnum("CallingConvention", uint8_t(Proc.getCallConv()), + makeArrayRef(CallingConventions)); + W.printFlags("FunctionOptions", uint8_t(Proc.getOptions()), + makeArrayRef(FunctionOptionEnum)); + W.printNumber("NumParameters", Proc.getParameterCount()); printTypeIndex("ArgListType", Proc.getArgumentList()); StringRef ReturnTypeName = getTypeName(Proc.getReturnType()); @@ -333,21 +370,20 @@ Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) { SmallString<256> TypeName(ReturnTypeName); TypeName.push_back(' '); TypeName.append(ArgListTypeName); - Name = saveName(TypeName); - return Error::success(); + Name = CVTD.saveName(TypeName); } -Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) { +void CVTypeDumperImpl::visitMemberFunction(MemberFunctionRecord &MF) { printTypeIndex("ReturnType", MF.getReturnType()); printTypeIndex("ClassType", MF.getClassType()); printTypeIndex("ThisType", MF.getThisType()); - W->printEnum("CallingConvention", uint8_t(MF.getCallConv()), - makeArrayRef(CallingConventions)); - W->printFlags("FunctionOptions", uint8_t(MF.getOptions()), - makeArrayRef(FunctionOptionEnum)); - W->printNumber("NumParameters", MF.getParameterCount()); + W.printEnum("CallingConvention", uint8_t(MF.getCallConv()), + makeArrayRef(CallingConventions)); + W.printFlags("FunctionOptions", uint8_t(MF.getOptions()), + makeArrayRef(FunctionOptionEnum)); + W.printNumber("NumParameters", MF.getParameterCount()); printTypeIndex("ArgListType", MF.getArgumentList()); - W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment()); + W.printNumber("ThisAdjustment", MF.getThisPointerAdjustment()); StringRef ReturnTypeName = getTypeName(MF.getReturnType()); StringRef ClassTypeName = getTypeName(MF.getClassType()); @@ -357,56 +393,52 @@ Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) { TypeName.append(ClassTypeName); TypeName.append("::"); TypeName.append(ArgListTypeName); - Name = saveName(TypeName); - return Error::success(); + Name = CVTD.saveName(TypeName); } -Error CVTypeDumper::visitMethodOverloadList( +void CVTypeDumperImpl::visitMethodOverloadList( MethodOverloadListRecord &MethodList) { for (auto &M : MethodList.getMethods()) { - ListScope S(*W, "Method"); + ListScope S(W, "Method"); printMemberAttributes(M.getAccess(), M.getKind(), M.getOptions()); printTypeIndex("Type", M.getType()); if (M.isIntroducingVirtual()) - W->printHex("VFTableOffset", M.getVFTableOffset()); + W.printHex("VFTableOffset", M.getVFTableOffset()); } - return Error::success(); } -Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) { +void CVTypeDumperImpl::visitFuncId(FuncIdRecord &Func) { printTypeIndex("ParentScope", Func.getParentScope()); printTypeIndex("FunctionType", Func.getFunctionType()); - W->printString("Name", Func.getName()); + W.printString("Name", Func.getName()); Name = Func.getName(); - return Error::success(); } -Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) { - W->printBinary("Signature", TS.getGuid()); - W->printNumber("Age", TS.getAge()); - W->printString("Name", TS.getName()); +void CVTypeDumperImpl::visitTypeServer2(TypeServer2Record &TS) { + W.printBinary("Signature", TS.getGuid()); + W.printNumber("Age", TS.getAge()); + W.printString("Name", TS.getName()); Name = TS.getName(); - return Error::success(); } -Error CVTypeDumper::visitPointer(PointerRecord &Ptr) { +void CVTypeDumperImpl::visitPointer(PointerRecord &Ptr) { printTypeIndex("PointeeType", Ptr.getReferentType()); - W->printHex("PointerAttributes", uint32_t(Ptr.getOptions())); - W->printEnum("PtrType", unsigned(Ptr.getPointerKind()), - makeArrayRef(PtrKindNames)); - W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames)); + W.printHex("PointerAttributes", uint32_t(Ptr.getOptions())); + W.printEnum("PtrType", unsigned(Ptr.getPointerKind()), + makeArrayRef(PtrKindNames)); + W.printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames)); - W->printNumber("IsFlat", Ptr.isFlat()); - W->printNumber("IsConst", Ptr.isConst()); - W->printNumber("IsVolatile", Ptr.isVolatile()); - W->printNumber("IsUnaligned", Ptr.isUnaligned()); + W.printNumber("IsFlat", Ptr.isFlat()); + W.printNumber("IsConst", Ptr.isConst()); + W.printNumber("IsVolatile", Ptr.isVolatile()); + W.printNumber("IsUnaligned", Ptr.isUnaligned()); if (Ptr.isPointerToMember()) { const MemberPointerInfo &MI = Ptr.getMemberInfo(); printTypeIndex("ClassType", MI.getContainingType()); - W->printEnum("Representation", uint16_t(MI.getRepresentation()), - makeArrayRef(PtrMemberRepNames)); + W.printEnum("Representation", uint16_t(MI.getRepresentation()), + makeArrayRef(PtrMemberRepNames)); StringRef PointeeName = getTypeName(Ptr.getReferentType()); StringRef ClassName = getTypeName(MI.getContainingType()); @@ -414,7 +446,7 @@ Error CVTypeDumper::visitPointer(PointerRecord &Ptr) { TypeName.push_back(' '); TypeName.append(ClassName); TypeName.append("::*"); - Name = saveName(TypeName); + Name = CVTD.saveName(TypeName); } else { SmallString<256> TypeName; if (Ptr.isConst()) @@ -434,15 +466,14 @@ Error CVTypeDumper::visitPointer(PointerRecord &Ptr) { TypeName.append("*"); if (!TypeName.empty()) - Name = saveName(TypeName); + Name = CVTD.saveName(TypeName); } - return Error::success(); } -Error CVTypeDumper::visitModifier(ModifierRecord &Mod) { +void CVTypeDumperImpl::visitModifier(ModifierRecord &Mod) { uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); printTypeIndex("ModifiedType", Mod.getModifiedType()); - W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames)); + W.printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames)); StringRef ModifiedName = getTypeName(Mod.getModifiedType()); SmallString<256> TypeName; @@ -453,162 +484,146 @@ Error CVTypeDumper::visitModifier(ModifierRecord &Mod) { if (Mods & uint16_t(ModifierOptions::Unaligned)) TypeName.append("__unaligned "); TypeName.append(ModifiedName); - Name = saveName(TypeName); - return Error::success(); + Name = CVTD.saveName(TypeName); } -Error CVTypeDumper::visitBitField(BitFieldRecord &BitField) { +void CVTypeDumperImpl::visitBitField(BitFieldRecord &BitField) { printTypeIndex("Type", BitField.getType()); - W->printNumber("BitSize", BitField.getBitSize()); - W->printNumber("BitOffset", BitField.getBitOffset()); - return Error::success(); + W.printNumber("BitSize", BitField.getBitSize()); + W.printNumber("BitOffset", BitField.getBitOffset()); } -Error CVTypeDumper::visitVFTableShape(VFTableShapeRecord &Shape) { - W->printNumber("VFEntryCount", Shape.getEntryCount()); - return Error::success(); +void CVTypeDumperImpl::visitVFTableShape(VFTableShapeRecord &Shape) { + W.printNumber("VFEntryCount", Shape.getEntryCount()); } -Error CVTypeDumper::visitUdtSourceLine(UdtSourceLineRecord &Line) { +void CVTypeDumperImpl::visitUdtSourceLine(UdtSourceLineRecord &Line) { printTypeIndex("UDT", Line.getUDT()); printTypeIndex("SourceFile", Line.getSourceFile()); - W->printNumber("LineNumber", Line.getLineNumber()); - return Error::success(); + W.printNumber("LineNumber", Line.getLineNumber()); } -Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) { +void CVTypeDumperImpl::visitUdtModSourceLine(UdtModSourceLineRecord &Line) { printTypeIndex("UDT", Line.getUDT()); printTypeIndex("SourceFile", Line.getSourceFile()); - W->printNumber("LineNumber", Line.getLineNumber()); - W->printNumber("Module", Line.getModule()); - return Error::success(); + W.printNumber("LineNumber", Line.getLineNumber()); + W.printNumber("Module", Line.getModule()); } -Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) { - W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size())); +void CVTypeDumperImpl::visitBuildInfo(BuildInfoRecord &Args) { + W.printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size())); - ListScope Arguments(*W, "Arguments"); + ListScope Arguments(W, "Arguments"); for (auto Arg : Args.getArgs()) { printTypeIndex("ArgType", Arg); } - return Error::success(); } -void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) { +void CVTypeDumperImpl::printMemberAttributes(MemberAttributes Attrs) { return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(), Attrs.getFlags()); } -void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind, - MethodOptions Options) { - W->printEnum("AccessSpecifier", uint8_t(Access), - makeArrayRef(MemberAccessNames)); +void CVTypeDumperImpl::printMemberAttributes(MemberAccess Access, + MethodKind Kind, + MethodOptions Options) { + W.printEnum("AccessSpecifier", uint8_t(Access), + makeArrayRef(MemberAccessNames)); // Data members will be vanilla. Don't try to print a method kind for them. if (Kind != MethodKind::Vanilla) - W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames)); + W.printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames)); if (Options != MethodOptions::None) { - W->printFlags("MethodOptions", unsigned(Options), - makeArrayRef(MethodOptionNames)); + W.printFlags("MethodOptions", unsigned(Options), + makeArrayRef(MethodOptionNames)); } } -Error CVTypeDumper::visitUnknownMember(const CVRecord<TypeLeafKind> &Record) { - W->printHex("UnknownMember", unsigned(Record.Type)); - return Error::success(); +void CVTypeDumperImpl::visitUnknownMember(TypeLeafKind Leaf) { + W.printHex("UnknownMember", unsigned(Leaf)); } -Error CVTypeDumper::visitUnknownType(const CVRecord<TypeLeafKind> &Record) { - DictScope S(*W, "UnknownType"); - W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames)); - W->printNumber("Length", uint32_t(Record.Data.size())); - return Error::success(); +void CVTypeDumperImpl::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) { + DictScope S(W, "UnknownType"); + W.printEnum("Kind", uint16_t(Rec.Type), makeArrayRef(LeafTypeNames)); + W.printNumber("Length", uint32_t(Rec.Data.size())); } -Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) { - DictScope S(*W, "NestedType"); +void CVTypeDumperImpl::visitNestedType(NestedTypeRecord &Nested) { + DictScope S(W, "NestedType"); printTypeIndex("Type", Nested.getNestedType()); - W->printString("Name", Nested.getName()); + W.printString("Name", Nested.getName()); Name = Nested.getName(); - return Error::success(); } -Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) { - DictScope S(*W, "OneMethod"); +void CVTypeDumperImpl::visitOneMethod(OneMethodRecord &Method) { + DictScope S(W, "OneMethod"); MethodKind K = Method.getKind(); printMemberAttributes(Method.getAccess(), K, Method.getOptions()); printTypeIndex("Type", Method.getType()); // If virtual, then read the vftable offset. if (Method.isIntroducingVirtual()) - W->printHex("VFTableOffset", Method.getVFTableOffset()); - W->printString("Name", Method.getName()); + W.printHex("VFTableOffset", Method.getVFTableOffset()); + W.printString("Name", Method.getName()); Name = Method.getName(); - return Error::success(); } -Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) { - DictScope S(*W, "OverloadedMethod"); - W->printHex("MethodCount", Method.getNumOverloads()); +void CVTypeDumperImpl::visitOverloadedMethod(OverloadedMethodRecord &Method) { + DictScope S(W, "OverloadedMethod"); + W.printHex("MethodCount", Method.getNumOverloads()); printTypeIndex("MethodListIndex", Method.getMethodList()); - W->printString("Name", Method.getName()); + W.printString("Name", Method.getName()); Name = Method.getName(); - return Error::success(); } -Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) { - DictScope S(*W, "DataMember"); +void CVTypeDumperImpl::visitDataMember(DataMemberRecord &Field) { + DictScope S(W, "DataMember"); printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("Type", Field.getType()); - W->printHex("FieldOffset", Field.getFieldOffset()); - W->printString("Name", Field.getName()); + W.printHex("FieldOffset", Field.getFieldOffset()); + W.printString("Name", Field.getName()); Name = Field.getName(); - return Error::success(); } -Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) { - DictScope S(*W, "StaticDataMember"); +void CVTypeDumperImpl::visitStaticDataMember(StaticDataMemberRecord &Field) { + DictScope S(W, "StaticDataMember"); printMemberAttributes(Field.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("Type", Field.getType()); - W->printString("Name", Field.getName()); + W.printString("Name", Field.getName()); Name = Field.getName(); - return Error::success(); } -Error CVTypeDumper::visitVFPtr(VFPtrRecord &VFTable) { - DictScope S(*W, "VFPtr"); +void CVTypeDumperImpl::visitVFPtr(VFPtrRecord &VFTable) { + DictScope S(W, "VFPtr"); printTypeIndex("Type", VFTable.getType()); - return Error::success(); } -Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) { - DictScope S(*W, "Enumerator"); +void CVTypeDumperImpl::visitEnumerator(EnumeratorRecord &Enum) { + DictScope S(W, "Enumerator"); printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla, MethodOptions::None); - W->printNumber("EnumValue", Enum.getValue()); - W->printString("Name", Enum.getName()); + W.printNumber("EnumValue", Enum.getValue()); + W.printString("Name", Enum.getName()); Name = Enum.getName(); - return Error::success(); } -Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) { - DictScope S(*W, "BaseClass"); +void CVTypeDumperImpl::visitBaseClass(BaseClassRecord &Base) { + DictScope S(W, "BaseClass"); printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("BaseType", Base.getBaseType()); - W->printHex("BaseOffset", Base.getBaseOffset()); - return Error::success(); + W.printHex("BaseOffset", Base.getBaseOffset()); } -Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) { - DictScope S(*W, "VirtualBaseClass"); +void CVTypeDumperImpl::visitVirtualBaseClass(VirtualBaseClassRecord &Base) { + DictScope S(W, "VirtualBaseClass"); printMemberAttributes(Base.getAccess(), MethodKind::Vanilla, MethodOptions::None); printTypeIndex("BaseType", Base.getBaseType()); printTypeIndex("VBPtrType", Base.getVBPtrType()); - W->printHex("VBPtrOffset", Base.getVBPtrOffset()); - W->printHex("VBTableIndex", Base.getVTableIndex()); - return Error::success(); + W.printHex("VBPtrOffset", Base.getVBPtrOffset()); + W.printHex("VBTableIndex", Base.getVTableIndex()); } StringRef CVTypeDumper::getTypeName(TypeIndex TI) { @@ -648,29 +663,28 @@ void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) { W->printHex(FieldName, TI.getIndex()); } -Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) { +bool CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) { assert(W && "printer should not be null"); - CVTypeVisitor Visitor(*this); - - if (auto EC = Visitor.visitTypeRecord(Record)) - return EC; - return Error::success(); + CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes); + Dumper.visitTypeRecord(Record); + return !Dumper.hadError(); } -Error CVTypeDumper::dump(const CVTypeArray &Types) { +bool CVTypeDumper::dump(const CVTypeArray &Types) { assert(W && "printer should not be null"); - CVTypeVisitor Visitor(*this); - if (auto EC = Visitor.visitTypeStream(Types)) - return EC; - return Error::success(); + CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes); + Dumper.visitTypeStream(Types); + return !Dumper.hadError(); } -Error CVTypeDumper::dump(ArrayRef<uint8_t> Data) { +bool CVTypeDumper::dump(ArrayRef<uint8_t> Data) { ByteStream<> Stream(Data); CVTypeArray Types; StreamReader Reader(Stream); - if (auto EC = Reader.readArray(Types, Reader.getLength())) - return EC; + if (auto EC = Reader.readArray(Types, Reader.getLength())) { + consumeError(std::move(EC)); + return false; + } return dump(Types); } diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index b8b035f7..f71a31d 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -15,8 +15,6 @@ #include "llvm/DebugInfo/CodeView/StreamRef.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" -#include "llvm/Support/Error.h" #include "llvm/Support/ScopedPrinter.h" using namespace llvm; @@ -51,30 +49,32 @@ namespace { /// - If the type record already exists in the destination stream, discard it /// and update the type index map to forward the source type index to the /// existing destination type index. -class TypeStreamMerger : public TypeVisitorCallbacks { +class TypeStreamMerger : public CVTypeVisitor<TypeStreamMerger> { public: TypeStreamMerger(TypeTableBuilder &DestStream) : DestStream(DestStream) { assert(!hadError()); } -/// TypeVisitorCallbacks overrides. + /// CVTypeVisitor overrides. #define TYPE_RECORD(EnumName, EnumVal, Name) \ - Error visit##Name(Name##Record &Record) override; -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - TYPE_RECORD(EnumName, EnumVal, Name) + void visit##Name(Name##Record &Record); #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + void visit##Name(Name##Record &Record); #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "llvm/DebugInfo/CodeView/TypeRecords.def" - Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) override; + void visitUnknownType(const CVRecord<TypeLeafKind> &Record); + + void visitTypeBegin(const CVRecord<TypeLeafKind> &Record); + void visitTypeEnd(const CVRecord<TypeLeafKind> &Record); - Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override; - Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override; + void visitFieldList(TypeLeafKind Leaf, ArrayRef<uint8_t> FieldData); bool mergeStream(const CVTypeArray &Types); private: - bool hadError() { return FoundBadTypeIndex; } + bool hadError() { return FoundBadTypeIndex || CVTypeVisitor::hadError(); } bool FoundBadTypeIndex = false; @@ -91,46 +91,45 @@ private: } // end anonymous namespace -Error TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) { +void TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) { BeginIndexMapSize = IndexMap.size(); - return Error::success(); } -Error TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) { +void TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) { assert(IndexMap.size() == BeginIndexMapSize + 1); - return Error::success(); +} + +void TypeStreamMerger::visitFieldList(TypeLeafKind Leaf, + ArrayRef<uint8_t> FieldData) { + CVTypeVisitor::visitFieldList(Leaf, FieldData); + IndexMap.push_back(DestStream.writeFieldList(FieldBuilder)); + FieldBuilder.reset(); } #define TYPE_RECORD(EnumName, EnumVal, Name) \ - Error TypeStreamMerger::visit##Name(Name##Record &Record) { \ + void TypeStreamMerger::visit##Name(Name##Record &Record) { \ FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ IndexMap.push_back(DestStream.write##Name(Record)); \ - return Error::success(); \ } #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #define MEMBER_RECORD(EnumName, EnumVal, Name) \ - Error TypeStreamMerger::visit##Name(Name##Record &Record) { \ + void TypeStreamMerger::visit##Name(Name##Record &Record) { \ FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ FieldBuilder.write##Name(Record); \ - return Error::success(); \ } #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "llvm/DebugInfo/CodeView/TypeRecords.def" -Error TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) { +void TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) { // We failed to translate a type. Translate this index as "not translated". IndexMap.push_back( TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct)); - return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); + parseError(); } bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) { assert(IndexMap.empty()); - CVTypeVisitor Visitor(*this); - if (auto EC = Visitor.visitTypeStream(Types)) { - consumeError(std::move(EC)); - return false; - } + visitTypeStream(Types); IndexMap.clear(); return !hadError(); } diff --git a/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp b/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp index eb169f7..07aebb7 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp @@ -32,8 +32,6 @@ public: return "The specified block address is not valid."; case raw_error_code::not_writable: return "The PDB does not support writing."; - case raw_error_code::invalid_tpi_hash: - return "The Type record has an invalid hash value."; } llvm_unreachable("Unrecognized raw_error_code"); } diff --git a/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp index 46717f2..99e5037 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp @@ -84,44 +84,39 @@ template <typename T> static uint32_t getTpiHash(T &Rec) { } namespace { -class TpiHashVerifier : public TypeVisitorCallbacks { +class TpiHashVerifier : public CVTypeVisitor<TpiHashVerifier> { public: TpiHashVerifier(FixedStreamArray<support::ulittle32_t> &HashValues, uint32_t NumHashBuckets) : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {} - Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override { - return verifySourceLine(Rec); - } + void visitUdtSourceLine(UdtSourceLineRecord &Rec) { verifySourceLine(Rec); } - Error visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override { - return verifySourceLine(Rec); + void visitUdtModSourceLine(UdtModSourceLineRecord &Rec) { + 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); } + void visitClass(ClassRecord &Rec) { verify(Rec); } + void visitEnum(EnumRecord &Rec) { verify(Rec); } + void visitInterface(ClassRecord &Rec) { verify(Rec); } + void visitStruct(ClassRecord &Rec) { verify(Rec); } + void visitUnion(UnionRecord &Rec) { verify(Rec); } - Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override { - ++Index; - return Error::success(); - } + void visitTypeEnd(const CVRecord<TypeLeafKind> &Record) { ++Index; } private: - template <typename T> Error verify(T &Rec) { + template <typename T> void verify(T &Rec) { uint32_t Hash = getTpiHash(Rec); if (Hash && Hash % NumHashBuckets != HashValues[Index]) - return make_error<RawError>(raw_error_code::invalid_tpi_hash); - return Error::success(); + parseError(); } - template <typename T> Error verifySourceLine(T &Rec) { + template <typename T> void verifySourceLine(T &Rec) { char Buf[4]; support::endian::write32le(Buf, Rec.getUDT().getIndex()); uint32_t Hash = hashStringV1(StringRef(Buf, 4)); if (Hash % NumHashBuckets != HashValues[Index]) - return make_error<RawError>(raw_error_code::invalid_tpi_hash); - return Error::success(); + parseError(); } FixedStreamArray<support::ulittle32_t> HashValues; @@ -134,8 +129,11 @@ private: // Currently we only verify SRC_LINE records. Error TpiStream::verifyHashValues() { TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets); - CVTypeVisitor Visitor(Verifier); - return Visitor.visitTypeStream(TypeRecords); + Verifier.visitTypeStream(TypeRecords); + if (Verifier.hadError()) + return make_error<RawError>(raw_error_code::corrupt_file, + "Corrupt TPI hash table."); + return Error::success(); } Error TpiStream::reload() { |