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