[llvm] r272929 - Resubmit "[pdb] Change type visitor pattern to be dynamic."
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 16 11:22:27 PDT 2016
Author: zturner
Date: Thu Jun 16 13:22:27 2016
New Revision: 272929
URL: http://llvm.org/viewvc/llvm-project?rev=272929&view=rev
Log:
Resubmit "[pdb] Change type visitor pattern to be dynamic."
There was a regression introduced during type stream merging when
visiting a field list record. This has been fixed in this patch.
Added:
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
Modified:
llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h
llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp
llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h Thu Jun 16 13:22:27 2016
@@ -11,151 +11,31 @@
#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
#include "llvm/DebugInfo/CodeView/CVRecord.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/Support/ErrorOr.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
-template <typename Derived>
class CVTypeVisitor {
public:
- CVTypeVisitor() {}
+ explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
- bool hadError() const { return HadError; }
-
- template <typename T>
- bool consumeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
- if (Data.size() < sizeof(*Res)) {
- HadError = true;
- return false;
- }
- Res = reinterpret_cast<const T *>(Data.data());
- Data = Data.drop_front(sizeof(*Res));
- return true;
- }
-
- /// Actions to take on known types. By default, they do nothing. Visit methods
- /// for member records take the FieldData by non-const reference and are
- /// expected to consume the trailing bytes used by the field.
- /// FIXME: Make the visitor interpret the trailing bytes so that clients don't
- /// need to.
-#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 "TypeRecords.def"
-
- void visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
- ArrayRef<uint8_t> LeafData = Record.Data;
- auto *DerivedThis = static_cast<Derived *>(this);
- DerivedThis->visitTypeBegin(Record);
- switch (Record.Type) {
- default:
- DerivedThis->visitUnknownType(Record);
- break;
- case LF_FIELDLIST:
- DerivedThis->visitFieldList(Record.Type, LeafData);
- 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 parseError(); \
- DerivedThis->visit##Name(*Result); \
- break; \
- }
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
- TYPE_RECORD(EnumVal, EnumVal, AliasName)
-#define MEMBER_RECORD(EnumName, EnumVal, Name)
-#include "TypeRecords.def"
- }
- DerivedThis->visitTypeEnd(Record);
- }
+ Error visitTypeRecord(const CVRecord<TypeLeafKind> &Record);
/// Visits the type records in Data. Sets the error flag on parse failures.
- void visitTypeStream(const CVTypeArray &Types) {
- for (const auto &I : Types) {
- visitTypeRecord(I);
- if (hadError())
- break;
- }
- }
-
- /// Action to take on unknown types. By default, they are ignored.
- void visitUnknownType(const CVRecord<TypeLeafKind> &Record) {}
-
- /// Paired begin/end actions for all types. Receives all record data,
- /// including the fixed-length record prefix.
- void visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {}
- void visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {}
-
- ArrayRef<uint8_t> skipPadding(ArrayRef<uint8_t> Data) {
- if (Data.empty())
- return Data;
- uint8_t Leaf = Data.front();
- if (Leaf < LF_PAD0)
- return Data;
- // 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) {
- parseError();
- return None;
- }
- return Data.drop_front(BytesToAdvance);
- }
+ 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.
- void visitFieldList(TypeLeafKind Leaf, ArrayRef<uint8_t> FieldData) {
- auto *DerivedThis = static_cast<Derived *>(this);
- while (!FieldData.empty()) {
- const ulittle16_t *LeafPtr;
- if (!CVTypeVisitor::consumeObject(FieldData, LeafPtr))
- return;
- 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.
- DerivedThis->visitUnknownMember(Leaf);
- return parseError();
-#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- case EnumName: { \
- TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName); \
- auto Result = Name##Record::deserialize(RK, FieldData); \
- if (Result.getError()) \
- return parseError(); \
- DerivedThis->visit##Name(*Result); \
- break; \
- }
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
- MEMBER_RECORD(EnumVal, EnumVal, AliasName)
-#include "TypeRecords.def"
- }
- FieldData = skipPadding(FieldData);
- if (hadError())
- break;
- }
- }
-
- /// Action to take on unknown members. By default, they are ignored. Member
- /// record parsing cannot recover from an unknown member record, so this
- /// method is only called at most once per field list record.
- void visitUnknownMember(TypeLeafKind Leaf) {}
-
- /// Helper for returning from a void function when the stream is corrupted.
- void parseError() { HadError = true; }
+ Error visitFieldList(const CVRecord<TypeLeafKind> &Record);
private:
- /// Whether a type stream parsing error was encountered.
- bool HadError = false;
+ /// The interface to the class that gets notified of each visitation.
+ TypeVisitorCallbacks &Callbacks;
};
} // end namespace codeview
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h Thu Jun 16 13:22:27 2016
@@ -14,6 +14,7 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
namespace llvm {
class ScopedPrinter;
@@ -21,7 +22,7 @@ class ScopedPrinter;
namespace codeview {
/// Dumper for CodeView type streams found in COFF object files and PDB files.
-class CVTypeDumper {
+class CVTypeDumper : public TypeVisitorCallbacks {
public:
CVTypeDumper(ScopedPrinter *W, bool PrintRecordBytes)
: W(W), PrintRecordBytes(PrintRecordBytes) {}
@@ -33,17 +34,17 @@ public:
/// and true otherwise. This should be called in order, since the dumper
/// maintains state about previous records which are necessary for cross
/// type references.
- bool dump(const CVRecord<TypeLeafKind> &Record);
+ Error dump(const CVRecord<TypeLeafKind> &Record);
/// Dumps the type records in Types. Returns false if there was a type stream
/// parse error, and true otherwise.
- bool dump(const CVTypeArray &Types);
+ Error dump(const CVTypeArray &Types);
/// Dumps the type records in Data. Returns false if there was a type stream
/// parse error, and true otherwise. Use this method instead of the
/// CVTypeArray overload when type records are laid out contiguously in
/// memory.
- bool dump(ArrayRef<uint8_t> Data);
+ Error dump(ArrayRef<uint8_t> Data);
/// Gets the type index for the next type record.
unsigned getNextTypeIndex() const {
@@ -61,11 +62,35 @@ public:
void setPrinter(ScopedPrinter *P);
ScopedPrinter *getPrinter() { return W; }
+ /// Action to take on unknown types. By default, they are ignored.
+ Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) override;
+ Error visitUnknownMember(const CVRecord<TypeLeafKind> &Record) override;
+
+ /// Paired begin/end actions for all types. Receives all record data,
+ /// including the fixed-length record prefix.
+ Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
+ Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
+
+#define TYPE_RECORD(EnumName, EnumVal, Name) \
+ Error visit##Name(Name##Record &Record) override;
+#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"
+
private:
+ void printMemberAttributes(MemberAttributes Attrs);
+ void printMemberAttributes(MemberAccess Access, MethodKind Kind,
+ MethodOptions Options);
+
ScopedPrinter *W;
bool PrintRecordBytes = false;
+ /// Name of the current type. Only valid before visitTypeEnd.
+ StringRef Name;
+
/// All user defined type records in .debug$T live in here. Type indices
/// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
/// index into this vector.
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def Thu Jun 16 13:22:27 2016
@@ -83,6 +83,7 @@ TYPE_RECORD(LF_STRING_ID, 0x1605, String
TYPE_RECORD(LF_UDT_SRC_LINE, 0x1606, UdtSourceLine)
TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine)
+
TYPE_RECORD(LF_METHODLIST, 0x1206, MethodOverloadList)
@@ -195,6 +196,8 @@ CV_TYPE(LF_MODIFIER_EX, 0x1518)
CV_TYPE(LF_VECTOR, 0x151b)
CV_TYPE(LF_MATRIX, 0x151c)
+// ID leaf records. Subsequent leaf types may be referenced from .debug$S.
+
// Numeric leaf types. These are generally contained in other records, and not
// encountered in the main type stream.
Added: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h?rev=272929&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h Thu Jun 16 13:22:27 2016
@@ -0,0 +1,61 @@
+//===- TypeVisitorCallbacks.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_TYPEVISITORCALLBACKS_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+class TypeVisitorCallbacks {
+ friend class CVTypeVisitor;
+
+public:
+ virtual ~TypeVisitorCallbacks() {}
+
+ /// Action to take on unknown types. By default, they are ignored.
+ virtual Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
+ return Error::success();
+ }
+ virtual Error visitUnknownMember(const CVRecord<TypeLeafKind> &Record) {
+ return Error::success();
+ }
+
+ /// Paired begin/end actions for all types. Receives all record data,
+ /// including the fixed-length record prefix.
+ virtual Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {
+ return Error::success();
+ }
+ virtual Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
+ 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(); }
+#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"
+};
+}
+}
+
+#endif
\ No newline at end of file
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h Thu Jun 16 13:22:27 2016
@@ -25,6 +25,7 @@ enum class raw_error_code {
index_out_of_bounds,
invalid_block_address,
not_writable,
+ invalid_tpi_hash,
};
/// Base class for errors originating when parsing raw PDB files
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Thu Jun 16 13:22:27 2016
@@ -322,10 +322,9 @@ void CodeViewDebug::emitTypeInformation(
ScopedPrinter SP(CommentOS);
SP.setPrefix(CommentPrefix);
CVTD.setPrinter(&SP);
- bool DumpSuccess =
- CVTD.dump({Record.bytes_begin(), Record.bytes_end()});
- (void)DumpSuccess;
- assert(DumpSuccess && "produced malformed type record");
+ Error EC = CVTD.dump({Record.bytes_begin(), Record.bytes_end()});
+ assert(!EC && "produced malformed type record");
+ consumeError(std::move(EC));
// emitRawComment will insert its own tab and comment string before
// the first line, so strip off our first one. It also prints its own
// newline.
Modified: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt Thu Jun 16 13:22:27 2016
@@ -1,6 +1,7 @@
add_llvm_library(LLVMDebugInfoCodeView
ByteStream.cpp
CodeViewError.cpp
+ CVTypeVisitor.cpp
EnumTables.cpp
FieldListRecordBuilder.cpp
Line.cpp
Added: llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp?rev=272929&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp (added)
+++ llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp Thu Jun 16 13:22:27 2016
@@ -0,0 +1,123 @@
+//===- 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 = 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 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();
+}
Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp Thu Jun 16 13:22:27 2016
@@ -189,55 +189,6 @@ static const EnumEntry<uint8_t> Function
#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) \
@@ -250,39 +201,44 @@ static StringRef getLeafTypeName(TypeLea
return "UnknownLeaf";
}
-void CVTypeDumperImpl::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
+Error CVTypeDumper::visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {
// Reset Name to the empty string. If the visitor sets it, we know it.
Name = "";
- W.startLine() << getLeafTypeName(Rec.Type) << " ("
- << HexNumber(CVTD.getNextTypeIndex()) << ") {\n";
- W.indent();
- W.printEnum("TypeLeafKind", unsigned(Rec.Type), makeArrayRef(LeafTypeNames));
+ W->startLine() << getLeafTypeName(Record.Type) << " ("
+ << HexNumber(getNextTypeIndex()) << ") {\n";
+ W->indent();
+ W->printEnum("TypeLeafKind", unsigned(Record.Type),
+ makeArrayRef(LeafTypeNames));
+ return Error::success();
}
-void CVTypeDumperImpl::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
+Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
// 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.
- CVTD.recordType(Name);
+ recordType(Name);
+
if (PrintRecordBytes)
- W.printBinaryBlock("LeafData", getBytesAsCharacters(Rec.Data));
+ W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
- W.unindent();
- W.startLine() << "}\n";
+ W->unindent();
+ W->startLine() << "}\n";
+ return Error::success();
}
-void CVTypeDumperImpl::visitStringId(StringIdRecord &String) {
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitArgList(ArgListRecord &Args) {
+Error CVTypeDumper::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]);
@@ -292,77 +248,84 @@ void CVTypeDumperImpl::visitArgList(ArgL
TypeName.append(", ");
}
TypeName.push_back(')');
- Name = CVTD.saveName(TypeName);
+ Name = saveName(TypeName);
+ return Error::success();
}
-void CVTypeDumperImpl::visitClass(ClassRecord &Class) {
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitUnion(UnionRecord &Union) {
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitEnum(EnumRecord &Enum) {
- W.printNumber("NumEnumerators", Enum.getMemberCount());
- W.printFlags("Properties", uint16_t(Enum.getOptions()),
- makeArrayRef(ClassOptionNames));
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitArray(ArrayRecord &AT) {
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitVFTable(VFTableRecord &VFT) {
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitMemberFuncId(MemberFuncIdRecord &Id) {
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitProcedure(ProcedureRecord &Proc) {
+Error CVTypeDumper::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());
@@ -370,20 +333,21 @@ void CVTypeDumperImpl::visitProcedure(Pr
SmallString<256> TypeName(ReturnTypeName);
TypeName.push_back(' ');
TypeName.append(ArgListTypeName);
- Name = CVTD.saveName(TypeName);
+ Name = saveName(TypeName);
+ return Error::success();
}
-void CVTypeDumperImpl::visitMemberFunction(MemberFunctionRecord &MF) {
+Error CVTypeDumper::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());
@@ -393,52 +357,56 @@ void CVTypeDumperImpl::visitMemberFuncti
TypeName.append(ClassTypeName);
TypeName.append("::");
TypeName.append(ArgListTypeName);
- Name = CVTD.saveName(TypeName);
+ Name = saveName(TypeName);
+ return Error::success();
}
-void CVTypeDumperImpl::visitMethodOverloadList(
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitFuncId(FuncIdRecord &Func) {
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitTypeServer2(TypeServer2Record &TS) {
- W.printBinary("Signature", TS.getGuid());
- W.printNumber("Age", TS.getAge());
- W.printString("Name", TS.getName());
+Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) {
+ W->printBinary("Signature", TS.getGuid());
+ W->printNumber("Age", TS.getAge());
+ W->printString("Name", TS.getName());
Name = TS.getName();
+ return Error::success();
}
-void CVTypeDumperImpl::visitPointer(PointerRecord &Ptr) {
+Error CVTypeDumper::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.printNumber("IsFlat", Ptr.isFlat());
- W.printNumber("IsConst", Ptr.isConst());
- W.printNumber("IsVolatile", Ptr.isVolatile());
- W.printNumber("IsUnaligned", Ptr.isUnaligned());
+ 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());
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());
@@ -446,7 +414,7 @@ void CVTypeDumperImpl::visitPointer(Poin
TypeName.push_back(' ');
TypeName.append(ClassName);
TypeName.append("::*");
- Name = CVTD.saveName(TypeName);
+ Name = saveName(TypeName);
} else {
SmallString<256> TypeName;
if (Ptr.isConst())
@@ -466,14 +434,15 @@ void CVTypeDumperImpl::visitPointer(Poin
TypeName.append("*");
if (!TypeName.empty())
- Name = CVTD.saveName(TypeName);
+ Name = saveName(TypeName);
}
+ return Error::success();
}
-void CVTypeDumperImpl::visitModifier(ModifierRecord &Mod) {
+Error CVTypeDumper::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;
@@ -484,146 +453,162 @@ void CVTypeDumperImpl::visitModifier(Mod
if (Mods & uint16_t(ModifierOptions::Unaligned))
TypeName.append("__unaligned ");
TypeName.append(ModifiedName);
- Name = CVTD.saveName(TypeName);
+ Name = saveName(TypeName);
+ return Error::success();
}
-void CVTypeDumperImpl::visitBitField(BitFieldRecord &BitField) {
+Error CVTypeDumper::visitBitField(BitFieldRecord &BitField) {
printTypeIndex("Type", BitField.getType());
- W.printNumber("BitSize", BitField.getBitSize());
- W.printNumber("BitOffset", BitField.getBitOffset());
+ W->printNumber("BitSize", BitField.getBitSize());
+ W->printNumber("BitOffset", BitField.getBitOffset());
+ return Error::success();
}
-void CVTypeDumperImpl::visitVFTableShape(VFTableShapeRecord &Shape) {
- W.printNumber("VFEntryCount", Shape.getEntryCount());
+Error CVTypeDumper::visitVFTableShape(VFTableShapeRecord &Shape) {
+ W->printNumber("VFEntryCount", Shape.getEntryCount());
+ return Error::success();
}
-void CVTypeDumperImpl::visitUdtSourceLine(UdtSourceLineRecord &Line) {
+Error CVTypeDumper::visitUdtSourceLine(UdtSourceLineRecord &Line) {
printTypeIndex("UDT", Line.getUDT());
printTypeIndex("SourceFile", Line.getSourceFile());
- W.printNumber("LineNumber", Line.getLineNumber());
+ W->printNumber("LineNumber", Line.getLineNumber());
+ return Error::success();
}
-void CVTypeDumperImpl::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
+Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
printTypeIndex("UDT", Line.getUDT());
printTypeIndex("SourceFile", Line.getSourceFile());
- W.printNumber("LineNumber", Line.getLineNumber());
- W.printNumber("Module", Line.getModule());
+ W->printNumber("LineNumber", Line.getLineNumber());
+ W->printNumber("Module", Line.getModule());
+ return Error::success();
}
-void CVTypeDumperImpl::visitBuildInfo(BuildInfoRecord &Args) {
- W.printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
+Error CVTypeDumper::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 CVTypeDumperImpl::printMemberAttributes(MemberAttributes Attrs) {
+void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) {
return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
Attrs.getFlags());
}
-void CVTypeDumperImpl::printMemberAttributes(MemberAccess Access,
- MethodKind Kind,
- MethodOptions Options) {
- W.printEnum("AccessSpecifier", uint8_t(Access),
- makeArrayRef(MemberAccessNames));
+void CVTypeDumper::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));
}
}
-void CVTypeDumperImpl::visitUnknownMember(TypeLeafKind Leaf) {
- W.printHex("UnknownMember", unsigned(Leaf));
+Error CVTypeDumper::visitUnknownMember(const CVRecord<TypeLeafKind> &Record) {
+ W->printHex("UnknownMember", unsigned(Record.Type));
+ 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::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::visitNestedType(NestedTypeRecord &Nested) {
- DictScope S(W, "NestedType");
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitOneMethod(OneMethodRecord &Method) {
- DictScope S(W, "OneMethod");
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitOverloadedMethod(OverloadedMethodRecord &Method) {
- DictScope S(W, "OverloadedMethod");
- W.printHex("MethodCount", Method.getNumOverloads());
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitDataMember(DataMemberRecord &Field) {
- DictScope S(W, "DataMember");
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitStaticDataMember(StaticDataMemberRecord &Field) {
- DictScope S(W, "StaticDataMember");
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitVFPtr(VFPtrRecord &VFTable) {
- DictScope S(W, "VFPtr");
+Error CVTypeDumper::visitVFPtr(VFPtrRecord &VFTable) {
+ DictScope S(*W, "VFPtr");
printTypeIndex("Type", VFTable.getType());
+ return Error::success();
}
-void CVTypeDumperImpl::visitEnumerator(EnumeratorRecord &Enum) {
- DictScope S(W, "Enumerator");
+Error CVTypeDumper::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();
}
-void CVTypeDumperImpl::visitBaseClass(BaseClassRecord &Base) {
- DictScope S(W, "BaseClass");
+Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
+ DictScope S(*W, "BaseClass");
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("BaseType", Base.getBaseType());
- W.printHex("BaseOffset", Base.getBaseOffset());
+ W->printHex("BaseOffset", Base.getBaseOffset());
+ return Error::success();
}
-void CVTypeDumperImpl::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
- DictScope S(W, "VirtualBaseClass");
+Error CVTypeDumper::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());
+ W->printHex("VBPtrOffset", Base.getVBPtrOffset());
+ W->printHex("VBTableIndex", Base.getVTableIndex());
+ return Error::success();
}
StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
@@ -663,28 +648,29 @@ void CVTypeDumper::printTypeIndex(String
W->printHex(FieldName, TI.getIndex());
}
-bool CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
+Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
assert(W && "printer should not be null");
- CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes);
- Dumper.visitTypeRecord(Record);
- return !Dumper.hadError();
+ CVTypeVisitor Visitor(*this);
+
+ if (auto EC = Visitor.visitTypeRecord(Record))
+ return EC;
+ return Error::success();
}
-bool CVTypeDumper::dump(const CVTypeArray &Types) {
+Error CVTypeDumper::dump(const CVTypeArray &Types) {
assert(W && "printer should not be null");
- CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes);
- Dumper.visitTypeStream(Types);
- return !Dumper.hadError();
+ CVTypeVisitor Visitor(*this);
+ if (auto EC = Visitor.visitTypeStream(Types))
+ return EC;
+ return Error::success();
}
-bool CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
+Error CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
ByteStream<> Stream(Data);
CVTypeArray Types;
StreamReader Reader(Stream);
- if (auto EC = Reader.readArray(Types, Reader.getLength())) {
- consumeError(std::move(EC));
- return false;
- }
+ if (auto EC = Reader.readArray(Types, Reader.getLength()))
+ return EC;
return dump(Types);
}
Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp Thu Jun 16 13:22:27 2016
@@ -15,6 +15,8 @@
#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;
@@ -49,32 +51,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 CVTypeVisitor<TypeStreamMerger> {
+class TypeStreamMerger : public TypeVisitorCallbacks {
public:
TypeStreamMerger(TypeTableBuilder &DestStream) : DestStream(DestStream) {
assert(!hadError());
}
- /// CVTypeVisitor overrides.
+/// TypeVisitorCallbacks overrides.
#define TYPE_RECORD(EnumName, EnumVal, Name) \
- void visit##Name(Name##Record &Record);
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+ Error visit##Name(Name##Record &Record) override;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- void visit##Name(Name##Record &Record);
+ TYPE_RECORD(EnumName, EnumVal, Name)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- void visitUnknownType(const CVRecord<TypeLeafKind> &Record);
+ Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) override;
- 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);
+ Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) override;
bool mergeStream(const CVTypeArray &Types);
private:
- bool hadError() { return FoundBadTypeIndex || CVTypeVisitor::hadError(); }
+ bool hadError() { return FoundBadTypeIndex; }
bool FoundBadTypeIndex = false;
@@ -91,45 +93,52 @@ private:
} // end anonymous namespace
-void TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
+Error TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
BeginIndexMapSize = IndexMap.size();
+ return Error::success();
}
-void TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
+Error 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);
+Error TypeStreamMerger::visitFieldListEnd(const CVRecord<TypeLeafKind> &Rec) {
IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
FieldBuilder.reset();
+ return Error::success();
}
#define TYPE_RECORD(EnumName, EnumVal, Name) \
- void TypeStreamMerger::visit##Name(Name##Record &Record) { \
+ Error 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) \
- void TypeStreamMerger::visit##Name(Name##Record &Record) { \
+ Error 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"
-void TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
+Error 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));
- parseError();
+ return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
}
bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
assert(IndexMap.empty());
- visitTypeStream(Types);
+ CVTypeVisitor Visitor(*this);
+ if (auto EC = Visitor.visitTypeStream(Types)) {
+ consumeError(std::move(EC));
+ return false;
+ }
IndexMap.clear();
return !hadError();
}
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp Thu Jun 16 13:22:27 2016
@@ -32,6 +32,8 @@ 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");
}
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp Thu Jun 16 13:22:27 2016
@@ -84,39 +84,44 @@ template <typename T> static uint32_t ge
}
namespace {
-class TpiHashVerifier : public CVTypeVisitor<TpiHashVerifier> {
+class TpiHashVerifier : public TypeVisitorCallbacks {
public:
TpiHashVerifier(FixedStreamArray<support::ulittle32_t> &HashValues,
uint32_t NumHashBuckets)
: HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
- void visitUdtSourceLine(UdtSourceLineRecord &Rec) { verifySourceLine(Rec); }
-
- void visitUdtModSourceLine(UdtModSourceLineRecord &Rec) {
- verifySourceLine(Rec);
+ Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override {
+ return verifySourceLine(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 visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override {
+ return verifySourceLine(Rec);
+ }
- void visitTypeEnd(const CVRecord<TypeLeafKind> &Record) { ++Index; }
+ 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 visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override {
+ ++Index;
+ return Error::success();
+ }
private:
- template <typename T> void verify(T &Rec) {
+ template <typename T> Error verify(T &Rec) {
uint32_t Hash = getTpiHash(Rec);
if (Hash && Hash % NumHashBuckets != HashValues[Index])
- parseError();
+ return make_error<RawError>(raw_error_code::invalid_tpi_hash);
+ return Error::success();
}
- template <typename T> void verifySourceLine(T &Rec) {
+ template <typename T> Error 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])
- parseError();
+ return make_error<RawError>(raw_error_code::invalid_tpi_hash);
+ return Error::success();
}
FixedStreamArray<support::ulittle32_t> HashValues;
@@ -129,11 +134,8 @@ private:
// Currently we only verify SRC_LINE records.
Error TpiStream::verifyHashValues() {
TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets);
- Verifier.visitTypeStream(TypeRecords);
- if (Verifier.hadError())
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Corrupt TPI hash table.");
- return Error::success();
+ CVTypeVisitor Visitor(Verifier);
+ return Visitor.visitTypeStream(TypeRecords);
}
Error TpiStream::reload() {
Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp Thu Jun 16 13:22:27 2016
@@ -328,8 +328,10 @@ Error LLVMOutputStyle::dumpTpiStream(uin
for (auto &Type : Tpi->types(&HadError)) {
DictScope DD(P, "");
- if (DumpRecords)
- TD.dump(Type);
+ if (DumpRecords) {
+ if (auto EC = TD.dump(Type))
+ return EC;
+ }
if (DumpRecordBytes)
P.printBinaryBlock("Bytes", Type.Data);
@@ -347,8 +349,10 @@ Error LLVMOutputStyle::dumpTpiStream(uin
TD.setPrinter(nullptr);
bool HadError = false;
- for (auto &Type : Tpi->types(&HadError))
- TD.dump(Type);
+ for (auto &Type : Tpi->types(&HadError)) {
+ if (auto EC = TD.dump(Type))
+ return EC;
+ }
TD.setPrinter(OldP);
dumpTpiHash(P, *Tpi);
Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=272929&r1=272928&r2=272929&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Thu Jun 16 13:22:27 2016
@@ -1108,9 +1108,9 @@ void COFFDumper::printCodeViewTypeSectio
if (Magic != COFF::DEBUG_SECTION_MAGIC)
return error(object_error::parse_failed);
- if (!CVTD.dump({Data.bytes_begin(), Data.bytes_end()})) {
+ if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()})) {
W.flush();
- error(object_error::parse_failed);
+ error(llvm::errorToErrorCode(std::move(EC)));
}
}
@@ -1555,8 +1555,8 @@ void llvm::dumpCodeViewMergedTypes(
Buf.append(Record.begin(), Record.end());
});
CVTypeDumper CVTD(&Writer, opts::CodeViewSubsectionBytes);
- if (!CVTD.dump({Buf.str().bytes_begin(), Buf.str().bytes_end()})) {
+ if (auto EC = CVTD.dump({Buf.str().bytes_begin(), Buf.str().bytes_end()})) {
Writer.flush();
- error(object_error::parse_failed);
+ error(llvm::errorToErrorCode(std::move(EC)));
}
}
More information about the llvm-commits
mailing list