diff options
Diffstat (limited to 'contrib/llvm/include/llvm/DebugInfo/CodeView')
47 files changed, 2196 insertions, 2744 deletions
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ByteStream.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/ByteStream.h deleted file mode 100644 index f398c93..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ByteStream.h +++ /dev/null @@ -1,58 +0,0 @@ -//===- ByteStream.h - Reads stream data from a byte sequence ----*- 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_BYTESTREAM_H -#define LLVM_DEBUGINFO_CODEVIEW_BYTESTREAM_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" -#include "llvm/Support/Error.h" -#include <cstdint> -#include <memory> -#include <type_traits> - -namespace llvm { -namespace codeview { -class StreamReader; - -template <bool Writable = false> class ByteStream : public StreamInterface { - typedef typename std::conditional<Writable, MutableArrayRef<uint8_t>, - ArrayRef<uint8_t>>::type ArrayType; - -public: - ByteStream() {} - explicit ByteStream(ArrayType Data) : Data(Data) {} - ~ByteStream() override {} - - Error readBytes(uint32_t Offset, uint32_t Size, - ArrayRef<uint8_t> &Buffer) const override; - Error readLongestContiguousChunk(uint32_t Offset, - ArrayRef<uint8_t> &Buffer) const override; - - Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override; - - uint32_t getLength() const override; - - Error commit() const override; - - ArrayRef<uint8_t> data() const { return Data; } - StringRef str() const; - -private: - ArrayType Data; -}; - -extern template class ByteStream<true>; -extern template class ByteStream<false>; - -} // end namespace pdb -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_BYTESTREAM_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVDebugRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVDebugRecord.h new file mode 100644 index 0000000..5a0bb42 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVDebugRecord.h @@ -0,0 +1,55 @@ +//===- CVDebugRecord.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_CVDEBUGRECORD_H +#define LLVM_DEBUGINFO_CODEVIEW_CVDEBUGRECORD_H + +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace OMF { +struct Signature { + enum ID : uint32_t { + PDB70 = 0x53445352, // RSDS + PDB20 = 0x3031424e, // NB10 + CV50 = 0x3131424e, // NB11 + CV41 = 0x3930424e, // NB09 + }; + + support::ulittle32_t CVSignature; + support::ulittle32_t Offset; +}; +} + +namespace codeview { +struct PDB70DebugInfo { + support::ulittle32_t CVSignature; + uint8_t Signature[16]; + support::ulittle32_t Age; + // char PDBFileName[]; +}; + +struct PDB20DebugInfo { + support::ulittle32_t CVSignature; + support::ulittle32_t Offset; + support::ulittle32_t Signature; + support::ulittle32_t Age; + // char PDBFileName[]; +}; + +union DebugInfo { + struct OMF::Signature Signature; + struct PDB20DebugInfo PDB20; + struct PDB70DebugInfo PDB70; +}; +} +} + +#endif + diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h index dba359f..a327d45 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -11,46 +11,73 @@ #define LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" -#include "llvm/DebugInfo/CodeView/StreamReader.h" +#include "llvm/DebugInfo/MSF/StreamReader.h" +#include "llvm/DebugInfo/MSF/StreamRef.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> namespace llvm { + namespace codeview { -template <typename Kind> struct CVRecord { - uint32_t Length; +template <typename Kind> class CVRecord { +public: + CVRecord() = default; + CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {} + + uint32_t length() const { return RecordData.size(); } + Kind kind() const { return Type; } + ArrayRef<uint8_t> data() const { return RecordData; } + + ArrayRef<uint8_t> content() const { + return RecordData.drop_front(sizeof(RecordPrefix)); + } + + Optional<uint32_t> hash() const { return Hash; } + + void setHash(uint32_t Value) { Hash = Value; } + Kind Type; - ArrayRef<uint8_t> Data; - ArrayRef<uint8_t> RawData; + ArrayRef<uint8_t> RecordData; + Optional<uint32_t> Hash; }; -template <typename Kind> struct VarStreamArrayExtractor<CVRecord<Kind>> { - Error operator()(StreamRef Stream, uint32_t &Len, - CVRecord<Kind> &Item) const { +} // end namespace codeview + +namespace msf { + +template <typename Kind> +struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> { + Error operator()(ReadableStreamRef Stream, uint32_t &Len, + codeview::CVRecord<Kind> &Item) const { + using namespace codeview; const RecordPrefix *Prefix = nullptr; StreamReader Reader(Stream); uint32_t Offset = Reader.getOffset(); if (auto EC = Reader.readObject(Prefix)) return EC; - Item.Length = Prefix->RecordLen; - if (Item.Length < 2) + if (Prefix->RecordLen < 2) return make_error<CodeViewError>(cv_error_code::corrupt_record); - Item.Type = static_cast<Kind>(uint16_t(Prefix->RecordKind)); + Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind)); Reader.setOffset(Offset); + ArrayRef<uint8_t> RawData; if (auto EC = - Reader.readBytes(Item.RawData, Item.Length + sizeof(uint16_t))) + Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t))) return EC; - Item.Data = Item.RawData.slice(sizeof(RecordPrefix)); - Len = Prefix->RecordLen + 2; + Item = codeview::CVRecord<Kind>(K, RawData); + Len = Item.length(); return Error::success(); } }; -} -} -#endif +} // end namespace msf + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h index 7c88956..b2d3f5e 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h @@ -18,83 +18,17 @@ namespace llvm { namespace codeview { +class SymbolVisitorCallbacks; -template <typename Derived> class CVSymbolVisitor { +class CVSymbolVisitor { public: - CVSymbolVisitor(SymbolVisitorDelegate *Delegate) : Delegate(Delegate) {} + CVSymbolVisitor(SymbolVisitorCallbacks &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 symbols. 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 SYMBOL_RECORD(EnumName, EnumVal, Name) \ - void visit##Name(SymbolRecordKind Kind, Name &Record) {} -#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "CVSymbolTypes.def" - - void visitSymbolRecord(const CVRecord<SymbolKind> &Record) { - ArrayRef<uint8_t> Data = Record.Data; - auto *DerivedThis = static_cast<Derived *>(this); - DerivedThis->visitSymbolBegin(Record.Type, Data); - uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0; - switch (Record.Type) { - default: - DerivedThis->visitUnknownSymbol(Record.Type, Data); - break; -#define SYMBOL_RECORD(EnumName, EnumVal, Name) \ - case EnumName: { \ - SymbolRecordKind RK = static_cast<SymbolRecordKind>(EnumName); \ - auto Result = Name::deserialize(RK, RecordOffset, Data); \ - if (Result.getError()) \ - return parseError(); \ - DerivedThis->visit##Name(Record.Type, *Result); \ - break; \ - } -#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ - SYMBOL_RECORD(EnumVal, EnumVal, AliasName) -#include "CVSymbolTypes.def" - } - DerivedThis->visitSymbolEnd(Record.Type, Record.Data); - } - - /// Visits the symbol records in Data. Sets the error flag on parse failures. - void visitSymbolStream(const CVSymbolArray &Symbols) { - for (const auto &I : Symbols) { - visitSymbolRecord(I); - if (hadError()) - break; - } - } - - /// Action to take on unknown symbols. By default, they are ignored. - void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data) {} - - /// Paired begin/end actions for all symbols. Receives all record data, - /// including the fixed-length record prefix. - void visitSymbolBegin(SymbolKind Leaf, ArrayRef<uint8_t> RecordData) {} - void visitSymbolEnd(SymbolKind Leaf, ArrayRef<uint8_t> OriginalSymData) {} - - /// Helper for returning from a void function when the stream is corrupted. - void parseError() { HadError = true; } + Error visitSymbolRecord(CVSymbol &Record); + Error visitSymbolStream(const CVSymbolArray &Symbols); private: - SymbolVisitorDelegate *Delegate; - /// Whether a symbol stream parsing error was encountered. - bool HadError = false; + SymbolVisitorCallbacks &Callbacks; }; } // end namespace codeview diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeDumper.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeDumper.h new file mode 100644 index 0000000..e1dd6a1 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeDumper.h @@ -0,0 +1,56 @@ +//===-- CVTypeDumper.h - CodeView type info dumper --------------*- 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_CVTYPEDUMPER_H +#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEDUMPER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/ScopedPrinter.h" + +namespace llvm { + +namespace codeview { + +/// Dumper for CodeView type streams found in COFF object files and PDB files. +class CVTypeDumper { +public: + explicit CVTypeDumper(TypeDatabase &TypeDB) : TypeDB(TypeDB) {} + + /// Dumps one type record. Returns false if there was a type parsing error, + /// and true otherwise. This should be called in order, since the dumper + /// maintains state about previous records which are necessary for cross + /// type references. + Error dump(const CVType &Record, TypeVisitorCallbacks &Dumper); + + /// Dumps the type records in Types. Returns false if there was a type stream + /// parse error, and true otherwise. + Error dump(const CVTypeArray &Types, TypeVisitorCallbacks &Dumper); + + /// 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. + Error dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper); + + static void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, + TypeIndex TI, TypeDatabase &DB); + +private: + TypeDatabase &TypeDB; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index 930ac69..d1b0363 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H #define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H +#include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" @@ -22,16 +23,14 @@ class CVTypeVisitor { public: explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks); - Error visitTypeRecord(const CVRecord<TypeLeafKind> &Record); + Error visitTypeRecord(CVType &Record); + Error visitMemberRecord(CVMemberRecord &Record); /// Visits the type records in Data. Sets the error flag on parse failures. Error visitTypeStream(const CVTypeArray &Types); - Error skipPadding(ArrayRef<uint8_t> &Data); - - /// Visits individual member records of a field list record. Member records do - /// not describe their own length, and need special handling. - Error visitFieldList(const CVRecord<TypeLeafKind> &Record); + Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList); + Error visitFieldListMemberStream(msf::StreamReader Reader); private: /// The interface to the class that gets notified of each visitation. diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index 1ee203b..e21cfa3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -21,8 +21,6 @@ namespace codeview { enum class TypeRecordKind : uint16_t { #define TYPE_RECORD(lf_ename, value, name) name = value, #include "TypeRecords.def" - // FIXME: Add serialization support - FieldList = 0x1203, }; /// Duplicate copy of the above enum, but using the official CV names. Useful @@ -278,6 +276,7 @@ enum class MethodOptions : uint16_t { CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(MethodOptions) /// Equivalent to CV_modifier_t. +/// TODO: Add flag for _Atomic modifier enum class ModifierOptions : uint16_t { None = 0x0000, Const = 0x0001, @@ -526,7 +525,7 @@ enum class RegisterId : uint16_t { }; /// These values correspond to the THUNK_ORDINAL enumeration. -enum class ThunkOrdinal { +enum class ThunkOrdinal : uint8_t { Standard, ThisAdjustor, Vcall, @@ -536,7 +535,7 @@ enum class ThunkOrdinal { BranchIsland }; -enum class TrampolineType { TrampIncremental, BranchIsland }; +enum class TrampolineType : uint16_t { TrampIncremental, BranchIsland }; // These values correspond to the CV_SourceChksum_t enumeration. enum class FileChecksumKind : uint8_t { None, MD5, SHA1, SHA256 }; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h index 69ff29a..0556fd0 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h @@ -21,6 +21,7 @@ enum class cv_error_code { insufficient_buffer, operation_unsupported, corrupt_record, + unknown_member_record, }; /// Base class for errors originating when parsing raw PDB files diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewOStream.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewOStream.h deleted file mode 100644 index 14d057a..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewOStream.h +++ /dev/null @@ -1,39 +0,0 @@ -//===- CodeViewOStream.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_CODEVIEWOSTREAM_H -#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWOSTREAM_H - -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" - -namespace llvm { -namespace codeview { - -template <typename Writer> class CodeViewOStream { -private: - CodeViewOStream(const CodeViewOStream &) = delete; - CodeViewOStream &operator=(const CodeViewOStream &) = delete; - -public: - typedef typename Writer::LabelType LabelType; - -public: - explicit CodeViewOStream(Writer &W); - -private: - uint64_t size() const { return W.tell(); } - -private: - Writer &W; -}; -} -} - -#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h new file mode 100644 index 0000000..5a036b9 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -0,0 +1,170 @@ +//===- CodeViewRecordIO.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_CODEVIEWRECORDIO_H +#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/MSF/StreamReader.h" +#include "llvm/DebugInfo/MSF/StreamWriter.h" +#include "llvm/Support/Error.h" +#include <cassert> +#include <cstdint> +#include <type_traits> + +namespace llvm { +namespace codeview { + +class CodeViewRecordIO { + uint32_t getCurrentOffset() const { + return (isWriting()) ? Writer->getOffset() : Reader->getOffset(); + } + +public: + explicit CodeViewRecordIO(msf::StreamReader &Reader) : Reader(&Reader) {} + explicit CodeViewRecordIO(msf::StreamWriter &Writer) : Writer(&Writer) {} + + Error beginRecord(Optional<uint32_t> MaxLength); + Error endRecord(); + + Error mapInteger(TypeIndex &TypeInd); + + bool isReading() const { return Reader != nullptr; } + bool isWriting() const { return !isReading(); } + + uint32_t maxFieldLength() const; + + template <typename T> Error mapObject(T &Value) { + if (isWriting()) + return Writer->writeObject(Value); + + const T *ValuePtr; + if (auto EC = Reader->readObject(ValuePtr)) + return EC; + Value = *ValuePtr; + return Error::success(); + } + + template <typename T> Error mapInteger(T &Value) { + if (isWriting()) + return Writer->writeInteger(Value); + + return Reader->readInteger(Value); + } + + template <typename T> Error mapEnum(T &Value) { + if (sizeof(Value) > maxFieldLength()) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer); + + using U = typename std::underlying_type<T>::type; + U X; + if (isWriting()) + X = static_cast<U>(Value); + + if (auto EC = mapInteger(X)) + return EC; + if (isReading()) + Value = static_cast<T>(X); + return Error::success(); + } + + Error mapEncodedInteger(int64_t &Value); + Error mapEncodedInteger(uint64_t &Value); + Error mapEncodedInteger(APSInt &Value); + Error mapStringZ(StringRef &Value); + Error mapGuid(StringRef &Guid); + + Error mapStringZVectorZ(std::vector<StringRef> &Value); + + template <typename SizeType, typename T, typename ElementMapper> + Error mapVectorN(T &Items, const ElementMapper &Mapper) { + SizeType Size; + if (isWriting()) { + Size = static_cast<SizeType>(Items.size()); + if (auto EC = Writer->writeInteger(Size)) + return EC; + + for (auto &X : Items) { + if (auto EC = Mapper(*this, X)) + return EC; + } + } else { + if (auto EC = Reader->readInteger(Size)) + return EC; + for (SizeType I = 0; I < Size; ++I) { + typename T::value_type Item; + if (auto EC = Mapper(*this, Item)) + return EC; + Items.push_back(Item); + } + } + + return Error::success(); + } + + template <typename T, typename ElementMapper> + Error mapVectorTail(T &Items, const ElementMapper &Mapper) { + if (isWriting()) { + for (auto &Item : Items) { + if (auto EC = Mapper(*this, Item)) + return EC; + } + } else { + typename T::value_type Field; + // Stop when we run out of bytes or we hit record padding bytes. + while (!Reader->empty() && Reader->peek() < 0xf0 /* LF_PAD0 */) { + if (auto EC = Mapper(*this, Field)) + return EC; + Items.push_back(Field); + } + } + return Error::success(); + } + + Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes); + Error mapByteVectorTail(std::vector<uint8_t> &Bytes); + + Error skipPadding(); + +private: + Error writeEncodedSignedInteger(const int64_t &Value); + Error writeEncodedUnsignedInteger(const uint64_t &Value); + + struct RecordLimit { + uint32_t BeginOffset; + Optional<uint32_t> MaxLength; + + Optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const { + if (!MaxLength.hasValue()) + return None; + assert(CurrentOffset >= BeginOffset); + + uint32_t BytesUsed = CurrentOffset - BeginOffset; + if (BytesUsed >= *MaxLength) + return 0; + return *MaxLength - BytesUsed; + } + }; + + SmallVector<RecordLimit, 2> Limits; + + msf::StreamReader *Reader = nullptr; + msf::StreamWriter *Writer = nullptr; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/EnumTables.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/EnumTables.h index 021288e..10d1c58 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/EnumTables.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/EnumTables.h @@ -20,6 +20,7 @@ namespace llvm { namespace codeview { ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames(); +ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames(); ArrayRef<EnumEntry<uint16_t>> getRegisterNames(); ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames(); ArrayRef<EnumEntry<uint16_t>> getLocalFlagNames(); diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h deleted file mode 100644 index 75a0751..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h +++ /dev/null @@ -1,65 +0,0 @@ -//===- FieldListRecordBuilder.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_FIELDLISTRECORDBUILDER_H -#define LLVM_DEBUGINFO_CODEVIEW_FIELDLISTRECORDBUILDER_H - -#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" - -namespace llvm { -namespace codeview { - -class MethodInfo { -public: - MethodInfo() : Access(), Kind(), Options(), Type(), VTableSlotOffset(-1) {} - - MethodInfo(MemberAccess Access, MethodKind Kind, MethodOptions Options, - TypeIndex Type, int32_t VTableSlotOffset) - : Access(Access), Kind(Kind), Options(Options), Type(Type), - VTableSlotOffset(VTableSlotOffset) {} - - MemberAccess getAccess() const { return Access; } - MethodKind getKind() const { return Kind; } - MethodOptions getOptions() const { return Options; } - TypeIndex getType() const { return Type; } - int32_t getVTableSlotOffset() const { return VTableSlotOffset; } - -private: - MemberAccess Access; - MethodKind Kind; - MethodOptions Options; - TypeIndex Type; - int32_t VTableSlotOffset; -}; - -class FieldListRecordBuilder : public ListRecordBuilder { -private: - FieldListRecordBuilder(const FieldListRecordBuilder &) = delete; - void operator=(const FieldListRecordBuilder &) = delete; - -public: - FieldListRecordBuilder(); - - void reset() { ListRecordBuilder::reset(); } - - void writeBaseClass(const BaseClassRecord &Record); - void writeEnumerator(const EnumeratorRecord &Record); - void writeDataMember(const DataMemberRecord &Record); - void writeOneMethod(const OneMethodRecord &Record); - void writeOverloadedMethod(const OverloadedMethodRecord &Record); - void writeNestedType(const NestedTypeRecord &Record); - void writeStaticDataMember(const StaticDataMemberRecord &Record); - void writeVirtualBaseClass(const VirtualBaseClassRecord &Record); - void writeVFPtr(const VFPtrRecord &Type); -}; -} -} - -#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h deleted file mode 100644 index 00bf03d4..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h +++ /dev/null @@ -1,65 +0,0 @@ -//===- ListRecordBuilder.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_LISTRECORDBUILDER_H -#define LLVM_DEBUGINFO_CODEVIEW_LISTRECORDBUILDER_H - -#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h" - -namespace llvm { -namespace codeview { -class TypeTableBuilder; - -class ListRecordBuilder { -private: - ListRecordBuilder(const ListRecordBuilder &) = delete; - ListRecordBuilder &operator=(const ListRecordBuilder &) = delete; - -protected: - const int MethodKindShift = 2; - - explicit ListRecordBuilder(TypeRecordKind Kind); - -public: - llvm::StringRef str() { return Builder.str(); } - - void reset() { - Builder.reset(Kind); - ContinuationOffsets.clear(); - SubrecordStart = 0; - } - - void writeListContinuation(const ListContinuationRecord &R); - - /// Writes this list record as a possible sequence of records. - TypeIndex writeListRecord(TypeTableBuilder &Table); - -protected: - void finishSubRecord(); - - TypeRecordBuilder &getBuilder() { return Builder; } - -private: - size_t getLastContinuationStart() const { - return ContinuationOffsets.empty() ? 0 : ContinuationOffsets.back(); - } - size_t getLastContinuationEnd() const { return Builder.size(); } - size_t getLastContinuationSize() const { - return getLastContinuationEnd() - getLastContinuationStart(); - } - - TypeRecordKind Kind; - TypeRecordBuilder Builder; - SmallVector<size_t, 4> ContinuationOffsets; - size_t SubrecordStart = 0; -}; -} -} - -#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h deleted file mode 100644 index 002f885..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h +++ /dev/null @@ -1,48 +0,0 @@ -//===- MemoryTypeTableBuilder.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_MEMORYTYPETABLEBUILDER_H -#define LLVM_DEBUGINFO_CODEVIEW_MEMORYTYPETABLEBUILDER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" -#include <vector> - -namespace llvm { -namespace codeview { - -class MemoryTypeTableBuilder : public TypeTableBuilder { -public: - MemoryTypeTableBuilder() {} - - bool empty() const { return Records.empty(); } - - template <typename TFunc> void ForEachRecord(TFunc Func) { - uint32_t Index = TypeIndex::FirstNonSimpleIndex; - - for (StringRef R : Records) { - Func(TypeIndex(Index), R); - ++Index; - } - } - -protected: - TypeIndex writeRecord(llvm::StringRef Data) override; - -private: - std::vector<StringRef> Records; - BumpPtrAllocator RecordStorage; - DenseMap<StringRef, TypeIndex> HashedRecords; -}; - -} // end namespace codeview -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_MEMORYTYPETABLEBUILDER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/MethodListRecordBuilder.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/MethodListRecordBuilder.h deleted file mode 100644 index faa404d..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/MethodListRecordBuilder.h +++ /dev/null @@ -1,35 +0,0 @@ -//===- MethodListRecordBuilder.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_METHODLISTRECORDBUILDER_H -#define LLVM_DEBUGINFO_CODEVIEW_METHODLISTRECORDBUILDER_H - -#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h" - -namespace llvm { -namespace codeview { - -class MethodInfo; - -class MethodListRecordBuilder : public ListRecordBuilder { -private: - MethodListRecordBuilder(const MethodListRecordBuilder &) = delete; - MethodListRecordBuilder &operator=(const MethodListRecordBuilder &) = delete; - -public: - MethodListRecordBuilder(); - - void writeMethod(MemberAccess Access, MethodKind Kind, MethodOptions Options, - TypeIndex Type, int32_t VTableSlotOffset); - void writeMethod(const MethodInfo &Method); -}; -} -} - -#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h index 6affac8..8860ae4 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h @@ -11,8 +11,8 @@ #define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H #include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" -#include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/DebugInfo/MSF/StreamRef.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -59,29 +59,31 @@ struct ColumnNumberEntry { class ModuleSubstream { public: ModuleSubstream(); - ModuleSubstream(ModuleSubstreamKind Kind, StreamRef Data); - static Error initialize(StreamRef Stream, ModuleSubstream &Info); + ModuleSubstream(ModuleSubstreamKind Kind, msf::ReadableStreamRef Data); + static Error initialize(msf::ReadableStreamRef Stream, ModuleSubstream &Info); uint32_t getRecordLength() const; ModuleSubstreamKind getSubstreamKind() const; - StreamRef getRecordData() const; + msf::ReadableStreamRef getRecordData() const; private: ModuleSubstreamKind Kind; - StreamRef Data; + msf::ReadableStreamRef Data; }; -template <> struct VarStreamArrayExtractor<ModuleSubstream> { - Error operator()(StreamRef Stream, uint32_t &Length, - ModuleSubstream &Info) const { - if (auto EC = ModuleSubstream::initialize(Stream, Info)) +typedef msf::VarStreamArray<ModuleSubstream> ModuleSubstreamArray; +} // namespace codeview + +namespace msf { +template <> struct VarStreamArrayExtractor<codeview::ModuleSubstream> { + Error operator()(ReadableStreamRef Stream, uint32_t &Length, + codeview::ModuleSubstream &Info) const { + if (auto EC = codeview::ModuleSubstream::initialize(Stream, Info)) return EC; Length = Info.getRecordLength(); return Error::success(); } }; - -typedef VarStreamArray<ModuleSubstream> ModuleSubstreamArray; -} -} +} // namespace msf +} // namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h index 6df2309..f9927d6 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h @@ -10,28 +10,75 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H #define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/ModuleSubstream.h" -#include "llvm/DebugInfo/CodeView/StreamReader.h" -#include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/DebugInfo/MSF/StreamReader.h" +#include "llvm/DebugInfo/MSF/StreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> namespace llvm { + namespace codeview { struct LineColumnEntry { support::ulittle32_t NameIndex; - FixedStreamArray<LineNumberEntry> LineNumbers; - FixedStreamArray<ColumnNumberEntry> Columns; + msf::FixedStreamArray<LineNumberEntry> LineNumbers; + msf::FixedStreamArray<ColumnNumberEntry> Columns; }; -template <> class VarStreamArrayExtractor<LineColumnEntry> { +struct FileChecksumEntry { + uint32_t FileNameOffset; // Byte offset of filename in global stringtable. + FileChecksumKind Kind; // The type of checksum. + ArrayRef<uint8_t> Checksum; // The bytes of the checksum. +}; + +typedef msf::VarStreamArray<LineColumnEntry> LineInfoArray; +typedef msf::VarStreamArray<FileChecksumEntry> FileChecksumArray; + +class IModuleSubstreamVisitor { public: - VarStreamArrayExtractor(const LineSubstreamHeader *Header) : Header(Header) {} + virtual ~IModuleSubstreamVisitor() = default; - Error operator()(StreamRef Stream, uint32_t &Len, - LineColumnEntry &Item) const { + virtual Error visitUnknown(ModuleSubstreamKind Kind, + msf::ReadableStreamRef Data) = 0; + virtual Error visitSymbols(msf::ReadableStreamRef Data); + virtual Error visitLines(msf::ReadableStreamRef Data, + const LineSubstreamHeader *Header, + const LineInfoArray &Lines); + virtual Error visitStringTable(msf::ReadableStreamRef Data); + virtual Error visitFileChecksums(msf::ReadableStreamRef Data, + const FileChecksumArray &Checksums); + virtual Error visitFrameData(msf::ReadableStreamRef Data); + virtual Error visitInlineeLines(msf::ReadableStreamRef Data); + virtual Error visitCrossScopeImports(msf::ReadableStreamRef Data); + virtual Error visitCrossScopeExports(msf::ReadableStreamRef Data); + virtual Error visitILLines(msf::ReadableStreamRef Data); + virtual Error visitFuncMDTokenMap(msf::ReadableStreamRef Data); + virtual Error visitTypeMDTokenMap(msf::ReadableStreamRef Data); + virtual Error visitMergedAssemblyInput(msf::ReadableStreamRef Data); + virtual Error visitCoffSymbolRVA(msf::ReadableStreamRef Data); +}; + +Error visitModuleSubstream(const ModuleSubstream &R, + IModuleSubstreamVisitor &V); +} // end namespace codeview + +namespace msf { + +template <> class VarStreamArrayExtractor<codeview::LineColumnEntry> { +public: + VarStreamArrayExtractor(const codeview::LineSubstreamHeader *Header) + : Header(Header) {} + + Error operator()(ReadableStreamRef Stream, uint32_t &Len, + codeview::LineColumnEntry &Item) const { + using namespace codeview; const LineFileBlockHeader *BlockHeader; StreamReader Reader(Stream); if (auto EC = Reader.readObject(BlockHeader)) @@ -61,19 +108,14 @@ public: } private: - const LineSubstreamHeader *Header; + const codeview::LineSubstreamHeader *Header; }; -struct FileChecksumEntry { - uint32_t FileNameOffset; // Byte offset of filename in global stringtable. - FileChecksumKind Kind; // The type of checksum. - ArrayRef<uint8_t> Checksum; // The bytes of the checksum. -}; - -template <> class VarStreamArrayExtractor<FileChecksumEntry> { +template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> { public: - Error operator()(StreamRef Stream, uint32_t &Len, - FileChecksumEntry &Item) const { + Error operator()(ReadableStreamRef Stream, uint32_t &Len, + codeview::FileChecksumEntry &Item) const { + using namespace codeview; const FileChecksum *Header; StreamReader Reader(Stream); if (auto EC = Reader.readObject(Header)) @@ -87,35 +129,8 @@ public: } }; -typedef VarStreamArray<LineColumnEntry> LineInfoArray; -typedef VarStreamArray<FileChecksumEntry> FileChecksumArray; - -class IModuleSubstreamVisitor { -public: - virtual ~IModuleSubstreamVisitor() {} - - virtual Error visitUnknown(ModuleSubstreamKind Kind, StreamRef Data) = 0; - virtual Error visitSymbols(StreamRef Data); - virtual Error visitLines(StreamRef Data, const LineSubstreamHeader *Header, - const LineInfoArray &Lines); - virtual Error visitStringTable(StreamRef Data); - virtual Error visitFileChecksums(StreamRef Data, - const FileChecksumArray &Checksums); - virtual Error visitFrameData(StreamRef Data); - virtual Error visitInlineeLines(StreamRef Data); - virtual Error visitCrossScopeImports(StreamRef Data); - virtual Error visitCrossScopeExports(StreamRef Data); - virtual Error visitILLines(StreamRef Data); - virtual Error visitFuncMDTokenMap(StreamRef Data); - virtual Error visitTypeMDTokenMap(StreamRef Data); - virtual Error visitMergedAssemblyInput(StreamRef Data); - virtual Error visitCoffSymbolRVA(StreamRef Data); -}; - -Error visitModuleSubstream(const ModuleSubstream &R, - IModuleSubstreamVisitor &V); +} // end namespace msf -} // namespace codeview -} // namespace llvm +} // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h index 84179f5..97b6f56 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h @@ -13,8 +13,11 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Endian.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/MSF/StreamReader.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include <cinttypes> #include <tuple> @@ -24,8 +27,12 @@ using llvm::support::little32_t; using llvm::support::ulittle16_t; using llvm::support::ulittle32_t; +/// Limit on the size of all codeview symbol and type records, including the +/// RecordPrefix. MSVC does not emit any records larger than this. +enum : unsigned { MaxRecordLength = 0xFF00 }; + struct RecordPrefix { - ulittle16_t RecordLen; // Record length, starting from &Leaf. + ulittle16_t RecordLen; // Record length, starting from &RecordKind. ulittle16_t RecordKind; // Record kind enum (SymRecordKind or TypeRecordKind) }; @@ -34,54 +41,40 @@ struct RecordPrefix { StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData); StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData); -/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if -/// there are not enough bytes remaining. Reinterprets the consumed bytes as a -/// T object and points 'Res' at them. -template <typename T, typename U> -inline std::error_code consumeObject(U &Data, const T *&Res) { - if (Data.size() < sizeof(*Res)) - return std::make_error_code(std::errc::illegal_byte_sequence); - Res = reinterpret_cast<const T *>(Data.data()); - Data = Data.drop_front(sizeof(*Res)); - return std::error_code(); -} - -inline std::error_code consume(ArrayRef<uint8_t> &Data) { - return std::error_code(); -} +inline Error consume(msf::StreamReader &Reader) { return Error::success(); } /// Decodes a numeric "leaf" value. These are integer literals encountered in /// the type stream. If the value is positive and less than LF_NUMERIC (1 << /// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR /// that indicates the bitwidth and sign of the numeric data. -std::error_code consume(ArrayRef<uint8_t> &Data, APSInt &Num); -std::error_code consume(StringRef &Data, APSInt &Num); +Error consume(msf::StreamReader &Reader, APSInt &Num); /// Decodes a numeric leaf value that is known to be a particular type. -std::error_code consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Value); +Error consume_numeric(msf::StreamReader &Reader, uint64_t &Value); /// Decodes signed and unsigned fixed-length integers. -std::error_code consume(ArrayRef<uint8_t> &Data, uint32_t &Item); -std::error_code consume(StringRef &Data, uint32_t &Item); -std::error_code consume(ArrayRef<uint8_t> &Data, int32_t &Item); +Error consume(msf::StreamReader &Reader, uint32_t &Item); +Error consume(msf::StreamReader &Reader, int32_t &Item); /// Decodes a null terminated string. -std::error_code consume(ArrayRef<uint8_t> &Data, StringRef &Item); +Error consume(msf::StreamReader &Reader, StringRef &Item); + +Error consume(StringRef &Data, APSInt &Num); +Error consume(StringRef &Data, uint32_t &Item); /// Decodes an arbitrary object whose layout matches that of the underlying /// byte sequence, and returns a pointer to the object. -template <typename T> -std::error_code consume(ArrayRef<uint8_t> &Data, T *&Item) { - return consumeObject(Data, Item); +template <typename T> Error consume(msf::StreamReader &Reader, T *&Item) { + return Reader.readObject(Item); } template <typename T, typename U> struct serialize_conditional_impl { serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {} - std::error_code deserialize(ArrayRef<uint8_t> &Data) const { + Error deserialize(msf::StreamReader &Reader) const { if (!Func()) - return std::error_code(); - return consume(Data, Item); + return Error::success(); + return consume(Reader, Item); } T &Item; @@ -96,22 +89,8 @@ serialize_conditional_impl<T, U> serialize_conditional(T &Item, U Func) { template <typename T, typename U> struct serialize_array_impl { serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {} - std::error_code deserialize(ArrayRef<uint8_t> &Data) const { - uint32_t N = Func(); - if (N == 0) - return std::error_code(); - - uint32_t Size = sizeof(T) * N; - - if (Size / sizeof(T) != N) - return std::make_error_code(std::errc::illegal_byte_sequence); - - if (Data.size() < Size) - return std::make_error_code(std::errc::illegal_byte_sequence); - - Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.data()), N); - Data = Data.drop_front(Size); - return std::error_code(); + Error deserialize(msf::StreamReader &Reader) const { + return Reader.readArray(Item, Func()); } ArrayRef<T> &Item; @@ -121,15 +100,15 @@ template <typename T, typename U> struct serialize_array_impl { template <typename T> struct serialize_vector_tail_impl { serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {} - std::error_code deserialize(ArrayRef<uint8_t> &Data) const { + Error deserialize(msf::StreamReader &Reader) const { T Field; // Stop when we run out of bytes or we hit record padding bytes. - while (!Data.empty() && Data.front() < LF_PAD0) { - if (auto EC = consume(Data, Field)) + while (!Reader.empty() && Reader.peek() < LF_PAD0) { + if (auto EC = consume(Reader, Field)) return EC; Item.push_back(Field); } - return std::error_code(); + return Error::success(); } std::vector<T> &Item; @@ -139,21 +118,18 @@ struct serialize_null_term_string_array_impl { serialize_null_term_string_array_impl(std::vector<StringRef> &Item) : Item(Item) {} - std::error_code deserialize(ArrayRef<uint8_t> &Data) const { - if (Data.empty()) - return std::make_error_code(std::errc::illegal_byte_sequence); + Error deserialize(msf::StreamReader &Reader) const { + if (Reader.empty()) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer, + "Null terminated string is empty!"); - StringRef Field; - // Stop when we run out of bytes or we hit record padding bytes. - while (Data.front() != 0) { - if (auto EC = consume(Data, Field)) + while (Reader.peek() != 0) { + StringRef Field; + if (auto EC = Reader.readZeroString(Field)) return EC; Item.push_back(Field); - if (Data.empty()) - return std::make_error_code(std::errc::illegal_byte_sequence); } - Data = Data.drop_front(1); - return std::error_code(); + return Reader.skip(1); } std::vector<StringRef> &Item; @@ -162,10 +138,9 @@ struct serialize_null_term_string_array_impl { template <typename T> struct serialize_arrayref_tail_impl { serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {} - std::error_code deserialize(ArrayRef<uint8_t> &Data) const { - uint32_t Count = Data.size() / sizeof(T); - Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.begin()), Count); - return std::error_code(); + Error deserialize(msf::StreamReader &Reader) const { + uint32_t Count = Reader.bytesRemaining() / sizeof(T); + return Reader.readArray(Item, Count); } ArrayRef<T> &Item; @@ -174,8 +149,8 @@ template <typename T> struct serialize_arrayref_tail_impl { template <typename T> struct serialize_numeric_impl { serialize_numeric_impl(T &Item) : Item(Item) {} - std::error_code deserialize(ArrayRef<uint8_t> &Data) const { - return consume_numeric(Data, Item); + Error deserialize(msf::StreamReader &Reader) const { + return consume_numeric(Reader, Item); } T &Item; @@ -226,52 +201,50 @@ template <typename T> serialize_numeric_impl<T> serialize_numeric(T &Item) { #define CV_NUMERIC_FIELD(I) serialize_numeric(I) template <typename T, typename U> -std::error_code consume(ArrayRef<uint8_t> &Data, - const serialize_conditional_impl<T, U> &Item) { - return Item.deserialize(Data); +Error consume(msf::StreamReader &Reader, + const serialize_conditional_impl<T, U> &Item) { + return Item.deserialize(Reader); } template <typename T, typename U> -std::error_code consume(ArrayRef<uint8_t> &Data, - const serialize_array_impl<T, U> &Item) { - return Item.deserialize(Data); +Error consume(msf::StreamReader &Reader, + const serialize_array_impl<T, U> &Item) { + return Item.deserialize(Reader); } -inline std::error_code -consume(ArrayRef<uint8_t> &Data, - const serialize_null_term_string_array_impl &Item) { - return Item.deserialize(Data); +inline Error consume(msf::StreamReader &Reader, + const serialize_null_term_string_array_impl &Item) { + return Item.deserialize(Reader); } template <typename T> -std::error_code consume(ArrayRef<uint8_t> &Data, - const serialize_vector_tail_impl<T> &Item) { - return Item.deserialize(Data); +Error consume(msf::StreamReader &Reader, + const serialize_vector_tail_impl<T> &Item) { + return Item.deserialize(Reader); } template <typename T> -std::error_code consume(ArrayRef<uint8_t> &Data, - const serialize_arrayref_tail_impl<T> &Item) { - return Item.deserialize(Data); +Error consume(msf::StreamReader &Reader, + const serialize_arrayref_tail_impl<T> &Item) { + return Item.deserialize(Reader); } template <typename T> -std::error_code consume(ArrayRef<uint8_t> &Data, - const serialize_numeric_impl<T> &Item) { - return Item.deserialize(Data); +Error consume(msf::StreamReader &Reader, + const serialize_numeric_impl<T> &Item) { + return Item.deserialize(Reader); } template <typename T, typename U, typename... Args> -std::error_code consume(ArrayRef<uint8_t> &Data, T &&X, U &&Y, - Args &&... Rest) { - if (auto EC = consume(Data, X)) +Error consume(msf::StreamReader &Reader, T &&X, U &&Y, Args &&... Rest) { + if (auto EC = consume(Reader, X)) return EC; - return consume(Data, Y, std::forward<Args>(Rest)...); + return consume(Reader, Y, std::forward<Args>(Rest)...); } #define CV_DESERIALIZE(...) \ if (auto EC = consume(__VA_ARGS__)) \ - return EC; + return std::move(EC); } } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h deleted file mode 100644 index 0b9349a..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h +++ /dev/null @@ -1,275 +0,0 @@ -//===- StreamArray.h - Array backed by an arbitrary stream ----------------===// -// -// 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_STREAMARRAY_H -#define LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H - -#include "llvm/DebugInfo/CodeView/StreamRef.h" -#include "llvm/Support/Error.h" - -#include <functional> -#include <type_traits> - -namespace llvm { -namespace codeview { - -/// VarStreamArrayExtractor is intended to be specialized to provide customized -/// extraction logic. On input it receives a StreamRef pointing to the -/// beginning of the next record, but where the length of the record is not yet -/// known. Upon completion, it should return an appropriate Error instance if -/// a record could not be extracted, or if one could be extracted it should -/// return success and set Len to the number of bytes this record occupied in -/// the underlying stream, and it should fill out the fields of the value type -/// Item appropriately to represent the current record. -/// -/// You can specialize this template for your own custom value types to avoid -/// having to specify a second template argument to VarStreamArray (documented -/// below). -template <typename T> struct VarStreamArrayExtractor { - // Method intentionally deleted. You must provide an explicit specialization - // with the following method implemented. - Error operator()(StreamRef Stream, uint32_t &Len, T &Item) const = delete; -}; - -/// VarStreamArray represents an array of variable length records backed by a -/// stream. This could be a contiguous sequence of bytes in memory, it could -/// be a file on disk, or it could be a PDB stream where bytes are stored as -/// discontiguous blocks in a file. Usually it is desirable to treat arrays -/// as contiguous blocks of memory, but doing so with large PDB files, for -/// example, could mean allocating huge amounts of memory just to allow -/// re-ordering of stream data to be contiguous before iterating over it. By -/// abstracting this out, we need not duplicate this memory, and we can -/// iterate over arrays in arbitrarily formatted streams. Elements are parsed -/// lazily on iteration, so there is no upfront cost associated with building -/// a VarStreamArray, no matter how large it may be. -/// -/// You create a VarStreamArray by specifying a ValueType and an Extractor type. -/// If you do not specify an Extractor type, it expects you to specialize -/// VarStreamArrayExtractor<T> for your ValueType. -/// -/// By default an Extractor is default constructed in the class, but in some -/// cases you might find it useful for an Extractor to maintain state across -/// extractions. In this case you can provide your own Extractor through a -/// secondary constructor. The following examples show various ways of -/// creating a VarStreamArray. -/// -/// // Will use VarStreamArrayExtractor<MyType> as the extractor. -/// VarStreamArray<MyType> MyTypeArray; -/// -/// // Will use a default-constructed MyExtractor as the extractor. -/// VarStreamArray<MyType, MyExtractor> MyTypeArray2; -/// -/// // Will use the specific instance of MyExtractor provided. -/// // MyExtractor need not be default-constructible in this case. -/// MyExtractor E(SomeContext); -/// VarStreamArray<MyType, MyExtractor> MyTypeArray3(E); -/// -template <typename ValueType, typename Extractor> class VarStreamArrayIterator; - -template <typename ValueType, - typename Extractor = VarStreamArrayExtractor<ValueType>> -class VarStreamArray { - friend class VarStreamArrayIterator<ValueType, Extractor>; - -public: - typedef VarStreamArrayIterator<ValueType, Extractor> Iterator; - - VarStreamArray() {} - explicit VarStreamArray(const Extractor &E) : E(E) {} - - explicit VarStreamArray(StreamRef Stream) : Stream(Stream) {} - VarStreamArray(StreamRef Stream, const Extractor &E) : Stream(Stream), E(E) {} - - VarStreamArray(const VarStreamArray<ValueType, Extractor> &Other) - : Stream(Other.Stream), E(Other.E) {} - - Iterator begin(bool *HadError = nullptr) const { - return Iterator(*this, E, HadError); - } - - Iterator end() const { return Iterator(E); } - - const Extractor &getExtractor() const { return E; } - - StreamRef getUnderlyingStream() const { return Stream; } - -private: - StreamRef Stream; - Extractor E; -}; - -template <typename ValueType, typename Extractor> class VarStreamArrayIterator { - typedef VarStreamArrayIterator<ValueType, Extractor> IterType; - typedef VarStreamArray<ValueType, Extractor> ArrayType; - -public: - VarStreamArrayIterator(const ArrayType &Array, const Extractor &E, - bool *HadError = nullptr) - : IterRef(Array.Stream), Array(&Array), HadError(HadError), Extract(E) { - if (IterRef.getLength() == 0) - moveToEnd(); - else { - auto EC = Extract(IterRef, ThisLen, ThisValue); - if (EC) { - consumeError(std::move(EC)); - markError(); - } - } - } - VarStreamArrayIterator() {} - explicit VarStreamArrayIterator(const Extractor &E) : Extract(E) {} - ~VarStreamArrayIterator() {} - - bool operator==(const IterType &R) const { - if (Array && R.Array) { - // Both have a valid array, make sure they're same. - assert(Array == R.Array); - return IterRef == R.IterRef; - } - - // Both iterators are at the end. - if (!Array && !R.Array) - return true; - - // One is not at the end and one is. - return false; - } - - bool operator!=(const IterType &R) { return !(*this == R); } - - const ValueType &operator*() const { - assert(Array && !HasError); - return ThisValue; - } - - IterType &operator++() { - // We are done with the current record, discard it so that we are - // positioned at the next record. - IterRef = IterRef.drop_front(ThisLen); - if (IterRef.getLength() == 0) { - // There is nothing after the current record, we must make this an end - // iterator. - moveToEnd(); - } else { - // There is some data after the current record. - auto EC = Extract(IterRef, ThisLen, ThisValue); - if (EC) { - consumeError(std::move(EC)); - markError(); - } else if (ThisLen == 0) { - // An empty record? Make this an end iterator. - moveToEnd(); - } - } - return *this; - } - - IterType operator++(int) { - IterType Original = *this; - ++*this; - return Original; - } - -private: - void moveToEnd() { - Array = nullptr; - ThisLen = 0; - } - void markError() { - moveToEnd(); - HasError = true; - if (HadError != nullptr) - *HadError = true; - } - - ValueType ThisValue; - StreamRef IterRef; - const ArrayType *Array{nullptr}; - uint32_t ThisLen{0}; - bool HasError{false}; - bool *HadError{nullptr}; - Extractor Extract; -}; - -template <typename T> class FixedStreamArrayIterator; - -template <typename T> class FixedStreamArray { - friend class FixedStreamArrayIterator<T>; - -public: - FixedStreamArray() : Stream() {} - FixedStreamArray(StreamRef Stream) : Stream(Stream) { - assert(Stream.getLength() % sizeof(T) == 0); - } - - const T &operator[](uint32_t Index) const { - assert(Index < size()); - uint32_t Off = Index * sizeof(T); - ArrayRef<uint8_t> Data; - if (auto EC = Stream.readBytes(Off, sizeof(T), Data)) { - assert(false && "Unexpected failure reading from stream"); - // This should never happen since we asserted that the stream length was - // an exact multiple of the element size. - consumeError(std::move(EC)); - } - return *reinterpret_cast<const T *>(Data.data()); - } - - uint32_t size() const { return Stream.getLength() / sizeof(T); } - - FixedStreamArrayIterator<T> begin() const { - return FixedStreamArrayIterator<T>(*this, 0); - } - FixedStreamArrayIterator<T> end() const { - return FixedStreamArrayIterator<T>(*this, size()); - } - - StreamRef getUnderlyingStream() const { return Stream; } - -private: - StreamRef Stream; -}; - -template <typename T> class FixedStreamArrayIterator { -public: - FixedStreamArrayIterator(const FixedStreamArray<T> &Array, uint32_t Index) - : Array(Array), Index(Index) {} - - bool operator==(const FixedStreamArrayIterator<T> &R) { - assert(&Array == &R.Array); - return Index == R.Index; - } - - bool operator!=(const FixedStreamArrayIterator<T> &R) { - return !(*this == R); - } - - const T &operator*() const { return Array[Index]; } - - FixedStreamArrayIterator<T> &operator++() { - assert(Index < Array.size()); - ++Index; - return *this; - } - - FixedStreamArrayIterator<T> operator++(int) { - FixedStreamArrayIterator<T> Original = *this; - ++*this; - return Original; - } - -private: - const FixedStreamArray<T> &Array; - uint32_t Index; -}; - -} // namespace codeview -} // namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h deleted file mode 100644 index 241aec4..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h +++ /dev/null @@ -1,55 +0,0 @@ -//===- StreamInterface.h - Base interface for a stream of data --*- 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_STREAMINTERFACE_H -#define LLVM_DEBUGINFO_CODEVIEW_STREAMINTERFACE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Support/Error.h" -#include <cstdint> - -namespace llvm { -namespace codeview { - -/// StreamInterface abstracts the notion of a data stream. This way, an -/// implementation could implement trivial reading from a contiguous memory -/// buffer or, as in the case of PDB files, reading from a set of possibly -/// discontiguous blocks. The implementation is required to return references -/// to stable memory, so if this is not possible (for example in the case of -/// a PDB file with discontiguous blocks, it must keep its own pool of temp -/// storage. -class StreamInterface { -public: - virtual ~StreamInterface() {} - - // Given an offset into the stream and a number of bytes, attempt to read - // the bytes and set the output ArrayRef to point to a reference into the - // stream, without copying any data. - virtual Error readBytes(uint32_t Offset, uint32_t Size, - ArrayRef<uint8_t> &Buffer) const = 0; - - // Given an offset into the stream, read as much as possible without copying - // any data. - virtual Error readLongestContiguousChunk(uint32_t Offset, - ArrayRef<uint8_t> &Buffer) const = 0; - - // Attempt to write the given bytes into the stream at the desired offset. - // This will always necessitate a copy. Cannot shrink or grow the stream, - // only writes into existing allocated space. - virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const = 0; - - virtual uint32_t getLength() const = 0; - - virtual Error commit() const = 0; -}; - -} // end namespace codeview -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMINTERFACE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h deleted file mode 100644 index 2f497c2..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h +++ /dev/null @@ -1,111 +0,0 @@ -//===- StreamReader.h - Reads bytes and objects from a stream ---*- 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_STREAMREADER_H -#define LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" - -#include <string> - -namespace llvm { -namespace codeview { - -class StreamRef; - -class StreamReader { -public: - StreamReader(StreamRef Stream); - - Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer); - Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size); - Error readInteger(uint16_t &Dest); - Error readInteger(uint32_t &Dest); - Error readZeroString(StringRef &Dest); - Error readFixedString(StringRef &Dest, uint32_t Length); - Error readStreamRef(StreamRef &Ref); - Error readStreamRef(StreamRef &Ref, uint32_t Length); - - template <typename T> Error readEnum(T &Dest) { - typename std::underlying_type<T>::type N; - if (auto EC = readInteger(N)) - return EC; - Dest = static_cast<T>(N); - return Error::success(); - } - - template <typename T> Error readObject(const T *&Dest) { - ArrayRef<uint8_t> Buffer; - if (auto EC = readBytes(Buffer, sizeof(T))) - return EC; - Dest = reinterpret_cast<const T *>(Buffer.data()); - return Error::success(); - } - - template <typename T> - Error readArray(ArrayRef<T> &Array, uint32_t NumElements) { - ArrayRef<uint8_t> Bytes; - if (NumElements == 0) { - Array = ArrayRef<T>(); - return Error::success(); - } - - if (NumElements > UINT32_MAX/sizeof(T)) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); - - if (auto EC = readBytes(Bytes, NumElements * sizeof(T))) - return EC; - Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements); - return Error::success(); - } - - template <typename T, typename U> - Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) { - StreamRef S; - if (auto EC = readStreamRef(S, Size)) - return EC; - Array = VarStreamArray<T, U>(S, Array.getExtractor()); - return Error::success(); - } - - template <typename T> - Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) { - if (NumItems == 0) { - Array = FixedStreamArray<T>(); - return Error::success(); - } - uint32_t Length = NumItems * sizeof(T); - if (Length / sizeof(T) != NumItems) - return make_error<CodeViewError>(cv_error_code::corrupt_record); - if (Offset + Length > Stream.getLength()) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); - StreamRef View = Stream.slice(Offset, Length); - Array = FixedStreamArray<T>(View); - Offset += Length; - return Error::success(); - } - - void setOffset(uint32_t Off) { Offset = Off; } - uint32_t getOffset() const { return Offset; } - uint32_t getLength() const { return Stream.getLength(); } - uint32_t bytesRemaining() const { return getLength() - getOffset(); } - -private: - StreamRef Stream; - uint32_t Offset; -}; -} // namespace codeview -} // namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamRef.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamRef.h deleted file mode 100644 index a4f244a..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamRef.h +++ /dev/null @@ -1,104 +0,0 @@ -//===- StreamRef.h - A copyable reference to a stream -----------*- 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_STREAMREF_H -#define LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H - -#include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" - -namespace llvm { -namespace codeview { - -class StreamRef { -public: - StreamRef() : Stream(nullptr), ViewOffset(0), Length(0) {} - StreamRef(const StreamInterface &Stream) - : Stream(&Stream), ViewOffset(0), Length(Stream.getLength()) {} - StreamRef(const StreamInterface &Stream, uint32_t Offset, uint32_t Length) - : Stream(&Stream), ViewOffset(Offset), Length(Length) {} - - // Use StreamRef.slice() instead. - StreamRef(const StreamRef &S, uint32_t Offset, uint32_t Length) = delete; - - Error readBytes(uint32_t Offset, uint32_t Size, - ArrayRef<uint8_t> &Buffer) const { - if (ViewOffset + Offset < Offset) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); - if (Size + Offset > Length) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); - return Stream->readBytes(ViewOffset + Offset, Size, Buffer); - } - - // Given an offset into the stream, read as much as possible without copying - // any data. - Error readLongestContiguousChunk(uint32_t Offset, - ArrayRef<uint8_t> &Buffer) const { - if (Offset >= Length) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); - - if (auto EC = Stream->readLongestContiguousChunk(Offset, Buffer)) - return EC; - // This StreamRef might refer to a smaller window over a larger stream. In - // that case we will have read out more bytes than we should return, because - // we should not read past the end of the current view. - uint32_t MaxLength = Length - Offset; - if (Buffer.size() > MaxLength) - Buffer = Buffer.slice(0, MaxLength); - return Error::success(); - } - - Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const { - if (Data.size() + Offset > Length) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); - return Stream->writeBytes(ViewOffset + Offset, Data); - } - - uint32_t getLength() const { return Length; } - - Error commit() const { return Stream->commit(); } - - StreamRef drop_front(uint32_t N) const { - if (!Stream) - return StreamRef(); - - N = std::min(N, Length); - return StreamRef(*Stream, ViewOffset + N, Length - N); - } - - StreamRef keep_front(uint32_t N) const { - if (!Stream) - return StreamRef(); - N = std::min(N, Length); - return StreamRef(*Stream, ViewOffset, N); - } - - StreamRef slice(uint32_t Offset, uint32_t Len) const { - return drop_front(Offset).keep_front(Len); - } - - bool operator==(const StreamRef &Other) const { - if (Stream != Other.Stream) - return false; - if (ViewOffset != Other.ViewOffset) - return false; - if (Length != Other.Length) - return false; - return true; - } - -private: - const StreamInterface *Stream; - uint32_t ViewOffset; - uint32_t Length; -}; -} -} - -#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamWriter.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamWriter.h deleted file mode 100644 index 4d393d2..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamWriter.h +++ /dev/null @@ -1,86 +0,0 @@ -//===- StreamWriter.h - Writes bytes and objects to a stream ----*- 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_STREAMWRITER_H -#define LLVM_DEBUGINFO_CODEVIEW_STREAMWRITER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" - -#include <string> - -namespace llvm { -namespace codeview { - -class StreamRef; - -class StreamWriter { -public: - StreamWriter(StreamRef Stream); - - Error writeBytes(ArrayRef<uint8_t> Buffer); - Error writeInteger(uint16_t Dest); - Error writeInteger(uint32_t Dest); - Error writeZeroString(StringRef Str); - Error writeFixedString(StringRef Str); - Error writeStreamRef(StreamRef Ref); - Error writeStreamRef(StreamRef Ref, uint32_t Size); - - template <typename T> Error writeEnum(T Num) { - return writeInteger( - static_cast<typename std::underlying_type<T>::type>(Num)); - } - - template <typename T> Error writeObject(const T &Obj) { - static_assert(!std::is_pointer<T>::value, - "writeObject should not be used with pointers, to write " - "the pointed-to value dereference the pointer before calling " - "writeObject"); - return writeBytes( - ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T))); - } - - template <typename T> Error writeArray(ArrayRef<T> Array) { - if (Array.size() == 0) - return Error::success(); - - if (Array.size() > UINT32_MAX / sizeof(T)) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); - - return writeBytes( - ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()), - Array.size() * sizeof(T))); - } - - template <typename T, typename U> - Error writeArray(VarStreamArray<T, U> Array) { - return writeStreamRef(Array.getUnderlyingStream()); - } - - template <typename T> Error writeArray(FixedStreamArray<T> Array) { - return writeStreamRef(Array.getUnderlyingStream()); - } - - void setOffset(uint32_t Off) { Offset = Off; } - uint32_t getOffset() const { return Offset; } - uint32_t getLength() const { return Stream.getLength(); } - uint32_t bytesRemaining() const { return getLength() - getOffset(); } - -private: - StreamRef Stream; - uint32_t Offset; -}; -} // namespace codeview -} // namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h new file mode 100644 index 0000000..13c2bb1 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h @@ -0,0 +1,74 @@ +//===- SymbolDeserializer.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_SYMBOLDESERIALIZER_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDESERIALIZER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" +#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" +#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h" +#include "llvm/DebugInfo/MSF/ByteStream.h" +#include "llvm/DebugInfo/MSF/StreamReader.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class SymbolVisitorDelegate; +class SymbolDeserializer : public SymbolVisitorCallbacks { + struct MappingInfo { + explicit MappingInfo(ArrayRef<uint8_t> RecordData) + : Stream(RecordData), Reader(Stream), Mapping(Reader) {} + + msf::ByteStream Stream; + msf::StreamReader Reader; + SymbolRecordMapping Mapping; + }; + +public: + explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate) + : Delegate(Delegate) {} + + Error visitSymbolBegin(CVSymbol &Record) override { + assert(!Mapping && "Already in a symbol mapping!"); + Mapping = llvm::make_unique<MappingInfo>(Record.content()); + return Mapping->Mapping.visitSymbolBegin(Record); + } + Error visitSymbolEnd(CVSymbol &Record) override { + assert(Mapping && "Not in a symbol mapping!"); + auto EC = Mapping->Mapping.visitSymbolEnd(Record); + Mapping.reset(); + return EC; + } + +#define SYMBOL_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \ + return visitKnownRecordImpl(CVR, Record); \ + } +#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "CVSymbolTypes.def" + +private: + template <typename T> Error visitKnownRecordImpl(CVSymbol &CVR, T &Record) { + + Record.RecordOffset = + Delegate ? Delegate->getRecordOffset(Mapping->Reader) : 0; + if (auto EC = Mapping->Mapping.visitKnownRecord(CVR, Record)) + return EC; + return Error::success(); + } + + SymbolVisitorDelegate *Delegate; + std::unique_ptr<MappingInfo> Mapping; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h index 30b0a40..823636c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h @@ -10,20 +10,17 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H -#include "SymbolVisitorDelegate.h" - #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" - -#include <stdint.h> +#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h" +#include <cstdint> namespace llvm { - namespace codeview { class SymbolDumpDelegate : public SymbolVisitorDelegate { public: - virtual ~SymbolDumpDelegate() {} + ~SymbolDumpDelegate() override = default; virtual void printRelocatedField(StringRef Label, uint32_t RelocOffset, uint32_t Offset, @@ -31,6 +28,7 @@ public: virtual void printBinaryBlockWithRelocs(StringRef Label, ArrayRef<uint8_t> Block) = 0; }; + } // end namespace codeview } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h index 648e40f..a5419b3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -20,30 +20,30 @@ namespace llvm { class ScopedPrinter; namespace codeview { -class CVTypeDumper; +class TypeDatabase; /// Dumper for CodeView symbol streams found in COFF object files and PDB files. class CVSymbolDumper { public: - CVSymbolDumper(ScopedPrinter &W, CVTypeDumper &CVTD, + CVSymbolDumper(ScopedPrinter &W, TypeDatabase &TypeDB, std::unique_ptr<SymbolDumpDelegate> ObjDelegate, bool PrintRecordBytes) - : W(W), CVTD(CVTD), ObjDelegate(std::move(ObjDelegate)), + : W(W), TypeDB(TypeDB), ObjDelegate(std::move(ObjDelegate)), PrintRecordBytes(PrintRecordBytes) {} /// Dumps one type record. Returns false if there was a type parsing error, /// 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<SymbolKind> &Record); + Error dump(CVRecord<SymbolKind> &Record); /// Dumps the type records in Data. Returns false if there was a type stream /// parse error, and true otherwise. - bool dump(const CVSymbolArray &Symbols); + Error dump(const CVSymbolArray &Symbols); private: ScopedPrinter &W; - CVTypeDumper &CVTD; + TypeDatabase &TypeDB; std::unique_ptr<SymbolDumpDelegate> ObjDelegate; bool PrintRecordBytes; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h index 77e894f..57772d3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -11,23 +11,24 @@ #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" +#include <cstddef> +#include <cstdint> +#include <vector> namespace llvm { namespace codeview { -using llvm::support::ulittle16_t; -using llvm::support::ulittle32_t; -using llvm::support::little32_t; - class SymbolRecord { protected: explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {} @@ -42,216 +43,119 @@ private: // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or // S_LPROC32_DPC_ID class ProcSym : public SymbolRecord { -public: - struct Hdr { - ulittle32_t PtrParent; - ulittle32_t PtrEnd; - ulittle32_t PtrNext; - ulittle32_t CodeSize; - ulittle32_t DbgStart; - ulittle32_t DbgEnd; - TypeIndex FunctionType; - ulittle32_t CodeOffset; - ulittle16_t Segment; - uint8_t Flags; // ProcSymFlags enum - // Name: The null-terminated name follows. - }; - - ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H, - StringRef Name) - : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) { - } + static constexpr uint32_t RelocationOffset = 32; - static ErrorOr<ProcSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return ProcSym(Kind, RecordOffset, H, Name); - } +public: + explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, CodeOffset); - } - - uint32_t RecordOffset; - Hdr Header; + return RecordOffset + RelocationOffset; + } + + uint32_t Parent = 0; + uint32_t End = 0; + uint32_t Next = 0; + uint32_t CodeSize = 0; + uint32_t DbgStart = 0; + uint32_t DbgEnd = 0; + TypeIndex FunctionType; + uint32_t CodeOffset = 0; + uint16_t Segment = 0; + ProcSymFlags Flags = ProcSymFlags::None; StringRef Name; + + uint32_t RecordOffset = 0; }; // S_THUNK32 class Thunk32Sym : public SymbolRecord { public: - struct Hdr { - ulittle32_t Parent; - ulittle32_t End; - ulittle32_t Next; - ulittle32_t Off; - ulittle16_t Seg; - ulittle16_t Len; - uint8_t Ord; // ThunkOrdinal enumeration - // Name: The null-terminated name follows. - // Variant portion of thunk - }; - - Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H, - StringRef Name, ArrayRef<uint8_t> VariantData) - : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name), - VariantData(VariantData) {} - - static ErrorOr<Thunk32Sym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - ArrayRef<uint8_t> VariantData; - - CV_DESERIALIZE(Data, H, Name, CV_ARRAY_FIELD_TAIL(VariantData)); - - return Thunk32Sym(Kind, RecordOffset, H, Name, VariantData); - } + explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} - uint32_t RecordOffset; - Hdr Header; + uint32_t Parent; + uint32_t End; + uint32_t Next; + uint32_t Offset; + uint16_t Segment; + uint16_t Length; + ThunkOrdinal Thunk; StringRef Name; ArrayRef<uint8_t> VariantData; + + uint32_t RecordOffset; }; // S_TRAMPOLINE class TrampolineSym : public SymbolRecord { public: - struct Hdr { - ulittle16_t Type; // TrampolineType enum - ulittle16_t Size; - ulittle32_t ThunkOff; - ulittle32_t TargetOff; - ulittle16_t ThunkSection; - ulittle16_t TargetSection; - }; - - TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H) - : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H) {} - - static ErrorOr<TrampolineSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; + explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} - CV_DESERIALIZE(Data, H); - - return TrampolineSym(Kind, RecordOffset, H); - } + TrampolineType Type; + uint16_t Size; + uint32_t ThunkOffset; + uint32_t TargetOffset; + uint16_t ThunkSection; + uint16_t TargetSection; uint32_t RecordOffset; - Hdr Header; }; // S_SECTION class SectionSym : public SymbolRecord { public: - struct Hdr { - ulittle16_t SectionNumber; - uint8_t Alignment; - uint8_t Reserved; // Must be 0 - ulittle32_t Rva; - ulittle32_t Length; - ulittle32_t Characteristics; - // Name: The null-terminated name follows. - }; - - SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H, - StringRef Name) - : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) { - } - - static ErrorOr<SectionSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - - CV_DESERIALIZE(Data, H, Name); + explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} - return SectionSym(Kind, RecordOffset, H, Name); - } + uint16_t SectionNumber; + uint8_t Alignment; + uint32_t Rva; + uint32_t Length; + uint32_t Characteristics; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; // S_COFFGROUP class CoffGroupSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t Size; - ulittle32_t Characteristics; - ulittle32_t Offset; - ulittle16_t Segment; - // Name: The null-terminated name follows. - }; - - CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H, - StringRef Name) - : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) { - } - - static ErrorOr<CoffGroupSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - - CV_DESERIALIZE(Data, H, Name); + explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} - return CoffGroupSym(Kind, RecordOffset, H, Name); - } + uint32_t Size; + uint32_t Characteristics; + uint32_t Offset; + uint16_t Segment; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; class ScopeEndSym : public SymbolRecord { public: + explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset) : SymbolRecord(Kind), RecordOffset(RecordOffset) {} - static ErrorOr<ScopeEndSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - return ScopeEndSym(Kind, RecordOffset); - } uint32_t RecordOffset; }; class CallerSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t Count; - }; - - CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *Header, - ArrayRef<TypeIndex> Indices) - : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*Header), - Indices(Indices) {} - - static ErrorOr<CallerSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *Header; - ArrayRef<TypeIndex> Indices; - - CV_DESERIALIZE(Data, Header, CV_ARRAY_FIELD_N(Indices, Header->Count)); - - return CallerSym(Kind, RecordOffset, Header, Indices); - } + explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} + std::vector<TypeIndex> Indices; uint32_t RecordOffset; - Hdr Header; - ArrayRef<TypeIndex> Indices; }; struct BinaryAnnotationIterator { @@ -264,7 +168,7 @@ struct BinaryAnnotationIterator { }; BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {} - BinaryAnnotationIterator() {} + BinaryAnnotationIterator() = default; BinaryAnnotationIterator(const BinaryAnnotationIterator &Other) : Data(Other.Data) {} @@ -435,1018 +339,608 @@ private: // S_INLINESITE class InlineSiteSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t PtrParent; - ulittle32_t PtrEnd; - TypeIndex Inlinee; - // BinaryAnnotations - }; - - InlineSiteSym(uint32_t RecordOffset, const Hdr *H, - ArrayRef<uint8_t> Annotations) + explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + InlineSiteSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::InlineSiteSym), - RecordOffset(RecordOffset), Header(*H), Annotations(Annotations) {} - - static ErrorOr<InlineSiteSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - ArrayRef<uint8_t> Annotations; - CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Annotations)); - - return InlineSiteSym(RecordOffset, H, Annotations); - } + RecordOffset(RecordOffset) {} llvm::iterator_range<BinaryAnnotationIterator> annotations() const { - return llvm::make_range(BinaryAnnotationIterator(Annotations), + return llvm::make_range(BinaryAnnotationIterator(AnnotationData), BinaryAnnotationIterator()); } - uint32_t RecordOffset; - Hdr Header; + uint32_t Parent; + uint32_t End; + TypeIndex Inlinee; + std::vector<uint8_t> AnnotationData; -private: - ArrayRef<uint8_t> Annotations; + uint32_t RecordOffset; }; // S_PUB32 class PublicSym32 : public SymbolRecord { public: - struct Hdr { - ulittle32_t Index; // Type index, or Metadata token if a managed symbol - ulittle32_t Off; - ulittle16_t Seg; - // Name: The null-terminated name follows. - }; - - PublicSym32(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} - - static ErrorOr<PublicSym32> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); + explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit PublicSym32(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::PublicSym32), + RecordOffset(RecordOffset) {} - return PublicSym32(RecordOffset, H, Name); - } + uint32_t Index; + uint32_t Offset; + uint16_t Segment; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; // S_REGISTER class RegisterSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t Index; // Type index or Metadata token - ulittle16_t Register; // RegisterId enumeration - // Name: The null-terminated name follows. - }; - - RegisterSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} + explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + RegisterSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::RegisterSym), + RecordOffset(RecordOffset) {} - static ErrorOr<RegisterSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return RegisterSym(RecordOffset, H, Name); - } + uint32_t Index; + RegisterId Register; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; // S_PROCREF, S_LPROCREF class ProcRefSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t SumName; // SUC of the name (?) - ulittle32_t SymOffset; // Offset of actual symbol in $$Symbols - ulittle16_t Mod; // Module containing the actual symbol - // Name: The null-terminated name follows. - }; - - ProcRefSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} - - static ErrorOr<ProcRefSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return ProcRefSym(RecordOffset, H, Name); + explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit ProcRefSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) { } - uint32_t RecordOffset; - Hdr Header; + uint32_t SumName; + uint32_t SymOffset; + uint16_t Module; StringRef Name; + + uint32_t RecordOffset; }; // S_LOCAL class LocalSym : public SymbolRecord { public: - struct Hdr { - TypeIndex Type; - ulittle16_t Flags; // LocalSymFlags enum - // Name: The null-terminated name follows. - }; - - LocalSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} + explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit LocalSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {} - static ErrorOr<LocalSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return LocalSym(RecordOffset, H, Name); - } + TypeIndex Type; + LocalSymFlags Flags; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; struct LocalVariableAddrRange { - ulittle32_t OffsetStart; - ulittle16_t ISectStart; - ulittle16_t Range; + uint32_t OffsetStart; + uint16_t ISectStart; + uint16_t Range; }; struct LocalVariableAddrGap { - ulittle16_t GapStartOffset; - ulittle16_t Range; + uint16_t GapStartOffset; + uint16_t Range; }; enum : uint16_t { MaxDefRange = 0xf000 }; // S_DEFRANGE class DefRangeSym : public SymbolRecord { -public: - struct Hdr { - ulittle32_t Program; - LocalVariableAddrRange Range; - // LocalVariableAddrGap Gaps[]; - }; + static constexpr uint32_t RelocationOffset = 8; - DefRangeSym(uint32_t RecordOffset, const Hdr *H, - ArrayRef<LocalVariableAddrGap> Gaps) - : SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset), - Header(*H), Gaps(Gaps) {} - - static ErrorOr<DefRangeSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - ArrayRef<LocalVariableAddrGap> Gaps; - CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps)); - - return DefRangeSym(RecordOffset, H, Gaps); - } +public: + explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit DefRangeSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DefRangeSym), + RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, Range); + return RecordOffset + RelocationOffset; } + uint32_t Program; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; + uint32_t RecordOffset; - Hdr Header; - ArrayRef<LocalVariableAddrGap> Gaps; }; // S_DEFRANGE_SUBFIELD class DefRangeSubfieldSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 12; + public: - struct Hdr { - ulittle32_t Program; - ulittle16_t OffsetInParent; - LocalVariableAddrRange Range; - // LocalVariableAddrGap Gaps[]; - }; - DefRangeSubfieldSym(uint32_t RecordOffset, const Hdr *H, - ArrayRef<LocalVariableAddrGap> Gaps) + explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + DefRangeSubfieldSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym), - RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {} - - static ErrorOr<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - ArrayRef<LocalVariableAddrGap> Gaps; - CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps)); - - return DefRangeSubfieldSym(RecordOffset, H, Gaps); - } + RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, Range); + return RecordOffset + RelocationOffset; } + uint32_t Program; + uint16_t OffsetInParent; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; + uint32_t RecordOffset; - Hdr Header; - ArrayRef<LocalVariableAddrGap> Gaps; }; // S_DEFRANGE_REGISTER class DefRangeRegisterSym : public SymbolRecord { public: - struct Hdr { + struct Header { ulittle16_t Register; ulittle16_t MayHaveNoName; - LocalVariableAddrRange Range; - // LocalVariableAddrGap Gaps[]; }; - - DefRangeRegisterSym(uint32_t RecordOffset, const Hdr *H, - ArrayRef<LocalVariableAddrGap> Gaps) + explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + DefRangeRegisterSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), - RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {} - - DefRangeRegisterSym(uint16_t Register, uint16_t MayHaveNoName, - uint32_t OffsetStart, uint16_t ISectStart, uint16_t Range, - ArrayRef<LocalVariableAddrGap> Gaps) - : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), RecordOffset(0), - Gaps(Gaps) { - Header.Register = Register; - Header.MayHaveNoName = MayHaveNoName; - Header.Range.OffsetStart = OffsetStart; - Header.Range.ISectStart = ISectStart; - Header.Range.Range = Range; - } + RecordOffset(RecordOffset) {} - static ErrorOr<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - ArrayRef<LocalVariableAddrGap> Gaps; - CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps)); + uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } - return DefRangeRegisterSym(RecordOffset, H, Gaps); - } - - uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, Range); - } + Header Hdr; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; uint32_t RecordOffset; - Hdr Header; - ArrayRef<LocalVariableAddrGap> Gaps; }; // S_DEFRANGE_SUBFIELD_REGISTER class DefRangeSubfieldRegisterSym : public SymbolRecord { public: - struct Hdr { - ulittle16_t Register; // Register to which the variable is relative + struct Header { + ulittle16_t Register; ulittle16_t MayHaveNoName; ulittle32_t OffsetInParent; - LocalVariableAddrRange Range; - // LocalVariableAddrGap Gaps[]; }; - - DefRangeSubfieldRegisterSym(uint32_t RecordOffset, const Hdr *H, - ArrayRef<LocalVariableAddrGap> Gaps) + explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind) + : SymbolRecord(Kind) {} + DefRangeSubfieldRegisterSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym), - RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {} - - DefRangeSubfieldRegisterSym(uint16_t Register, uint16_t MayHaveNoName, - uint32_t OffsetInParent, - ArrayRef<LocalVariableAddrGap> Gaps) - : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym), - RecordOffset(0), Gaps(Gaps) { - Header.Register = Register; - Header.MayHaveNoName = MayHaveNoName; - Header.OffsetInParent = OffsetInParent; - } + RecordOffset(RecordOffset) {} - static ErrorOr<DefRangeSubfieldRegisterSym> - deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - ArrayRef<LocalVariableAddrGap> Gaps; - CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps)); + uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } - return DefRangeSubfieldRegisterSym(RecordOffset, H, Gaps); - } - - uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, Range); - } + Header Hdr; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; uint32_t RecordOffset; - Hdr Header; - ArrayRef<LocalVariableAddrGap> Gaps; }; // S_DEFRANGE_FRAMEPOINTER_REL class DefRangeFramePointerRelSym : public SymbolRecord { -public: - struct Hdr { - little32_t Offset; // Offset from the frame pointer register - LocalVariableAddrRange Range; - // LocalVariableAddrGap Gaps[]; - }; + static constexpr uint32_t RelocationOffset = 8; - DefRangeFramePointerRelSym(uint32_t RecordOffset, const Hdr *H, - ArrayRef<LocalVariableAddrGap> Gaps) +public: + explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind) + : SymbolRecord(Kind) {} + DefRangeFramePointerRelSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym), - RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {} - - static ErrorOr<DefRangeFramePointerRelSym> - deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - ArrayRef<LocalVariableAddrGap> Gaps; - CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps)); - - return DefRangeFramePointerRelSym(RecordOffset, H, Gaps); - } + RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, Range); + return RecordOffset + RelocationOffset; } + int32_t Offset; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; + uint32_t RecordOffset; - Hdr Header; - ArrayRef<LocalVariableAddrGap> Gaps; }; // S_DEFRANGE_REGISTER_REL class DefRangeRegisterRelSym : public SymbolRecord { public: - struct Hdr { - ulittle16_t BaseRegister; + struct Header { + ulittle16_t Register; ulittle16_t Flags; little32_t BasePointerOffset; - LocalVariableAddrRange Range; - // LocalVariableAddrGap Gaps[]; }; - - DefRangeRegisterRelSym(uint32_t RecordOffset, const Hdr *H, - ArrayRef<LocalVariableAddrGap> Gaps) + explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit DefRangeRegisterRelSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), - RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {} - - DefRangeRegisterRelSym(uint16_t BaseRegister, uint16_t Flags, - int32_t BasePointerOffset, uint32_t OffsetStart, - uint16_t ISectStart, uint16_t Range, - ArrayRef<LocalVariableAddrGap> Gaps) - : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), RecordOffset(0), - Gaps(Gaps) { - Header.BaseRegister = BaseRegister; - Header.Flags = Flags; - Header.BasePointerOffset = BasePointerOffset; - Header.Range.OffsetStart = OffsetStart; - Header.Range.ISectStart = ISectStart; - Header.Range.Range = Range; - } + RecordOffset(RecordOffset) {} - static ErrorOr<DefRangeRegisterRelSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - ArrayRef<LocalVariableAddrGap> Gaps; - CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps)); + // The flags implement this notional bitfield: + // uint16_t IsSubfield : 1; + // uint16_t Padding : 3; + // uint16_t OffsetInParent : 12; + enum : uint16_t { + IsSubfieldFlag = 1, + OffsetInParentShift = 4, + }; - return DefRangeRegisterRelSym(RecordOffset, H, Gaps); - } + bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; } + uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; } - bool hasSpilledUDTMember() const { return Header.Flags & 1; } - uint16_t offsetInParent() const { return Header.Flags >> 4; } + uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } - uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, Range); - } + Header Hdr; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; uint32_t RecordOffset; - Hdr Header; - ArrayRef<LocalVariableAddrGap> Gaps; }; // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE class DefRangeFramePointerRelFullScopeSym : public SymbolRecord { public: - struct Hdr { - little32_t Offset; // Offset from the frame pointer register - }; - - DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset, const Hdr *H) + explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind) + : SymbolRecord(Kind) {} + explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym), - RecordOffset(RecordOffset), Header(*H) {} - - static ErrorOr<DefRangeFramePointerRelFullScopeSym> - deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); + RecordOffset(RecordOffset) {} - return DefRangeFramePointerRelFullScopeSym(RecordOffset, H); - } + int32_t Offset; uint32_t RecordOffset; - Hdr Header; }; // S_BLOCK32 class BlockSym : public SymbolRecord { -public: - struct Hdr { - ulittle32_t PtrParent; - ulittle32_t PtrEnd; - ulittle32_t CodeSize; - ulittle32_t CodeOffset; - ulittle16_t Segment; - // Name: The null-terminated name follows. - }; + static constexpr uint32_t RelocationOffset = 16; - BlockSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} - - static ErrorOr<BlockSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return BlockSym(RecordOffset, H, Name); - } +public: + explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit BlockSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, CodeOffset); + return RecordOffset + RelocationOffset; } - uint32_t RecordOffset; - Hdr Header; + uint32_t Parent; + uint32_t End; + uint32_t CodeSize; + uint32_t CodeOffset; + uint16_t Segment; StringRef Name; + + uint32_t RecordOffset; }; // S_LABEL32 class LabelSym : public SymbolRecord { -public: - struct Hdr { - ulittle32_t CodeOffset; - ulittle16_t Segment; - uint8_t Flags; // CV_PROCFLAGS - // Name: The null-terminated name follows. - }; - - LabelSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} + static constexpr uint32_t RelocationOffset = 4; - static ErrorOr<LabelSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return LabelSym(RecordOffset, H, Name); - } +public: + explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit LabelSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, CodeOffset); + return RecordOffset + RelocationOffset; } - uint32_t RecordOffset; - Hdr Header; + uint32_t CodeOffset; + uint16_t Segment; + ProcSymFlags Flags; StringRef Name; + + uint32_t RecordOffset; }; // S_OBJNAME class ObjNameSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t Signature; - // Name: The null-terminated name follows. - }; - - ObjNameSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} - - static ErrorOr<ObjNameSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return ObjNameSym(RecordOffset, H, Name); + explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + ObjNameSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) { } - uint32_t RecordOffset; - Hdr Header; + uint32_t Signature; StringRef Name; + + uint32_t RecordOffset; }; // S_ENVBLOCK class EnvBlockSym : public SymbolRecord { public: - struct Hdr { - uint8_t Reserved; - // Sequence of zero terminated strings. - }; - - EnvBlockSym(uint32_t RecordOffset, const Hdr *H, - const std::vector<StringRef> &Fields) - : SymbolRecord(SymbolRecordKind::EnvBlockSym), RecordOffset(RecordOffset), - Header(*H), Fields(Fields) {} - - static ErrorOr<EnvBlockSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - std::vector<StringRef> Fields; - CV_DESERIALIZE(Data, H, CV_STRING_ARRAY_NULL_TERM(Fields)); + explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + EnvBlockSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::EnvBlockSym), + RecordOffset(RecordOffset) {} - return EnvBlockSym(RecordOffset, H, Fields); - } + std::vector<StringRef> Fields; uint32_t RecordOffset; - Hdr Header; - std::vector<StringRef> Fields; }; // S_EXPORT class ExportSym : public SymbolRecord { public: - struct Hdr { - ulittle16_t Ordinal; - ulittle16_t Flags; // ExportFlags - // Name: The null-terminated name follows. - }; + explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + ExportSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {} - ExportSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} - - static ErrorOr<ExportSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return ExportSym(RecordOffset, H, Name); - } + uint16_t Ordinal; + ExportFlags Flags; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; // S_FILESTATIC class FileStaticSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t Index; // Type Index - ulittle32_t ModFilenameOffset; // Index of mod filename in string table - ulittle16_t Flags; // LocalSymFlags enum - // Name: The null-terminated name follows. - }; - - FileStaticSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) + explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + FileStaticSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::FileStaticSym), - RecordOffset(RecordOffset), Header(*H), Name(Name) {} - - static ErrorOr<FileStaticSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); + RecordOffset(RecordOffset) {} - return FileStaticSym(RecordOffset, H, Name); - } + uint32_t Index; + uint32_t ModFilenameOffset; + LocalSymFlags Flags; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; // S_COMPILE2 class Compile2Sym : public SymbolRecord { public: - struct Hdr { - ulittle32_t flags; // CompileSym2Flags enum - uint8_t getLanguage() const { return flags & 0xFF; } - unsigned short Machine; // CPUType enum - unsigned short VersionFrontendMajor; - unsigned short VersionFrontendMinor; - unsigned short VersionFrontendBuild; - unsigned short VersionBackendMajor; - unsigned short VersionBackendMinor; - unsigned short VersionBackendBuild; - // Version: The null-terminated version string follows. - // Optional block of zero terminated strings terminated with a double zero. - }; - - Compile2Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version) - : SymbolRecord(SymbolRecordKind::Compile2Sym), RecordOffset(RecordOffset), - Header(*H), Version(Version) {} - - static ErrorOr<Compile2Sym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Version; - CV_DESERIALIZE(Data, H, Version); + explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + Compile2Sym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::Compile2Sym), + RecordOffset(RecordOffset) {} + + CompileSym2Flags Flags; + CPUType Machine; + uint16_t VersionFrontendMajor; + uint16_t VersionFrontendMinor; + uint16_t VersionFrontendBuild; + uint16_t VersionBackendMajor; + uint16_t VersionBackendMinor; + uint16_t VersionBackendBuild; + StringRef Version; + std::vector<StringRef> ExtraStrings; - return Compile2Sym(RecordOffset, H, Version); - } + uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; } + uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; } uint32_t RecordOffset; - Hdr Header; - StringRef Version; }; // S_COMPILE3 class Compile3Sym : public SymbolRecord { public: - struct Hdr { - ulittle32_t flags; // CompileSym3Flags enum - uint8_t getLanguage() const { return flags & 0xff; } - ulittle16_t Machine; // CPUType enum - ulittle16_t VersionFrontendMajor; - ulittle16_t VersionFrontendMinor; - ulittle16_t VersionFrontendBuild; - ulittle16_t VersionFrontendQFE; - ulittle16_t VersionBackendMajor; - ulittle16_t VersionBackendMinor; - ulittle16_t VersionBackendBuild; - ulittle16_t VersionBackendQFE; - // VersionString: The null-terminated version string follows. - }; - - Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version) - : SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset), - Header(*H), Version(Version) {} + explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + Compile3Sym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::Compile3Sym), + RecordOffset(RecordOffset) {} + + CompileSym3Flags Flags; + CPUType Machine; + uint16_t VersionFrontendMajor; + uint16_t VersionFrontendMinor; + uint16_t VersionFrontendBuild; + uint16_t VersionFrontendQFE; + uint16_t VersionBackendMajor; + uint16_t VersionBackendMinor; + uint16_t VersionBackendBuild; + uint16_t VersionBackendQFE; + StringRef Version; - static ErrorOr<Compile3Sym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Version; - CV_DESERIALIZE(Data, H, Version); - - return Compile3Sym(RecordOffset, H, Version); - } + uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; } + uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; } uint32_t RecordOffset; - Hdr Header; - StringRef Version; }; // S_FRAMEPROC class FrameProcSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t TotalFrameBytes; - ulittle32_t PaddingFrameBytes; - ulittle32_t OffsetToPadding; - ulittle32_t BytesOfCalleeSavedRegisters; - ulittle32_t OffsetOfExceptionHandler; - ulittle16_t SectionIdOfExceptionHandler; - ulittle32_t Flags; - }; - - FrameProcSym(uint32_t RecordOffset, const Hdr *H) + explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit FrameProcSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::FrameProcSym), - RecordOffset(RecordOffset), Header(*H) {} + RecordOffset(RecordOffset) {} - static ErrorOr<FrameProcSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); - - return FrameProcSym(RecordOffset, H); - } + uint32_t TotalFrameBytes; + uint32_t PaddingFrameBytes; + uint32_t OffsetToPadding; + uint32_t BytesOfCalleeSavedRegisters; + uint32_t OffsetOfExceptionHandler; + uint16_t SectionIdOfExceptionHandler; + FrameProcedureOptions Flags; uint32_t RecordOffset; - Hdr Header; }; // S_CALLSITEINFO class CallSiteInfoSym : public SymbolRecord { -public: - struct Hdr { - ulittle32_t CodeOffset; - ulittle16_t Segment; - ulittle16_t Reserved; - TypeIndex Type; - }; + static constexpr uint32_t RelocationOffset = 4; - CallSiteInfoSym(uint32_t RecordOffset, const Hdr *H) - : SymbolRecord(SymbolRecordKind::CallSiteInfoSym), - RecordOffset(RecordOffset), Header(*H) {} - - static ErrorOr<CallSiteInfoSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); - - return CallSiteInfoSym(RecordOffset, H); - } +public: + explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit CallSiteInfoSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, CodeOffset); + return RecordOffset + RelocationOffset; } + uint32_t CodeOffset; + uint16_t Segment; + TypeIndex Type; + uint32_t RecordOffset; - Hdr Header; }; // S_HEAPALLOCSITE class HeapAllocationSiteSym : public SymbolRecord { -public: - struct Hdr { - ulittle32_t CodeOffset; - ulittle16_t Segment; - ulittle16_t CallInstructionSize; - TypeIndex Type; - }; + static constexpr uint32_t RelocationOffset = 4; - HeapAllocationSiteSym(uint32_t RecordOffset, const Hdr *H) +public: + explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit HeapAllocationSiteSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym), - RecordOffset(RecordOffset), Header(*H) {} - - static ErrorOr<HeapAllocationSiteSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); - - return HeapAllocationSiteSym(RecordOffset, H); - } + RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, CodeOffset); + return RecordOffset + RelocationOffset; } + uint32_t CodeOffset; + uint16_t Segment; + uint16_t CallInstructionSize; + TypeIndex Type; + uint32_t RecordOffset; - Hdr Header; }; // S_FRAMECOOKIE class FrameCookieSym : public SymbolRecord { -public: - struct Hdr { - ulittle32_t CodeOffset; - ulittle16_t Register; - uint8_t CookieKind; - uint8_t Flags; - }; - - FrameCookieSym(uint32_t RecordOffset, const Hdr *H) - : SymbolRecord(SymbolRecordKind::FrameCookieSym), - RecordOffset(RecordOffset), Header(*H) {} + static constexpr uint32_t RelocationOffset = 4; - static ErrorOr<FrameCookieSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); - - return FrameCookieSym(RecordOffset, H); - } +public: + explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit FrameCookieSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::FrameCookieSym) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, CodeOffset); + return RecordOffset + RelocationOffset; } + uint32_t CodeOffset; + uint16_t Register; + uint8_t CookieKind; + uint8_t Flags; + uint32_t RecordOffset; - Hdr Header; }; // S_UDT, S_COBOLUDT class UDTSym : public SymbolRecord { public: - struct Hdr { - TypeIndex Type; // Type of the UDT - // Name: The null-terminated name follows. - }; - - UDTSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::UDTSym), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} + explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit UDTSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::UDTSym) {} - static ErrorOr<UDTSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return UDTSym(RecordOffset, H, Name); - } + TypeIndex Type; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; // S_BUILDINFO class BuildInfoSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t BuildId; - }; - - BuildInfoSym(uint32_t RecordOffset, const Hdr *H) + explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + BuildInfoSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::BuildInfoSym), - RecordOffset(RecordOffset), Header(*H) {} + RecordOffset(RecordOffset) {} - static ErrorOr<BuildInfoSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - CV_DESERIALIZE(Data, H); - - return BuildInfoSym(RecordOffset, H); - } + uint32_t BuildId; uint32_t RecordOffset; - Hdr Header; }; // S_BPREL32 class BPRelativeSym : public SymbolRecord { public: - struct Hdr { - little32_t Offset; // Offset from the base pointer register - TypeIndex Type; // Type of the variable - // Name: The null-terminated name follows. - }; - - BPRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) + explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit BPRelativeSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::BPRelativeSym), - RecordOffset(RecordOffset), Header(*H), Name(Name) {} - - static ErrorOr<BPRelativeSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); + RecordOffset(RecordOffset) {} - return BPRelativeSym(RecordOffset, H, Name); - } + int32_t Offset; + TypeIndex Type; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; // S_REGREL32 class RegRelativeSym : public SymbolRecord { public: - struct Hdr { - ulittle32_t Offset; // Offset from the register - TypeIndex Type; // Type of the variable - ulittle16_t Register; // Register to which the variable is relative - // Name: The null-terminated name follows. - }; - - RegRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) + explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit RegRelativeSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::RegRelativeSym), - RecordOffset(RecordOffset), Header(*H), Name(Name) {} - - static ErrorOr<RegRelativeSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); + RecordOffset(RecordOffset) {} - return RegRelativeSym(RecordOffset, H, Name); - } + uint32_t Offset; + TypeIndex Type; + uint16_t Register; + StringRef Name; uint32_t RecordOffset; - Hdr Header; - StringRef Name; }; // S_CONSTANT, S_MANCONSTANT class ConstantSym : public SymbolRecord { public: - struct Hdr { - TypeIndex Type; - // Value: The value of the constant. - // Name: The null-terminated name follows. - }; - - ConstantSym(uint32_t RecordOffset, const Hdr *H, const APSInt &Value, - StringRef Name) - : SymbolRecord(SymbolRecordKind::ConstantSym), RecordOffset(RecordOffset), - Header(*H), Value(Value), Name(Name) {} - - static ErrorOr<ConstantSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - APSInt Value; - StringRef Name; - CV_DESERIALIZE(Data, H, Value, Name); - - return ConstantSym(RecordOffset, H, Value, Name); - } + explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + ConstantSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::ConstantSym), + RecordOffset(RecordOffset) {} - uint32_t RecordOffset; - Hdr Header; + TypeIndex Type; APSInt Value; StringRef Name; + + uint32_t RecordOffset; }; // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA class DataSym : public SymbolRecord { -public: - struct Hdr { - TypeIndex Type; - ulittle32_t DataOffset; - ulittle16_t Segment; - // Name: The null-terminated name follows. - }; - - DataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) - : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset), - Header(*H), Name(Name) {} + static constexpr uint32_t RelocationOffset = 8; - static ErrorOr<DataSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return DataSym(RecordOffset, H, Name); - } +public: + explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + DataSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, DataOffset); + return RecordOffset + RelocationOffset; } - uint32_t RecordOffset; - Hdr Header; + TypeIndex Type; + uint32_t DataOffset; + uint16_t Segment; StringRef Name; + + uint32_t RecordOffset; }; // S_LTHREAD32, S_GTHREAD32 class ThreadLocalDataSym : public SymbolRecord { -public: - struct Hdr { - TypeIndex Type; - ulittle32_t DataOffset; - ulittle16_t Segment; - // Name: The null-terminated name follows. - }; + static constexpr uint32_t RelocationOffset = 8; - ThreadLocalDataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name) +public: + explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit ThreadLocalDataSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym), - RecordOffset(RecordOffset), Header(*H), Name(Name) {} - - static ErrorOr<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind, - uint32_t RecordOffset, - ArrayRef<uint8_t> &Data) { - const Hdr *H = nullptr; - StringRef Name; - CV_DESERIALIZE(Data, H, Name); - - return ThreadLocalDataSym(RecordOffset, H, Name); - } + RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { - return RecordOffset + offsetof(Hdr, DataOffset); + return RecordOffset + RelocationOffset; } - uint32_t RecordOffset; - Hdr Header; + TypeIndex Type; + uint32_t DataOffset; + uint16_t Segment; StringRef Name; + + uint32_t RecordOffset; }; typedef CVRecord<SymbolKind> CVSymbol; -typedef VarStreamArray<CVSymbol> CVSymbolArray; +typedef msf::VarStreamArray<CVSymbol> CVSymbolArray; -} // namespace codeview -} // namespace llvm +} // end namespace codeview +} // end namespace llvm -#endif +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h new file mode 100644 index 0000000..1bd14ed --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h @@ -0,0 +1,44 @@ +//===- SymbolRecordMapping.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_SYMBOLRECORDMAPPING_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORDMAPPING_H + +#include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" +#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" + +namespace llvm { +namespace msf { +class StreamReader; +class StreamWriter; +} + +namespace codeview { +class SymbolRecordMapping : public SymbolVisitorCallbacks { +public: + explicit SymbolRecordMapping(msf::StreamReader &Reader) : IO(Reader) {} + explicit SymbolRecordMapping(msf::StreamWriter &Writer) : IO(Writer) {} + + Error visitSymbolBegin(CVSymbol &Record) override; + Error visitSymbolEnd(CVSymbol &Record) override; + +#define SYMBOL_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVSymbol &CVR, Name &Record) override; +#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "CVSymbolTypes.def" + +private: + Optional<SymbolKind> Kind; + + CodeViewRecordIO IO; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h new file mode 100644 index 0000000..4eb914e --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h @@ -0,0 +1,96 @@ +//===- symbolSerializer.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_SYMBOLSERIALIZER_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H + +#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" +#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" +#include "llvm/DebugInfo/MSF/ByteStream.h" +#include "llvm/DebugInfo/MSF/StreamWriter.h" + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { + +class SymbolSerializer : public SymbolVisitorCallbacks { + uint32_t RecordStart = 0; + msf::StreamWriter &Writer; + SymbolRecordMapping Mapping; + Optional<SymbolKind> CurrentSymbol; + + Error writeRecordPrefix(SymbolKind Kind) { + RecordPrefix Prefix; + Prefix.RecordKind = Kind; + Prefix.RecordLen = 0; + if (auto EC = Writer.writeObject(Prefix)) + return EC; + return Error::success(); + } + +public: + explicit SymbolSerializer(msf::StreamWriter &Writer) + : Writer(Writer), Mapping(Writer) {} + + virtual Error visitSymbolBegin(CVSymbol &Record) override { + assert(!CurrentSymbol.hasValue() && "Already in a symbol mapping!"); + + RecordStart = Writer.getOffset(); + if (auto EC = writeRecordPrefix(Record.kind())) + return EC; + + CurrentSymbol = Record.kind(); + if (auto EC = Mapping.visitSymbolBegin(Record)) + return EC; + + return Error::success(); + } + + virtual Error visitSymbolEnd(CVSymbol &Record) override { + assert(CurrentSymbol.hasValue() && "Not in a symbol mapping!"); + + if (auto EC = Mapping.visitSymbolEnd(Record)) + return EC; + + uint32_t RecordEnd = Writer.getOffset(); + Writer.setOffset(RecordStart); + uint16_t Length = RecordEnd - Writer.getOffset() - 2; + if (auto EC = Writer.writeInteger(Length)) + return EC; + + Writer.setOffset(RecordEnd); + CurrentSymbol.reset(); + + return Error::success(); + } + +#define SYMBOL_RECORD(EnumName, EnumVal, Name) \ + virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \ + return visitKnownRecordImpl(CVR, Record); \ + } +#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "CVSymbolTypes.def" + +private: + template <typename RecordKind> + Error visitKnownRecordImpl(CVSymbol &CVR, RecordKind &Record) { + return Mapping.visitKnownRecord(CVR, Record); + } +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h new file mode 100644 index 0000000..96a93bf --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h @@ -0,0 +1,71 @@ +//===- SymbolVisitorCallbackPipeline.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_SYMBOLVISITORCALLBACKPIPELINE_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKPIPELINE_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" +#include "llvm/Support/Error.h" +#include <vector> + +namespace llvm { +namespace codeview { + +class SymbolVisitorCallbackPipeline : public SymbolVisitorCallbacks { +public: + SymbolVisitorCallbackPipeline() = default; + + Error visitUnknownSymbol(CVSymbol &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitUnknownSymbol(Record)) + return EC; + } + return Error::success(); + } + + Error visitSymbolBegin(CVSymbol &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitSymbolBegin(Record)) + return EC; + } + return Error::success(); + } + + Error visitSymbolEnd(CVSymbol &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitSymbolEnd(Record)) + return EC; + } + return Error::success(); + } + + void addCallbackToPipeline(SymbolVisitorCallbacks &Callbacks) { + Pipeline.push_back(&Callbacks); + } + +#define SYMBOL_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \ + for (auto Visitor : Pipeline) { \ + if (auto EC = Visitor->visitKnownRecord(CVR, Record)) \ + return EC; \ + } \ + return Error::success(); \ + } +#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def" + +private: + std::vector<SymbolVisitorCallbacks *> Pipeline; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKPIPELINE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h new file mode 100644 index 0000000..aaa9d2e --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h @@ -0,0 +1,48 @@ +//===- SymbolVisitorCallbacks.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_SYMBOLVISITORCALLBACKS_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKS_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { + +class SymbolVisitorCallbacks { + friend class CVSymbolVisitor; + +public: + virtual ~SymbolVisitorCallbacks() = default; + + /// Action to take on unknown symbols. By default, they are ignored. + virtual Error visitUnknownSymbol(CVSymbol &Record) { + return Error::success(); + } + + /// Paired begin/end actions for all symbols. Receives all record data, + /// including the fixed-length record prefix. visitSymbolBegin() should + /// return + /// the type of the Symbol, or an error if it cannot be determined. + virtual Error visitSymbolBegin(CVSymbol &Record) { return Error::success(); } + virtual Error visitSymbolEnd(CVSymbol &Record) { return Error::success(); } + +#define SYMBOL_RECORD(EnumName, EnumVal, Name) \ + virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) { \ + return Error::success(); \ + } +#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "CVSymbolTypes.def" +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKS_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h index a496516..2b468a2 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h @@ -10,24 +10,28 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" - -#include <stdint.h> +#include <cstdint> namespace llvm { +namespace msf { +class StreamReader; +} // end namespace msf + namespace codeview { class SymbolVisitorDelegate { public: - virtual ~SymbolVisitorDelegate() {} + virtual ~SymbolVisitorDelegate() = default; - virtual uint32_t getRecordOffset(ArrayRef<uint8_t> Record) = 0; + virtual uint32_t getRecordOffset(msf::StreamReader Reader) = 0; virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0; virtual StringRef getStringTable() = 0; }; + } // end namespace codeview + } // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h new file mode 100644 index 0000000..cccc286 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h @@ -0,0 +1,55 @@ +//===- TypeDatabase.h - A collection of CodeView type records ---*- 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_TYPEDATABASE_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASE_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/StringSaver.h" + +namespace llvm { +namespace codeview { +class TypeDatabase { +public: + TypeDatabase() : TypeNameStorage(Allocator) {} + + /// Gets the type index for the next type record. + TypeIndex getNextTypeIndex() const; + + /// Records the name of a type, and reserves its type index. + void recordType(StringRef Name, CVType Data); + + /// Saves the name in a StringSet and creates a stable StringRef. + StringRef saveTypeName(StringRef TypeName); + + StringRef getTypeName(TypeIndex Index) const; + + bool containsTypeIndex(TypeIndex Index) const; + + uint32_t size() const; + +private: + BumpPtrAllocator Allocator; + + /// 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. + SmallVector<StringRef, 10> CVUDTNames; + SmallVector<CVType, 10> TypeRecords; + + StringSaver TypeNameStorage; +}; +} +} + +#endif
\ No newline at end of file diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h new file mode 100644 index 0000000..39d234c --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h @@ -0,0 +1,53 @@ +//===-- TypeDatabaseVisitor.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_TYPEDATABASEVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASEVISITOR_H + +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" + +namespace llvm { +namespace codeview { + +/// Dumper for CodeView type streams found in COFF object files and PDB files. +class TypeDatabaseVisitor : public TypeVisitorCallbacks { +public: + explicit TypeDatabaseVisitor(TypeDatabase &TypeDB) : TypeDB(TypeDB) {} + + /// Paired begin/end actions for all types. Receives all record data, + /// including the fixed-length record prefix. + Error visitTypeBegin(CVType &Record) override; + Error visitTypeEnd(CVType &Record) override; + Error visitMemberBegin(CVMemberRecord &Record) override; + Error visitMemberEnd(CVMemberRecord &Record) override; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override; +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "TypeRecords.def" + +private: + bool IsInFieldList = false; + + /// Name of the current type. Only valid before visitTypeEnd. + StringRef Name; + + TypeDatabase &TypeDB; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h new file mode 100644 index 0000000..dc5eaf8 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h @@ -0,0 +1,136 @@ +//===- TypeDeserializer.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/DebugInfo/MSF/ByteStream.h" +#include "llvm/DebugInfo/MSF/StreamReader.h" +#include "llvm/Support/Error.h" +#include <cassert> +#include <cstdint> +#include <memory> + +namespace llvm { +namespace codeview { + +class TypeDeserializer : public TypeVisitorCallbacks { + struct MappingInfo { + explicit MappingInfo(ArrayRef<uint8_t> RecordData) + : Stream(RecordData), Reader(Stream), Mapping(Reader) {} + + msf::ByteStream Stream; + msf::StreamReader Reader; + TypeRecordMapping Mapping; + }; + +public: + TypeDeserializer() = default; + + Error visitTypeBegin(CVType &Record) override { + assert(!Mapping && "Already in a type mapping!"); + Mapping = llvm::make_unique<MappingInfo>(Record.content()); + return Mapping->Mapping.visitTypeBegin(Record); + } + + Error visitTypeEnd(CVType &Record) override { + assert(Mapping && "Not in a type mapping!"); + auto EC = Mapping->Mapping.visitTypeEnd(Record); + Mapping.reset(); + return EC; + } + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \ + return visitKnownRecordImpl<Name##Record>(CVR, Record); \ + } +#define MEMBER_RECORD(EnumName, EnumVal, Name) +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "TypeRecords.def" + +private: + template <typename RecordType> + Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) { + return Mapping->Mapping.visitKnownRecord(CVR, Record); + } + + std::unique_ptr<MappingInfo> Mapping; +}; + +class FieldListDeserializer : public TypeVisitorCallbacks { + struct MappingInfo { + explicit MappingInfo(msf::StreamReader &R) + : Reader(R), Mapping(Reader), StartOffset(0) {} + + msf::StreamReader &Reader; + TypeRecordMapping Mapping; + uint32_t StartOffset; + }; + +public: + explicit FieldListDeserializer(msf::StreamReader &Reader) : Mapping(Reader) { + CVType FieldList; + FieldList.Type = TypeLeafKind::LF_FIELDLIST; + consumeError(Mapping.Mapping.visitTypeBegin(FieldList)); + } + + ~FieldListDeserializer() override { + CVType FieldList; + FieldList.Type = TypeLeafKind::LF_FIELDLIST; + consumeError(Mapping.Mapping.visitTypeEnd(FieldList)); + } + + Error visitMemberBegin(CVMemberRecord &Record) override { + Mapping.StartOffset = Mapping.Reader.getOffset(); + return Mapping.Mapping.visitMemberBegin(Record); + } + + Error visitMemberEnd(CVMemberRecord &Record) override { + if (auto EC = Mapping.Mapping.visitMemberEnd(Record)) + return EC; + return Error::success(); + } + +#define TYPE_RECORD(EnumName, EnumVal, Name) +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \ + return visitKnownMemberImpl<Name##Record>(CVR, Record); \ + } +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "TypeRecords.def" + +private: + template <typename RecordType> + Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) { + if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record)) + return EC; + + uint32_t EndOffset = Mapping.Reader.getOffset(); + uint32_t RecordLength = EndOffset - Mapping.StartOffset; + Mapping.Reader.setOffset(Mapping.StartOffset); + if (auto EC = Mapping.Reader.readBytes(CVR.Data, RecordLength)) + return EC; + assert(Mapping.Reader.getOffset() == EndOffset); + return Error::success(); + } + MappingInfo Mapping; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h new file mode 100644 index 0000000..a466e42 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h @@ -0,0 +1,67 @@ +//===-- TypeDumpVisitor.h - CodeView type info dumper -----------*- 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_TYPEDUMPVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPVISITOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" + +namespace llvm { +class ScopedPrinter; + +namespace codeview { + +/// Dumper for CodeView type streams found in COFF object files and PDB files. +class TypeDumpVisitor : public TypeVisitorCallbacks { +public: + TypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W, bool PrintRecordBytes) + : W(W), PrintRecordBytes(PrintRecordBytes), TypeDB(TypeDB) {} + + void printTypeIndex(StringRef FieldName, TypeIndex TI) const; + + /// Action to take on unknown types. By default, they are ignored. + Error visitUnknownType(CVType &Record) override; + Error visitUnknownMember(CVMemberRecord &Record) override; + + /// Paired begin/end actions for all types. Receives all record data, + /// including the fixed-length record prefix. + Error visitTypeBegin(CVType &Record) override; + Error visitTypeEnd(CVType &Record) override; + Error visitMemberBegin(CVMemberRecord &Record) override; + Error visitMemberEnd(CVMemberRecord &Record) override; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override; +#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; + + TypeDatabase &TypeDB; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumper.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumper.h deleted file mode 100644 index ca79ab0..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumper.h +++ /dev/null @@ -1,105 +0,0 @@ -//===-- TypeDumper.h - CodeView type info dumper ----------------*- 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_TYPEDUMPER_H -#define LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H - -#include "llvm/ADT/ArrayRef.h" -#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; - -namespace codeview { - -/// Dumper for CodeView type streams found in COFF object files and PDB files. -class CVTypeDumper : public TypeVisitorCallbacks { -public: - CVTypeDumper(ScopedPrinter *W, bool PrintRecordBytes) - : W(W), PrintRecordBytes(PrintRecordBytes) {} - - StringRef getTypeName(TypeIndex TI); - void printTypeIndex(StringRef FieldName, TypeIndex TI); - - /// Dumps one type record. Returns false if there was a type parsing error, - /// and true otherwise. This should be called in order, since the dumper - /// maintains state about previous records which are necessary for cross - /// type references. - 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. - 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. - Error dump(ArrayRef<uint8_t> Data); - - /// Gets the type index for the next type record. - unsigned getNextTypeIndex() const { - return 0x1000 + CVUDTNames.size(); - } - - /// Records the name of a type, and reserves its type index. - void recordType(StringRef Name) { CVUDTNames.push_back(Name); } - - /// Saves the name in a StringSet and creates a stable StringRef. - StringRef saveName(StringRef TypeName) { - return TypeNames.insert(TypeName).first->getKey(); - } - - 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. - SmallVector<StringRef, 10> CVUDTNames; - - StringSet<> TypeNames; -}; - -} // end namespace codeview -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumperBase.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumperBase.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumperBase.h diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h index c2ebf38..3c11d24 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -93,7 +93,7 @@ public: static const uint32_t SimpleModeMask = 0x00000700; public: - TypeIndex() : Index(0) {} + TypeIndex() : Index(static_cast<uint32_t>(SimpleTypeKind::None)) {} explicit TypeIndex(uint32_t Index) : Index(Index) {} explicit TypeIndex(SimpleTypeKind Kind) : Index(static_cast<uint32_t>(Kind)) {} @@ -101,6 +101,7 @@ public: : Index(static_cast<uint32_t>(Kind) | static_cast<uint32_t>(Mode)) {} uint32_t getIndex() const { return Index; } + void setIndex(uint32_t I) { Index = I; } bool isSimple() const { return Index < FirstNonSimpleIndex; } bool isNoneType() const { return *this == None(); } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h index 42751fb..4f1c047 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -12,27 +12,54 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/Support/ErrorOr.h" -#include <cinttypes> -#include <utility> +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/Support/Endian.h" +#include <algorithm> +#include <cstdint> +#include <vector> namespace llvm { + +namespace msf { +class StreamReader; +} // end namespace msf + namespace codeview { -using llvm::support::little32_t; -using llvm::support::ulittle16_t; -using llvm::support::ulittle32_t; +using support::little32_t; +using support::ulittle16_t; +using support::ulittle32_t; + +typedef CVRecord<TypeLeafKind> CVType; + +struct CVMemberRecord { + TypeLeafKind Kind; + ArrayRef<uint8_t> Data; +}; +typedef msf::VarStreamArray<CVType> CVTypeArray; /// Equvalent to CV_fldattr_t in cvinfo.h. struct MemberAttributes { - ulittle16_t Attrs; + uint16_t Attrs = 0; enum { MethodKindShift = 2, }; + MemberAttributes() = default; + + explicit MemberAttributes(MemberAccess Access) + : Attrs(static_cast<uint16_t>(Access)) {} + + MemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Flags) { + Attrs = static_cast<uint16_t>(Access); + Attrs |= (static_cast<uint16_t>(Kind) << MethodKindShift); + Attrs |= static_cast<uint16_t>(Flags); + } /// Get the access specifier. Valid for any kind of member. MemberAccess getAccess() const { @@ -73,7 +100,7 @@ struct MemberAttributes { // if it represents a member pointer. class MemberPointerInfo { public: - MemberPointerInfo() {} + MemberPointerInfo() = default; MemberPointerInfo(TypeIndex ContainingType, PointerToMemberRepresentation Representation) @@ -83,25 +110,18 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<MemberPointerInfo> deserialize(ArrayRef<uint8_t> &Data); - TypeIndex getContainingType() const { return ContainingType; } PointerToMemberRepresentation getRepresentation() const { return Representation; } -private: - struct Layout { - TypeIndex ClassType; - ulittle16_t Representation; // PointerToMemberRepresentation - }; - TypeIndex ContainingType; PointerToMemberRepresentation Representation; }; class TypeRecord { protected: + TypeRecord() = default; explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {} public: @@ -114,6 +134,7 @@ private: // LF_MODIFIER class ModifierRecord : public TypeRecord { public: + explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers) : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType), Modifiers(Modifiers) {} @@ -122,18 +143,9 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<ModifierRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getModifiedType() const { return ModifiedType; } ModifierOptions getModifiers() const { return Modifiers; } -private: - struct Layout { - TypeIndex ModifiedType; - ulittle16_t Modifiers; // ModifierOptions - }; - TypeIndex ModifiedType; ModifierOptions Modifiers; }; @@ -141,6 +153,7 @@ private: // LF_PROCEDURE class ProcedureRecord : public TypeRecord { public: + explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv, FunctionOptions Options, uint16_t ParameterCount, TypeIndex ArgumentList) @@ -152,26 +165,12 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<ProcedureRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - - static uint32_t getLayoutSize() { return 2 + sizeof(Layout); } - TypeIndex getReturnType() const { return ReturnType; } CallingConvention getCallConv() const { return CallConv; } FunctionOptions getOptions() const { return Options; } uint16_t getParameterCount() const { return ParameterCount; } TypeIndex getArgumentList() const { return ArgumentList; } -private: - struct Layout { - TypeIndex ReturnType; - CallingConvention CallConv; - FunctionOptions Options; - ulittle16_t NumParameters; - TypeIndex ArgListType; - }; - TypeIndex ReturnType; CallingConvention CallConv; FunctionOptions Options; @@ -182,6 +181,8 @@ private: // LF_MFUNCTION class MemberFunctionRecord : public TypeRecord { public: + explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType, TypeIndex ThisType, CallingConvention CallConv, FunctionOptions Options, uint16_t ParameterCount, @@ -196,9 +197,6 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<MemberFunctionRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getReturnType() const { return ReturnType; } TypeIndex getClassType() const { return ClassType; } TypeIndex getThisType() const { return ThisType; } @@ -208,18 +206,6 @@ public: TypeIndex getArgumentList() const { return ArgumentList; } int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; } -private: - struct Layout { - TypeIndex ReturnType; - TypeIndex ClassType; - TypeIndex ThisType; - CallingConvention CallConv; - FunctionOptions Options; - ulittle16_t NumParameters; - TypeIndex ArgListType; - little32_t ThisAdjustment; - }; - TypeIndex ReturnType; TypeIndex ClassType; TypeIndex ThisType; @@ -233,6 +219,7 @@ private: // LF_MFUNC_ID class MemberFuncIdRecord : public TypeRecord { public: + explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType, StringRef Name) : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType), @@ -242,18 +229,9 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<MemberFuncIdRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); TypeIndex getClassType() const { return ClassType; } TypeIndex getFunctionType() const { return FunctionType; } StringRef getName() const { return Name; } - -private: - struct Layout { - TypeIndex ClassType; - TypeIndex FunctionType; - // Name: The null-terminated name follows. - }; TypeIndex ClassType; TypeIndex FunctionType; StringRef Name; @@ -262,6 +240,8 @@ private: // LF_ARGLIST, LF_SUBSTR_LIST class ArgListRecord : public TypeRecord { public: + explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices) : TypeRecord(Kind), StringIndices(Indices) {} @@ -269,19 +249,8 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<ArgListRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - ArrayRef<TypeIndex> getIndices() const { return StringIndices; } - static uint32_t getLayoutSize() { return 2 + sizeof(Layout); } - -private: - struct Layout { - ulittle32_t NumArgs; // Number of arguments - // ArgTypes[]: Type indicies of arguments - }; - std::vector<TypeIndex> StringIndices; }; @@ -294,94 +263,96 @@ public: static const uint32_t PointerModeShift = 5; static const uint32_t PointerModeMask = 0x07; + static const uint32_t PointerOptionMask = 0xFF; + static const uint32_t PointerSizeShift = 13; static const uint32_t PointerSizeMask = 0xFF; - PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode, - PointerOptions Options, uint8_t Size) - : PointerRecord(ReferentType, Kind, Mode, Options, Size, - MemberPointerInfo()) {} + explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} - PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode, - PointerOptions Options, uint8_t Size, + PointerRecord(TypeIndex ReferentType, uint32_t Attrs) + : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), + Attrs(Attrs) {} + + PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM, + PointerOptions PO, uint8_t Size) + : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), + Attrs(calcAttrs(PK, PM, PO, Size)) {} + + PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM, + PointerOptions PO, uint8_t Size, + const MemberPointerInfo &Member) + : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), + Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(Member) {} + + PointerRecord(TypeIndex ReferentType, uint32_t Attrs, const MemberPointerInfo &Member) : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), - PtrKind(Kind), Mode(Mode), Options(Options), Size(Size), - MemberInfo(Member) {} + Attrs(Attrs), MemberInfo(Member) {} /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<PointerRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getReferentType() const { return ReferentType; } - PointerKind getPointerKind() const { return PtrKind; } - PointerMode getMode() const { return Mode; } - PointerOptions getOptions() const { return Options; } - uint8_t getSize() const { return Size; } - MemberPointerInfo getMemberInfo() const { return MemberInfo; } - bool isPointerToMember() const { - return Mode == PointerMode::PointerToDataMember || - Mode == PointerMode::PointerToMemberFunction; + PointerKind getPointerKind() const { + return static_cast<PointerKind>((Attrs >> PointerKindShift) & + PointerKindMask); + } + + PointerMode getMode() const { + return static_cast<PointerMode>((Attrs >> PointerModeShift) & + PointerModeMask); } - bool isFlat() const { - return !!(uint32_t(Options) & uint32_t(PointerOptions::Flat32)); + + PointerOptions getOptions() const { + return static_cast<PointerOptions>(Attrs); } - bool isConst() const { - return !!(uint32_t(Options) & uint32_t(PointerOptions::Const)); + + uint8_t getSize() const { + return (Attrs >> PointerSizeShift) & PointerSizeMask; } + + MemberPointerInfo getMemberInfo() const { return *MemberInfo; } + + bool isPointerToMember() const { + return getMode() == PointerMode::PointerToDataMember || + getMode() == PointerMode::PointerToMemberFunction; + } + + bool isFlat() const { return !!(Attrs & uint32_t(PointerOptions::Flat32)); } + bool isConst() const { return !!(Attrs & uint32_t(PointerOptions::Const)); } + bool isVolatile() const { - return !!(uint32_t(Options) & uint32_t(PointerOptions::Volatile)); + return !!(Attrs & uint32_t(PointerOptions::Volatile)); } + bool isUnaligned() const { - return !!(uint32_t(Options) & uint32_t(PointerOptions::Unaligned)); + return !!(Attrs & uint32_t(PointerOptions::Unaligned)); } -private: - struct Layout { - TypeIndex PointeeType; - ulittle32_t Attrs; // pointer attributes - // if pointer to member: - // PointerToMemberTail - PointerKind getPtrKind() const { - return PointerKind(Attrs & PointerKindMask); - } - PointerMode getPtrMode() const { - return PointerMode((Attrs >> PointerModeShift) & PointerModeMask); - } - uint8_t getPtrSize() const { - return (Attrs >> PointerSizeShift) & PointerSizeMask; - } - bool isFlat() const { return Attrs & (1 << 8); } - bool isVolatile() const { return Attrs & (1 << 9); } - bool isConst() const { return Attrs & (1 << 10); } - bool isUnaligned() const { return Attrs & (1 << 11); } - - bool isPointerToDataMember() const { - return getPtrMode() == PointerMode::PointerToDataMember; - } - bool isPointerToMemberFunction() const { - return getPtrMode() == PointerMode::PointerToMemberFunction; - } - bool isPointerToMember() const { - return isPointerToMemberFunction() || isPointerToDataMember(); - } - }; - TypeIndex ReferentType; - PointerKind PtrKind; - PointerMode Mode; - PointerOptions Options; - uint8_t Size; - MemberPointerInfo MemberInfo; + uint32_t Attrs; + + Optional<MemberPointerInfo> MemberInfo; + +private: + static uint32_t calcAttrs(PointerKind PK, PointerMode PM, PointerOptions PO, + uint8_t Size) { + uint32_t A = 0; + A |= static_cast<uint32_t>(PK); + A |= static_cast<uint32_t>(PO); + A |= (static_cast<uint32_t>(PM) << PointerModeShift); + A |= (static_cast<uint32_t>(Size) << PointerSizeShift); + return A; + } }; // LF_NESTTYPE class NestedTypeRecord : public TypeRecord { public: + explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} NestedTypeRecord(TypeIndex Type, StringRef Name) : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {} @@ -389,26 +360,31 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<NestedTypeRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getNestedType() const { return Type; } StringRef getName() const { return Name; } -private: - struct Layout { - ulittle16_t Pad0; // Should be zero - TypeIndex Type; // Type index of nested type - // Name: Null-terminated string - }; - TypeIndex Type; StringRef Name; }; +// LF_FIELDLIST +class FieldListRecord : public TypeRecord { +public: + explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + explicit FieldListRecord(ArrayRef<uint8_t> Data) + : TypeRecord(TypeRecordKind::FieldList), Data(Data) {} + + /// Rewrite member type indices with IndexMap. Returns false if a type index + /// is not in the map. + bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { return false; } + + ArrayRef<uint8_t> Data; +}; + // LF_ARRAY class ArrayRecord : public TypeRecord { public: + explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size, StringRef Name) : TypeRecord(TypeRecordKind::Array), ElementType(ElementType), @@ -418,30 +394,20 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<ArrayRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getElementType() const { return ElementType; } TypeIndex getIndexType() const { return IndexType; } uint64_t getSize() const { return Size; } - llvm::StringRef getName() const { return Name; } - -private: - struct Layout { - TypeIndex ElementType; - TypeIndex IndexType; - // SizeOf: LF_NUMERIC encoded size in bytes. Not element count! - // Name: The null-terminated name follows. - }; + StringRef getName() const { return Name; } TypeIndex ElementType; TypeIndex IndexType; uint64_t Size; - llvm::StringRef Name; + StringRef Name; }; class TagRecord : public TypeRecord { protected: + explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, StringRef Name, StringRef UniqueName) : TypeRecord(Kind), MemberCount(MemberCount), Options(Options), @@ -457,13 +423,16 @@ public: static const int WinRTKindShift = 14; static const int WinRTKindMask = 0xC000; + bool hasUniqueName() const { + return (Options & ClassOptions::HasUniqueName) != ClassOptions::None; + } + uint16_t getMemberCount() const { return MemberCount; } ClassOptions getOptions() const { return Options; } TypeIndex getFieldList() const { return FieldList; } StringRef getName() const { return Name; } StringRef getUniqueName() const { return UniqueName; } -private: uint16_t MemberCount; ClassOptions Options; TypeIndex FieldList; @@ -474,45 +443,34 @@ private: // LF_CLASS, LF_STRUCTURE, LF_INTERFACE class ClassRecord : public TagRecord { public: + explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {} ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, - HfaKind Hfa, WindowsRTClassKind WinRTKind, TypeIndex FieldList, - TypeIndex DerivationList, TypeIndex VTableShape, uint64_t Size, - StringRef Name, StringRef UniqueName) + TypeIndex FieldList, TypeIndex DerivationList, + TypeIndex VTableShape, uint64_t Size, StringRef Name, + StringRef UniqueName) : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName), - Hfa(Hfa), WinRTKind(WinRTKind), DerivationList(DerivationList), - VTableShape(VTableShape), Size(Size) {} + DerivationList(DerivationList), VTableShape(VTableShape), Size(Size) {} /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<ClassRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); + HfaKind getHfa() const { + uint16_t Value = static_cast<uint16_t>(Options); + Value = (Value & HfaKindMask) >> HfaKindShift; + return static_cast<HfaKind>(Value); + } + + WindowsRTClassKind getWinRTKind() const { + uint16_t Value = static_cast<uint16_t>(Options); + Value = (Value & WinRTKindMask) >> WinRTKindShift; + return static_cast<WindowsRTClassKind>(Value); + } - HfaKind getHfa() const { return Hfa; } - WindowsRTClassKind getWinRTKind() const { return WinRTKind; } TypeIndex getDerivationList() const { return DerivationList; } TypeIndex getVTableShape() const { return VTableShape; } uint64_t getSize() const { return Size; } -private: - struct Layout { - ulittle16_t MemberCount; // Number of members in FieldList. - ulittle16_t Properties; // ClassOptions bitset - TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members - TypeIndex DerivedFrom; // LF_DERIVED: List of known derived classes - TypeIndex VShape; // LF_VTSHAPE: Shape of the vftable - // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC - // integer. - // Name: The null-terminated name follows. - - bool hasUniqueName() const { - return Properties & uint16_t(ClassOptions::HasUniqueName); - } - }; - - HfaKind Hfa; - WindowsRTClassKind WinRTKind; TypeIndex DerivationList; TypeIndex VTableShape; uint64_t Size; @@ -520,40 +478,28 @@ private: // LF_UNION struct UnionRecord : public TagRecord { - UnionRecord(uint16_t MemberCount, ClassOptions Options, HfaKind Hfa, - TypeIndex FieldList, uint64_t Size, StringRef Name, - StringRef UniqueName) + explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {} + UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, + uint64_t Size, StringRef Name, StringRef UniqueName) : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name, UniqueName), - Hfa(Hfa), Size(Size) {} + Size(Size) {} - static ErrorOr<UnionRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); + HfaKind getHfa() const { + uint16_t Value = static_cast<uint16_t>(Options); + Value = (Value & HfaKindMask) >> HfaKindShift; + return static_cast<HfaKind>(Value); + } - HfaKind getHfa() const { return Hfa; } uint64_t getSize() const { return Size; } -private: - struct Layout { - ulittle16_t MemberCount; // Number of members in FieldList. - ulittle16_t Properties; // ClassOptions bitset - TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members - // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC - // integer. - // Name: The null-terminated name follows. - - bool hasUniqueName() const { - return Properties & uint16_t(ClassOptions::HasUniqueName); - } - }; - - HfaKind Hfa; uint64_t Size; }; // LF_ENUM class EnumRecord : public TagRecord { public: + explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {} EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType) : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name, @@ -563,30 +509,14 @@ public: /// Rewrite member type indices with IndexMap. Returns false if a type index is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<EnumRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getUnderlyingType() const { return UnderlyingType; } - -private: - struct Layout { - ulittle16_t NumEnumerators; // Number of enumerators - ulittle16_t Properties; - TypeIndex UnderlyingType; - TypeIndex FieldListType; - // Name: The null-terminated name follows. - - bool hasUniqueName() const { - return Properties & uint16_t(ClassOptions::HasUniqueName); - } - }; - TypeIndex UnderlyingType; }; // LF_BITFIELD class BitFieldRecord : public TypeRecord { public: + explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset) : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize), BitOffset(BitOffset) {} @@ -595,20 +525,9 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<BitFieldRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getType() const { return Type; } uint8_t getBitOffset() const { return BitOffset; } uint8_t getBitSize() const { return BitSize; } - -private: - struct Layout { - TypeIndex Type; - uint8_t BitSize; - uint8_t BitOffset; - }; - TypeIndex Type; uint8_t BitSize; uint8_t BitOffset; @@ -617,6 +536,7 @@ private: // LF_VTSHAPE class VFTableShapeRecord : public TypeRecord { public: + explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots) : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {} explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots) @@ -626,26 +546,13 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<VFTableShapeRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - ArrayRef<VFTableSlotKind> getSlots() const { if (!SlotsRef.empty()) return SlotsRef; return Slots; } - uint32_t getEntryCount() const { return getSlots().size(); } - -private: - struct Layout { - // Number of vftable entries. Each method may have more than one entry due - // to - // things like covariant return types. - ulittle16_t VFEntryCount; - // Descriptors[]: 4-bit virtual method descriptors of type CV_VTS_desc_e. - }; -private: + uint32_t getEntryCount() const { return getSlots().size(); } ArrayRef<VFTableSlotKind> SlotsRef; std::vector<VFTableSlotKind> Slots; }; @@ -653,6 +560,7 @@ private: // LF_TYPESERVER2 class TypeServer2Record : public TypeRecord { public: + explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {} TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name) : TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age), Name(Name) {} @@ -661,22 +569,12 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<TypeServer2Record> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - StringRef getGuid() const { return Guid; } uint32_t getAge() const { return Age; } StringRef getName() const { return Name; } -private: - struct Layout { - char Guid[16]; // GUID - ulittle32_t Age; - // Name: Name of the PDB as a null-terminated string - }; - StringRef Guid; uint32_t Age; StringRef Name; @@ -685,6 +583,7 @@ private: // LF_STRING_ID class StringIdRecord : public TypeRecord { public: + explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} StringIdRecord(TypeIndex Id, StringRef String) : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {} @@ -692,19 +591,9 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<StringIdRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getId() const { return Id; } StringRef getString() const { return String; } - -private: - struct Layout { - TypeIndex id; - // Name: Name of the PDB as a null-terminated string - }; - TypeIndex Id; StringRef String; }; @@ -712,6 +601,7 @@ private: // LF_FUNC_ID class FuncIdRecord : public TypeRecord { public: + explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name) : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope), FunctionType(FunctionType), Name(Name) {} @@ -720,22 +610,12 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<FuncIdRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getParentScope() const { return ParentScope; } TypeIndex getFunctionType() const { return FunctionType; } StringRef getName() const { return Name; } -private: - struct Layout { - TypeIndex ParentScope; - TypeIndex FunctionType; - // Name: The null-terminated name follows. - }; - TypeIndex ParentScope; TypeIndex FunctionType; StringRef Name; @@ -744,6 +624,7 @@ private: // LF_UDT_SRC_LINE class UdtSourceLineRecord : public TypeRecord { public: + explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber) : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), SourceFile(SourceFile), LineNumber(LineNumber) {} @@ -752,20 +633,10 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<UdtSourceLineRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getUDT() const { return UDT; } TypeIndex getSourceFile() const { return SourceFile; } uint32_t getLineNumber() const { return LineNumber; } -private: - struct Layout { - TypeIndex UDT; // The user-defined type - TypeIndex SourceFile; // StringID containing the source filename - ulittle32_t LineNumber; - }; - TypeIndex UDT; TypeIndex SourceFile; uint32_t LineNumber; @@ -774,6 +645,7 @@ private: // LF_UDT_MOD_SRC_LINE class UdtModSourceLineRecord : public TypeRecord { public: + explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber, uint16_t Module) : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), @@ -781,28 +653,11 @@ public: bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<UdtModSourceLineRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data) { - const Layout *L = nullptr; - CV_DESERIALIZE(Data, L); - - return UdtModSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber, - L->Module); - } - TypeIndex getUDT() const { return UDT; } TypeIndex getSourceFile() const { return SourceFile; } uint32_t getLineNumber() const { return LineNumber; } uint16_t getModule() const { return Module; } -private: - struct Layout { - TypeIndex UDT; // The user-defined type - TypeIndex SourceFile; // StringID containing the source filename - ulittle32_t LineNumber; - ulittle16_t Module; // Module that contributes this UDT definition - }; - TypeIndex UDT; TypeIndex SourceFile; uint32_t LineNumber; @@ -812,6 +667,7 @@ private: // LF_BUILDINFO class BuildInfoRecord : public TypeRecord { public: + explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices) : TypeRecord(TypeRecordKind::BuildInfo), ArgIndices(ArgIndices.begin(), ArgIndices.end()) {} @@ -820,111 +676,73 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<BuildInfoRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - ArrayRef<TypeIndex> getArgs() const { return ArgIndices; } - -private: - struct Layout { - ulittle16_t NumArgs; // Number of arguments - // ArgTypes[]: Type indicies of arguments - }; SmallVector<TypeIndex, 4> ArgIndices; }; // LF_VFTABLE class VFTableRecord : public TypeRecord { public: + explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable, uint32_t VFPtrOffset, StringRef Name, ArrayRef<StringRef> Methods) - : TypeRecord(TypeRecordKind::VFTable), - CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable), - VFPtrOffset(VFPtrOffset), Name(Name), MethodNamesRef(Methods) {} - VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable, - uint32_t VFPtrOffset, StringRef Name, - const std::vector<StringRef> &Methods) - : TypeRecord(TypeRecordKind::VFTable), - CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable), - VFPtrOffset(VFPtrOffset), Name(Name), MethodNames(Methods) {} + : TypeRecord(TypeRecordKind::VFTable), CompleteClass(CompleteClass), + OverriddenVFTable(OverriddenVFTable), VFPtrOffset(VFPtrOffset) { + MethodNames.push_back(Name); + MethodNames.insert(MethodNames.end(), Methods.begin(), Methods.end()); + } /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<VFTableRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getCompleteClass() const { return CompleteClass; } TypeIndex getOverriddenVTable() const { return OverriddenVFTable; } uint32_t getVFPtrOffset() const { return VFPtrOffset; } - StringRef getName() const { return Name; } + StringRef getName() const { return makeArrayRef(MethodNames).front(); } ArrayRef<StringRef> getMethodNames() const { - if (!MethodNamesRef.empty()) - return MethodNamesRef; - return MethodNames; + return makeArrayRef(MethodNames).drop_front(); } -private: - struct Layout { - TypeIndex CompleteClass; // Class that owns this vftable. - TypeIndex OverriddenVFTable; // VFTable that this overrides. - ulittle32_t VFPtrOffset; // VFPtr offset in CompleteClass - ulittle32_t NamesLen; // Length of subsequent names array in bytes. - // Names: A sequence of null-terminated strings. First string is vftable - // names. - }; - TypeIndex CompleteClass; TypeIndex OverriddenVFTable; - ulittle32_t VFPtrOffset; - StringRef Name; - ArrayRef<StringRef> MethodNamesRef; + uint32_t VFPtrOffset; std::vector<StringRef> MethodNames; }; // LF_ONEMETHOD class OneMethodRecord : public TypeRecord { public: - OneMethodRecord(TypeIndex Type, MethodKind Kind, MethodOptions Options, - MemberAccess Access, int32_t VFTableOffset, StringRef Name) - : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Kind(Kind), - Options(Options), Access(Access), VFTableOffset(VFTableOffset), - Name(Name) {} + OneMethodRecord() : TypeRecord(TypeRecordKind::OneMethod) {} + explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + OneMethodRecord(TypeIndex Type, MemberAttributes Attrs, int32_t VFTableOffset, + StringRef Name) + : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Attrs(Attrs), + VFTableOffset(VFTableOffset), Name(Name) {} + OneMethodRecord(TypeIndex Type, MemberAccess Access, MethodKind MK, + MethodOptions Options, int32_t VFTableOffset, StringRef Name) + : TypeRecord(TypeRecordKind::OneMethod), Type(Type), + Attrs(Access, MK, Options), VFTableOffset(VFTableOffset), Name(Name) {} /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<OneMethodRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getType() const { return Type; } - MethodKind getKind() const { return Kind; } - MethodOptions getOptions() const { return Options; } - MemberAccess getAccess() const { return Access; } + MethodKind getMethodKind() const { return Attrs.getMethodKind(); } + MethodOptions getOptions() const { return Attrs.getFlags(); } + MemberAccess getAccess() const { return Attrs.getAccess(); } int32_t getVFTableOffset() const { return VFTableOffset; } StringRef getName() const { return Name; } bool isIntroducingVirtual() const { - return Kind == MethodKind::IntroducingVirtual || - Kind == MethodKind::PureIntroducingVirtual; + return getMethodKind() == MethodKind::IntroducingVirtual || + getMethodKind() == MethodKind::PureIntroducingVirtual; } -private: - struct Layout { - MemberAttributes Attrs; - TypeIndex Type; - // If is introduced virtual method: - // VFTableOffset: int32_t offset in vftable - // Name: Null-terminated string - }; - TypeIndex Type; - MethodKind Kind; - MethodOptions Options; - MemberAccess Access; + MemberAttributes Attrs; int32_t VFTableOffset; StringRef Name; }; @@ -932,6 +750,7 @@ private: // LF_METHODLIST class MethodOverloadListRecord : public TypeRecord { public: + explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods) : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {} @@ -939,27 +758,14 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<MethodOverloadListRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - ArrayRef<OneMethodRecord> getMethods() const { return Methods; } - -private: - struct Layout { - MemberAttributes Attrs; - ulittle16_t Padding; - - TypeIndex Type; - // If is introduced virtual method: - // VFTableOffset: int32_t offset in vftable - }; - std::vector<OneMethodRecord> Methods; }; /// For method overload sets. LF_METHOD class OverloadedMethodRecord : public TypeRecord { public: + explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList, StringRef Name) : TypeRecord(TypeRecordKind::OverloadedMethod), @@ -969,20 +775,9 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<OverloadedMethodRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - uint16_t getNumOverloads() const { return NumOverloads; } TypeIndex getMethodList() const { return MethodList; } StringRef getName() const { return Name; } - -private: - struct Layout { - ulittle16_t MethodCount; // Size of overload set - TypeIndex MethList; // Type index of methods in overload set - // Name: Null-terminated string - }; - uint16_t NumOverloads; TypeIndex MethodList; StringRef Name; @@ -991,32 +786,26 @@ private: // LF_MEMBER class DataMemberRecord : public TypeRecord { public: + explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset, + StringRef Name) + : TypeRecord(TypeRecordKind::DataMember), Attrs(Attrs), Type(Type), + FieldOffset(Offset), Name(Name) {} DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset, StringRef Name) - : TypeRecord(TypeRecordKind::DataMember), Access(Access), Type(Type), + : TypeRecord(TypeRecordKind::DataMember), Attrs(Access), Type(Type), FieldOffset(Offset), Name(Name) {} /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<DataMemberRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - - MemberAccess getAccess() const { return Access; } + MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getType() const { return Type; } uint64_t getFieldOffset() const { return FieldOffset; } StringRef getName() const { return Name; } -private: - struct Layout { - MemberAttributes Attrs; // Access control attributes, etc - TypeIndex Type; - // FieldOffset: LF_NUMERIC encoded byte offset - // Name: Null-terminated string - }; - - MemberAccess Access; + MemberAttributes Attrs; TypeIndex Type; uint64_t FieldOffset; StringRef Name; @@ -1025,29 +814,23 @@ private: // LF_STMEMBER class StaticDataMemberRecord : public TypeRecord { public: + explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name) + : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type), + Name(Name) {} StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name) - : TypeRecord(TypeRecordKind::StaticDataMember), Access(Access), - Type(Type), Name(Name) {} + : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Access), Type(Type), + Name(Name) {} /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<StaticDataMemberRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - - MemberAccess getAccess() const { return Access; } + MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getType() const { return Type; } StringRef getName() const { return Name; } -private: - struct Layout { - MemberAttributes Attrs; // Access control attributes, etc - TypeIndex Type; - // Name: Null-terminated string - }; - - MemberAccess Access; + MemberAttributes Attrs; TypeIndex Type; StringRef Name; }; @@ -1055,29 +838,23 @@ private: // LF_ENUMERATE class EnumeratorRecord : public TypeRecord { public: + explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name) + : TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs), + Value(std::move(Value)), Name(Name) {} EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name) - : TypeRecord(TypeRecordKind::Enumerator), Access(Access), + : TypeRecord(TypeRecordKind::Enumerator), Attrs(Access), Value(std::move(Value)), Name(Name) {} /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<EnumeratorRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - - MemberAccess getAccess() const { return Access; } + MemberAccess getAccess() const { return Attrs.getAccess(); } APSInt getValue() const { return Value; } StringRef getName() const { return Name; } -private: - struct Layout { - MemberAttributes Attrs; // Access control attributes, etc - // EnumValue: LF_NUMERIC encoded enumerator value - // Name: Null-terminated string - }; - - MemberAccess Access; + MemberAttributes Attrs; APSInt Value; StringRef Name; }; @@ -1085,6 +862,7 @@ private: // LF_VFUNCTAB class VFPtrRecord : public TypeRecord { public: + explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} VFPtrRecord(TypeIndex Type) : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {} @@ -1092,44 +870,31 @@ public: /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<VFPtrRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - TypeIndex getType() const { return Type; } -private: - struct Layout { - ulittle16_t Pad0; - TypeIndex Type; // Type of vfptr - }; TypeIndex Type; }; // LF_BCLASS, LF_BINTERFACE class BaseClassRecord : public TypeRecord { public: + explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset) + : TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type), + Offset(Offset) {} BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset) - : TypeRecord(TypeRecordKind::BaseClass), Access(Access), Type(Type), + : TypeRecord(TypeRecordKind::BaseClass), Attrs(Access), Type(Type), Offset(Offset) {} /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<BaseClassRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - - MemberAccess getAccess() const { return Access; } + MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getBaseType() const { return Type; } uint64_t getBaseOffset() const { return Offset; } -private: - struct Layout { - MemberAttributes Attrs; // Access control attributes, etc - TypeIndex BaseType; // Base class type - // BaseOffset: LF_NUMERIC encoded byte offset of base from derived. - }; - MemberAccess Access; + MemberAttributes Attrs; TypeIndex Type; uint64_t Offset; }; @@ -1137,34 +902,29 @@ private: // LF_VBCLASS, LF_IVBCLASS class VirtualBaseClassRecord : public TypeRecord { public: - VirtualBaseClassRecord(MemberAccess Access, TypeIndex BaseType, - TypeIndex VBPtrType, uint64_t Offset, uint64_t Index) - : TypeRecord(TypeRecordKind::VirtualBaseClass), Access(Access), - BaseType(BaseType), VBPtrType(VBPtrType), VBPtrOffset(Offset), - VTableIndex(Index) {} + explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs, + TypeIndex BaseType, TypeIndex VBPtrType, + uint64_t Offset, uint64_t Index) + : TypeRecord(Kind), Attrs(Attrs), BaseType(BaseType), + VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {} + VirtualBaseClassRecord(TypeRecordKind Kind, MemberAccess Access, + TypeIndex BaseType, TypeIndex VBPtrType, + uint64_t Offset, uint64_t Index) + : TypeRecord(Kind), Attrs(Access), BaseType(BaseType), + VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {} /// Rewrite member type indices with IndexMap. Returns false if a type index /// is not in the map. bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<VirtualBaseClassRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - - MemberAccess getAccess() const { return Access; } + MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getBaseType() const { return BaseType; } TypeIndex getVBPtrType() const { return VBPtrType; } uint64_t getVBPtrOffset() const { return VBPtrOffset; } uint64_t getVTableIndex() const { return VTableIndex; } -private: - struct Layout { - MemberAttributes Attrs; // Access control attributes, etc. - TypeIndex BaseType; // Base class type - TypeIndex VBPtrType; // Virtual base pointer type - // VBPtrOffset: Offset of vbptr from vfptr encoded as LF_NUMERIC. - // VBTableIndex: Index of vbase within vbtable encoded as LF_NUMERIC. - }; - MemberAccess Access; + MemberAttributes Attrs; TypeIndex BaseType; TypeIndex VBPtrType; uint64_t VBPtrOffset; @@ -1175,6 +935,7 @@ private: /// together. The first will end in an LF_INDEX record that points to the next. class ListContinuationRecord : public TypeRecord { public: + explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ListContinuationRecord(TypeIndex ContinuationIndex) : TypeRecord(TypeRecordKind::ListContinuation), ContinuationIndex(ContinuationIndex) {} @@ -1183,20 +944,11 @@ public: bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static ErrorOr<ListContinuationRecord> deserialize(TypeRecordKind Kind, - ArrayRef<uint8_t> &Data); - -private: - struct Layout { - ulittle16_t Pad0; - TypeIndex ContinuationIndex; - }; TypeIndex ContinuationIndex; }; -typedef CVRecord<TypeLeafKind> CVType; -typedef VarStreamArray<CVType> CVTypeArray; -} -} +} // end namespace codeview + +} // end namespace llvm -#endif +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h index eb7993b..5a6507e 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h @@ -47,6 +47,12 @@ public: llvm::StringRef str(); uint64_t size() const { return Stream.tell(); } + TypeRecordKind kind() const { return Kind; } + + /// Returns the number of bytes remaining before this record is larger than + /// the maximum record length. Accounts for the extra two byte size field in + /// the header. + size_t maxBytesRemaining() const { return MaxRecordLength - size() - 2; } void truncate(uint64_t Size) { // This works because raw_svector_ostream is not buffered. @@ -56,10 +62,12 @@ public: void reset(TypeRecordKind K) { Buffer.clear(); + Kind = K; writeTypeRecordKind(K); } private: + TypeRecordKind Kind; llvm::SmallVector<char, 256> Buffer; llvm::raw_svector_ostream Stream; llvm::support::endian::Writer<llvm::support::endianness::little> Writer; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h new file mode 100644 index 0000000..fe470a7 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h @@ -0,0 +1,52 @@ +//===- TypeRecordMapping.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_TYPERECORDMAPPING_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDMAPPING_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace msf { +class StreamReader; +class StreamWriter; +} +namespace codeview { +class TypeRecordMapping : public TypeVisitorCallbacks { +public: + explicit TypeRecordMapping(msf::StreamReader &Reader) : IO(Reader) {} + explicit TypeRecordMapping(msf::StreamWriter &Writer) : IO(Writer) {} + + Error visitTypeBegin(CVType &Record) override; + Error visitTypeEnd(CVType &Record) override; + + Error visitMemberBegin(CVMemberRecord &Record) override; + Error visitMemberEnd(CVMemberRecord &Record) override; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override; +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "TypeRecords.def" + +private: + Optional<TypeLeafKind> TypeKind; + Optional<TypeLeafKind> MemberKind; + + CodeViewRecordIO IO; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def index 0959f4b..c98dbac 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def @@ -43,6 +43,8 @@ TYPE_RECORD(LF_PROCEDURE, 0x1008, Procedure) TYPE_RECORD(LF_MFUNCTION, 0x1009, MemberFunction) TYPE_RECORD(LF_ARGLIST, 0x1201, ArgList) +TYPE_RECORD(LF_FIELDLIST, 0x1203, FieldList) + TYPE_RECORD(LF_ARRAY, 0x1503, Array) TYPE_RECORD(LF_CLASS, 0x1504, Class) TYPE_RECORD_ALIAS(LF_STRUCTURE, 0x1505, Struct, Class) @@ -159,7 +161,6 @@ CV_TYPE(LF_OEM2, 0x1011) CV_TYPE(LF_SKIP, 0x1200) CV_TYPE(LF_DEFARG_ST, 0x1202) -CV_TYPE(LF_FIELDLIST, 0x1203) CV_TYPE(LF_DERIVED, 0x1204) CV_TYPE(LF_DIMCONU, 0x1207) CV_TYPE(LF_DIMCONLU, 0x1208) diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h new file mode 100644 index 0000000..e059221 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h @@ -0,0 +1,140 @@ +//===- TypeSerializer.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_TYPESERIALIZER_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H + +#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/DebugInfo/MSF/ByteStream.h" +#include "llvm/DebugInfo/MSF/StreamWriter.h" + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" + +namespace llvm { + +namespace codeview { + +class TypeSerializer : public TypeVisitorCallbacks { + struct SubRecord { + SubRecord(TypeLeafKind K, uint32_t S) : Kind(K), Size(S) {} + + TypeLeafKind Kind; + uint32_t Size = 0; + }; + struct RecordSegment { + SmallVector<SubRecord, 16> SubRecords; + + uint32_t length() const { + uint32_t L = sizeof(RecordPrefix); + for (const auto &R : SubRecords) { + L += R.Size; + } + return L; + } + }; + + typedef SmallVector<MutableArrayRef<uint8_t>, 2> RecordList; + + static constexpr uint8_t ContinuationLength = 8; + BumpPtrAllocator &RecordStorage; + RecordSegment CurrentSegment; + RecordList FieldListSegments; + + TypeIndex LastTypeIndex; + Optional<TypeLeafKind> TypeKind; + Optional<TypeLeafKind> MemberKind; + std::vector<uint8_t> RecordBuffer; + msf::MutableByteStream Stream; + msf::StreamWriter Writer; + TypeRecordMapping Mapping; + + RecordList SeenRecords; + StringMap<TypeIndex> HashedRecords; + + bool isInFieldList() const; + TypeIndex calcNextTypeIndex() const; + TypeIndex incrementTypeIndex(); + MutableArrayRef<uint8_t> getCurrentSubRecordData(); + MutableArrayRef<uint8_t> getCurrentRecordData(); + Error writeRecordPrefix(TypeLeafKind Kind); + TypeIndex insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record); + + Expected<MutableArrayRef<uint8_t>> + addPadding(MutableArrayRef<uint8_t> Record); + +public: + explicit TypeSerializer(BumpPtrAllocator &Storage); + + ArrayRef<MutableArrayRef<uint8_t>> records() const; + TypeIndex getLastTypeIndex() const; + TypeIndex insertRecordBytes(MutableArrayRef<uint8_t> Record); + Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record); + + Error visitTypeBegin(CVType &Record) override; + Error visitTypeEnd(CVType &Record) override; + Error visitMemberBegin(CVMemberRecord &Record) override; + Error visitMemberEnd(CVMemberRecord &Record) override; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \ + return visitKnownRecordImpl(CVR, Record); \ + } +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \ + return visitKnownMemberImpl<Name##Record>(CVR, Record); \ + } +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/TypeRecords.def" + +private: + template <typename RecordKind> + Error visitKnownRecordImpl(CVType &CVR, RecordKind &Record) { + return Mapping.visitKnownRecord(CVR, Record); + } + + template <typename RecordType> + Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) { + assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind())); + + if (auto EC = Writer.writeEnum(CVR.Kind)) + return EC; + + if (auto EC = Mapping.visitKnownMember(CVR, Record)) + return EC; + + // Get all the data that was just written and is yet to be committed to + // the current segment. Then pad it to 4 bytes. + MutableArrayRef<uint8_t> ThisRecord = getCurrentSubRecordData(); + auto ExpectedRecord = addPadding(ThisRecord); + if (!ExpectedRecord) + return ExpectedRecord.takeError(); + ThisRecord = *ExpectedRecord; + + CurrentSegment.SubRecords.emplace_back(CVR.Kind, ThisRecord.size()); + CVR.Data = ThisRecord; + + // Both the last subrecord and the total length of this segment should be + // multiples of 4. + assert(ThisRecord.size() % 4 == 0); + assert(CurrentSegment.length() % 4 == 0); + + return Error::success(); + } +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h index 5b2aa61..4e6d81e 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h @@ -10,61 +10,120 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H #define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeSerializer.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/Support/Compiler.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <type_traits> namespace llvm { - -class StringRef; - namespace codeview { -class FieldListRecordBuilder; -class MethodListRecordBuilder; -class TypeRecordBuilder; - class TypeTableBuilder { private: + TypeIndex handleError(Error EC) const { + assert(false && "Couldn't write Type!"); + consumeError(std::move(EC)); + return TypeIndex(); + } + + BumpPtrAllocator &Allocator; + TypeSerializer Serializer; + +public: + explicit TypeTableBuilder(BumpPtrAllocator &Allocator) + : Allocator(Allocator), Serializer(Allocator) {} TypeTableBuilder(const TypeTableBuilder &) = delete; TypeTableBuilder &operator=(const TypeTableBuilder &) = delete; -protected: - TypeTableBuilder(); + bool empty() const { return Serializer.records().empty(); } -public: - virtual ~TypeTableBuilder(); + BumpPtrAllocator &getAllocator() const { return Allocator; } + + template <typename T> TypeIndex writeKnownType(T &Record) { + static_assert(!std::is_same<T, FieldListRecord>::value, + "Can't serialize FieldList!"); + + CVType Type; + Type.Type = static_cast<TypeLeafKind>(Record.getKind()); + if (auto EC = Serializer.visitTypeBegin(Type)) + return handleError(std::move(EC)); + if (auto EC = Serializer.visitKnownRecord(Type, Record)) + return handleError(std::move(EC)); + + auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type); + if (!ExpectedIndex) + return handleError(ExpectedIndex.takeError()); + + return *ExpectedIndex; + } + + TypeIndex writeSerializedRecord(MutableArrayRef<uint8_t> Record) { + return Serializer.insertRecordBytes(Record); + } + + template <typename TFunc> void ForEachRecord(TFunc Func) { + uint32_t Index = TypeIndex::FirstNonSimpleIndex; + + for (auto Record : Serializer.records()) { + Func(TypeIndex(Index), Record); + ++Index; + } + } + + ArrayRef<MutableArrayRef<uint8_t>> records() const { + return Serializer.records(); + } +}; + +class FieldListRecordBuilder { + TypeTableBuilder &TypeTable; + TypeSerializer TempSerializer; + CVType Type; public: - TypeIndex writeModifier(const ModifierRecord &Record); - TypeIndex writeProcedure(const ProcedureRecord &Record); - TypeIndex writeMemberFunction(const MemberFunctionRecord &Record); - TypeIndex writeArgList(const ArgListRecord &Record); - TypeIndex writePointer(const PointerRecord &Record); - TypeIndex writeArray(const ArrayRecord &Record); - TypeIndex writeClass(const ClassRecord &Record); - TypeIndex writeUnion(const UnionRecord &Record); - TypeIndex writeEnum(const EnumRecord &Record); - TypeIndex writeBitField(const BitFieldRecord &Record); - TypeIndex writeVFTableShape(const VFTableShapeRecord &Record); - TypeIndex writeStringId(const StringIdRecord &Record); - TypeIndex writeVFTable(const VFTableRecord &Record); - TypeIndex writeUdtSourceLine(const UdtSourceLineRecord &Record); - TypeIndex writeUdtModSourceLine(const UdtModSourceLineRecord &Record); - TypeIndex writeFuncId(const FuncIdRecord &Record); - TypeIndex writeMemberFuncId(const MemberFuncIdRecord &Record); - TypeIndex writeBuildInfo(const BuildInfoRecord &Record); - TypeIndex writeMethodOverloadList(const MethodOverloadListRecord &Record); - TypeIndex writeTypeServer2(const TypeServer2Record &Record); - - TypeIndex writeFieldList(FieldListRecordBuilder &FieldList); - - TypeIndex writeRecord(TypeRecordBuilder &builder); - - virtual TypeIndex writeRecord(llvm::StringRef record) = 0; + explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable) + : TypeTable(TypeTable), TempSerializer(TypeTable.getAllocator()) { + Type.Type = TypeLeafKind::LF_FIELDLIST; + } + + void begin() { + if (auto EC = TempSerializer.visitTypeBegin(Type)) + consumeError(std::move(EC)); + } + + template <typename T> void writeMemberType(T &Record) { + CVMemberRecord CVMR; + CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind()); + if (auto EC = TempSerializer.visitMemberBegin(CVMR)) + consumeError(std::move(EC)); + if (auto EC = TempSerializer.visitKnownMember(CVMR, Record)) + consumeError(std::move(EC)); + if (auto EC = TempSerializer.visitMemberEnd(CVMR)) + consumeError(std::move(EC)); + } + + TypeIndex end() { + if (auto EC = TempSerializer.visitTypeEnd(Type)) { + consumeError(std::move(EC)); + return TypeIndex(); + } + + TypeIndex Index; + for (auto Record : TempSerializer.records()) { + Index = TypeTable.writeSerializedRecord(Record); + } + return Index; + } }; -} -} -#endif +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h new file mode 100644 index 0000000..f251296 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h @@ -0,0 +1,114 @@ +//===- TypeVisitorCallbackPipeline.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_TYPEVISITORCALLBACKPIPELINE_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKPIPELINE_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/Error.h" +#include <vector> + +namespace llvm { +namespace codeview { + +class TypeVisitorCallbackPipeline : public TypeVisitorCallbacks { +public: + TypeVisitorCallbackPipeline() = default; + + Error visitUnknownType(CVRecord<TypeLeafKind> &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitUnknownType(Record)) + return EC; + } + return Error::success(); + } + + Error visitUnknownMember(CVMemberRecord &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitUnknownMember(Record)) + return EC; + } + return Error::success(); + } + + Error visitTypeBegin(CVType &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitTypeBegin(Record)) + return EC; + } + return Error::success(); + } + + Error visitTypeEnd(CVType &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitTypeEnd(Record)) + return EC; + } + return Error::success(); + } + + Error visitMemberBegin(CVMemberRecord &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitMemberBegin(Record)) + return EC; + } + return Error::success(); + } + + Error visitMemberEnd(CVMemberRecord &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitMemberEnd(Record)) + return EC; + } + return Error::success(); + } + + void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks) { + Pipeline.push_back(&Callbacks); + } + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \ + return visitKnownRecordImpl(CVR, Record); \ + } +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownMember(CVMemberRecord &CVMR, Name##Record &Record) \ + override { \ + return visitKnownMemberImpl(CVMR, Record); \ + } +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/TypeRecords.def" + +private: + template <typename T> Error visitKnownRecordImpl(CVType &CVR, T &Record) { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitKnownRecord(CVR, Record)) + return EC; + } + return Error::success(); + } + + template <typename T> + Error visitKnownMemberImpl(CVMemberRecord &CVMR, T &Record) { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitKnownMember(CVMR, Record)) + return EC; + } + return Error::success(); + } + std::vector<TypeVisitorCallbacks *> Pipeline; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKPIPELINE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h index 310847e..5e27df3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h @@ -10,54 +10,53 @@ #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/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/Support/Error.h" namespace llvm { namespace codeview { + class TypeVisitorCallbacks { friend class CVTypeVisitor; public: - virtual ~TypeVisitorCallbacks() {} + virtual ~TypeVisitorCallbacks() = default; /// 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(); - } - + virtual Error visitUnknownType(CVType &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) { + /// including the fixed-length record prefix. visitTypeBegin() should return + /// the type of the Record, or an error if it cannot be determined. + virtual Error visitTypeBegin(CVType &Record) { return Error::success(); } + virtual Error visitTypeEnd(CVType &Record) { return Error::success(); } + + virtual Error visitUnknownMember(CVMemberRecord &Record) { return Error::success(); } - virtual Error visitFieldListBegin(const CVRecord<TypeLeafKind> &Record) { + virtual Error visitMemberBegin(CVMemberRecord &Record) { return Error::success(); } - virtual Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) { + virtual Error visitMemberEnd(CVMemberRecord &Record) { return Error::success(); } #define TYPE_RECORD(EnumName, EnumVal, Name) \ - virtual Error visit##Name(Name##Record &Record) { return Error::success(); } + virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) { \ + return Error::success(); \ + } #define MEMBER_RECORD(EnumName, EnumVal, Name) \ - TYPE_RECORD(EnumName, EnumVal, Name) + virtual Error visitKnownMember(CVMemberRecord &CVM, Name##Record &Record) { \ + return Error::success(); \ + } + #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "TypeRecords.def" }; -} -} -#endif +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H |