diff options
Diffstat (limited to 'contrib/llvm/include/llvm/DebugInfo/CodeView')
56 files changed, 2283 insertions, 802 deletions
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h index a327d45..44040e0 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -14,8 +14,9 @@ #include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/MSF/StreamRef.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <cstdint> @@ -26,12 +27,19 @@ namespace codeview { template <typename Kind> class CVRecord { public: - CVRecord() = default; + CVRecord() : Type(static_cast<Kind>(0)) {} + CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {} + bool valid() const { return Type != static_cast<Kind>(0); } + uint32_t length() const { return RecordData.size(); } Kind kind() const { return Type; } ArrayRef<uint8_t> data() const { return RecordData; } + StringRef str_data() const { + return StringRef(reinterpret_cast<const char *>(RecordData.data()), + RecordData.size()); + } ArrayRef<uint8_t> content() const { return RecordData.drop_front(sizeof(RecordPrefix)); @@ -46,17 +54,22 @@ public: Optional<uint32_t> Hash; }; -} // end namespace codeview +template <typename Kind> struct RemappedRecord { + explicit RemappedRecord(const CVRecord<Kind> &R) : OriginalRecord(R) {} -namespace msf { + CVRecord<Kind> OriginalRecord; + SmallVector<std::pair<uint32_t, TypeIndex>, 8> Mappings; +}; + +} // end namespace codeview template <typename Kind> struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> { - Error operator()(ReadableStreamRef Stream, uint32_t &Len, - codeview::CVRecord<Kind> &Item) const { + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + codeview::CVRecord<Kind> &Item) { using namespace codeview; const RecordPrefix *Prefix = nullptr; - StreamReader Reader(Stream); + BinaryStreamReader Reader(Stream); uint32_t Offset = Reader.getOffset(); if (auto EC = Reader.readObject(Prefix)) @@ -76,8 +89,6 @@ struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> { } }; -} // 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 b2d3f5e..7c8cd12 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h @@ -25,7 +25,9 @@ public: CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks); Error visitSymbolRecord(CVSymbol &Record); + Error visitSymbolRecord(CVSymbol &Record, uint32_t Offset); Error visitSymbolStream(const CVSymbolArray &Symbols); + Error visitSymbolStream(const CVSymbolArray &Symbols, uint32_t InitialOffset); private: SymbolVisitorCallbacks &Callbacks; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeDumper.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeDumper.h deleted file mode 100644 index e1dd6a1..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeDumper.h +++ /dev/null @@ -1,56 +0,0 @@ -//===-- 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 d1b0363..df55e18 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -10,32 +10,42 @@ #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" #include "llvm/Support/Error.h" namespace llvm { namespace codeview { +class TypeCollection; +class TypeVisitorCallbacks; + +enum VisitorDataSource { + VDS_BytesPresent, // The record bytes are passed into the the visitation + // function. The algorithm should first deserialize them + // before passing them on through the pipeline. + VDS_BytesExternal // The record bytes are not present, and it is the + // responsibility of the visitor callback interface to + // supply the bytes. +}; -class CVTypeVisitor { -public: - explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks); - - Error visitTypeRecord(CVType &Record); - Error visitMemberRecord(CVMemberRecord &Record); +Error visitTypeRecord(CVType &Record, TypeIndex Index, + TypeVisitorCallbacks &Callbacks, + VisitorDataSource Source = VDS_BytesPresent); +Error visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks, + VisitorDataSource Source = VDS_BytesPresent); - /// Visits the type records in Data. Sets the error flag on parse failures. - Error visitTypeStream(const CVTypeArray &Types); +Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks, + VisitorDataSource Source = VDS_BytesPresent); +Error visitMemberRecord(TypeLeafKind Kind, ArrayRef<uint8_t> Record, + TypeVisitorCallbacks &Callbacks); - Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList); - Error visitFieldListMemberStream(msf::StreamReader Reader); +Error visitMemberRecordStream(ArrayRef<uint8_t> FieldList, + TypeVisitorCallbacks &Callbacks); -private: - /// The interface to the class that gets notified of each visitation. - TypeVisitorCallbacks &Callbacks; -}; +Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, + VisitorDataSource Source = VDS_BytesPresent); +Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks); +Error visitTypeStream(TypeCollection &Types, TypeVisitorCallbacks &Callbacks); } // end namespace codeview } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index e21cfa3..b7a7e33 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -6,6 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// +// Defines constants and basic types describing CodeView debug information. +// +//===----------------------------------------------------------------------===// #ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H #define LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H @@ -13,6 +17,8 @@ #include <cinttypes> #include <type_traits> +#include "llvm/Support/Endian.h" + namespace llvm { namespace codeview { @@ -20,28 +26,28 @@ namespace codeview { /// documentation and headers talk about this as the "leaf" type. enum class TypeRecordKind : uint16_t { #define TYPE_RECORD(lf_ename, value, name) name = value, -#include "TypeRecords.def" +#include "CodeViewTypes.def" }; /// Duplicate copy of the above enum, but using the official CV names. Useful /// for reference purposes and when dealing with unknown record types. enum TypeLeafKind : uint16_t { #define CV_TYPE(name, val) name = val, -#include "TypeRecords.def" +#include "CodeViewTypes.def" }; /// Distinguishes individual records in the Symbols subsection of a .debug$S /// section. Equivalent to SYM_ENUM_e in cvinfo.h. enum class SymbolRecordKind : uint16_t { #define SYMBOL_RECORD(lf_ename, value, name) name = value, -#include "CVSymbolTypes.def" +#include "CodeViewSymbols.def" }; /// Duplicate copy of the above enum, but using the official CV names. Useful /// for reference purposes and when dealing with unknown record types. enum SymbolKind : uint16_t { #define CV_SYMBOL(name, val) name = val, -#include "CVSymbolTypes.def" +#include "CodeViewSymbols.def" }; #define CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(Class) \ @@ -275,6 +281,12 @@ enum class MethodOptions : uint16_t { }; CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(MethodOptions) +/// Equivalent to CV_LABEL_TYPE_e. +enum class LabelType : uint16_t { + Near = 0x0, + Far = 0x4, +}; + /// Equivalent to CV_modifier_t. /// TODO: Add flag for _Atomic modifier enum class ModifierOptions : uint16_t { @@ -285,7 +297,7 @@ enum class ModifierOptions : uint16_t { }; CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ModifierOptions) -enum class ModuleSubstreamKind : uint32_t { +enum class DebugSubsectionKind : uint32_t { None = 0, Symbols = 0xf1, Lines = 0xf2, @@ -390,6 +402,16 @@ enum class LocalSymFlags : uint16_t { }; CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(LocalSymFlags) +/// Corresponds to the CV_PUBSYMFLAGS bitfield. +enum class PublicSymFlags : uint32_t { + None = 0, + Code = 1 << 0, + Function = 1 << 1, + Managed = 1 << 2, + MSIL = 1 << 3, +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(PublicSymFlags) + /// Corresponds to the CV_PROCFLAGS bitfield. enum class ProcSymFlags : uint8_t { None = 0, @@ -406,6 +428,8 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ProcSymFlags) /// Corresponds to COMPILESYM2::Flags bitfield. enum class CompileSym2Flags : uint32_t { + None = 0, + SourceLanguageMask = 0xFF, EC = 1 << 8, NoDbgInfo = 1 << 9, LTCG = 1 << 10, @@ -420,6 +444,8 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym2Flags) /// Corresponds to COMPILESYM3::Flags bitfield. enum class CompileSym3Flags : uint32_t { + None = 0, + SourceLanguageMask = 0xFF, EC = 1 << 8, NoDbgInfo = 1 << 9, LTCG = 1 << 10, @@ -436,6 +462,7 @@ enum class CompileSym3Flags : uint32_t { CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym3Flags) enum class ExportFlags : uint16_t { + None = 0, IsConstant = 1 << 0, IsData = 1 << 1, IsPrivate = 1 << 2, @@ -540,9 +567,54 @@ 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 }; -enum LineFlags : uint32_t { - HaveColumns = 1, // CV_LINES_HAVE_COLUMNS -}; +enum LineFlags : uint16_t { + LF_None = 0, + LF_HaveColumns = 1, // CV_LINES_HAVE_COLUMNS +}; + +/// Data in the the SUBSEC_FRAMEDATA subection. +struct FrameData { + support::ulittle32_t RvaStart; + support::ulittle32_t CodeSize; + support::ulittle32_t LocalSize; + support::ulittle32_t ParamsSize; + support::ulittle32_t MaxStackSize; + support::ulittle32_t FrameFunc; + support::ulittle16_t PrologSize; + support::ulittle16_t SavedRegsSize; + support::ulittle32_t Flags; + enum : uint32_t { + HasSEH = 1 << 0, + HasEH = 1 << 1, + IsFunctionStart = 1 << 2, + }; +}; + +// Corresponds to LocalIdAndGlobalIdPair structure. +// This structure information allows cross-referencing between PDBs. For +// example, when a PDB is being built during compilation it is not yet known +// what other modules may end up in the PDB at link time. So certain types of +// IDs may clash between the various compile time PDBs. For each affected +// module, a subsection would be put into the PDB containing a mapping from its +// local IDs to a single ID namespace for all items in the PDB file. +struct CrossModuleExport { + support::ulittle32_t Local; + support::ulittle32_t Global; +}; + +struct CrossModuleImport { + support::ulittle32_t ModuleNameOffset; + support::ulittle32_t Count; // Number of elements + // support::ulittle32_t ids[Count]; // id from referenced module +}; + +enum class CodeViewContainer { ObjectFile, Pdb }; + +inline uint32_t alignOf(CodeViewContainer Container) { + if (Container == CodeViewContainer::ObjectFile) + return 1; + return 4; +} } } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h index 0556fd0..586a720 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, + no_records, unknown_member_record, }; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h index 5a036b9..94f104f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -17,8 +17,8 @@ #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/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Error.h" #include <cassert> #include <cstdint> @@ -33,8 +33,8 @@ class CodeViewRecordIO { } public: - explicit CodeViewRecordIO(msf::StreamReader &Reader) : Reader(&Reader) {} - explicit CodeViewRecordIO(msf::StreamWriter &Writer) : Writer(&Writer) {} + explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {} + explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {} Error beginRecord(Optional<uint32_t> MaxLength); Error endRecord(); @@ -84,7 +84,7 @@ public: Error mapEncodedInteger(uint64_t &Value); Error mapEncodedInteger(APSInt &Value); Error mapStringZ(StringRef &Value); - Error mapGuid(StringRef &Guid); + Error mapGuid(GUID &Guid); Error mapStringZVectorZ(std::vector<StringRef> &Value); @@ -136,6 +136,7 @@ public: Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes); Error mapByteVectorTail(std::vector<uint8_t> &Bytes); + Error padToAlignment(uint32_t Align); Error skipPadding(); private: @@ -160,8 +161,8 @@ private: SmallVector<RecordLimit, 2> Limits; - msf::StreamReader *Reader = nullptr; - msf::StreamWriter *Writer = nullptr; + BinaryStreamReader *Reader = nullptr; + BinaryStreamWriter *Writer = nullptr; }; } // end namespace codeview diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def index 32813d8..32813d8 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def index c98dbac..8c193bb 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def @@ -41,6 +41,7 @@ TYPE_RECORD(LF_POINTER, 0x1002, Pointer) TYPE_RECORD(LF_MODIFIER, 0x1001, Modifier) TYPE_RECORD(LF_PROCEDURE, 0x1008, Procedure) TYPE_RECORD(LF_MFUNCTION, 0x1009, MemberFunction) +TYPE_RECORD(LF_LABEL, 0x000e, Label) TYPE_RECORD(LF_ARGLIST, 0x1201, ArgList) TYPE_RECORD(LF_FIELDLIST, 0x1203, FieldList) @@ -79,9 +80,7 @@ MEMBER_RECORD(LF_INDEX, 0x1404, ListContinuation) TYPE_RECORD(LF_FUNC_ID, 0x1601, FuncId) TYPE_RECORD(LF_MFUNC_ID, 0x1602, MemberFuncId) TYPE_RECORD(LF_BUILDINFO, 0x1603, BuildInfo) -// FIXME: We reuse the structure of ArgListRecord for substring lists, but it -// makes for confusing dumper output. -TYPE_RECORD_ALIAS(LF_SUBSTR_LIST, 0x1604, StringList, ArgList) +TYPE_RECORD(LF_SUBSTR_LIST, 0x1604, StringList) TYPE_RECORD(LF_STRING_ID, 0x1605, StringId) TYPE_RECORD(LF_UDT_SRC_LINE, 0x1606, UdtSourceLine) TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine) @@ -103,7 +102,6 @@ CV_TYPE(LF_MFUNCTION_16t, 0x0009) CV_TYPE(LF_COBOL0_16t, 0x000b) CV_TYPE(LF_COBOL1, 0x000c) CV_TYPE(LF_BARRAY_16t, 0x000d) -CV_TYPE(LF_LABEL, 0x000e) CV_TYPE(LF_NULLLEAF, 0x000f) // LF_NULL CV_TYPE(LF_NOTTRAN, 0x0010) CV_TYPE(LF_DIMARRAY_16t, 0x0011) diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h new file mode 100644 index 0000000..78b2845 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h @@ -0,0 +1,104 @@ +//===- DebugChecksumsSubsection.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_DEBUGCHECKSUMSSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCHECKSUMSSUBSECTION_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +namespace codeview { + +class DebugStringTableSubsection; + +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. +}; + +} // end namespace codeview + +template <> struct VarStreamArrayExtractor<codeview::FileChecksumEntry> { +public: + using ContextType = void; + + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + codeview::FileChecksumEntry &Item); +}; + +namespace codeview { + +class DebugChecksumsSubsectionRef final : public DebugSubsectionRef { + using FileChecksumArray = VarStreamArray<codeview::FileChecksumEntry>; + using Iterator = FileChecksumArray::Iterator; + +public: + DebugChecksumsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::FileChecksums) {} + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::FileChecksums; + } + + bool valid() const { return Checksums.valid(); } + + Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); + + Iterator begin() const { return Checksums.begin(); } + Iterator end() const { return Checksums.end(); } + + const FileChecksumArray &getArray() const { return Checksums; } + +private: + FileChecksumArray Checksums; +}; + +class DebugChecksumsSubsection final : public DebugSubsection { +public: + explicit DebugChecksumsSubsection(DebugStringTableSubsection &Strings); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::FileChecksums; + } + + void addChecksum(StringRef FileName, FileChecksumKind Kind, + ArrayRef<uint8_t> Bytes); + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + uint32_t mapChecksumOffset(StringRef FileName) const; + +private: + DebugStringTableSubsection &Strings; + + DenseMap<uint32_t, uint32_t> OffsetMap; + uint32_t SerializedSize = 0; + BumpPtrAllocator Storage; + std::vector<FileChecksumEntry> Checksums; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGCHECKSUMSSUBSECTION_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h new file mode 100644 index 0000000..2f9e981 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h @@ -0,0 +1,68 @@ +//===- DebugCrossExSubsection.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_DEBUGCROSSEXSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <map> + +namespace llvm { +namespace codeview { + +class DebugCrossModuleExportsSubsectionRef final : public DebugSubsectionRef { + using ReferenceArray = FixedStreamArray<CrossModuleExport>; + using Iterator = ReferenceArray::Iterator; + +public: + DebugCrossModuleExportsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::CrossScopeExports) {} + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::CrossScopeExports; + } + + Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); + + Iterator begin() const { return References.begin(); } + Iterator end() const { return References.end(); } + +private: + FixedStreamArray<CrossModuleExport> References; +}; + +class DebugCrossModuleExportsSubsection final : public DebugSubsection { +public: + DebugCrossModuleExportsSubsection() + : DebugSubsection(DebugSubsectionKind::CrossScopeExports) {} + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::CrossScopeExports; + } + + void addMapping(uint32_t Local, uint32_t Global); + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + +private: + std::map<uint32_t, uint32_t> Mappings; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h new file mode 100644 index 0000000..8be7ef2 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h @@ -0,0 +1,95 @@ +//===- DebugCrossExSubsection.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_DEBUGCROSSIMPSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSIMPSUBSECTION_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +namespace codeview { + +struct CrossModuleImportItem { + const CrossModuleImport *Header = nullptr; + FixedStreamArray<support::ulittle32_t> Imports; +}; + +} // end namespace codeview + +template <> struct VarStreamArrayExtractor<codeview::CrossModuleImportItem> { +public: + using ContextType = void; + + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + codeview::CrossModuleImportItem &Item); +}; + +namespace codeview { + +class DebugStringTableSubsection; + +class DebugCrossModuleImportsSubsectionRef final : public DebugSubsectionRef { + using ReferenceArray = VarStreamArray<CrossModuleImportItem>; + using Iterator = ReferenceArray::Iterator; + +public: + DebugCrossModuleImportsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::CrossScopeImports) {} + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::CrossScopeImports; + } + + Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); + + Iterator begin() const { return References.begin(); } + Iterator end() const { return References.end(); } + +private: + ReferenceArray References; +}; + +class DebugCrossModuleImportsSubsection final : public DebugSubsection { +public: + explicit DebugCrossModuleImportsSubsection( + DebugStringTableSubsection &Strings) + : DebugSubsection(DebugSubsectionKind::CrossScopeImports), + Strings(Strings) {} + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::CrossScopeImports; + } + + void addImport(StringRef Module, uint32_t ImportId); + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + +private: + DebugStringTableSubsection &Strings; + StringMap<std::vector<support::ulittle32_t>> Mappings; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSIMPSUBSECTION_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h new file mode 100644 index 0000000..1e329c7 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h @@ -0,0 +1,60 @@ +//===- DebugFrameDataSubsection.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_DEBUGFRAMEDATASUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGFRAMEDATASUBSECTION_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class DebugFrameDataSubsectionRef final : public DebugSubsectionRef { +public: + DebugFrameDataSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::FrameData) {} + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::FrameData; + } + + Error initialize(BinaryStreamReader Reader); + + FixedStreamArray<FrameData>::Iterator begin() const { return Frames.begin(); } + FixedStreamArray<FrameData>::Iterator end() const { return Frames.end(); } + + const void *getRelocPtr() const { return RelocPtr; } + +private: + const uint32_t *RelocPtr = nullptr; + FixedStreamArray<FrameData> Frames; +}; + +class DebugFrameDataSubsection final : public DebugSubsection { +public: + DebugFrameDataSubsection() + : DebugSubsection(DebugSubsectionKind::FrameData) {} + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::FrameData; + } + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + void addFrameData(const FrameData &Frame); + void setFrames(ArrayRef<FrameData> Frames); + +private: + std::vector<FrameData> Frames; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h new file mode 100644 index 0000000..b88c0ea --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h @@ -0,0 +1,121 @@ +//===- DebugInlineeLinesSubsection.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_DEBUGINLINEELINESSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGINLINEELINESSUBSECTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +namespace codeview { + +class DebugChecksumsSubsection; + +enum class InlineeLinesSignature : uint32_t { + Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE + ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX +}; + +struct InlineeSourceLineHeader { + TypeIndex Inlinee; // ID of the function that was inlined. + support::ulittle32_t FileID; // Offset into FileChecksums subsection. + support::ulittle32_t SourceLineNum; // First line of inlined code. + // If extra files present: + // ulittle32_t ExtraFileCount; + // ulittle32_t Files[]; +}; + +struct InlineeSourceLine { + const InlineeSourceLineHeader *Header; + FixedStreamArray<support::ulittle32_t> ExtraFiles; +}; + +} // end namespace codeview + +template <> struct VarStreamArrayExtractor<codeview::InlineeSourceLine> { + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + codeview::InlineeSourceLine &Item); + + bool HasExtraFiles = false; +}; + +namespace codeview { + +class DebugInlineeLinesSubsectionRef final : public DebugSubsectionRef { + using LinesArray = VarStreamArray<InlineeSourceLine>; + using Iterator = LinesArray::Iterator; + +public: + DebugInlineeLinesSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::InlineeLines; + } + + Error initialize(BinaryStreamReader Reader); + bool hasExtraFiles() const; + + Iterator begin() const { return Lines.begin(); } + Iterator end() const { return Lines.end(); } + +private: + InlineeLinesSignature Signature; + VarStreamArray<InlineeSourceLine> Lines; +}; + +class DebugInlineeLinesSubsection final : public DebugSubsection { +public: + struct Entry { + std::vector<support::ulittle32_t> ExtraFiles; + InlineeSourceLineHeader Header; + }; + + DebugInlineeLinesSubsection(DebugChecksumsSubsection &Checksums, + bool HasExtraFiles = false); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::InlineeLines; + } + + Error commit(BinaryStreamWriter &Writer) const override; + uint32_t calculateSerializedSize() const override; + + void addInlineSite(TypeIndex FuncId, StringRef FileName, uint32_t SourceLine); + void addExtraFile(StringRef FileName); + + bool hasExtraFiles() const { return HasExtraFiles; } + void setHasExtraFiles(bool Has) { HasExtraFiles = Has; } + + std::vector<Entry>::const_iterator begin() const { return Entries.begin(); } + std::vector<Entry>::const_iterator end() const { return Entries.end(); } + +private: + DebugChecksumsSubsection &Checksums; + bool HasExtraFiles = false; + uint32_t ExtraFileCount = 0; + std::vector<Entry> Entries; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGINLINEELINESSUBSECTION_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h new file mode 100644 index 0000000..53044b6 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h @@ -0,0 +1,150 @@ +//===- DebugLinesSubsection.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_DEBUGLINESSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace codeview { + +class DebugChecksumsSubsection; +class DebugStringTableSubsection; + +// Corresponds to the `CV_DebugSLinesHeader_t` structure. +struct LineFragmentHeader { + support::ulittle32_t RelocOffset; // Code offset of line contribution. + support::ulittle16_t RelocSegment; // Code segment of line contribution. + support::ulittle16_t Flags; // See LineFlags enumeration. + support::ulittle32_t CodeSize; // Code size of this line contribution. +}; + +// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure. +struct LineBlockFragmentHeader { + support::ulittle32_t NameIndex; // Offset of FileChecksum entry in File + // checksums buffer. The checksum entry then + // contains another offset into the string + // table of the actual name. + support::ulittle32_t NumLines; // Number of lines + support::ulittle32_t BlockSize; // Code size of block, in bytes. + // The following two variable length arrays appear immediately after the + // header. The structure definitions follow. + // LineNumberEntry Lines[NumLines]; + // ColumnNumberEntry Columns[NumLines]; +}; + +// Corresponds to `CV_Line_t` structure +struct LineNumberEntry { + support::ulittle32_t Offset; // Offset to start of code bytes for line number + support::ulittle32_t Flags; // Start:24, End:7, IsStatement:1 +}; + +// Corresponds to `CV_Column_t` structure +struct ColumnNumberEntry { + support::ulittle16_t StartColumn; + support::ulittle16_t EndColumn; +}; + +struct LineColumnEntry { + support::ulittle32_t NameIndex; + FixedStreamArray<LineNumberEntry> LineNumbers; + FixedStreamArray<ColumnNumberEntry> Columns; +}; + +class LineColumnExtractor { +public: + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + LineColumnEntry &Item); + + const LineFragmentHeader *Header = nullptr; +}; + +class DebugLinesSubsectionRef final : public DebugSubsectionRef { + friend class LineColumnExtractor; + + using LineInfoArray = VarStreamArray<LineColumnEntry, LineColumnExtractor>; + using Iterator = LineInfoArray::Iterator; + +public: + DebugLinesSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::Lines; + } + + Error initialize(BinaryStreamReader Reader); + + Iterator begin() const { return LinesAndColumns.begin(); } + Iterator end() const { return LinesAndColumns.end(); } + + const LineFragmentHeader *header() const { return Header; } + + bool hasColumnInfo() const; + +private: + const LineFragmentHeader *Header = nullptr; + LineInfoArray LinesAndColumns; +}; + +class DebugLinesSubsection final : public DebugSubsection { + struct Block { + Block(uint32_t ChecksumBufferOffset) + : ChecksumBufferOffset(ChecksumBufferOffset) {} + + uint32_t ChecksumBufferOffset; + std::vector<LineNumberEntry> Lines; + std::vector<ColumnNumberEntry> Columns; + }; + +public: + DebugLinesSubsection(DebugChecksumsSubsection &Checksums, + DebugStringTableSubsection &Strings); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::Lines; + } + + void createBlock(StringRef FileName); + void addLineInfo(uint32_t Offset, const LineInfo &Line); + void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line, + uint32_t ColStart, uint32_t ColEnd); + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + void setRelocationAddress(uint16_t Segment, uint32_t Offset); + void setCodeSize(uint32_t Size); + void setFlags(LineFlags Flags); + + bool hasColumnInfo() const; + +private: + DebugChecksumsSubsection &Checksums; + uint32_t RelocOffset = 0; + uint16_t RelocSegment = 0; + uint32_t CodeSize = 0; + LineFlags Flags = LF_None; + std::vector<Block> Blocks; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h new file mode 100644 index 0000000..7f0f10e --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h @@ -0,0 +1,89 @@ +//===- DebugStringTableSubsection.h - CodeView String Table -----*- 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_DEBUGSTRINGTABLESUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" +#include <cstdint> + +namespace llvm { + +class BinaryStreamReader; + +namespace codeview { + +/// Represents a read-only view of a CodeView string table. This is a very +/// simple flat buffer consisting of null-terminated strings, where strings +/// are retrieved by their offset in the buffer. DebugStringTableSubsectionRef +/// does not own the underlying storage for the buffer. +class DebugStringTableSubsectionRef : public DebugSubsectionRef { +public: + DebugStringTableSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::StringTable; + } + + Error initialize(BinaryStreamRef Contents); + Error initialize(BinaryStreamReader &Reader); + + Expected<StringRef> getString(uint32_t Offset) const; + + bool valid() const { return Stream.valid(); } + + BinaryStreamRef getBuffer() const { return Stream; } + +private: + BinaryStreamRef Stream; +}; + +/// Represents a read-write view of a CodeView string table. +/// DebugStringTableSubsection owns the underlying storage for the table, and is +/// capable of serializing the string table into a format understood by +/// DebugStringTableSubsectionRef. +class DebugStringTableSubsection : public DebugSubsection { +public: + DebugStringTableSubsection(); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::StringTable; + } + + // If string S does not exist in the string table, insert it. + // Returns the ID for S. + uint32_t insert(StringRef S); + + // Return the ID for string S. Assumes S exists in the table. + uint32_t getStringId(StringRef S) const; + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + uint32_t size() const; + + StringMap<uint32_t>::const_iterator begin() const { return Strings.begin(); } + + StringMap<uint32_t>::const_iterator end() const { return Strings.end(); } + +private: + StringMap<uint32_t> Strings; + uint32_t StringSize = 1; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsection.h new file mode 100644 index 0000000..e427e00 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsection.h @@ -0,0 +1,52 @@ +//===- DebugSubsection.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_MODULEDEBUGFRAGMENT_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Casting.h" + +namespace llvm { +namespace codeview { + +class DebugSubsectionRef { +public: + explicit DebugSubsectionRef(DebugSubsectionKind Kind) : Kind(Kind) {} + virtual ~DebugSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { return true; } + + DebugSubsectionKind kind() const { return Kind; } + +protected: + DebugSubsectionKind Kind; +}; + +class DebugSubsection { +public: + explicit DebugSubsection(DebugSubsectionKind Kind) : Kind(Kind) {} + virtual ~DebugSubsection(); + + static bool classof(const DebugSubsection *S) { return true; } + + DebugSubsectionKind kind() const { return Kind; } + + virtual Error commit(BinaryStreamWriter &Writer) const = 0; + virtual uint32_t calculateSerializedSize() const = 0; + +protected: + DebugSubsectionKind Kind; +}; + +} // namespace codeview +} // namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h new file mode 100644 index 0000000..fc0cf0d --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h @@ -0,0 +1,103 @@ +//===- DebugSubsectionRecord.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_DEBUGSUBSECTIONRECORD_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" +#include <cstdint> +#include <memory> + +namespace llvm { + +class BinaryStreamWriter; + +namespace codeview { + +class DebugSubsection; + +// Corresponds to the `CV_DebugSSubsectionHeader_t` structure. +struct DebugSubsectionHeader { + support::ulittle32_t Kind; // codeview::DebugSubsectionKind enum + support::ulittle32_t Length; // number of bytes occupied by this record. +}; + +class DebugSubsectionRecord { +public: + DebugSubsectionRecord(); + DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data, + CodeViewContainer Container); + + static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info, + CodeViewContainer Container); + + uint32_t getRecordLength() const; + DebugSubsectionKind kind() const; + BinaryStreamRef getRecordData() const; + +private: + CodeViewContainer Container = CodeViewContainer::ObjectFile; + DebugSubsectionKind Kind = DebugSubsectionKind::None; + BinaryStreamRef Data; +}; + +class DebugSubsectionRecordBuilder { +public: + DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection, + CodeViewContainer Container); + + /// Use this to copy existing subsections directly from source to destination. + /// For example, line table subsections in an object file only need to be + /// relocated before being copied into the PDB. + DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents, + CodeViewContainer Container); + + uint32_t calculateSerializedLength(); + Error commit(BinaryStreamWriter &Writer) const; + +private: + /// The subsection to build. Will be null if Contents is non-empty. + std::shared_ptr<DebugSubsection> Subsection; + + /// The bytes of the subsection. Only non-empty if Subsection is null. + DebugSubsectionRecord Contents; + + CodeViewContainer Container; +}; + +} // end namespace codeview + +template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> { + Error operator()(BinaryStreamRef Stream, uint32_t &Length, + codeview::DebugSubsectionRecord &Info) { + // FIXME: We need to pass the container type through to this function. In + // practice this isn't super important since the subsection header describes + // its length and we can just skip it. It's more important when writing. + if (auto EC = codeview::DebugSubsectionRecord::initialize( + Stream, Info, codeview::CodeViewContainer::Pdb)) + return EC; + Length = alignTo(Info.getRecordLength(), 4); + return Error::success(); + } +}; + +namespace codeview { + +using DebugSubsectionArray = VarStreamArray<DebugSubsectionRecord>; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h new file mode 100644 index 0000000..75f749d --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h @@ -0,0 +1,114 @@ +//===- DebugSubsectionVisitor.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_MODULEDEBUGFRAGMENTVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" +#include "llvm/Support/Error.h" +#include <cstdint> + +namespace llvm { + +namespace codeview { + +class DebugChecksumsSubsectionRef; +class DebugSubsectionRecord; +class DebugInlineeLinesSubsectionRef; +class DebugCrossModuleExportsSubsectionRef; +class DebugCrossModuleImportsSubsectionRef; +class DebugFrameDataSubsectionRef; +class DebugLinesSubsectionRef; +class DebugStringTableSubsectionRef; +class DebugSymbolRVASubsectionRef; +class DebugSymbolsSubsectionRef; +class DebugUnknownSubsectionRef; +class StringsAndChecksumsRef; + +class DebugSubsectionVisitor { +public: + virtual ~DebugSubsectionVisitor() = default; + + virtual Error visitUnknown(DebugUnknownSubsectionRef &Unknown) { + return Error::success(); + } + virtual Error visitLines(DebugLinesSubsectionRef &Lines, + const StringsAndChecksumsRef &State) = 0; + virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, + const StringsAndChecksumsRef &State) = 0; + virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, + const StringsAndChecksumsRef &State) = 0; + virtual Error + visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE, + const StringsAndChecksumsRef &State) = 0; + virtual Error + visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE, + const StringsAndChecksumsRef &State) = 0; + + virtual Error visitStringTable(DebugStringTableSubsectionRef &ST, + const StringsAndChecksumsRef &State) = 0; + + virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE, + const StringsAndChecksumsRef &State) = 0; + + virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD, + const StringsAndChecksumsRef &State) = 0; + virtual Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs, + const StringsAndChecksumsRef &State) = 0; +}; + +Error visitDebugSubsection(const DebugSubsectionRecord &R, + DebugSubsectionVisitor &V, + const StringsAndChecksumsRef &State); + +namespace detail { +template <typename T> +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, + StringsAndChecksumsRef &State) { + State.initialize(std::forward<T>(FragmentRange)); + + for (const DebugSubsectionRecord &L : FragmentRange) { + if (auto EC = visitDebugSubsection(L, V, State)) + return EC; + } + return Error::success(); +} +} // namespace detail + +template <typename T> +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) { + StringsAndChecksumsRef State; + return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V, + State); +} + +template <typename T> +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, + const DebugStringTableSubsectionRef &Strings) { + StringsAndChecksumsRef State(Strings); + return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V, + State); +} + +template <typename T> +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums) { + StringsAndChecksumsRef State(Strings, Checksums); + return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V, + State); +} + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h new file mode 100644 index 0000000..a4c04b5 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h @@ -0,0 +1,67 @@ +//===- DebugSymbolRVASubsection.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_DEBUGSYMBOLRVASUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLRVASUBSECTION_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +class BinaryStreamReader; + +namespace codeview { + +class DebugSymbolRVASubsectionRef final : public DebugSubsectionRef { +public: + using ArrayType = FixedStreamArray<support::ulittle32_t>; + + DebugSymbolRVASubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::CoffSymbolRVA; + } + + ArrayType::Iterator begin() const { return RVAs.begin(); } + ArrayType::Iterator end() const { return RVAs.end(); } + + Error initialize(BinaryStreamReader &Reader); + +private: + ArrayType RVAs; +}; + +class DebugSymbolRVASubsection final : public DebugSubsection { +public: + DebugSymbolRVASubsection(); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::CoffSymbolRVA; + } + + Error commit(BinaryStreamWriter &Writer) const override; + uint32_t calculateSerializedSize() const override; + + void addRVA(uint32_t RVA) { RVAs.push_back(support::ulittle32_t(RVA)); } + +private: + std::vector<support::ulittle32_t> RVAs; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLRVASUBSECTION_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h new file mode 100644 index 0000000..dfda7de --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h @@ -0,0 +1,56 @@ +//===- DebugSymbolsSubsection.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_DEBUGSYMBOLSSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLSSUBSECTION_H + +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class DebugSymbolsSubsectionRef final : public DebugSubsectionRef { +public: + DebugSymbolsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::Symbols) {} + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::Symbols; + } + + Error initialize(BinaryStreamReader Reader); + + CVSymbolArray::Iterator begin() const { return Records.begin(); } + CVSymbolArray::Iterator end() const { return Records.end(); } + +private: + CVSymbolArray Records; +}; + +class DebugSymbolsSubsection final : public DebugSubsection { +public: + DebugSymbolsSubsection() : DebugSubsection(DebugSubsectionKind::Symbols) {} + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::Symbols; + } + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + void addSymbol(CVSymbol Symbol); + +private: + uint32_t Length = 0; + std::vector<CVSymbol> Records; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h new file mode 100644 index 0000000..ea9a96c --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h @@ -0,0 +1,32 @@ +//===- DebugUnknownSubsection.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_MODULEDEBUGUNKNOWNFRAGMENT_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGUNKNOWNFRAGMENT_H + +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamRef.h" + +namespace llvm { +namespace codeview { + +class DebugUnknownSubsectionRef final : public DebugSubsectionRef { +public: + DebugUnknownSubsectionRef(DebugSubsectionKind Kind, BinaryStreamRef Data) + : DebugSubsectionRef(Kind), Data(Data) {} + + BinaryStreamRef getData() const { return Data; } + +private: + BinaryStreamRef Data; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/EnumTables.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/EnumTables.h index 10d1c58..ee0f0f7 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/EnumTables.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/EnumTables.h @@ -1,4 +1,4 @@ -//===- EnumTables.h Enum to string conversion tables ------------*- C++ -*-===// +//===- EnumTables.h - Enum to string conversion tables ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,17 +11,18 @@ #define LLVM_DEBUGINFO_CODEVIEW_ENUMTABLES_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/Support/COFF.h" #include "llvm/Support/ScopedPrinter.h" - -#include <stdint.h> +#include <cstdint> namespace llvm { namespace codeview { + ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames(); ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames(); ArrayRef<EnumEntry<uint16_t>> getRegisterNames(); +ArrayRef<EnumEntry<uint32_t>> getPublicSymFlagNames(); ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames(); ArrayRef<EnumEntry<uint16_t>> getLocalFlagNames(); ArrayRef<EnumEntry<uint8_t>> getFrameCookieKindNames(); @@ -37,7 +38,8 @@ ArrayRef<EnumEntry<uint8_t>> getThunkOrdinalNames(); ArrayRef<EnumEntry<uint16_t>> getTrampolineNames(); ArrayRef<EnumEntry<COFF::SectionCharacteristics>> getImageSectionCharacteristicNames(); -} // namespace codeview -} // namespace llvm + +} // end namespace codeview +} // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_ENUMTABLES_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/Formatters.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/Formatters.h new file mode 100644 index 0000000..278ad02 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/Formatters.h @@ -0,0 +1,73 @@ +//===- Formatters.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_FORMATTERS_H +#define LLVM_DEBUGINFO_CODEVIEW_FORMATTERS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/GUID.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdint> + +namespace llvm { + +namespace codeview { + +namespace detail { + +class GuidAdapter final : public FormatAdapter<ArrayRef<uint8_t>> { + ArrayRef<uint8_t> Guid; + +public: + explicit GuidAdapter(ArrayRef<uint8_t> Guid); + explicit GuidAdapter(StringRef Guid); + + void format(raw_ostream &Stream, StringRef Style) override; +}; + +} // end namespace detail + +inline detail::GuidAdapter fmt_guid(StringRef Item) { + return detail::GuidAdapter(Item); +} + +inline detail::GuidAdapter fmt_guid(ArrayRef<uint8_t> Item) { + return detail::GuidAdapter(Item); +} + +} // end namespace codeview + +template <> struct format_provider<codeview::TypeIndex> { +public: + static void format(const codeview::TypeIndex &V, raw_ostream &Stream, + StringRef Style) { + if (V.isNoneType()) + Stream << "<no type>"; + else { + Stream << formatv("{0:X+4}", V.getIndex()); + if (V.isSimple()) + Stream << " (" << codeview::TypeIndex::simpleTypeName(V) << ")"; + } + } +}; + +template <> struct format_provider<codeview::GUID> { + static void format(const codeview::GUID &V, llvm::raw_ostream &Stream, + StringRef Style) { + Stream << V; + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_FORMATTERS_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/GUID.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/GUID.h new file mode 100644 index 0000000..a055ce9 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/GUID.h @@ -0,0 +1,55 @@ +//===- GUID.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_GUID_H +#define LLVM_DEBUGINFO_CODEVIEW_GUID_H + +#include <cstdint> +#include <cstring> + +namespace llvm { +class raw_ostream; + +namespace codeview { + +/// This represents the 'GUID' type from windows.h. +struct GUID { + uint8_t Guid[16]; +}; + +inline bool operator==(const GUID &LHS, const GUID &RHS) { + return 0 == ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)); +} + +inline bool operator<(const GUID &LHS, const GUID &RHS) { + return ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)) < 0; +} + +inline bool operator<=(const GUID &LHS, const GUID &RHS) { + return ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)) <= 0; +} + +inline bool operator>(const GUID &LHS, const GUID &RHS) { + return !(LHS <= RHS); +} + +inline bool operator>=(const GUID &LHS, const GUID &RHS) { + return !(LHS < RHS); +} + +inline bool operator!=(const GUID &LHS, const GUID &RHS) { + return !(LHS == RHS); +} + +raw_ostream &operator<<(raw_ostream &OS, const GUID &Guid); + +} // namespace codeview +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h new file mode 100644 index 0000000..cc0c243 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h @@ -0,0 +1,113 @@ +//===- LazyRandomTypeCollection.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_LAZYRANDOMTYPECOLLECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/StringSaver.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace codeview { + +/// \brief Provides amortized O(1) random access to a CodeView type stream. +/// Normally to access a type from a type stream, you must know its byte +/// offset into the type stream, because type records are variable-lengthed. +/// However, this is not the way we prefer to access them. For example, given +/// a symbol record one of the fields may be the TypeIndex of the symbol's +/// type record. Or given a type record such as an array type, there might +/// be a TypeIndex for the element type. Sequential access is perfect when +/// we're just dumping every entry, but it's very poor for real world usage. +/// +/// Type streams in PDBs contain an additional field which is a list of pairs +/// containing indices and their corresponding offsets, roughly every ~8KB of +/// record data. This general idea need not be confined to PDBs though. By +/// supplying such an array, the producer of a type stream can allow the +/// consumer much better access time, because the consumer can find the nearest +/// index in this array, and do a linear scan forward only from there. +/// +/// LazyRandomTypeCollection implements this algorithm, but additionally goes +/// one step further by caching offsets of every record that has been visited at +/// least once. This way, even repeated visits of the same record will never +/// require more than one linear scan. For a type stream of N elements divided +/// into M chunks of roughly equal size, this yields a worst case lookup time +/// of O(N/M) and an amortized time of O(1). +class LazyRandomTypeCollection : public TypeCollection { + using PartialOffsetArray = FixedStreamArray<TypeIndexOffset>; + + struct CacheEntry { + CVType Type; + uint32_t Offset; + StringRef Name; + }; + +public: + explicit LazyRandomTypeCollection(uint32_t RecordCountHint); + LazyRandomTypeCollection(StringRef Data, uint32_t RecordCountHint); + LazyRandomTypeCollection(ArrayRef<uint8_t> Data, uint32_t RecordCountHint); + LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint, + PartialOffsetArray PartialOffsets); + LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint); + + void reset(ArrayRef<uint8_t> Data, uint32_t RecordCountHint); + void reset(StringRef Data, uint32_t RecordCountHint); + + uint32_t getOffsetOfType(TypeIndex Index); + + CVType getType(TypeIndex Index) override; + StringRef getTypeName(TypeIndex Index) override; + bool contains(TypeIndex Index) override; + uint32_t size() override; + uint32_t capacity() override; + Optional<TypeIndex> getFirst() override; + Optional<TypeIndex> getNext(TypeIndex Prev) override; + +private: + Error ensureTypeExists(TypeIndex Index); + void ensureCapacityFor(TypeIndex Index); + + Error visitRangeForType(TypeIndex TI); + Error fullScanForType(TypeIndex TI); + void visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End); + + /// Number of actual records. + uint32_t Count = 0; + + /// The largest type index which we've visited. + TypeIndex LargestTypeIndex = TypeIndex::None(); + + BumpPtrAllocator Allocator; + StringSaver NameStorage; + + /// The type array to allow random access visitation of. + CVTypeArray Types; + + std::vector<CacheEntry> Records; + + /// An array of index offsets for the given type stream, allowing log(N) + /// lookups of a type record by index. Similar to KnownOffsets but only + /// contains offsets for some type indices, some of which may not have + /// ever been visited. + PartialOffsetArray PartialOffsets; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/Line.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/Line.h index 975b503..ac229c3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/Line.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/Line.h @@ -127,27 +127,6 @@ public: bool isNeverStepInto() const { return LineInf.isNeverStepInto(); } }; -enum class InlineeLinesSignature : uint32_t { - Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE - ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX -}; - -struct InlineeSourceLine { - TypeIndex Inlinee; // ID of the function that was inlined. - ulittle32_t FileID; // Offset into FileChecksums subsection. - ulittle32_t SourceLineNum; // First line of inlined code. - // If extra files present: - // ulittle32_t ExtraFileCount; - // ulittle32_t Files[]; -}; - -struct FileChecksum { - ulittle32_t FileNameOffset; // Byte offset of filename in global string table. - uint8_t ChecksumSize; // Number of bytes of checksum. - uint8_t ChecksumKind; // FileChecksumKind - // Checksum bytes follow. -}; - } // namespace codeview } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h deleted file mode 100644 index 8860ae4..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h +++ /dev/null @@ -1,89 +0,0 @@ -//===- ModuleSubstream.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_MODULESUBSTREAM_H -#define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H - -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/MSF/StreamArray.h" -#include "llvm/DebugInfo/MSF/StreamRef.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" - -namespace llvm { -namespace codeview { - -// Corresponds to the `CV_DebugSSubsectionHeader_t` structure. -struct ModuleSubsectionHeader { - support::ulittle32_t Kind; // codeview::ModuleSubstreamKind enum - support::ulittle32_t Length; // number of bytes occupied by this record. -}; - -// Corresponds to the `CV_DebugSLinesHeader_t` structure. -struct LineSubstreamHeader { - support::ulittle32_t RelocOffset; // Code offset of line contribution. - support::ulittle16_t RelocSegment; // Code segment of line contribution. - support::ulittle16_t Flags; // See LineFlags enumeration. - support::ulittle32_t CodeSize; // Code size of this line contribution. -}; - -// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure. -struct LineFileBlockHeader { - support::ulittle32_t NameIndex; // Index in DBI name buffer of filename. - support::ulittle32_t NumLines; // Number of lines - support::ulittle32_t BlockSize; // Code size of block, in bytes. - // The following two variable length arrays appear immediately after the - // header. The structure definitions follow. - // LineNumberEntry Lines[NumLines]; - // ColumnNumberEntry Columns[NumLines]; -}; - -// Corresponds to `CV_Line_t` structure -struct LineNumberEntry { - support::ulittle32_t Offset; // Offset to start of code bytes for line number - support::ulittle32_t Flags; // Start:24, End:7, IsStatement:1 -}; - -// Corresponds to `CV_Column_t` structure -struct ColumnNumberEntry { - support::ulittle16_t StartColumn; - support::ulittle16_t EndColumn; -}; - -class ModuleSubstream { -public: - ModuleSubstream(); - ModuleSubstream(ModuleSubstreamKind Kind, msf::ReadableStreamRef Data); - static Error initialize(msf::ReadableStreamRef Stream, ModuleSubstream &Info); - uint32_t getRecordLength() const; - ModuleSubstreamKind getSubstreamKind() const; - msf::ReadableStreamRef getRecordData() const; - -private: - ModuleSubstreamKind Kind; - msf::ReadableStreamRef Data; -}; - -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(); - } -}; -} // 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 deleted file mode 100644 index f9927d6..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h +++ /dev/null @@ -1,136 +0,0 @@ -//===- ModuleSubstreamVisitor.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_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/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; - msf::FixedStreamArray<LineNumberEntry> LineNumbers; - msf::FixedStreamArray<ColumnNumberEntry> Columns; -}; - -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: - virtual ~IModuleSubstreamVisitor() = default; - - 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)) - return EC; - bool HasColumn = Header->Flags & LineFlags::HaveColumns; - uint32_t LineInfoSize = - BlockHeader->NumLines * - (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); - if (BlockHeader->BlockSize < sizeof(LineFileBlockHeader)) - return make_error<CodeViewError>(cv_error_code::corrupt_record, - "Invalid line block record size"); - uint32_t Size = BlockHeader->BlockSize - sizeof(LineFileBlockHeader); - if (LineInfoSize > Size) - return make_error<CodeViewError>(cv_error_code::corrupt_record, - "Invalid line block record size"); - // The value recorded in BlockHeader->BlockSize includes the size of - // LineFileBlockHeader. - Len = BlockHeader->BlockSize; - Item.NameIndex = BlockHeader->NameIndex; - if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) - return EC; - if (HasColumn) { - if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines)) - return EC; - } - return Error::success(); - } - -private: - const codeview::LineSubstreamHeader *Header; -}; - -template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> { -public: - 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)) - return EC; - Item.FileNameOffset = Header->FileNameOffset; - Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind); - if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize)) - return EC; - Len = sizeof(FileChecksum) + Header->ChecksumSize; - return Error::success(); - } -}; - -} // end namespace msf - -} // 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 97b6f56..58449c2 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h @@ -15,7 +15,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <cinttypes> @@ -41,37 +41,37 @@ struct RecordPrefix { StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData); StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData); -inline Error consume(msf::StreamReader &Reader) { return Error::success(); } +inline Error consume(BinaryStreamReader &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. -Error consume(msf::StreamReader &Reader, APSInt &Num); +Error consume(BinaryStreamReader &Reader, APSInt &Num); /// Decodes a numeric leaf value that is known to be a particular type. -Error consume_numeric(msf::StreamReader &Reader, uint64_t &Value); +Error consume_numeric(BinaryStreamReader &Reader, uint64_t &Value); /// Decodes signed and unsigned fixed-length integers. -Error consume(msf::StreamReader &Reader, uint32_t &Item); -Error consume(msf::StreamReader &Reader, int32_t &Item); +Error consume(BinaryStreamReader &Reader, uint32_t &Item); +Error consume(BinaryStreamReader &Reader, int32_t &Item); /// Decodes a null terminated string. -Error consume(msf::StreamReader &Reader, StringRef &Item); +Error consume(BinaryStreamReader &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> Error consume(msf::StreamReader &Reader, T *&Item) { +template <typename T> Error consume(BinaryStreamReader &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) {} - Error deserialize(msf::StreamReader &Reader) const { + Error deserialize(BinaryStreamReader &Reader) const { if (!Func()) return Error::success(); return consume(Reader, Item); @@ -89,7 +89,7 @@ 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) {} - Error deserialize(msf::StreamReader &Reader) const { + Error deserialize(BinaryStreamReader &Reader) const { return Reader.readArray(Item, Func()); } @@ -100,7 +100,7 @@ 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) {} - Error deserialize(msf::StreamReader &Reader) const { + Error deserialize(BinaryStreamReader &Reader) const { T Field; // Stop when we run out of bytes or we hit record padding bytes. while (!Reader.empty() && Reader.peek() < LF_PAD0) { @@ -118,14 +118,14 @@ struct serialize_null_term_string_array_impl { serialize_null_term_string_array_impl(std::vector<StringRef> &Item) : Item(Item) {} - Error deserialize(msf::StreamReader &Reader) const { + Error deserialize(BinaryStreamReader &Reader) const { if (Reader.empty()) return make_error<CodeViewError>(cv_error_code::insufficient_buffer, "Null terminated string is empty!"); while (Reader.peek() != 0) { StringRef Field; - if (auto EC = Reader.readZeroString(Field)) + if (auto EC = Reader.readCString(Field)) return EC; Item.push_back(Field); } @@ -138,7 +138,7 @@ struct serialize_null_term_string_array_impl { template <typename T> struct serialize_arrayref_tail_impl { serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {} - Error deserialize(msf::StreamReader &Reader) const { + Error deserialize(BinaryStreamReader &Reader) const { uint32_t Count = Reader.bytesRemaining() / sizeof(T); return Reader.readArray(Item, Count); } @@ -149,7 +149,7 @@ template <typename T> struct serialize_arrayref_tail_impl { template <typename T> struct serialize_numeric_impl { serialize_numeric_impl(T &Item) : Item(Item) {} - Error deserialize(msf::StreamReader &Reader) const { + Error deserialize(BinaryStreamReader &Reader) const { return consume_numeric(Reader, Item); } @@ -201,42 +201,42 @@ template <typename T> serialize_numeric_impl<T> serialize_numeric(T &Item) { #define CV_NUMERIC_FIELD(I) serialize_numeric(I) template <typename T, typename U> -Error consume(msf::StreamReader &Reader, +Error consume(BinaryStreamReader &Reader, const serialize_conditional_impl<T, U> &Item) { return Item.deserialize(Reader); } template <typename T, typename U> -Error consume(msf::StreamReader &Reader, +Error consume(BinaryStreamReader &Reader, const serialize_array_impl<T, U> &Item) { return Item.deserialize(Reader); } -inline Error consume(msf::StreamReader &Reader, +inline Error consume(BinaryStreamReader &Reader, const serialize_null_term_string_array_impl &Item) { return Item.deserialize(Reader); } template <typename T> -Error consume(msf::StreamReader &Reader, +Error consume(BinaryStreamReader &Reader, const serialize_vector_tail_impl<T> &Item) { return Item.deserialize(Reader); } template <typename T> -Error consume(msf::StreamReader &Reader, +Error consume(BinaryStreamReader &Reader, const serialize_arrayref_tail_impl<T> &Item) { return Item.deserialize(Reader); } template <typename T> -Error consume(msf::StreamReader &Reader, +Error consume(BinaryStreamReader &Reader, const serialize_numeric_impl<T> &Item) { return Item.deserialize(Reader); } template <typename T, typename U, typename... Args> -Error consume(msf::StreamReader &Reader, T &&X, U &&Y, Args &&... Rest) { +Error consume(BinaryStreamReader &Reader, T &&X, U &&Y, Args &&... Rest) { if (auto EC = consume(Reader, X)) return EC; return consume(Reader, Y, std::forward<Args>(Rest)...); diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h new file mode 100644 index 0000000..1a83882 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h @@ -0,0 +1,102 @@ +//===- StringsAndChecksums.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_STRINGSANDCHECKSUMS_H +#define LLVM_DEBUGINFO_CODEVIEW_STRINGSANDCHECKSUMS_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include <memory> + +namespace llvm { +namespace codeview { + +class StringsAndChecksumsRef { +public: + // If no subsections are known about initially, we find as much as we can. + StringsAndChecksumsRef(); + + // If only a string table subsection is given, we find a checksums subsection. + explicit StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings); + + // If both subsections are given, we don't need to find anything. + StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums); + + void setChecksums(const DebugChecksumsSubsectionRef &CS); + + template <typename T> void initialize(T &&FragmentRange) { + for (const DebugSubsectionRecord &R : FragmentRange) { + if (Strings && Checksums) + return; + if (R.kind() == DebugSubsectionKind::FileChecksums) { + initializeChecksums(R); + continue; + } + if (R.kind() == DebugSubsectionKind::StringTable && !Strings) { + // While in practice we should never encounter a string table even + // though the string table is already initialized, in theory it's + // possible. PDBs are supposed to have one global string table and + // then this subsection should not appear. Whereas object files are + // supposed to have this subsection appear exactly once. However, + // for testing purposes it's nice to be able to test this subsection + // independently of one format or the other, so for some tests we + // manually construct a PDB that contains this subsection in addition + // to a global string table. + initializeStrings(R); + continue; + } + } + } + + const DebugStringTableSubsectionRef &strings() const { return *Strings; } + const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; } + + bool hasStrings() const { return Strings != nullptr; } + bool hasChecksums() const { return Checksums != nullptr; } + +private: + void initializeStrings(const DebugSubsectionRecord &SR); + void initializeChecksums(const DebugSubsectionRecord &FCR); + + std::unique_ptr<DebugStringTableSubsectionRef> OwnedStrings; + std::unique_ptr<DebugChecksumsSubsectionRef> OwnedChecksums; + + const DebugStringTableSubsectionRef *Strings = nullptr; + const DebugChecksumsSubsectionRef *Checksums = nullptr; +}; + +class StringsAndChecksums { +public: + using StringsPtr = std::shared_ptr<DebugStringTableSubsection>; + using ChecksumsPtr = std::shared_ptr<DebugChecksumsSubsection>; + + // If no subsections are known about initially, we find as much as we can. + StringsAndChecksums() = default; + + void setStrings(const StringsPtr &SP) { Strings = SP; } + void setChecksums(const ChecksumsPtr &CP) { Checksums = CP; } + + const StringsPtr &strings() const { return Strings; } + const ChecksumsPtr &checksums() const { return Checksums; } + + bool hasStrings() const { return Strings != nullptr; } + bool hasChecksums() const { return Checksums != nullptr; } + +private: + StringsPtr Strings; + ChecksumsPtr Checksums; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_STRINGSANDCHECKSUMS_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h index 13c2bb1..5b6599d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h @@ -15,8 +15,8 @@ #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/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" namespace llvm { @@ -24,21 +24,40 @@ namespace codeview { class SymbolVisitorDelegate; class SymbolDeserializer : public SymbolVisitorCallbacks { struct MappingInfo { - explicit MappingInfo(ArrayRef<uint8_t> RecordData) - : Stream(RecordData), Reader(Stream), Mapping(Reader) {} + MappingInfo(ArrayRef<uint8_t> RecordData, CodeViewContainer Container) + : Stream(RecordData, llvm::support::little), Reader(Stream), + Mapping(Reader, Container) {} - msf::ByteStream Stream; - msf::StreamReader Reader; + BinaryByteStream Stream; + BinaryStreamReader Reader; SymbolRecordMapping Mapping; }; public: - explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate) - : Delegate(Delegate) {} + template <typename T> static Error deserializeAs(CVSymbol Symbol, T &Record) { + // If we're just deserializing one record, then don't worry about alignment + // as there's nothing that comes after. + SymbolDeserializer S(nullptr, CodeViewContainer::ObjectFile); + if (auto EC = S.visitSymbolBegin(Symbol)) + return EC; + if (auto EC = S.visitKnownRecord(Symbol, Record)) + return EC; + if (auto EC = S.visitSymbolEnd(Symbol)) + return EC; + return Error::success(); + } + + explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate, + CodeViewContainer Container) + : Delegate(Delegate), Container(Container) {} + + Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override { + return visitSymbolBegin(Record); + } Error visitSymbolBegin(CVSymbol &Record) override { assert(!Mapping && "Already in a symbol mapping!"); - Mapping = llvm::make_unique<MappingInfo>(Record.content()); + Mapping = llvm::make_unique<MappingInfo>(Record.content(), Container); return Mapping->Mapping.visitSymbolBegin(Record); } Error visitSymbolEnd(CVSymbol &Record) override { @@ -53,7 +72,7 @@ public: return visitKnownRecordImpl(CVR, Record); \ } #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "CVSymbolTypes.def" +#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" private: template <typename T> Error visitKnownRecordImpl(CVSymbol &CVR, T &Record) { @@ -66,6 +85,7 @@ private: } SymbolVisitorDelegate *Delegate; + CodeViewContainer Container; std::unique_ptr<MappingInfo> Mapping; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h index a5419b3..293daa8 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -20,15 +20,17 @@ namespace llvm { class ScopedPrinter; namespace codeview { -class TypeDatabase; +class TypeCollection; /// Dumper for CodeView symbol streams found in COFF object files and PDB files. class CVSymbolDumper { public: - CVSymbolDumper(ScopedPrinter &W, TypeDatabase &TypeDB, + CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types, + CodeViewContainer Container, std::unique_ptr<SymbolDumpDelegate> ObjDelegate, bool PrintRecordBytes) - : W(W), TypeDB(TypeDB), ObjDelegate(std::move(ObjDelegate)), + : W(W), Types(Types), Container(Container), + ObjDelegate(std::move(ObjDelegate)), PrintRecordBytes(PrintRecordBytes) {} /// Dumps one type record. Returns false if there was a type parsing error, @@ -43,7 +45,8 @@ public: private: ScopedPrinter &W; - TypeDatabase &TypeDB; + TypeCollection &Types; + CodeViewContainer Container; 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 57772d3..f3086cf 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -13,16 +13,14 @@ #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/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <cstddef> #include <cstdint> #include <vector> @@ -36,7 +34,6 @@ protected: public: SymbolRecordKind getKind() const { return Kind; } -private: SymbolRecordKind Kind; }; @@ -155,6 +152,7 @@ public: : SymbolRecord(Kind), RecordOffset(RecordOffset) {} std::vector<TypeIndex> Indices; + uint32_t RecordOffset; }; @@ -167,8 +165,8 @@ struct BinaryAnnotationIterator { int32_t S1; }; - BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {} BinaryAnnotationIterator() = default; + BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {} BinaryAnnotationIterator(const BinaryAnnotationIterator &Other) : Data(Other.Data) {} @@ -176,7 +174,7 @@ struct BinaryAnnotationIterator { return Data == Other.Data; } - bool operator!=(BinaryAnnotationIterator Other) const { + bool operator!=(const BinaryAnnotationIterator &Other) const { return !(*this == Other); } @@ -344,9 +342,9 @@ public: : SymbolRecord(SymbolRecordKind::InlineSiteSym), RecordOffset(RecordOffset) {} - llvm::iterator_range<BinaryAnnotationIterator> annotations() const { - return llvm::make_range(BinaryAnnotationIterator(AnnotationData), - BinaryAnnotationIterator()); + iterator_range<BinaryAnnotationIterator> annotations() const { + return make_range(BinaryAnnotationIterator(AnnotationData), + BinaryAnnotationIterator()); } uint32_t Parent; @@ -365,7 +363,7 @@ public: : SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset) {} - uint32_t Index; + PublicSymFlags Flags; uint32_t Offset; uint16_t Segment; StringRef Name; @@ -381,7 +379,7 @@ public: : SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset) {} - uint32_t Index; + TypeIndex Index; RegisterId Register; StringRef Name; @@ -481,6 +479,7 @@ public: ulittle16_t Register; ulittle16_t MayHaveNoName; }; + explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} DefRangeRegisterSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), @@ -503,6 +502,7 @@ public: ulittle16_t MayHaveNoName; ulittle32_t OffsetInParent; }; + explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} DefRangeSubfieldRegisterSym(uint32_t RecordOffset) @@ -548,6 +548,7 @@ public: ulittle16_t Flags; little32_t BasePointerOffset; }; + explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} explicit DefRangeRegisterRelSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), @@ -681,7 +682,7 @@ public: : SymbolRecord(SymbolRecordKind::FileStaticSym), RecordOffset(RecordOffset) {} - uint32_t Index; + TypeIndex Index; uint32_t ModFilenameOffset; LocalSymFlags Flags; StringRef Name; @@ -734,6 +735,10 @@ public: uint16_t VersionBackendQFE; StringRef Version; + void setLanguage(SourceLanguage Lang) { + Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang)); + } + uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; } uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; } @@ -816,7 +821,7 @@ public: uint32_t CodeOffset; uint16_t Register; - uint8_t CookieKind; + FrameCookieKind CookieKind; uint8_t Flags; uint32_t RecordOffset; @@ -843,7 +848,7 @@ public: : SymbolRecord(SymbolRecordKind::BuildInfoSym), RecordOffset(RecordOffset) {} - uint32_t BuildId; + TypeIndex BuildId; uint32_t RecordOffset; }; @@ -873,7 +878,7 @@ public: uint32_t Offset; TypeIndex Type; - uint16_t Register; + RegisterId Register; StringRef Name; uint32_t RecordOffset; @@ -937,8 +942,8 @@ public: uint32_t RecordOffset; }; -typedef CVRecord<SymbolKind> CVSymbol; -typedef msf::VarStreamArray<CVSymbol> CVSymbolArray; +using CVSymbol = CVRecord<SymbolKind>; +using CVSymbolArray = VarStreamArray<CVSymbol>; } // end namespace codeview } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h index 1bd14ed..391e8f1 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h @@ -14,16 +14,18 @@ #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" namespace llvm { -namespace msf { -class StreamReader; -class StreamWriter; -} +class BinaryStreamReader; +class BinaryStreamWriter; namespace codeview { class SymbolRecordMapping : public SymbolVisitorCallbacks { public: - explicit SymbolRecordMapping(msf::StreamReader &Reader) : IO(Reader) {} - explicit SymbolRecordMapping(msf::StreamWriter &Writer) : IO(Writer) {} + explicit SymbolRecordMapping(BinaryStreamReader &Reader, + CodeViewContainer Container) + : IO(Reader), Container(Container) {} + explicit SymbolRecordMapping(BinaryStreamWriter &Writer, + CodeViewContainer Container) + : IO(Writer), Container(Container) {} Error visitSymbolBegin(CVSymbol &Record) override; Error visitSymbolEnd(CVSymbol &Record) override; @@ -31,12 +33,13 @@ public: #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ Error visitKnownRecord(CVSymbol &CVR, Name &Record) override; #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "CVSymbolTypes.def" +#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" private: Optional<SymbolKind> Kind; CodeViewRecordIO IO; + CodeViewContainer Container; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h index 4eb914e..b63ced5 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolSerializer.h @@ -1,4 +1,4 @@ -//===- symbolSerializer.h ---------------------------------------*- C++ -*-===// +//===- SymbolSerializer.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,25 +10,27 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.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/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> namespace llvm { namespace codeview { class SymbolSerializer : public SymbolVisitorCallbacks { - uint32_t RecordStart = 0; - msf::StreamWriter &Writer; + BumpPtrAllocator &Storage; + std::vector<uint8_t> RecordBuffer; + MutableBinaryByteStream Stream; + BinaryStreamWriter Writer; SymbolRecordMapping Mapping; Optional<SymbolKind> CurrentSymbol; @@ -42,47 +44,29 @@ class SymbolSerializer : public SymbolVisitorCallbacks { } 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(); + SymbolSerializer(BumpPtrAllocator &Storage, CodeViewContainer Container); + + template <typename SymType> + static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage, + CodeViewContainer Container) { + CVSymbol Result; + Result.Type = static_cast<SymbolKind>(Sym.Kind); + SymbolSerializer Serializer(Storage, Container); + consumeError(Serializer.visitSymbolBegin(Result)); + consumeError(Serializer.visitKnownRecord(Result, Sym)); + consumeError(Serializer.visitSymbolEnd(Result)); + return Result; } - 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(); - } + Error visitSymbolBegin(CVSymbol &Record) override; + Error visitSymbolEnd(CVSymbol &Record) override; #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ - virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \ + Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \ return visitKnownRecordImpl(CVR, Record); \ } #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "CVSymbolTypes.def" +#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" private: template <typename RecordKind> @@ -90,7 +74,8 @@ private: return Mapping.visitKnownRecord(CVR, Record); } }; -} -} -#endif +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h index 96a93bf..e29511a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h @@ -30,6 +30,14 @@ public: return Error::success(); } + Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitSymbolBegin(Record, Offset)) + return EC; + } + return Error::success(); + } + Error visitSymbolBegin(CVSymbol &Record) override { for (auto Visitor : Pipeline) { if (auto EC = Visitor->visitSymbolBegin(Record)) @@ -59,7 +67,7 @@ public: return Error::success(); \ } #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def" +#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" private: std::vector<SymbolVisitorCallbacks *> Pipeline; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h index aaa9d2e..0816f7c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h @@ -29,8 +29,10 @@ public: /// 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. + /// return the type of the Symbol, or an error if it cannot be determined. + virtual Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) { + return Error::success(); + } virtual Error visitSymbolBegin(CVSymbol &Record) { return Error::success(); } virtual Error visitSymbolEnd(CVSymbol &Record) { return Error::success(); } @@ -39,7 +41,7 @@ public: return Error::success(); \ } #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "CVSymbolTypes.def" +#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" }; } // end namespace codeview diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h index 2b468a2..a2a3c6f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h @@ -15,19 +15,19 @@ namespace llvm { -namespace msf { -class StreamReader; -} // end namespace msf +class BinaryStreamReader; namespace codeview { +class DebugStringTableSubsectionRef; + class SymbolVisitorDelegate { public: virtual ~SymbolVisitorDelegate() = default; - virtual uint32_t getRecordOffset(msf::StreamReader Reader) = 0; + virtual uint32_t getRecordOffset(BinaryStreamReader Reader) = 0; virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0; - virtual StringRef getStringTable() = 0; + virtual DebugStringTableSubsectionRef getStringTable() = 0; }; } // end namespace codeview diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h new file mode 100644 index 0000000..0f856f5 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h @@ -0,0 +1,38 @@ +//===- TypeCollection.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_TYPECOLLECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H + +#include "llvm/ADT/StringRef.h" + +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" + +namespace llvm { +namespace codeview { +class TypeCollection { +public: + virtual ~TypeCollection() = default; + + bool empty() { return size() == 0; } + + virtual Optional<TypeIndex> getFirst() = 0; + virtual Optional<TypeIndex> getNext(TypeIndex Prev) = 0; + + virtual CVType getType(TypeIndex Index) = 0; + virtual StringRef getTypeName(TypeIndex Index) = 0; + virtual bool contains(TypeIndex Index) = 0; + virtual uint32_t size() = 0; + virtual uint32_t capacity() = 0; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h deleted file mode 100644 index cccc286..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h +++ /dev/null @@ -1,55 +0,0 @@ -//===- 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 deleted file mode 100644 index 39d234c..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h +++ /dev/null @@ -1,53 +0,0 @@ -//===-- 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 index dc5eaf8..965cdfd 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h @@ -16,8 +16,8 @@ #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/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" #include <cassert> #include <cstdint> @@ -29,22 +29,39 @@ namespace codeview { class TypeDeserializer : public TypeVisitorCallbacks { struct MappingInfo { explicit MappingInfo(ArrayRef<uint8_t> RecordData) - : Stream(RecordData), Reader(Stream), Mapping(Reader) {} + : Stream(RecordData, llvm::support::little), Reader(Stream), + Mapping(Reader) {} - msf::ByteStream Stream; - msf::StreamReader Reader; + BinaryByteStream Stream; + BinaryStreamReader Reader; TypeRecordMapping Mapping; }; public: TypeDeserializer() = default; + template <typename T> static Error deserializeAs(CVType &CVT, T &Record) { + Record.Kind = static_cast<TypeRecordKind>(CVT.kind()); + MappingInfo I(CVT.content()); + if (auto EC = I.Mapping.visitTypeBegin(CVT)) + return EC; + if (auto EC = I.Mapping.visitKnownRecord(CVT, Record)) + return EC; + if (auto EC = I.Mapping.visitTypeEnd(CVT)) + return EC; + return Error::success(); + } + 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 visitTypeBegin(CVType &Record, TypeIndex Index) override { + return visitTypeBegin(Record); + } + Error visitTypeEnd(CVType &Record) override { assert(Mapping && "Not in a type mapping!"); auto EC = Mapping->Mapping.visitTypeEnd(Record); @@ -59,7 +76,7 @@ public: #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" +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" private: template <typename RecordType> @@ -72,16 +89,16 @@ private: class FieldListDeserializer : public TypeVisitorCallbacks { struct MappingInfo { - explicit MappingInfo(msf::StreamReader &R) + explicit MappingInfo(BinaryStreamReader &R) : Reader(R), Mapping(Reader), StartOffset(0) {} - msf::StreamReader &Reader; + BinaryStreamReader &Reader; TypeRecordMapping Mapping; uint32_t StartOffset; }; public: - explicit FieldListDeserializer(msf::StreamReader &Reader) : Mapping(Reader) { + explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) { CVType FieldList; FieldList.Type = TypeLeafKind::LF_FIELDLIST; consumeError(Mapping.Mapping.visitTypeBegin(FieldList)); @@ -111,7 +128,7 @@ public: } #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "TypeRecords.def" +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" private: template <typename RecordType> diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h index a466e42..afb8b36 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h @@ -12,7 +12,6 @@ #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" @@ -22,14 +21,25 @@ class ScopedPrinter; namespace codeview { +class TypeCollection; + /// 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) {} + TypeDumpVisitor(TypeCollection &TpiTypes, ScopedPrinter *W, + bool PrintRecordBytes) + : W(W), PrintRecordBytes(PrintRecordBytes), TpiTypes(TpiTypes) {} + + /// When dumping types from an IPI stream in a PDB, a type index may refer to + /// a type or an item ID. The dumper will lookup the "name" of the index in + /// the item database if appropriate. If ItemDB is null, it will use TypeDB, + /// which is correct when dumping types from an object file (/Z7). + void setIpiTypes(TypeCollection &Types) { IpiTypes = &Types; } void printTypeIndex(StringRef FieldName, TypeIndex TI) const; + void printItemIndex(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; @@ -37,6 +47,7 @@ public: /// Paired begin/end actions for all types. Receives all record data, /// including the fixed-length record prefix. Error visitTypeBegin(CVType &Record) override; + Error visitTypeBegin(CVType &Record, TypeIndex Index) override; Error visitTypeEnd(CVType &Record) override; Error visitMemberBegin(CVMemberRecord &Record) override; Error visitMemberEnd(CVMemberRecord &Record) override; @@ -47,18 +58,26 @@ public: 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" +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" private: void printMemberAttributes(MemberAttributes Attrs); void printMemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Options); + /// Get the database of indices for the stream that we are dumping. If ItemDB + /// is set, then we must be dumping an item (IPI) stream. This will also + /// always get the appropriate DB for printing item names. + TypeCollection &getSourceTypes() const { + return IpiTypes ? *IpiTypes : TpiTypes; + } + ScopedPrinter *W; bool PrintRecordBytes = false; - TypeDatabase &TypeDB; + TypeCollection &TpiTypes; + TypeCollection *IpiTypes = nullptr; }; } // end namespace codeview diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumperBase.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumperBase.h deleted file mode 100644 index e69de29..0000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeDumperBase.h +++ /dev/null diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h index 3c11d24..e0c2226 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -10,13 +10,20 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H #define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/Endian.h" #include <cassert> #include <cinttypes> +#include <functional> namespace llvm { + +class ScopedPrinter; + namespace codeview { +class TypeCollection; + enum class SimpleTypeKind : uint32_t { None = 0x0000, // uncharacterized type (no type) Void = 0x0003, // void @@ -106,6 +113,15 @@ public: bool isNoneType() const { return *this == None(); } + uint32_t toArrayIndex() const { + assert(!isSimple()); + return getIndex() - FirstNonSimpleIndex; + } + + static TypeIndex fromArrayIndex(uint32_t Index) { + return TypeIndex(Index + FirstNonSimpleIndex); + } + SimpleTypeKind getSimpleKind() const { assert(isSimple()); return static_cast<SimpleTypeKind>(Index & SimpleKindMask); @@ -159,6 +175,39 @@ public: static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); } static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); } + TypeIndex &operator+=(unsigned N) { + Index += N; + return *this; + } + + TypeIndex &operator++() { + Index += 1; + return *this; + } + + TypeIndex operator++(int) { + TypeIndex Copy = *this; + operator++(); + return Copy; + } + + TypeIndex &operator-=(unsigned N) { + assert(Index >= N); + Index -= N; + return *this; + } + + TypeIndex &operator--() { + Index -= 1; + return *this; + } + + TypeIndex operator--(int) { + TypeIndex Copy = *this; + operator--(); + return Copy; + } + friend inline bool operator==(const TypeIndex &A, const TypeIndex &B) { return A.getIndex() == B.getIndex(); } @@ -183,11 +232,58 @@ public: return A.getIndex() >= B.getIndex(); } + friend inline TypeIndex operator+(const TypeIndex &A, uint32_t N) { + TypeIndex Result(A); + Result += N; + return Result; + } + + friend inline TypeIndex operator-(const TypeIndex &A, uint32_t N) { + assert(A.getIndex() >= N); + TypeIndex Result(A); + Result -= N; + return Result; + } + + friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) { + assert(A >= B); + return A.toArrayIndex() - B.toArrayIndex(); + } + + static StringRef simpleTypeName(TypeIndex TI); + private: support::ulittle32_t Index; }; +// Used for pseudo-indexing an array of type records. An array of such records +// sorted by TypeIndex can allow log(N) lookups even though such a type record +// stream does not provide random access. +struct TypeIndexOffset { + TypeIndex Type; + support::ulittle32_t Offset; +}; + +void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI, + TypeCollection &Types); } -} + +template <> struct DenseMapInfo<codeview::TypeIndex> { + static inline codeview::TypeIndex getEmptyKey() { + return codeview::TypeIndex{DenseMapInfo<uint32_t>::getEmptyKey()}; + } + static inline codeview::TypeIndex getTombstoneKey() { + return codeview::TypeIndex{DenseMapInfo<uint32_t>::getTombstoneKey()}; + } + static unsigned getHashValue(const codeview::TypeIndex &TI) { + return DenseMapInfo<uint32_t>::getHashValue(TI.getIndex()); + } + static bool isEqual(const codeview::TypeIndex &LHS, + const codeview::TypeIndex &RHS) { + return LHS == RHS; + } +}; + +} // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h new file mode 100644 index 0000000..afe8942 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h @@ -0,0 +1,41 @@ +//===- TypeIndexDiscovery.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_TYPEINDEXDISCOVERY_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEXDISCOVERY_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +enum class TiRefKind { TypeRef, IndexRef }; +struct TiReference { + TiRefKind Kind; + uint32_t Offset; + uint32_t Count; +}; + +void discoverTypeIndices(ArrayRef<uint8_t> RecordData, + SmallVectorImpl<TiReference> &Refs); +void discoverTypeIndices(const CVType &Type, + SmallVectorImpl<TiReference> &Refs); +void discoverTypeIndices(const CVType &Type, + SmallVectorImpl<TypeIndex> &Indices); + +/// Discover type indices in symbol records. Returns false if this is an unknown +/// record. +bool discoverTypeIndices(const CVSymbol &Symbol, + SmallVectorImpl<TiReference> &Refs); +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeName.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeName.h new file mode 100644 index 0000000..a987b4a --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeName.h @@ -0,0 +1,22 @@ +//===- TypeName.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_TYPENAME_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPENAME_H + +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" + +namespace llvm { +namespace codeview { +std::string computeTypeName(TypeCollection &Types, TypeIndex Index); +} +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h index 4f1c047..7942c0c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -15,41 +15,42 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/GUID.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/MSF/StreamArray.h" +#include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/Endian.h" #include <algorithm> #include <cstdint> #include <vector> namespace llvm { - -namespace msf { -class StreamReader; -} // end namespace msf - namespace codeview { using support::little32_t; using support::ulittle16_t; using support::ulittle32_t; -typedef CVRecord<TypeLeafKind> CVType; +using CVType = CVRecord<TypeLeafKind>; +using RemappedType = RemappedRecord<TypeLeafKind>; struct CVMemberRecord { TypeLeafKind Kind; ArrayRef<uint8_t> Data; }; -typedef msf::VarStreamArray<CVType> CVTypeArray; +using CVTypeArray = VarStreamArray<CVType>; +using CVTypeRange = iterator_range<CVTypeArray::Iterator>; /// Equvalent to CV_fldattr_t in cvinfo.h. struct MemberAttributes { uint16_t Attrs = 0; + enum { MethodKindShift = 2, }; + MemberAttributes() = default; explicit MemberAttributes(MemberAccess Access) @@ -106,10 +107,6 @@ public: PointerToMemberRepresentation Representation) : ContainingType(ContainingType), Representation(Representation) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getContainingType() const { return ContainingType; } PointerToMemberRepresentation getRepresentation() const { return Representation; @@ -127,22 +124,18 @@ protected: public: TypeRecordKind getKind() const { return Kind; } -private: TypeRecordKind Kind; }; // LF_MODIFIER class ModifierRecord : public TypeRecord { public: + ModifierRecord() = default; explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers) : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType), Modifiers(Modifiers) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getModifiedType() const { return ModifiedType; } ModifierOptions getModifiers() const { return Modifiers; } @@ -153,6 +146,7 @@ public: // LF_PROCEDURE class ProcedureRecord : public TypeRecord { public: + ProcedureRecord() = default; explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv, FunctionOptions Options, uint16_t ParameterCount, @@ -161,10 +155,6 @@ public: CallConv(CallConv), Options(Options), ParameterCount(ParameterCount), ArgumentList(ArgumentList) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getReturnType() const { return ReturnType; } CallingConvention getCallConv() const { return CallConv; } FunctionOptions getOptions() const { return Options; } @@ -181,6 +171,7 @@ public: // LF_MFUNCTION class MemberFunctionRecord : public TypeRecord { public: + MemberFunctionRecord() = default; explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType, @@ -193,10 +184,6 @@ public: ArgumentList(ArgumentList), ThisPointerAdjustment(ThisPointerAdjustment) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getReturnType() const { return ReturnType; } TypeIndex getClassType() const { return ClassType; } TypeIndex getThisType() const { return ThisType; } @@ -216,38 +203,58 @@ public: int32_t ThisPointerAdjustment; }; +// LF_LABEL +class LabelRecord : public TypeRecord { +public: + LabelRecord() = default; + explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {} + + LabelType Mode; +}; + // LF_MFUNC_ID class MemberFuncIdRecord : public TypeRecord { public: + MemberFuncIdRecord() = default; explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType, StringRef Name) : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType), FunctionType(FunctionType), Name(Name) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getClassType() const { return ClassType; } TypeIndex getFunctionType() const { return FunctionType; } StringRef getName() const { return Name; } + TypeIndex ClassType; TypeIndex FunctionType; StringRef Name; }; -// LF_ARGLIST, LF_SUBSTR_LIST +// LF_ARGLIST class ArgListRecord : public TypeRecord { public: + ArgListRecord() = default; explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices) - : TypeRecord(Kind), StringIndices(Indices) {} + : TypeRecord(Kind), ArgIndices(Indices) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); + ArrayRef<TypeIndex> getIndices() const { return ArgIndices; } + + std::vector<TypeIndex> ArgIndices; +}; + +// LF_SUBSTR_LIST +class StringListRecord : public TypeRecord { +public: + StringListRecord() = default; + explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices) + : TypeRecord(Kind), StringIndices(Indices) {} ArrayRef<TypeIndex> getIndices() const { return StringIndices; } @@ -268,6 +275,7 @@ public: static const uint32_t PointerSizeShift = 13; static const uint32_t PointerSizeMask = 0xFF; + PointerRecord() = default; explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} PointerRecord(TypeIndex ReferentType, uint32_t Attrs) @@ -280,19 +288,9 @@ public: 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) + PointerOptions PO, uint8_t Size, const MemberPointerInfo &MPI) : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), - 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); + Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(MPI) {} TypeIndex getReferentType() const { return ReferentType; } @@ -334,7 +332,6 @@ public: TypeIndex ReferentType; uint32_t Attrs; - Optional<MemberPointerInfo> MemberInfo; private: @@ -352,14 +349,11 @@ private: // LF_NESTTYPE class NestedTypeRecord : public TypeRecord { public: + NestedTypeRecord() = default; explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} NestedTypeRecord(TypeIndex Type, StringRef Name) : TypeRecord(TypeRecordKind::NestedType), 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); - TypeIndex getNestedType() const { return Type; } StringRef getName() const { return Name; } @@ -370,30 +364,24 @@ public: // LF_FIELDLIST class FieldListRecord : public TypeRecord { public: + FieldListRecord() = default; 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: + ArrayRecord() = default; explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size, StringRef Name) : TypeRecord(TypeRecordKind::Array), ElementType(ElementType), IndexType(IndexType), Size(Size), Name(Name) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getElementType() const { return ElementType; } TypeIndex getIndexType() const { return IndexType; } uint64_t getSize() const { return Size; } @@ -407,6 +395,7 @@ public: class TagRecord : public TypeRecord { protected: + TagRecord() = default; explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, StringRef Name, StringRef UniqueName) @@ -414,10 +403,6 @@ protected: FieldList(FieldList), Name(Name), UniqueName(UniqueName) {} public: - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - static const int HfaKindShift = 11; static const int HfaKindMask = 0x1800; static const int WinRTKindShift = 14; @@ -443,6 +428,7 @@ public: // LF_CLASS, LF_STRUCTURE, LF_INTERFACE class ClassRecord : public TagRecord { public: + ClassRecord() = default; explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {} ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, TypeIndex DerivationList, @@ -451,10 +437,6 @@ public: : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName), 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); - HfaKind getHfa() const { uint16_t Value = static_cast<uint16_t>(Options); Value = (Value & HfaKindMask) >> HfaKindShift; @@ -478,6 +460,7 @@ public: // LF_UNION struct UnionRecord : public TagRecord { + UnionRecord() = default; explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {} UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, uint64_t Size, StringRef Name, StringRef UniqueName) @@ -499,6 +482,7 @@ struct UnionRecord : public TagRecord { // LF_ENUM class EnumRecord : public TagRecord { public: + EnumRecord() = default; explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {} EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType) @@ -506,28 +490,24 @@ public: UniqueName), UnderlyingType(UnderlyingType) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getUnderlyingType() const { return UnderlyingType; } + TypeIndex UnderlyingType; }; // LF_BITFIELD class BitFieldRecord : public TypeRecord { public: + BitFieldRecord() = default; explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset) : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize), BitOffset(BitOffset) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getType() const { return Type; } uint8_t getBitOffset() const { return BitOffset; } uint8_t getBitSize() const { return BitSize; } + TypeIndex Type; uint8_t BitSize; uint8_t BitOffset; @@ -536,16 +516,13 @@ public: // LF_VTSHAPE class VFTableShapeRecord : public TypeRecord { public: + VFTableShapeRecord() = default; explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots) : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {} explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots) : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - ArrayRef<VFTableSlotKind> getSlots() const { if (!SlotsRef.empty()) return SlotsRef; @@ -553,6 +530,7 @@ public: } uint32_t getEntryCount() const { return getSlots().size(); } + ArrayRef<VFTableSlotKind> SlotsRef; std::vector<VFTableSlotKind> Slots; }; @@ -560,22 +538,19 @@ public: // LF_TYPESERVER2 class TypeServer2Record : public TypeRecord { public: + TypeServer2Record() = default; explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {} - TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name) - : TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age), - Name(Name) {} - - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - - StringRef getGuid() const { return Guid; } + TypeServer2Record(StringRef GuidStr, uint32_t Age, StringRef Name) + : TypeRecord(TypeRecordKind::TypeServer2), Age(Age), Name(Name) { + assert(GuidStr.size() == 16 && "guid isn't 16 bytes"); + ::memcpy(Guid.Guid, GuidStr.data(), 16); + } + const GUID &getGuid() const { return Guid; } uint32_t getAge() const { return Age; } - StringRef getName() const { return Name; } - StringRef Guid; + GUID Guid; uint32_t Age; StringRef Name; }; @@ -583,17 +558,14 @@ public: // LF_STRING_ID class StringIdRecord : public TypeRecord { public: + StringIdRecord() = default; explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} StringIdRecord(TypeIndex Id, StringRef String) : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getId() const { return Id; } - StringRef getString() const { return String; } + TypeIndex Id; StringRef String; }; @@ -601,19 +573,14 @@ public: // LF_FUNC_ID class FuncIdRecord : public TypeRecord { public: + FuncIdRecord() = default; explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name) : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope), FunctionType(FunctionType), Name(Name) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getParentScope() const { return ParentScope; } - TypeIndex getFunctionType() const { return FunctionType; } - StringRef getName() const { return Name; } TypeIndex ParentScope; @@ -624,15 +591,12 @@ public: // LF_UDT_SRC_LINE class UdtSourceLineRecord : public TypeRecord { public: + UdtSourceLineRecord() = default; explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber) : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), SourceFile(SourceFile), LineNumber(LineNumber) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getUDT() const { return UDT; } TypeIndex getSourceFile() const { return SourceFile; } uint32_t getLineNumber() const { return LineNumber; } @@ -645,14 +609,13 @@ public: // LF_UDT_MOD_SRC_LINE class UdtModSourceLineRecord : public TypeRecord { public: + UdtModSourceLineRecord() = default; explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber, uint16_t Module) : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {} - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getUDT() const { return UDT; } TypeIndex getSourceFile() const { return SourceFile; } uint32_t getLineNumber() const { return LineNumber; } @@ -667,22 +630,21 @@ public: // LF_BUILDINFO class BuildInfoRecord : public TypeRecord { public: + BuildInfoRecord() = default; explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices) : TypeRecord(TypeRecordKind::BuildInfo), ArgIndices(ArgIndices.begin(), ArgIndices.end()) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - ArrayRef<TypeIndex> getArgs() const { return ArgIndices; } + SmallVector<TypeIndex, 4> ArgIndices; }; // LF_VFTABLE class VFTableRecord : public TypeRecord { public: + VFTableRecord() = default; explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable, uint32_t VFPtrOffset, StringRef Name, @@ -693,14 +655,11 @@ public: 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); - TypeIndex getCompleteClass() const { return CompleteClass; } TypeIndex getOverriddenVTable() const { return OverriddenVFTable; } uint32_t getVFPtrOffset() const { return VFPtrOffset; } StringRef getName() const { return makeArrayRef(MethodNames).front(); } + ArrayRef<StringRef> getMethodNames() const { return makeArrayRef(MethodNames).drop_front(); } @@ -714,7 +673,7 @@ public: // LF_ONEMETHOD class OneMethodRecord : public TypeRecord { public: - OneMethodRecord() : TypeRecord(TypeRecordKind::OneMethod) {} + OneMethodRecord() = default; explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} OneMethodRecord(TypeIndex Type, MemberAttributes Attrs, int32_t VFTableOffset, StringRef Name) @@ -725,10 +684,6 @@ public: : 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); - TypeIndex getType() const { return Type; } MethodKind getMethodKind() const { return Attrs.getMethodKind(); } MethodOptions getOptions() const { return Attrs.getFlags(); } @@ -750,34 +705,30 @@ public: // LF_METHODLIST class MethodOverloadListRecord : public TypeRecord { public: + MethodOverloadListRecord() = default; explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods) : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - ArrayRef<OneMethodRecord> getMethods() const { return Methods; } + std::vector<OneMethodRecord> Methods; }; /// For method overload sets. LF_METHOD class OverloadedMethodRecord : public TypeRecord { public: + OverloadedMethodRecord() = default; explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList, StringRef Name) : TypeRecord(TypeRecordKind::OverloadedMethod), NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - uint16_t getNumOverloads() const { return NumOverloads; } TypeIndex getMethodList() const { return MethodList; } StringRef getName() const { return Name; } + uint16_t NumOverloads; TypeIndex MethodList; StringRef Name; @@ -786,6 +737,7 @@ public: // LF_MEMBER class DataMemberRecord : public TypeRecord { public: + DataMemberRecord() = default; explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset, StringRef Name) @@ -796,10 +748,6 @@ public: : 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); - MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getType() const { return Type; } uint64_t getFieldOffset() const { return FieldOffset; } @@ -814,6 +762,7 @@ public: // LF_STMEMBER class StaticDataMemberRecord : public TypeRecord { public: + StaticDataMemberRecord() = default; explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name) : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type), @@ -822,10 +771,6 @@ public: : 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); - MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getType() const { return Type; } StringRef getName() const { return Name; } @@ -838,6 +783,7 @@ public: // LF_ENUMERATE class EnumeratorRecord : public TypeRecord { public: + EnumeratorRecord() = default; explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name) : TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs), @@ -846,10 +792,6 @@ public: : 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); - MemberAccess getAccess() const { return Attrs.getAccess(); } APSInt getValue() const { return Value; } StringRef getName() const { return Name; } @@ -862,14 +804,11 @@ public: // LF_VFUNCTAB class VFPtrRecord : public TypeRecord { public: + VFPtrRecord() = default; explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} VFPtrRecord(TypeIndex Type) : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {} - /// Rewrite member type indices with IndexMap. Returns false if a type index - /// is not in the map. - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex getType() const { return Type; } TypeIndex Type; @@ -878,6 +817,7 @@ public: // LF_BCLASS, LF_BINTERFACE class BaseClassRecord : public TypeRecord { public: + BaseClassRecord() = default; explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset) : TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type), @@ -886,10 +826,6 @@ public: : 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); - MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getBaseType() const { return Type; } uint64_t getBaseOffset() const { return Offset; } @@ -902,6 +838,7 @@ public: // LF_VBCLASS, LF_IVBCLASS class VirtualBaseClassRecord : public TypeRecord { public: + VirtualBaseClassRecord() = default; explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs, TypeIndex BaseType, TypeIndex VBPtrType, @@ -914,10 +851,6 @@ public: : 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); - MemberAccess getAccess() const { return Attrs.getAccess(); } TypeIndex getBaseType() const { return BaseType; } TypeIndex getVBPtrType() const { return VBPtrType; } @@ -935,6 +868,7 @@ public: /// together. The first will end in an LF_INDEX record that points to the next. class ListContinuationRecord : public TypeRecord { public: + ListContinuationRecord() = default; explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} ListContinuationRecord(TypeIndex ContinuationIndex) : TypeRecord(TypeRecordKind::ListContinuation), @@ -942,13 +876,10 @@ public: TypeIndex getContinuationIndex() const { return ContinuationIndex; } - bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap); - TypeIndex ContinuationIndex; }; } // end namespace codeview - } // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h index fe470a7..cbe8d60 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h @@ -16,16 +16,16 @@ #include "llvm/Support/Error.h" namespace llvm { -namespace msf { -class StreamReader; -class StreamWriter; -} +class BinaryStreamReader; +class BinaryStreamWriter; + namespace codeview { class TypeRecordMapping : public TypeVisitorCallbacks { public: - explicit TypeRecordMapping(msf::StreamReader &Reader) : IO(Reader) {} - explicit TypeRecordMapping(msf::StreamWriter &Writer) : IO(Writer) {} + explicit TypeRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {} + explicit TypeRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {} + using TypeVisitorCallbacks::visitTypeBegin; Error visitTypeBegin(CVType &Record) override; Error visitTypeEnd(CVType &Record) override; @@ -38,7 +38,7 @@ public: 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" +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" private: Optional<TypeLeafKind> TypeKind; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h index e059221..0e734a8 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h @@ -10,22 +10,29 @@ #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/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Error.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <vector> namespace llvm { - namespace codeview { +class TypeHasher; + class TypeSerializer : public TypeVisitorCallbacks { struct SubRecord { SubRecord(TypeLeafKind K, uint32_t S) : Kind(K), Size(S) {} @@ -45,43 +52,54 @@ class TypeSerializer : public TypeVisitorCallbacks { } }; - typedef SmallVector<MutableArrayRef<uint8_t>, 2> RecordList; + using MutableRecordList = SmallVector<MutableArrayRef<uint8_t>, 2>; static constexpr uint8_t ContinuationLength = 8; BumpPtrAllocator &RecordStorage; RecordSegment CurrentSegment; - RecordList FieldListSegments; + MutableRecordList FieldListSegments; - TypeIndex LastTypeIndex; Optional<TypeLeafKind> TypeKind; Optional<TypeLeafKind> MemberKind; std::vector<uint8_t> RecordBuffer; - msf::MutableByteStream Stream; - msf::StreamWriter Writer; + MutableBinaryByteStream Stream; + BinaryStreamWriter Writer; TypeRecordMapping Mapping; - RecordList SeenRecords; - StringMap<TypeIndex> HashedRecords; + /// Private type record hashing implementation details are handled here. + std::unique_ptr<TypeHasher> Hasher; + + /// Contains a list of all records indexed by TypeIndex.toArrayIndex(). + SmallVector<ArrayRef<uint8_t>, 2> SeenRecords; + + /// Temporary storage that we use to copy a record's data while re-writing + /// its type indices. + SmallVector<uint8_t, 256> RemapStorage; + + TypeIndex nextTypeIndex() const; 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); + explicit TypeSerializer(BumpPtrAllocator &Storage, bool Hash = true); + ~TypeSerializer() override; - ArrayRef<MutableArrayRef<uint8_t>> records() const; - TypeIndex getLastTypeIndex() const; - TypeIndex insertRecordBytes(MutableArrayRef<uint8_t> Record); + void reset(); + + BumpPtrAllocator &getAllocator() { return RecordStorage; } + + ArrayRef<ArrayRef<uint8_t>> records() const; + TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record); + TypeIndex insertRecord(const RemappedType &Record); Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record); + using TypeVisitorCallbacks::visitTypeBegin; Error visitTypeBegin(CVType &Record) override; Error visitTypeEnd(CVType &Record) override; Error visitMemberBegin(CVMemberRecord &Record) override; @@ -97,7 +115,7 @@ public: return visitKnownMemberImpl<Name##Record>(CVR, Record); \ } #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "llvm/DebugInfo/CodeView/TypeRecords.def" +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" private: template <typename RecordKind> @@ -134,7 +152,8 @@ private: return Error::success(); } }; -} -} -#endif +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h index af396c7..d78fab4 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h @@ -12,13 +12,76 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Error.h" namespace llvm { namespace codeview { -/// Merges one type stream into another. Returns true on success. -bool mergeTypeStreams(TypeTableBuilder &DestStream, const CVTypeArray &Types); +class TypeIndex; +class TypeTableBuilder; + +/// \brief Merge one set of type records into another. This method assumes +/// that all records are type records, and there are no Id records present. +/// +/// \param Dest The table to store the re-written type records into. +/// +/// \param SourceToDest A vector, indexed by the TypeIndex in the source +/// type stream, that contains the index of the corresponding type record +/// in the destination stream. +/// +/// \param Types The collection of types to merge in. +/// +/// \returns Error::success() if the operation succeeded, otherwise an +/// appropriate error code. +Error mergeTypeRecords(TypeTableBuilder &Dest, + SmallVectorImpl<TypeIndex> &SourceToDest, + const CVTypeArray &Types); + +/// \brief Merge one set of id records into another. This method assumes +/// that all records are id records, and there are no Type records present. +/// However, since Id records can refer back to Type records, this method +/// assumes that the referenced type records have also been merged into +/// another type stream (for example using the above method), and accepts +/// the mapping from source to dest for that stream so that it can re-write +/// the type record mappings accordingly. +/// +/// \param Dest The table to store the re-written id records into. +/// +/// \param Types The mapping to use for the type records that these id +/// records refer to. +/// +/// \param SourceToDest A vector, indexed by the TypeIndex in the source +/// id stream, that contains the index of the corresponding id record +/// in the destination stream. +/// +/// \param Ids The collection of id records to merge in. +/// +/// \returns Error::success() if the operation succeeded, otherwise an +/// appropriate error code. +Error mergeIdRecords(TypeTableBuilder &Dest, ArrayRef<TypeIndex> Types, + SmallVectorImpl<TypeIndex> &SourceToDest, + const CVTypeArray &Ids); + +/// \brief Merge a unified set of type and id records, splitting them into +/// separate output streams. +/// +/// \param DestIds The table to store the re-written id records into. +/// +/// \param DestTypes the table to store the re-written type records into. +/// +/// \param SourceToDest A vector, indexed by the TypeIndex in the source +/// id stream, that contains the index of the corresponding id record +/// in the destination stream. +/// +/// \param IdsAndTypes The collection of id records to merge in. +/// +/// \returns Error::success() if the operation succeeded, otherwise an +/// appropriate error code. +Error mergeTypeAndIdRecords(TypeTableBuilder &DestIds, + TypeTableBuilder &DestTypes, + SmallVectorImpl<TypeIndex> &SourceToDest, + const CVTypeArray &IdsAndTypes); } // end namespace codeview } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h index 4e6d81e..1069dcd 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h @@ -13,8 +13,8 @@ #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/DebugInfo/CodeView/TypeSerializer.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Error.h" #include <algorithm> @@ -37,8 +37,9 @@ private: TypeSerializer Serializer; public: - explicit TypeTableBuilder(BumpPtrAllocator &Allocator) - : Allocator(Allocator), Serializer(Allocator) {} + explicit TypeTableBuilder(BumpPtrAllocator &Allocator, + bool WriteUnique = true) + : Allocator(Allocator), Serializer(Allocator, WriteUnique) {} TypeTableBuilder(const TypeTableBuilder &) = delete; TypeTableBuilder &operator=(const TypeTableBuilder &) = delete; @@ -64,10 +65,14 @@ public: return *ExpectedIndex; } - TypeIndex writeSerializedRecord(MutableArrayRef<uint8_t> Record) { + TypeIndex writeSerializedRecord(ArrayRef<uint8_t> Record) { return Serializer.insertRecordBytes(Record); } + TypeIndex writeSerializedRecord(const RemappedType &Record) { + return Serializer.insertRecord(Record); + } + template <typename TFunc> void ForEachRecord(TFunc Func) { uint32_t Index = TypeIndex::FirstNonSimpleIndex; @@ -77,23 +82,24 @@ public: } } - ArrayRef<MutableArrayRef<uint8_t>> records() const { - return Serializer.records(); - } + ArrayRef<ArrayRef<uint8_t>> records() const { return Serializer.records(); } }; class FieldListRecordBuilder { TypeTableBuilder &TypeTable; + BumpPtrAllocator Allocator; TypeSerializer TempSerializer; CVType Type; public: explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable) - : TypeTable(TypeTable), TempSerializer(TypeTable.getAllocator()) { + : TypeTable(TypeTable), TempSerializer(Allocator, false) { Type.Type = TypeLeafKind::LF_FIELDLIST; } void begin() { + TempSerializer.reset(); + if (auto EC = TempSerializer.visitTypeBegin(Type)) consumeError(std::move(EC)); } @@ -109,16 +115,18 @@ public: consumeError(std::move(EC)); } - TypeIndex end() { + TypeIndex end(bool Write) { + TypeIndex Index; if (auto EC = TempSerializer.visitTypeEnd(Type)) { consumeError(std::move(EC)); return TypeIndex(); } - TypeIndex Index; - for (auto Record : TempSerializer.records()) { - Index = TypeTable.writeSerializedRecord(Record); + if (Write) { + for (auto Record : TempSerializer.records()) + Index = TypeTable.writeSerializedRecord(Record); } + return Index; } }; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableCollection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableCollection.h new file mode 100644 index 0000000..80326a0 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeTableCollection.h @@ -0,0 +1,43 @@ +//===- TypeTableCollection.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_TYPETABLECOLLECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H + +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/Support/StringSaver.h" + +#include <vector> + +namespace llvm { +namespace codeview { + +class TypeTableCollection : public TypeCollection { +public: + explicit TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records); + + Optional<TypeIndex> getFirst() override; + Optional<TypeIndex> getNext(TypeIndex Prev) override; + + CVType getType(TypeIndex Index) override; + StringRef getTypeName(TypeIndex Index) override; + bool contains(TypeIndex Index) override; + uint32_t size() override; + uint32_t capacity() override; + +private: + BumpPtrAllocator Allocator; + StringSaver NameStorage; + std::vector<StringRef> Names; + ArrayRef<ArrayRef<uint8_t>> Records; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h index f251296..126fb8a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h @@ -47,6 +47,14 @@ public: return Error::success(); } + Error visitTypeBegin(CVType &Record, TypeIndex Index) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitTypeBegin(Record, Index)) + return EC; + } + return Error::success(); + } + Error visitTypeEnd(CVType &Record) override { for (auto Visitor : Pipeline) { if (auto EC = Visitor->visitTypeEnd(Record)) @@ -86,7 +94,7 @@ public: } #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "llvm/DebugInfo/CodeView/TypeRecords.def" +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" private: template <typename T> Error visitKnownRecordImpl(CVType &CVR, T &Record) { diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h index 5e27df3..d7a4733 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h @@ -17,8 +17,6 @@ namespace llvm { namespace codeview { class TypeVisitorCallbacks { - friend class CVTypeVisitor; - public: virtual ~TypeVisitorCallbacks() = default; @@ -26,8 +24,15 @@ public: 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. visitTypeBegin() should return - /// the type of the Record, or an error if it cannot be determined. + /// the type of the Record, or an error if it cannot be determined. Exactly + /// one of the two visitTypeBegin methods will be called, depending on whether + /// records are being visited sequentially or randomly. An implementation + /// should be prepared to handle both (or assert if it can't handle random + /// access visitation). virtual Error visitTypeBegin(CVType &Record) { return Error::success(); } + virtual Error visitTypeBegin(CVType &Record, TypeIndex Index) { + return Error::success(); + } virtual Error visitTypeEnd(CVType &Record) { return Error::success(); } virtual Error visitUnknownMember(CVMemberRecord &Record) { @@ -53,7 +58,11 @@ public: #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "TypeRecords.def" +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" +#undef TYPE_RECORD +#undef TYPE_RECORD_ALIAS +#undef MEMBER_RECORD +#undef MEMBER_RECORD_ALIAS }; } // end namespace codeview |