diff options
Diffstat (limited to 'contrib/llvm/include/llvm/DebugInfo')
104 files changed, 4611 insertions, 2944 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/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/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 diff --git a/contrib/llvm/include/llvm/DebugInfo/DIContext.h b/contrib/llvm/include/llvm/DebugInfo/DIContext.h index 2f88371..804419c5 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DIContext.h +++ b/contrib/llvm/include/llvm/DebugInfo/DIContext.h @@ -17,9 +17,12 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/DataTypes.h" +#include <cassert> +#include <cstdint> +#include <memory> #include <string> +#include <tuple> +#include <utility> namespace llvm { @@ -32,8 +35,12 @@ struct DILineInfo { uint32_t Line; uint32_t Column; + // DWARF-specific. + uint32_t Discriminator; + DILineInfo() - : FileName("<invalid>"), FunctionName("<invalid>"), Line(0), Column(0) {} + : FileName("<invalid>"), FunctionName("<invalid>"), Line(0), Column(0), + Discriminator(0) {} bool operator==(const DILineInfo &RHS) const { return Line == RHS.Line && Column == RHS.Column && @@ -42,6 +49,10 @@ struct DILineInfo { bool operator!=(const DILineInfo &RHS) const { return !(*this == RHS); } + bool operator<(const DILineInfo &RHS) const { + return std::tie(FileName, FunctionName, Line, Column) < + std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column); + } }; typedef SmallVector<std::pair<uint64_t, DILineInfo>, 16> DILineInfoTable; @@ -49,19 +60,24 @@ typedef SmallVector<std::pair<uint64_t, DILineInfo>, 16> DILineInfoTable; /// DIInliningInfo - a format-neutral container for inlined code description. class DIInliningInfo { SmallVector<DILineInfo, 4> Frames; - public: - DIInliningInfo() {} + +public: + DIInliningInfo() = default; + DILineInfo getFrame(unsigned Index) const { assert(Index < Frames.size()); return Frames[Index]; } + DILineInfo *getMutableFrame(unsigned Index) { assert(Index < Frames.size()); return &Frames[Index]; } + uint32_t getNumberOfFrames() const { return Frames.size(); } + void addFrame(const DILineInfo &Frame) { Frames.push_back(Frame); } @@ -124,6 +140,7 @@ enum DIDumpType { DIDT_AppleNamespaces, DIDT_AppleObjC, DIDT_CUIndex, + DIDT_GdbIndex, DIDT_TUIndex, }; @@ -133,13 +150,14 @@ public: CK_DWARF, CK_PDB }; - DIContextKind getKind() const { return Kind; } DIContext(DIContextKind K) : Kind(K) {} - virtual ~DIContext() {} + virtual ~DIContext() = default; + + DIContextKind getKind() const { return Kind; } virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All, - bool DumpEH = false) = 0; + bool DumpEH = false, bool SummarizeTypes = false) = 0; virtual DILineInfo getLineInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; @@ -147,6 +165,7 @@ public: uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + private: const DIContextKind Kind; }; @@ -192,6 +211,6 @@ public: virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0; }; -} +} // end namespace llvm -#endif +#endif // LLVM_DEBUGINFO_DICONTEXT_H diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h index 6ab5d5c..db9bd50 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -10,26 +10,52 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H #define LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataExtractor.h" - +#include "llvm/Support/Dwarf.h" namespace llvm { +class DWARFUnit; +class DWARFFormValue; class raw_ostream; class DWARFAbbreviationDeclaration { public: struct AttributeSpec { - AttributeSpec(uint16_t Attr, uint16_t Form) : Attr(Attr), Form(Form) {} - uint16_t Attr; - uint16_t Form; + AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<int64_t> V) + : Attr(A), Form(F), ByteSizeOrValue(V) {} + dwarf::Attribute Attr; + dwarf::Form Form; + /// The following field is used for ByteSize for non-implicit_const + /// attributes and as value for implicit_const ones, indicated by + /// Form == DW_FORM_implicit_const. + /// The following cases are distinguished: + /// * Form != DW_FORM_implicit_const and ByteSizeOrValue has a value: + /// ByteSizeOrValue contains the fixed size in bytes + /// for the Form in this object. + /// * Form != DW_FORM_implicit_const and ByteSizeOrValue is None: + /// byte size of Form either varies according to the DWARFUnit + /// that it is contained in or the value size varies and must be + /// decoded from the debug information in order to determine its size. + /// * Form == DW_FORM_implicit_const: + /// ByteSizeOrValue contains value for the implicit_const attribute. + Optional<int64_t> ByteSizeOrValue; + bool isImplicitConst() const { + return Form == dwarf::DW_FORM_implicit_const; + } + /// Get the fixed byte size of this Form if possible. This function might + /// use the DWARFUnit to calculate the size of the Form, like for + /// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for + /// the ByteSize member. + Optional<int64_t> getByteSize(const DWARFUnit &U) const; }; typedef SmallVector<AttributeSpec, 8> AttributeSpecVector; DWARFAbbreviationDeclaration(); uint32_t getCode() const { return Code; } - uint32_t getTag() const { return Tag; } + dwarf::Tag getTag() const { return Tag; } bool hasChildren() const { return HasChildren; } typedef iterator_range<AttributeSpecVector::const_iterator> @@ -39,22 +65,77 @@ public: return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); } - uint16_t getFormByIndex(uint32_t idx) const { - return idx < AttributeSpecs.size() ? AttributeSpecs[idx].Form : 0; + dwarf::Form getFormByIndex(uint32_t idx) const { + if (idx < AttributeSpecs.size()) + return AttributeSpecs[idx].Form; + return dwarf::Form(0); } - uint32_t findAttributeIndex(uint16_t attr) const; + /// Get the index of the specified attribute. + /// + /// Searches the this abbreviation declaration for the index of the specified + /// attribute. + /// + /// \param attr DWARF attribute to search for. + /// \returns Optional index of the attribute if found, None otherwise. + Optional<uint32_t> findAttributeIndex(dwarf::Attribute attr) const; + + /// Extract a DWARF form value from a DIE specified by DIE offset. + /// + /// Extract an attribute value for a DWARFUnit given the DIE offset and the + /// attribute. + /// + /// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation + /// code in the .debug_info data. + /// \param Attr DWARF attribute to search for. + /// \param U the DWARFUnit the contains the DIE. + /// \returns Optional DWARF form value if the attribute was extracted. + Optional<DWARFFormValue> getAttributeValue(const uint32_t DIEOffset, + const dwarf::Attribute Attr, + const DWARFUnit &U) const; + bool extract(DataExtractor Data, uint32_t* OffsetPtr); void dump(raw_ostream &OS) const; + // Return an optional byte size of all attribute data in this abbreviation + // if a constant byte size can be calculated given a DWARFUnit. This allows + // DWARF parsing to be faster as many DWARF DIEs have a fixed byte size. + Optional<size_t> getFixedAttributesByteSize(const DWARFUnit &U) const; + private: void clear(); + /// A helper structure that can quickly determine the size in bytes of an + /// abbreviation declaration. + struct FixedSizeInfo { + /// The fixed byte size for fixed size forms. + uint16_t NumBytes; + /// Number of DW_FORM_address forms in this abbrevation declaration. + uint8_t NumAddrs; + /// Number of DW_FORM_ref_addr forms in this abbrevation declaration. + uint8_t NumRefAddrs; + /// Number of 4 byte in DWARF32 and 8 byte in DWARF64 forms. + uint8_t NumDwarfOffsets; + /// Constructor + FixedSizeInfo() + : NumBytes(0), NumAddrs(0), NumRefAddrs(0), NumDwarfOffsets(0) {} + /// Calculate the fixed size in bytes given a DWARFUnit. + /// + /// \param U the DWARFUnit to use when determing the byte size. + /// \returns the size in bytes for all attribute data in this abbreviation. + /// The returned size does not include bytes for the ULEB128 abbreviation + /// code + size_t getByteSize(const DWARFUnit &U) const; + }; + uint32_t Code; - uint32_t Tag; + dwarf::Tag Tag; + uint8_t CodeByteSize; bool HasChildren; - AttributeSpecVector AttributeSpecs; + /// If this abbreviation has a fixed byte size then FixedAttributeSize member + /// variable below will have a value. + Optional<FixedSizeInfo> FixedAttributeSize; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h index 47dbf5f..6334372 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/Support/Dwarf.h" #include <cstdint> namespace llvm { @@ -30,7 +31,7 @@ class DWARFAcceleratorTable { struct HeaderData { typedef uint16_t AtomType; - typedef uint16_t Form; + typedef dwarf::Form Form; uint32_t DIEOffsetBase; SmallVector<std::pair<AtomType, Form>, 3> Atoms; }; diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h index 741a31c..ef310e7 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -10,18 +10,31 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H #define LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" +#include "llvm/Object/ObjectFile.h" +#include <cstdint> +#include <deque> +#include <map> +#include <memory> +#include <utility> namespace llvm { @@ -30,17 +43,17 @@ namespace llvm { // dwarf where we expect relocated values. This adds a bit of complexity to the // dwarf parsing/extraction at the benefit of not allocating memory for the // entire size of the debug info sections. -typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap; +typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t>> RelocAddrMap; /// DWARFContext /// This data structure is the top level entity that deals with dwarf debug /// information parsing. The actual data is supplied through pure virtual /// methods that a concrete implementation provides. class DWARFContext : public DIContext { - DWARFUnitSection<DWARFCompileUnit> CUs; std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs; std::unique_ptr<DWARFUnitIndex> CUIndex; + std::unique_ptr<DWARFGdbIndex> GdbIndex; std::unique_ptr<DWARFUnitIndex> TUIndex; std::unique_ptr<DWARFDebugAbbrev> Abbrev; std::unique_ptr<DWARFDebugLoc> Loc; @@ -55,9 +68,6 @@ class DWARFContext : public DIContext { std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; std::unique_ptr<DWARFDebugLocDWO> LocDWO; - DWARFContext(DWARFContext &) = delete; - DWARFContext &operator=(DWARFContext &) = delete; - /// Read compile units from the debug_info section (if necessary) /// and store them in CUs. void parseCompileUnits(); @@ -76,13 +86,15 @@ class DWARFContext : public DIContext { public: DWARFContext() : DIContext(CK_DWARF) {} + DWARFContext(DWARFContext &) = delete; + DWARFContext &operator=(DWARFContext &) = delete; static bool classof(const DIContext *DICtx) { return DICtx->getKind() == CK_DWARF; } void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All, - bool DumpEH = false) override; + bool DumpEH = false, bool SummarizeTypes = false) override; typedef DWARFUnitSection<DWARFCompileUnit>::iterator_range cu_iterator_range; typedef DWARFUnitSection<DWARFTypeUnit>::iterator_range tu_iterator_range; @@ -149,6 +161,7 @@ public: } const DWARFUnitIndex &getCUIndex(); + DWARFGdbIndex &getGdbIndex(); const DWARFUnitIndex &getTUIndex(); /// Get a pointer to the parsed DebugAbbrev object. @@ -220,11 +233,13 @@ public: virtual const DWARFSection& getAppleNamespacesSection() = 0; virtual const DWARFSection& getAppleObjCSection() = 0; virtual StringRef getCUIndexSection() = 0; + virtual StringRef getGdbIndexSection() = 0; virtual StringRef getTUIndexSection() = 0; static bool isSupportedVersion(unsigned version) { return version == 2 || version == 3 || version == 4 || version == 5; } + private: /// Return the compile unit that includes an offset (relative to .debug_info). DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); @@ -239,6 +254,7 @@ private: /// pointers to it. class DWARFContextInMemory : public DWARFContext { virtual void anchor(); + bool IsLittleEndian; uint8_t AddressSize; DWARFSection InfoSection; @@ -272,6 +288,7 @@ class DWARFContextInMemory : public DWARFContext { DWARFSection AppleNamespacesSection; DWARFSection AppleObjCSection; StringRef CUIndexSection; + StringRef GdbIndexSection; StringRef TUIndexSection; SmallVector<SmallString<32>, 4> UncompressedSections; @@ -279,6 +296,7 @@ class DWARFContextInMemory : public DWARFContext { public: DWARFContextInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr); + bool isLittleEndian() const override { return IsLittleEndian; } uint8_t getAddressSize() const override { return AddressSize; } const DWARFSection &getInfoSection() override { return InfoSection; } @@ -318,9 +336,10 @@ public: return AddrSection; } StringRef getCUIndexSection() override { return CUIndexSection; } + StringRef getGdbIndexSection() override { return GdbIndexSection; } StringRef getTUIndexSection() override { return TUIndexSection; } }; -} +} // end namespace llvm -#endif +#endif // LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h index 67c4a2b..f732dee 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -23,6 +23,9 @@ class DWARFAbbreviationDeclarationSet { uint32_t FirstAbbrCode; std::vector<DWARFAbbreviationDeclaration> Decls; + typedef std::vector<DWARFAbbreviationDeclaration>::const_iterator + const_iterator; + public: DWARFAbbreviationDeclarationSet(); @@ -33,6 +36,14 @@ public: const DWARFAbbreviationDeclaration * getAbbreviationDeclaration(uint32_t AbbrCode) const; + const_iterator begin() const { + return Decls.begin(); + } + + const_iterator end() const { + return Decls.end(); + } + private: void clear(); }; @@ -53,6 +64,14 @@ public: void dump(raw_ostream &OS) const; void extract(DataExtractor Data); + DWARFAbbreviationDeclarationSetMap::const_iterator begin() const { + return AbbrDeclSets.begin(); + } + + DWARFAbbreviationDeclarationSetMap::const_iterator end() const { + return AbbrDeclSets.end(); + } + private: void clear(); }; diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h index 837a8e6..5a60239 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h @@ -59,6 +59,8 @@ public: uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } + const Header &getHeader() const { return HeaderData; } + desc_iterator_range descriptors() const { return desc_iterator_range(ArangeDescriptors.begin(), ArangeDescriptors.end()); diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h index f29d5fe..f36f470 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -15,6 +15,7 @@ #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Dwarf.h" namespace llvm { @@ -25,134 +26,39 @@ class DWARFContext; class DWARFFormValue; struct DWARFDebugInfoEntryInlinedChain; -/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data. -class DWARFDebugInfoEntryMinimal { +/// DWARFDebugInfoEntry - A DIE with only the minimum required data. +class DWARFDebugInfoEntry { /// Offset within the .debug_info of the start of this entry. uint32_t Offset; - /// How many to add to "this" to get the sibling. - uint32_t SiblingIdx; + /// The integer depth of this DIE within the compile unit DIEs where the + /// compile/type unit DIE has a depth of zero. + uint32_t Depth; const DWARFAbbreviationDeclaration *AbbrevDecl; public: - DWARFDebugInfoEntryMinimal() - : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} - - void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, - unsigned indent = 0) const; - void dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr, - uint16_t attr, uint16_t form, unsigned indent = 0) const; + DWARFDebugInfoEntry() + : Offset(0), Depth(0), AbbrevDecl(nullptr) {} /// Extracts a debug info entry, which is a child of a given unit, /// starting at a given offset. If DIE can't be extracted, returns false and /// doesn't change OffsetPtr. - bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr); - - uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; } - bool isNULL() const { return AbbrevDecl == nullptr; } - - /// Returns true if DIE represents a subprogram (not inlined). - bool isSubprogramDIE() const; - /// Returns true if DIE represents a subprogram or an inlined - /// subroutine. - bool isSubroutineDIE() const; + bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr); + /// High performance extraction should use this call. + bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr, + const DataExtractor &DebugInfoData, + uint32_t UEndOffset, + uint32_t Depth); uint32_t getOffset() const { return Offset; } - bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } - - // We know we are kept in a vector of contiguous entries, so we know - // our sibling will be some index after "this". - const DWARFDebugInfoEntryMinimal *getSibling() const { - return SiblingIdx > 0 ? this + SiblingIdx : nullptr; + uint32_t getDepth() const { return Depth; } + dwarf::Tag getTag() const { + return AbbrevDecl ? AbbrevDecl->getTag() : dwarf::DW_TAG_null; } - - // We know we are kept in a vector of contiguous entries, so we know - // we don't need to store our child pointer, if we have a child it will - // be the next entry in the list... - const DWARFDebugInfoEntryMinimal *getFirstChild() const { - return hasChildren() ? this + 1 : nullptr; - } - - void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) { - if (Sibling) { - // We know we are kept in a vector of contiguous entries, so we know - // our sibling will be some index after "this". - SiblingIdx = Sibling - this; - } else - SiblingIdx = 0; - } - + bool hasChildren() const { return AbbrevDecl && AbbrevDecl->hasChildren(); } const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { return AbbrevDecl; } - - bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr, - DWARFFormValue &FormValue) const; - - const char *getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr, - const char *FailValue) const; - - uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr, - uint64_t FailValue) const; - - uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U, - const uint16_t Attr, - uint64_t FailValue) const; - - uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr, - uint64_t FailValue) const; - - uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U, - const uint16_t Attr, - uint64_t FailValue) const; - - uint64_t getRangesBaseAttribute(const DWARFUnit *U, uint64_t FailValue) const; - - /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. - /// Returns true if both attributes are present. - bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, - uint64_t &HighPC) const; - - DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const; - - void collectChildrenAddressRanges(const DWARFUnit *U, - DWARFAddressRangesVector &Ranges) const; - - bool addressRangeContainsAddress(const DWARFUnit *U, - const uint64_t Address) const; - - /// If a DIE represents a subprogram (or inlined subroutine), - /// returns its mangled name (or short name, if mangled is missing). - /// This name may be fetched from specification or abstract origin - /// for this subprogram. Returns null if no name is found. - const char *getSubroutineName(const DWARFUnit *U, DINameKind Kind) const; - - /// Return the DIE name resolving DW_AT_sepcification or - /// DW_AT_abstract_origin references if necessary. - /// Returns null if no name is found. - const char *getName(const DWARFUnit *U, DINameKind Kind) const; - - /// Retrieves values of DW_AT_call_file, DW_AT_call_line and - /// DW_AT_call_column from DIE (or zeroes if they are missing). - void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile, - uint32_t &CallLine, uint32_t &CallColumn) const; - - /// Get inlined chain for a given address, rooted at the current DIE. - /// Returns empty chain if address is not contained in address range - /// of current DIE. - DWARFDebugInfoEntryInlinedChain - getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const; -}; - -/// DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine -/// DIEs, (possibly ending with subprogram DIE), all of which are contained -/// in some concrete inlined instance tree. Address range for each DIE -/// (except the last DIE) in this chain is contained in address -/// range for next DIE in the chain. -struct DWARFDebugInfoEntryInlinedChain { - DWARFDebugInfoEntryInlinedChain() : U(nullptr) {} - SmallVector<DWARFDebugInfoEntryMinimal, 4> DIEs; - const DWARFUnit *U; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index 760950b..878f1c7 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -116,12 +116,12 @@ public: // An unsigned integer indicating the identity of the source file // corresponding to a machine instruction. uint16_t File; - // An unsigned integer whose value encodes the applicable instruction set - // architecture for the current instruction. - uint8_t Isa; // An unsigned integer representing the DWARF path discriminator value // for this location. uint32_t Discriminator; + // An unsigned integer whose value encodes the applicable instruction set + // architecture for the current instruction. + uint8_t Isa; // A boolean indicating that the current instruction is the beginning of a // statement. uint8_t IsStmt:1, @@ -188,6 +188,8 @@ public: bool lookupAddressRange(uint64_t address, uint64_t size, std::vector<uint32_t> &result) const; + bool hasFileAtIndex(uint64_t FileIndex) const; + // Extracts filename by its index in filename table in prologue. // Returns true on success. bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h index d13c7f5..5a0352d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h @@ -12,7 +12,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataExtractor.h" -#include "llvm/Support/Dwarf.h" +#include <cstdint> namespace llvm { @@ -46,13 +46,14 @@ class DWARFDebugMacro { MacroList Macros; public: - DWARFDebugMacro() {} + DWARFDebugMacro() = default; + /// Print the macro list found within the debug_macinfo section. void dump(raw_ostream &OS) const; /// Parse the debug_macinfo section accessible via the 'data' parameter. void parse(DataExtractor data); }; -} +} // end namespace llvm -#endif +#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h new file mode 100644 index 0000000..2b23837 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h @@ -0,0 +1,77 @@ +//===-- DWARFDebugPubTable.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_LIB_DEBUGINFO_DWARFDEBUGPUBTABLE_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGPUBTABLE_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Dwarf.h" +#include <vector> + +namespace llvm { + +class raw_ostream; + +/// Represents structure for holding and parsing .debug_pub* tables. +class DWARFDebugPubTable { +public: + struct Entry { + /// Section offset from the beginning of the compilation unit. + uint32_t SecOffset; + + /// An entry of the various gnu_pub* debug sections. + llvm::dwarf::PubIndexEntryDescriptor Descriptor; + + /// The name of the object as given by the DW_AT_name attribute of the + /// referenced DIE. + const char *Name; + }; + + /// Each table consists of sets of variable length entries. Each set describes + /// the names of global objects and functions, or global types, respectively, + /// whose definitions are represented by debugging information entries owned + /// by a single compilation unit. + struct Set { + /// The total length of the entries for that set, not including the length + /// field itself. + uint32_t Length; + + /// This number is specific to the name lookup table and is independent of + /// the DWARF version number. + uint16_t Version; + + /// The offset from the beginning of the .debug_info section of the + /// compilation unit header referenced by the set. + uint32_t Offset; + + /// The size in bytes of the contents of the .debug_info section generated + /// to represent that compilation unit. + uint32_t Size; + + std::vector<Entry> Entries; + }; + +private: + std::vector<Set> Sets; + + /// gnu styled tables contains additional information. + /// This flag determines whether or not section we parse is debug_gnu* table. + bool GnuStyle; + +public: + DWARFDebugPubTable(StringRef Data, bool LittleEndian, bool GnuStyle); + void dump(StringRef Name, raw_ostream &OS) const; + + ArrayRef<Set> getData() { return Sets; } +}; +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h new file mode 100644 index 0000000..e335e28 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -0,0 +1,347 @@ +//===-- DWARFDie.h --------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDIE_H +#define LLVM_LIB_DEBUGINFO_DWARFDIE_H + +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" + +namespace llvm { + +class DWARFUnit; +class DWARFDebugInfoEntry; +class raw_ostream; + +//===----------------------------------------------------------------------===// +/// Utility class that carries the DWARF compile/type unit and the debug info +/// entry in an object. +/// +/// When accessing information from a debug info entry we always need to DWARF +/// compile/type unit in order to extract the info correctly as some information +/// is relative to the compile/type unit. Prior to this class the DWARFUnit and +/// the DWARFDebugInfoEntry was passed around separately and there was the +/// possibility for error if the wrong DWARFUnit was used to extract a unit +/// relative offset. This class helps to ensure that this doesn't happen and +/// also simplifies the attribute extraction calls by not having to specify the +/// DWARFUnit for each call. +class DWARFDie { + DWARFUnit *U; + const DWARFDebugInfoEntry *Die; +public: + DWARFDie() : U(nullptr), Die(nullptr) {} + DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry * D) : U(Unit), Die(D) {} + + bool isValid() const { return U && Die; } + explicit operator bool() const { return isValid(); } + const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; } + DWARFUnit *getDwarfUnit() const { return U; } + + + /// Get the abbreviation declaration for this DIE. + /// + /// \returns the abbreviation declaration or NULL for null tags. + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { + assert(isValid() && "must check validity prior to calling"); + return Die->getAbbreviationDeclarationPtr(); + } + + /// Get the absolute offset into the debug info or types section. + /// + /// \returns the DIE offset or -1U if invalid. + uint32_t getOffset() const { + assert(isValid() && "must check validity prior to calling"); + return Die->getOffset(); + } + + dwarf::Tag getTag() const { + auto AbbrevDecl = getAbbreviationDeclarationPtr(); + if (AbbrevDecl) + return AbbrevDecl->getTag(); + return dwarf::DW_TAG_null; + } + + bool hasChildren() const { + assert(isValid() && "must check validity prior to calling"); + return Die->hasChildren(); + } + + /// Returns true for a valid DIE that terminates a sibling chain. + bool isNULL() const { + return getAbbreviationDeclarationPtr() == nullptr; + } + /// Returns true if DIE represents a subprogram (not inlined). + bool isSubprogramDIE() const; + + /// Returns true if DIE represents a subprogram or an inlined subroutine. + bool isSubroutineDIE() const; + + /// Get the parent of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has a parent or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getParent() const; + + /// Get the sibling of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has a sibling or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getSibling() const; + + /// Get the first child of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has children or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getFirstChild() const { + if (isValid() && Die->hasChildren()) + return DWARFDie(U, Die + 1); + return DWARFDie(); + } + + /// Dump the DIE and all of its attributes to the supplied stream. + /// + /// \param OS the stream to use for output. + /// \param recurseDepth the depth to recurse to when dumping this DIE and its + /// children. + /// \param indent the number of characters to indent each line that is output. + void dump(raw_ostream &OS, unsigned recurseDepth, unsigned indent = 0) const; + + /// Extract the specified attribute from this DIE. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns an optional DWARFFormValue that will have the form value if the + /// attribute was successfully extracted. + Optional<DWARFFormValue> getAttributeValue(dwarf::Attribute Attr) const; + + /// Extract the specified attribute from this DIE as a C string. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \param FailValue the value to return if this DIE doesn't have this + /// attribute. + /// \returns the NULL terminated C string value owned by the DWARF section + /// that contains the string or FailValue if the attribute doesn't exist or + /// if the attribute's form isn't a form that describes an string. + const char *getAttributeValueAsString(dwarf::Attribute Attr, + const char *FailValue) const; + + /// Extract the specified attribute from this DIE as an address. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns an optional value for the attribute. + Optional<uint64_t> getAttributeValueAsAddress(dwarf::Attribute Attr) const; + + /// Extract the specified attribute from this DIE as a signed integer. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns an optional value for the attribute. + Optional<int64_t> + getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const; + + /// Extract the specified attribute from this DIE as an unsigned integer. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns an optional value for the attribute. + Optional<uint64_t> + getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const; + + /// Extract the specified attribute from this DIE as absolute DIE Offset. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns an optional value for the attribute. + Optional<uint64_t> getAttributeValueAsReference(dwarf::Attribute Attr) const; + + /// Extract the specified attribute from this DIE as absolute section offset. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns an optional value for the attribute. + Optional<uint64_t> + getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const; + + /// Extract the specified attribute from this DIE as the referenced DIE. + /// + /// Regardless of the reference type, return the correct DWARFDie instance if + /// the attribute exists. The returned DWARFDie object might be from another + /// DWARFUnit, but that is all encapsulated in the new DWARFDie object. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns a valid DWARFDie instance if the attribute exists, or an invalid + /// DWARFDie object if it doesn't. + DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const; + + /// Extract the range base attribute from this DIE as absolute section offset. + /// + /// This is a utility function that checks for either the DW_AT_rnglists_base + /// or DW_AT_GNU_ranges_base attribute. + /// + /// \returns anm optional absolute section offset value for the attribute. + Optional<uint64_t> getRangesBaseAttribute() const; + + /// Get the DW_AT_high_pc attribute value as an address. + /// + /// In DWARF version 4 and later the high PC can be encoded as an offset from + /// the DW_AT_low_pc. This function takes care of extracting the value as an + /// address or offset and adds it to the low PC if needed and returns the + /// value as an optional in case the DIE doesn't have a DW_AT_high_pc + /// attribute. + /// + /// \param LowPC the low PC that might be needed to calculate the high PC. + /// \returns an optional address value for the attribute. + Optional<uint64_t> getHighPC(uint64_t LowPC) const; + + /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. + /// Returns true if both attributes are present. + bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const; + + /// Get the address ranges for this DIE. + /// + /// Get the hi/low PC range if both attributes are available or exrtracts the + /// non-contiguous address ranges from the DW_AT_ranges attribute. + /// + /// Extracts the range information from this DIE only. This call doesn't look + /// for the range in any DW_AT_specification or DW_AT_abstract_origin DIEs. + /// + /// \returns a address range vector that might be empty if no address range + /// information is available. + DWARFAddressRangesVector getAddressRanges() const; + + /// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any + /// of its children. + /// + /// Get the hi/low PC range if both attributes are available or exrtracts the + /// non-contiguous address ranges from the DW_AT_ranges attribute for this DIE + /// and all children. + /// + /// \param Ranges the addres range vector to fill in. + void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const; + + bool addressRangeContainsAddress(const uint64_t Address) const; + + /// If a DIE represents a subprogram (or inlined subroutine), returns its + /// mangled name (or short name, if mangled is missing). This name may be + /// fetched from specification or abstract origin for this subprogram. + /// Returns null if no name is found. + const char *getSubroutineName(DINameKind Kind) const; + + /// Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin + /// references if necessary. Returns null if no name is found. + const char *getName(DINameKind Kind) const; + + /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column + /// from DIE (or zeroes if they are missing). This function looks for + /// DW_AT_call attributes in this DIE only, it will not resolve the attribute + /// values in any DW_AT_specification or DW_AT_abstract_origin DIEs. + /// \param CallFile filled in with non-zero if successful, zero if there is no + /// DW_AT_call_file attribute in this DIE. + /// \param CallLine filled in with non-zero if successful, zero if there is no + /// DW_AT_call_line attribute in this DIE. + /// \param CallColumn filled in with non-zero if successful, zero if there is + /// no DW_AT_call_column attribute in this DIE. + void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, + uint32_t &CallColumn) const; + + /// Get inlined chain for a given address, rooted at the current DIE. + /// Returns empty chain if address is not contained in address range + /// of current DIE. + void + getInlinedChainForAddress(const uint64_t Address, + SmallVectorImpl<DWARFDie> &InlinedChain) const; + + class iterator; + + iterator begin() const; + iterator end() const; + iterator_range<iterator> children() const; +}; + + +inline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) { + return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() && + LHS.getDwarfUnit() == RHS.getDwarfUnit(); +} + +inline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) { + return !(LHS == RHS); +} + +class DWARFDie::iterator : public iterator_facade_base<iterator, + std::forward_iterator_tag, + const DWARFDie> { + DWARFDie Die; + void skipNull() { + if (Die && Die.isNULL()) + Die = DWARFDie(); + } +public: + iterator() = default; + explicit iterator(DWARFDie D) : Die(D) { + // If we start out with only a Null DIE then invalidate. + skipNull(); + } + iterator &operator++() { + Die = Die.getSibling(); + // Don't include the NULL die when iterating. + skipNull(); + return *this; + } + explicit operator bool() const { return Die.isValid(); } + const DWARFDie &operator*() const { return Die; } + bool operator==(const iterator &X) const { return Die == X.Die; } +}; + +// These inline functions must follow the DWARFDie::iterator definition above +// as they use functions from that class. +inline DWARFDie::iterator DWARFDie::begin() const { + return iterator(getFirstChild()); +} + +inline DWARFDie::iterator DWARFDie::end() const { + return iterator(); +} + +inline iterator_range<DWARFDie::iterator> DWARFDie::children() const { + return make_range(begin(), end()); +} + +} // end namespace llvm + +#endif // LLVM_LIB_DEBUGINFO_DWARFDIE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index b2f750d..1b7659d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -12,6 +12,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Dwarf.h" namespace llvm { @@ -48,15 +49,20 @@ private: const uint8_t* data; }; - uint16_t Form; // Form for this value. + dwarf::Form Form; // Form for this value. ValueType Value; // Contains all data for the form. + const DWARFUnit *U; // Remember the DWARFUnit at extract time. public: - DWARFFormValue(uint16_t Form = 0) : Form(Form) {} - uint16_t getForm() const { return Form; } + DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F), U(nullptr) {} + dwarf::Form getForm() const { return Form; } + void setForm(dwarf::Form F) { Form = F; } + void setUValue(uint64_t V) { Value.uval = V; } + void setSValue(int64_t V) { Value.sval = V; } + void setPValue(const char *V) { Value.cstr = V; } bool isFormClass(FormClass FC) const; - - void dump(raw_ostream &OS, const DWARFUnit *U) const; + const DWARFUnit *getUnit() const { return U; } + void dump(raw_ostream &OS) const; /// \brief extracts a value in data at offset *offset_ptr. /// @@ -64,34 +70,98 @@ public: /// case no relocation processing will be performed and some /// kind of forms that depend on Unit information are disallowed. /// \returns whether the extraction succeeded. - bool extractValue(DataExtractor data, uint32_t *offset_ptr, - const DWARFUnit *u); + bool extractValue(const DataExtractor &Data, uint32_t *OffsetPtr, + const DWARFUnit *U); bool isInlinedCStr() const { return Value.data != nullptr && Value.data == (const uint8_t*)Value.cstr; } /// getAsFoo functions below return the extracted value as Foo if only /// DWARFFormValue has form class is suitable for representing Foo. - Optional<uint64_t> getAsReference(const DWARFUnit *U) const; + Optional<uint64_t> getAsReference() const; Optional<uint64_t> getAsUnsignedConstant() const; Optional<int64_t> getAsSignedConstant() const; - Optional<const char *> getAsCString(const DWARFUnit *U) const; - Optional<uint64_t> getAsAddress(const DWARFUnit *U) const; + Optional<const char *> getAsCString() const; + Optional<uint64_t> getAsAddress() const; Optional<uint64_t> getAsSectionOffset() const; Optional<ArrayRef<uint8_t>> getAsBlock() const; - + Optional<uint64_t> getAsCStringOffset() const; + Optional<uint64_t> getAsReferenceUVal() const; + /// Get the fixed byte size for a given form. + /// + /// If the form always has a fixed valid byte size that doesn't depend on a + /// DWARFUnit, then an Optional with a value will be returned. If the form + /// can vary in size depending on the DWARFUnit (DWARF version, address byte + /// size, or DWARF 32/64) and the DWARFUnit is valid, then an Optional with a + /// valid value is returned. If the form is always encoded using a variable + /// length storage format (ULEB or SLEB numbers or blocks) or the size + /// depends on a DWARFUnit and the DWARFUnit is NULL, then None will be + /// returned. + /// \param Form The DWARF form to get the fixed byte size for + /// \param U The DWARFUnit that can be used to help determine the byte size. + /// + /// \returns Optional<uint8_t> value with the fixed byte size or None if + /// \p Form doesn't have a fixed byte size or a DWARFUnit wasn't supplied + /// and was needed to calculate the byte size. + static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, + const DWARFUnit *U = nullptr); + /// Get the fixed byte size for a given form. + /// + /// If the form has a fixed byte size given a valid DWARF version and address + /// byte size, then an Optional with a valid value is returned. If the form + /// is always encoded using a variable length storage format (ULEB or SLEB + /// numbers or blocks) then None will be returned. + /// + /// \param Form DWARF form to get the fixed byte size for + /// \param Version DWARF version number. + /// \param AddrSize size of an address in bytes. + /// \param Format enum value from llvm::dwarf::DwarfFormat. + /// \returns Optional<uint8_t> value with the fixed byte size or None if + /// \p Form doesn't have a fixed byte size. + static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, uint16_t Version, + uint8_t AddrSize, + llvm::dwarf::DwarfFormat Format); + + /// Skip a form in \p debug_info_data at offset specified by \p offset_ptr. + /// + /// Skips the bytes for this form in the debug info and updates the offset. + /// + /// \param debug_info_data the .debug_info data to use to skip the value. + /// \param offset_ptr a reference to the offset that will be updated. + /// \param U the DWARFUnit to use when skipping the form in case the form + /// size differs according to data in the DWARFUnit. + /// \returns true on success, false if the form was not skipped. bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, - const DWARFUnit *u) const; - static bool skipValue(uint16_t form, DataExtractor debug_info_data, - uint32_t *offset_ptr, const DWARFUnit *u); - static bool skipValue(uint16_t form, DataExtractor debug_info_data, + const DWARFUnit *U) const; + /// Skip a form in \p debug_info_data at offset specified by \p offset_ptr. + /// + /// Skips the bytes for this form in the debug info and updates the offset. + /// + /// \param form the DW_FORM enumeration that indicates the form to skip. + /// \param debug_info_data the .debug_info data to use to skip the value. + /// \param offset_ptr a reference to the offset that will be updated. + /// \param U the DWARFUnit to use when skipping the form in case the form + /// size differs according to data in the DWARFUnit. + /// \returns true on success, false if the form was not skipped. + static bool skipValue(dwarf::Form form, DataExtractor debug_info_data, + uint32_t *offset_ptr, const DWARFUnit *U); + /// Skip a form in \p debug_info_data at offset specified by \p offset_ptr. + /// + /// Skips the bytes for this form in the debug info and updates the offset. + /// + /// \param form the DW_FORM enumeration that indicates the form to skip. + /// \param debug_info_data the .debug_info data to use to skip the value. + /// \param offset_ptr a reference to the offset that will be updated. + /// \param Version DWARF version number. + /// \param AddrSize size of an address in bytes. + /// \param Format enum value from llvm::dwarf::DwarfFormat. + /// \returns true on success, false if the form was not skipped. + static bool skipValue(dwarf::Form form, DataExtractor debug_info_data, uint32_t *offset_ptr, uint16_t Version, - uint8_t AddrSize); + uint8_t AddrSize, llvm::dwarf::DwarfFormat Format); - static ArrayRef<uint8_t> getFixedFormSizes(uint8_t AddrSize, - uint16_t Version); private: - void dumpString(raw_ostream &OS, const DWARFUnit *U) const; + void dumpString(raw_ostream &OS) const; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h new file mode 100644 index 0000000..66041be --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h @@ -0,0 +1,68 @@ +//===-- DWARFGdbIndex.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_LIB_DEBUGINFO_DWARFGDBINDEX_H +#define LLVM_LIB_DEBUGINFO_DWARFGDBINDEX_H + +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +class DWARFGdbIndex { + uint32_t Version; + + uint32_t CuListOffset; + uint32_t AddressAreaOffset; + uint32_t SymbolTableOffset; + uint32_t ConstantPoolOffset; + + struct CompUnitEntry { + uint64_t Offset; // Offset of a CU in the .debug_info section. + uint64_t Length; // Length of that CU. + }; + SmallVector<CompUnitEntry, 0> CuList; + + struct AddressEntry { + uint64_t LowAddress; // The low address. + uint64_t HighAddress; // The high address. + uint32_t CuIndex; // The CU index. + }; + SmallVector<AddressEntry, 0> AddressArea; + + struct SymTableEntry { + uint32_t NameOffset; // Offset of the symbol's name in the constant pool. + uint32_t VecOffset; // Offset of the CU vector in the constant pool. + }; + SmallVector<SymTableEntry, 0> SymbolTable; + + // Each value is CU index + attributes. + SmallVector<std::pair<uint32_t, SmallVector<uint32_t, 0>>, 0> + ConstantPoolVectors; + + StringRef ConstantPoolStrings; + uint32_t StringPoolOffset; + + void dumpCUList(raw_ostream &OS) const; + void dumpAddressArea(raw_ostream &OS) const; + void dumpSymbolTable(raw_ostream &OS) const; + void dumpConstantPool(raw_ostream &OS) const; + + bool parseImpl(DataExtractor Data); + +public: + void dump(raw_ostream &OS); + void parse(DataExtractor Data); + + bool HasContent = false; + bool HasError = false; +}; +} + +#endif // LLVM_LIB_DEBUGINFO_DWARFGDBINDEX_H diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h index a697edd..4f1e129 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -29,7 +29,7 @@ public: uint32_t getHeaderSize() const override { return DWARFUnit::getHeaderSize() + 12; } - void dump(raw_ostream &OS); + void dump(raw_ostream &OS, bool Brief = false); static const DWARFSectionKind Section = DW_SECT_TYPES; protected: diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 9c3fe3b..db7b59b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -10,10 +10,13 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFUNIT_H #define LLVM_LIB_DEBUGINFO_DWARFUNIT_H +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" @@ -124,7 +127,9 @@ class DWARFUnit { uint8_t AddrSize; uint64_t BaseAddr; // The compile unit debug information entry items. - std::vector<DWARFDebugInfoEntryMinimal> DieArray; + std::vector<DWARFDebugInfoEntry> DieArray; + typedef iterator_range<std::vector<DWARFDebugInfoEntry>::iterator> + die_iterator_range; class DWOHolder { object::OwningBinary<object::ObjectFile> DWOFile; @@ -138,6 +143,12 @@ class DWARFUnit { const DWARFUnitIndex::Entry *IndexEntry; + uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) { + auto First = DieArray.data(); + assert(Die >= First && Die < First + DieArray.size()); + return Die - First; + } + protected: virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); /// Size in bytes of the unit header. @@ -191,30 +202,46 @@ public: uint32_t getNextUnitOffset() const { return Offset + Length + 4; } uint32_t getLength() const { return Length; } uint16_t getVersion() const { return Version; } + dwarf::DwarfFormat getFormat() const { + return dwarf::DwarfFormat::DWARF32; // FIXME: Support DWARF64. + } const DWARFAbbreviationDeclarationSet *getAbbreviations() const { return Abbrevs; } uint8_t getAddressByteSize() const { return AddrSize; } + uint8_t getRefAddrByteSize() const { + if (Version == 2) + return AddrSize; + return getDwarfOffsetByteSize(); + } + uint8_t getDwarfOffsetByteSize() const { + if (getFormat() == dwarf::DwarfFormat::DWARF64) + return 8; + return 4; + } uint64_t getBaseAddress() const { return BaseAddr; } void setBaseAddress(uint64_t base_addr) { BaseAddr = base_addr; } - const DWARFDebugInfoEntryMinimal *getUnitDIE(bool ExtractUnitDIEOnly = true) { + DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { extractDIEsIfNeeded(ExtractUnitDIEOnly); - return DieArray.empty() ? nullptr : &DieArray[0]; + if (DieArray.empty()) + return DWARFDie(); + return DWARFDie(this, &DieArray[0]); } const char *getCompilationDir(); - uint64_t getDWOId(); + Optional<uint64_t> getDWOId(); void collectAddressRanges(DWARFAddressRangesVector &CURanges); /// getInlinedChainForAddress - fetches inlined chain for a given address. /// Returns empty chain if there is no subprogram containing address. The /// chain is valid as long as parsed compile unit DIEs are not cleared. - DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); + void getInlinedChainForAddress(uint64_t Address, + SmallVectorImpl<DWARFDie> &InlinedChain); /// getUnitSection - Return the DWARFUnitSection containing this unit. const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } @@ -232,30 +259,34 @@ public: /// created by this unit. In other word, it's illegal to call this /// method on a DIE that isn't accessible by following /// children/sibling links starting from this unit's getUnitDIE(). - uint32_t getDIEIndex(const DWARFDebugInfoEntryMinimal *DIE) { - assert(!DieArray.empty() && DIE >= &DieArray[0] && - DIE < &DieArray[0] + DieArray.size()); - return DIE - &DieArray[0]; + uint32_t getDIEIndex(const DWARFDie &D) { + return getDIEIndex(D.getDebugInfoEntry()); } /// \brief Return the DIE object at the given index. - const DWARFDebugInfoEntryMinimal *getDIEAtIndex(unsigned Index) const { + DWARFDie getDIEAtIndex(unsigned Index) { assert(Index < DieArray.size()); - return &DieArray[Index]; + return DWARFDie(this, &DieArray[Index]); } + DWARFDie getParent(const DWARFDebugInfoEntry *Die); + DWARFDie getSibling(const DWARFDebugInfoEntry *Die); + /// \brief Return the DIE object for a given offset inside the /// unit's DIE vector. /// /// The unit needs to have its DIEs extracted for this method to work. - const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) const { + DWARFDie getDIEForOffset(uint32_t Offset) { + extractDIEsIfNeeded(false); assert(!DieArray.empty()); auto it = std::lower_bound( DieArray.begin(), DieArray.end(), Offset, - [](const DWARFDebugInfoEntryMinimal &LHS, uint32_t Offset) { + [](const DWARFDebugInfoEntry &LHS, uint32_t Offset) { return LHS.getOffset() < Offset; }); - return it == DieArray.end() ? nullptr : &*it; + if (it == DieArray.end()) + return DWARFDie(); + return DWARFDie(this, &*it); } uint32_t getLineTableOffset() const { @@ -265,6 +296,11 @@ public: return 0; } + die_iterator_range dies() { + extractDIEsIfNeeded(false); + return die_iterator_range(DieArray.begin(), DieArray.end()); + } + private: /// Size in bytes of the .debug_info data associated with this compile unit. size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } @@ -274,11 +310,7 @@ private: size_t extractDIEsIfNeeded(bool CUDieOnly); /// extractDIEsToVector - Appends all parsed DIEs to a vector. void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, - std::vector<DWARFDebugInfoEntryMinimal> &DIEs) const; - /// setDIERelations - We read in all of the DIE entries into our flat list - /// of DIE entries and now we need to go back through all of them and set the - /// parent, sibling and child pointers for quick DIE navigation. - void setDIERelations(); + std::vector<DWARFDebugInfoEntry> &DIEs) const; /// clearDIEs - Clear parsed DIEs to keep memory usage low. void clearDIEs(bool KeepCUDie); @@ -289,7 +321,7 @@ private: /// getSubprogramForAddress - Returns subprogram DIE with address range /// encompassing the provided address. The pointer is alive as long as parsed /// compile unit DIEs are not cleared. - const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address); + DWARFDie getSubprogramForAddress(uint64_t Address); }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/ByteStream.h b/contrib/llvm/include/llvm/DebugInfo/MSF/ByteStream.h new file mode 100644 index 0000000..547844b --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/ByteStream.h @@ -0,0 +1,169 @@ +//===- 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_MSF_BYTESTREAM_H +#define LLVM_DEBUGINFO_MSF_BYTESTREAM_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/MSF/MSFError.h" +#include "llvm/DebugInfo/MSF/StreamInterface.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/MemoryBuffer.h" +#include <algorithm> +#include <cstdint> +#include <cstring> +#include <memory> + +namespace llvm { +namespace msf { + +class ByteStream : public ReadableStream { +public: + ByteStream() = default; + explicit ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {} + explicit ByteStream(StringRef Data) + : Data(Data.bytes_begin(), Data.bytes_end()) {} + + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const override { + if (Offset > Data.size()) + return make_error<MSFError>(msf_error_code::insufficient_buffer); + if (Data.size() < Size + Offset) + return make_error<MSFError>(msf_error_code::insufficient_buffer); + Buffer = Data.slice(Offset, Size); + return Error::success(); + } + + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const override { + if (Offset >= Data.size()) + return make_error<MSFError>(msf_error_code::insufficient_buffer); + Buffer = Data.slice(Offset); + return Error::success(); + } + + uint32_t getLength() const override { return Data.size(); } + + ArrayRef<uint8_t> data() const { return Data; } + + StringRef str() const { + const char *CharData = reinterpret_cast<const char *>(Data.data()); + return StringRef(CharData, Data.size()); + } + +protected: + ArrayRef<uint8_t> Data; +}; + +// MemoryBufferByteStream behaves like a read-only ByteStream, but has its data +// backed by an llvm::MemoryBuffer. It also owns the underlying MemoryBuffer. +class MemoryBufferByteStream : public ByteStream { +public: + explicit MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer) + : ByteStream(ArrayRef<uint8_t>(Buffer->getBuffer().bytes_begin(), + Buffer->getBuffer().bytes_end())), + MemBuffer(std::move(Buffer)) {} + + std::unique_ptr<MemoryBuffer> MemBuffer; +}; + +class MutableByteStream : public WritableStream { +public: + MutableByteStream() = default; + explicit MutableByteStream(MutableArrayRef<uint8_t> Data) + : Data(Data), ImmutableStream(Data) {} + + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const override { + return ImmutableStream.readBytes(Offset, Size, Buffer); + } + + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const override { + return ImmutableStream.readLongestContiguousChunk(Offset, Buffer); + } + + uint32_t getLength() const override { return ImmutableStream.getLength(); } + + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override { + if (Buffer.empty()) + return Error::success(); + + if (Data.size() < Buffer.size()) + return make_error<MSFError>(msf_error_code::insufficient_buffer); + if (Offset > Buffer.size() - Data.size()) + return make_error<MSFError>(msf_error_code::insufficient_buffer); + + uint8_t *DataPtr = const_cast<uint8_t *>(Data.data()); + ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size()); + return Error::success(); + } + + Error commit() const override { return Error::success(); } + + MutableArrayRef<uint8_t> data() const { return Data; } + +private: + MutableArrayRef<uint8_t> Data; + ByteStream ImmutableStream; +}; + +// A simple adapter that acts like a ByteStream but holds ownership over +// and underlying FileOutputBuffer. +class FileBufferByteStream : public WritableStream { +private: + class StreamImpl : public MutableByteStream { + public: + StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer) + : MutableByteStream(MutableArrayRef<uint8_t>(Buffer->getBufferStart(), + Buffer->getBufferEnd())), + FileBuffer(std::move(Buffer)) {} + + Error commit() const override { + if (FileBuffer->commit()) + return llvm::make_error<MSFError>(msf_error_code::not_writable); + return Error::success(); + } + + private: + std::unique_ptr<FileOutputBuffer> FileBuffer; + }; + +public: + explicit FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer) + : Impl(std::move(Buffer)) {} + + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const override { + return Impl.readBytes(Offset, Size, Buffer); + } + + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const override { + return Impl.readLongestContiguousChunk(Offset, Buffer); + } + + uint32_t getLength() const override { return Impl.getLength(); } + + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const override { + return Impl.writeBytes(Offset, Data); + } + + Error commit() const override { return Impl.commit(); } + +private: + StreamImpl Impl; +}; + +} // end namespace msf +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_BYTESTREAM_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h b/contrib/llvm/include/llvm/DebugInfo/MSF/IMSFFile.h index fccea2a..f98e715 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/IPDBFile.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/IMSFFile.h @@ -1,4 +1,4 @@ -//===- IPDBFile.h - Abstract base class for a PDB file ----------*- C++ -*-===// +//===- IMSFFile.h - Abstract base class for an MSF file ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,23 +7,20 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_PDB_RAW_IPDBFILE_H -#define LLVM_DEBUGINFO_PDB_RAW_IPDBFILE_H +#ifndef LLVM_DEBUGINFO_MSF_IMSFFILE_H +#define LLVM_DEBUGINFO_MSF_IMSFFILE_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" - -#include <stdint.h> +#include <cstdint> namespace llvm { -namespace pdb { +namespace msf { -class IPDBFile { +class IMSFFile { public: - virtual ~IPDBFile() {} + virtual ~IMSFFile() = default; virtual uint32_t getBlockSize() const = 0; virtual uint32_t getBlockCount() const = 0; @@ -38,7 +35,8 @@ public: virtual Error setBlockData(uint32_t BlockIndex, uint32_t Offset, ArrayRef<uint8_t> Data) const = 0; }; -} -} -#endif // LLVM_DEBUGINFO_PDB_RAW_IPDBFILE_H +} // end namespace msf +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_IMSFFILE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h index 92d9bc0..6d067cc 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/MsfBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h @@ -7,14 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_PDB_RAW_MSFBUILDER_H -#define LLVM_DEBUGINFO_PDB_RAW_MSFBUILDER_H +#ifndef LLVM_DEBUGINFO_MSF_MSFBUILDER_H +#define LLVM_DEBUGINFO_MSF_MSFBUILDER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" -#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Endian.h" @@ -24,19 +23,19 @@ #include <vector> namespace llvm { -namespace pdb { -class MsfBuilder { +namespace msf { +class MSFBuilder { public: - /// \brief Create a new `MsfBuilder`. + /// \brief Create a new `MSFBuilder`. /// /// \param BlockSize The internal block size used by the PDB file. See /// isValidBlockSize() for a list of valid block sizes. /// /// \param MinBlockCount Causes the builder to reserve up front space for - /// at least `MinBlockCount` blocks. This is useful when using `MsfBuilder` - /// to read an existing PDB that you want to write back out later. The - /// original PDB file's SuperBlock contains the exact number of blocks used - /// by the file, so is a good hint as to how many blocks the new PDB file + /// at least `MinBlockCount` blocks. This is useful when using `MSFBuilder` + /// to read an existing MSF that you want to write back out later. The + /// original MSF file's SuperBlock contains the exact number of blocks used + /// by the file, so is a good hint as to how many blocks the new MSF file /// will contain. Furthermore, it is actually necessary in this case. To /// preserve stability of the file's layout, it is helpful to try to keep /// all streams mapped to their original block numbers. To ensure that this @@ -45,7 +44,7 @@ public: /// /// \param CanGrow If true, any operation which results in an attempt to /// locate a free block when all available blocks have been exhausted will - /// allocate a new block, thereby growing the size of the final PDB file. + /// allocate a new block, thereby growing the size of the final MSF file. /// When false, any such attempt will result in an error. This is especially /// useful in testing scenarios when you know your test isn't going to do /// anything to increase the size of the file, so having an Error returned if @@ -55,34 +54,34 @@ public: /// failed. Currently the only way this can fail is if an invalid block size /// is specified, or `MinBlockCount` does not leave enough room for the /// mandatory reserved blocks required by an MSF file. - static Expected<MsfBuilder> create(BumpPtrAllocator &Allocator, + static Expected<MSFBuilder> create(BumpPtrAllocator &Allocator, uint32_t BlockSize, uint32_t MinBlockCount = 0, bool CanGrow = true); /// Request the block map to be at a specific block address. This is useful - /// when editing a PDB and you want the layout to be as stable as possible. + /// when editing a MSF and you want the layout to be as stable as possible. Error setBlockMapAddr(uint32_t Addr); Error setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks); void setFreePageMap(uint32_t Fpm); void setUnknown1(uint32_t Unk1); /// Add a stream to the MSF file with the given size, occupying the given - /// list of blocks. This is useful when reading a PDB file and you want a + /// list of blocks. This is useful when reading a MSF file and you want a /// particular stream to occupy the original set of blocks. If the given /// blocks are already allocated, or if the number of blocks specified is /// incorrect for the given stream size, this function will return an Error. - Error addStream(uint32_t Size, ArrayRef<uint32_t> Blocks); + Expected<uint32_t> addStream(uint32_t Size, ArrayRef<uint32_t> Blocks); /// Add a stream to the MSF file with the given size, occupying any available /// blocks that the builder decides to use. This is useful when building a /// new PDB file from scratch and you don't care what blocks a stream occupies /// but you just want it to work. - Error addStream(uint32_t Size); + Expected<uint32_t> addStream(uint32_t Size); /// Update the size of an existing stream. This will allocate or deallocate /// blocks as needed to match the requested size. This can fail if `CanGrow` - /// was set to false when initializing the `MsfBuilder`. + /// was set to false when initializing the `MSFBuilder`. Error setStreamSize(uint32_t Idx, uint32_t Size); /// Get the total number of streams in the MSF layout. This should return 1 @@ -112,10 +111,12 @@ public: /// Finalize the layout and build the headers and structures that describe the /// MSF layout and can be written directly to the MSF file. - Expected<msf::Layout> build(); + Expected<MSFLayout> build(); + + BumpPtrAllocator &getAllocator() { return Allocator; } private: - MsfBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow, + MSFBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow, BumpPtrAllocator &Allocator); Error allocateBlocks(uint32_t NumBlocks, MutableArrayRef<uint32_t> Blocks); @@ -127,7 +128,7 @@ private: bool IsGrowable; uint32_t FreePageMap; - uint32_t Unknown1; + uint32_t Unknown1 = 0; uint32_t BlockSize; uint32_t MininumBlocks; uint32_t BlockMapAddr; @@ -135,7 +136,7 @@ private: std::vector<uint32_t> DirectoryBlocks; std::vector<std::pair<uint32_t, BlockList>> StreamData; }; -} -} +} // namespace msf +} // namespace llvm -#endif +#endif // LLVM_DEBUGINFO_MSF_MSFBUILDER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/MsfCommon.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h index 2f6a698..93a9c80 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/MsfCommon.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h @@ -1,4 +1,4 @@ -//===- MsfCommon.h - Common types and functions for MSF files ---*- C++ -*-===// +//===- MSFCommon.h - Common types and functions for MSF files ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,10 +7,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_PDB_RAW_MSFCOMMON_H -#define LLVM_DEBUGINFO_PDB_RAW_MSFCOMMON_H +#ifndef LLVM_DEBUGINFO_MSF_MSFCOMMON_H +#define LLVM_DEBUGINFO_MSF_MSFCOMMON_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -19,7 +20,6 @@ #include <vector> namespace llvm { -namespace pdb { namespace msf { static const char Magic[] = {'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', ' ', 'C', '/', 'C', '+', '+', ' ', @@ -38,7 +38,7 @@ struct SuperBlock { // The index of the free block map. support::ulittle32_t FreeBlockMapBlock; // This contains the number of blocks resident in the file system. In - // practice, NumBlocks * BlockSize is equivalent to the size of the PDB + // practice, NumBlocks * BlockSize is equivalent to the size of the MSF // file. support::ulittle32_t NumBlocks; // This contains the number of bytes which make up the directory. @@ -49,8 +49,10 @@ struct SuperBlock { support::ulittle32_t BlockMapAddr; }; -struct Layout { - SuperBlock *SB; +struct MSFLayout { + MSFLayout() : SB(nullptr) {} + const SuperBlock *SB; + BitVector FreePageMap; ArrayRef<support::ulittle32_t> DirectoryBlocks; ArrayRef<support::ulittle32_t> StreamSizes; std::vector<ArrayRef<support::ulittle32_t>> StreamMap; @@ -82,9 +84,21 @@ inline uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize) { return BlockNumber * BlockSize; } -Error validateSuperBlock(const SuperBlock &SB); +inline uint32_t getFpmIntervalLength(const MSFLayout &L) { + return L.SB->BlockSize; } + +inline uint32_t getNumFpmIntervals(const MSFLayout &L) { + uint32_t Length = getFpmIntervalLength(L); + return llvm::alignTo(L.SB->NumBlocks, Length) / Length; } + +inline uint32_t getFullFpmByteSize(const MSFLayout &L) { + return llvm::alignTo(L.SB->NumBlocks, 8) / 8; } -#endif +Error validateSuperBlock(const SuperBlock &SB); +} // namespace msf +} // namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_MSFCOMMON_H diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFError.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFError.h new file mode 100644 index 0000000..e66aeca --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFError.h @@ -0,0 +1,47 @@ +//===- MSFError.h - Error extensions for MSF Files --------------*- 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_MSF_MSFERROR_H +#define LLVM_DEBUGINFO_MSF_MSFERROR_H + +#include "llvm/Support/Error.h" + +#include <string> + +namespace llvm { +namespace msf { +enum class msf_error_code { + unspecified = 1, + insufficient_buffer, + not_writable, + no_stream, + invalid_format, + block_in_use +}; + +/// Base class for errors originating when parsing raw PDB files +class MSFError : public ErrorInfo<MSFError> { +public: + static char ID; + MSFError(msf_error_code C); + MSFError(const std::string &Context); + MSFError(msf_error_code C, const std::string &Context); + + void log(raw_ostream &OS) const override; + const std::string &getErrorMessage() const; + std::error_code convertToErrorCode() const override; + +private: + std::string ErrMsg; + msf_error_code Code; +}; +} // namespace msf +} // namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_MSFERROR_H diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFStreamLayout.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFStreamLayout.h new file mode 100644 index 0000000..bdde98f --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFStreamLayout.h @@ -0,0 +1,35 @@ +//===- MSFStreamLayout.h - Describes the layout of 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_MSF_MSFSTREAMLAYOUT_H +#define LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H + +#include "llvm/Support/Endian.h" + +#include <cstdint> +#include <vector> + +namespace llvm { +namespace msf { + +/// \brief Describes the layout of a stream in an MSF layout. A "stream" here +/// is defined as any logical unit of data which may be arranged inside the MSF +/// file as a sequence of (possibly discontiguous) blocks. When we want to read +/// from a particular MSF Stream, we fill out a stream layout structure and the +/// reader uses it to determine which blocks in the underlying MSF file contain +/// the data, so that it can be pieced together in the right order. +class MSFStreamLayout { +public: + uint32_t Length; + std::vector<support::ulittle32_t> Blocks; +}; +} // namespace msf +} // namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h new file mode 100644 index 0000000..fff4e9c --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h @@ -0,0 +1,144 @@ +//===- MappedBlockStream.h - Discontiguous stream data in an MSF -*- 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_MSF_MAPPEDBLOCKSTREAM_H +#define LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/MSF/MSFStreamLayout.h" +#include "llvm/DebugInfo/MSF/StreamInterface.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace msf { + +struct MSFLayout; + +/// MappedBlockStream represents data stored in an MSF file into chunks of a +/// particular size (called the Block Size), and whose chunks may not be +/// necessarily contiguous. The arrangement of these chunks MSF the file +/// is described by some other metadata contained within the MSF file. In +/// the case of a standard MSF Stream, the layout of the stream's blocks +/// is described by the MSF "directory", but in the case of the directory +/// itself, the layout is described by an array at a fixed location within +/// the MSF. MappedBlockStream provides methods for reading from and writing +/// to one of these streams transparently, as if it were a contiguous sequence +/// of bytes. +class MappedBlockStream : public ReadableStream { + friend class WritableMappedBlockStream; +public: + static std::unique_ptr<MappedBlockStream> + createStream(uint32_t BlockSize, uint32_t NumBlocks, + const MSFStreamLayout &Layout, const ReadableStream &MsfData); + + static std::unique_ptr<MappedBlockStream> + createIndexedStream(const MSFLayout &Layout, const ReadableStream &MsfData, + uint32_t StreamIndex); + + static std::unique_ptr<MappedBlockStream> + createFpmStream(const MSFLayout &Layout, const ReadableStream &MsfData); + + static std::unique_ptr<MappedBlockStream> + createDirectoryStream(const MSFLayout &Layout, const ReadableStream &MsfData); + + 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; + + uint32_t getLength() const override; + + uint32_t getNumBytesCopied() const; + + llvm::BumpPtrAllocator &getAllocator() { return Pool; } + + void invalidateCache(); + + uint32_t getBlockSize() const { return BlockSize; } + uint32_t getNumBlocks() const { return NumBlocks; } + uint32_t getStreamLength() const { return StreamLayout.Length; } + +protected: + MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks, + const MSFStreamLayout &StreamLayout, + const ReadableStream &MsfData); + +private: + const MSFStreamLayout &getStreamLayout() const { return StreamLayout; } + void fixCacheAfterWrite(uint32_t Offset, ArrayRef<uint8_t> Data) const; + + Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const; + bool tryReadContiguously(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const; + + const uint32_t BlockSize; + const uint32_t NumBlocks; + const MSFStreamLayout StreamLayout; + const ReadableStream &MsfData; + + typedef MutableArrayRef<uint8_t> CacheEntry; + mutable llvm::BumpPtrAllocator Pool; + mutable DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap; +}; + +class WritableMappedBlockStream : public WritableStream { +public: + static std::unique_ptr<WritableMappedBlockStream> + createStream(uint32_t BlockSize, uint32_t NumBlocks, + const MSFStreamLayout &Layout, const WritableStream &MsfData); + + static std::unique_ptr<WritableMappedBlockStream> + createIndexedStream(const MSFLayout &Layout, const WritableStream &MsfData, + uint32_t StreamIndex); + + static std::unique_ptr<WritableMappedBlockStream> + createDirectoryStream(const MSFLayout &Layout, const WritableStream &MsfData); + + static std::unique_ptr<WritableMappedBlockStream> + createFpmStream(const MSFLayout &Layout, const WritableStream &MsfData); + + 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; + uint32_t getLength() const override; + + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override; + + Error commit() const override; + + const MSFStreamLayout &getStreamLayout() const { + return ReadInterface.getStreamLayout(); + } + uint32_t getBlockSize() const { return ReadInterface.getBlockSize(); } + uint32_t getNumBlocks() const { return ReadInterface.getNumBlocks(); } + uint32_t getStreamLength() const { return ReadInterface.getStreamLength(); } + +protected: + WritableMappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks, + const MSFStreamLayout &StreamLayout, + const WritableStream &MsfData); + +private: + MappedBlockStream ReadInterface; + + const WritableStream &WriteInterface; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/SequencedItemStream.h b/contrib/llvm/include/llvm/DebugInfo/MSF/SequencedItemStream.h new file mode 100644 index 0000000..1949bee --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/SequencedItemStream.h @@ -0,0 +1,93 @@ +//===- SequencedItemStream.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_MSF_SEQUENCEDITEMSTREAM_H +#define LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/MSF/MSFError.h" +#include "llvm/DebugInfo/MSF/StreamInterface.h" +#include "llvm/Support/Error.h" +#include <cstddef> +#include <cstdint> + +namespace llvm { +namespace msf { + +template <typename T> struct SequencedItemTraits { + static size_t length(const T &Item) = delete; + static ArrayRef<uint8_t> bytes(const T &Item) = delete; +}; + +/// SequencedItemStream represents a sequence of objects stored in a +/// standard container but for which it is useful to view as a stream of +/// contiguous bytes. An example of this might be if you have a std::vector +/// of TPI records, where each record contains a byte sequence that +/// represents that one record serialized, but where each consecutive item +/// might not be allocated immediately after the previous item. Using a +/// SequencedItemStream, we can adapt the VarStreamArray class to trivially +/// extract one item at a time, allowing the data to be used anywhere a +/// VarStreamArray could be used. +template <typename T, typename Traits = SequencedItemTraits<T>> +class SequencedItemStream : public ReadableStream { +public: + SequencedItemStream() = default; + + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) const override { + auto ExpectedIndex = translateOffsetIndex(Offset); + if (!ExpectedIndex) + return ExpectedIndex.takeError(); + const auto &Item = Items[*ExpectedIndex]; + if (Size > Traits::length(Item)) + return make_error<MSFError>(msf_error_code::insufficient_buffer); + Buffer = Traits::bytes(Item).take_front(Size); + return Error::success(); + } + + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) const override { + auto ExpectedIndex = translateOffsetIndex(Offset); + if (!ExpectedIndex) + return ExpectedIndex.takeError(); + Buffer = Traits::bytes(Items[*ExpectedIndex]); + return Error::success(); + } + + void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; } + + uint32_t getLength() const override { + uint32_t Size = 0; + for (const auto &Item : Items) + Size += Traits::length(Item); + return Size; + } + +private: + Expected<uint32_t> translateOffsetIndex(uint32_t Offset) const { + uint32_t CurrentOffset = 0; + uint32_t CurrentIndex = 0; + for (const auto &Item : Items) { + if (CurrentOffset >= Offset) + break; + CurrentOffset += Traits::length(Item); + ++CurrentIndex; + } + if (CurrentOffset != Offset) + return make_error<MSFError>(msf_error_code::insufficient_buffer); + return CurrentIndex; + } + + ArrayRef<T> Items; +}; + +} // end namespace msf +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamArray.h index 0b9349a..5dfeb8c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamArray.h @@ -1,4 +1,4 @@ -//===- StreamArray.h - Array backed by an arbitrary stream ----------------===// +//===- StreamArray.h - Array backed by an arbitrary stream ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,17 +7,18 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H -#define LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H +#ifndef LLVM_DEBUGINFO_MSF_STREAMARRAY_H +#define LLVM_DEBUGINFO_MSF_STREAMARRAY_H -#include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/DebugInfo/MSF/StreamRef.h" #include "llvm/Support/Error.h" - -#include <functional> -#include <type_traits> +#include <cassert> +#include <cstdint> namespace llvm { -namespace codeview { +namespace msf { /// VarStreamArrayExtractor is intended to be specialized to provide customized /// extraction logic. On input it receives a StreamRef pointing to the @@ -34,7 +35,8 @@ namespace codeview { 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; + Error operator()(ReadableStreamRef Stream, uint32_t &Len, + T &Item) const = delete; }; /// VarStreamArray represents an array of variable length records backed by a @@ -74,17 +76,19 @@ 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() {} + VarStreamArray() = default; explicit VarStreamArray(const Extractor &E) : E(E) {} - explicit VarStreamArray(StreamRef Stream) : Stream(Stream) {} - VarStreamArray(StreamRef Stream, const Extractor &E) : Stream(Stream), E(E) {} + explicit VarStreamArray(ReadableStreamRef Stream) : Stream(Stream) {} + VarStreamArray(ReadableStreamRef Stream, const Extractor &E) + : Stream(Stream), E(E) {} VarStreamArray(const VarStreamArray<ValueType, Extractor> &Other) : Stream(Other.Stream), E(Other.E) {} @@ -97,14 +101,17 @@ public: const Extractor &getExtractor() const { return E; } - StreamRef getUnderlyingStream() const { return Stream; } + ReadableStreamRef getUnderlyingStream() const { return Stream; } private: - StreamRef Stream; + ReadableStreamRef Stream; Extractor E; }; -template <typename ValueType, typename Extractor> class VarStreamArrayIterator { +template <typename ValueType, typename Extractor> +class VarStreamArrayIterator + : public iterator_facade_base<VarStreamArrayIterator<ValueType, Extractor>, + std::forward_iterator_tag, ValueType> { typedef VarStreamArrayIterator<ValueType, Extractor> IterType; typedef VarStreamArray<ValueType, Extractor> ArrayType; @@ -122,9 +129,9 @@ public: } } } - VarStreamArrayIterator() {} + VarStreamArrayIterator() = default; explicit VarStreamArrayIterator(const Extractor &E) : Extract(E) {} - ~VarStreamArrayIterator() {} + ~VarStreamArrayIterator() = default; bool operator==(const IterType &R) const { if (Array && R.Array) { @@ -141,8 +148,6 @@ public: return false; } - bool operator!=(const IterType &R) { return !(*this == R); } - const ValueType &operator*() const { assert(Array && !HasError); return ThisValue; @@ -170,12 +175,6 @@ public: return *this; } - IterType operator++(int) { - IterType Original = *this; - ++*this; - return Original; - } - private: void moveToEnd() { Array = nullptr; @@ -189,7 +188,7 @@ private: } ValueType ThisValue; - StreamRef IterRef; + ReadableStreamRef IterRef; const ArrayType *Array{nullptr}; uint32_t ThisLen{0}; bool HasError{false}; @@ -203,11 +202,21 @@ template <typename T> class FixedStreamArray { friend class FixedStreamArrayIterator<T>; public: - FixedStreamArray() : Stream() {} - FixedStreamArray(StreamRef Stream) : Stream(Stream) { + FixedStreamArray() = default; + FixedStreamArray(ReadableStreamRef Stream) : Stream(Stream) { assert(Stream.getLength() % sizeof(T) == 0); } + bool operator==(const FixedStreamArray<T> &Other) const { + return Stream == Other.Stream; + } + + bool operator!=(const FixedStreamArray<T> &Other) const { + return !(*this == Other); + } + + FixedStreamArray &operator=(const FixedStreamArray &) = default; + const T &operator[](uint32_t Index) const { assert(Index < size()); uint32_t Off = Index * sizeof(T); @@ -223,53 +232,73 @@ public: uint32_t size() const { return Stream.getLength() / sizeof(T); } + bool empty() const { return size() == 0; } + FixedStreamArrayIterator<T> begin() const { return FixedStreamArrayIterator<T>(*this, 0); } + FixedStreamArrayIterator<T> end() const { return FixedStreamArrayIterator<T>(*this, size()); } - StreamRef getUnderlyingStream() const { return Stream; } + ReadableStreamRef getUnderlyingStream() const { return Stream; } private: - StreamRef Stream; + ReadableStreamRef Stream; }; -template <typename T> class FixedStreamArrayIterator { +template <typename T> +class FixedStreamArrayIterator + : public iterator_facade_base<FixedStreamArrayIterator<T>, + std::random_access_iterator_tag, T> { + 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; + FixedStreamArrayIterator<T> & + operator=(const FixedStreamArrayIterator<T> &Other) { + Array = Other.Array; + Index = Other.Index; + return *this; } - bool operator!=(const FixedStreamArrayIterator<T> &R) { - return !(*this == R); + const T &operator*() const { return Array[Index]; } + + bool operator==(const FixedStreamArrayIterator<T> &R) const { + assert(Array == R.Array); + return (Index == R.Index) && (Array == R.Array); } - const T &operator*() const { return Array[Index]; } + FixedStreamArrayIterator<T> &operator+=(std::ptrdiff_t N) { + Index += N; + return *this; + } - FixedStreamArrayIterator<T> &operator++() { - assert(Index < Array.size()); - ++Index; + FixedStreamArrayIterator<T> &operator-=(std::ptrdiff_t N) { + assert(Index >= N); + Index -= N; return *this; } - FixedStreamArrayIterator<T> operator++(int) { - FixedStreamArrayIterator<T> Original = *this; - ++*this; - return Original; + std::ptrdiff_t operator-(const FixedStreamArrayIterator<T> &R) const { + assert(Array == R.Array); + assert(Index >= R.Index); + return Index - R.Index; + } + + bool operator<(const FixedStreamArrayIterator<T> &RHS) const { + assert(Array == RHS.Array); + return Index < RHS.Index; } private: - const FixedStreamArray<T> &Array; + FixedStreamArray<T> Array; uint32_t Index; }; -} // namespace codeview +} // namespace msf } // namespace llvm -#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMARRAY_H +#endif // LLVM_DEBUGINFO_MSF_STREAMARRAY_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamInterface.h index 241aec4..09782d8 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamInterface.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamInterface.h @@ -7,26 +7,19 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMINTERFACE_H -#define LLVM_DEBUGINFO_CODEVIEW_STREAMINTERFACE_H +#ifndef LLVM_DEBUGINFO_MSF_STREAMINTERFACE_H +#define LLVM_DEBUGINFO_MSF_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 { +namespace msf { + +class ReadableStream { public: - virtual ~StreamInterface() {} + virtual ~ReadableStream() = default; // 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 @@ -39,17 +32,22 @@ public: virtual Error readLongestContiguousChunk(uint32_t Offset, ArrayRef<uint8_t> &Buffer) const = 0; + virtual uint32_t getLength() const = 0; +}; + +class WritableStream : public ReadableStream { +public: + ~WritableStream() override = default; + // 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 msf } // end namespace llvm -#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMINTERFACE_H +#endif // LLVM_DEBUGINFO_MSF_STREAMINTERFACE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamReader.h index 2f497c2..fc2ca78 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamReader.h @@ -7,35 +7,40 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H -#define LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H +#ifndef LLVM_DEBUGINFO_MSF_STREAMREADER_H +#define LLVM_DEBUGINFO_MSF_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/DebugInfo/MSF/MSFError.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/DebugInfo/MSF/StreamInterface.h" +#include "llvm/DebugInfo/MSF/StreamRef.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <string> namespace llvm { -namespace codeview { - -class StreamRef; +namespace msf { class StreamReader { public: - StreamReader(StreamRef Stream); + StreamReader(ReadableStreamRef Stream); Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer); Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size); + Error readInteger(uint8_t &Dest); Error readInteger(uint16_t &Dest); Error readInteger(uint32_t &Dest); + Error readInteger(uint64_t &Dest); + Error readInteger(int8_t &Dest); + Error readInteger(int16_t &Dest); + Error readInteger(int32_t &Dest); + Error readInteger(int64_t &Dest); Error readZeroString(StringRef &Dest); Error readFixedString(StringRef &Dest, uint32_t Length); - Error readStreamRef(StreamRef &Ref); - Error readStreamRef(StreamRef &Ref, uint32_t Length); + Error readStreamRef(ReadableStreamRef &Ref); + Error readStreamRef(ReadableStreamRef &Ref, uint32_t Length); template <typename T> Error readEnum(T &Dest) { typename std::underlying_type<T>::type N; @@ -61,8 +66,8 @@ public: return Error::success(); } - if (NumElements > UINT32_MAX/sizeof(T)) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); + if (NumElements > UINT32_MAX / sizeof(T)) + return make_error<MSFError>(msf_error_code::insufficient_buffer); if (auto EC = readBytes(Bytes, NumElements * sizeof(T))) return EC; @@ -72,7 +77,7 @@ public: template <typename T, typename U> Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) { - StreamRef S; + ReadableStreamRef S; if (auto EC = readStreamRef(S, Size)) return EC; Array = VarStreamArray<T, U>(S, Array.getExtractor()); @@ -87,25 +92,30 @@ public: } uint32_t Length = NumItems * sizeof(T); if (Length / sizeof(T) != NumItems) - return make_error<CodeViewError>(cv_error_code::corrupt_record); + return make_error<MSFError>(msf_error_code::invalid_format); if (Offset + Length > Stream.getLength()) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); - StreamRef View = Stream.slice(Offset, Length); + return make_error<MSFError>(msf_error_code::insufficient_buffer); + ReadableStreamRef View = Stream.slice(Offset, Length); Array = FixedStreamArray<T>(View); Offset += Length; return Error::success(); } + bool empty() const { return bytesRemaining() == 0; } 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(); } + Error skip(uint32_t Amount); + + uint8_t peek() const; + private: - StreamRef Stream; + ReadableStreamRef Stream; uint32_t Offset; }; -} // namespace codeview +} // namespace msf } // namespace llvm -#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H +#endif // LLVM_DEBUGINFO_MSF_STREAMREADER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/StreamRef.h b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamRef.h new file mode 100644 index 0000000..eee71e5 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamRef.h @@ -0,0 +1,135 @@ +//===- 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_MSF_STREAMREF_H +#define LLVM_DEBUGINFO_MSF_STREAMREF_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/MSF/MSFError.h" +#include "llvm/DebugInfo/MSF/StreamInterface.h" +#include "llvm/Support/Error.h" +#include <algorithm> +#include <cstdint> + +namespace llvm { +namespace msf { + +template <class StreamType, class RefType> class StreamRefBase { +public: + StreamRefBase() : Stream(nullptr), ViewOffset(0), Length(0) {} + StreamRefBase(const StreamType &Stream, uint32_t Offset, uint32_t Length) + : Stream(&Stream), ViewOffset(Offset), Length(Length) {} + + uint32_t getLength() const { return Length; } + const StreamType *getStream() const { return Stream; } + + RefType drop_front(uint32_t N) const { + if (!Stream) + return RefType(); + + N = std::min(N, Length); + return RefType(*Stream, ViewOffset + N, Length - N); + } + + RefType keep_front(uint32_t N) const { + if (!Stream) + return RefType(); + N = std::min(N, Length); + return RefType(*Stream, ViewOffset, N); + } + + RefType slice(uint32_t Offset, uint32_t Len) const { + return drop_front(Offset).keep_front(Len); + } + + bool operator==(const RefType &Other) const { + if (Stream != Other.Stream) + return false; + if (ViewOffset != Other.ViewOffset) + return false; + if (Length != Other.Length) + return false; + return true; + } + +protected: + const StreamType *Stream; + uint32_t ViewOffset; + uint32_t Length; +}; + +class ReadableStreamRef + : public StreamRefBase<ReadableStream, ReadableStreamRef> { +public: + ReadableStreamRef() = default; + ReadableStreamRef(const ReadableStream &Stream) + : StreamRefBase(Stream, 0, Stream.getLength()) {} + ReadableStreamRef(const ReadableStream &Stream, uint32_t Offset, + uint32_t Length) + : StreamRefBase(Stream, Offset, Length) {} + + // Use StreamRef.slice() instead. + ReadableStreamRef(const ReadableStreamRef &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<MSFError>(msf_error_code::insufficient_buffer); + if (Size + Offset > Length) + return make_error<MSFError>(msf_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<MSFError>(msf_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(); + } +}; + +class WritableStreamRef + : public StreamRefBase<WritableStream, WritableStreamRef> { +public: + WritableStreamRef() = default; + WritableStreamRef(const WritableStream &Stream) + : StreamRefBase(Stream, 0, Stream.getLength()) {} + WritableStreamRef(const WritableStream &Stream, uint32_t Offset, + uint32_t Length) + : StreamRefBase(Stream, Offset, Length) {} + + // Use StreamRef.slice() instead. + WritableStreamRef(const WritableStreamRef &S, uint32_t Offset, + uint32_t Length) = delete; + + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const { + if (Data.size() + Offset > Length) + return make_error<MSFError>(msf_error_code::insufficient_buffer); + return Stream->writeBytes(ViewOffset + Offset, Data); + } + + Error commit() const { return Stream->commit(); } +}; + +} // end namespace msf +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_STREAMREF_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamWriter.h b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamWriter.h index 4d393d2..2bb1443 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StreamWriter.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/StreamWriter.h @@ -7,34 +7,39 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMWRITER_H -#define LLVM_DEBUGINFO_CODEVIEW_STREAMWRITER_H +#ifndef LLVM_DEBUGINFO_MSF_STREAMWRITER_H +#define LLVM_DEBUGINFO_MSF_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/ADT/StringRef.h" +#include "llvm/DebugInfo/MSF/MSFError.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/DebugInfo/MSF/StreamRef.h" #include "llvm/Support/Error.h" - -#include <string> +#include <cstdint> +#include <type_traits> namespace llvm { -namespace codeview { - -class StreamRef; +namespace msf { class StreamWriter { public: - StreamWriter(StreamRef Stream); + StreamWriter() = default; + explicit StreamWriter(WritableStreamRef Stream); Error writeBytes(ArrayRef<uint8_t> Buffer); + Error writeInteger(uint8_t Int); Error writeInteger(uint16_t Dest); Error writeInteger(uint32_t Dest); + Error writeInteger(uint64_t Dest); + Error writeInteger(int8_t Int); + Error writeInteger(int16_t Dest); + Error writeInteger(int32_t Dest); + Error writeInteger(int64_t Dest); Error writeZeroString(StringRef Str); Error writeFixedString(StringRef Str); - Error writeStreamRef(StreamRef Ref); - Error writeStreamRef(StreamRef Ref, uint32_t Size); + Error writeStreamRef(ReadableStreamRef Ref); + Error writeStreamRef(ReadableStreamRef Ref, uint32_t Size); template <typename T> Error writeEnum(T Num) { return writeInteger( @@ -51,11 +56,11 @@ public: } template <typename T> Error writeArray(ArrayRef<T> Array) { - if (Array.size() == 0) + if (Array.empty()) return Error::success(); if (Array.size() > UINT32_MAX / sizeof(T)) - return make_error<CodeViewError>(cv_error_code::insufficient_buffer); + return make_error<MSFError>(msf_error_code::insufficient_buffer); return writeBytes( ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()), @@ -77,10 +82,11 @@ public: uint32_t bytesRemaining() const { return getLength() - getOffset(); } private: - StreamRef Stream; - uint32_t Offset; + WritableStreamRef Stream; + uint32_t Offset = 0; }; -} // namespace codeview -} // namespace llvm -#endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREADER_H +} // end namespace msf +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_STREAMWRITER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/contrib/llvm/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h index 50f5c40..9bf0738 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h @@ -10,8 +10,11 @@ #ifndef LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H #define LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H -#include "IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/Support/Casting.h" +#include <algorithm> +#include <cstdint> #include <memory> namespace llvm { @@ -23,7 +26,7 @@ public: ConcreteSymbolEnumerator(std::unique_ptr<IPDBEnumSymbols> SymbolEnumerator) : Enumerator(std::move(SymbolEnumerator)) {} - ~ConcreteSymbolEnumerator() override {} + ~ConcreteSymbolEnumerator() override = default; uint32_t getChildCount() const override { return Enumerator->getChildCount(); @@ -55,7 +58,8 @@ private: std::unique_ptr<IPDBEnumSymbols> Enumerator; }; -} -} -#endif +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAError.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAError.h index f198d07..35a39a0 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAError.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAError.h @@ -10,10 +10,9 @@ #ifndef LLVM_DEBUGINFO_PDB_DIA_DIAERROR_H #define LLVM_DEBUGINFO_PDB_DIA_DIAERROR_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" -#include <string> - namespace llvm { namespace pdb { enum class dia_error_code { @@ -30,11 +29,11 @@ class DIAError : public ErrorInfo<DIAError> { public: static char ID; DIAError(dia_error_code C); - DIAError(const std::string &Context); - DIAError(dia_error_code C, const std::string &Context); + DIAError(StringRef Context); + DIAError(dia_error_code C, StringRef Context); void log(raw_ostream &OS) const override; - const std::string &getErrorMessage() const; + StringRef getErrorMessage() const; std::error_code convertToErrorCode() const override; private: diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/GenericError.h b/contrib/llvm/include/llvm/DebugInfo/PDB/GenericError.h index 959c261..466cb45 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/GenericError.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/GenericError.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_ERROR_H #define LLVM_DEBUGINFO_PDB_ERROR_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" namespace llvm { @@ -26,11 +27,11 @@ class GenericError : public ErrorInfo<GenericError> { public: static char ID; GenericError(generic_error_code C); - GenericError(const std::string &Context); - GenericError(generic_error_code C, const std::string &Context); + GenericError(StringRef Context); + GenericError(generic_error_code C, StringRef Context); void log(raw_ostream &OS) const override; - const std::string &getErrorMessage() const; + StringRef getErrorMessage() const; std::error_code convertToErrorCode() const override; private: diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h index 8e9f6f8..e48dc25 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h @@ -10,7 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H #define LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H -#include "PDBTypes.h" +#include <cstdint> #include <memory> namespace llvm { @@ -21,7 +21,7 @@ public: typedef std::unique_ptr<ChildType> ChildTypePtr; typedef IPDBEnumChildren<ChildType> MyType; - virtual ~IPDBEnumChildren() {} + virtual ~IPDBEnumChildren() = default; virtual uint32_t getChildCount() const = 0; virtual ChildTypePtr getChildAtIndex(uint32_t Index) const = 0; @@ -29,7 +29,8 @@ public: virtual void reset() = 0; virtual MyType *clone() const = 0; }; -} -} -#endif +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h index 3d2c37e..15e97ac 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -40,7 +40,7 @@ public: T *ConcreteSymbol = dyn_cast<T>(Symbol.get()); if (!ConcreteSymbol) return nullptr; - Symbol.release(); + (void)Symbol.release(); return std::unique_ptr<T>(ConcreteSymbol); } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBContext.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBContext.h index 836e392..84ab8ed 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBContext.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBContext.h @@ -12,14 +12,18 @@ #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" +#include <cstdint> +#include <memory> +#include <string> namespace llvm { namespace object { class COFFObjectFile; - } +} // end namespace object + +namespace pdb { - namespace pdb { /// PDBContext /// This data structure is the top level entity that deals with PDB debug /// information parsing. This data structure exists only when there is a @@ -27,20 +31,18 @@ class COFFObjectFile; /// (e.g. PDB and DWARF). More control and power over the debug information /// access can be had by using the PDB interfaces directly. class PDBContext : public DIContext { - - PDBContext(PDBContext &) = delete; - PDBContext &operator=(PDBContext &) = delete; - public: PDBContext(const object::COFFObjectFile &Object, std::unique_ptr<IPDBSession> PDBSession); + PDBContext(PDBContext &) = delete; + PDBContext &operator=(PDBContext &) = delete; static bool classof(const DIContext *DICtx) { return DICtx->getKind() == CK_PDB; } void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All, - bool DumpEH = false) override; + bool DumpEH = false, bool SummarizeTypes = false) override; DILineInfo getLineInfoForAddress( uint64_t Address, @@ -56,7 +58,9 @@ class COFFObjectFile; std::string getFunctionName(uint64_t Address, DINameKind NameKind) const; std::unique_ptr<IPDBSession> Session; }; - } -} -#endif +} // end namespace pdb + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBCONTEXT_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h index a9325a4..0d232f1 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -12,9 +12,10 @@ #include "llvm/Config/llvm-config.h" #include "llvm/DebugInfo/CodeView/CodeView.h" -#include <functional> +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" #include <cstdint> #include <cstring> +#include <functional> namespace llvm { namespace pdb { @@ -73,13 +74,6 @@ enum class PDB_ReaderType { Raw = 1, }; -/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but -/// is abstracted here for the purposes of non-Windows platforms that don't have -/// the GUID structure defined. -struct PDB_UniqueId { - char Guid[16]; -}; - /// An enumeration indicating the type of data contained in this table. enum class PDB_TableType { Symbols, diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h index 6ab3c80..c97ca32 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -11,10 +11,10 @@ #define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H #include "llvm/DebugInfo/CodeView/ModuleSubstream.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" -#include "llvm/DebugInfo/CodeView/StreamRef.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/DebugInfo/MSF/StreamRef.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" -#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/ModInfo.h" #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" @@ -36,32 +36,8 @@ class ISectionContribVisitor; class DbiStream { friend class DbiStreamBuilder; - struct HeaderInfo { - support::little32_t VersionSignature; - support::ulittle32_t VersionHeader; - support::ulittle32_t Age; // Should match InfoStream. - support::ulittle16_t GlobalSymbolStreamIndex; // Global symbol stream # - support::ulittle16_t BuildNumber; // See DbiBuildNo structure. - support::ulittle16_t PublicSymbolStreamIndex; // Public symbols stream # - support::ulittle16_t PdbDllVersion; // version of mspdbNNN.dll - support::ulittle16_t SymRecordStreamIndex; // Symbol records stream # - support::ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll - support::little32_t ModiSubstreamSize; // Size of module info stream - support::little32_t SecContrSubstreamSize; // Size of sec. contrib stream - support::little32_t SectionMapSize; // Size of sec. map substream - support::little32_t FileInfoSize; // Size of file info substream - support::little32_t TypeServerSize; // Size of type server map - support::ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server - support::little32_t OptionalDbgHdrSize; // Size of DbgHeader info - support::little32_t ECSubstreamSize; // Size of EC stream (what is EC?) - support::ulittle16_t Flags; // See DbiFlags enum. - support::ulittle16_t MachineType; // See PDB_MachineType enum. - - support::ulittle32_t Reserved; // Pad to 64 bytes - }; - public: - DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream); + DbiStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream); ~DbiStream(); Error reload(); @@ -86,8 +62,6 @@ public: PDB_Machine getMachineType() const; - enum { InvalidStreamIndex = 0xffff }; - /// If the given stream type is present, returns its stream index. If it is /// not present, returns InvalidStreamIndex. uint32_t getDebugStreamIndex(DbgHeaderType Type) const; @@ -96,16 +70,15 @@ public: Expected<StringRef> getFileNameForIndex(uint32_t Index) const; - codeview::FixedStreamArray<object::coff_section> getSectionHeaders(); + msf::FixedStreamArray<object::coff_section> getSectionHeaders(); - codeview::FixedStreamArray<object::FpoData> getFpoRecords(); + msf::FixedStreamArray<object::FpoData> getFpoRecords(); - codeview::FixedStreamArray<SecMapEntry> getSectionMap() const; + msf::FixedStreamArray<SecMapEntry> getSectionMap() const; void visitSectionContributions(ISectionContribVisitor &Visitor) const; - Error commit(); - private: + Error initializeModInfoArray(); Error initializeSectionContributionData(); Error initializeSectionHeadersData(); Error initializeSectionMapData(); @@ -113,35 +86,35 @@ private: Error initializeFpoRecords(); PDBFile &Pdb; - std::unique_ptr<MappedBlockStream> Stream; + std::unique_ptr<msf::MappedBlockStream> Stream; std::vector<ModuleInfoEx> ModuleInfos; NameHashTable ECNames; - codeview::StreamRef ModInfoSubstream; - codeview::StreamRef SecContrSubstream; - codeview::StreamRef SecMapSubstream; - codeview::StreamRef FileInfoSubstream; - codeview::StreamRef TypeServerMapSubstream; - codeview::StreamRef ECSubstream; + msf::ReadableStreamRef ModInfoSubstream; + msf::ReadableStreamRef SecContrSubstream; + msf::ReadableStreamRef SecMapSubstream; + msf::ReadableStreamRef FileInfoSubstream; + msf::ReadableStreamRef TypeServerMapSubstream; + msf::ReadableStreamRef ECSubstream; - codeview::StreamRef NamesBuffer; + msf::ReadableStreamRef NamesBuffer; - codeview::FixedStreamArray<support::ulittle16_t> DbgStreams; + msf::FixedStreamArray<support::ulittle16_t> DbgStreams; PdbRaw_DbiSecContribVer SectionContribVersion; - codeview::FixedStreamArray<SectionContrib> SectionContribs; - codeview::FixedStreamArray<SectionContrib2> SectionContribs2; - codeview::FixedStreamArray<SecMapEntry> SectionMap; - codeview::FixedStreamArray<support::little32_t> FileNameOffsets; + msf::FixedStreamArray<SectionContrib> SectionContribs; + msf::FixedStreamArray<SectionContrib2> SectionContribs2; + msf::FixedStreamArray<SecMapEntry> SectionMap; + msf::FixedStreamArray<support::little32_t> FileNameOffsets; - std::unique_ptr<MappedBlockStream> SectionHeaderStream; - codeview::FixedStreamArray<object::coff_section> SectionHeaders; + std::unique_ptr<msf::MappedBlockStream> SectionHeaderStream; + msf::FixedStreamArray<object::coff_section> SectionHeaders; - std::unique_ptr<MappedBlockStream> FpoStream; - codeview::FixedStreamArray<object::FpoData> FpoRecords; + std::unique_ptr<msf::MappedBlockStream> FpoStream; + msf::FixedStreamArray<object::FpoData> FpoRecords; - const HeaderInfo *Header; + const DbiStreamHeader *Header; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h index 2c7350f..99a3ac7 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h @@ -11,20 +11,31 @@ #define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAMBUILDER_H #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/Error.h" +#include "llvm/DebugInfo/MSF/ByteStream.h" +#include "llvm/DebugInfo/MSF/StreamReader.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/Support/Endian.h" namespace llvm { +namespace msf { +class MSFBuilder; +} +namespace object { +struct coff_section; +} namespace pdb { class DbiStream; +struct DbiStreamHeader; class PDBFile; class DbiStreamBuilder { public: - DbiStreamBuilder(); + DbiStreamBuilder(msf::MSFBuilder &Msf); DbiStreamBuilder(const DbiStreamBuilder &) = delete; DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete; @@ -36,12 +47,57 @@ public: void setPdbDllRbld(uint16_t R); void setFlags(uint16_t F); void setMachineType(PDB_Machine M); + void setSectionContribs(ArrayRef<SectionContrib> SecMap); + void setSectionMap(ArrayRef<SecMapEntry> SecMap); + + // Add given bytes as a new stream. + Error addDbgStream(pdb::DbgHeaderType Type, ArrayRef<uint8_t> Data); uint32_t calculateSerializedLength() const; - Expected<std::unique_ptr<DbiStream>> build(PDBFile &File); + Error addModuleInfo(StringRef ObjFile, StringRef Module); + Error addModuleSourceFile(StringRef Module, StringRef File); + + Error finalizeMsfLayout(); + + Error commit(const msf::MSFLayout &Layout, + const msf::WritableStream &Buffer); + + // A helper function to create Section Contributions from COFF input + // section headers. + static std::vector<SectionContrib> + createSectionContribs(ArrayRef<llvm::object::coff_section> SecHdrs); + + // A helper function to create a Section Map from a COFF section header. + static std::vector<SecMapEntry> + createSectionMap(ArrayRef<llvm::object::coff_section> SecHdrs); private: + struct DebugStream { + ArrayRef<uint8_t> Data; + uint16_t StreamNumber = 0; + }; + + Error finalize(); + uint32_t calculateModiSubstreamSize() const; + uint32_t calculateSectionContribsStreamSize() const; + uint32_t calculateSectionMapStreamSize() const; + uint32_t calculateFileInfoSubstreamSize() const; + uint32_t calculateNamesBufferSize() const; + uint32_t calculateDbgStreamsSize() const; + + Error generateModiSubstream(); + Error generateFileInfoSubstream(); + + struct ModuleInfo { + std::vector<StringRef> SourceFiles; + StringRef Obj; + StringRef Mod; + }; + + msf::MSFBuilder &Msf; + BumpPtrAllocator &Allocator; + Optional<PdbRaw_DbiVer> VerHeader; uint32_t Age; uint16_t BuildNumber; @@ -49,6 +105,20 @@ private: uint16_t PdbDllRbld; uint16_t Flags; PDB_Machine MachineType; + + const DbiStreamHeader *Header; + + StringMap<std::unique_ptr<ModuleInfo>> ModuleInfos; + std::vector<ModuleInfo *> ModuleInfoList; + + StringMap<uint32_t> SourceFileNames; + + msf::WritableStreamRef NamesBuffer; + msf::MutableByteStream ModInfoBuffer; + msf::MutableByteStream FileInfoBuffer; + ArrayRef<SectionContrib> SectionContribs; + ArrayRef<SecMapEntry> SectionMap; + llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h deleted file mode 100644 index 0f35431..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h +++ /dev/null @@ -1,37 +0,0 @@ -//===- DirectoryStreamData.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_PDB_RAW_DIRECTORYSTREAMDATA_H -#define LLVM_DEBUGINFO_PDB_RAW_DIRECTORYSTREAMDATA_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/Support/Endian.h" - -namespace llvm { -namespace pdb { -class IPDBFile; - -class DirectoryStreamData : public IPDBStreamData { -public: - DirectoryStreamData(const PDBFile &File) : File(File) {} - - virtual uint32_t getLength() { return File.getNumDirectoryBytes(); } - virtual llvm::ArrayRef<llvm::support::ulittle32_t> getStreamBlocks() { - return File.getDirectoryBlockArray(); - } - -private: - const PDBFile &File; -}; -} -} - -#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/GlobalsStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/GlobalsStream.h new file mode 100644 index 0000000..175f093 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/GlobalsStream.h @@ -0,0 +1,45 @@ +//===- GlobalsStream.h - PDB Index of Symbols by Name ------ ----*- 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_PDB_RAW_GLOBALS_STREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_GLOBALS_STREAM_H + +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class DbiStream; +class PDBFile; + +class GlobalsStream { +public: + explicit GlobalsStream(std::unique_ptr<msf::MappedBlockStream> Stream); + ~GlobalsStream(); + Error commit(); + msf::FixedStreamArray<support::ulittle32_t> getHashBuckets() const { + return HashBuckets; + } + uint32_t getNumBuckets() const { return NumBuckets; } + Error reload(); + +private: + msf::FixedStreamArray<support::ulittle32_t> HashBuckets; + msf::FixedStreamArray<PSHashRecord> HashRecords; + uint32_t NumBuckets; + std::unique_ptr<msf::MappedBlockStream> Stream; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h deleted file mode 100644 index ab3c9f7..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/IPDBStreamData.h +++ /dev/null @@ -1,38 +0,0 @@ -//===- IPDBStreamData.h - Base interface for PDB Stream 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_PDB_RAW_IPDBSTREAMDATA_H -#define LLVM_DEBUGINFO_PDB_RAW_IPDBSTREAMDATA_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Support/Endian.h" - -namespace llvm { -namespace pdb { -/// IPDBStream abstracts the notion of PDB stream data. Although we already -/// have another stream abstraction (namely in the form of StreamInterface -/// and MappedBlockStream), they assume that the stream data is referenced -/// the same way. Namely, by looking in the directory to get the list of -/// stream blocks, and by looking in the array of stream lengths to get the -/// length. This breaks down for the directory itself, however, since its -/// length and list of blocks are stored elsewhere. By abstracting the -/// notion of stream data further, we can use a MappedBlockStream to read -/// from the directory itself, or from an indexed stream which references -/// the directory. -class IPDBStreamData { -public: - virtual ~IPDBStreamData() {} - - virtual uint32_t getLength() = 0; - virtual ArrayRef<support::ulittle32_t> getStreamBlocks() = 0; -}; -} -} - -#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h index 355a25a..fb00d6a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h @@ -12,17 +12,19 @@ namespace llvm { namespace pdb { + struct SectionContrib; struct SectionContrib2; class ISectionContribVisitor { public: - virtual ~ISectionContribVisitor() {} + virtual ~ISectionContribVisitor() = default; virtual void visit(const SectionContrib &C) = 0; virtual void visit(const SectionContrib2 &C) = 0; }; -} // namespace pdb -} // namespace llvm + +} // end namespace pdb +} // end namespace llvm #endif // LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h deleted file mode 100644 index 30563bc..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/IndexedStreamData.h +++ /dev/null @@ -1,34 +0,0 @@ -//===- IndexedStreamData.h - Standard PDB Stream 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_PDB_RAW_INDEXEDSTREAMDATA_H -#define LLVM_DEBUGINFO_PDB_RAW_INDEXEDSTREAMDATA_H - -#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" - -namespace llvm { -namespace pdb { -class IPDBFile; - -class IndexedStreamData : public IPDBStreamData { -public: - IndexedStreamData(uint32_t StreamIdx, const IPDBFile &File); - virtual ~IndexedStreamData() {} - - uint32_t getLength() override; - ArrayRef<support::ulittle32_t> getStreamBlocks() override; - -private: - uint32_t StreamIdx; - const IPDBFile &File; -}; -} -} - -#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h index 1980bec..6b8b94f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h @@ -11,8 +11,8 @@ #define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H #include "llvm/ADT/StringMap.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" -#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/NameMap.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" @@ -27,18 +27,10 @@ class PDBFile; class InfoStream { friend class InfoStreamBuilder; - struct HeaderInfo { - support::ulittle32_t Version; - support::ulittle32_t Signature; - support::ulittle32_t Age; - PDB_UniqueId Guid; - }; - public: - InfoStream(std::unique_ptr<MappedBlockStream> Stream); + InfoStream(std::unique_ptr<msf::MappedBlockStream> Stream); Error reload(); - Error commit(); PdbRaw_ImplVer getVersion() const; uint32_t getSignature() const; @@ -49,7 +41,7 @@ public: iterator_range<StringMapConstIterator<uint32_t>> named_streams() const; private: - std::unique_ptr<MappedBlockStream> Stream; + std::unique_ptr<msf::MappedBlockStream> Stream; // PDB file format version. We only support VC70. See the enumeration // `PdbRaw_ImplVer` for the other possible values. diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h index e9869bb..cb60b1e 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h @@ -19,12 +19,16 @@ #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" namespace llvm { +namespace msf { +class MSFBuilder; +class StreamWriter; +} namespace pdb { class PDBFile; class InfoStreamBuilder { public: - InfoStreamBuilder(); + InfoStreamBuilder(msf::MSFBuilder &Msf); InfoStreamBuilder(const InfoStreamBuilder &) = delete; InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete; @@ -37,13 +41,18 @@ public: uint32_t calculateSerializedLength() const; - Expected<std::unique_ptr<InfoStream>> build(PDBFile &File); + Error finalizeMsfLayout(); + + Error commit(const msf::MSFLayout &Layout, + const msf::WritableStream &Buffer) const; private: - Optional<PdbRaw_ImplVer> Ver; - Optional<uint32_t> Sig; - Optional<uint32_t> Age; - Optional<PDB_UniqueId> Guid; + msf::MSFBuilder &Msf; + + PdbRaw_ImplVer Ver; + uint32_t Sig; + uint32_t Age; + PDB_UniqueId Guid; NameMapBuilder NamedStreams; }; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h deleted file mode 100644 index 36424c0..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h +++ /dev/null @@ -1,68 +0,0 @@ -//===- MappedBlockStream.h - Reads stream data from a PDBFile ---*- 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_PDB_RAW_MAPPEDBLOCKSTREAM_H -#define LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" -#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <cstdint> -#include <vector> - -namespace llvm { -namespace pdb { - -class IPDBFile; -class PDBFile; - -class MappedBlockStream : public codeview::StreamInterface { -public: - 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; - - uint32_t getNumBytesCopied() const; - - static Expected<std::unique_ptr<MappedBlockStream>> - createIndexedStream(uint32_t StreamIdx, const IPDBFile &File); - static Expected<std::unique_ptr<MappedBlockStream>> - createDirectoryStream(const PDBFile &File); - - llvm::BumpPtrAllocator &getAllocator() { return Pool; } - -protected: - MappedBlockStream(std::unique_ptr<IPDBStreamData> Data, const IPDBFile &File); - - Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const; - bool tryReadContiguously(uint32_t Offset, uint32_t Size, - ArrayRef<uint8_t> &Buffer) const; - - const IPDBFile &Pdb; - std::unique_ptr<IPDBStreamData> Data; - - typedef MutableArrayRef<uint8_t> CacheEntry; - mutable llvm::BumpPtrAllocator Pool; - mutable DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap; -}; - -} // end namespace pdb -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_PDB_RAW_MAPPEDBLOCKSTREAM_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h index b8da0bf..bf5cf53 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h @@ -11,24 +11,26 @@ #define LLVM_DEBUGINFO_PDB_RAW_MODINFO_H #include "llvm/ADT/StringRef.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/DebugInfo/PDB/Raw/RawTypes.h" +#include "llvm/Support/Error.h" #include <cstdint> #include <vector> namespace llvm { + namespace pdb { class ModInfo { -private: - struct FileLayout; + friend class DbiStreamBuilder; public: ModInfo(); ModInfo(const ModInfo &Info); ~ModInfo(); - static Error initialize(codeview::StreamRef Stream, ModInfo &Info); + static Error initialize(msf::ReadableStreamRef Stream, ModInfo &Info); bool hasECInfo() const; uint16_t getTypeServerIndex() const; @@ -48,13 +50,12 @@ public: private: StringRef ModuleName; StringRef ObjFileName; - const FileLayout *Layout; + const ModuleInfoHeader *Layout = nullptr; }; struct ModuleInfoEx { ModuleInfoEx(const ModInfo &Info) : Info(Info) {} - ModuleInfoEx(const ModuleInfoEx &Ex) - : Info(Ex.Info), SourceFiles(Ex.SourceFiles) {} + ModuleInfoEx(const ModuleInfoEx &Ex) = default; ModInfo Info; std::vector<StringRef> SourceFiles; @@ -62,9 +63,10 @@ struct ModuleInfoEx { } // end namespace pdb -namespace codeview { +namespace msf { + template <> struct VarStreamArrayExtractor<pdb::ModInfo> { - Error operator()(StreamRef Stream, uint32_t &Length, + Error operator()(ReadableStreamRef Stream, uint32_t &Length, pdb::ModInfo &Info) const { if (auto EC = pdb::ModInfo::initialize(Stream, Info)) return EC; @@ -72,7 +74,8 @@ template <> struct VarStreamArrayExtractor<pdb::ModInfo> { return Error::success(); } }; -} + +} // end namespace msf } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h index d22962c..d5e7a68 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h @@ -13,10 +13,10 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/ModuleSubstream.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" -#include "llvm/DebugInfo/CodeView/StreamRef.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/DebugInfo/MSF/StreamRef.h" #include "llvm/Support/Error.h" namespace llvm { @@ -26,11 +26,14 @@ class ModInfo; class ModStream { public: - ModStream(const ModInfo &Module, std::unique_ptr<MappedBlockStream> Stream); + ModStream(const ModInfo &Module, + std::unique_ptr<msf::MappedBlockStream> Stream); ~ModStream(); Error reload(); + uint32_t signature() const { return Signature; } + iterator_range<codeview::CVSymbolArray::Iterator> symbols(bool *HadError) const; @@ -42,12 +45,14 @@ public: private: const ModInfo &Mod; - std::unique_ptr<MappedBlockStream> Stream; + uint32_t Signature; + + std::unique_ptr<msf::MappedBlockStream> Stream; codeview::CVSymbolArray SymbolsSubstream; - codeview::StreamRef LinesSubstream; - codeview::StreamRef C13LinesSubstream; - codeview::StreamRef GlobalRefsSubstream; + msf::ReadableStreamRef LinesSubstream; + msf::ReadableStreamRef C13LinesSubstream; + msf::ReadableStreamRef GlobalRefsSubstream; codeview::ModuleSubstreamArray LineInfo; }; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h index c9e060a..00d022d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h @@ -12,15 +12,15 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.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" #include <cstdint> #include <vector> namespace llvm { -namespace codeview { +namespace msf { class StreamReader; } namespace pdb { @@ -29,7 +29,7 @@ class NameHashTable { public: NameHashTable(); - Error load(codeview::StreamReader &Stream); + Error load(msf::StreamReader &Stream); uint32_t getNameCount() const { return NameCount; } uint32_t getHashVersion() const { return HashVersion; } @@ -38,11 +38,11 @@ public: StringRef getStringForID(uint32_t ID) const; uint32_t getIDForString(StringRef Str) const; - codeview::FixedStreamArray<support::ulittle32_t> name_ids() const; + msf::FixedStreamArray<support::ulittle32_t> name_ids() const; private: - codeview::StreamRef NamesBuffer; - codeview::FixedStreamArray<support::ulittle32_t> IDs; + msf::ReadableStreamRef NamesBuffer; + msf::FixedStreamArray<support::ulittle32_t> IDs; uint32_t Signature; uint32_t HashVersion; uint32_t NameCount; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h index 8a9b0d1..de1163b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h @@ -16,7 +16,7 @@ #include <cstdint> namespace llvm { -namespace codeview { +namespace msf { class StreamReader; class StreamWriter; } @@ -28,8 +28,7 @@ class NameMap { public: NameMap(); - Error load(codeview::StreamReader &Stream); - Error commit(codeview::StreamWriter &Writer); + Error load(msf::StreamReader &Stream); bool tryGetValue(StringRef Name, uint32_t &Value) const; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h index bf49bfd..f5244ac 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h @@ -17,6 +17,9 @@ #include <memory> namespace llvm { +namespace msf { +class StreamWriter; +} namespace pdb { class NameMap; @@ -27,6 +30,7 @@ public: void addMapping(StringRef Name, uint32_t Mapping); Expected<std::unique_ptr<NameMap>> build(); + Error commit(msf::StreamWriter &Writer) const; uint32_t calculateSerializedLength() const; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h index f4d7eb4..29f5b21 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -11,10 +11,10 @@ #define LLVM_DEBUGINFO_PDB_RAW_PDBFILE_H #include "llvm/ADT/DenseMap.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" -#include "llvm/DebugInfo/PDB/Raw/IPDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h" +#include "llvm/DebugInfo/MSF/IMSFFile.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/DebugInfo/MSF/StreamInterface.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -24,25 +24,26 @@ namespace llvm { -namespace codeview { -class StreamInterface; +namespace msf { +class MappedBlockStream; } namespace pdb { class DbiStream; +class GlobalsStream; class InfoStream; -class MappedBlockStream; class NameHashTable; class PDBFileBuilder; class PublicsStream; class SymbolStream; class TpiStream; -class PDBFile : public IPDBFile { +class PDBFile : public msf::IMSFFile { friend PDBFileBuilder; public: - explicit PDBFile(std::unique_ptr<codeview::StreamInterface> PdbFileBuffer); + PDBFile(std::unique_ptr<msf::ReadableStream> PdbFileBuffer, + BumpPtrAllocator &Allocator); ~PDBFile() override; uint32_t getFreeBlockMapBlock() const; @@ -66,11 +67,18 @@ public: Error setBlockData(uint32_t BlockIndex, uint32_t Offset, ArrayRef<uint8_t> Data) const override; - ArrayRef<support::ulittle32_t> getStreamSizes() const { return StreamSizes; } + ArrayRef<uint32_t> getFpmPages() const { return FpmPages; } + + ArrayRef<support::ulittle32_t> getStreamSizes() const { + return ContainerLayout.StreamSizes; + } ArrayRef<ArrayRef<support::ulittle32_t>> getStreamMap() const { - return StreamMap; + return ContainerLayout.StreamMap; } + const msf::MSFLayout &getMsfLayout() const { return ContainerLayout; } + const msf::ReadableStream &getMsfBuffer() const { return *Buffer; } + ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const; Error parseFileHeaders(); @@ -78,33 +86,45 @@ public: Expected<InfoStream &> getPDBInfoStream(); Expected<DbiStream &> getPDBDbiStream(); + Expected<GlobalsStream &> getPDBGlobalsStream(); Expected<TpiStream &> getPDBTpiStream(); Expected<TpiStream &> getPDBIpiStream(); Expected<PublicsStream &> getPDBPublicsStream(); Expected<SymbolStream &> getPDBSymbolStream(); Expected<NameHashTable &> getStringTable(); - Error commit(); + BumpPtrAllocator &getAllocator() { return Allocator; } + + bool hasPDBDbiStream() const; + bool hasPDBGlobalsStream(); + bool hasPDBInfoStream(); + bool hasPDBIpiStream() const; + bool hasPDBPublicsStream(); + bool hasPDBSymbolStream(); + bool hasPDBTpiStream() const; + bool hasStringTable(); + + private: + Expected<std::unique_ptr<msf::MappedBlockStream>> safelyCreateIndexedStream( + const msf::MSFLayout &Layout, const msf::ReadableStream &MsfData, + uint32_t StreamIndex) const; -private: - Error setSuperBlock(const msf::SuperBlock *Block); + BumpPtrAllocator &Allocator; - BumpPtrAllocator Allocator; + std::unique_ptr<msf::ReadableStream> Buffer; - std::unique_ptr<codeview::StreamInterface> Buffer; - const msf::SuperBlock *SB; - ArrayRef<support::ulittle32_t> StreamSizes; - ArrayRef<support::ulittle32_t> DirectoryBlocks; - std::vector<ArrayRef<support::ulittle32_t>> StreamMap; + std::vector<uint32_t> FpmPages; + msf::MSFLayout ContainerLayout; + std::unique_ptr<GlobalsStream> Globals; std::unique_ptr<InfoStream> Info; std::unique_ptr<DbiStream> Dbi; std::unique_ptr<TpiStream> Tpi; std::unique_ptr<TpiStream> Ipi; std::unique_ptr<PublicsStream> Publics; std::unique_ptr<SymbolStream> Symbols; - std::unique_ptr<MappedBlockStream> DirectoryStream; - std::unique_ptr<MappedBlockStream> StringTableStream; + std::unique_ptr<msf::MappedBlockStream> DirectoryStream; + std::unique_ptr<msf::MappedBlockStream> StringTableStream; std::unique_ptr<NameHashTable> StringTable; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h index 47c755b..27fc4b5 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h @@ -13,45 +13,50 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" -#include "llvm/DebugInfo/PDB/Raw/MsfBuilder.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" - #include <memory> #include <vector> namespace llvm { -namespace codeview { -class StreamInterface; +namespace msf { +class MSFBuilder; } namespace pdb { class DbiStreamBuilder; class InfoStreamBuilder; -class PDBFile; +class TpiStreamBuilder; class PDBFileBuilder { public: - explicit PDBFileBuilder( - std::unique_ptr<codeview::StreamInterface> FileBuffer); + explicit PDBFileBuilder(BumpPtrAllocator &Allocator); PDBFileBuilder(const PDBFileBuilder &) = delete; PDBFileBuilder &operator=(const PDBFileBuilder &) = delete; - Error initialize(const msf::SuperBlock &Super); + Error initialize(uint32_t BlockSize); - MsfBuilder &getMsfBuilder(); + msf::MSFBuilder &getMsfBuilder(); InfoStreamBuilder &getInfoBuilder(); DbiStreamBuilder &getDbiBuilder(); + TpiStreamBuilder &getTpiBuilder(); + TpiStreamBuilder &getIpiBuilder(); - Expected<std::unique_ptr<PDBFile>> build(); + Error commit(StringRef Filename); private: + Expected<msf::MSFLayout> finalizeMsfLayout() const; + + BumpPtrAllocator &Allocator; + + std::unique_ptr<msf::MSFBuilder> Msf; std::unique_ptr<InfoStreamBuilder> Info; std::unique_ptr<DbiStreamBuilder> Dbi; - - std::unique_ptr<PDBFile> File; - std::unique_ptr<MsfBuilder> Msf; + std::unique_ptr<TpiStreamBuilder> Tpi; + std::unique_ptr<TpiStreamBuilder> Ipi; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h index f5bfb0e..577f298 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h @@ -10,10 +10,10 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H #define LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H -#include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" -#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" #include "llvm/DebugInfo/PDB/Raw/RawTypes.h" @@ -22,14 +22,14 @@ namespace llvm { namespace pdb { class DbiStream; +struct GSIHashHeader; class PDBFile; class PublicsStream { - struct GSIHashHeader; struct HeaderInfo; public: - PublicsStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream); + PublicsStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream); ~PublicsStream(); Error reload(); @@ -38,16 +38,16 @@ public: uint32_t getNumBuckets() const { return NumBuckets; } iterator_range<codeview::CVSymbolArray::Iterator> getSymbols(bool *HadError) const; - codeview::FixedStreamArray<support::ulittle32_t> getHashBuckets() const { + msf::FixedStreamArray<support::ulittle32_t> getHashBuckets() const { return HashBuckets; } - codeview::FixedStreamArray<support::ulittle32_t> getAddressMap() const { + msf::FixedStreamArray<support::ulittle32_t> getAddressMap() const { return AddressMap; } - codeview::FixedStreamArray<support::ulittle32_t> getThunkMap() const { + msf::FixedStreamArray<support::ulittle32_t> getThunkMap() const { return ThunkMap; } - codeview::FixedStreamArray<SectionOffset> getSectionOffsets() const { + msf::FixedStreamArray<SectionOffset> getSectionOffsets() const { return SectionOffsets; } @@ -56,14 +56,14 @@ public: private: PDBFile &Pdb; - std::unique_ptr<MappedBlockStream> Stream; + std::unique_ptr<msf::MappedBlockStream> Stream; uint32_t NumBuckets = 0; ArrayRef<uint8_t> Bitmap; - codeview::FixedStreamArray<PSHashRecord> HashRecords; - codeview::FixedStreamArray<support::ulittle32_t> HashBuckets; - codeview::FixedStreamArray<support::ulittle32_t> AddressMap; - codeview::FixedStreamArray<support::ulittle32_t> ThunkMap; - codeview::FixedStreamArray<SectionOffset> SectionOffsets; + msf::FixedStreamArray<PSHashRecord> HashRecords; + msf::FixedStreamArray<support::ulittle32_t> HashBuckets; + msf::FixedStreamArray<support::ulittle32_t> AddressMap; + msf::FixedStreamArray<support::ulittle32_t> ThunkMap; + msf::FixedStreamArray<SectionOffset> SectionOffsets; const HeaderInfo *Header; const GSIHashHeader *HashHdr; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawConstants.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawConstants.h index 8daaf47..af114ff 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawConstants.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawConstants.h @@ -17,6 +17,8 @@ namespace llvm { namespace pdb { +const uint16_t kInvalidStreamIndex = 0xFFFF; + enum PdbRaw_ImplVer : uint32_t { PdbImplVC2 = 19941610, PdbImplVC4 = 19950623, @@ -61,6 +63,8 @@ enum SpecialStream : uint32_t { StreamTPI = 2, StreamDBI = 3, StreamIPI = 4, + + kSpecialStreamCount }; enum class DbgHeaderType : uint16_t { diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h index b0687cd..f96b806 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h @@ -19,11 +19,14 @@ namespace pdb { enum class raw_error_code { unspecified = 1, feature_unsupported, + invalid_format, corrupt_file, insufficient_buffer, no_stream, index_out_of_bounds, invalid_block_address, + duplicate_entry, + no_entry, not_writable, invalid_tpi_hash, }; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawSession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawSession.h index 73d281e..5a6c469 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawSession.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawSession.h @@ -12,6 +12,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/Error.h" namespace llvm { @@ -20,7 +21,8 @@ class PDBFile; class RawSession : public IPDBSession { public: - explicit RawSession(std::unique_ptr<PDBFile> PdbFile); + RawSession(std::unique_ptr<PDBFile> PdbFile, + std::unique_ptr<BumpPtrAllocator> Allocator); ~RawSession() override; static Error createFromPdb(StringRef Path, @@ -68,6 +70,7 @@ public: private: std::unique_ptr<PDBFile> Pdb; + std::unique_ptr<BumpPtrAllocator> Allocator; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h index afcfe94..d404b39 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h @@ -80,6 +80,228 @@ struct TypeIndexOffset { support::ulittle32_t Offset; }; +/// Some of the values are stored in bitfields. Since this needs to be portable +/// across compilers and architectures (big / little endian in particular) we +/// can't use the actual structures below, but must instead do the shifting +/// and masking ourselves. The struct definitions are provided for reference. +struct DbiFlags { + /// uint16_t IncrementalLinking : 1; // True if linked incrementally + /// uint16_t IsStripped : 1; // True if private symbols were + /// stripped. + /// uint16_t HasCTypes : 1; // True if linked with /debug:ctypes. + /// uint16_t Reserved : 13; + static const uint16_t FlagIncrementalMask = 0x0001; + static const uint16_t FlagStrippedMask = 0x0002; + static const uint16_t FlagHasCTypesMask = 0x0004; +}; + +struct DbiBuildNo { + /// uint16_t MinorVersion : 8; + /// uint16_t MajorVersion : 7; + /// uint16_t NewVersionFormat : 1; + static const uint16_t BuildMinorMask = 0x00FF; + static const uint16_t BuildMinorShift = 0; + + static const uint16_t BuildMajorMask = 0x7F00; + static const uint16_t BuildMajorShift = 8; +}; + +/// The fixed size header that appears at the beginning of the DBI Stream. +struct DbiStreamHeader { + support::little32_t VersionSignature; + support::ulittle32_t VersionHeader; + + /// How "old" is this DBI Stream. Should match the age of the PDB InfoStream. + support::ulittle32_t Age; + + /// Global symbol stream # + support::ulittle16_t GlobalSymbolStreamIndex; + + /// See DbiBuildNo structure. + support::ulittle16_t BuildNumber; + + /// Public symbols stream # + support::ulittle16_t PublicSymbolStreamIndex; + + /// version of mspdbNNN.dll + support::ulittle16_t PdbDllVersion; + + /// Symbol records stream # + support::ulittle16_t SymRecordStreamIndex; + + /// rbld number of mspdbNNN.dll + support::ulittle16_t PdbDllRbld; + + /// Size of module info stream + support::little32_t ModiSubstreamSize; + + /// Size of sec. contrib stream + support::little32_t SecContrSubstreamSize; + + /// Size of sec. map substream + support::little32_t SectionMapSize; + + /// Size of file info substream + support::little32_t FileInfoSize; + + /// Size of type server map + support::little32_t TypeServerSize; + + /// Index of MFC Type Server + support::ulittle32_t MFCTypeServerIndex; + + /// Size of DbgHeader info + support::little32_t OptionalDbgHdrSize; + + /// Size of EC stream (what is EC?) + support::little32_t ECSubstreamSize; + + /// See DbiFlags enum. + support::ulittle16_t Flags; + + /// See PDB_MachineType enum. + support::ulittle16_t MachineType; + + /// Pad to 64 bytes + support::ulittle32_t Reserved; +}; +static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!"); + +struct SectionContribEntry { + support::ulittle16_t Section; + char Padding1[2]; + support::little32_t Offset; + support::little32_t Size; + support::ulittle32_t Characteristics; + support::ulittle16_t ModuleIndex; + char Padding2[2]; + support::ulittle32_t DataCrc; + support::ulittle32_t RelocCrc; +}; + +/// The header preceeding the File Info Substream of the DBI stream. +struct FileInfoSubstreamHeader { + /// Total # of modules, should match number of records in the ModuleInfo + /// substream. + support::ulittle16_t NumModules; + + /// Total # of source files. This value is not accurate because PDB actually + /// supports more than 64k source files, so we ignore it and compute the value + /// from other stream fields. + support::ulittle16_t NumSourceFiles; + + /// Following this header the File Info Substream is laid out as follows: + /// ulittle16_t ModIndices[NumModules]; + /// ulittle16_t ModFileCounts[NumModules]; + /// ulittle32_t FileNameOffsets[NumSourceFiles]; + /// char Names[][NumSourceFiles]; + /// with the caveat that `NumSourceFiles` cannot be trusted, so + /// it is computed by summing the `ModFileCounts` array. +}; + +struct ModInfoFlags { + /// uint16_t fWritten : 1; // True if ModInfo is dirty + /// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?) + /// uint16_t unused : 6; // Reserved + /// uint16_t iTSM : 8; // Type Server Index for this module + static const uint16_t HasECFlagMask = 0x2; + + static const uint16_t TypeServerIndexMask = 0xFF00; + static const uint16_t TypeServerIndexShift = 8; +}; + +/// The header preceeding each entry in the Module Info substream of the DBI +/// stream. +struct ModuleInfoHeader { + /// Currently opened module. This field is a pointer in the reference + /// implementation, but that won't work on 64-bit systems, and anyway it + /// doesn't make sense to read a pointer from a file. For now it is unused, + /// so just ignore it. + support::ulittle32_t Mod; + + /// First section contribution of this module. + SectionContribEntry SC; + + /// See ModInfoFlags definition. + support::ulittle16_t Flags; + + /// Stream Number of module debug info + support::ulittle16_t ModDiStream; + + /// Size of local symbol debug info in above stream + support::ulittle32_t SymBytes; + + /// Size of line number debug info in above stream + support::ulittle32_t LineBytes; + + /// Size of C13 line number info in above stream + support::ulittle32_t C13Bytes; + + /// Number of files contributing to this module + support::ulittle16_t NumFiles; + + /// Padding so the next field is 4-byte aligned. + char Padding1[2]; + + /// Array of [0..NumFiles) DBI name buffer offsets. This field is a pointer + /// in the reference implementation, but as with `Mod`, we ignore it for now + /// since it is unused. + support::ulittle32_t FileNameOffs; + + /// Name Index for src file name + support::ulittle32_t SrcFileNameNI; + + /// Name Index for path to compiler PDB + support::ulittle32_t PdbFilePathNI; + + /// Following this header are two zero terminated strings. + /// char ModuleName[]; + /// char ObjFileName[]; +}; + +/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but +/// is abstracted here for the purposes of non-Windows platforms that don't have +/// the GUID structure defined. +struct PDB_UniqueId { + uint8_t Guid[16]; +}; + +// The header preceeding the global TPI stream. +// This corresponds to `HDR` in PDB/dbi/tpi.h. +struct TpiStreamHeader { + struct EmbeddedBuf { + support::little32_t Off; + support::ulittle32_t Length; + }; + + support::ulittle32_t Version; + support::ulittle32_t HeaderSize; + support::ulittle32_t TypeIndexBegin; + support::ulittle32_t TypeIndexEnd; + support::ulittle32_t TypeRecordBytes; + + // The following members correspond to `TpiHash` in PDB/dbi/tpi.h. + support::ulittle16_t HashStreamIndex; + support::ulittle16_t HashAuxStreamIndex; + support::ulittle32_t HashKeySize; + support::ulittle32_t NumHashBuckets; + + EmbeddedBuf HashValueBuffer; + EmbeddedBuf IndexOffsetBuffer; + EmbeddedBuf HashAdjBuffer; +}; + +const uint32_t MinTpiHashBuckets = 0x1000; +const uint32_t MaxTpiHashBuckets = 0x40000; + +/// The header preceeding the global PDB Stream (Stream 1) +struct InfoStreamHeader { + support::ulittle32_t Version; + support::ulittle32_t Signature; + support::ulittle32_t Age; + PDB_UniqueId Guid; +}; + } // namespace pdb } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h index 685a234..41d5e6a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h @@ -10,19 +10,20 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H #define LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H -#include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/Support/Error.h" namespace llvm { +namespace msf { +class MappedBlockStream; +} namespace pdb { class PDBFile; class SymbolStream { public: - SymbolStream(std::unique_ptr<MappedBlockStream> Stream); + SymbolStream(std::unique_ptr<msf::MappedBlockStream> Stream); ~SymbolStream(); Error reload(); @@ -33,7 +34,7 @@ public: private: codeview::CVSymbolArray SymbolRecords; - std::unique_ptr<MappedBlockStream> Stream; + std::unique_ptr<msf::MappedBlockStream> Stream; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiHashing.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiHashing.h new file mode 100644 index 0000000..67a4952 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiHashing.h @@ -0,0 +1,95 @@ +//===- TpiHashing.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_PDB_TPIHASHING_H +#define LLVM_DEBUGINFO_PDB_TPIHASHING_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/DebugInfo/PDB/Raw/RawError.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <string> + +namespace llvm { +namespace pdb { + +class TpiHashUpdater : public codeview::TypeVisitorCallbacks { +public: + TpiHashUpdater() = default; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + virtual Error visitKnownRecord(codeview::CVType &CVR, \ + codeview::Name##Record &Record) override { \ + visitKnownRecordImpl(CVR, Record); \ + return Error::success(); \ + } +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/TypeRecords.def" + +private: + template <typename RecordKind> + void visitKnownRecordImpl(codeview::CVType &CVR, RecordKind &Record) { + CVR.Hash = 0; + } + + void visitKnownRecordImpl(codeview::CVType &CVR, + codeview::UdtSourceLineRecord &Rec); + void visitKnownRecordImpl(codeview::CVType &CVR, + codeview::UdtModSourceLineRecord &Rec); + void visitKnownRecordImpl(codeview::CVType &CVR, codeview::ClassRecord &Rec); + void visitKnownRecordImpl(codeview::CVType &CVR, codeview::EnumRecord &Rec); + void visitKnownRecordImpl(codeview::CVType &CVR, codeview::UnionRecord &Rec); +}; + +class TpiHashVerifier : public codeview::TypeVisitorCallbacks { +public: + TpiHashVerifier(msf::FixedStreamArray<support::ulittle32_t> &HashValues, + uint32_t NumHashBuckets) + : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {} + + Error visitKnownRecord(codeview::CVType &CVR, + codeview::UdtSourceLineRecord &Rec) override; + Error visitKnownRecord(codeview::CVType &CVR, + codeview::UdtModSourceLineRecord &Rec) override; + Error visitKnownRecord(codeview::CVType &CVR, + codeview::ClassRecord &Rec) override; + Error visitKnownRecord(codeview::CVType &CVR, + codeview::EnumRecord &Rec) override; + Error visitKnownRecord(codeview::CVType &CVR, + codeview::UnionRecord &Rec) override; + Error visitTypeBegin(codeview::CVType &CVR) override; + +private: + Error verifySourceLine(codeview::TypeIndex TI); + + Error errorInvalidHash() { + return make_error<RawError>( + raw_error_code::invalid_tpi_hash, + "Type index is 0x" + + utohexstr(codeview::TypeIndex::FirstNonSimpleIndex + Index)); + } + + msf::FixedStreamArray<support::ulittle32_t> HashValues; + codeview::CVType RawRecord; + uint32_t NumHashBuckets; + uint32_t Index = -1; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_TPIHASHING_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStream.h index 4f36d70..de21abe 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStream.h @@ -10,11 +10,9 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H #define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H -#include "llvm/DebugInfo/CodeView/StreamArray.h" -#include "llvm/DebugInfo/CodeView/StreamRef.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/MSF/StreamArray.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" -#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Raw/RawConstants.h" #include "llvm/DebugInfo/PDB/Raw/RawTypes.h" #include "llvm/Support/raw_ostream.h" @@ -22,14 +20,18 @@ #include "llvm/Support/Error.h" namespace llvm { +namespace msf { +class MappedBlockStream; +} namespace pdb { class PDBFile; class TpiStream { - struct HeaderInfo; + friend class TpiStreamBuilder; public: - TpiStream(const PDBFile &File, std::unique_ptr<MappedBlockStream> Stream); + TpiStream(const PDBFile &File, + std::unique_ptr<msf::MappedBlockStream> Stream); ~TpiStream(); Error reload(); @@ -43,9 +45,9 @@ public: uint32_t getHashKeySize() const; uint32_t NumHashBuckets() const; - codeview::FixedStreamArray<support::ulittle32_t> getHashValues() const; - codeview::FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const; - codeview::FixedStreamArray<TypeIndexOffset> getHashAdjustments() const; + msf::FixedStreamArray<support::ulittle32_t> getHashValues() const; + msf::FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const; + msf::FixedStreamArray<TypeIndexOffset> getHashAdjustments() const; iterator_range<codeview::CVTypeArray::Iterator> types(bool *HadError) const; @@ -55,16 +57,16 @@ private: Error verifyHashValues(); const PDBFile &Pdb; - std::unique_ptr<MappedBlockStream> Stream; + std::unique_ptr<msf::MappedBlockStream> Stream; codeview::CVTypeArray TypeRecords; - std::unique_ptr<MappedBlockStream> HashStream; - codeview::FixedStreamArray<support::ulittle32_t> HashValues; - codeview::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets; - codeview::FixedStreamArray<TypeIndexOffset> HashAdjustments; + std::unique_ptr<msf::ReadableStream> HashStream; + msf::FixedStreamArray<support::ulittle32_t> HashValues; + msf::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets; + msf::FixedStreamArray<TypeIndexOffset> HashAdjustments; - const HeaderInfo *Header; + const TpiStreamHeader *Header; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h new file mode 100644 index 0000000..f9a6421 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h @@ -0,0 +1,82 @@ +//===- TpiStreamBuilder.h - PDB Tpi Stream Creation -------------*- 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_PDB_RAW_PDBTPISTREAMBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAMBUILDER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/MSF/ByteStream.h" +#include "llvm/DebugInfo/MSF/SequencedItemStream.h" +#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" + +#include <vector> + +namespace llvm { +namespace codeview { +class TypeRecord; +} +namespace msf { +class ByteStream; +class MSFBuilder; +struct MSFLayout; +class ReadableStreamRef; +class WritableStream; + +template <> struct SequencedItemTraits<llvm::codeview::CVType> { + static size_t length(const codeview::CVType &Item) { return Item.length(); } + static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) { + return Item.data(); + } +}; +} +namespace pdb { +class PDBFile; +class TpiStream; +struct TpiStreamHeader; + +class TpiStreamBuilder { +public: + explicit TpiStreamBuilder(msf::MSFBuilder &Msf, uint32_t StreamIdx); + ~TpiStreamBuilder(); + + TpiStreamBuilder(const TpiStreamBuilder &) = delete; + TpiStreamBuilder &operator=(const TpiStreamBuilder &) = delete; + + void setVersionHeader(PdbRaw_TpiVer Version); + void addTypeRecord(const codeview::CVType &Record); + + Error finalizeMsfLayout(); + + Error commit(const msf::MSFLayout &Layout, const msf::WritableStream &Buffer); + + uint32_t calculateSerializedLength() const; + +private: + uint32_t calculateHashBufferSize() const; + Error finalize(); + + msf::MSFBuilder &Msf; + BumpPtrAllocator &Allocator; + + Optional<PdbRaw_TpiVer> VerHeader; + std::vector<codeview::CVType> TypeRecords; + msf::SequencedItemStream<codeview::CVType> TypeRecordStream; + uint32_t HashStreamIndex = kInvalidStreamIndex; + std::unique_ptr<msf::ByteStream> HashValueStream; + + const TpiStreamHeader *Header; + uint32_t Idx; +}; +} +} + +#endif |