diff options
| author | Ralf Luther <luther.ralf@gmail.com> | 2019-03-27 20:23:17 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit2@aicp-server-3> | 2019-03-27 20:23:17 +0000 |
| commit | 1ce3a9d272e564b22a1333a1e36a3d3ab7cfab01 (patch) | |
| tree | 391382eadd4fec5bb480f2e8934fa352770221d1 /clang-r353983/include/llvm/DebugInfo/CodeView | |
| parent | d1d48b140bafaa8a50107292f5fce95562575765 (diff) | |
| parent | 4f56932d3416ac03f646bc1a611b3135fec2fe08 (diff) | |
Merge "Update prebuilt Clang to r353983." into p9.0HEADp9.0-backupp9.0
Diffstat (limited to 'clang-r353983/include/llvm/DebugInfo/CodeView')
60 files changed, 8050 insertions, 0 deletions
diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h b/clang-r353983/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h new file mode 100644 index 00000000..0ac8b651 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h @@ -0,0 +1,69 @@ +//===- AppendingTypeTableBuilder.h -------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_APPENDINGTYPETABLEBUILDER_H +#define LLVM_DEBUGINFO_CODEVIEW_APPENDINGTYPETABLEBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h" +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/Allocator.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <vector> + +namespace llvm { +namespace codeview { + +class ContinuationRecordBuilder; + +class AppendingTypeTableBuilder : public TypeCollection { + + BumpPtrAllocator &RecordStorage; + SimpleTypeSerializer SimpleSerializer; + + /// Contains a list of all records indexed by TypeIndex.toArrayIndex(). + SmallVector<ArrayRef<uint8_t>, 2> SeenRecords; + +public: + explicit AppendingTypeTableBuilder(BumpPtrAllocator &Storage); + ~AppendingTypeTableBuilder(); + + // TypeTableCollection overrides + Optional<TypeIndex> getFirst() override; + Optional<TypeIndex> getNext(TypeIndex Prev) override; + CVType getType(TypeIndex Index) override; + StringRef getTypeName(TypeIndex Index) override; + bool contains(TypeIndex Index) override; + uint32_t size() override; + uint32_t capacity() override; + + // public interface + void reset(); + TypeIndex nextTypeIndex() const; + + BumpPtrAllocator &getAllocator() { return RecordStorage; } + + ArrayRef<ArrayRef<uint8_t>> records() const; + TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record); + TypeIndex insertRecord(ContinuationRecordBuilder &Builder); + + template <typename T> TypeIndex writeLeafType(T &Record) { + ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record); + return insertRecordBytes(Data); + } +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/CVRecord.h b/clang-r353983/include/llvm/DebugInfo/CodeView/CVRecord.h new file mode 100644 index 00000000..1df3d16e --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -0,0 +1,120 @@ +//===- CVRecord.h -----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H +#define LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> + +namespace llvm { + +namespace codeview { + +template <typename Kind> class CVRecord { +public: + CVRecord() : Type(static_cast<Kind>(0)) {} + + CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {} + + bool valid() const { return Type != static_cast<Kind>(0); } + + uint32_t length() const { return RecordData.size(); } + Kind kind() const { return Type; } + ArrayRef<uint8_t> data() const { return RecordData; } + StringRef str_data() const { + return StringRef(reinterpret_cast<const char *>(RecordData.data()), + RecordData.size()); + } + + ArrayRef<uint8_t> content() const { + return RecordData.drop_front(sizeof(RecordPrefix)); + } + + Kind Type; + ArrayRef<uint8_t> RecordData; +}; + +template <typename Kind> struct RemappedRecord { + explicit RemappedRecord(const CVRecord<Kind> &R) : OriginalRecord(R) {} + + CVRecord<Kind> OriginalRecord; + SmallVector<std::pair<uint32_t, TypeIndex>, 8> Mappings; +}; + +template <typename Record, typename Func> +Error forEachCodeViewRecord(ArrayRef<uint8_t> StreamBuffer, Func F) { + while (!StreamBuffer.empty()) { + if (StreamBuffer.size() < sizeof(RecordPrefix)) + return make_error<CodeViewError>(cv_error_code::corrupt_record); + + const RecordPrefix *Prefix = + reinterpret_cast<const RecordPrefix *>(StreamBuffer.data()); + + size_t RealLen = Prefix->RecordLen + 2; + if (StreamBuffer.size() < RealLen) + return make_error<CodeViewError>(cv_error_code::corrupt_record); + + ArrayRef<uint8_t> Data = StreamBuffer.take_front(RealLen); + StreamBuffer = StreamBuffer.drop_front(RealLen); + + Record R(static_cast<decltype(Record::Type)>((uint16_t)Prefix->RecordKind), + Data); + if (auto EC = F(R)) + return EC; + } + return Error::success(); +} + +/// Read a complete record from a stream at a random offset. +template <typename Kind> +inline Expected<CVRecord<Kind>> readCVRecordFromStream(BinaryStreamRef Stream, + uint32_t Offset) { + const RecordPrefix *Prefix = nullptr; + BinaryStreamReader Reader(Stream); + Reader.setOffset(Offset); + + if (auto EC = Reader.readObject(Prefix)) + return std::move(EC); + if (Prefix->RecordLen < 2) + return make_error<CodeViewError>(cv_error_code::corrupt_record); + Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind)); + + Reader.setOffset(Offset); + ArrayRef<uint8_t> RawData; + if (auto EC = Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t))) + return std::move(EC); + return codeview::CVRecord<Kind>(K, RawData); +} + +} // end namespace codeview + +template <typename Kind> +struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> { + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + codeview::CVRecord<Kind> &Item) { + auto ExpectedRec = codeview::readCVRecordFromStream<Kind>(Stream, 0); + if (!ExpectedRec) + return ExpectedRec.takeError(); + Item = *ExpectedRec; + Len = ExpectedRec->length(); + return Error::success(); + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h b/clang-r353983/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h new file mode 100644 index 00000000..1615ff41 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h @@ -0,0 +1,38 @@ +//===- CVSymbolVisitor.h ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H + +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h" +#include "llvm/Support/ErrorOr.h" + +namespace llvm { +namespace codeview { +class SymbolVisitorCallbacks; + +class CVSymbolVisitor { +public: + CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks); + + Error visitSymbolRecord(CVSymbol &Record); + Error visitSymbolRecord(CVSymbol &Record, uint32_t Offset); + Error visitSymbolStream(const CVSymbolArray &Symbols); + Error visitSymbolStream(const CVSymbolArray &Symbols, uint32_t InitialOffset); + +private: + SymbolVisitorCallbacks &Callbacks; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/clang-r353983/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h new file mode 100644 index 00000000..7538cb2c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -0,0 +1,52 @@ +//===- CVTypeVisitor.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H + +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class TypeCollection; +class TypeVisitorCallbacks; + +enum VisitorDataSource { + VDS_BytesPresent, // The record bytes are passed into the visitation + // function. The algorithm should first deserialize them + // before passing them on through the pipeline. + VDS_BytesExternal // The record bytes are not present, and it is the + // responsibility of the visitor callback interface to + // supply the bytes. +}; + +Error visitTypeRecord(CVType &Record, TypeIndex Index, + TypeVisitorCallbacks &Callbacks, + VisitorDataSource Source = VDS_BytesPresent); +Error visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks, + VisitorDataSource Source = VDS_BytesPresent); + +Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks, + VisitorDataSource Source = VDS_BytesPresent); +Error visitMemberRecord(TypeLeafKind Kind, ArrayRef<uint8_t> Record, + TypeVisitorCallbacks &Callbacks); + +Error visitMemberRecordStream(ArrayRef<uint8_t> FieldList, + TypeVisitorCallbacks &Callbacks); + +Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, + VisitorDataSource Source = VDS_BytesPresent); +Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks); +Error visitTypeStream(TypeCollection &Types, TypeVisitorCallbacks &Callbacks); + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/CodeView.h b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeView.h new file mode 100644 index 00000000..4fbf507a --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeView.h @@ -0,0 +1,596 @@ +//===- CodeView.h -----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines constants and basic types describing CodeView debug information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H +#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H + +#include <cinttypes> +#include <type_traits> + +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace codeview { + +/// Distinguishes individual records in .debug$T or .debug$P section or PDB type +/// stream. The documentation and headers talk about this as the "leaf" type. +enum class TypeRecordKind : uint16_t { +#define TYPE_RECORD(lf_ename, value, name) name = value, +#include "CodeViewTypes.def" +}; + +/// Duplicate copy of the above enum, but using the official CV names. Useful +/// for reference purposes and when dealing with unknown record types. +enum TypeLeafKind : uint16_t { +#define CV_TYPE(name, val) name = val, +#include "CodeViewTypes.def" +}; + +/// Distinguishes individual records in the Symbols subsection of a .debug$S +/// section. Equivalent to SYM_ENUM_e in cvinfo.h. +enum class SymbolRecordKind : uint16_t { +#define SYMBOL_RECORD(lf_ename, value, name) name = value, +#include "CodeViewSymbols.def" +}; + +/// Duplicate copy of the above enum, but using the official CV names. Useful +/// for reference purposes and when dealing with unknown record types. +enum SymbolKind : uint16_t { +#define CV_SYMBOL(name, val) name = val, +#include "CodeViewSymbols.def" +}; + +#define CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(Class) \ + inline Class operator|(Class a, Class b) { \ + return static_cast<Class>( \ + static_cast<std::underlying_type<Class>::type>(a) | \ + static_cast<std::underlying_type<Class>::type>(b)); \ + } \ + inline Class operator&(Class a, Class b) { \ + return static_cast<Class>( \ + static_cast<std::underlying_type<Class>::type>(a) & \ + static_cast<std::underlying_type<Class>::type>(b)); \ + } \ + inline Class operator~(Class a) { \ + return static_cast<Class>( \ + ~static_cast<std::underlying_type<Class>::type>(a)); \ + } \ + inline Class &operator|=(Class &a, Class b) { \ + a = a | b; \ + return a; \ + } \ + inline Class &operator&=(Class &a, Class b) { \ + a = a & b; \ + return a; \ + } + +/// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx +enum class CPUType : uint16_t { + Intel8080 = 0x0, + Intel8086 = 0x1, + Intel80286 = 0x2, + Intel80386 = 0x3, + Intel80486 = 0x4, + Pentium = 0x5, + PentiumPro = 0x6, + Pentium3 = 0x7, + MIPS = 0x10, + MIPS16 = 0x11, + MIPS32 = 0x12, + MIPS64 = 0x13, + MIPSI = 0x14, + MIPSII = 0x15, + MIPSIII = 0x16, + MIPSIV = 0x17, + MIPSV = 0x18, + M68000 = 0x20, + M68010 = 0x21, + M68020 = 0x22, + M68030 = 0x23, + M68040 = 0x24, + Alpha = 0x30, + Alpha21164 = 0x31, + Alpha21164A = 0x32, + Alpha21264 = 0x33, + Alpha21364 = 0x34, + PPC601 = 0x40, + PPC603 = 0x41, + PPC604 = 0x42, + PPC620 = 0x43, + PPCFP = 0x44, + PPCBE = 0x45, + SH3 = 0x50, + SH3E = 0x51, + SH3DSP = 0x52, + SH4 = 0x53, + SHMedia = 0x54, + ARM3 = 0x60, + ARM4 = 0x61, + ARM4T = 0x62, + ARM5 = 0x63, + ARM5T = 0x64, + ARM6 = 0x65, + ARM_XMAC = 0x66, + ARM_WMMX = 0x67, + ARM7 = 0x68, + ARM64 = 0x69, + Omni = 0x70, + Ia64 = 0x80, + Ia64_2 = 0x81, + CEE = 0x90, + AM33 = 0xa0, + M32R = 0xb0, + TriCore = 0xc0, + X64 = 0xd0, + EBC = 0xe0, + Thumb = 0xf0, + ARMNT = 0xf4, + D3D11_Shader = 0x100, +}; + +/// These values correspond to the CV_CFL_LANG enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx +enum SourceLanguage : uint8_t { + C = 0x00, + Cpp = 0x01, + Fortran = 0x02, + Masm = 0x03, + Pascal = 0x04, + Basic = 0x05, + Cobol = 0x06, + Link = 0x07, + Cvtres = 0x08, + Cvtpgd = 0x09, + CSharp = 0x0a, + VB = 0x0b, + ILAsm = 0x0c, + Java = 0x0d, + JScript = 0x0e, + MSIL = 0x0f, + HLSL = 0x10, + + /// The DMD compiler emits 'D' for the CV source language. Microsoft doesn't + /// have an enumerator for it yet. + D = 'D', +}; + +/// These values correspond to the CV_call_e enumeration, and are documented +/// at the following locations: +/// https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx +/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680207(v=vs.85).aspx +/// +enum class CallingConvention : uint8_t { + NearC = 0x00, // near right to left push, caller pops stack + FarC = 0x01, // far right to left push, caller pops stack + NearPascal = 0x02, // near left to right push, callee pops stack + FarPascal = 0x03, // far left to right push, callee pops stack + NearFast = 0x04, // near left to right push with regs, callee pops stack + FarFast = 0x05, // far left to right push with regs, callee pops stack + NearStdCall = 0x07, // near standard call + FarStdCall = 0x08, // far standard call + NearSysCall = 0x09, // near sys call + FarSysCall = 0x0a, // far sys call + ThisCall = 0x0b, // this call (this passed in register) + MipsCall = 0x0c, // Mips call + Generic = 0x0d, // Generic call sequence + AlphaCall = 0x0e, // Alpha call + PpcCall = 0x0f, // PPC call + SHCall = 0x10, // Hitachi SuperH call + ArmCall = 0x11, // ARM call + AM33Call = 0x12, // AM33 call + TriCall = 0x13, // TriCore Call + SH5Call = 0x14, // Hitachi SuperH-5 call + M32RCall = 0x15, // M32R Call + ClrCall = 0x16, // clr call + Inline = + 0x17, // Marker for routines always inlined and thus lacking a convention + NearVector = 0x18 // near left to right push with regs, callee pops stack +}; + +enum class ClassOptions : uint16_t { + None = 0x0000, + Packed = 0x0001, + HasConstructorOrDestructor = 0x0002, + HasOverloadedOperator = 0x0004, + Nested = 0x0008, + ContainsNestedClass = 0x0010, + HasOverloadedAssignmentOperator = 0x0020, + HasConversionOperator = 0x0040, + ForwardReference = 0x0080, + Scoped = 0x0100, + HasUniqueName = 0x0200, + Sealed = 0x0400, + Intrinsic = 0x2000 +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ClassOptions) + +enum class FrameProcedureOptions : uint32_t { + None = 0x00000000, + HasAlloca = 0x00000001, + HasSetJmp = 0x00000002, + HasLongJmp = 0x00000004, + HasInlineAssembly = 0x00000008, + HasExceptionHandling = 0x00000010, + MarkedInline = 0x00000020, + HasStructuredExceptionHandling = 0x00000040, + Naked = 0x00000080, + SecurityChecks = 0x00000100, + AsynchronousExceptionHandling = 0x00000200, + NoStackOrderingForSecurityChecks = 0x00000400, + Inlined = 0x00000800, + StrictSecurityChecks = 0x00001000, + SafeBuffers = 0x00002000, + EncodedLocalBasePointerMask = 0x0000C000, + EncodedParamBasePointerMask = 0x00030000, + ProfileGuidedOptimization = 0x00040000, + ValidProfileCounts = 0x00080000, + OptimizedForSpeed = 0x00100000, + GuardCfg = 0x00200000, + GuardCfw = 0x00400000 +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(FrameProcedureOptions) + +enum class FunctionOptions : uint8_t { + None = 0x00, + CxxReturnUdt = 0x01, + Constructor = 0x02, + ConstructorWithVirtualBases = 0x04 +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(FunctionOptions) + +enum class HfaKind : uint8_t { + None = 0x00, + Float = 0x01, + Double = 0x02, + Other = 0x03 +}; + +/// Source-level access specifier. (CV_access_e) +enum class MemberAccess : uint8_t { + None = 0, + Private = 1, + Protected = 2, + Public = 3 +}; + +/// Part of member attribute flags. (CV_methodprop_e) +enum class MethodKind : uint8_t { + Vanilla = 0x00, + Virtual = 0x01, + Static = 0x02, + Friend = 0x03, + IntroducingVirtual = 0x04, + PureVirtual = 0x05, + PureIntroducingVirtual = 0x06 +}; + +/// Equivalent to CV_fldattr_t bitfield. +enum class MethodOptions : uint16_t { + None = 0x0000, + AccessMask = 0x0003, + MethodKindMask = 0x001c, + Pseudo = 0x0020, + NoInherit = 0x0040, + NoConstruct = 0x0080, + CompilerGenerated = 0x0100, + Sealed = 0x0200 +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(MethodOptions) + +/// Equivalent to CV_LABEL_TYPE_e. +enum class LabelType : uint16_t { + Near = 0x0, + Far = 0x4, +}; + +/// Equivalent to CV_modifier_t. +/// TODO: Add flag for _Atomic modifier +enum class ModifierOptions : uint16_t { + None = 0x0000, + Const = 0x0001, + Volatile = 0x0002, + Unaligned = 0x0004 +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ModifierOptions) + +enum class DebugSubsectionKind : uint32_t { + None = 0, + Symbols = 0xf1, + Lines = 0xf2, + StringTable = 0xf3, + FileChecksums = 0xf4, + FrameData = 0xf5, + InlineeLines = 0xf6, + CrossScopeImports = 0xf7, + CrossScopeExports = 0xf8, + + // These appear to relate to .Net assembly info. + ILLines = 0xf9, + FuncMDTokenMap = 0xfa, + TypeMDTokenMap = 0xfb, + MergedAssemblyInput = 0xfc, + + CoffSymbolRVA = 0xfd, +}; + +/// Equivalent to CV_ptrtype_e. +enum class PointerKind : uint8_t { + Near16 = 0x00, // 16 bit pointer + Far16 = 0x01, // 16:16 far pointer + Huge16 = 0x02, // 16:16 huge pointer + BasedOnSegment = 0x03, // based on segment + BasedOnValue = 0x04, // based on value of base + BasedOnSegmentValue = 0x05, // based on segment value of base + BasedOnAddress = 0x06, // based on address of base + BasedOnSegmentAddress = 0x07, // based on segment address of base + BasedOnType = 0x08, // based on type + BasedOnSelf = 0x09, // based on self + Near32 = 0x0a, // 32 bit pointer + Far32 = 0x0b, // 16:32 pointer + Near64 = 0x0c // 64 bit pointer +}; + +/// Equivalent to CV_ptrmode_e. +enum class PointerMode : uint8_t { + Pointer = 0x00, // "normal" pointer + LValueReference = 0x01, // "old" reference + PointerToDataMember = 0x02, // pointer to data member + PointerToMemberFunction = 0x03, // pointer to member function + RValueReference = 0x04 // r-value reference +}; + +/// Equivalent to misc lfPointerAttr bitfields. +enum class PointerOptions : uint32_t { + None = 0x00000000, + Flat32 = 0x00000100, + Volatile = 0x00000200, + Const = 0x00000400, + Unaligned = 0x00000800, + Restrict = 0x00001000, + WinRTSmartPointer = 0x00080000, + LValueRefThisPointer = 0x00100000, + RValueRefThisPointer = 0x00200000 +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(PointerOptions) + +/// Equivalent to CV_pmtype_e. +enum class PointerToMemberRepresentation : uint16_t { + Unknown = 0x00, // not specified (pre VC8) + SingleInheritanceData = 0x01, // member data, single inheritance + MultipleInheritanceData = 0x02, // member data, multiple inheritance + VirtualInheritanceData = 0x03, // member data, virtual inheritance + GeneralData = 0x04, // member data, most general + SingleInheritanceFunction = 0x05, // member function, single inheritance + MultipleInheritanceFunction = 0x06, // member function, multiple inheritance + VirtualInheritanceFunction = 0x07, // member function, virtual inheritance + GeneralFunction = 0x08 // member function, most general +}; + +enum class VFTableSlotKind : uint8_t { + Near16 = 0x00, + Far16 = 0x01, + This = 0x02, + Outer = 0x03, + Meta = 0x04, + Near = 0x05, + Far = 0x06 +}; + +enum class WindowsRTClassKind : uint8_t { + None = 0x00, + RefClass = 0x01, + ValueClass = 0x02, + Interface = 0x03 +}; + +/// Corresponds to CV_LVARFLAGS bitfield. +enum class LocalSymFlags : uint16_t { + None = 0, + IsParameter = 1 << 0, + IsAddressTaken = 1 << 1, + IsCompilerGenerated = 1 << 2, + IsAggregate = 1 << 3, + IsAggregated = 1 << 4, + IsAliased = 1 << 5, + IsAlias = 1 << 6, + IsReturnValue = 1 << 7, + IsOptimizedOut = 1 << 8, + IsEnregisteredGlobal = 1 << 9, + IsEnregisteredStatic = 1 << 10, +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(LocalSymFlags) + +/// Corresponds to the CV_PUBSYMFLAGS bitfield. +enum class PublicSymFlags : uint32_t { + None = 0, + Code = 1 << 0, + Function = 1 << 1, + Managed = 1 << 2, + MSIL = 1 << 3, +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(PublicSymFlags) + +/// Corresponds to the CV_PROCFLAGS bitfield. +enum class ProcSymFlags : uint8_t { + None = 0, + HasFP = 1 << 0, + HasIRET = 1 << 1, + HasFRET = 1 << 2, + IsNoReturn = 1 << 3, + IsUnreachable = 1 << 4, + HasCustomCallingConv = 1 << 5, + IsNoInline = 1 << 6, + HasOptimizedDebugInfo = 1 << 7, +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ProcSymFlags) + +/// Corresponds to COMPILESYM2::Flags bitfield. +enum class CompileSym2Flags : uint32_t { + None = 0, + SourceLanguageMask = 0xFF, + EC = 1 << 8, + NoDbgInfo = 1 << 9, + LTCG = 1 << 10, + NoDataAlign = 1 << 11, + ManagedPresent = 1 << 12, + SecurityChecks = 1 << 13, + HotPatch = 1 << 14, + CVTCIL = 1 << 15, + MSILModule = 1 << 16, +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym2Flags) + +/// Corresponds to COMPILESYM3::Flags bitfield. +enum class CompileSym3Flags : uint32_t { + None = 0, + SourceLanguageMask = 0xFF, + EC = 1 << 8, + NoDbgInfo = 1 << 9, + LTCG = 1 << 10, + NoDataAlign = 1 << 11, + ManagedPresent = 1 << 12, + SecurityChecks = 1 << 13, + HotPatch = 1 << 14, + CVTCIL = 1 << 15, + MSILModule = 1 << 16, + Sdl = 1 << 17, + PGO = 1 << 18, + Exp = 1 << 19, +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym3Flags) + +enum class ExportFlags : uint16_t { + None = 0, + IsConstant = 1 << 0, + IsData = 1 << 1, + IsPrivate = 1 << 2, + HasNoName = 1 << 3, + HasExplicitOrdinal = 1 << 4, + IsForwarder = 1 << 5 +}; +CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ExportFlags) + +// Corresponds to BinaryAnnotationOpcode enum. +enum class BinaryAnnotationsOpCode : uint32_t { + Invalid, + CodeOffset, + ChangeCodeOffsetBase, + ChangeCodeOffset, + ChangeCodeLength, + ChangeFile, + ChangeLineOffset, + ChangeLineEndDelta, + ChangeRangeKind, + ChangeColumnStart, + ChangeColumnEndDelta, + ChangeCodeOffsetAndLineOffset, + ChangeCodeLengthAndCodeOffset, + ChangeColumnEnd, +}; + +// Corresponds to CV_cookietype_e enum. +enum class FrameCookieKind : uint8_t { + Copy, + XorStackPointer, + XorFramePointer, + XorR13, +}; + +// Corresponds to CV_HREG_e enum. +enum class RegisterId : uint16_t { +#define CV_REGISTER(name, value) name = value, +#include "CodeViewRegisters.def" +#undef CV_REGISTER +}; + +/// Two-bit value indicating which register is the designated frame pointer +/// register. Appears in the S_FRAMEPROC record flags. +enum class EncodedFramePtrReg : uint8_t { + None = 0, + StackPtr = 1, + FramePtr = 2, + BasePtr = 3, +}; + +RegisterId decodeFramePtrReg(EncodedFramePtrReg EncodedReg, CPUType CPU); + +EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU); + +/// These values correspond to the THUNK_ORDINAL enumeration. +enum class ThunkOrdinal : uint8_t { + Standard, + ThisAdjustor, + Vcall, + Pcode, + UnknownLoad, + 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 }; + +enum LineFlags : uint16_t { + LF_None = 0, + LF_HaveColumns = 1, // CV_LINES_HAVE_COLUMNS +}; + +/// Data in the SUBSEC_FRAMEDATA subection. +struct FrameData { + support::ulittle32_t RvaStart; + support::ulittle32_t CodeSize; + support::ulittle32_t LocalSize; + support::ulittle32_t ParamsSize; + support::ulittle32_t MaxStackSize; + support::ulittle32_t FrameFunc; + support::ulittle16_t PrologSize; + support::ulittle16_t SavedRegsSize; + support::ulittle32_t Flags; + enum : uint32_t { + HasSEH = 1 << 0, + HasEH = 1 << 1, + IsFunctionStart = 1 << 2, + }; +}; + +// Corresponds to LocalIdAndGlobalIdPair structure. +// This structure information allows cross-referencing between PDBs. For +// example, when a PDB is being built during compilation it is not yet known +// what other modules may end up in the PDB at link time. So certain types of +// IDs may clash between the various compile time PDBs. For each affected +// module, a subsection would be put into the PDB containing a mapping from its +// local IDs to a single ID namespace for all items in the PDB file. +struct CrossModuleExport { + support::ulittle32_t Local; + support::ulittle32_t Global; +}; + +struct CrossModuleImport { + support::ulittle32_t ModuleNameOffset; + support::ulittle32_t Count; // Number of elements + // support::ulittle32_t ids[Count]; // id from referenced module +}; + +enum class CodeViewContainer { ObjectFile, Pdb }; + +inline uint32_t alignOf(CodeViewContainer Container) { + if (Container == CodeViewContainer::ObjectFile) + return 1; + return 4; +} +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewError.h b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewError.h new file mode 100644 index 00000000..9990c8d0 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewError.h @@ -0,0 +1,54 @@ +//===- CodeViewError.h - Error extensions for CodeView ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_CODEVIEW_CODEVIEWERROR_H +#define LLVM_DEBUGINFO_PDB_CODEVIEW_CODEVIEWERROR_H + +#include "llvm/Support/Error.h" + +#include <string> + +namespace llvm { +namespace codeview { +enum class cv_error_code { + unspecified = 1, + insufficient_buffer, + operation_unsupported, + corrupt_record, + no_records, + unknown_member_record, +}; +} // namespace codeview +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum<llvm::codeview::cv_error_code> : std::true_type {}; +} // namespace std + +namespace llvm { +namespace codeview { +const std::error_category &CVErrorCategory(); + +inline std::error_code make_error_code(cv_error_code E) { + return std::error_code(static_cast<int>(E), CVErrorCategory()); +} + +/// Base class for errors originating when parsing raw PDB files +class CodeViewError : public ErrorInfo<CodeViewError, StringError> { +public: + using ErrorInfo<CodeViewError, + StringError>::ErrorInfo; // inherit constructors + CodeViewError(const Twine &S) : ErrorInfo(S, cv_error_code::unspecified) {} + static char ID; +}; + +} // namespace codeview +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h new file mode 100644 index 00000000..b2476f16 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -0,0 +1,170 @@ +//===- CodeViewRecordIO.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamWriter.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(BinaryStreamReader &Reader) : Reader(&Reader) {} + explicit CodeViewRecordIO(BinaryStreamWriter &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(GUID &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 padToAlignment(uint32_t Align); + 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; + + BinaryStreamReader *Reader = nullptr; + BinaryStreamWriter *Writer = nullptr; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def new file mode 100644 index 00000000..0593bc05 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def @@ -0,0 +1,358 @@ +//===-- CodeViewRegisters.def - CodeView registers --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// See CV_HREG_e in cvconst.h. This should match the constants there. +// +//===----------------------------------------------------------------------===// + +#ifndef CV_REGISTER +#define CV_REGISTER(name, value) +#endif + +// This currently only contains the "register subset shared by all processor +// types" (ERR etc.) and the x86 registers. + +// Some system headers define macros that conflict with our enums. Every +// compiler supported by LLVM has the push_macro and pop_macro pragmas, so use +// them to avoid the conflict. +#pragma push_macro("CR0") +#pragma push_macro("CR1") +#pragma push_macro("CR2") +#pragma push_macro("CR3") +#pragma push_macro("CR4") + +CV_REGISTER(ERR, 30000) +CV_REGISTER(TEB, 30001) +CV_REGISTER(TIMER, 30002) +CV_REGISTER(EFAD1, 30003) +CV_REGISTER(EFAD2, 30004) +CV_REGISTER(EFAD3, 30005) +CV_REGISTER(VFRAME, 30006) +CV_REGISTER(HANDLE, 30007) +CV_REGISTER(PARAMS, 30008) +CV_REGISTER(LOCALS, 30009) +CV_REGISTER(TID, 30010) +CV_REGISTER(ENV, 30011) +CV_REGISTER(CMDLN, 30012) + +CV_REGISTER(NONE, 0) +CV_REGISTER(AL, 1) +CV_REGISTER(CL, 2) +CV_REGISTER(DL, 3) +CV_REGISTER(BL, 4) +CV_REGISTER(AH, 5) +CV_REGISTER(CH, 6) +CV_REGISTER(DH, 7) +CV_REGISTER(BH, 8) +CV_REGISTER(AX, 9) +CV_REGISTER(CX, 10) +CV_REGISTER(DX, 11) +CV_REGISTER(BX, 12) +CV_REGISTER(SP, 13) +CV_REGISTER(BP, 14) +CV_REGISTER(SI, 15) +CV_REGISTER(DI, 16) +CV_REGISTER(EAX, 17) +CV_REGISTER(ECX, 18) +CV_REGISTER(EDX, 19) +CV_REGISTER(EBX, 20) +CV_REGISTER(ESP, 21) +CV_REGISTER(EBP, 22) +CV_REGISTER(ESI, 23) +CV_REGISTER(EDI, 24) +CV_REGISTER(ES, 25) +CV_REGISTER(CS, 26) +CV_REGISTER(SS, 27) +CV_REGISTER(DS, 28) +CV_REGISTER(FS, 29) +CV_REGISTER(GS, 30) +CV_REGISTER(IP, 31) +CV_REGISTER(FLAGS, 32) +CV_REGISTER(EIP, 33) +CV_REGISTER(EFLAGS, 34) +CV_REGISTER(TEMP, 40) +CV_REGISTER(TEMPH, 41) +CV_REGISTER(QUOTE, 42) +CV_REGISTER(PCDR3, 43) +CV_REGISTER(PCDR4, 44) +CV_REGISTER(PCDR5, 45) +CV_REGISTER(PCDR6, 46) +CV_REGISTER(PCDR7, 47) +CV_REGISTER(CR0, 80) +CV_REGISTER(CR1, 81) +CV_REGISTER(CR2, 82) +CV_REGISTER(CR3, 83) +CV_REGISTER(CR4, 84) +CV_REGISTER(DR0, 90) +CV_REGISTER(DR1, 91) +CV_REGISTER(DR2, 92) +CV_REGISTER(DR3, 93) +CV_REGISTER(DR4, 94) +CV_REGISTER(DR5, 95) +CV_REGISTER(DR6, 96) +CV_REGISTER(DR7, 97) +CV_REGISTER(GDTR, 110) +CV_REGISTER(GDTL, 111) +CV_REGISTER(IDTR, 112) +CV_REGISTER(IDTL, 113) +CV_REGISTER(LDTR, 114) +CV_REGISTER(TR, 115) + +CV_REGISTER(PSEUDO1, 116) +CV_REGISTER(PSEUDO2, 117) +CV_REGISTER(PSEUDO3, 118) +CV_REGISTER(PSEUDO4, 119) +CV_REGISTER(PSEUDO5, 120) +CV_REGISTER(PSEUDO6, 121) +CV_REGISTER(PSEUDO7, 122) +CV_REGISTER(PSEUDO8, 123) +CV_REGISTER(PSEUDO9, 124) + +CV_REGISTER(ST0, 128) +CV_REGISTER(ST1, 129) +CV_REGISTER(ST2, 130) +CV_REGISTER(ST3, 131) +CV_REGISTER(ST4, 132) +CV_REGISTER(ST5, 133) +CV_REGISTER(ST6, 134) +CV_REGISTER(ST7, 135) +CV_REGISTER(CTRL, 136) +CV_REGISTER(STAT, 137) +CV_REGISTER(TAG, 138) +CV_REGISTER(FPIP, 139) +CV_REGISTER(FPCS, 140) +CV_REGISTER(FPDO, 141) +CV_REGISTER(FPDS, 142) +CV_REGISTER(ISEM, 143) +CV_REGISTER(FPEIP, 144) +CV_REGISTER(FPEDO, 145) + +CV_REGISTER(MM0, 146) +CV_REGISTER(MM1, 147) +CV_REGISTER(MM2, 148) +CV_REGISTER(MM3, 149) +CV_REGISTER(MM4, 150) +CV_REGISTER(MM5, 151) +CV_REGISTER(MM6, 152) +CV_REGISTER(MM7, 153) + +CV_REGISTER(XMM0, 154) +CV_REGISTER(XMM1, 155) +CV_REGISTER(XMM2, 156) +CV_REGISTER(XMM3, 157) +CV_REGISTER(XMM4, 158) +CV_REGISTER(XMM5, 159) +CV_REGISTER(XMM6, 160) +CV_REGISTER(XMM7, 161) + +CV_REGISTER(MXCSR, 211) + +CV_REGISTER(EDXEAX, 212) + +CV_REGISTER(EMM0L, 220) +CV_REGISTER(EMM1L, 221) +CV_REGISTER(EMM2L, 222) +CV_REGISTER(EMM3L, 223) +CV_REGISTER(EMM4L, 224) +CV_REGISTER(EMM5L, 225) +CV_REGISTER(EMM6L, 226) +CV_REGISTER(EMM7L, 227) + +CV_REGISTER(EMM0H, 228) +CV_REGISTER(EMM1H, 229) +CV_REGISTER(EMM2H, 230) +CV_REGISTER(EMM3H, 231) +CV_REGISTER(EMM4H, 232) +CV_REGISTER(EMM5H, 233) +CV_REGISTER(EMM6H, 234) +CV_REGISTER(EMM7H, 235) + +CV_REGISTER(MM00, 236) +CV_REGISTER(MM01, 237) +CV_REGISTER(MM10, 238) +CV_REGISTER(MM11, 239) +CV_REGISTER(MM20, 240) +CV_REGISTER(MM21, 241) +CV_REGISTER(MM30, 242) +CV_REGISTER(MM31, 243) +CV_REGISTER(MM40, 244) +CV_REGISTER(MM41, 245) +CV_REGISTER(MM50, 246) +CV_REGISTER(MM51, 247) +CV_REGISTER(MM60, 248) +CV_REGISTER(MM61, 249) +CV_REGISTER(MM70, 250) +CV_REGISTER(MM71, 251) + +CV_REGISTER(BND0, 396) +CV_REGISTER(BND1, 397) +CV_REGISTER(BND2, 398) + + +CV_REGISTER(XMM8, 252) +CV_REGISTER(XMM9, 253) +CV_REGISTER(XMM10, 254) +CV_REGISTER(XMM11, 255) +CV_REGISTER(XMM12, 256) +CV_REGISTER(XMM13, 257) +CV_REGISTER(XMM14, 258) +CV_REGISTER(XMM15, 259) + + +CV_REGISTER(SIL, 324) +CV_REGISTER(DIL, 325) +CV_REGISTER(BPL, 326) +CV_REGISTER(SPL, 327) + +CV_REGISTER(RAX, 328) +CV_REGISTER(RBX, 329) +CV_REGISTER(RCX, 330) +CV_REGISTER(RDX, 331) +CV_REGISTER(RSI, 332) +CV_REGISTER(RDI, 333) +CV_REGISTER(RBP, 334) +CV_REGISTER(RSP, 335) + +CV_REGISTER(R8, 336) +CV_REGISTER(R9, 337) +CV_REGISTER(R10, 338) +CV_REGISTER(R11, 339) +CV_REGISTER(R12, 340) +CV_REGISTER(R13, 341) +CV_REGISTER(R14, 342) +CV_REGISTER(R15, 343) + +CV_REGISTER(R8B, 344) +CV_REGISTER(R9B, 345) +CV_REGISTER(R10B, 346) +CV_REGISTER(R11B, 347) +CV_REGISTER(R12B, 348) +CV_REGISTER(R13B, 349) +CV_REGISTER(R14B, 350) +CV_REGISTER(R15B, 351) + +CV_REGISTER(R8W, 352) +CV_REGISTER(R9W, 353) +CV_REGISTER(R10W, 354) +CV_REGISTER(R11W, 355) +CV_REGISTER(R12W, 356) +CV_REGISTER(R13W, 357) +CV_REGISTER(R14W, 358) +CV_REGISTER(R15W, 359) + +CV_REGISTER(R8D, 360) +CV_REGISTER(R9D, 361) +CV_REGISTER(R10D, 362) +CV_REGISTER(R11D, 363) +CV_REGISTER(R12D, 364) +CV_REGISTER(R13D, 365) +CV_REGISTER(R14D, 366) +CV_REGISTER(R15D, 367) + + +// cvconst.h defines both CV_REG_YMM0 (252) and CV_AMD64_YMM0 (368). Keep the +// original prefix to distinguish them. + +CV_REGISTER(AMD64_YMM0, 368) +CV_REGISTER(AMD64_YMM1, 369) +CV_REGISTER(AMD64_YMM2, 370) +CV_REGISTER(AMD64_YMM3, 371) +CV_REGISTER(AMD64_YMM4, 372) +CV_REGISTER(AMD64_YMM5, 373) +CV_REGISTER(AMD64_YMM6, 374) +CV_REGISTER(AMD64_YMM7, 375) +CV_REGISTER(AMD64_YMM8, 376) +CV_REGISTER(AMD64_YMM9, 377) +CV_REGISTER(AMD64_YMM10, 378) +CV_REGISTER(AMD64_YMM11, 379) +CV_REGISTER(AMD64_YMM12, 380) +CV_REGISTER(AMD64_YMM13, 381) +CV_REGISTER(AMD64_YMM14, 382) +CV_REGISTER(AMD64_YMM15, 383) + +CV_REGISTER(AMD64_XMM16, 694) +CV_REGISTER(AMD64_XMM17, 695) +CV_REGISTER(AMD64_XMM18, 696) +CV_REGISTER(AMD64_XMM19, 697) +CV_REGISTER(AMD64_XMM20, 698) +CV_REGISTER(AMD64_XMM21, 699) +CV_REGISTER(AMD64_XMM22, 700) +CV_REGISTER(AMD64_XMM23, 701) +CV_REGISTER(AMD64_XMM24, 702) +CV_REGISTER(AMD64_XMM25, 703) +CV_REGISTER(AMD64_XMM26, 704) +CV_REGISTER(AMD64_XMM27, 705) +CV_REGISTER(AMD64_XMM28, 706) +CV_REGISTER(AMD64_XMM29, 707) +CV_REGISTER(AMD64_XMM30, 708) +CV_REGISTER(AMD64_XMM31, 709) + +CV_REGISTER(AMD64_YMM16, 710) +CV_REGISTER(AMD64_YMM17, 711) +CV_REGISTER(AMD64_YMM18, 712) +CV_REGISTER(AMD64_YMM19, 713) +CV_REGISTER(AMD64_YMM20, 714) +CV_REGISTER(AMD64_YMM21, 715) +CV_REGISTER(AMD64_YMM22, 716) +CV_REGISTER(AMD64_YMM23, 717) +CV_REGISTER(AMD64_YMM24, 718) +CV_REGISTER(AMD64_YMM25, 719) +CV_REGISTER(AMD64_YMM26, 720) +CV_REGISTER(AMD64_YMM27, 721) +CV_REGISTER(AMD64_YMM28, 722) +CV_REGISTER(AMD64_YMM29, 723) +CV_REGISTER(AMD64_YMM30, 724) +CV_REGISTER(AMD64_YMM31, 725) + +CV_REGISTER(AMD64_ZMM0, 726) +CV_REGISTER(AMD64_ZMM1, 727) +CV_REGISTER(AMD64_ZMM2, 728) +CV_REGISTER(AMD64_ZMM3, 729) +CV_REGISTER(AMD64_ZMM4, 730) +CV_REGISTER(AMD64_ZMM5, 731) +CV_REGISTER(AMD64_ZMM6, 732) +CV_REGISTER(AMD64_ZMM7, 733) +CV_REGISTER(AMD64_ZMM8, 734) +CV_REGISTER(AMD64_ZMM9, 735) +CV_REGISTER(AMD64_ZMM10, 736) +CV_REGISTER(AMD64_ZMM11, 737) +CV_REGISTER(AMD64_ZMM12, 738) +CV_REGISTER(AMD64_ZMM13, 739) +CV_REGISTER(AMD64_ZMM14, 740) +CV_REGISTER(AMD64_ZMM15, 741) +CV_REGISTER(AMD64_ZMM16, 742) +CV_REGISTER(AMD64_ZMM17, 743) +CV_REGISTER(AMD64_ZMM18, 744) +CV_REGISTER(AMD64_ZMM19, 745) +CV_REGISTER(AMD64_ZMM20, 746) +CV_REGISTER(AMD64_ZMM21, 747) +CV_REGISTER(AMD64_ZMM22, 748) +CV_REGISTER(AMD64_ZMM23, 749) +CV_REGISTER(AMD64_ZMM24, 750) +CV_REGISTER(AMD64_ZMM25, 751) +CV_REGISTER(AMD64_ZMM26, 752) +CV_REGISTER(AMD64_ZMM27, 753) +CV_REGISTER(AMD64_ZMM28, 754) +CV_REGISTER(AMD64_ZMM29, 755) +CV_REGISTER(AMD64_ZMM30, 756) +CV_REGISTER(AMD64_ZMM31, 757) + +CV_REGISTER(AMD64_K0, 758) +CV_REGISTER(AMD64_K1, 759) +CV_REGISTER(AMD64_K2, 760) +CV_REGISTER(AMD64_K3, 761) +CV_REGISTER(AMD64_K4, 762) +CV_REGISTER(AMD64_K5, 763) +CV_REGISTER(AMD64_K6, 764) +CV_REGISTER(AMD64_K7, 765) + +#pragma pop_macro("CR0") +#pragma pop_macro("CR1") +#pragma pop_macro("CR2") +#pragma pop_macro("CR3") +#pragma pop_macro("CR4") diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def new file mode 100644 index 00000000..e36d8046 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def @@ -0,0 +1,260 @@ +//===-- CodeViewSymbols.def - All CodeView leaf types -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// See LEAF_ENUM_e in cvinfo.h. This should match the constants there. +// +//===----------------------------------------------------------------------===// + +#ifndef CV_SYMBOL +#define CV_SYMBOL(ename, value) +#endif + +#ifndef SYMBOL_RECORD +#define SYMBOL_RECORD(lf_ename, value, name) CV_SYMBOL(lf_ename, value) +#endif + +#ifndef SYMBOL_RECORD_ALIAS +#define SYMBOL_RECORD_ALIAS(lf_ename, value, name, alias_name) \ + SYMBOL_RECORD(lf_ename, value, name) +#endif + +// 16 bit symbol types. Not very useful, provided only for reference. +CV_SYMBOL(S_COMPILE , 0x0001) +CV_SYMBOL(S_REGISTER_16t , 0x0002) +CV_SYMBOL(S_CONSTANT_16t , 0x0003) +CV_SYMBOL(S_UDT_16t , 0x0004) +CV_SYMBOL(S_SSEARCH , 0x0005) +CV_SYMBOL(S_SKIP , 0x0007) +CV_SYMBOL(S_CVRESERVE , 0x0008) +CV_SYMBOL(S_OBJNAME_ST , 0x0009) +CV_SYMBOL(S_ENDARG , 0x000a) +CV_SYMBOL(S_COBOLUDT_16t , 0x000b) +CV_SYMBOL(S_MANYREG_16t , 0x000c) +CV_SYMBOL(S_RETURN , 0x000d) +CV_SYMBOL(S_ENTRYTHIS , 0x000e) +CV_SYMBOL(S_BPREL16 , 0x0100) +CV_SYMBOL(S_LDATA16 , 0x0101) +CV_SYMBOL(S_GDATA16 , 0x0102) +CV_SYMBOL(S_PUB16 , 0x0103) +CV_SYMBOL(S_LPROC16 , 0x0104) +CV_SYMBOL(S_GPROC16 , 0x0105) +CV_SYMBOL(S_THUNK16 , 0x0106) +CV_SYMBOL(S_BLOCK16 , 0x0107) +CV_SYMBOL(S_WITH16 , 0x0108) +CV_SYMBOL(S_LABEL16 , 0x0109) +CV_SYMBOL(S_CEXMODEL16 , 0x010a) +CV_SYMBOL(S_VFTABLE16 , 0x010b) +CV_SYMBOL(S_REGREL16 , 0x010c) +CV_SYMBOL(S_BPREL32_16t , 0x0200) +CV_SYMBOL(S_LDATA32_16t , 0x0201) +CV_SYMBOL(S_GDATA32_16t , 0x0202) +CV_SYMBOL(S_PUB32_16t , 0x0203) +CV_SYMBOL(S_LPROC32_16t , 0x0204) +CV_SYMBOL(S_GPROC32_16t , 0x0205) +CV_SYMBOL(S_THUNK32_ST , 0x0206) +CV_SYMBOL(S_BLOCK32_ST , 0x0207) +CV_SYMBOL(S_WITH32_ST , 0x0208) +CV_SYMBOL(S_LABEL32_ST , 0x0209) +CV_SYMBOL(S_CEXMODEL32 , 0x020a) +CV_SYMBOL(S_VFTABLE32_16t , 0x020b) +CV_SYMBOL(S_REGREL32_16t , 0x020c) +CV_SYMBOL(S_LTHREAD32_16t , 0x020d) +CV_SYMBOL(S_GTHREAD32_16t , 0x020e) +CV_SYMBOL(S_SLINK32 , 0x020f) +CV_SYMBOL(S_LPROCMIPS_16t , 0x0300) +CV_SYMBOL(S_GPROCMIPS_16t , 0x0301) +CV_SYMBOL(S_PROCREF_ST , 0x0400) +CV_SYMBOL(S_DATAREF_ST , 0x0401) +CV_SYMBOL(S_ALIGN , 0x0402) +CV_SYMBOL(S_LPROCREF_ST , 0x0403) +CV_SYMBOL(S_OEM , 0x0404) + +// All post 16 bit symbol types have the 0x1000 bit set. +CV_SYMBOL(S_TI16_MAX , 0x1000) + +// Mostly unused "start" symbol types. +CV_SYMBOL(S_REGISTER_ST , 0x1001) +CV_SYMBOL(S_CONSTANT_ST , 0x1002) +CV_SYMBOL(S_UDT_ST , 0x1003) +CV_SYMBOL(S_COBOLUDT_ST , 0x1004) +CV_SYMBOL(S_MANYREG_ST , 0x1005) +CV_SYMBOL(S_BPREL32_ST , 0x1006) +CV_SYMBOL(S_LDATA32_ST , 0x1007) +CV_SYMBOL(S_GDATA32_ST , 0x1008) +CV_SYMBOL(S_PUB32_ST , 0x1009) +CV_SYMBOL(S_LPROC32_ST , 0x100a) +CV_SYMBOL(S_GPROC32_ST , 0x100b) +CV_SYMBOL(S_VFTABLE32 , 0x100c) +CV_SYMBOL(S_REGREL32_ST , 0x100d) +CV_SYMBOL(S_LTHREAD32_ST , 0x100e) +CV_SYMBOL(S_GTHREAD32_ST , 0x100f) +CV_SYMBOL(S_LPROCMIPS_ST , 0x1010) +CV_SYMBOL(S_GPROCMIPS_ST , 0x1011) + +CV_SYMBOL(S_COMPILE2_ST , 0x1013) +CV_SYMBOL(S_MANYREG2_ST , 0x1014) +CV_SYMBOL(S_LPROCIA64_ST , 0x1015) +CV_SYMBOL(S_GPROCIA64_ST , 0x1016) +CV_SYMBOL(S_LOCALSLOT_ST , 0x1017) +CV_SYMBOL(S_PARAMSLOT_ST , 0x1018) +CV_SYMBOL(S_ANNOTATION , 0x1019) +CV_SYMBOL(S_GMANPROC_ST , 0x101a) +CV_SYMBOL(S_LMANPROC_ST , 0x101b) +CV_SYMBOL(S_RESERVED1 , 0x101c) +CV_SYMBOL(S_RESERVED2 , 0x101d) +CV_SYMBOL(S_RESERVED3 , 0x101e) +CV_SYMBOL(S_RESERVED4 , 0x101f) +CV_SYMBOL(S_LMANDATA_ST , 0x1020) +CV_SYMBOL(S_GMANDATA_ST , 0x1021) +CV_SYMBOL(S_MANFRAMEREL_ST, 0x1022) +CV_SYMBOL(S_MANREGISTER_ST, 0x1023) +CV_SYMBOL(S_MANSLOT_ST , 0x1024) +CV_SYMBOL(S_MANMANYREG_ST , 0x1025) +CV_SYMBOL(S_MANREGREL_ST , 0x1026) +CV_SYMBOL(S_MANMANYREG2_ST, 0x1027) +CV_SYMBOL(S_MANTYPREF , 0x1028) +CV_SYMBOL(S_UNAMESPACE_ST , 0x1029) + +// End of S_*_ST symbols, which do not appear to be generated by modern +// compilers. +CV_SYMBOL(S_ST_MAX , 0x1100) + + +CV_SYMBOL(S_WITH32 , 0x1104) +CV_SYMBOL(S_MANYREG , 0x110a) +CV_SYMBOL(S_LPROCMIPS , 0x1114) +CV_SYMBOL(S_GPROCMIPS , 0x1115) +CV_SYMBOL(S_MANYREG2 , 0x1117) +CV_SYMBOL(S_LPROCIA64 , 0x1118) +CV_SYMBOL(S_GPROCIA64 , 0x1119) +CV_SYMBOL(S_LOCALSLOT , 0x111a) +CV_SYMBOL(S_PARAMSLOT , 0x111b) + +// Managed code symbols. +CV_SYMBOL(S_MANFRAMEREL , 0x111e) +CV_SYMBOL(S_MANREGISTER , 0x111f) +CV_SYMBOL(S_MANSLOT , 0x1120) +CV_SYMBOL(S_MANMANYREG , 0x1121) +CV_SYMBOL(S_MANREGREL , 0x1122) +CV_SYMBOL(S_MANMANYREG2 , 0x1123) +CV_SYMBOL(S_DATAREF , 0x1126) +CV_SYMBOL(S_ANNOTATIONREF , 0x1128) +CV_SYMBOL(S_TOKENREF , 0x1129) +CV_SYMBOL(S_GMANPROC , 0x112a) +CV_SYMBOL(S_LMANPROC , 0x112b) +CV_SYMBOL(S_ATTR_FRAMEREL , 0x112e) +CV_SYMBOL(S_ATTR_REGISTER , 0x112f) +CV_SYMBOL(S_ATTR_REGREL , 0x1130) +CV_SYMBOL(S_ATTR_MANYREG , 0x1131) + + +CV_SYMBOL(S_SEPCODE , 0x1132) +CV_SYMBOL(S_LOCAL_2005 , 0x1133) +CV_SYMBOL(S_DEFRANGE_2005 , 0x1134) +CV_SYMBOL(S_DEFRANGE2_2005, 0x1135) +CV_SYMBOL(S_DISCARDED , 0x113b) + +// Current symbol types for most procedures as of this writing. +CV_SYMBOL(S_LPROCMIPS_ID , 0x1148) +CV_SYMBOL(S_GPROCMIPS_ID , 0x1149) +CV_SYMBOL(S_LPROCIA64_ID , 0x114a) +CV_SYMBOL(S_GPROCIA64_ID , 0x114b) + +CV_SYMBOL(S_DEFRANGE_HLSL , 0x1150) +CV_SYMBOL(S_GDATA_HLSL , 0x1151) +CV_SYMBOL(S_LDATA_HLSL , 0x1152) +CV_SYMBOL(S_LOCAL_DPC_GROUPSHARED, 0x1154) +CV_SYMBOL(S_DEFRANGE_DPC_PTR_TAG, 0x1157) +CV_SYMBOL(S_DPC_SYM_TAG_MAP, 0x1158) +CV_SYMBOL(S_ARMSWITCHTABLE , 0x1159) +CV_SYMBOL(S_POGODATA , 0x115c) +CV_SYMBOL(S_INLINESITE2 , 0x115d) +CV_SYMBOL(S_MOD_TYPEREF , 0x115f) +CV_SYMBOL(S_REF_MINIPDB , 0x1160) +CV_SYMBOL(S_PDBMAP , 0x1161) +CV_SYMBOL(S_GDATA_HLSL32 , 0x1162) +CV_SYMBOL(S_LDATA_HLSL32 , 0x1163) +CV_SYMBOL(S_GDATA_HLSL32_EX, 0x1164) +CV_SYMBOL(S_LDATA_HLSL32_EX, 0x1165) + +CV_SYMBOL(S_FASTLINK, 0x1167) // Undocumented +SYMBOL_RECORD_ALIAS(S_INLINEES, 0x1168, InlineesSym, CallerSym) // Undocumented + +// Known symbol types +SYMBOL_RECORD(S_END , 0x0006, ScopeEndSym) +SYMBOL_RECORD_ALIAS(S_INLINESITE_END , 0x114e, InlineSiteEnd, ScopeEndSym) +SYMBOL_RECORD_ALIAS(S_PROC_ID_END , 0x114f, ProcEnd, ScopeEndSym) + +SYMBOL_RECORD(S_THUNK32 , 0x1102, Thunk32Sym) +SYMBOL_RECORD(S_TRAMPOLINE , 0x112c, TrampolineSym) +SYMBOL_RECORD(S_SECTION , 0x1136, SectionSym) +SYMBOL_RECORD(S_COFFGROUP , 0x1137, CoffGroupSym) +SYMBOL_RECORD(S_EXPORT , 0x1138, ExportSym) + +SYMBOL_RECORD(S_LPROC32 , 0x110f, ProcSym) +SYMBOL_RECORD_ALIAS(S_GPROC32 , 0x1110, GlobalProcSym, ProcSym) +SYMBOL_RECORD_ALIAS(S_LPROC32_ID , 0x1146, ProcIdSym, ProcSym) +SYMBOL_RECORD_ALIAS(S_GPROC32_ID , 0x1147, GlobalProcIdSym, ProcSym) +SYMBOL_RECORD_ALIAS(S_LPROC32_DPC , 0x1155, DPCProcSym, ProcSym) +SYMBOL_RECORD_ALIAS(S_LPROC32_DPC_ID , 0x1156, DPCProcIdSym, ProcSym) + +SYMBOL_RECORD(S_REGISTER , 0x1106, RegisterSym) +SYMBOL_RECORD(S_PUB32 , 0x110e, PublicSym32) + +SYMBOL_RECORD(S_PROCREF , 0x1125, ProcRefSym) +SYMBOL_RECORD_ALIAS(S_LPROCREF, 0x1127, LocalProcRef, ProcRefSym) + + +SYMBOL_RECORD(S_ENVBLOCK , 0x113d, EnvBlockSym) + +SYMBOL_RECORD(S_INLINESITE , 0x114d, InlineSiteSym) +SYMBOL_RECORD(S_LOCAL , 0x113e, LocalSym) +SYMBOL_RECORD(S_DEFRANGE , 0x113f, DefRangeSym) +SYMBOL_RECORD(S_DEFRANGE_SUBFIELD, 0x1140, DefRangeSubfieldSym) +SYMBOL_RECORD(S_DEFRANGE_REGISTER, 0x1141, DefRangeRegisterSym) +SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL, 0x1142, DefRangeFramePointerRelSym) +SYMBOL_RECORD(S_DEFRANGE_SUBFIELD_REGISTER, 0x1143, DefRangeSubfieldRegisterSym) +SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE, 0x1144, DefRangeFramePointerRelFullScopeSym) +SYMBOL_RECORD(S_DEFRANGE_REGISTER_REL, 0x1145, DefRangeRegisterRelSym) +SYMBOL_RECORD(S_BLOCK32 , 0x1103, BlockSym) +SYMBOL_RECORD(S_LABEL32 , 0x1105, LabelSym) +SYMBOL_RECORD(S_OBJNAME , 0x1101, ObjNameSym) +SYMBOL_RECORD(S_COMPILE2 , 0x1116, Compile2Sym) +SYMBOL_RECORD(S_COMPILE3 , 0x113c, Compile3Sym) +SYMBOL_RECORD(S_FRAMEPROC , 0x1012, FrameProcSym) +SYMBOL_RECORD(S_CALLSITEINFO , 0x1139, CallSiteInfoSym) +SYMBOL_RECORD(S_FILESTATIC , 0x1153, FileStaticSym) +SYMBOL_RECORD(S_HEAPALLOCSITE , 0x115e, HeapAllocationSiteSym) +SYMBOL_RECORD(S_FRAMECOOKIE , 0x113a, FrameCookieSym) + +SYMBOL_RECORD(S_CALLEES , 0x115a, CallerSym) +SYMBOL_RECORD_ALIAS(S_CALLERS, 0x115b, CalleeSym, CallerSym) + +SYMBOL_RECORD(S_UDT , 0x1108, UDTSym) +SYMBOL_RECORD_ALIAS(S_COBOLUDT , 0x1109, CobolUDT, UDTSym) + +SYMBOL_RECORD(S_BUILDINFO , 0x114c, BuildInfoSym) +SYMBOL_RECORD(S_BPREL32 , 0x110b, BPRelativeSym) +SYMBOL_RECORD(S_REGREL32 , 0x1111, RegRelativeSym) + +SYMBOL_RECORD(S_CONSTANT , 0x1107, ConstantSym) +SYMBOL_RECORD_ALIAS(S_MANCONSTANT , 0x112d, ManagedConstant, ConstantSym) + +SYMBOL_RECORD(S_LDATA32 , 0x110c, DataSym) +SYMBOL_RECORD_ALIAS(S_GDATA32 , 0x110d, GlobalData, DataSym) +SYMBOL_RECORD_ALIAS(S_LMANDATA , 0x111c, ManagedLocalData, DataSym) +SYMBOL_RECORD_ALIAS(S_GMANDATA , 0x111d, ManagedGlobalData, DataSym) + +SYMBOL_RECORD(S_LTHREAD32 , 0x1112, ThreadLocalDataSym) +SYMBOL_RECORD_ALIAS(S_GTHREAD32 , 0x1113, GlobalTLS, ThreadLocalDataSym) + +SYMBOL_RECORD(S_UNAMESPACE , 0x1124, UsingNamespaceSym) + +#undef CV_SYMBOL +#undef SYMBOL_RECORD +#undef SYMBOL_RECORD_ALIAS diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewTypes.def b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewTypes.def new file mode 100644 index 00000000..a31111eb --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/CodeViewTypes.def @@ -0,0 +1,249 @@ +//===-- CodeViewTypes.def - All CodeView leaf types -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// See LEAF_ENUM_e in cvinfo.h. This should match the constants there. +// +//===----------------------------------------------------------------------===// + +// If the type is known, then we have a record describing it in TypeRecord.h. + +#ifndef CV_TYPE +#define CV_TYPE(lf_ename, value) +#endif + +// If the type is known, then we have a record describing it in TypeRecord.h. +#ifndef TYPE_RECORD +#define TYPE_RECORD(lf_ename, value, name) CV_TYPE(lf_ename, value) +#endif + +#ifndef TYPE_RECORD_ALIAS +#define TYPE_RECORD_ALIAS(lf_ename, value, name, alias_name) \ + TYPE_RECORD(lf_ename, value, name) +#endif + +#ifndef MEMBER_RECORD +#define MEMBER_RECORD(lf_ename, value, name) TYPE_RECORD(lf_ename, value, name) +#endif + +#ifndef MEMBER_RECORD_ALIAS +#define MEMBER_RECORD_ALIAS(lf_ename, value, name, alias_name) \ + MEMBER_RECORD(lf_ename, value, name) +#endif + +TYPE_RECORD(LF_POINTER, 0x1002, Pointer) +TYPE_RECORD(LF_MODIFIER, 0x1001, Modifier) +TYPE_RECORD(LF_PROCEDURE, 0x1008, Procedure) +TYPE_RECORD(LF_MFUNCTION, 0x1009, MemberFunction) +TYPE_RECORD(LF_LABEL, 0x000e, Label) +TYPE_RECORD(LF_ARGLIST, 0x1201, ArgList) + +TYPE_RECORD(LF_FIELDLIST, 0x1203, FieldList) + +TYPE_RECORD(LF_ARRAY, 0x1503, Array) +TYPE_RECORD(LF_CLASS, 0x1504, Class) +TYPE_RECORD_ALIAS(LF_STRUCTURE, 0x1505, Struct, Class) +TYPE_RECORD_ALIAS(LF_INTERFACE, 0x1519, Interface, Class) +TYPE_RECORD(LF_UNION, 0x1506, Union) +TYPE_RECORD(LF_ENUM, 0x1507, Enum) +TYPE_RECORD(LF_TYPESERVER2, 0x1515, TypeServer2) +TYPE_RECORD(LF_VFTABLE, 0x151d, VFTable) +TYPE_RECORD(LF_VTSHAPE, 0x000a, VFTableShape) + +TYPE_RECORD(LF_BITFIELD, 0x1205, BitField) + +// Member type records. These are generally not length prefixed, and appear +// inside of a field list record. +MEMBER_RECORD(LF_BCLASS, 0x1400, BaseClass) +MEMBER_RECORD_ALIAS(LF_BINTERFACE, 0x151a, BaseInterface, BaseClass) + +MEMBER_RECORD(LF_VBCLASS, 0x1401, VirtualBaseClass) +MEMBER_RECORD_ALIAS(LF_IVBCLASS, 0x1402, IndirectVirtualBaseClass, + VirtualBaseClass) + +MEMBER_RECORD(LF_VFUNCTAB, 0x1409, VFPtr) +MEMBER_RECORD(LF_STMEMBER, 0x150e, StaticDataMember) +MEMBER_RECORD(LF_METHOD, 0x150f, OverloadedMethod) +MEMBER_RECORD(LF_MEMBER, 0x150d, DataMember) +MEMBER_RECORD(LF_NESTTYPE, 0x1510, NestedType) +MEMBER_RECORD(LF_ONEMETHOD, 0x1511, OneMethod) +MEMBER_RECORD(LF_ENUMERATE, 0x1502, Enumerator) +MEMBER_RECORD(LF_INDEX, 0x1404, ListContinuation) + +// ID leaf records. Subsequent leaf types may be referenced from .debug$S. +TYPE_RECORD(LF_FUNC_ID, 0x1601, FuncId) +TYPE_RECORD(LF_MFUNC_ID, 0x1602, MemberFuncId) +TYPE_RECORD(LF_BUILDINFO, 0x1603, BuildInfo) +TYPE_RECORD(LF_SUBSTR_LIST, 0x1604, StringList) +TYPE_RECORD(LF_STRING_ID, 0x1605, StringId) +TYPE_RECORD(LF_UDT_SRC_LINE, 0x1606, UdtSourceLine) +TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine) + + +TYPE_RECORD(LF_METHODLIST, 0x1206, MethodOverloadList) + +TYPE_RECORD(LF_PRECOMP, 0x1509, Precomp) +TYPE_RECORD(LF_ENDPRECOMP, 0x0014, EndPrecomp) + +// 16 bit type records. +CV_TYPE(LF_MODIFIER_16t, 0x0001) +CV_TYPE(LF_POINTER_16t, 0x0002) +CV_TYPE(LF_ARRAY_16t, 0x0003) +CV_TYPE(LF_CLASS_16t, 0x0004) +CV_TYPE(LF_STRUCTURE_16t, 0x0005) +CV_TYPE(LF_UNION_16t, 0x0006) +CV_TYPE(LF_ENUM_16t, 0x0007) +CV_TYPE(LF_PROCEDURE_16t, 0x0008) +CV_TYPE(LF_MFUNCTION_16t, 0x0009) +CV_TYPE(LF_COBOL0_16t, 0x000b) +CV_TYPE(LF_COBOL1, 0x000c) +CV_TYPE(LF_BARRAY_16t, 0x000d) +CV_TYPE(LF_NULLLEAF, 0x000f) // LF_NULL +CV_TYPE(LF_NOTTRAN, 0x0010) +CV_TYPE(LF_DIMARRAY_16t, 0x0011) +CV_TYPE(LF_VFTPATH_16t, 0x0012) +CV_TYPE(LF_PRECOMP_16t, 0x0013) +CV_TYPE(LF_OEM_16t, 0x0015) +CV_TYPE(LF_TYPESERVER_ST, 0x0016) + +CV_TYPE(LF_SKIP_16t, 0x0200) +CV_TYPE(LF_ARGLIST_16t, 0x0201) +CV_TYPE(LF_DEFARG_16t, 0x0202) +CV_TYPE(LF_LIST, 0x0203) +CV_TYPE(LF_FIELDLIST_16t, 0x0204) +CV_TYPE(LF_DERIVED_16t, 0x0205) +CV_TYPE(LF_BITFIELD_16t, 0x0206) +CV_TYPE(LF_METHODLIST_16t, 0x0207) +CV_TYPE(LF_DIMCONU_16t, 0x0208) +CV_TYPE(LF_DIMCONLU_16t, 0x0209) +CV_TYPE(LF_DIMVARU_16t, 0x020a) +CV_TYPE(LF_DIMVARLU_16t, 0x020b) +CV_TYPE(LF_REFSYM, 0x020c) + +// 16 bit member types. Generally not length prefixed. +CV_TYPE(LF_BCLASS_16t, 0x0400) +CV_TYPE(LF_VBCLASS_16t, 0x0401) +CV_TYPE(LF_IVBCLASS_16t, 0x0402) +CV_TYPE(LF_ENUMERATE_ST, 0x0403) +CV_TYPE(LF_FRIENDFCN_16t, 0x0404) +CV_TYPE(LF_INDEX_16t, 0x0405) +CV_TYPE(LF_MEMBER_16t, 0x0406) +CV_TYPE(LF_STMEMBER_16t, 0x0407) +CV_TYPE(LF_METHOD_16t, 0x0408) +CV_TYPE(LF_NESTTYPE_16t, 0x0409) +CV_TYPE(LF_VFUNCTAB_16t, 0x040a) +CV_TYPE(LF_FRIENDCLS_16t, 0x040b) +CV_TYPE(LF_ONEMETHOD_16t, 0x040c) +CV_TYPE(LF_VFUNCOFF_16t, 0x040d) + +CV_TYPE(LF_TI16_MAX, 0x1000) + +CV_TYPE(LF_ARRAY_ST, 0x1003) +CV_TYPE(LF_CLASS_ST, 0x1004) +CV_TYPE(LF_STRUCTURE_ST, 0x1005) +CV_TYPE(LF_UNION_ST, 0x1006) +CV_TYPE(LF_ENUM_ST, 0x1007) +CV_TYPE(LF_COBOL0, 0x100a) +CV_TYPE(LF_BARRAY, 0x100b) +CV_TYPE(LF_DIMARRAY_ST, 0x100c) +CV_TYPE(LF_VFTPATH, 0x100d) +CV_TYPE(LF_PRECOMP_ST, 0x100e) +CV_TYPE(LF_OEM, 0x100f) +CV_TYPE(LF_ALIAS_ST, 0x1010) +CV_TYPE(LF_OEM2, 0x1011) + +CV_TYPE(LF_SKIP, 0x1200) +CV_TYPE(LF_DEFARG_ST, 0x1202) +CV_TYPE(LF_DERIVED, 0x1204) +CV_TYPE(LF_DIMCONU, 0x1207) +CV_TYPE(LF_DIMCONLU, 0x1208) +CV_TYPE(LF_DIMVARU, 0x1209) +CV_TYPE(LF_DIMVARLU, 0x120a) + +// Member type records. These are generally not length prefixed, and appear +// inside of a field list record. +CV_TYPE(LF_FRIENDFCN_ST, 0x1403) +CV_TYPE(LF_MEMBER_ST, 0x1405) +CV_TYPE(LF_STMEMBER_ST, 0x1406) +CV_TYPE(LF_METHOD_ST, 0x1407) +CV_TYPE(LF_NESTTYPE_ST, 0x1408) +CV_TYPE(LF_FRIENDCLS, 0x140a) +CV_TYPE(LF_ONEMETHOD_ST, 0x140b) +CV_TYPE(LF_VFUNCOFF, 0x140c) +CV_TYPE(LF_NESTTYPEEX_ST, 0x140d) +CV_TYPE(LF_MEMBERMODIFY_ST, 0x140e) +CV_TYPE(LF_MANAGED_ST, 0x140f) + +CV_TYPE(LF_ST_MAX, 0x1500) +CV_TYPE(LF_TYPESERVER, 0x1501) +CV_TYPE(LF_DIMARRAY, 0x1508) +CV_TYPE(LF_ALIAS, 0x150a) +CV_TYPE(LF_DEFARG, 0x150b) +CV_TYPE(LF_FRIENDFCN, 0x150c) +CV_TYPE(LF_NESTTYPEEX, 0x1512) +CV_TYPE(LF_MEMBERMODIFY, 0x1513) +CV_TYPE(LF_MANAGED, 0x1514) +CV_TYPE(LF_STRIDED_ARRAY, 0x1516) +CV_TYPE(LF_HLSL, 0x1517) +CV_TYPE(LF_MODIFIER_EX, 0x1518) +CV_TYPE(LF_VECTOR, 0x151b) +CV_TYPE(LF_MATRIX, 0x151c) + +// ID leaf records. Subsequent leaf types may be referenced from .debug$S. + +// Numeric leaf types. These are generally contained in other records, and not +// encountered in the main type stream. + +CV_TYPE(LF_NUMERIC, 0x8000) +CV_TYPE(LF_CHAR, 0x8000) +CV_TYPE(LF_SHORT, 0x8001) +CV_TYPE(LF_USHORT, 0x8002) +CV_TYPE(LF_LONG, 0x8003) +CV_TYPE(LF_ULONG, 0x8004) +CV_TYPE(LF_REAL32, 0x8005) +CV_TYPE(LF_REAL64, 0x8006) +CV_TYPE(LF_REAL80, 0x8007) +CV_TYPE(LF_REAL128, 0x8008) +CV_TYPE(LF_QUADWORD, 0x8009) +CV_TYPE(LF_UQUADWORD, 0x800a) +CV_TYPE(LF_REAL48, 0x800b) +CV_TYPE(LF_COMPLEX32, 0x800c) +CV_TYPE(LF_COMPLEX64, 0x800d) +CV_TYPE(LF_COMPLEX80, 0x800e) +CV_TYPE(LF_COMPLEX128, 0x800f) +CV_TYPE(LF_VARSTRING, 0x8010) +CV_TYPE(LF_OCTWORD, 0x8017) +CV_TYPE(LF_UOCTWORD, 0x8018) +CV_TYPE(LF_DECIMAL, 0x8019) +CV_TYPE(LF_DATE, 0x801a) +CV_TYPE(LF_UTF8STRING, 0x801b) +CV_TYPE(LF_REAL16, 0x801c) + +// Padding bytes. These are emitted into alignment bytes in the type stream. + +CV_TYPE(LF_PAD0, 0xf0) +CV_TYPE(LF_PAD1, 0xf1) +CV_TYPE(LF_PAD2, 0xf2) +CV_TYPE(LF_PAD3, 0xf3) +CV_TYPE(LF_PAD4, 0xf4) +CV_TYPE(LF_PAD5, 0xf5) +CV_TYPE(LF_PAD6, 0xf6) +CV_TYPE(LF_PAD7, 0xf7) +CV_TYPE(LF_PAD8, 0xf8) +CV_TYPE(LF_PAD9, 0xf9) +CV_TYPE(LF_PAD10, 0xfa) +CV_TYPE(LF_PAD11, 0xfb) +CV_TYPE(LF_PAD12, 0xfc) +CV_TYPE(LF_PAD13, 0xfd) +CV_TYPE(LF_PAD14, 0xfe) +CV_TYPE(LF_PAD15, 0xff) + +#undef CV_TYPE +#undef TYPE_RECORD +#undef TYPE_RECORD_ALIAS +#undef MEMBER_RECORD +#undef MEMBER_RECORD_ALIAS diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h b/clang-r353983/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h new file mode 100644 index 00000000..cd67f783 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h @@ -0,0 +1,64 @@ +//===- ContinuationRecordBuilder.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_CONTINUATIONRECORDBUILDER_H +#define LLVM_DEBUGINFO_CODEVIEW_CONTINUATIONRECORDBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Error.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <vector> + +namespace llvm { +namespace codeview { +enum class ContinuationRecordKind { FieldList, MethodOverloadList }; + +class ContinuationRecordBuilder { + SmallVector<uint32_t, 4> SegmentOffsets; + Optional<ContinuationRecordKind> Kind; + AppendingBinaryByteStream Buffer; + BinaryStreamWriter SegmentWriter; + TypeRecordMapping Mapping; + ArrayRef<uint8_t> InjectedSegmentBytes; + + uint32_t getCurrentSegmentLength() const; + + void insertSegmentEnd(uint32_t Offset); + CVType createSegmentRecord(uint32_t OffBegin, uint32_t OffEnd, + Optional<TypeIndex> RefersTo); + +public: + ContinuationRecordBuilder(); + ~ContinuationRecordBuilder(); + + void begin(ContinuationRecordKind RecordKind); + + // This template is explicitly instantiated in the implementation file for all + // supported types. The method itself is ugly, so inlining it into the header + // file clutters an otherwise straightforward interface. + template <typename RecordType> void writeMemberType(RecordType &Record); + + std::vector<CVType> end(TypeIndex Index); +}; +} // namespace codeview +} // namespace llvm + +#endif
\ No newline at end of file diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h new file mode 100644 index 00000000..01f83676 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h @@ -0,0 +1,103 @@ +//===- DebugChecksumsSubsection.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGCHECKSUMSSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCHECKSUMSSUBSECTION_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +namespace codeview { + +class DebugStringTableSubsection; + +struct FileChecksumEntry { + uint32_t FileNameOffset; // Byte offset of filename in global stringtable. + FileChecksumKind Kind; // The type of checksum. + ArrayRef<uint8_t> Checksum; // The bytes of the checksum. +}; + +} // end namespace codeview + +template <> struct VarStreamArrayExtractor<codeview::FileChecksumEntry> { +public: + using ContextType = void; + + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + codeview::FileChecksumEntry &Item); +}; + +namespace codeview { + +class DebugChecksumsSubsectionRef final : public DebugSubsectionRef { + using FileChecksumArray = VarStreamArray<codeview::FileChecksumEntry>; + using Iterator = FileChecksumArray::Iterator; + +public: + DebugChecksumsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::FileChecksums) {} + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::FileChecksums; + } + + bool valid() const { return Checksums.valid(); } + + Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); + + Iterator begin() const { return Checksums.begin(); } + Iterator end() const { return Checksums.end(); } + + const FileChecksumArray &getArray() const { return Checksums; } + +private: + FileChecksumArray Checksums; +}; + +class DebugChecksumsSubsection final : public DebugSubsection { +public: + explicit DebugChecksumsSubsection(DebugStringTableSubsection &Strings); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::FileChecksums; + } + + void addChecksum(StringRef FileName, FileChecksumKind Kind, + ArrayRef<uint8_t> Bytes); + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + uint32_t mapChecksumOffset(StringRef FileName) const; + +private: + DebugStringTableSubsection &Strings; + + DenseMap<uint32_t, uint32_t> OffsetMap; + uint32_t SerializedSize = 0; + BumpPtrAllocator Storage; + std::vector<FileChecksumEntry> Checksums; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGCHECKSUMSSUBSECTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h new file mode 100644 index 00000000..64a78a7c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h @@ -0,0 +1,67 @@ +//===- DebugCrossExSubsection.h ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <map> + +namespace llvm { +namespace codeview { + +class DebugCrossModuleExportsSubsectionRef final : public DebugSubsectionRef { + using ReferenceArray = FixedStreamArray<CrossModuleExport>; + using Iterator = ReferenceArray::Iterator; + +public: + DebugCrossModuleExportsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::CrossScopeExports) {} + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::CrossScopeExports; + } + + Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); + + Iterator begin() const { return References.begin(); } + Iterator end() const { return References.end(); } + +private: + FixedStreamArray<CrossModuleExport> References; +}; + +class DebugCrossModuleExportsSubsection final : public DebugSubsection { +public: + DebugCrossModuleExportsSubsection() + : DebugSubsection(DebugSubsectionKind::CrossScopeExports) {} + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::CrossScopeExports; + } + + void addMapping(uint32_t Local, uint32_t Global); + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + +private: + std::map<uint32_t, uint32_t> Mappings; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h new file mode 100644 index 00000000..e7683cb2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h @@ -0,0 +1,94 @@ +//===- DebugCrossImpSubsection.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSIMPSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSIMPSUBSECTION_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +namespace codeview { + +struct CrossModuleImportItem { + const CrossModuleImport *Header = nullptr; + FixedStreamArray<support::ulittle32_t> Imports; +}; + +} // end namespace codeview + +template <> struct VarStreamArrayExtractor<codeview::CrossModuleImportItem> { +public: + using ContextType = void; + + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + codeview::CrossModuleImportItem &Item); +}; + +namespace codeview { + +class DebugStringTableSubsection; + +class DebugCrossModuleImportsSubsectionRef final : public DebugSubsectionRef { + using ReferenceArray = VarStreamArray<CrossModuleImportItem>; + using Iterator = ReferenceArray::Iterator; + +public: + DebugCrossModuleImportsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::CrossScopeImports) {} + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::CrossScopeImports; + } + + Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); + + Iterator begin() const { return References.begin(); } + Iterator end() const { return References.end(); } + +private: + ReferenceArray References; +}; + +class DebugCrossModuleImportsSubsection final : public DebugSubsection { +public: + explicit DebugCrossModuleImportsSubsection( + DebugStringTableSubsection &Strings) + : DebugSubsection(DebugSubsectionKind::CrossScopeImports), + Strings(Strings) {} + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::CrossScopeImports; + } + + void addImport(StringRef Module, uint32_t ImportId); + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + +private: + DebugStringTableSubsection &Strings; + StringMap<std::vector<support::ulittle32_t>> Mappings; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSIMPSUBSECTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h new file mode 100644 index 00000000..d5cd6402 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h @@ -0,0 +1,63 @@ +//===- DebugFrameDataSubsection.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGFRAMEDATASUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGFRAMEDATASUBSECTION_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class DebugFrameDataSubsectionRef final : public DebugSubsectionRef { +public: + DebugFrameDataSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::FrameData) {} + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::FrameData; + } + + Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); + + FixedStreamArray<FrameData>::Iterator begin() const { return Frames.begin(); } + FixedStreamArray<FrameData>::Iterator end() const { return Frames.end(); } + + const support::ulittle32_t *getRelocPtr() const { return RelocPtr; } + +private: + const support::ulittle32_t *RelocPtr = nullptr; + FixedStreamArray<FrameData> Frames; +}; + +class DebugFrameDataSubsection final : public DebugSubsection { +public: + DebugFrameDataSubsection(bool IncludeRelocPtr) + : DebugSubsection(DebugSubsectionKind::FrameData), + IncludeRelocPtr(IncludeRelocPtr) {} + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::FrameData; + } + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + void addFrameData(const FrameData &Frame); + void setFrames(ArrayRef<FrameData> Frames); + +private: + bool IncludeRelocPtr = false; + std::vector<FrameData> Frames; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h new file mode 100644 index 00000000..1ca2bd02 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h @@ -0,0 +1,120 @@ +//===- DebugInlineeLinesSubsection.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGINLINEELINESSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGINLINEELINESSUBSECTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +namespace codeview { + +class DebugChecksumsSubsection; + +enum class InlineeLinesSignature : uint32_t { + Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE + ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX +}; + +struct InlineeSourceLineHeader { + TypeIndex Inlinee; // ID of the function that was inlined. + support::ulittle32_t FileID; // Offset into FileChecksums subsection. + support::ulittle32_t SourceLineNum; // First line of inlined code. + // If extra files present: + // ulittle32_t ExtraFileCount; + // ulittle32_t Files[]; +}; + +struct InlineeSourceLine { + const InlineeSourceLineHeader *Header; + FixedStreamArray<support::ulittle32_t> ExtraFiles; +}; + +} // end namespace codeview + +template <> struct VarStreamArrayExtractor<codeview::InlineeSourceLine> { + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + codeview::InlineeSourceLine &Item); + + bool HasExtraFiles = false; +}; + +namespace codeview { + +class DebugInlineeLinesSubsectionRef final : public DebugSubsectionRef { + using LinesArray = VarStreamArray<InlineeSourceLine>; + using Iterator = LinesArray::Iterator; + +public: + DebugInlineeLinesSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::InlineeLines; + } + + Error initialize(BinaryStreamReader Reader); + bool hasExtraFiles() const; + + Iterator begin() const { return Lines.begin(); } + Iterator end() const { return Lines.end(); } + +private: + InlineeLinesSignature Signature; + VarStreamArray<InlineeSourceLine> Lines; +}; + +class DebugInlineeLinesSubsection final : public DebugSubsection { +public: + struct Entry { + std::vector<support::ulittle32_t> ExtraFiles; + InlineeSourceLineHeader Header; + }; + + DebugInlineeLinesSubsection(DebugChecksumsSubsection &Checksums, + bool HasExtraFiles = false); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::InlineeLines; + } + + Error commit(BinaryStreamWriter &Writer) const override; + uint32_t calculateSerializedSize() const override; + + void addInlineSite(TypeIndex FuncId, StringRef FileName, uint32_t SourceLine); + void addExtraFile(StringRef FileName); + + bool hasExtraFiles() const { return HasExtraFiles; } + void setHasExtraFiles(bool Has) { HasExtraFiles = Has; } + + std::vector<Entry>::const_iterator begin() const { return Entries.begin(); } + std::vector<Entry>::const_iterator end() const { return Entries.end(); } + +private: + DebugChecksumsSubsection &Checksums; + bool HasExtraFiles = false; + uint32_t ExtraFileCount = 0; + std::vector<Entry> Entries; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGINLINEELINESSUBSECTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h new file mode 100644 index 00000000..1f8e56c5 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h @@ -0,0 +1,149 @@ +//===- DebugLinesSubsection.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace codeview { + +class DebugChecksumsSubsection; +class DebugStringTableSubsection; + +// Corresponds to the `CV_DebugSLinesHeader_t` structure. +struct LineFragmentHeader { + support::ulittle32_t RelocOffset; // Code offset of line contribution. + support::ulittle16_t RelocSegment; // Code segment of line contribution. + support::ulittle16_t Flags; // See LineFlags enumeration. + support::ulittle32_t CodeSize; // Code size of this line contribution. +}; + +// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure. +struct LineBlockFragmentHeader { + support::ulittle32_t NameIndex; // Offset of FileChecksum entry in File + // checksums buffer. The checksum entry then + // contains another offset into the string + // table of the actual name. + support::ulittle32_t NumLines; // Number of lines + support::ulittle32_t BlockSize; // Code size of block, in bytes. + // The following two variable length arrays appear immediately after the + // header. The structure definitions follow. + // LineNumberEntry Lines[NumLines]; + // ColumnNumberEntry Columns[NumLines]; +}; + +// Corresponds to `CV_Line_t` structure +struct LineNumberEntry { + support::ulittle32_t Offset; // Offset to start of code bytes for line number + support::ulittle32_t Flags; // Start:24, End:7, IsStatement:1 +}; + +// Corresponds to `CV_Column_t` structure +struct ColumnNumberEntry { + support::ulittle16_t StartColumn; + support::ulittle16_t EndColumn; +}; + +struct LineColumnEntry { + support::ulittle32_t NameIndex; + FixedStreamArray<LineNumberEntry> LineNumbers; + FixedStreamArray<ColumnNumberEntry> Columns; +}; + +class LineColumnExtractor { +public: + Error operator()(BinaryStreamRef Stream, uint32_t &Len, + LineColumnEntry &Item); + + const LineFragmentHeader *Header = nullptr; +}; + +class DebugLinesSubsectionRef final : public DebugSubsectionRef { + friend class LineColumnExtractor; + + using LineInfoArray = VarStreamArray<LineColumnEntry, LineColumnExtractor>; + using Iterator = LineInfoArray::Iterator; + +public: + DebugLinesSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::Lines; + } + + Error initialize(BinaryStreamReader Reader); + + Iterator begin() const { return LinesAndColumns.begin(); } + Iterator end() const { return LinesAndColumns.end(); } + + const LineFragmentHeader *header() const { return Header; } + + bool hasColumnInfo() const; + +private: + const LineFragmentHeader *Header = nullptr; + LineInfoArray LinesAndColumns; +}; + +class DebugLinesSubsection final : public DebugSubsection { + struct Block { + Block(uint32_t ChecksumBufferOffset) + : ChecksumBufferOffset(ChecksumBufferOffset) {} + + uint32_t ChecksumBufferOffset; + std::vector<LineNumberEntry> Lines; + std::vector<ColumnNumberEntry> Columns; + }; + +public: + DebugLinesSubsection(DebugChecksumsSubsection &Checksums, + DebugStringTableSubsection &Strings); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::Lines; + } + + void createBlock(StringRef FileName); + void addLineInfo(uint32_t Offset, const LineInfo &Line); + void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line, + uint32_t ColStart, uint32_t ColEnd); + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + void setRelocationAddress(uint16_t Segment, uint32_t Offset); + void setCodeSize(uint32_t Size); + void setFlags(LineFlags Flags); + + bool hasColumnInfo() const; + +private: + DebugChecksumsSubsection &Checksums; + uint32_t RelocOffset = 0; + uint16_t RelocSegment = 0; + uint32_t CodeSize = 0; + LineFlags Flags = LF_None; + std::vector<Block> Blocks; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h new file mode 100644 index 00000000..6e5b8add --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h @@ -0,0 +1,96 @@ +//===- DebugStringTableSubsection.h - CodeView String Table -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" +#include <cstdint> + +namespace llvm { + +class BinaryStreamReader; + +namespace codeview { + +/// Represents a read-only view of a CodeView string table. This is a very +/// simple flat buffer consisting of null-terminated strings, where strings +/// are retrieved by their offset in the buffer. DebugStringTableSubsectionRef +/// does not own the underlying storage for the buffer. +class DebugStringTableSubsectionRef : public DebugSubsectionRef { +public: + DebugStringTableSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::StringTable; + } + + Error initialize(BinaryStreamRef Contents); + Error initialize(BinaryStreamReader &Reader); + + Expected<StringRef> getString(uint32_t Offset) const; + + bool valid() const { return Stream.valid(); } + + BinaryStreamRef getBuffer() const { return Stream; } + +private: + BinaryStreamRef Stream; +}; + +/// Represents a read-write view of a CodeView string table. +/// DebugStringTableSubsection owns the underlying storage for the table, and is +/// capable of serializing the string table into a format understood by +/// DebugStringTableSubsectionRef. +class DebugStringTableSubsection : public DebugSubsection { +public: + DebugStringTableSubsection(); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::StringTable; + } + + // If string S does not exist in the string table, insert it. + // Returns the ID for S. + uint32_t insert(StringRef S); + + // Return the ID for string S. Assumes S exists in the table. + uint32_t getIdForString(StringRef S) const; + + StringRef getStringForId(uint32_t Id) const; + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + uint32_t size() const; + + StringMap<uint32_t>::const_iterator begin() const { + return StringToId.begin(); + } + + StringMap<uint32_t>::const_iterator end() const { return StringToId.end(); } + + std::vector<uint32_t> sortedIds() const; + +private: + DenseMap<uint32_t, StringRef> IdToString; + StringMap<uint32_t> StringToId; + uint32_t StringSize = 1; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSubsection.h new file mode 100644 index 00000000..66272870 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSubsection.h @@ -0,0 +1,51 @@ +//===- DebugSubsection.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Casting.h" + +namespace llvm { +namespace codeview { + +class DebugSubsectionRef { +public: + explicit DebugSubsectionRef(DebugSubsectionKind Kind) : Kind(Kind) {} + virtual ~DebugSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { return true; } + + DebugSubsectionKind kind() const { return Kind; } + +protected: + DebugSubsectionKind Kind; +}; + +class DebugSubsection { +public: + explicit DebugSubsection(DebugSubsectionKind Kind) : Kind(Kind) {} + virtual ~DebugSubsection(); + + static bool classof(const DebugSubsection *S) { return true; } + + DebugSubsectionKind kind() const { return Kind; } + + virtual Error commit(BinaryStreamWriter &Writer) const = 0; + virtual uint32_t calculateSerializedSize() const = 0; + +protected: + DebugSubsectionKind Kind; +}; + +} // namespace codeview +} // namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h new file mode 100644 index 00000000..bcb379f0 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h @@ -0,0 +1,102 @@ +//===- DebugSubsectionRecord.h ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" +#include <cstdint> +#include <memory> + +namespace llvm { + +class BinaryStreamWriter; + +namespace codeview { + +class DebugSubsection; + +// Corresponds to the `CV_DebugSSubsectionHeader_t` structure. +struct DebugSubsectionHeader { + support::ulittle32_t Kind; // codeview::DebugSubsectionKind enum + support::ulittle32_t Length; // number of bytes occupied by this record. +}; + +class DebugSubsectionRecord { +public: + DebugSubsectionRecord(); + DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data, + CodeViewContainer Container); + + static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info, + CodeViewContainer Container); + + uint32_t getRecordLength() const; + DebugSubsectionKind kind() const; + BinaryStreamRef getRecordData() const; + +private: + CodeViewContainer Container = CodeViewContainer::ObjectFile; + DebugSubsectionKind Kind = DebugSubsectionKind::None; + BinaryStreamRef Data; +}; + +class DebugSubsectionRecordBuilder { +public: + DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection, + CodeViewContainer Container); + + /// Use this to copy existing subsections directly from source to destination. + /// For example, line table subsections in an object file only need to be + /// relocated before being copied into the PDB. + DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents, + CodeViewContainer Container); + + uint32_t calculateSerializedLength(); + Error commit(BinaryStreamWriter &Writer) const; + +private: + /// The subsection to build. Will be null if Contents is non-empty. + std::shared_ptr<DebugSubsection> Subsection; + + /// The bytes of the subsection. Only non-empty if Subsection is null. + DebugSubsectionRecord Contents; + + CodeViewContainer Container; +}; + +} // end namespace codeview + +template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> { + Error operator()(BinaryStreamRef Stream, uint32_t &Length, + codeview::DebugSubsectionRecord &Info) { + // FIXME: We need to pass the container type through to this function. In + // practice this isn't super important since the subsection header describes + // its length and we can just skip it. It's more important when writing. + if (auto EC = codeview::DebugSubsectionRecord::initialize( + Stream, Info, codeview::CodeViewContainer::Pdb)) + return EC; + Length = alignTo(Info.getRecordLength(), 4); + return Error::success(); + } +}; + +namespace codeview { + +using DebugSubsectionArray = VarStreamArray<DebugSubsectionRecord>; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h new file mode 100644 index 00000000..720b1b49 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h @@ -0,0 +1,113 @@ +//===- DebugSubsectionVisitor.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" +#include "llvm/Support/Error.h" +#include <cstdint> + +namespace llvm { + +namespace codeview { + +class DebugChecksumsSubsectionRef; +class DebugSubsectionRecord; +class DebugInlineeLinesSubsectionRef; +class DebugCrossModuleExportsSubsectionRef; +class DebugCrossModuleImportsSubsectionRef; +class DebugFrameDataSubsectionRef; +class DebugLinesSubsectionRef; +class DebugStringTableSubsectionRef; +class DebugSymbolRVASubsectionRef; +class DebugSymbolsSubsectionRef; +class DebugUnknownSubsectionRef; +class StringsAndChecksumsRef; + +class DebugSubsectionVisitor { +public: + virtual ~DebugSubsectionVisitor() = default; + + virtual Error visitUnknown(DebugUnknownSubsectionRef &Unknown) { + return Error::success(); + } + virtual Error visitLines(DebugLinesSubsectionRef &Lines, + const StringsAndChecksumsRef &State) = 0; + virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, + const StringsAndChecksumsRef &State) = 0; + virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, + const StringsAndChecksumsRef &State) = 0; + virtual Error + visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE, + const StringsAndChecksumsRef &State) = 0; + virtual Error + visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE, + const StringsAndChecksumsRef &State) = 0; + + virtual Error visitStringTable(DebugStringTableSubsectionRef &ST, + const StringsAndChecksumsRef &State) = 0; + + virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE, + const StringsAndChecksumsRef &State) = 0; + + virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD, + const StringsAndChecksumsRef &State) = 0; + virtual Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs, + const StringsAndChecksumsRef &State) = 0; +}; + +Error visitDebugSubsection(const DebugSubsectionRecord &R, + DebugSubsectionVisitor &V, + const StringsAndChecksumsRef &State); + +namespace detail { +template <typename T> +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, + StringsAndChecksumsRef &State) { + State.initialize(std::forward<T>(FragmentRange)); + + for (const DebugSubsectionRecord &L : FragmentRange) { + if (auto EC = visitDebugSubsection(L, V, State)) + return EC; + } + return Error::success(); +} +} // namespace detail + +template <typename T> +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) { + StringsAndChecksumsRef State; + return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V, + State); +} + +template <typename T> +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, + const DebugStringTableSubsectionRef &Strings) { + StringsAndChecksumsRef State(Strings); + return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V, + State); +} + +template <typename T> +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums) { + StringsAndChecksumsRef State(Strings, Checksums); + return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V, + State); +} + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h new file mode 100644 index 00000000..91b740ce --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h @@ -0,0 +1,66 @@ +//===- DebugSymbolRVASubsection.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLRVASUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLRVASUBSECTION_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +class BinaryStreamReader; + +namespace codeview { + +class DebugSymbolRVASubsectionRef final : public DebugSubsectionRef { +public: + using ArrayType = FixedStreamArray<support::ulittle32_t>; + + DebugSymbolRVASubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::CoffSymbolRVA; + } + + ArrayType::Iterator begin() const { return RVAs.begin(); } + ArrayType::Iterator end() const { return RVAs.end(); } + + Error initialize(BinaryStreamReader &Reader); + +private: + ArrayType RVAs; +}; + +class DebugSymbolRVASubsection final : public DebugSubsection { +public: + DebugSymbolRVASubsection(); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::CoffSymbolRVA; + } + + Error commit(BinaryStreamWriter &Writer) const override; + uint32_t calculateSerializedSize() const override; + + void addRVA(uint32_t RVA) { RVAs.push_back(support::ulittle32_t(RVA)); } + +private: + std::vector<support::ulittle32_t> RVAs; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLRVASUBSECTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h new file mode 100644 index 00000000..784fc594 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h @@ -0,0 +1,55 @@ +//===- DebugSymbolsSubsection.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLSSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLSSUBSECTION_H + +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class DebugSymbolsSubsectionRef final : public DebugSubsectionRef { +public: + DebugSymbolsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::Symbols) {} + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::Symbols; + } + + Error initialize(BinaryStreamReader Reader); + + CVSymbolArray::Iterator begin() const { return Records.begin(); } + CVSymbolArray::Iterator end() const { return Records.end(); } + +private: + CVSymbolArray Records; +}; + +class DebugSymbolsSubsection final : public DebugSubsection { +public: + DebugSymbolsSubsection() : DebugSubsection(DebugSubsectionKind::Symbols) {} + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::Symbols; + } + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + void addSymbol(CVSymbol Symbol); + +private: + uint32_t Length = 0; + std::vector<CVSymbol> Records; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h new file mode 100644 index 00000000..fa7df325 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h @@ -0,0 +1,31 @@ +//===- DebugUnknownSubsection.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGUNKNOWNFRAGMENT_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGUNKNOWNFRAGMENT_H + +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamRef.h" + +namespace llvm { +namespace codeview { + +class DebugUnknownSubsectionRef final : public DebugSubsectionRef { +public: + DebugUnknownSubsectionRef(DebugSubsectionKind Kind, BinaryStreamRef Data) + : DebugSubsectionRef(Kind), Data(Data) {} + + BinaryStreamRef getData() const { return Data; } + +private: + BinaryStreamRef Data; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/EnumTables.h b/clang-r353983/include/llvm/DebugInfo/CodeView/EnumTables.h new file mode 100644 index 00000000..74f8c717 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/EnumTables.h @@ -0,0 +1,44 @@ +//===- EnumTables.h - Enum to string conversion tables ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_ENUMTABLES_H +#define LLVM_DEBUGINFO_CODEVIEW_ENUMTABLES_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/Support/ScopedPrinter.h" +#include <cstdint> + +namespace llvm { +namespace codeview { + +ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames(); +ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames(); +ArrayRef<EnumEntry<uint16_t>> getRegisterNames(); +ArrayRef<EnumEntry<uint32_t>> getPublicSymFlagNames(); +ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames(); +ArrayRef<EnumEntry<uint16_t>> getLocalFlagNames(); +ArrayRef<EnumEntry<uint8_t>> getFrameCookieKindNames(); +ArrayRef<EnumEntry<SourceLanguage>> getSourceLanguageNames(); +ArrayRef<EnumEntry<uint32_t>> getCompileSym2FlagNames(); +ArrayRef<EnumEntry<uint32_t>> getCompileSym3FlagNames(); +ArrayRef<EnumEntry<uint32_t>> getFileChecksumNames(); +ArrayRef<EnumEntry<unsigned>> getCPUTypeNames(); +ArrayRef<EnumEntry<uint32_t>> getFrameProcSymFlagNames(); +ArrayRef<EnumEntry<uint16_t>> getExportSymFlagNames(); +ArrayRef<EnumEntry<uint32_t>> getModuleSubstreamKindNames(); +ArrayRef<EnumEntry<uint8_t>> getThunkOrdinalNames(); +ArrayRef<EnumEntry<uint16_t>> getTrampolineNames(); +ArrayRef<EnumEntry<COFF::SectionCharacteristics>> +getImageSectionCharacteristicNames(); + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_ENUMTABLES_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/Formatters.h b/clang-r353983/include/llvm/DebugInfo/CodeView/Formatters.h new file mode 100644 index 00000000..7d04a6a8 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/Formatters.h @@ -0,0 +1,72 @@ +//===- Formatters.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_FORMATTERS_H +#define LLVM_DEBUGINFO_CODEVIEW_FORMATTERS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/GUID.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdint> + +namespace llvm { + +namespace codeview { + +namespace detail { + +class GuidAdapter final : public FormatAdapter<ArrayRef<uint8_t>> { + ArrayRef<uint8_t> Guid; + +public: + explicit GuidAdapter(ArrayRef<uint8_t> Guid); + explicit GuidAdapter(StringRef Guid); + + void format(raw_ostream &Stream, StringRef Style) override; +}; + +} // end namespace detail + +inline detail::GuidAdapter fmt_guid(StringRef Item) { + return detail::GuidAdapter(Item); +} + +inline detail::GuidAdapter fmt_guid(ArrayRef<uint8_t> Item) { + return detail::GuidAdapter(Item); +} + +} // end namespace codeview + +template <> struct format_provider<codeview::TypeIndex> { +public: + static void format(const codeview::TypeIndex &V, raw_ostream &Stream, + StringRef Style) { + if (V.isNoneType()) + Stream << "<no type>"; + else { + Stream << formatv("{0:X+4}", V.getIndex()); + if (V.isSimple()) + Stream << " (" << codeview::TypeIndex::simpleTypeName(V) << ")"; + } + } +}; + +template <> struct format_provider<codeview::GUID> { + static void format(const codeview::GUID &V, llvm::raw_ostream &Stream, + StringRef Style) { + Stream << V; + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_FORMATTERS_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/FunctionId.h b/clang-r353983/include/llvm/DebugInfo/CodeView/FunctionId.h new file mode 100644 index 00000000..bc102278 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/FunctionId.h @@ -0,0 +1,55 @@ +//===- FunctionId.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_FUNCTIONID_H +#define LLVM_DEBUGINFO_CODEVIEW_FUNCTIONID_H + +#include <cinttypes> + +namespace llvm { +namespace codeview { + +class FunctionId { +public: + FunctionId() : Index(0) {} + + explicit FunctionId(uint32_t Index) : Index(Index) {} + + uint32_t getIndex() const { return Index; } + +private: + uint32_t Index; +}; + +inline bool operator==(const FunctionId &A, const FunctionId &B) { + return A.getIndex() == B.getIndex(); +} + +inline bool operator!=(const FunctionId &A, const FunctionId &B) { + return A.getIndex() != B.getIndex(); +} + +inline bool operator<(const FunctionId &A, const FunctionId &B) { + return A.getIndex() < B.getIndex(); +} + +inline bool operator<=(const FunctionId &A, const FunctionId &B) { + return A.getIndex() <= B.getIndex(); +} + +inline bool operator>(const FunctionId &A, const FunctionId &B) { + return A.getIndex() > B.getIndex(); +} + +inline bool operator>=(const FunctionId &A, const FunctionId &B) { + return A.getIndex() >= B.getIndex(); +} +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/GUID.h b/clang-r353983/include/llvm/DebugInfo/CodeView/GUID.h new file mode 100644 index 00000000..5f807e6f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/GUID.h @@ -0,0 +1,54 @@ +//===- GUID.h ---------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_GUID_H +#define LLVM_DEBUGINFO_CODEVIEW_GUID_H + +#include <cstdint> +#include <cstring> + +namespace llvm { +class raw_ostream; + +namespace codeview { + +/// This represents the 'GUID' type from windows.h. +struct GUID { + uint8_t Guid[16]; +}; + +inline bool operator==(const GUID &LHS, const GUID &RHS) { + return 0 == ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)); +} + +inline bool operator<(const GUID &LHS, const GUID &RHS) { + return ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)) < 0; +} + +inline bool operator<=(const GUID &LHS, const GUID &RHS) { + return ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)) <= 0; +} + +inline bool operator>(const GUID &LHS, const GUID &RHS) { + return !(LHS <= RHS); +} + +inline bool operator>=(const GUID &LHS, const GUID &RHS) { + return !(LHS < RHS); +} + +inline bool operator!=(const GUID &LHS, const GUID &RHS) { + return !(LHS == RHS); +} + +raw_ostream &operator<<(raw_ostream &OS, const GUID &Guid); + +} // namespace codeview +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h b/clang-r353983/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h new file mode 100644 index 00000000..a43ce20e --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h @@ -0,0 +1,115 @@ +//===- GlobalTypeTableBuilder.h ----------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPETABLEBUILDER_H +#define LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPETABLEBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h" +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeHashing.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/Allocator.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <vector> + +namespace llvm { +namespace codeview { + +class ContinuationRecordBuilder; + +class GlobalTypeTableBuilder : public TypeCollection { + /// Storage for records. These need to outlive the TypeTableBuilder. + BumpPtrAllocator &RecordStorage; + + /// A serializer that can write non-continuation leaf types. Only used as + /// a convenience function so that we can provide an interface method to + /// write an unserialized record. + SimpleTypeSerializer SimpleSerializer; + + /// Hash table. + DenseMap<GloballyHashedType, TypeIndex> HashedRecords; + + /// Contains a list of all records indexed by TypeIndex.toArrayIndex(). + SmallVector<ArrayRef<uint8_t>, 2> SeenRecords; + + /// Contains a list of all hash values inexed by TypeIndex.toArrayIndex(). + SmallVector<GloballyHashedType, 2> SeenHashes; + +public: + explicit GlobalTypeTableBuilder(BumpPtrAllocator &Storage); + ~GlobalTypeTableBuilder(); + + // TypeTableCollection overrides + Optional<TypeIndex> getFirst() override; + Optional<TypeIndex> getNext(TypeIndex Prev) override; + CVType getType(TypeIndex Index) override; + StringRef getTypeName(TypeIndex Index) override; + bool contains(TypeIndex Index) override; + uint32_t size() override; + uint32_t capacity() override; + + // public interface + void reset(); + TypeIndex nextTypeIndex() const; + + BumpPtrAllocator &getAllocator() { return RecordStorage; } + + ArrayRef<ArrayRef<uint8_t>> records() const; + ArrayRef<GloballyHashedType> hashes() const; + + template <typename CreateFunc> + TypeIndex insertRecordAs(GloballyHashedType Hash, size_t RecordSize, + CreateFunc Create) { + auto Result = HashedRecords.try_emplace(Hash, nextTypeIndex()); + + if (LLVM_UNLIKELY(Result.second /*inserted*/ || + Result.first->second.isSimple())) { + uint8_t *Stable = RecordStorage.Allocate<uint8_t>(RecordSize); + MutableArrayRef<uint8_t> Data(Stable, RecordSize); + ArrayRef<uint8_t> StableRecord = Create(Data); + if (StableRecord.empty()) { + // Records with forward references into the Type stream will be deferred + // for insertion at a later time, on the second pass. + Result.first->getSecond() = TypeIndex(SimpleTypeKind::NotTranslated); + return TypeIndex(SimpleTypeKind::NotTranslated); + } + if (Result.first->second.isSimple()) { + assert(Result.first->second.getIndex() == + (uint32_t)SimpleTypeKind::NotTranslated); + // On the second pass, update with index to remapped record. The + // (initially misbehaved) record will now come *after* other records + // resolved in the first pass, with proper *back* references in the + // stream. + Result.first->second = nextTypeIndex(); + } + SeenRecords.push_back(StableRecord); + SeenHashes.push_back(Hash); + } + + return Result.first->second; + } + + TypeIndex insertRecordBytes(ArrayRef<uint8_t> Data); + TypeIndex insertRecord(ContinuationRecordBuilder &Builder); + + template <typename T> TypeIndex writeLeafType(T &Record) { + ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record); + return insertRecordBytes(Data); + } +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h new file mode 100644 index 00000000..4e03627e --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h @@ -0,0 +1,115 @@ +//===- LazyRandomTypeCollection.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/StringSaver.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace codeview { + +/// Provides amortized O(1) random access to a CodeView type stream. +/// Normally to access a type from a type stream, you must know its byte +/// offset into the type stream, because type records are variable-lengthed. +/// However, this is not the way we prefer to access them. For example, given +/// a symbol record one of the fields may be the TypeIndex of the symbol's +/// type record. Or given a type record such as an array type, there might +/// be a TypeIndex for the element type. Sequential access is perfect when +/// we're just dumping every entry, but it's very poor for real world usage. +/// +/// Type streams in PDBs contain an additional field which is a list of pairs +/// containing indices and their corresponding offsets, roughly every ~8KB of +/// record data. This general idea need not be confined to PDBs though. By +/// supplying such an array, the producer of a type stream can allow the +/// consumer much better access time, because the consumer can find the nearest +/// index in this array, and do a linear scan forward only from there. +/// +/// LazyRandomTypeCollection implements this algorithm, but additionally goes +/// one step further by caching offsets of every record that has been visited at +/// least once. This way, even repeated visits of the same record will never +/// require more than one linear scan. For a type stream of N elements divided +/// into M chunks of roughly equal size, this yields a worst case lookup time +/// of O(N/M) and an amortized time of O(1). +class LazyRandomTypeCollection : public TypeCollection { + using PartialOffsetArray = FixedStreamArray<TypeIndexOffset>; + + struct CacheEntry { + CVType Type; + uint32_t Offset; + StringRef Name; + }; + +public: + explicit LazyRandomTypeCollection(uint32_t RecordCountHint); + LazyRandomTypeCollection(StringRef Data, uint32_t RecordCountHint); + LazyRandomTypeCollection(ArrayRef<uint8_t> Data, uint32_t RecordCountHint); + LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint, + PartialOffsetArray PartialOffsets); + LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint); + + void reset(ArrayRef<uint8_t> Data, uint32_t RecordCountHint); + void reset(StringRef Data, uint32_t RecordCountHint); + void reset(BinaryStreamReader &Reader, uint32_t RecordCountHint); + + uint32_t getOffsetOfType(TypeIndex Index); + + Optional<CVType> tryGetType(TypeIndex Index); + + CVType getType(TypeIndex Index) override; + StringRef getTypeName(TypeIndex Index) override; + bool contains(TypeIndex Index) override; + uint32_t size() override; + uint32_t capacity() override; + Optional<TypeIndex> getFirst() override; + Optional<TypeIndex> getNext(TypeIndex Prev) override; + +private: + Error ensureTypeExists(TypeIndex Index); + void ensureCapacityFor(TypeIndex Index); + + Error visitRangeForType(TypeIndex TI); + Error fullScanForType(TypeIndex TI); + void visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End); + + /// Number of actual records. + uint32_t Count = 0; + + /// The largest type index which we've visited. + TypeIndex LargestTypeIndex = TypeIndex::None(); + + BumpPtrAllocator Allocator; + StringSaver NameStorage; + + /// The type array to allow random access visitation of. + CVTypeArray Types; + + std::vector<CacheEntry> Records; + + /// An array of index offsets for the given type stream, allowing log(N) + /// lookups of a type record by index. Similar to KnownOffsets but only + /// contains offsets for some type indices, some of which may not have + /// ever been visited. + PartialOffsetArray PartialOffsets; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/Line.h b/clang-r353983/include/llvm/DebugInfo/CodeView/Line.h new file mode 100644 index 00000000..eb2aa154 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/Line.h @@ -0,0 +1,132 @@ +//===- Line.h ---------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_LINE_H +#define LLVM_DEBUGINFO_CODEVIEW_LINE_H + +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/Endian.h" +#include <cinttypes> + +namespace llvm { +namespace codeview { + +using llvm::support::ulittle32_t; + +class LineInfo { +public: + enum : uint32_t { + AlwaysStepIntoLineNumber = 0xfeefee, + NeverStepIntoLineNumber = 0xf00f00 + }; + + enum : int { EndLineDeltaShift = 24 }; + + enum : uint32_t { + StartLineMask = 0x00ffffff, + EndLineDeltaMask = 0x7f000000, + StatementFlag = 0x80000000u + }; + + LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement); + LineInfo(uint32_t LineData) : LineData(LineData) {} + + uint32_t getStartLine() const { return LineData & StartLineMask; } + + uint32_t getLineDelta() const { + return (LineData & EndLineDeltaMask) >> EndLineDeltaShift; + } + + uint32_t getEndLine() const { return getStartLine() + getLineDelta(); } + + bool isStatement() const { return (LineData & StatementFlag) != 0; } + + uint32_t getRawData() const { return LineData; } + + bool isAlwaysStepInto() const { + return getStartLine() == AlwaysStepIntoLineNumber; + } + + bool isNeverStepInto() const { + return getStartLine() == NeverStepIntoLineNumber; + } + +private: + uint32_t LineData; +}; + +class ColumnInfo { +private: + static const uint32_t StartColumnMask = 0x0000ffffu; + static const uint32_t EndColumnMask = 0xffff0000u; + static const int EndColumnShift = 16; + +public: + ColumnInfo(uint16_t StartColumn, uint16_t EndColumn) { + ColumnData = + (static_cast<uint32_t>(StartColumn) & StartColumnMask) | + ((static_cast<uint32_t>(EndColumn) << EndColumnShift) & EndColumnMask); + } + + uint16_t getStartColumn() const { + return static_cast<uint16_t>(ColumnData & StartColumnMask); + } + + uint16_t getEndColumn() const { + return static_cast<uint16_t>((ColumnData & EndColumnMask) >> + EndColumnShift); + } + + uint32_t getRawData() const { return ColumnData; } + +private: + uint32_t ColumnData; +}; + +class Line { +private: + int32_t CodeOffset; + LineInfo LineInf; + ColumnInfo ColumnInf; + +public: + Line(int32_t CodeOffset, uint32_t StartLine, uint32_t EndLine, + uint16_t StartColumn, uint16_t EndColumn, bool IsStatement) + : CodeOffset(CodeOffset), LineInf(StartLine, EndLine, IsStatement), + ColumnInf(StartColumn, EndColumn) {} + + Line(int32_t CodeOffset, LineInfo LineInf, ColumnInfo ColumnInf) + : CodeOffset(CodeOffset), LineInf(LineInf), ColumnInf(ColumnInf) {} + + LineInfo getLineInfo() const { return LineInf; } + + ColumnInfo getColumnInfo() const { return ColumnInf; } + + int32_t getCodeOffset() const { return CodeOffset; } + + uint32_t getStartLine() const { return LineInf.getStartLine(); } + + uint32_t getLineDelta() const { return LineInf.getLineDelta(); } + + uint32_t getEndLine() const { return LineInf.getEndLine(); } + + uint16_t getStartColumn() const { return ColumnInf.getStartColumn(); } + + uint16_t getEndColumn() const { return ColumnInf.getEndColumn(); } + + bool isStatement() const { return LineInf.isStatement(); } + + bool isAlwaysStepInto() const { return LineInf.isAlwaysStepInto(); } + + bool isNeverStepInto() const { return LineInf.isNeverStepInto(); } +}; + +} // namespace codeview +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h b/clang-r353983/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h new file mode 100644 index 00000000..1b2f6d29 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h @@ -0,0 +1,80 @@ +//===- MergingTypeTableBuilder.h ---------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H +#define LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h" +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeHashing.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/Allocator.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <vector> + +namespace llvm { +namespace codeview { + +class ContinuationRecordBuilder; + +class MergingTypeTableBuilder : public TypeCollection { + /// Storage for records. These need to outlive the TypeTableBuilder. + BumpPtrAllocator &RecordStorage; + + /// A serializer that can write non-continuation leaf types. Only used as + /// a convenience function so that we can provide an interface method to + /// write an unserialized record. + SimpleTypeSerializer SimpleSerializer; + + /// Hash table. + DenseMap<LocallyHashedType, TypeIndex> HashedRecords; + + /// Contains a list of all records indexed by TypeIndex.toArrayIndex(). + SmallVector<ArrayRef<uint8_t>, 2> SeenRecords; + +public: + explicit MergingTypeTableBuilder(BumpPtrAllocator &Storage); + ~MergingTypeTableBuilder(); + + // TypeTableCollection overrides + Optional<TypeIndex> getFirst() override; + Optional<TypeIndex> getNext(TypeIndex Prev) override; + CVType getType(TypeIndex Index) override; + StringRef getTypeName(TypeIndex Index) override; + bool contains(TypeIndex Index) override; + uint32_t size() override; + uint32_t capacity() override; + + // public interface + void reset(); + TypeIndex nextTypeIndex() const; + + BumpPtrAllocator &getAllocator() { return RecordStorage; } + + ArrayRef<ArrayRef<uint8_t>> records() const; + + TypeIndex insertRecordAs(hash_code Hash, ArrayRef<uint8_t> &Record); + TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record); + TypeIndex insertRecord(ContinuationRecordBuilder &Builder); + + template <typename T> TypeIndex writeLeafType(T &Record) { + ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record); + return insertRecordBytes(Data); + } +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/RecordName.h b/clang-r353983/include/llvm/DebugInfo/CodeView/RecordName.h new file mode 100644 index 00000000..cc09db89 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/RecordName.h @@ -0,0 +1,23 @@ +//===- RecordName.h ------------------------------------------- *- C++ --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H +#define LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" + +namespace llvm { +namespace codeview { +std::string computeTypeName(TypeCollection &Types, TypeIndex Index); +StringRef getSymbolName(CVSymbol Sym); +} // namespace codeview +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/RecordSerialization.h b/clang-r353983/include/llvm/DebugInfo/CodeView/RecordSerialization.h new file mode 100644 index 00000000..618146ce --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/RecordSerialization.h @@ -0,0 +1,227 @@ +//===- RecordSerialization.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDSERIALIZATION_H +#define LLVM_DEBUGINFO_CODEVIEW_RECORDSERIALIZATION_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cinttypes> +#include <tuple> + +namespace llvm { +namespace codeview { +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 &RecordKind. + ulittle16_t RecordKind; // Record kind enum (SymRecordKind or TypeRecordKind) +}; + +/// Reinterpret a byte array as an array of characters. Does not interpret as +/// a C string, as StringRef has several helpers (split) that make that easy. +StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData); +StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData); + +inline Error consume(BinaryStreamReader &Reader) { return Error::success(); } + +/// Decodes a numeric "leaf" value. These are integer literals encountered in +/// the type stream. If the value is positive and less than LF_NUMERIC (1 << +/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR +/// that indicates the bitwidth and sign of the numeric data. +Error consume(BinaryStreamReader &Reader, APSInt &Num); + +/// Decodes a numeric leaf value that is known to be a particular type. +Error consume_numeric(BinaryStreamReader &Reader, uint64_t &Value); + +/// Decodes signed and unsigned fixed-length integers. +Error consume(BinaryStreamReader &Reader, uint32_t &Item); +Error consume(BinaryStreamReader &Reader, int32_t &Item); + +/// Decodes a null terminated string. +Error consume(BinaryStreamReader &Reader, StringRef &Item); + +Error consume(StringRef &Data, APSInt &Num); +Error consume(StringRef &Data, uint32_t &Item); + +/// Decodes an arbitrary object whose layout matches that of the underlying +/// byte sequence, and returns a pointer to the object. +template <typename T> Error consume(BinaryStreamReader &Reader, T *&Item) { + return Reader.readObject(Item); +} + +template <typename T, typename U> struct serialize_conditional_impl { + serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {} + + Error deserialize(BinaryStreamReader &Reader) const { + if (!Func()) + return Error::success(); + return consume(Reader, Item); + } + + T &Item; + U Func; +}; + +template <typename T, typename U> +serialize_conditional_impl<T, U> serialize_conditional(T &Item, U Func) { + return serialize_conditional_impl<T, U>(Item, Func); +} + +template <typename T, typename U> struct serialize_array_impl { + serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {} + + Error deserialize(BinaryStreamReader &Reader) const { + return Reader.readArray(Item, Func()); + } + + ArrayRef<T> &Item; + U Func; +}; + +template <typename T> struct serialize_vector_tail_impl { + serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {} + + Error deserialize(BinaryStreamReader &Reader) const { + T Field; + // Stop when we run out of bytes or we hit record padding bytes. + while (!Reader.empty() && Reader.peek() < LF_PAD0) { + if (auto EC = consume(Reader, Field)) + return EC; + Item.push_back(Field); + } + return Error::success(); + } + + std::vector<T> &Item; +}; + +struct serialize_null_term_string_array_impl { + serialize_null_term_string_array_impl(std::vector<StringRef> &Item) + : Item(Item) {} + + Error deserialize(BinaryStreamReader &Reader) const { + if (Reader.empty()) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer, + "Null terminated string is empty!"); + + while (Reader.peek() != 0) { + StringRef Field; + if (auto EC = Reader.readCString(Field)) + return EC; + Item.push_back(Field); + } + return Reader.skip(1); + } + + std::vector<StringRef> &Item; +}; + +template <typename T> struct serialize_arrayref_tail_impl { + serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {} + + Error deserialize(BinaryStreamReader &Reader) const { + uint32_t Count = Reader.bytesRemaining() / sizeof(T); + return Reader.readArray(Item, Count); + } + + ArrayRef<T> &Item; +}; + +template <typename T> struct serialize_numeric_impl { + serialize_numeric_impl(T &Item) : Item(Item) {} + + Error deserialize(BinaryStreamReader &Reader) const { + return consume_numeric(Reader, Item); + } + + T &Item; +}; + +template <typename T, typename U> +serialize_array_impl<T, U> serialize_array(ArrayRef<T> &Item, U Func) { + return serialize_array_impl<T, U>(Item, Func); +} + +inline serialize_null_term_string_array_impl +serialize_null_term_string_array(std::vector<StringRef> &Item) { + return serialize_null_term_string_array_impl(Item); +} + +template <typename T> +serialize_vector_tail_impl<T> serialize_array_tail(std::vector<T> &Item) { + return serialize_vector_tail_impl<T>(Item); +} + +template <typename T> +serialize_arrayref_tail_impl<T> serialize_array_tail(ArrayRef<T> &Item) { + return serialize_arrayref_tail_impl<T>(Item); +} + +template <typename T> serialize_numeric_impl<T> serialize_numeric(T &Item) { + return serialize_numeric_impl<T>(Item); +} + +template <typename T, typename U> +Error consume(BinaryStreamReader &Reader, + const serialize_conditional_impl<T, U> &Item) { + return Item.deserialize(Reader); +} + +template <typename T, typename U> +Error consume(BinaryStreamReader &Reader, + const serialize_array_impl<T, U> &Item) { + return Item.deserialize(Reader); +} + +inline Error consume(BinaryStreamReader &Reader, + const serialize_null_term_string_array_impl &Item) { + return Item.deserialize(Reader); +} + +template <typename T> +Error consume(BinaryStreamReader &Reader, + const serialize_vector_tail_impl<T> &Item) { + return Item.deserialize(Reader); +} + +template <typename T> +Error consume(BinaryStreamReader &Reader, + const serialize_arrayref_tail_impl<T> &Item) { + return Item.deserialize(Reader); +} + +template <typename T> +Error consume(BinaryStreamReader &Reader, + const serialize_numeric_impl<T> &Item) { + return Item.deserialize(Reader); +} + +template <typename T, typename U, typename... Args> +Error consume(BinaryStreamReader &Reader, T &&X, U &&Y, Args &&... Rest) { + if (auto EC = consume(Reader, X)) + return EC; + return consume(Reader, Y, std::forward<Args>(Rest)...); +} + +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h new file mode 100644 index 00000000..3ca09b44 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h @@ -0,0 +1,52 @@ +//===- SimpleTypeSerializer.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SIMPLETYPESERIALIZER_H +#define LLVM_DEBUGINFO_CODEVIEW_SIMPLETYPESERIALIZER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Error.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <vector> + +namespace llvm { +namespace codeview { + +class SimpleTypeSerializer { + std::vector<uint8_t> ScratchBuffer; + +public: + SimpleTypeSerializer(); + ~SimpleTypeSerializer(); + + // This template is explicitly instantiated in the implementation file for all + // supported types. The method itself is ugly, so inlining it into the header + // file clutters an otherwise straightforward interface. + template <typename T> ArrayRef<uint8_t> serialize(T &Record); + + // Don't allow serialization of field list records using this interface. + ArrayRef<uint8_t> serialize(const FieldListRecord &Record) = delete; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SIMPLETYPESERIALIZER_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h b/clang-r353983/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h new file mode 100644 index 00000000..22a283e7 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h @@ -0,0 +1,106 @@ +//===- StringsAndChecksums.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_STRINGSANDCHECKSUMS_H +#define LLVM_DEBUGINFO_CODEVIEW_STRINGSANDCHECKSUMS_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include <memory> + +namespace llvm { +namespace codeview { + +class StringsAndChecksumsRef { +public: + // If no subsections are known about initially, we find as much as we can. + StringsAndChecksumsRef(); + + // If only a string table subsection is given, we find a checksums subsection. + explicit StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings); + + // If both subsections are given, we don't need to find anything. + StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums); + + void setStrings(const DebugStringTableSubsectionRef &Strings); + void setChecksums(const DebugChecksumsSubsectionRef &CS); + + void reset(); + void resetStrings(); + void resetChecksums(); + + template <typename T> void initialize(T &&FragmentRange) { + for (const DebugSubsectionRecord &R : FragmentRange) { + if (Strings && Checksums) + return; + if (R.kind() == DebugSubsectionKind::FileChecksums) { + initializeChecksums(R); + continue; + } + if (R.kind() == DebugSubsectionKind::StringTable && !Strings) { + // While in practice we should never encounter a string table even + // though the string table is already initialized, in theory it's + // possible. PDBs are supposed to have one global string table and + // then this subsection should not appear. Whereas object files are + // supposed to have this subsection appear exactly once. However, + // for testing purposes it's nice to be able to test this subsection + // independently of one format or the other, so for some tests we + // manually construct a PDB that contains this subsection in addition + // to a global string table. + initializeStrings(R); + continue; + } + } + } + + const DebugStringTableSubsectionRef &strings() const { return *Strings; } + const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; } + + bool hasStrings() const { return Strings != nullptr; } + bool hasChecksums() const { return Checksums != nullptr; } + +private: + void initializeStrings(const DebugSubsectionRecord &SR); + void initializeChecksums(const DebugSubsectionRecord &FCR); + + std::shared_ptr<DebugStringTableSubsectionRef> OwnedStrings; + std::shared_ptr<DebugChecksumsSubsectionRef> OwnedChecksums; + + const DebugStringTableSubsectionRef *Strings = nullptr; + const DebugChecksumsSubsectionRef *Checksums = nullptr; +}; + +class StringsAndChecksums { +public: + using StringsPtr = std::shared_ptr<DebugStringTableSubsection>; + using ChecksumsPtr = std::shared_ptr<DebugChecksumsSubsection>; + + // If no subsections are known about initially, we find as much as we can. + StringsAndChecksums() = default; + + void setStrings(const StringsPtr &SP) { Strings = SP; } + void setChecksums(const ChecksumsPtr &CP) { Checksums = CP; } + + const StringsPtr &strings() const { return Strings; } + const ChecksumsPtr &checksums() const { return Checksums; } + + bool hasStrings() const { return Strings != nullptr; } + bool hasChecksums() const { return Checksums != nullptr; } + +private: + StringsPtr Strings; + ChecksumsPtr Checksums; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_STRINGSANDCHECKSUMS_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h new file mode 100644 index 00000000..62761cb8 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h @@ -0,0 +1,99 @@ +//===- SymbolDeserializer.h -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class SymbolVisitorDelegate; +class SymbolDeserializer : public SymbolVisitorCallbacks { + struct MappingInfo { + MappingInfo(ArrayRef<uint8_t> RecordData, CodeViewContainer Container) + : Stream(RecordData, llvm::support::little), Reader(Stream), + Mapping(Reader, Container) {} + + BinaryByteStream Stream; + BinaryStreamReader Reader; + SymbolRecordMapping Mapping; + }; + +public: + template <typename T> static Error deserializeAs(CVSymbol Symbol, T &Record) { + // If we're just deserializing one record, then don't worry about alignment + // as there's nothing that comes after. + SymbolDeserializer S(nullptr, CodeViewContainer::ObjectFile); + if (auto EC = S.visitSymbolBegin(Symbol)) + return EC; + if (auto EC = S.visitKnownRecord(Symbol, Record)) + return EC; + if (auto EC = S.visitSymbolEnd(Symbol)) + return EC; + return Error::success(); + } + template <typename T> static Expected<T> deserializeAs(CVSymbol Symbol) { + T Record(static_cast<SymbolRecordKind>(Symbol.kind())); + if (auto EC = deserializeAs<T>(Symbol, Record)) + return std::move(EC); + return Record; + } + + explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate, + CodeViewContainer Container) + : Delegate(Delegate), Container(Container) {} + + Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override { + return visitSymbolBegin(Record); + } + + Error visitSymbolBegin(CVSymbol &Record) override { + assert(!Mapping && "Already in a symbol mapping!"); + Mapping = llvm::make_unique<MappingInfo>(Record.content(), Container); + 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 "llvm/DebugInfo/CodeView/CodeViewSymbols.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; + CodeViewContainer Container; + std::unique_ptr<MappingInfo> Mapping; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h new file mode 100644 index 00000000..12f45dcb --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h @@ -0,0 +1,34 @@ +//===-- SymbolDumpDelegate.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h" +#include <cstdint> + +namespace llvm { +namespace codeview { + +class SymbolDumpDelegate : public SymbolVisitorDelegate { +public: + ~SymbolDumpDelegate() override = default; + + virtual void printRelocatedField(StringRef Label, uint32_t RelocOffset, + uint32_t Offset, + StringRef *RelocSym = nullptr) = 0; + virtual void printBinaryBlockWithRelocs(StringRef Label, + ArrayRef<uint8_t> Block) = 0; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolDumper.h new file mode 100644 index 00000000..d832a48b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -0,0 +1,58 @@ +//===-- SymbolDumper.h - CodeView symbol info dumper ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" + +namespace llvm { +class ScopedPrinter; + +namespace codeview { +class TypeCollection; + +/// Dumper for CodeView symbol streams found in COFF object files and PDB files. +class CVSymbolDumper { +public: + CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types, + CodeViewContainer Container, + std::unique_ptr<SymbolDumpDelegate> ObjDelegate, CPUType CPU, + bool PrintRecordBytes) + : W(W), Types(Types), Container(Container), + ObjDelegate(std::move(ObjDelegate)), CompilationCPUType(CPU), + 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. + Error dump(CVRecord<SymbolKind> &Record); + + /// Dumps the type records in Data. Returns false if there was a type stream + /// parse error, and true otherwise. + Error dump(const CVSymbolArray &Symbols); + + CPUType getCompilationCPUType() const { return CompilationCPUType; } + +private: + ScopedPrinter &W; + TypeCollection &Types; + CodeViewContainer Container; + std::unique_ptr<SymbolDumpDelegate> ObjDelegate; + CPUType CompilationCPUType; + bool PrintRecordBytes; +}; +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecord.h new file mode 100644 index 00000000..ac7b106e --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -0,0 +1,995 @@ +//===- SymbolRecord.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/Endian.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace codeview { + +class SymbolRecord { +protected: + explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {} + +public: + SymbolRecordKind getKind() const { return Kind; } + + SymbolRecordKind Kind; +}; + +// S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or +// S_LPROC32_DPC_ID +class ProcSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 32; + +public: + explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { + 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: + explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} + + 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: + explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} + + TrampolineType Type; + uint16_t Size; + uint32_t ThunkOffset; + uint32_t TargetOffset; + uint16_t ThunkSection; + uint16_t TargetSection; + + uint32_t RecordOffset; +}; + +// S_SECTION +class SectionSym : public SymbolRecord { +public: + explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} + + uint16_t SectionNumber; + uint8_t Alignment; + uint32_t Rva; + uint32_t Length; + uint32_t Characteristics; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_COFFGROUP +class CoffGroupSym : public SymbolRecord { +public: + explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} + + uint32_t Size; + uint32_t Characteristics; + uint32_t Offset; + uint16_t Segment; + StringRef Name; + + uint32_t RecordOffset; +}; + +class ScopeEndSym : public SymbolRecord { +public: + explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} + + uint32_t RecordOffset; +}; + +class CallerSym : public SymbolRecord { +public: + explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} + + std::vector<TypeIndex> Indices; + + uint32_t RecordOffset; +}; + +struct BinaryAnnotationIterator { + struct AnnotationData { + BinaryAnnotationsOpCode OpCode; + StringRef Name; + uint32_t U1; + uint32_t U2; + int32_t S1; + }; + + BinaryAnnotationIterator() = default; + BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {} + BinaryAnnotationIterator(const BinaryAnnotationIterator &Other) + : Data(Other.Data) {} + + bool operator==(BinaryAnnotationIterator Other) const { + return Data == Other.Data; + } + + bool operator!=(const BinaryAnnotationIterator &Other) const { + return !(*this == Other); + } + + BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) { + Data = Other.Data; + return *this; + } + + BinaryAnnotationIterator &operator++() { + if (!ParseCurrentAnnotation()) { + *this = BinaryAnnotationIterator(); + return *this; + } + Data = Next; + Next = ArrayRef<uint8_t>(); + Current.reset(); + return *this; + } + + BinaryAnnotationIterator operator++(int) { + BinaryAnnotationIterator Orig(*this); + ++(*this); + return Orig; + } + + const AnnotationData &operator*() { + ParseCurrentAnnotation(); + return Current.getValue(); + } + +private: + static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) { + if (Annotations.empty()) + return -1; + + uint8_t FirstByte = Annotations.front(); + Annotations = Annotations.drop_front(); + + if ((FirstByte & 0x80) == 0x00) + return FirstByte; + + if (Annotations.empty()) + return -1; + + uint8_t SecondByte = Annotations.front(); + Annotations = Annotations.drop_front(); + + if ((FirstByte & 0xC0) == 0x80) + return ((FirstByte & 0x3F) << 8) | SecondByte; + + if (Annotations.empty()) + return -1; + + uint8_t ThirdByte = Annotations.front(); + Annotations = Annotations.drop_front(); + + if (Annotations.empty()) + return -1; + + uint8_t FourthByte = Annotations.front(); + Annotations = Annotations.drop_front(); + + if ((FirstByte & 0xE0) == 0xC0) + return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) | + (ThirdByte << 8) | FourthByte; + + return -1; + }; + + static int32_t DecodeSignedOperand(uint32_t Operand) { + if (Operand & 1) + return -(Operand >> 1); + return Operand >> 1; + }; + + static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) { + return DecodeSignedOperand(GetCompressedAnnotation(Annotations)); + }; + + bool ParseCurrentAnnotation() { + if (Current.hasValue()) + return true; + + Next = Data; + uint32_t Op = GetCompressedAnnotation(Next); + AnnotationData Result; + Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op); + switch (Result.OpCode) { + case BinaryAnnotationsOpCode::Invalid: + Result.Name = "Invalid"; + Next = ArrayRef<uint8_t>(); + break; + case BinaryAnnotationsOpCode::CodeOffset: + Result.Name = "CodeOffset"; + Result.U1 = GetCompressedAnnotation(Next); + break; + case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: + Result.Name = "ChangeCodeOffsetBase"; + Result.U1 = GetCompressedAnnotation(Next); + break; + case BinaryAnnotationsOpCode::ChangeCodeOffset: + Result.Name = "ChangeCodeOffset"; + Result.U1 = GetCompressedAnnotation(Next); + break; + case BinaryAnnotationsOpCode::ChangeCodeLength: + Result.Name = "ChangeCodeLength"; + Result.U1 = GetCompressedAnnotation(Next); + break; + case BinaryAnnotationsOpCode::ChangeFile: + Result.Name = "ChangeFile"; + Result.U1 = GetCompressedAnnotation(Next); + break; + case BinaryAnnotationsOpCode::ChangeLineEndDelta: + Result.Name = "ChangeLineEndDelta"; + Result.U1 = GetCompressedAnnotation(Next); + break; + case BinaryAnnotationsOpCode::ChangeRangeKind: + Result.Name = "ChangeRangeKind"; + Result.U1 = GetCompressedAnnotation(Next); + break; + case BinaryAnnotationsOpCode::ChangeColumnStart: + Result.Name = "ChangeColumnStart"; + Result.U1 = GetCompressedAnnotation(Next); + break; + case BinaryAnnotationsOpCode::ChangeColumnEnd: + Result.Name = "ChangeColumnEnd"; + Result.U1 = GetCompressedAnnotation(Next); + break; + case BinaryAnnotationsOpCode::ChangeLineOffset: + Result.Name = "ChangeLineOffset"; + Result.S1 = DecodeSignedOperand(Next); + break; + case BinaryAnnotationsOpCode::ChangeColumnEndDelta: + Result.Name = "ChangeColumnEndDelta"; + Result.S1 = DecodeSignedOperand(Next); + break; + case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: { + Result.Name = "ChangeCodeOffsetAndLineOffset"; + uint32_t Annotation = GetCompressedAnnotation(Next); + Result.S1 = DecodeSignedOperand(Annotation >> 4); + Result.U1 = Annotation & 0xf; + break; + } + case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: { + Result.Name = "ChangeCodeLengthAndCodeOffset"; + Result.U1 = GetCompressedAnnotation(Next); + Result.U2 = GetCompressedAnnotation(Next); + break; + } + } + Current = Result; + return true; + } + + Optional<AnnotationData> Current; + ArrayRef<uint8_t> Data; + ArrayRef<uint8_t> Next; +}; + +// S_INLINESITE +class InlineSiteSym : public SymbolRecord { +public: + explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + InlineSiteSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::InlineSiteSym), + RecordOffset(RecordOffset) {} + + iterator_range<BinaryAnnotationIterator> annotations() const { + return make_range(BinaryAnnotationIterator(AnnotationData), + BinaryAnnotationIterator()); + } + + uint32_t Parent; + uint32_t End; + TypeIndex Inlinee; + std::vector<uint8_t> AnnotationData; + + uint32_t RecordOffset; +}; + +// S_PUB32 +class PublicSym32 : public SymbolRecord { +public: + PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {} + explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit PublicSym32(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::PublicSym32), + RecordOffset(RecordOffset) {} + + PublicSymFlags Flags = PublicSymFlags::None; + uint32_t Offset = 0; + uint16_t Segment = 0; + StringRef Name; + + uint32_t RecordOffset = 0; +}; + +// S_REGISTER +class RegisterSym : public SymbolRecord { +public: + explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + RegisterSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::RegisterSym), + RecordOffset(RecordOffset) {} + + TypeIndex Index; + RegisterId Register; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_PROCREF, S_LPROCREF +class ProcRefSym : public SymbolRecord { +public: + explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit ProcRefSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) { + } + + uint32_t SumName; + uint32_t SymOffset; + uint16_t Module; + StringRef Name; + + uint16_t modi() const { return Module - 1; } + uint32_t RecordOffset; +}; + +// S_LOCAL +class LocalSym : public SymbolRecord { +public: + explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit LocalSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {} + + TypeIndex Type; + LocalSymFlags Flags; + StringRef Name; + + uint32_t RecordOffset; +}; + +struct LocalVariableAddrRange { + uint32_t OffsetStart; + uint16_t ISectStart; + uint16_t Range; +}; + +struct LocalVariableAddrGap { + uint16_t GapStartOffset; + uint16_t Range; +}; + +enum : uint16_t { MaxDefRange = 0xf000 }; + +// S_DEFRANGE +class DefRangeSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 8; + +public: + explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit DefRangeSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DefRangeSym), + RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + uint32_t Program; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; + + uint32_t RecordOffset; +}; + +// S_DEFRANGE_SUBFIELD +class DefRangeSubfieldSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 12; + +public: + explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + DefRangeSubfieldSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym), + RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + uint32_t Program; + uint16_t OffsetInParent; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; + + uint32_t RecordOffset; +}; + +// S_DEFRANGE_REGISTER +class DefRangeRegisterSym : public SymbolRecord { +public: + struct Header { + ulittle16_t Register; + ulittle16_t MayHaveNoName; + }; + + explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + DefRangeRegisterSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), + RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } + + Header Hdr; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; + + uint32_t RecordOffset; +}; + +// S_DEFRANGE_SUBFIELD_REGISTER +class DefRangeSubfieldRegisterSym : public SymbolRecord { +public: + struct Header { + ulittle16_t Register; + ulittle16_t MayHaveNoName; + ulittle32_t OffsetInParent; + }; + + explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind) + : SymbolRecord(Kind) {} + DefRangeSubfieldRegisterSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym), + RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } + + Header Hdr; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; + + uint32_t RecordOffset; +}; + +// S_DEFRANGE_FRAMEPOINTER_REL +class DefRangeFramePointerRelSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 8; + +public: + explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind) + : SymbolRecord(Kind) {} + DefRangeFramePointerRelSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym), + RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + int32_t Offset; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; + + uint32_t RecordOffset; +}; + +// S_DEFRANGE_REGISTER_REL +class DefRangeRegisterRelSym : public SymbolRecord { +public: + struct Header { + ulittle16_t Register; + ulittle16_t Flags; + little32_t BasePointerOffset; + }; + + explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit DefRangeRegisterRelSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), + RecordOffset(RecordOffset) {} + + // 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, + }; + + bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; } + uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; } + + uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } + + Header Hdr; + LocalVariableAddrRange Range; + std::vector<LocalVariableAddrGap> Gaps; + + uint32_t RecordOffset; +}; + +// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE +class DefRangeFramePointerRelFullScopeSym : public SymbolRecord { +public: + explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind) + : SymbolRecord(Kind) {} + explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym), + RecordOffset(RecordOffset) {} + + int32_t Offset; + + uint32_t RecordOffset; +}; + +// S_BLOCK32 +class BlockSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 16; + +public: + explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit BlockSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + 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 { + static constexpr uint32_t RelocationOffset = 4; + +public: + explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit LabelSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + uint32_t CodeOffset; + uint16_t Segment; + ProcSymFlags Flags; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_OBJNAME +class ObjNameSym : public SymbolRecord { +public: + explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {} + explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + ObjNameSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) { + } + + uint32_t Signature; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_ENVBLOCK +class EnvBlockSym : public SymbolRecord { +public: + explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + EnvBlockSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::EnvBlockSym), + RecordOffset(RecordOffset) {} + + std::vector<StringRef> Fields; + + uint32_t RecordOffset; +}; + +// S_EXPORT +class ExportSym : public SymbolRecord { +public: + explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + ExportSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {} + + uint16_t Ordinal; + ExportFlags Flags; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_FILESTATIC +class FileStaticSym : public SymbolRecord { +public: + explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + FileStaticSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::FileStaticSym), + RecordOffset(RecordOffset) {} + + TypeIndex Index; + uint32_t ModFilenameOffset; + LocalSymFlags Flags; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_COMPILE2 +class Compile2Sym : public SymbolRecord { +public: + 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; + + 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; +}; + +// S_COMPILE3 +class Compile3Sym : public SymbolRecord { +public: + Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {} + 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; + + void setLanguage(SourceLanguage Lang) { + Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang)); + } + + SourceLanguage getLanguage() const { + return static_cast<SourceLanguage>(static_cast<uint32_t>(Flags) & 0xFF); + } + CompileSym3Flags getFlags() const { + return static_cast<CompileSym3Flags>(static_cast<uint32_t>(Flags) & ~0xFF); + } + + bool hasOptimizations() const { + return CompileSym3Flags::None != + (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG)); + } + + uint32_t RecordOffset; +}; + +// S_FRAMEPROC +class FrameProcSym : public SymbolRecord { +public: + explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit FrameProcSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::FrameProcSym), + RecordOffset(RecordOffset) {} + + uint32_t TotalFrameBytes; + uint32_t PaddingFrameBytes; + uint32_t OffsetToPadding; + uint32_t BytesOfCalleeSavedRegisters; + uint32_t OffsetOfExceptionHandler; + uint16_t SectionIdOfExceptionHandler; + FrameProcedureOptions Flags; + + /// Extract the register this frame uses to refer to local variables. + RegisterId getLocalFramePtrReg(CPUType CPU) const { + return decodeFramePtrReg( + EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU); + } + + /// Extract the register this frame uses to refer to parameters. + RegisterId getParamFramePtrReg(CPUType CPU) const { + return decodeFramePtrReg( + EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU); + } + + uint32_t RecordOffset; + +private: +}; + +// S_CALLSITEINFO +class CallSiteInfoSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 4; + +public: + explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit CallSiteInfoSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + uint32_t CodeOffset; + uint16_t Segment; + TypeIndex Type; + + uint32_t RecordOffset; +}; + +// S_HEAPALLOCSITE +class HeapAllocationSiteSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 4; + +public: + explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit HeapAllocationSiteSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym), + RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + uint32_t CodeOffset; + uint16_t Segment; + uint16_t CallInstructionSize; + TypeIndex Type; + + uint32_t RecordOffset; +}; + +// S_FRAMECOOKIE +class FrameCookieSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 4; + +public: + explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit FrameCookieSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::FrameCookieSym) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + uint32_t CodeOffset; + uint16_t Register; + FrameCookieKind CookieKind; + uint8_t Flags; + + uint32_t RecordOffset; +}; + +// S_UDT, S_COBOLUDT +class UDTSym : public SymbolRecord { +public: + explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit UDTSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::UDTSym) {} + + TypeIndex Type; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_BUILDINFO +class BuildInfoSym : public SymbolRecord { +public: + explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + BuildInfoSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::BuildInfoSym), + RecordOffset(RecordOffset) {} + + TypeIndex BuildId; + + uint32_t RecordOffset; +}; + +// S_BPREL32 +class BPRelativeSym : public SymbolRecord { +public: + explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit BPRelativeSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::BPRelativeSym), + RecordOffset(RecordOffset) {} + + int32_t Offset; + TypeIndex Type; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_REGREL32 +class RegRelativeSym : public SymbolRecord { +public: + explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit RegRelativeSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::RegRelativeSym), + RecordOffset(RecordOffset) {} + + uint32_t Offset; + TypeIndex Type; + RegisterId Register; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_CONSTANT, S_MANCONSTANT +class ConstantSym : public SymbolRecord { +public: + explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + ConstantSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::ConstantSym), + RecordOffset(RecordOffset) {} + + TypeIndex Type; + APSInt Value; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA +class DataSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 8; + +public: + explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + DataSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + TypeIndex Type; + uint32_t DataOffset; + uint16_t Segment; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_LTHREAD32, S_GTHREAD32 +class ThreadLocalDataSym : public SymbolRecord { + static constexpr uint32_t RelocationOffset = 8; + +public: + explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit ThreadLocalDataSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym), + RecordOffset(RecordOffset) {} + + uint32_t getRelocationOffset() const { + return RecordOffset + RelocationOffset; + } + + TypeIndex Type; + uint32_t DataOffset; + uint16_t Segment; + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_UNAMESPACE +class UsingNamespaceSym : public SymbolRecord { +public: + explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit UsingNamespaceSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::RegRelativeSym), + RecordOffset(RecordOffset) {} + + StringRef Name; + + uint32_t RecordOffset; +}; + +// S_ANNOTATION + +using CVSymbol = CVRecord<SymbolKind>; +using CVSymbolArray = VarStreamArray<CVSymbol>; + +Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream, + uint32_t Offset); + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h new file mode 100644 index 00000000..57dbc56c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h @@ -0,0 +1,61 @@ +//===- SymbolRecordHelpers.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORDHELPERS_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORDHELPERS_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" + +namespace llvm { +namespace codeview { +/// Return true if this symbol opens a scope. This implies that the symbol has +/// "parent" and "end" fields, which contain the offset of the S_END or +/// S_INLINESITE_END record. +inline bool symbolOpensScope(SymbolKind Kind) { + switch (Kind) { + case SymbolKind::S_GPROC32: + case SymbolKind::S_LPROC32: + case SymbolKind::S_LPROC32_ID: + case SymbolKind::S_GPROC32_ID: + case SymbolKind::S_BLOCK32: + case SymbolKind::S_SEPCODE: + case SymbolKind::S_THUNK32: + case SymbolKind::S_INLINESITE: + case SymbolKind::S_INLINESITE2: + return true; + default: + break; + } + return false; +} + +/// Return true if this ssymbol ends a scope. +inline bool symbolEndsScope(SymbolKind Kind) { + switch (Kind) { + case SymbolKind::S_END: + case SymbolKind::S_PROC_ID_END: + case SymbolKind::S_INLINESITE_END: + return true; + default: + break; + } + return false; +} + +/// Given a symbol P for which symbolOpensScope(P) == true, return the +/// corresponding end offset. +uint32_t getScopeEndOffset(const CVSymbol &Symbol); +uint32_t getScopeParentOffset(const CVSymbol &Symbol); + +CVSymbolArray limitSymbolArrayToScope(const CVSymbolArray &Symbols, + uint32_t ScopeBegin); + +} // namespace codeview +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h new file mode 100644 index 00000000..34368b61 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h @@ -0,0 +1,46 @@ +//===- SymbolRecordMapping.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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 { +class BinaryStreamReader; +class BinaryStreamWriter; + +namespace codeview { +class SymbolRecordMapping : public SymbolVisitorCallbacks { +public: + explicit SymbolRecordMapping(BinaryStreamReader &Reader, + CodeViewContainer Container) + : IO(Reader), Container(Container) {} + explicit SymbolRecordMapping(BinaryStreamWriter &Writer, + CodeViewContainer Container) + : IO(Writer), Container(Container) {} + + Error visitSymbolBegin(CVSymbol &Record) override; + Error visitSymbolEnd(CVSymbol &Record) override; + +#define SYMBOL_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVSymbol &CVR, Name &Record) override; +#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" + +private: + Optional<SymbolKind> Kind; + + CodeViewRecordIO IO; + CodeViewContainer Container; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolSerializer.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolSerializer.h new file mode 100644 index 00000000..08271c16 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolSerializer.h @@ -0,0 +1,83 @@ +//===- SymbolSerializer.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" +#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace codeview { + +class SymbolSerializer : public SymbolVisitorCallbacks { + BumpPtrAllocator &Storage; + // Since this is a fixed size buffer, use a stack allocated buffer. This + // yields measurable performance increase over the repeated heap allocations + // when serializing many independent records via writeOneSymbol. + std::array<uint8_t, MaxRecordLength> RecordBuffer; + MutableBinaryByteStream Stream; + BinaryStreamWriter 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: + SymbolSerializer(BumpPtrAllocator &Storage, CodeViewContainer Container); + + template <typename SymType> + static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage, + CodeViewContainer Container) { + CVSymbol Result; + Result.Type = static_cast<SymbolKind>(Sym.Kind); + SymbolSerializer Serializer(Storage, Container); + consumeError(Serializer.visitSymbolBegin(Result)); + consumeError(Serializer.visitKnownRecord(Result, Sym)); + consumeError(Serializer.visitSymbolEnd(Result)); + return Result; + } + + Error visitSymbolBegin(CVSymbol &Record) override; + Error visitSymbolEnd(CVSymbol &Record) override; + +#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 "llvm/DebugInfo/CodeView/CodeViewSymbols.def" + +private: + template <typename RecordKind> + Error visitKnownRecordImpl(CVSymbol &CVR, RecordKind &Record) { + return Mapping.visitKnownRecord(CVR, Record); + } +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h new file mode 100644 index 00000000..145d63a6 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h @@ -0,0 +1,78 @@ +//===- SymbolVisitorCallbackPipeline.h --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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, uint32_t Offset) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitSymbolBegin(Record, Offset)) + return EC; + } + return Error::success(); + } + + Error visitSymbolBegin(CVSymbol &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitSymbolBegin(Record)) + 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/CodeViewSymbols.def" + +private: + std::vector<SymbolVisitorCallbacks *> Pipeline; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKPIPELINE_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h new file mode 100644 index 00000000..1a4d5b9d --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h @@ -0,0 +1,49 @@ +//===- SymbolVisitorCallbacks.h ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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, uint32_t Offset) { + return Error::success(); + } + 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 "llvm/DebugInfo/CodeView/CodeViewSymbols.def" +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKS_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h new file mode 100644 index 00000000..368d8b28 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h @@ -0,0 +1,36 @@ +//===-- SymbolVisitorDelegate.h ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H + +#include "llvm/ADT/StringRef.h" +#include <cstdint> + +namespace llvm { + +class BinaryStreamReader; + +namespace codeview { + +class DebugStringTableSubsectionRef; + +class SymbolVisitorDelegate { +public: + virtual ~SymbolVisitorDelegate() = default; + + virtual uint32_t getRecordOffset(BinaryStreamReader Reader) = 0; + virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0; + virtual DebugStringTableSubsectionRef getStringTable() = 0; +}; + +} // end namespace codeview + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeCollection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeCollection.h new file mode 100644 index 00000000..58b1dd05 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeCollection.h @@ -0,0 +1,47 @@ +//===- TypeCollection.h - A collection of CodeView type records -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H + +#include "llvm/ADT/StringRef.h" + +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" + +namespace llvm { +namespace codeview { +class TypeCollection { +public: + virtual ~TypeCollection() = default; + + bool empty() { return size() == 0; } + + virtual Optional<TypeIndex> getFirst() = 0; + virtual Optional<TypeIndex> getNext(TypeIndex Prev) = 0; + + virtual CVType getType(TypeIndex Index) = 0; + virtual StringRef getTypeName(TypeIndex Index) = 0; + virtual bool contains(TypeIndex Index) = 0; + virtual uint32_t size() = 0; + virtual uint32_t capacity() = 0; + + template <typename TFunc> void ForEachRecord(TFunc Func) { + Optional<TypeIndex> Next = getFirst(); + + while (Next.hasValue()) { + TypeIndex N = *Next; + Func(N, getType(N)); + Next = getNext(N); + } + } +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeDeserializer.h new file mode 100644 index 00000000..d2ee3478 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeDeserializer.h @@ -0,0 +1,165 @@ +//===- TypeDeserializer.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamReader.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, llvm::support::little), Reader(Stream), + Mapping(Reader) {} + + BinaryByteStream Stream; + BinaryStreamReader Reader; + TypeRecordMapping Mapping; + }; + +public: + TypeDeserializer() = default; + + template <typename T> static Error deserializeAs(CVType &CVT, T &Record) { + Record.Kind = static_cast<TypeRecordKind>(CVT.kind()); + MappingInfo I(CVT.content()); + if (auto EC = I.Mapping.visitTypeBegin(CVT)) + return EC; + if (auto EC = I.Mapping.visitKnownRecord(CVT, Record)) + return EC; + if (auto EC = I.Mapping.visitTypeEnd(CVT)) + return EC; + return Error::success(); + } + + template <typename T> + static Expected<T> deserializeAs(ArrayRef<uint8_t> Data) { + const RecordPrefix *Prefix = + reinterpret_cast<const RecordPrefix *>(Data.data()); + TypeRecordKind K = + static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind)); + T Record(K); + CVType CVT(static_cast<TypeLeafKind>(K), Data); + if (auto EC = deserializeAs<T>(CVT, Record)) + return std::move(EC); + return Record; + } + + Error visitTypeBegin(CVType &Record) override { + assert(!Mapping && "Already in a type mapping!"); + Mapping = llvm::make_unique<MappingInfo>(Record.content()); + return Mapping->Mapping.visitTypeBegin(Record); + } + + Error visitTypeBegin(CVType &Record, TypeIndex Index) override { + return visitTypeBegin(Record); + } + + Error visitTypeEnd(CVType &Record) override { + assert(Mapping && "Not in a type mapping!"); + auto EC = Mapping->Mapping.visitTypeEnd(Record); + 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 "llvm/DebugInfo/CodeView/CodeViewTypes.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(BinaryStreamReader &R) + : Reader(R), Mapping(Reader), StartOffset(0) {} + + BinaryStreamReader &Reader; + TypeRecordMapping Mapping; + uint32_t StartOffset; + }; + +public: + explicit FieldListDeserializer(BinaryStreamReader &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 "llvm/DebugInfo/CodeView/CodeViewTypes.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/clang-r353983/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h new file mode 100644 index 00000000..41a219ae --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h @@ -0,0 +1,85 @@ +//===-- TypeDumpVisitor.h - CodeView type info dumper -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" + +namespace llvm { +class ScopedPrinter; + +namespace codeview { + +class TypeCollection; + +/// Dumper for CodeView type streams found in COFF object files and PDB files. +class TypeDumpVisitor : public TypeVisitorCallbacks { +public: + TypeDumpVisitor(TypeCollection &TpiTypes, ScopedPrinter *W, + bool PrintRecordBytes) + : W(W), PrintRecordBytes(PrintRecordBytes), TpiTypes(TpiTypes) {} + + /// When dumping types from an IPI stream in a PDB, a type index may refer to + /// a type or an item ID. The dumper will lookup the "name" of the index in + /// the item database if appropriate. If ItemDB is null, it will use TypeDB, + /// which is correct when dumping types from an object file (/Z7). + void setIpiTypes(TypeCollection &Types) { IpiTypes = &Types; } + + void printTypeIndex(StringRef FieldName, TypeIndex TI) const; + + void printItemIndex(StringRef FieldName, TypeIndex TI) const; + + /// Action to take on unknown types. By default, they are ignored. + Error visitUnknownType(CVType &Record) override; + Error visitUnknownMember(CVMemberRecord &Record) override; + + /// Paired begin/end actions for all types. Receives all record data, + /// including the fixed-length record prefix. + Error visitTypeBegin(CVType &Record) override; + Error visitTypeBegin(CVType &Record, TypeIndex Index) override; + Error visitTypeEnd(CVType &Record) override; + Error visitMemberBegin(CVMemberRecord &Record) override; + Error visitMemberEnd(CVMemberRecord &Record) override; + +#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 "llvm/DebugInfo/CodeView/CodeViewTypes.def" + +private: + void printMemberAttributes(MemberAttributes Attrs); + void printMemberAttributes(MemberAccess Access, MethodKind Kind, + MethodOptions Options); + + /// Get the database of indices for the stream that we are dumping. If ItemDB + /// is set, then we must be dumping an item (IPI) stream. This will also + /// always get the appropriate DB for printing item names. + TypeCollection &getSourceTypes() const { + return IpiTypes ? *IpiTypes : TpiTypes; + } + + ScopedPrinter *W; + + bool PrintRecordBytes = false; + + TypeCollection &TpiTypes; + TypeCollection *IpiTypes = nullptr; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeHashing.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeHashing.h new file mode 100644 index 00000000..c2fbff64 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeHashing.h @@ -0,0 +1,233 @@ +//===- TypeHashing.h ---------------------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEHASHING_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEHASHING_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/Hashing.h" + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" + +#include "llvm/Support/FormatProviders.h" + +#include <type_traits> + +namespace llvm { +namespace codeview { + +/// A locally hashed type represents a straightforward hash code of a serialized +/// record. The record is simply serialized, and then the bytes are hashed by +/// a standard algorithm. This is sufficient for the case of de-duplicating +/// records within a single sequence of types, because if two records both have +/// a back-reference to the same type in the same stream, they will both have +/// the same numeric value for the TypeIndex of the back reference. +struct LocallyHashedType { + hash_code Hash; + ArrayRef<uint8_t> RecordData; + + /// Given a type, compute its local hash. + static LocallyHashedType hashType(ArrayRef<uint8_t> RecordData); + + /// Given a sequence of types, compute all of the local hashes. + template <typename Range> + static std::vector<LocallyHashedType> hashTypes(Range &&Records) { + std::vector<LocallyHashedType> Hashes; + Hashes.reserve(std::distance(std::begin(Records), std::end(Records))); + for (const auto &R : Records) + Hashes.push_back(hashType(R)); + + return Hashes; + } + + static std::vector<LocallyHashedType> + hashTypeCollection(TypeCollection &Types) { + std::vector<LocallyHashedType> Hashes; + Types.ForEachRecord([&Hashes](TypeIndex TI, const CVType &Type) { + Hashes.push_back(hashType(Type.RecordData)); + }); + return Hashes; + } +}; + +enum class GlobalTypeHashAlg : uint16_t { + SHA1 = 0, // standard 20-byte SHA1 hash + SHA1_8 // last 8-bytes of standard SHA1 hash +}; + +/// A globally hashed type represents a hash value that is sufficient to +/// uniquely identify a record across multiple type streams or type sequences. +/// This works by, for any given record A which references B, replacing the +/// TypeIndex that refers to B with a previously-computed global hash for B. As +/// this is a recursive algorithm (e.g. the global hash of B also depends on the +/// global hashes of the types that B refers to), a global hash can uniquely +/// identify identify that A occurs in another stream that has a completely +/// different graph structure. Although the hash itself is slower to compute, +/// probing is much faster with a globally hashed type, because the hash itself +/// is considered "as good as" the original type. Since type records can be +/// quite large, this makes the equality comparison of the hash much faster than +/// equality comparison of a full record. +struct GloballyHashedType { + GloballyHashedType() = default; + GloballyHashedType(StringRef H) + : GloballyHashedType(ArrayRef<uint8_t>(H.bytes_begin(), H.bytes_end())) {} + GloballyHashedType(ArrayRef<uint8_t> H) { + assert(H.size() == 8); + ::memcpy(Hash.data(), H.data(), 8); + } + std::array<uint8_t, 8> Hash; + + bool empty() const { return *(const uint64_t*)Hash.data() == 0; }
+ + /// Given a sequence of bytes representing a record, compute a global hash for + /// this record. Due to the nature of global hashes incorporating the hashes + /// of referenced records, this function requires a list of types and ids + /// that RecordData might reference, indexable by TypeIndex. + static GloballyHashedType hashType(ArrayRef<uint8_t> RecordData, + ArrayRef<GloballyHashedType> PreviousTypes, + ArrayRef<GloballyHashedType> PreviousIds); + + /// Given a sequence of bytes representing a record, compute a global hash for + /// this record. Due to the nature of global hashes incorporating the hashes + /// of referenced records, this function requires a list of types and ids + /// that RecordData might reference, indexable by TypeIndex. + static GloballyHashedType hashType(CVType Type, + ArrayRef<GloballyHashedType> PreviousTypes, + ArrayRef<GloballyHashedType> PreviousIds) { + return hashType(Type.RecordData, PreviousTypes, PreviousIds); + } + + /// Given a sequence of combined type and ID records, compute global hashes + /// for each of them, returning the results in a vector of hashed types. + template <typename Range> + static std::vector<GloballyHashedType> hashTypes(Range &&Records) { + std::vector<GloballyHashedType> Hashes; + bool UnresolvedRecords = false;
+ for (const auto &R : Records) {
+ GloballyHashedType H = hashType(R, Hashes, Hashes); + if (H.empty()) + UnresolvedRecords = true; + Hashes.push_back(H); + } + + // In some rare cases, there might be records with forward references in the + // stream. Several passes might be needed to fully hash each record in the + // Type stream. However this occurs on very small OBJs generated by MASM, + // with a dozen records at most. Therefore this codepath isn't + // time-critical, as it isn't taken in 99% of cases. + while (UnresolvedRecords) { + UnresolvedRecords = false; + auto HashIt = Hashes.begin(); + for (const auto &R : Records) { + if (HashIt->empty()) { + GloballyHashedType H = hashType(R, Hashes, Hashes); + if (H.empty()) + UnresolvedRecords = true; + else + *HashIt = H; + } + ++HashIt; + } + } + + return Hashes; + } + + /// Given a sequence of combined type and ID records, compute global hashes + /// for each of them, returning the results in a vector of hashed types. + template <typename Range> + static std::vector<GloballyHashedType> + hashIds(Range &&Records, ArrayRef<GloballyHashedType> TypeHashes) { + std::vector<GloballyHashedType> IdHashes; + for (const auto &R : Records) + IdHashes.push_back(hashType(R, TypeHashes, IdHashes)); + + return IdHashes; + } + + static std::vector<GloballyHashedType> + hashTypeCollection(TypeCollection &Types) { + std::vector<GloballyHashedType> Hashes; + Types.ForEachRecord([&Hashes](TypeIndex TI, const CVType &Type) { + Hashes.push_back(hashType(Type.RecordData, Hashes, Hashes)); + }); + return Hashes; + } +}; +#if defined(_MSC_VER) +// is_trivially_copyable is not available in older versions of libc++, but it is +// available in all supported versions of MSVC, so at least this gives us some +// coverage. +static_assert(std::is_trivially_copyable<GloballyHashedType>::value, + "GloballyHashedType must be trivially copyable so that we can " + "reinterpret_cast arrays of hash data to arrays of " + "GloballyHashedType"); +#endif +} // namespace codeview + +template <> struct DenseMapInfo<codeview::LocallyHashedType> { + static codeview::LocallyHashedType Empty; + static codeview::LocallyHashedType Tombstone; + + static codeview::LocallyHashedType getEmptyKey() { return Empty; } + + static codeview::LocallyHashedType getTombstoneKey() { return Tombstone; } + + static unsigned getHashValue(codeview::LocallyHashedType Val) { + return Val.Hash; + } + + static bool isEqual(codeview::LocallyHashedType LHS, + codeview::LocallyHashedType RHS) { + if (LHS.Hash != RHS.Hash) + return false; + return LHS.RecordData == RHS.RecordData; + } +}; + +template <> struct DenseMapInfo<codeview::GloballyHashedType> { + static codeview::GloballyHashedType Empty; + static codeview::GloballyHashedType Tombstone; + + static codeview::GloballyHashedType getEmptyKey() { return Empty; } + + static codeview::GloballyHashedType getTombstoneKey() { return Tombstone; } + + static unsigned getHashValue(codeview::GloballyHashedType Val) { + return *reinterpret_cast<const unsigned *>(Val.Hash.data()); + } + + static bool isEqual(codeview::GloballyHashedType LHS, + codeview::GloballyHashedType RHS) { + return LHS.Hash == RHS.Hash; + } +}; + +template <> struct format_provider<codeview::LocallyHashedType> { +public: + static void format(const codeview::LocallyHashedType &V, + llvm::raw_ostream &Stream, StringRef Style) { + write_hex(Stream, V.Hash, HexPrintStyle::Upper, 8); + } +}; + +template <> struct format_provider<codeview::GloballyHashedType> { +public: + static void format(const codeview::GloballyHashedType &V, + llvm::raw_ostream &Stream, StringRef Style) { + for (uint8_t B : V.Hash) { + write_hex(Stream, B, HexPrintStyle::Upper, 2); + } + } +}; + +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeIndex.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeIndex.h new file mode 100644 index 00000000..b9e2562b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -0,0 +1,299 @@ +//===- TypeIndex.h ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/Endian.h" +#include <cassert> +#include <cinttypes> +#include <functional> + +namespace llvm { + +class ScopedPrinter; + +namespace codeview { + +class TypeCollection; + +enum class SimpleTypeKind : uint32_t { + None = 0x0000, // uncharacterized type (no type) + Void = 0x0003, // void + NotTranslated = 0x0007, // type not translated by cvpack + HResult = 0x0008, // OLE/COM HRESULT + + SignedCharacter = 0x0010, // 8 bit signed + UnsignedCharacter = 0x0020, // 8 bit unsigned + NarrowCharacter = 0x0070, // really a char + WideCharacter = 0x0071, // wide char + Character16 = 0x007a, // char16_t + Character32 = 0x007b, // char32_t + + SByte = 0x0068, // 8 bit signed int + Byte = 0x0069, // 8 bit unsigned int + Int16Short = 0x0011, // 16 bit signed + UInt16Short = 0x0021, // 16 bit unsigned + Int16 = 0x0072, // 16 bit signed int + UInt16 = 0x0073, // 16 bit unsigned int + Int32Long = 0x0012, // 32 bit signed + UInt32Long = 0x0022, // 32 bit unsigned + Int32 = 0x0074, // 32 bit signed int + UInt32 = 0x0075, // 32 bit unsigned int + Int64Quad = 0x0013, // 64 bit signed + UInt64Quad = 0x0023, // 64 bit unsigned + Int64 = 0x0076, // 64 bit signed int + UInt64 = 0x0077, // 64 bit unsigned int + Int128Oct = 0x0014, // 128 bit signed int + UInt128Oct = 0x0024, // 128 bit unsigned int + Int128 = 0x0078, // 128 bit signed int + UInt128 = 0x0079, // 128 bit unsigned int + + Float16 = 0x0046, // 16 bit real + Float32 = 0x0040, // 32 bit real + Float32PartialPrecision = 0x0045, // 32 bit PP real + Float48 = 0x0044, // 48 bit real + Float64 = 0x0041, // 64 bit real + Float80 = 0x0042, // 80 bit real + Float128 = 0x0043, // 128 bit real + + Complex16 = 0x0056, // 16 bit complex + Complex32 = 0x0050, // 32 bit complex + Complex32PartialPrecision = 0x0055, // 32 bit PP complex + Complex48 = 0x0054, // 48 bit complex + Complex64 = 0x0051, // 64 bit complex + Complex80 = 0x0052, // 80 bit complex + Complex128 = 0x0053, // 128 bit complex + + Boolean8 = 0x0030, // 8 bit boolean + Boolean16 = 0x0031, // 16 bit boolean + Boolean32 = 0x0032, // 32 bit boolean + Boolean64 = 0x0033, // 64 bit boolean + Boolean128 = 0x0034, // 128 bit boolean +}; + +enum class SimpleTypeMode : uint32_t { + Direct = 0x00000000, // Not a pointer + NearPointer = 0x00000100, // Near pointer + FarPointer = 0x00000200, // Far pointer + HugePointer = 0x00000300, // Huge pointer + NearPointer32 = 0x00000400, // 32 bit near pointer + FarPointer32 = 0x00000500, // 32 bit far pointer + NearPointer64 = 0x00000600, // 64 bit near pointer + NearPointer128 = 0x00000700 // 128 bit near pointer +}; + +/// A 32-bit type reference. Types are indexed by their order of appearance in +/// .debug$T plus 0x1000. Type indices less than 0x1000 are "simple" types, +/// composed of a SimpleTypeMode byte followed by a SimpleTypeKind byte. +class TypeIndex { +public: + static const uint32_t FirstNonSimpleIndex = 0x1000; + static const uint32_t SimpleKindMask = 0x000000ff; + static const uint32_t SimpleModeMask = 0x00000700; + static const uint32_t DecoratedItemIdMask = 0x80000000; + +public: + 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)) {} + TypeIndex(SimpleTypeKind Kind, SimpleTypeMode Mode) + : 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 isDecoratedItemId() const { return !!(Index & DecoratedItemIdMask); } + + bool isNoneType() const { return *this == None(); } + + uint32_t toArrayIndex() const { + assert(!isSimple()); + return getIndex() - FirstNonSimpleIndex; + } + + static TypeIndex fromArrayIndex(uint32_t Index) { + return TypeIndex(Index + FirstNonSimpleIndex); + } + + SimpleTypeKind getSimpleKind() const { + assert(isSimple()); + return static_cast<SimpleTypeKind>(Index & SimpleKindMask); + } + + SimpleTypeMode getSimpleMode() const { + assert(isSimple()); + return static_cast<SimpleTypeMode>(Index & SimpleModeMask); + } + + TypeIndex makeDirect() const { return TypeIndex{getSimpleKind()}; } + + static TypeIndex None() { return TypeIndex(SimpleTypeKind::None); } + static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); } + static TypeIndex VoidPointer32() { + return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer32); + } + static TypeIndex VoidPointer64() { + return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer64); + } + + static TypeIndex NullptrT() { + // std::nullptr_t uses the pointer mode that doesn't indicate bit-width, + // presumably because std::nullptr_t is intended to be compatible with any + // pointer type. + return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer); + } + + static TypeIndex SignedCharacter() { + return TypeIndex(SimpleTypeKind::SignedCharacter); + } + static TypeIndex UnsignedCharacter() { + return TypeIndex(SimpleTypeKind::UnsignedCharacter); + } + static TypeIndex NarrowCharacter() { + return TypeIndex(SimpleTypeKind::NarrowCharacter); + } + static TypeIndex WideCharacter() { + return TypeIndex(SimpleTypeKind::WideCharacter); + } + static TypeIndex Int16Short() { + return TypeIndex(SimpleTypeKind::Int16Short); + } + static TypeIndex UInt16Short() { + return TypeIndex(SimpleTypeKind::UInt16Short); + } + static TypeIndex Int32() { return TypeIndex(SimpleTypeKind::Int32); } + static TypeIndex UInt32() { return TypeIndex(SimpleTypeKind::UInt32); } + static TypeIndex Int32Long() { return TypeIndex(SimpleTypeKind::Int32Long); } + static TypeIndex UInt32Long() { + return TypeIndex(SimpleTypeKind::UInt32Long); + } + static TypeIndex Int64() { return TypeIndex(SimpleTypeKind::Int64); } + static TypeIndex UInt64() { return TypeIndex(SimpleTypeKind::UInt64); } + static TypeIndex Int64Quad() { return TypeIndex(SimpleTypeKind::Int64Quad); } + static TypeIndex UInt64Quad() { + return TypeIndex(SimpleTypeKind::UInt64Quad); + } + + static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); } + static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); } + + TypeIndex &operator+=(unsigned N) { + Index += N; + return *this; + } + + TypeIndex &operator++() { + Index += 1; + return *this; + } + + TypeIndex operator++(int) { + TypeIndex Copy = *this; + operator++(); + return Copy; + } + + TypeIndex &operator-=(unsigned N) { + assert(Index >= N); + Index -= N; + return *this; + } + + TypeIndex &operator--() { + Index -= 1; + return *this; + } + + TypeIndex operator--(int) { + TypeIndex Copy = *this; + operator--(); + return Copy; + } + + friend inline bool operator==(const TypeIndex &A, const TypeIndex &B) { + return A.getIndex() == B.getIndex(); + } + + friend inline bool operator!=(const TypeIndex &A, const TypeIndex &B) { + return A.getIndex() != B.getIndex(); + } + + friend inline bool operator<(const TypeIndex &A, const TypeIndex &B) { + return A.getIndex() < B.getIndex(); + } + + friend inline bool operator<=(const TypeIndex &A, const TypeIndex &B) { + return A.getIndex() <= B.getIndex(); + } + + friend inline bool operator>(const TypeIndex &A, const TypeIndex &B) { + return A.getIndex() > B.getIndex(); + } + + friend inline bool operator>=(const TypeIndex &A, const TypeIndex &B) { + return A.getIndex() >= B.getIndex(); + } + + friend inline TypeIndex operator+(const TypeIndex &A, uint32_t N) { + TypeIndex Result(A); + Result += N; + return Result; + } + + friend inline TypeIndex operator-(const TypeIndex &A, uint32_t N) { + assert(A.getIndex() >= N); + TypeIndex Result(A); + Result -= N; + return Result; + } + + friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) { + assert(A >= B); + return A.toArrayIndex() - B.toArrayIndex(); + } + + static StringRef simpleTypeName(TypeIndex TI); + +private: + support::ulittle32_t Index; +}; + +// Used for pseudo-indexing an array of type records. An array of such records +// sorted by TypeIndex can allow log(N) lookups even though such a type record +// stream does not provide random access. +struct TypeIndexOffset { + TypeIndex Type; + support::ulittle32_t Offset; +}; + +void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI, + TypeCollection &Types); +} + +template <> struct DenseMapInfo<codeview::TypeIndex> { + static inline codeview::TypeIndex getEmptyKey() { + return codeview::TypeIndex{DenseMapInfo<uint32_t>::getEmptyKey()}; + } + static inline codeview::TypeIndex getTombstoneKey() { + return codeview::TypeIndex{DenseMapInfo<uint32_t>::getTombstoneKey()}; + } + static unsigned getHashValue(const codeview::TypeIndex &TI) { + return DenseMapInfo<uint32_t>::getHashValue(TI.getIndex()); + } + static bool isEqual(const codeview::TypeIndex &LHS, + const codeview::TypeIndex &RHS) { + return LHS == RHS; + } +}; + +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h new file mode 100644 index 00000000..46976878 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h @@ -0,0 +1,46 @@ +//===- TypeIndexDiscovery.h -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEINDEXDISCOVERY_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEXDISCOVERY_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +enum class TiRefKind { TypeRef, IndexRef }; +struct TiReference { + TiRefKind Kind; + uint32_t Offset; + uint32_t Count; +}; + +void discoverTypeIndices(ArrayRef<uint8_t> RecordData, + SmallVectorImpl<TiReference> &Refs); +void discoverTypeIndices(const CVType &Type, + SmallVectorImpl<TiReference> &Refs); +void discoverTypeIndices(const CVType &Type, + SmallVectorImpl<TypeIndex> &Indices); +void discoverTypeIndices(ArrayRef<uint8_t> RecordData, + SmallVectorImpl<TypeIndex> &Indices); + +/// Discover type indices in symbol records. Returns false if this is an unknown +/// record. +bool discoverTypeIndicesInSymbol(const CVSymbol &Symbol, + SmallVectorImpl<TiReference> &Refs); +bool discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData, + SmallVectorImpl<TiReference> &Refs); +bool discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData, + SmallVectorImpl<TypeIndex> &Indices); +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeRecord.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeRecord.h new file mode 100644 index 00000000..b147dd6c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -0,0 +1,964 @@ +//===- TypeRecord.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H + +#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/ADT/iterator_range.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/GUID.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/Endian.h" +#include <algorithm> +#include <cstdint> +#include <vector> + +namespace llvm { +namespace codeview { + +using support::little32_t; +using support::ulittle16_t; +using support::ulittle32_t; + +using CVType = CVRecord<TypeLeafKind>; +using RemappedType = RemappedRecord<TypeLeafKind>; + +struct CVMemberRecord { + TypeLeafKind Kind; + ArrayRef<uint8_t> Data; +}; +using CVTypeArray = VarStreamArray<CVType>; +using CVTypeRange = iterator_range<CVTypeArray::Iterator>; + +/// Equvalent to CV_fldattr_t in cvinfo.h. +struct MemberAttributes { + uint16_t Attrs = 0; + + enum { + MethodKindShift = 2, + }; + + MemberAttributes() = default; + + explicit MemberAttributes(MemberAccess Access) + : 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 { + return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask)); + } + + /// Indicates if a method is defined with friend, virtual, static, etc. + MethodKind getMethodKind() const { + return MethodKind( + (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >> + MethodKindShift); + } + + /// Get the flags that are not included in access control or method + /// properties. + MethodOptions getFlags() const { + return MethodOptions( + unsigned(Attrs) & + ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask)); + } + + /// Is this method virtual. + bool isVirtual() const { + auto MP = getMethodKind(); + return MP != MethodKind::Vanilla && MP != MethodKind::Friend && + MP != MethodKind::Static; + } + + /// Does this member introduce a new virtual method. + bool isIntroducedVirtual() const { + auto MP = getMethodKind(); + return MP == MethodKind::IntroducingVirtual || + MP == MethodKind::PureIntroducingVirtual; + } + + /// Is this method static. + bool isStatic() const { + return getMethodKind() == MethodKind::Static; + } +}; + +// Does not correspond to any tag, this is the tail of an LF_POINTER record +// if it represents a member pointer. +class MemberPointerInfo { +public: + MemberPointerInfo() = default; + + MemberPointerInfo(TypeIndex ContainingType, + PointerToMemberRepresentation Representation) + : ContainingType(ContainingType), Representation(Representation) {} + + TypeIndex getContainingType() const { return ContainingType; } + PointerToMemberRepresentation getRepresentation() const { + return Representation; + } + + TypeIndex ContainingType; + PointerToMemberRepresentation Representation; +}; + +class TypeRecord { +protected: + TypeRecord() = default; + explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {} + +public: + TypeRecordKind getKind() const { return Kind; } + + TypeRecordKind Kind; +}; + +// LF_MODIFIER +class ModifierRecord : public TypeRecord { +public: + ModifierRecord() = default; + explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers) + : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType), + Modifiers(Modifiers) {} + + TypeIndex getModifiedType() const { return ModifiedType; } + ModifierOptions getModifiers() const { return Modifiers; } + + TypeIndex ModifiedType; + ModifierOptions Modifiers; +}; + +// LF_PROCEDURE +class ProcedureRecord : public TypeRecord { +public: + ProcedureRecord() = default; + explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv, + FunctionOptions Options, uint16_t ParameterCount, + TypeIndex ArgumentList) + : TypeRecord(TypeRecordKind::Procedure), ReturnType(ReturnType), + CallConv(CallConv), Options(Options), ParameterCount(ParameterCount), + ArgumentList(ArgumentList) {} + + 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; } + + TypeIndex ReturnType; + CallingConvention CallConv; + FunctionOptions Options; + uint16_t ParameterCount; + TypeIndex ArgumentList; +}; + +// LF_MFUNCTION +class MemberFunctionRecord : public TypeRecord { +public: + MemberFunctionRecord() = default; + explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType, + TypeIndex ThisType, CallingConvention CallConv, + FunctionOptions Options, uint16_t ParameterCount, + TypeIndex ArgumentList, int32_t ThisPointerAdjustment) + : TypeRecord(TypeRecordKind::MemberFunction), ReturnType(ReturnType), + ClassType(ClassType), ThisType(ThisType), CallConv(CallConv), + Options(Options), ParameterCount(ParameterCount), + ArgumentList(ArgumentList), + ThisPointerAdjustment(ThisPointerAdjustment) {} + + TypeIndex getReturnType() const { return ReturnType; } + TypeIndex getClassType() const { return ClassType; } + TypeIndex getThisType() const { return ThisType; } + CallingConvention getCallConv() const { return CallConv; } + FunctionOptions getOptions() const { return Options; } + uint16_t getParameterCount() const { return ParameterCount; } + TypeIndex getArgumentList() const { return ArgumentList; } + int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; } + + TypeIndex ReturnType; + TypeIndex ClassType; + TypeIndex ThisType; + CallingConvention CallConv; + FunctionOptions Options; + uint16_t ParameterCount; + TypeIndex ArgumentList; + int32_t ThisPointerAdjustment; +}; + +// LF_LABEL +class LabelRecord : public TypeRecord { +public: + LabelRecord() = default; + explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {} + + LabelType Mode; +}; + +// LF_MFUNC_ID +class MemberFuncIdRecord : public TypeRecord { +public: + MemberFuncIdRecord() = default; + explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType, + StringRef Name) + : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType), + FunctionType(FunctionType), Name(Name) {} + + TypeIndex getClassType() const { return ClassType; } + TypeIndex getFunctionType() const { return FunctionType; } + StringRef getName() const { return Name; } + + TypeIndex ClassType; + TypeIndex FunctionType; + StringRef Name; +}; + +// LF_ARGLIST +class ArgListRecord : public TypeRecord { +public: + ArgListRecord() = default; + explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices) + : TypeRecord(Kind), ArgIndices(Indices) {} + + ArrayRef<TypeIndex> getIndices() const { return ArgIndices; } + + std::vector<TypeIndex> ArgIndices; +}; + +// LF_SUBSTR_LIST +class StringListRecord : public TypeRecord { +public: + StringListRecord() = default; + explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices) + : TypeRecord(Kind), StringIndices(Indices) {} + + ArrayRef<TypeIndex> getIndices() const { return StringIndices; } + + std::vector<TypeIndex> StringIndices; +}; + +// LF_POINTER +class PointerRecord : public TypeRecord { +public: + // ---------------------------XXXXX + static const uint32_t PointerKindShift = 0; + static const uint32_t PointerKindMask = 0x1F; + + // ------------------------XXX----- + static const uint32_t PointerModeShift = 5; + static const uint32_t PointerModeMask = 0x07; + + // ----------XXX------XXXXX-------- + static const uint32_t PointerOptionMask = 0x381f00; + + // -------------XXXXXX------------ + static const uint32_t PointerSizeShift = 13; + static const uint32_t PointerSizeMask = 0xFF; + + PointerRecord() = default; + explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + PointerRecord(TypeIndex ReferentType, uint32_t Attrs) + : 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 &MPI) + : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), + Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(MPI) {} + + TypeIndex getReferentType() const { return ReferentType; } + + PointerKind getPointerKind() const { + return static_cast<PointerKind>((Attrs >> PointerKindShift) & + PointerKindMask); + } + + PointerMode getMode() const { + return static_cast<PointerMode>((Attrs >> PointerModeShift) & + PointerModeMask); + } + + PointerOptions getOptions() const { + return static_cast<PointerOptions>(Attrs & PointerOptionMask); + } + + 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 !!(Attrs & uint32_t(PointerOptions::Volatile)); + } + + bool isUnaligned() const { + return !!(Attrs & uint32_t(PointerOptions::Unaligned)); + } + + bool isRestrict() const { + return !!(Attrs & uint32_t(PointerOptions::Restrict)); + } + + bool isLValueReferenceThisPtr() const { + return !!(Attrs & uint32_t(PointerOptions::LValueRefThisPointer)); + } + + bool isRValueReferenceThisPtr() const { + return !!(Attrs & uint32_t(PointerOptions::RValueRefThisPointer)); + } + + TypeIndex ReferentType; + uint32_t Attrs; + Optional<MemberPointerInfo> MemberInfo; + + void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO, + uint8_t Size) { + Attrs = calcAttrs(PK, PM, PO, Size); + } + +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: + NestedTypeRecord() = default; + explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + NestedTypeRecord(TypeIndex Type, StringRef Name) + : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {} + + TypeIndex getNestedType() const { return Type; } + StringRef getName() const { return Name; } + + TypeIndex Type; + StringRef Name; +}; + +// LF_FIELDLIST +class FieldListRecord : public TypeRecord { +public: + FieldListRecord() = default; + explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + explicit FieldListRecord(ArrayRef<uint8_t> Data) + : TypeRecord(TypeRecordKind::FieldList), Data(Data) {} + + ArrayRef<uint8_t> Data; +}; + +// LF_ARRAY +class ArrayRecord : public TypeRecord { +public: + ArrayRecord() = default; + explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size, + StringRef Name) + : TypeRecord(TypeRecordKind::Array), ElementType(ElementType), + IndexType(IndexType), Size(Size), Name(Name) {} + + TypeIndex getElementType() const { return ElementType; } + TypeIndex getIndexType() const { return IndexType; } + uint64_t getSize() const { return Size; } + StringRef getName() const { return Name; } + + TypeIndex ElementType; + TypeIndex IndexType; + uint64_t Size; + StringRef Name; +}; + +class TagRecord : public TypeRecord { +protected: + TagRecord() = default; + explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, + TypeIndex FieldList, StringRef Name, StringRef UniqueName) + : TypeRecord(Kind), MemberCount(MemberCount), Options(Options), + FieldList(FieldList), Name(Name), UniqueName(UniqueName) {} + +public: + static const int HfaKindShift = 11; + static const int HfaKindMask = 0x1800; + static const int WinRTKindShift = 14; + static const int WinRTKindMask = 0xC000; + + bool hasUniqueName() const { + return (Options & ClassOptions::HasUniqueName) != ClassOptions::None; + } + + bool isNested() const { + return (Options & ClassOptions::Nested) != ClassOptions::None; + } + + bool isForwardRef() const { + return (Options & ClassOptions::ForwardReference) != ClassOptions::None; + } + + bool containsNestedClass() const { + return (Options & ClassOptions::ContainsNestedClass) != ClassOptions::None; + } + + bool isScoped() const { + return (Options & ClassOptions::Scoped) != 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; } + + uint16_t MemberCount; + ClassOptions Options; + TypeIndex FieldList; + StringRef Name; + StringRef UniqueName; +}; + +// LF_CLASS, LF_STRUCTURE, LF_INTERFACE +class ClassRecord : public TagRecord { +public: + ClassRecord() = default; + explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {} + ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, + TypeIndex FieldList, TypeIndex DerivationList, + TypeIndex VTableShape, uint64_t Size, StringRef Name, + StringRef UniqueName) + : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName), + DerivationList(DerivationList), VTableShape(VTableShape), Size(Size) {} + + 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); + } + + TypeIndex getDerivationList() const { return DerivationList; } + TypeIndex getVTableShape() const { return VTableShape; } + uint64_t getSize() const { return Size; } + + TypeIndex DerivationList; + TypeIndex VTableShape; + uint64_t Size; +}; + +// LF_UNION +struct UnionRecord : public TagRecord { + UnionRecord() = default; + explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {} + UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, + uint64_t Size, StringRef Name, StringRef UniqueName) + : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name, + UniqueName), + Size(Size) {} + + HfaKind getHfa() const { + uint16_t Value = static_cast<uint16_t>(Options); + Value = (Value & HfaKindMask) >> HfaKindShift; + return static_cast<HfaKind>(Value); + } + + uint64_t getSize() const { return Size; } + + uint64_t Size; +}; + +// LF_ENUM +class EnumRecord : public TagRecord { +public: + EnumRecord() = default; + explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {} + EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, + StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType) + : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name, + UniqueName), + UnderlyingType(UnderlyingType) {} + + TypeIndex getUnderlyingType() const { return UnderlyingType; } + + TypeIndex UnderlyingType; +}; + +// LF_BITFIELD +class BitFieldRecord : public TypeRecord { +public: + BitFieldRecord() = default; + explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset) + : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize), + BitOffset(BitOffset) {} + + TypeIndex getType() const { return Type; } + uint8_t getBitOffset() const { return BitOffset; } + uint8_t getBitSize() const { return BitSize; } + + TypeIndex Type; + uint8_t BitSize; + uint8_t BitOffset; +}; + +// LF_VTSHAPE +class VFTableShapeRecord : public TypeRecord { +public: + VFTableShapeRecord() = default; + explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots) + : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {} + explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots) + : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {} + + ArrayRef<VFTableSlotKind> getSlots() const { + if (!SlotsRef.empty()) + return SlotsRef; + return Slots; + } + + uint32_t getEntryCount() const { return getSlots().size(); } + + ArrayRef<VFTableSlotKind> SlotsRef; + std::vector<VFTableSlotKind> Slots; +}; + +// LF_TYPESERVER2 +class TypeServer2Record : public TypeRecord { +public: + TypeServer2Record() = default; + explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {} + TypeServer2Record(StringRef GuidStr, uint32_t Age, StringRef Name) + : TypeRecord(TypeRecordKind::TypeServer2), Age(Age), Name(Name) { + assert(GuidStr.size() == 16 && "guid isn't 16 bytes"); + ::memcpy(Guid.Guid, GuidStr.data(), 16); + } + + const GUID &getGuid() const { return Guid; } + uint32_t getAge() const { return Age; } + StringRef getName() const { return Name; } + + GUID Guid; + uint32_t Age; + StringRef Name; +}; + +// LF_STRING_ID +class StringIdRecord : public TypeRecord { +public: + StringIdRecord() = default; + explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + StringIdRecord(TypeIndex Id, StringRef String) + : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {} + + TypeIndex getId() const { return Id; } + StringRef getString() const { return String; } + + TypeIndex Id; + StringRef String; +}; + +// LF_FUNC_ID +class FuncIdRecord : public TypeRecord { +public: + FuncIdRecord() = default; + explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name) + : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope), + FunctionType(FunctionType), Name(Name) {} + + TypeIndex getParentScope() const { return ParentScope; } + TypeIndex getFunctionType() const { return FunctionType; } + StringRef getName() const { return Name; } + + TypeIndex ParentScope; + TypeIndex FunctionType; + StringRef Name; +}; + +// LF_UDT_SRC_LINE +class UdtSourceLineRecord : public TypeRecord { +public: + UdtSourceLineRecord() = default; + explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber) + : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), + SourceFile(SourceFile), LineNumber(LineNumber) {} + + TypeIndex getUDT() const { return UDT; } + TypeIndex getSourceFile() const { return SourceFile; } + uint32_t getLineNumber() const { return LineNumber; } + + TypeIndex UDT; + TypeIndex SourceFile; + uint32_t LineNumber; +}; + +// LF_UDT_MOD_SRC_LINE +class UdtModSourceLineRecord : public TypeRecord { +public: + UdtModSourceLineRecord() = default; + explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, + uint32_t LineNumber, uint16_t Module) + : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), + SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {} + + TypeIndex getUDT() const { return UDT; } + TypeIndex getSourceFile() const { return SourceFile; } + uint32_t getLineNumber() const { return LineNumber; } + uint16_t getModule() const { return Module; } + + TypeIndex UDT; + TypeIndex SourceFile; + uint32_t LineNumber; + uint16_t Module; +}; + +// LF_BUILDINFO +class BuildInfoRecord : public TypeRecord { +public: + BuildInfoRecord() = default; + explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices) + : TypeRecord(TypeRecordKind::BuildInfo), + ArgIndices(ArgIndices.begin(), ArgIndices.end()) {} + + ArrayRef<TypeIndex> getArgs() const { return ArgIndices; } + + /// Indices of known build info arguments. + enum BuildInfoArg { + CurrentDirectory, ///< Absolute CWD path + BuildTool, ///< Absolute compiler path + SourceFile, ///< Path to main source file, relative or absolute + TypeServerPDB, ///< Absolute path of type server PDB (/Fd) + CommandLine, ///< Full canonical command line (maybe -cc1) + MaxArgs + }; + + SmallVector<TypeIndex, MaxArgs> ArgIndices; +}; + +// LF_VFTABLE +class VFTableRecord : public TypeRecord { +public: + VFTableRecord() = default; + explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable, + uint32_t VFPtrOffset, StringRef Name, + ArrayRef<StringRef> Methods) + : TypeRecord(TypeRecordKind::VFTable), CompleteClass(CompleteClass), + OverriddenVFTable(OverriddenVFTable), VFPtrOffset(VFPtrOffset) { + MethodNames.push_back(Name); + MethodNames.insert(MethodNames.end(), Methods.begin(), Methods.end()); + } + + TypeIndex getCompleteClass() const { return CompleteClass; } + TypeIndex getOverriddenVTable() const { return OverriddenVFTable; } + uint32_t getVFPtrOffset() const { return VFPtrOffset; } + StringRef getName() const { return makeArrayRef(MethodNames).front(); } + + ArrayRef<StringRef> getMethodNames() const { + return makeArrayRef(MethodNames).drop_front(); + } + + TypeIndex CompleteClass; + TypeIndex OverriddenVFTable; + uint32_t VFPtrOffset; + std::vector<StringRef> MethodNames; +}; + +// LF_ONEMETHOD +class OneMethodRecord : public TypeRecord { +public: + OneMethodRecord() = default; + 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) {} + + TypeIndex getType() const { return Type; } + 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 getMethodKind() == MethodKind::IntroducingVirtual || + getMethodKind() == MethodKind::PureIntroducingVirtual; + } + + TypeIndex Type; + MemberAttributes Attrs; + int32_t VFTableOffset; + StringRef Name; +}; + +// LF_METHODLIST +class MethodOverloadListRecord : public TypeRecord { +public: + MethodOverloadListRecord() = default; + explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods) + : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {} + + ArrayRef<OneMethodRecord> getMethods() const { return Methods; } + + std::vector<OneMethodRecord> Methods; +}; + +/// For method overload sets. LF_METHOD +class OverloadedMethodRecord : public TypeRecord { +public: + OverloadedMethodRecord() = default; + explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList, + StringRef Name) + : TypeRecord(TypeRecordKind::OverloadedMethod), + NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {} + + uint16_t getNumOverloads() const { return NumOverloads; } + TypeIndex getMethodList() const { return MethodList; } + StringRef getName() const { return Name; } + + uint16_t NumOverloads; + TypeIndex MethodList; + StringRef Name; +}; + +// LF_MEMBER +class DataMemberRecord : public TypeRecord { +public: + DataMemberRecord() = default; + explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset, + StringRef Name) + : TypeRecord(TypeRecordKind::DataMember), Attrs(Attrs), Type(Type), + FieldOffset(Offset), Name(Name) {} + DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset, + StringRef Name) + : TypeRecord(TypeRecordKind::DataMember), Attrs(Access), Type(Type), + FieldOffset(Offset), Name(Name) {} + + MemberAccess getAccess() const { return Attrs.getAccess(); } + TypeIndex getType() const { return Type; } + uint64_t getFieldOffset() const { return FieldOffset; } + StringRef getName() const { return Name; } + + MemberAttributes Attrs; + TypeIndex Type; + uint64_t FieldOffset; + StringRef Name; +}; + +// LF_STMEMBER +class StaticDataMemberRecord : public TypeRecord { +public: + StaticDataMemberRecord() = default; + explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name) + : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type), + Name(Name) {} + StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name) + : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Access), Type(Type), + Name(Name) {} + + MemberAccess getAccess() const { return Attrs.getAccess(); } + TypeIndex getType() const { return Type; } + StringRef getName() const { return Name; } + + MemberAttributes Attrs; + TypeIndex Type; + StringRef Name; +}; + +// LF_ENUMERATE +class EnumeratorRecord : public TypeRecord { +public: + EnumeratorRecord() = default; + explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name) + : TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs), + Value(std::move(Value)), Name(Name) {} + EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name) + : TypeRecord(TypeRecordKind::Enumerator), Attrs(Access), + Value(std::move(Value)), Name(Name) {} + + MemberAccess getAccess() const { return Attrs.getAccess(); } + APSInt getValue() const { return Value; } + StringRef getName() const { return Name; } + + MemberAttributes Attrs; + APSInt Value; + StringRef Name; +}; + +// LF_VFUNCTAB +class VFPtrRecord : public TypeRecord { +public: + VFPtrRecord() = default; + explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + VFPtrRecord(TypeIndex Type) + : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {} + + TypeIndex getType() const { return Type; } + + TypeIndex Type; +}; + +// LF_BCLASS, LF_BINTERFACE +class BaseClassRecord : public TypeRecord { +public: + BaseClassRecord() = default; + explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset) + : TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type), + Offset(Offset) {} + BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset) + : TypeRecord(TypeRecordKind::BaseClass), Attrs(Access), Type(Type), + Offset(Offset) {} + + MemberAccess getAccess() const { return Attrs.getAccess(); } + TypeIndex getBaseType() const { return Type; } + uint64_t getBaseOffset() const { return Offset; } + + MemberAttributes Attrs; + TypeIndex Type; + uint64_t Offset; +}; + +// LF_VBCLASS, LF_IVBCLASS +class VirtualBaseClassRecord : public TypeRecord { +public: + VirtualBaseClassRecord() = default; + explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs, + TypeIndex BaseType, TypeIndex VBPtrType, + 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) {} + + 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; } + + MemberAttributes Attrs; + TypeIndex BaseType; + TypeIndex VBPtrType; + uint64_t VBPtrOffset; + uint64_t VTableIndex; +}; + +/// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records +/// together. The first will end in an LF_INDEX record that points to the next. +class ListContinuationRecord : public TypeRecord { +public: + ListContinuationRecord() = default; + explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + ListContinuationRecord(TypeIndex ContinuationIndex) + : TypeRecord(TypeRecordKind::ListContinuation), + ContinuationIndex(ContinuationIndex) {} + + TypeIndex getContinuationIndex() const { return ContinuationIndex; } + + TypeIndex ContinuationIndex; +}; + +// LF_PRECOMP +class PrecompRecord : public TypeRecord { +public: + PrecompRecord() = default; + explicit PrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + uint32_t getStartTypeIndex() const { return StartTypeIndex; } + uint32_t getTypesCount() const { return TypesCount; } + uint32_t getSignature() const { return Signature; } + StringRef getPrecompFilePath() const { return PrecompFilePath; } + + uint32_t StartTypeIndex; + uint32_t TypesCount; + uint32_t Signature; + StringRef PrecompFilePath; +}; + +// LF_ENDPRECOMP +class EndPrecompRecord : public TypeRecord { +public: + EndPrecompRecord() = default; + explicit EndPrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + uint32_t getSignature() const { return Signature; } + + uint32_t Signature; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h new file mode 100644 index 00000000..e84704d9 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h @@ -0,0 +1,27 @@ +//===- TypeRecordHelpers.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" + +namespace llvm { + namespace codeview { + /// Given an arbitrary codeview type, determine if it is an LF_STRUCTURE, + /// LF_CLASS, LF_INTERFACE, LF_UNION, or LF_ENUM with the forward ref class + /// option. + bool isUdtForwardRef(CVType CVT); + + /// Given a CVType which is assumed to be an LF_MODIFIER, return the + /// TypeIndex of the type that the LF_MODIFIER modifies. + TypeIndex getModifiedType(const CVType &CVT); + } +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h new file mode 100644 index 00000000..b885d54a --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h @@ -0,0 +1,51 @@ +//===- TypeRecordMapping.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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 { +class BinaryStreamReader; +class BinaryStreamWriter; + +namespace codeview { +class TypeRecordMapping : public TypeVisitorCallbacks { +public: + explicit TypeRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {} + explicit TypeRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {} + + using TypeVisitorCallbacks::visitTypeBegin; + Error visitTypeBegin(CVType &Record) override; + Error visitTypeEnd(CVType &Record) override; + + 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 "llvm/DebugInfo/CodeView/CodeViewTypes.def" + +private: + Optional<TypeLeafKind> TypeKind; + Optional<TypeLeafKind> MemberKind; + + CodeViewRecordIO IO; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h new file mode 100644 index 00000000..d0506cce --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h @@ -0,0 +1,109 @@ +//===- TypeStreamMerger.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESTREAMMERGER_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPESTREAMMERGER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { + +class TypeIndex; +struct GloballyHashedType; +class GlobalTypeTableBuilder; +class MergingTypeTableBuilder; + +/// Merge one set of type records into another. This method assumes +/// that all records are type records, and there are no Id records present. +/// +/// \param Dest The table to store the re-written type records into. +/// +/// \param SourceToDest A vector, indexed by the TypeIndex in the source +/// type stream, that contains the index of the corresponding type record +/// in the destination stream. +/// +/// \param Types The collection of types to merge in. +/// +/// \returns Error::success() if the operation succeeded, otherwise an +/// appropriate error code. +Error mergeTypeRecords(MergingTypeTableBuilder &Dest, + SmallVectorImpl<TypeIndex> &SourceToDest, + const CVTypeArray &Types); + +/// Merge one set of id records into another. This method assumes +/// that all records are id records, and there are no Type records present. +/// However, since Id records can refer back to Type records, this method +/// assumes that the referenced type records have also been merged into +/// another type stream (for example using the above method), and accepts +/// the mapping from source to dest for that stream so that it can re-write +/// the type record mappings accordingly. +/// +/// \param Dest The table to store the re-written id records into. +/// +/// \param Types The mapping to use for the type records that these id +/// records refer to. +/// +/// \param SourceToDest A vector, indexed by the TypeIndex in the source +/// id stream, that contains the index of the corresponding id record +/// in the destination stream. +/// +/// \param Ids The collection of id records to merge in. +/// +/// \returns Error::success() if the operation succeeded, otherwise an +/// appropriate error code. +Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types, + SmallVectorImpl<TypeIndex> &SourceToDest, + const CVTypeArray &Ids); + +/// Merge a unified set of type and id records, splitting them into +/// separate output streams. +/// +/// \param DestIds The table to store the re-written id records into. +/// +/// \param DestTypes the table to store the re-written type records into. +/// +/// \param SourceToDest A vector, indexed by the TypeIndex in the source +/// id stream, that contains the index of the corresponding id record +/// in the destination stream. +/// +/// \param IdsAndTypes The collection of id records to merge in. +/// +/// \returns Error::success() if the operation succeeded, otherwise an +/// appropriate error code. +Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds, + MergingTypeTableBuilder &DestTypes, + SmallVectorImpl<TypeIndex> &SourceToDest, + const CVTypeArray &IdsAndTypes, + Optional<uint32_t> &PCHSignature); + +Error mergeTypeAndIdRecords(GlobalTypeTableBuilder &DestIds, + GlobalTypeTableBuilder &DestTypes, + SmallVectorImpl<TypeIndex> &SourceToDest, + const CVTypeArray &IdsAndTypes, + ArrayRef<GloballyHashedType> Hashes, + Optional<uint32_t> &PCHSignature); + +Error mergeTypeRecords(GlobalTypeTableBuilder &Dest, + SmallVectorImpl<TypeIndex> &SourceToDest, + const CVTypeArray &Types, + ArrayRef<GloballyHashedType> Hashes, + Optional<uint32_t> &PCHSignature); + +Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types, + SmallVectorImpl<TypeIndex> &SourceToDest, + const CVTypeArray &Ids, + ArrayRef<GloballyHashedType> Hashes); + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESTREAMMERGER_H diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h new file mode 100644 index 00000000..4f2e5deb --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h @@ -0,0 +1,37 @@ +//===- TypeSymbolEmitter.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESYMBOLEMITTER_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPESYMBOLEMITTER_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" + +namespace llvm { +class StringRef; + +namespace codeview { + +class TypeSymbolEmitter { +private: + TypeSymbolEmitter(const TypeSymbolEmitter &) = delete; + TypeSymbolEmitter &operator=(const TypeSymbolEmitter &) = delete; + +protected: + TypeSymbolEmitter() {} + +public: + virtual ~TypeSymbolEmitter() {} + +public: + virtual void writeUserDefinedType(TypeIndex TI, StringRef Name) = 0; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeTableCollection.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeTableCollection.h new file mode 100644 index 00000000..5cbe3400 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeTableCollection.h @@ -0,0 +1,42 @@ +//===- TypeTableCollection.h ---------------------------------- *- C++ --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H + +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/Support/StringSaver.h" + +#include <vector> + +namespace llvm { +namespace codeview { + +class TypeTableCollection : public TypeCollection { +public: + explicit TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records); + + Optional<TypeIndex> getFirst() override; + Optional<TypeIndex> getNext(TypeIndex Prev) override; + + CVType getType(TypeIndex Index) override; + StringRef getTypeName(TypeIndex Index) override; + bool contains(TypeIndex Index) override; + uint32_t size() override; + uint32_t capacity() override; + +private: + BumpPtrAllocator Allocator; + StringSaver NameStorage; + std::vector<StringRef> Names; + ArrayRef<ArrayRef<uint8_t>> Records; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h new file mode 100644 index 00000000..fb0b579d --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h @@ -0,0 +1,121 @@ +//===- TypeVisitorCallbackPipeline.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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 visitTypeBegin(CVType &Record, TypeIndex Index) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitTypeBegin(Record, Index)) + return EC; + } + return Error::success(); + } + + Error visitTypeEnd(CVType &Record) override { + for (auto Visitor : Pipeline) { + if (auto EC = Visitor->visitTypeEnd(Record)) + 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/CodeViewTypes.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/clang-r353983/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h new file mode 100644 index 00000000..33f8b1f2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h @@ -0,0 +1,70 @@ +//===- TypeVisitorCallbacks.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { + +class TypeVisitorCallbacks { +public: + virtual ~TypeVisitorCallbacks() = default; + + /// Action to take on unknown types. By default, they are ignored. + virtual Error visitUnknownType(CVType &Record) { return Error::success(); } + /// Paired begin/end actions for all types. Receives all record data, + /// including the fixed-length record prefix. visitTypeBegin() should return + /// the type of the Record, or an error if it cannot be determined. Exactly + /// one of the two visitTypeBegin methods will be called, depending on whether + /// records are being visited sequentially or randomly. An implementation + /// should be prepared to handle both (or assert if it can't handle random + /// access visitation). + virtual Error visitTypeBegin(CVType &Record) { return Error::success(); } + virtual Error visitTypeBegin(CVType &Record, TypeIndex Index) { + return Error::success(); + } + virtual Error visitTypeEnd(CVType &Record) { return Error::success(); } + + virtual Error visitUnknownMember(CVMemberRecord &Record) { + return Error::success(); + } + + virtual Error visitMemberBegin(CVMemberRecord &Record) { + return Error::success(); + } + + virtual Error visitMemberEnd(CVMemberRecord &Record) { + return Error::success(); + } + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) { \ + return Error::success(); \ + } +#define MEMBER_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 "llvm/DebugInfo/CodeView/CodeViewTypes.def" +#undef TYPE_RECORD +#undef TYPE_RECORD_ALIAS +#undef MEMBER_RECORD +#undef MEMBER_RECORD_ALIAS +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H |
