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 | |
| 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')
215 files changed, 22555 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 diff --git a/clang-r353983/include/llvm/DebugInfo/DIContext.h b/clang-r353983/include/llvm/DebugInfo/DIContext.h new file mode 100644 index 00000000..a41ab214 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DIContext.h @@ -0,0 +1,279 @@ +//===- DIContext.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 +// +//===----------------------------------------------------------------------===// +// +// This file defines DIContext, an abstract data structure that holds +// debug information data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DICONTEXT_H +#define LLVM_DEBUGINFO_DICONTEXT_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <string> +#include <tuple> +#include <utility> + +namespace llvm { + +/// A format-neutral container for source line information. +struct DILineInfo { + std::string FileName; + std::string FunctionName; + Optional<StringRef> Source; + uint32_t Line = 0; + uint32_t Column = 0; + uint32_t StartLine = 0; + + // DWARF-specific. + uint32_t Discriminator = 0; + + DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>") {} + + bool operator==(const DILineInfo &RHS) const { + return Line == RHS.Line && Column == RHS.Column && + FileName == RHS.FileName && FunctionName == RHS.FunctionName && + StartLine == RHS.StartLine && Discriminator == RHS.Discriminator; + } + + bool operator!=(const DILineInfo &RHS) const { + return !(*this == RHS); + } + + bool operator<(const DILineInfo &RHS) const { + return std::tie(FileName, FunctionName, Line, Column, StartLine, + Discriminator) < + std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column, + RHS.StartLine, RHS.Discriminator); + } + + explicit operator bool() const { return *this != DILineInfo(); } + + void dump(raw_ostream &OS) { + OS << "Line info: "; + if (FileName != "<invalid>") + OS << "file '" << FileName << "', "; + if (FunctionName != "<invalid>") + OS << "function '" << FunctionName << "', "; + OS << "line " << Line << ", "; + OS << "column " << Column << ", "; + OS << "start line " << StartLine << '\n'; + } +}; + +using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>; + +/// A format-neutral container for inlined code description. +class DIInliningInfo { + SmallVector<DILineInfo, 4> Frames; + +public: + DIInliningInfo() = default; + + const DILineInfo & getFrame(unsigned Index) const { + assert(Index < Frames.size()); + return Frames[Index]; + } + + DILineInfo *getMutableFrame(unsigned Index) { + assert(Index < Frames.size()); + return &Frames[Index]; + } + + uint32_t getNumberOfFrames() const { + return Frames.size(); + } + + void addFrame(const DILineInfo &Frame) { + Frames.push_back(Frame); + } + + void resize(unsigned i) { + Frames.resize(i); + } + +}; + +/// Container for description of a global variable. +struct DIGlobal { + std::string Name; + uint64_t Start = 0; + uint64_t Size = 0; + + DIGlobal() : Name("<invalid>") {} +}; + +/// A DINameKind is passed to name search methods to specify a +/// preference regarding the type of name resolution the caller wants. +enum class DINameKind { None, ShortName, LinkageName }; + +/// Controls which fields of DILineInfo container should be filled +/// with data. +struct DILineInfoSpecifier { + enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; + using FunctionNameKind = DINameKind; + + FileLineInfoKind FLIKind; + FunctionNameKind FNKind; + + DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default, + FunctionNameKind FNKind = FunctionNameKind::None) + : FLIKind(FLIKind), FNKind(FNKind) {} +}; + +/// This is just a helper to programmatically construct DIDumpType. +enum DIDumpTypeCounter { +#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \ + DIDT_ID_##ENUM_NAME, +#include "llvm/BinaryFormat/Dwarf.def" +#undef HANDLE_DWARF_SECTION + DIDT_ID_UUID, + DIDT_ID_Count +}; +static_assert(DIDT_ID_Count <= 32, "section types overflow storage"); + +/// Selects which debug sections get dumped. +enum DIDumpType : unsigned { + DIDT_Null, + DIDT_All = ~0U, +#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \ + DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME, +#include "llvm/BinaryFormat/Dwarf.def" +#undef HANDLE_DWARF_SECTION + DIDT_UUID = 1 << DIDT_ID_UUID, +}; + +/// Container for dump options that control which debug information will be +/// dumped. +struct DIDumpOptions { + unsigned DumpType = DIDT_All; + unsigned RecurseDepth = -1U; + uint16_t Version = 0; // DWARF version to assume when extracting. + uint8_t AddrSize = 4; // Address byte size to assume when extracting. + bool ShowAddresses = true; + bool ShowChildren = false; + bool ShowParents = false; + bool ShowForm = false; + bool SummarizeTypes = false; + bool Verbose = false; + bool DisplayRawContents = false; + + /// Return default option set for printing a single DIE without children. + static DIDumpOptions getForSingleDIE() { + DIDumpOptions Opts; + Opts.RecurseDepth = 0; + return Opts; + } + + /// Return the options with RecurseDepth set to 0 unless explicitly required. + DIDumpOptions noImplicitRecursion() const { + DIDumpOptions Opts = *this; + if (RecurseDepth == -1U && !ShowChildren) + Opts.RecurseDepth = 0; + return Opts; + } +}; + +class DIContext { +public: + enum DIContextKind { + CK_DWARF, + CK_PDB + }; + + DIContext(DIContextKind K) : Kind(K) {} + virtual ~DIContext() = default; + + DIContextKind getKind() const { return Kind; } + + virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0; + + virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) { + // No verifier? Just say things went well. + return true; + } + + virtual DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, + uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + +private: + const DIContextKind Kind; +}; + +/// An inferface for inquiring the load address of a loaded object file +/// to be used by the DIContext implementations when applying relocations +/// on the fly. +class LoadedObjectInfo { +protected: + LoadedObjectInfo() = default; + LoadedObjectInfo(const LoadedObjectInfo &) = default; + +public: + virtual ~LoadedObjectInfo() = default; + + /// Obtain the Load Address of a section by SectionRef. + /// + /// Calculate the address of the given section. + /// The section need not be present in the local address space. The addresses + /// need to be consistent with the addresses used to query the DIContext and + /// the output of this function should be deterministic, i.e. repeated calls + /// with the same Sec should give the same address. + virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const { + return 0; + } + + /// If conveniently available, return the content of the given Section. + /// + /// When the section is available in the local address space, in relocated + /// (loaded) form, e.g. because it was relocated by a JIT for execution, this + /// function should provide the contents of said section in `Data`. If the + /// loaded section is not available, or the cost of retrieving it would be + /// prohibitive, this function should return false. In that case, relocations + /// will be read from the local (unrelocated) object file and applied on the + /// fly. Note that this method is used purely for optimzation purposes in the + /// common case of JITting in the local address space, so returning false + /// should always be correct. + virtual bool getLoadedSectionContents(const object::SectionRef &Sec, + StringRef &Data) const { + return false; + } + + // FIXME: This is untested and unused anywhere in the LLVM project, it's + // used/needed by Julia (an external project). It should have some coverage + // (at least tests, but ideally example functionality). + /// Obtain a copy of this LoadedObjectInfo. + virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0; +}; + +template <typename Derived, typename Base = LoadedObjectInfo> +struct LoadedObjectInfoHelper : Base { +protected: + LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default; + LoadedObjectInfoHelper() = default; + +public: + template <typename... Ts> + LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {} + + std::unique_ptr<llvm::LoadedObjectInfo> clone() const override { + return llvm::make_unique<Derived>(static_cast<const Derived &>(*this)); + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DICONTEXT_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h new file mode 100644 index 00000000..ccf2891c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -0,0 +1,183 @@ +//===- DWARFAbbreviationDeclaration.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_DWARFABBREVIATIONDECLARATION_H +#define LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/Support/DataExtractor.h" +#include <cassert> +#include <cstddef> +#include <cstdint> + +namespace llvm { + +class DWARFFormValue; +class DWARFUnit; +class raw_ostream; + +class DWARFAbbreviationDeclaration { +public: + struct AttributeSpec { + AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value) + : Attr(A), Form(F), Value(Value) { + assert(isImplicitConst()); + } + AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<uint8_t> ByteSize) + : Attr(A), Form(F) { + assert(!isImplicitConst()); + this->ByteSize.HasByteSize = ByteSize.hasValue(); + if (this->ByteSize.HasByteSize) + this->ByteSize.ByteSize = *ByteSize; + } + + dwarf::Attribute Attr; + dwarf::Form Form; + + private: + /// The following field is used for ByteSize for non-implicit_const + /// attributes and as value for implicit_const ones, indicated by + /// Form == DW_FORM_implicit_const. + /// The following cases are distinguished: + /// * Form != DW_FORM_implicit_const and HasByteSize is true: + /// ByteSize contains the fixed size in bytes for the Form in this + /// object. + /// * Form != DW_FORM_implicit_const and HasByteSize is false: + /// byte size of Form either varies according to the DWARFUnit + /// that it is contained in or the value size varies and must be + /// decoded from the debug information in order to determine its size. + /// * Form == DW_FORM_implicit_const: + /// Value contains value for the implicit_const attribute. + struct ByteSizeStorage { + bool HasByteSize; + uint8_t ByteSize; + }; + union { + ByteSizeStorage ByteSize; + int64_t Value; + }; + + public: + bool isImplicitConst() const { + return Form == dwarf::DW_FORM_implicit_const; + } + + int64_t getImplicitConstValue() const { + assert(isImplicitConst()); + return Value; + } + + /// Get the fixed byte size of this Form if possible. This function might + /// use the DWARFUnit to calculate the size of the Form, like for + /// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for + /// the ByteSize member. + Optional<int64_t> getByteSize(const DWARFUnit &U) const; + }; + using AttributeSpecVector = SmallVector<AttributeSpec, 8>; + + DWARFAbbreviationDeclaration(); + + uint32_t getCode() const { return Code; } + uint8_t getCodeByteSize() const { return CodeByteSize; } + dwarf::Tag getTag() const { return Tag; } + bool hasChildren() const { return HasChildren; } + + using attr_iterator_range = + iterator_range<AttributeSpecVector::const_iterator>; + + attr_iterator_range attributes() const { + return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); + } + + dwarf::Form getFormByIndex(uint32_t idx) const { + assert(idx < AttributeSpecs.size()); + return AttributeSpecs[idx].Form; + } + + size_t getNumAttributes() const { + return AttributeSpecs.size(); + } + + dwarf::Attribute getAttrByIndex(uint32_t idx) const { + assert(idx < AttributeSpecs.size()); + return AttributeSpecs[idx].Attr; + } + + /// Get the index of the specified attribute. + /// + /// Searches the this abbreviation declaration for the index of the specified + /// attribute. + /// + /// \param attr DWARF attribute to search for. + /// \returns Optional index of the attribute if found, None otherwise. + Optional<uint32_t> findAttributeIndex(dwarf::Attribute attr) const; + + /// Extract a DWARF form value from a DIE specified by DIE offset. + /// + /// Extract an attribute value for a DWARFUnit given the DIE offset and the + /// attribute. + /// + /// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation + /// code in the .debug_info data. + /// \param Attr DWARF attribute to search for. + /// \param U the DWARFUnit the contains the DIE. + /// \returns Optional DWARF form value if the attribute was extracted. + Optional<DWARFFormValue> getAttributeValue(const uint32_t DIEOffset, + const dwarf::Attribute Attr, + const DWARFUnit &U) const; + + bool extract(DataExtractor Data, uint32_t* OffsetPtr); + void dump(raw_ostream &OS) const; + + // Return an optional byte size of all attribute data in this abbreviation + // if a constant byte size can be calculated given a DWARFUnit. This allows + // DWARF parsing to be faster as many DWARF DIEs have a fixed byte size. + Optional<size_t> getFixedAttributesByteSize(const DWARFUnit &U) const; + +private: + void clear(); + + /// A helper structure that can quickly determine the size in bytes of an + /// abbreviation declaration. + struct FixedSizeInfo { + /// The fixed byte size for fixed size forms. + uint16_t NumBytes = 0; + /// Number of DW_FORM_address forms in this abbrevation declaration. + uint8_t NumAddrs = 0; + /// Number of DW_FORM_ref_addr forms in this abbrevation declaration. + uint8_t NumRefAddrs = 0; + /// Number of 4 byte in DWARF32 and 8 byte in DWARF64 forms. + uint8_t NumDwarfOffsets = 0; + + FixedSizeInfo() = default; + + /// Calculate the fixed size in bytes given a DWARFUnit. + /// + /// \param U the DWARFUnit to use when determing the byte size. + /// \returns the size in bytes for all attribute data in this abbreviation. + /// The returned size does not include bytes for the ULEB128 abbreviation + /// code + size_t getByteSize(const DWARFUnit &U) const; + }; + + uint32_t Code; + dwarf::Tag Tag; + uint8_t CodeByteSize; + bool HasChildren; + AttributeSpecVector AttributeSpecs; + /// If this abbreviation has a fixed byte size then FixedAttributeSize member + /// variable below will have a value. + Optional<FixedSizeInfo> FixedAttributeSize; +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h new file mode 100644 index 00000000..0f09a595 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -0,0 +1,599 @@ +//===- DWARFAcceleratorTable.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_DWARFACCELERATORTABLE_H +#define LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include <cstdint> +#include <utility> + +namespace llvm { + +class raw_ostream; +class ScopedPrinter; + +/// The accelerator tables are designed to allow efficient random access +/// (using a symbol name as a key) into debug info by providing an index of the +/// debug info DIEs. This class implements the common functionality of Apple and +/// DWARF 5 accelerator tables. +/// TODO: Generalize the rest of the AppleAcceleratorTable interface and move it +/// to this class. +class DWARFAcceleratorTable { +protected: + DWARFDataExtractor AccelSection; + DataExtractor StringSection; + +public: + /// An abstract class representing a single entry in the accelerator tables. + class Entry { + protected: + SmallVector<DWARFFormValue, 3> Values; + + Entry() = default; + + // Make these protected so only (final) subclasses can be copied around. + Entry(const Entry &) = default; + Entry(Entry &&) = default; + Entry &operator=(const Entry &) = default; + Entry &operator=(Entry &&) = default; + ~Entry() = default; + + + public: + /// Returns the Offset of the Compilation Unit associated with this + /// Accelerator Entry or None if the Compilation Unit offset is not recorded + /// in this Accelerator Entry. + virtual Optional<uint64_t> getCUOffset() const = 0; + + /// Returns the Tag of the Debug Info Entry associated with this + /// Accelerator Entry or None if the Tag is not recorded in this + /// Accelerator Entry. + virtual Optional<dwarf::Tag> getTag() const = 0; + + /// Returns the raw values of fields in the Accelerator Entry. In general, + /// these can only be interpreted with the help of the metadata in the + /// owning Accelerator Table. + ArrayRef<DWARFFormValue> getValues() const { return Values; } + }; + + DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection, + DataExtractor StringSection) + : AccelSection(AccelSection), StringSection(StringSection) {} + virtual ~DWARFAcceleratorTable(); + + virtual llvm::Error extract() = 0; + virtual void dump(raw_ostream &OS) const = 0; + + DWARFAcceleratorTable(const DWARFAcceleratorTable &) = delete; + void operator=(const DWARFAcceleratorTable &) = delete; +}; + +/// This implements the Apple accelerator table format, a precursor of the +/// DWARF 5 accelerator table format. +class AppleAcceleratorTable : public DWARFAcceleratorTable { + struct Header { + uint32_t Magic; + uint16_t Version; + uint16_t HashFunction; + uint32_t BucketCount; + uint32_t HashCount; + uint32_t HeaderDataLength; + + void dump(ScopedPrinter &W) const; + }; + + struct HeaderData { + using AtomType = uint16_t; + using Form = dwarf::Form; + + uint32_t DIEOffsetBase; + SmallVector<std::pair<AtomType, Form>, 3> Atoms; + + Optional<uint64_t> extractOffset(Optional<DWARFFormValue> Value) const; + }; + + struct Header Hdr; + struct HeaderData HdrData; + bool IsValid = false; + + /// Returns true if we should continue scanning for entries or false if we've + /// reached the last (sentinel) entry of encountered a parsing error. + bool dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms, + uint32_t *DataOffset) const; + +public: + /// Apple-specific implementation of an Accelerator Entry. + class Entry final : public DWARFAcceleratorTable::Entry { + const HeaderData *HdrData = nullptr; + + Entry(const HeaderData &Data); + Entry() = default; + + void extract(const AppleAcceleratorTable &AccelTable, uint32_t *Offset); + + public: + Optional<uint64_t> getCUOffset() const override; + + /// Returns the Section Offset of the Debug Info Entry associated with this + /// Accelerator Entry or None if the DIE offset is not recorded in this + /// Accelerator Entry. The returned offset is relative to the start of the + /// Section containing the DIE. + Optional<uint64_t> getDIESectionOffset() const; + + Optional<dwarf::Tag> getTag() const override; + + /// Returns the value of the Atom in this Accelerator Entry, if the Entry + /// contains such Atom. + Optional<DWARFFormValue> lookup(HeaderData::AtomType Atom) const; + + friend class AppleAcceleratorTable; + friend class ValueIterator; + }; + + class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> { + const AppleAcceleratorTable *AccelTable = nullptr; + Entry Current; ///< The current entry. + unsigned DataOffset = 0; ///< Offset into the section. + unsigned Data = 0; ///< Current data entry. + unsigned NumData = 0; ///< Number of data entries. + + /// Advance the iterator. + void Next(); + public: + /// Construct a new iterator for the entries at \p DataOffset. + ValueIterator(const AppleAcceleratorTable &AccelTable, unsigned DataOffset); + /// End marker. + ValueIterator() = default; + + const Entry &operator*() const { return Current; } + ValueIterator &operator++() { Next(); return *this; } + ValueIterator operator++(int) { + ValueIterator I = *this; + Next(); + return I; + } + friend bool operator==(const ValueIterator &A, const ValueIterator &B) { + return A.NumData == B.NumData && A.DataOffset == B.DataOffset; + } + friend bool operator!=(const ValueIterator &A, const ValueIterator &B) { + return !(A == B); + } + }; + + AppleAcceleratorTable(const DWARFDataExtractor &AccelSection, + DataExtractor StringSection) + : DWARFAcceleratorTable(AccelSection, StringSection) {} + + llvm::Error extract() override; + uint32_t getNumBuckets(); + uint32_t getNumHashes(); + uint32_t getSizeHdr(); + uint32_t getHeaderDataLength(); + + /// Return the Atom description, which can be used to interpret the raw values + /// of the Accelerator Entries in this table. + ArrayRef<std::pair<HeaderData::AtomType, HeaderData::Form>> getAtomsDesc(); + bool validateForms(); + + /// Return information related to the DWARF DIE we're looking for when + /// performing a lookup by name. + /// + /// \param HashDataOffset an offset into the hash data table + /// \returns <DieOffset, DieTag> + /// DieOffset is the offset into the .debug_info section for the DIE + /// related to the input hash data offset. + /// DieTag is the tag of the DIE + std::pair<uint32_t, dwarf::Tag> readAtoms(uint32_t &HashDataOffset); + void dump(raw_ostream &OS) const override; + + /// Look up all entries in the accelerator table matching \c Key. + iterator_range<ValueIterator> equal_range(StringRef Key) const; +}; + +/// .debug_names section consists of one or more units. Each unit starts with a +/// header, which is followed by a list of compilation units, local and foreign +/// type units. +/// +/// These may be followed by an (optional) hash lookup table, which consists of +/// an array of buckets and hashes similar to the apple tables above. The only +/// difference is that the hashes array is 1-based, and consequently an empty +/// bucket is denoted by 0 and not UINT32_MAX. +/// +/// Next is the name table, which consists of an array of names and array of +/// entry offsets. This is different from the apple tables, which store names +/// next to the actual entries. +/// +/// The structure of the entries is described by an abbreviations table, which +/// comes after the name table. Unlike the apple tables, which have a uniform +/// entry structure described in the header, each .debug_names entry may have +/// different index attributes (DW_IDX_???) attached to it. +/// +/// The last segment consists of a list of entries, which is a 0-terminated list +/// referenced by the name table and interpreted with the help of the +/// abbreviation table. +class DWARFDebugNames : public DWARFAcceleratorTable { + /// The fixed-size part of a Dwarf 5 Name Index header + struct HeaderPOD { + uint32_t UnitLength; + uint16_t Version; + uint16_t Padding; + uint32_t CompUnitCount; + uint32_t LocalTypeUnitCount; + uint32_t ForeignTypeUnitCount; + uint32_t BucketCount; + uint32_t NameCount; + uint32_t AbbrevTableSize; + uint32_t AugmentationStringSize; + }; + +public: + class NameIndex; + class NameIterator; + class ValueIterator; + + /// Dwarf 5 Name Index header. + struct Header : public HeaderPOD { + SmallString<8> AugmentationString; + + Error extract(const DWARFDataExtractor &AS, uint32_t *Offset); + void dump(ScopedPrinter &W) const; + }; + + /// Index attribute and its encoding. + struct AttributeEncoding { + dwarf::Index Index; + dwarf::Form Form; + + constexpr AttributeEncoding(dwarf::Index Index, dwarf::Form Form) + : Index(Index), Form(Form) {} + + friend bool operator==(const AttributeEncoding &LHS, + const AttributeEncoding &RHS) { + return LHS.Index == RHS.Index && LHS.Form == RHS.Form; + } + }; + + /// Abbreviation describing the encoding of Name Index entries. + struct Abbrev { + uint32_t Code; ///< Abbreviation code + dwarf::Tag Tag; ///< Dwarf Tag of the described entity. + std::vector<AttributeEncoding> Attributes; ///< List of index attributes. + + Abbrev(uint32_t Code, dwarf::Tag Tag, + std::vector<AttributeEncoding> Attributes) + : Code(Code), Tag(Tag), Attributes(std::move(Attributes)) {} + + void dump(ScopedPrinter &W) const; + }; + + /// DWARF v5-specific implementation of an Accelerator Entry. + class Entry final : public DWARFAcceleratorTable::Entry { + const NameIndex *NameIdx; + const Abbrev *Abbr; + + Entry(const NameIndex &NameIdx, const Abbrev &Abbr); + + public: + Optional<uint64_t> getCUOffset() const override; + Optional<dwarf::Tag> getTag() const override { return tag(); } + + /// Returns the Index into the Compilation Unit list of the owning Name + /// Index or None if this Accelerator Entry does not have an associated + /// Compilation Unit. It is up to the user to verify that the returned Index + /// is valid in the owning NameIndex (or use getCUOffset(), which will + /// handle that check itself). Note that entries in NameIndexes which index + /// just a single Compilation Unit are implicitly associated with that unit, + /// so this function will return 0 even without an explicit + /// DW_IDX_compile_unit attribute. + Optional<uint64_t> getCUIndex() const; + + /// .debug_names-specific getter, which always succeeds (DWARF v5 index + /// entries always have a tag). + dwarf::Tag tag() const { return Abbr->Tag; } + + /// Returns the Offset of the DIE within the containing CU or TU. + Optional<uint64_t> getDIEUnitOffset() const; + + /// Return the Abbreviation that can be used to interpret the raw values of + /// this Accelerator Entry. + const Abbrev &getAbbrev() const { return *Abbr; } + + /// Returns the value of the Index Attribute in this Accelerator Entry, if + /// the Entry contains such Attribute. + Optional<DWARFFormValue> lookup(dwarf::Index Index) const; + + void dump(ScopedPrinter &W) const; + + friend class NameIndex; + friend class ValueIterator; + }; + + /// Error returned by NameIndex::getEntry to report it has reached the end of + /// the entry list. + class SentinelError : public ErrorInfo<SentinelError> { + public: + static char ID; + + void log(raw_ostream &OS) const override { OS << "Sentinel"; } + std::error_code convertToErrorCode() const override; + }; + +private: + /// DenseMapInfo for struct Abbrev. + struct AbbrevMapInfo { + static Abbrev getEmptyKey(); + static Abbrev getTombstoneKey(); + static unsigned getHashValue(uint32_t Code) { + return DenseMapInfo<uint32_t>::getHashValue(Code); + } + static unsigned getHashValue(const Abbrev &Abbr) { + return getHashValue(Abbr.Code); + } + static bool isEqual(uint32_t LHS, const Abbrev &RHS) { + return LHS == RHS.Code; + } + static bool isEqual(const Abbrev &LHS, const Abbrev &RHS) { + return LHS.Code == RHS.Code; + } + }; + +public: + /// A single entry in the Name Table (Dwarf 5 sect. 6.1.1.4.6) of the Name + /// Index. + class NameTableEntry { + DataExtractor StrData; + + uint32_t Index; + uint32_t StringOffset; + uint32_t EntryOffset; + + public: + NameTableEntry(const DataExtractor &StrData, uint32_t Index, + uint32_t StringOffset, uint32_t EntryOffset) + : StrData(StrData), Index(Index), StringOffset(StringOffset), + EntryOffset(EntryOffset) {} + + /// Return the index of this name in the parent Name Index. + uint32_t getIndex() const { return Index; } + + /// Returns the offset of the name of the described entities. + uint32_t getStringOffset() const { return StringOffset; } + + /// Return the string referenced by this name table entry or nullptr if the + /// string offset is not valid. + const char *getString() const { + uint32_t Off = StringOffset; + return StrData.getCStr(&Off); + } + + /// Returns the offset of the first Entry in the list. + uint32_t getEntryOffset() const { return EntryOffset; } + }; + + /// Represents a single accelerator table within the Dwarf 5 .debug_names + /// section. + class NameIndex { + DenseSet<Abbrev, AbbrevMapInfo> Abbrevs; + struct Header Hdr; + const DWARFDebugNames &Section; + + // Base of the whole unit and of various important tables, as offsets from + // the start of the section. + uint32_t Base; + uint32_t CUsBase; + uint32_t BucketsBase; + uint32_t HashesBase; + uint32_t StringOffsetsBase; + uint32_t EntryOffsetsBase; + uint32_t EntriesBase; + + void dumpCUs(ScopedPrinter &W) const; + void dumpLocalTUs(ScopedPrinter &W) const; + void dumpForeignTUs(ScopedPrinter &W) const; + void dumpAbbreviations(ScopedPrinter &W) const; + bool dumpEntry(ScopedPrinter &W, uint32_t *Offset) const; + void dumpName(ScopedPrinter &W, const NameTableEntry &NTE, + Optional<uint32_t> Hash) const; + void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const; + + Expected<AttributeEncoding> extractAttributeEncoding(uint32_t *Offset); + + Expected<std::vector<AttributeEncoding>> + extractAttributeEncodings(uint32_t *Offset); + + Expected<Abbrev> extractAbbrev(uint32_t *Offset); + + public: + NameIndex(const DWARFDebugNames &Section, uint32_t Base) + : Section(Section), Base(Base) {} + + /// Reads offset of compilation unit CU. CU is 0-based. + uint32_t getCUOffset(uint32_t CU) const; + uint32_t getCUCount() const { return Hdr.CompUnitCount; } + + /// Reads offset of local type unit TU, TU is 0-based. + uint32_t getLocalTUOffset(uint32_t TU) const; + uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; } + + /// Reads signature of foreign type unit TU. TU is 0-based. + uint64_t getForeignTUSignature(uint32_t TU) const; + uint32_t getForeignTUCount() const { return Hdr.ForeignTypeUnitCount; } + + /// Reads an entry in the Bucket Array for the given Bucket. The returned + /// value is a (1-based) index into the Names, StringOffsets and + /// EntryOffsets arrays. The input Bucket index is 0-based. + uint32_t getBucketArrayEntry(uint32_t Bucket) const; + uint32_t getBucketCount() const { return Hdr.BucketCount; } + + /// Reads an entry in the Hash Array for the given Index. The input Index + /// is 1-based. + uint32_t getHashArrayEntry(uint32_t Index) const; + + /// Reads an entry in the Name Table for the given Index. The Name Table + /// consists of two arrays -- String Offsets and Entry Offsets. The returned + /// offsets are relative to the starts of respective sections. Input Index + /// is 1-based. + NameTableEntry getNameTableEntry(uint32_t Index) const; + + uint32_t getNameCount() const { return Hdr.NameCount; } + + const DenseSet<Abbrev, AbbrevMapInfo> &getAbbrevs() const { + return Abbrevs; + } + + Expected<Entry> getEntry(uint32_t *Offset) const; + + /// Look up all entries in this Name Index matching \c Key. + iterator_range<ValueIterator> equal_range(StringRef Key) const; + + NameIterator begin() const { return NameIterator(this, 1); } + NameIterator end() const { return NameIterator(this, getNameCount() + 1); } + + llvm::Error extract(); + uint32_t getUnitOffset() const { return Base; } + uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; } + void dump(ScopedPrinter &W) const; + + friend class DWARFDebugNames; + }; + + class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> { + + /// The Name Index we are currently iterating through. The implementation + /// relies on the fact that this can also be used as an iterator into the + /// "NameIndices" vector in the Accelerator section. + const NameIndex *CurrentIndex = nullptr; + + /// Whether this is a local iterator (searches in CurrentIndex only) or not + /// (searches all name indices). + bool IsLocal; + + Optional<Entry> CurrentEntry; + unsigned DataOffset = 0; ///< Offset into the section. + std::string Key; ///< The Key we are searching for. + Optional<uint32_t> Hash; ///< Hash of Key, if it has been computed. + + bool getEntryAtCurrentOffset(); + Optional<uint32_t> findEntryOffsetInCurrentIndex(); + bool findInCurrentIndex(); + void searchFromStartOfCurrentIndex(); + void next(); + + /// Set the iterator to the "end" state. + void setEnd() { *this = ValueIterator(); } + + public: + /// Create a "begin" iterator for looping over all entries in the + /// accelerator table matching Key. The iterator will run through all Name + /// Indexes in the section in sequence. + ValueIterator(const DWARFDebugNames &AccelTable, StringRef Key); + + /// Create a "begin" iterator for looping over all entries in a specific + /// Name Index. Other indices in the section will not be visited. + ValueIterator(const NameIndex &NI, StringRef Key); + + /// End marker. + ValueIterator() = default; + + const Entry &operator*() const { return *CurrentEntry; } + ValueIterator &operator++() { + next(); + return *this; + } + ValueIterator operator++(int) { + ValueIterator I = *this; + next(); + return I; + } + + friend bool operator==(const ValueIterator &A, const ValueIterator &B) { + return A.CurrentIndex == B.CurrentIndex && A.DataOffset == B.DataOffset; + } + friend bool operator!=(const ValueIterator &A, const ValueIterator &B) { + return !(A == B); + } + }; + + class NameIterator { + + /// The Name Index we are iterating through. + const NameIndex *CurrentIndex; + + /// The current name in the Name Index. + uint32_t CurrentName; + + void next() { + assert(CurrentName <= CurrentIndex->getNameCount()); + ++CurrentName; + } + + public: + using iterator_category = std::input_iterator_tag; + using value_type = NameTableEntry; + using difference_type = uint32_t; + using pointer = NameTableEntry *; + using reference = NameTableEntry; // We return entries by value. + + /// Creates an iterator whose initial position is name CurrentName in + /// CurrentIndex. + NameIterator(const NameIndex *CurrentIndex, uint32_t CurrentName) + : CurrentIndex(CurrentIndex), CurrentName(CurrentName) {} + + NameTableEntry operator*() const { + return CurrentIndex->getNameTableEntry(CurrentName); + } + NameIterator &operator++() { + next(); + return *this; + } + NameIterator operator++(int) { + NameIterator I = *this; + next(); + return I; + } + + friend bool operator==(const NameIterator &A, const NameIterator &B) { + return A.CurrentIndex == B.CurrentIndex && A.CurrentName == B.CurrentName; + } + friend bool operator!=(const NameIterator &A, const NameIterator &B) { + return !(A == B); + } + }; + +private: + SmallVector<NameIndex, 0> NameIndices; + DenseMap<uint32_t, const NameIndex *> CUToNameIndex; + +public: + DWARFDebugNames(const DWARFDataExtractor &AccelSection, + DataExtractor StringSection) + : DWARFAcceleratorTable(AccelSection, StringSection) {} + + llvm::Error extract() override; + void dump(raw_ostream &OS) const override; + + /// Look up all entries in the accelerator table matching \c Key. + iterator_range<ValueIterator> equal_range(StringRef Key) const; + + using const_iterator = SmallVector<NameIndex, 0>::const_iterator; + const_iterator begin() const { return NameIndices.begin(); } + const_iterator end() const { return NameIndices.end(); } + + /// Return the Name Index covering the compile unit at CUOffset, or nullptr if + /// there is no Name Index covering that unit. + const NameIndex *getCUNameIndex(uint32_t CUOffset); +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h new file mode 100644 index 00000000..56d46c69 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h @@ -0,0 +1,67 @@ +//===- DWARFAddressRange.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_DWARF_DWARFADDRESSRANGE_H +#define LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H + +#include "llvm/DebugInfo/DIContext.h" +#include <cstdint> +#include <tuple> +#include <vector> + +namespace llvm { + +class raw_ostream; + +struct DWARFAddressRange { + uint64_t LowPC; + uint64_t HighPC; + uint64_t SectionIndex; + + DWARFAddressRange() = default; + + /// Used for unit testing. + DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0) + : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {} + + /// Returns true if LowPC is smaller or equal to HighPC. This accounts for + /// dead-stripped ranges. + bool valid() const { return LowPC <= HighPC; } + + /// Returns true if [LowPC, HighPC) intersects with [RHS.LowPC, RHS.HighPC). + bool intersects(const DWARFAddressRange &RHS) const { + assert(valid() && RHS.valid()); + // Empty ranges can't intersect. + if (LowPC == HighPC || RHS.LowPC == RHS.HighPC) + return false; + return LowPC < RHS.HighPC && RHS.LowPC < HighPC; + } + + /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC). + bool contains(const DWARFAddressRange &RHS) const { + assert(valid() && RHS.valid()); + return LowPC <= RHS.LowPC && RHS.HighPC <= HighPC; + } + + void dump(raw_ostream &OS, uint32_t AddressSize, + DIDumpOptions DumpOpts = {}) const; +}; + +static inline bool operator<(const DWARFAddressRange &LHS, + const DWARFAddressRange &RHS) { + return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC); +} + +raw_ostream &operator<<(raw_ostream &OS, const DWARFAddressRange &R); + +/// DWARFAddressRangesVector - represents a set of absolute address ranges. +using DWARFAddressRangesVector = std::vector<DWARFAddressRange>; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAttribute.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAttribute.h new file mode 100644 index 00000000..fc6f0a44 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFAttribute.h @@ -0,0 +1,55 @@ +//===- DWARFAttribute.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_DWARFATTRIBUTE_H +#define LLVM_DEBUGINFO_DWARFATTRIBUTE_H + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include <cstdint> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// Encapsulates a DWARF attribute value and all of the data required to +/// describe the attribute value. +/// +/// This class is designed to be used by clients that want to iterate across all +/// attributes in a DWARFDie. +struct DWARFAttribute { + /// The debug info/types offset for this attribute. + uint32_t Offset = 0; + /// The debug info/types section byte size of the data for this attribute. + uint32_t ByteSize = 0; + /// The attribute enumeration of this attribute. + dwarf::Attribute Attr; + /// The form and value for this attribute. + DWARFFormValue Value; + + DWARFAttribute(uint32_t O, dwarf::Attribute A = dwarf::Attribute(0), + dwarf::Form F = dwarf::Form(0)) : Attr(A), Value(F) {} + + bool isValid() const { + return Offset != 0 && Attr != dwarf::Attribute(0); + } + + explicit operator bool() const { + return isValid(); + } + + void clear() { + Offset = 0; + ByteSize = 0; + Attr = dwarf::Attribute(0); + Value = DWARFFormValue(); + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFATTRIBUTE_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h new file mode 100644 index 00000000..16b9bfb5 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h @@ -0,0 +1,38 @@ +//===- DWARFCompileUnit.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_DWARFCOMPILEUNIT_H +#define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H + +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" + +namespace llvm { + +class DWARFCompileUnit : public DWARFUnit { +public: + DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, + StringRef SS, const DWARFSection &SOS, + const DWARFSection *AOS, const DWARFSection &LS, bool LE, + bool IsDWO, const DWARFUnitVector &UnitVector) + : DWARFUnit(Context, Section, Header, DA, RS, LocSection, SS, SOS, AOS, + LS, LE, IsDWO, UnitVector) {} + + /// VTable anchor. + ~DWARFCompileUnit() override; + /// Dump this compile unit to \p OS. + void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override; + /// Enable LLVM-style RTTI. + static bool classof(const DWARFUnit *U) { return !U->isTypeUnit(); } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFContext.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFContext.h new file mode 100644 index 00000000..e4159278 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -0,0 +1,374 @@ +//===- DWARFContext.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_DWARF_DWARFCONTEXT_H +#define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H + +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" +#include "llvm/DebugInfo/DWARF/DWARFObject.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Host.h" +#include <cstdint> +#include <deque> +#include <map> +#include <memory> + +namespace llvm { + +class MCRegisterInfo; +class MemoryBuffer; +class raw_ostream; + +/// Used as a return value for a error callback passed to DWARF context. +/// Callback should return Halt if client application wants to stop +/// object parsing, or should return Continue otherwise. +enum class ErrorPolicy { Halt, Continue }; + +/// DWARFContext +/// This data structure is the top level entity that deals with dwarf debug +/// information parsing. The actual data is supplied through DWARFObj. +class DWARFContext : public DIContext { + DWARFUnitVector NormalUnits; + std::unique_ptr<DWARFUnitIndex> CUIndex; + std::unique_ptr<DWARFGdbIndex> GdbIndex; + std::unique_ptr<DWARFUnitIndex> TUIndex; + std::unique_ptr<DWARFDebugAbbrev> Abbrev; + std::unique_ptr<DWARFDebugLoc> Loc; + std::unique_ptr<DWARFDebugAranges> Aranges; + std::unique_ptr<DWARFDebugLine> Line; + std::unique_ptr<DWARFDebugFrame> DebugFrame; + std::unique_ptr<DWARFDebugFrame> EHFrame; + std::unique_ptr<DWARFDebugMacro> Macro; + std::unique_ptr<DWARFDebugNames> Names; + std::unique_ptr<AppleAcceleratorTable> AppleNames; + std::unique_ptr<AppleAcceleratorTable> AppleTypes; + std::unique_ptr<AppleAcceleratorTable> AppleNamespaces; + std::unique_ptr<AppleAcceleratorTable> AppleObjC; + + DWARFUnitVector DWOUnits; + std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; + std::unique_ptr<DWARFDebugLoclists> LocDWO; + + /// The maximum DWARF version of all units. + unsigned MaxVersion = 0; + + struct DWOFile { + object::OwningBinary<object::ObjectFile> File; + std::unique_ptr<DWARFContext> Context; + }; + StringMap<std::weak_ptr<DWOFile>> DWOFiles; + std::weak_ptr<DWOFile> DWP; + bool CheckedForDWP = false; + std::string DWPName; + + std::unique_ptr<MCRegisterInfo> RegInfo; + + /// Read compile units from the debug_info section (if necessary) + /// and type units from the debug_types sections (if necessary) + /// and store them in NormalUnits. + void parseNormalUnits(); + + /// Read compile units from the debug_info.dwo section (if necessary) + /// and type units from the debug_types.dwo section (if necessary) + /// and store them in DWOUnits. + /// If \p Lazy is true, set up to parse but don't actually parse them. + enum { EagerParse = false, LazyParse = true }; + void parseDWOUnits(bool Lazy = false); + + std::unique_ptr<const DWARFObject> DObj; + +public: + DWARFContext(std::unique_ptr<const DWARFObject> DObj, + std::string DWPName = ""); + ~DWARFContext(); + + DWARFContext(DWARFContext &) = delete; + DWARFContext &operator=(DWARFContext &) = delete; + + const DWARFObject &getDWARFObj() const { return *DObj; } + + static bool classof(const DIContext *DICtx) { + return DICtx->getKind() == CK_DWARF; + } + + /// Dump a textual representation to \p OS. If any \p DumpOffsets are present, + /// dump only the record at the specified offset. + void dump(raw_ostream &OS, DIDumpOptions DumpOpts, + std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets); + + void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override { + std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets; + dump(OS, DumpOpts, DumpOffsets); + } + + bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; + + using unit_iterator_range = DWARFUnitVector::iterator_range; + + /// Get units from .debug_info in this context. + unit_iterator_range info_section_units() { + parseNormalUnits(); + return unit_iterator_range(NormalUnits.begin(), + NormalUnits.begin() + + NormalUnits.getNumInfoUnits()); + } + + /// Get units from .debug_types in this context. + unit_iterator_range types_section_units() { + parseNormalUnits(); + return unit_iterator_range( + NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end()); + } + + /// Get compile units in this context. + unit_iterator_range compile_units() { return info_section_units(); } + + /// Get type units in this context. + unit_iterator_range type_units() { return types_section_units(); } + + /// Get all normal compile/type units in this context. + unit_iterator_range normal_units() { + parseNormalUnits(); + return unit_iterator_range(NormalUnits.begin(), NormalUnits.end()); + } + + /// Get units from .debug_info..dwo in the DWO context. + unit_iterator_range dwo_info_section_units() { + parseDWOUnits(); + return unit_iterator_range(DWOUnits.begin(), + DWOUnits.begin() + DWOUnits.getNumInfoUnits()); + } + + /// Get units from .debug_types.dwo in the DWO context. + unit_iterator_range dwo_types_section_units() { + parseDWOUnits(); + return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(), + DWOUnits.end()); + } + + /// Get compile units in the DWO context. + unit_iterator_range dwo_compile_units() { return dwo_info_section_units(); } + + /// Get type units in the DWO context. + unit_iterator_range dwo_type_units() { return dwo_types_section_units(); } + + /// Get all units in the DWO context. + unit_iterator_range dwo_units() { + parseDWOUnits(); + return unit_iterator_range(DWOUnits.begin(), DWOUnits.end()); + } + + /// Get the number of compile units in this context. + unsigned getNumCompileUnits() { + parseNormalUnits(); + return NormalUnits.getNumInfoUnits(); + } + + /// Get the number of type units in this context. + unsigned getNumTypeUnits() { + parseNormalUnits(); + return NormalUnits.getNumTypesUnits(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOCompileUnits() { + parseDWOUnits(); + return DWOUnits.getNumInfoUnits(); + } + + /// Get the number of type units in the DWO context. + unsigned getNumDWOTypeUnits() { + parseDWOUnits(); + return DWOUnits.getNumTypesUnits(); + } + + /// Get the unit at the specified index. + DWARFUnit *getUnitAtIndex(unsigned index) { + parseNormalUnits(); + return NormalUnits[index].get(); + } + + /// Get the unit at the specified index for the DWO units. + DWARFUnit *getDWOUnitAtIndex(unsigned index) { + parseDWOUnits(); + return DWOUnits[index].get(); + } + + DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); + + /// Return the compile unit that includes an offset (relative to .debug_info). + DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); + + /// Get a DIE given an exact offset. + DWARFDie getDIEForOffset(uint32_t Offset); + + unsigned getMaxVersion() { + // Ensure info units have been parsed to discover MaxVersion + info_section_units(); + return MaxVersion; + } + + unsigned getMaxDWOVersion() { + // Ensure DWO info units have been parsed to discover MaxVersion + dwo_info_section_units(); + return MaxVersion; + } + + void setMaxVersionIfGreater(unsigned Version) { + if (Version > MaxVersion) + MaxVersion = Version; + } + + const DWARFUnitIndex &getCUIndex(); + DWARFGdbIndex &getGdbIndex(); + const DWARFUnitIndex &getTUIndex(); + + /// Get a pointer to the parsed DebugAbbrev object. + const DWARFDebugAbbrev *getDebugAbbrev(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLoc *getDebugLoc(); + + /// Get a pointer to the parsed dwo abbreviations object. + const DWARFDebugAbbrev *getDebugAbbrevDWO(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLoclists *getDebugLocDWO(); + + /// Get a pointer to the parsed DebugAranges object. + const DWARFDebugAranges *getDebugAranges(); + + /// Get a pointer to the parsed frame information object. + const DWARFDebugFrame *getDebugFrame(); + + /// Get a pointer to the parsed eh frame information object. + const DWARFDebugFrame *getEHFrame(); + + /// Get a pointer to the parsed DebugMacro object. + const DWARFDebugMacro *getDebugMacro(); + + /// Get a reference to the parsed accelerator table object. + const DWARFDebugNames &getDebugNames(); + + /// Get a reference to the parsed accelerator table object. + const AppleAcceleratorTable &getAppleNames(); + + /// Get a reference to the parsed accelerator table object. + const AppleAcceleratorTable &getAppleTypes(); + + /// Get a reference to the parsed accelerator table object. + const AppleAcceleratorTable &getAppleNamespaces(); + + /// Get a reference to the parsed accelerator table object. + const AppleAcceleratorTable &getAppleObjC(); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + /// Report any parsing issues as warnings on stderr. + const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + /// Report any recoverable parsing problems using the callback. + Expected<const DWARFDebugLine::LineTable *> + getLineTableForUnit(DWARFUnit *U, + std::function<void(Error)> RecoverableErrorCallback); + + DataExtractor getStringExtractor() const { + return DataExtractor(DObj->getStringSection(), false, 0); + } + DataExtractor getLineStringExtractor() const { + return DataExtractor(DObj->getLineStringSection(), false, 0); + } + + /// Wraps the returned DIEs for a given address. + struct DIEsForAddress { + DWARFCompileUnit *CompileUnit = nullptr; + DWARFDie FunctionDIE; + DWARFDie BlockDIE; + explicit operator bool() const { return CompileUnit != nullptr; } + }; + + /// Get the compilation unit, the function DIE and lexical block DIE for the + /// given address where applicable. + DIEsForAddress getDIEsForAddress(uint64_t Address); + + DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + + bool isLittleEndian() const { return DObj->isLittleEndian(); } + static bool isSupportedVersion(unsigned version) { + return version == 2 || version == 3 || version == 4 || version == 5; + } + + std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath); + + const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); } + + /// Function used to handle default error reporting policy. Prints a error + /// message and returns Continue, so DWARF context ignores the error. + static ErrorPolicy defaultErrorHandler(Error E); + static std::unique_ptr<DWARFContext> + create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, + function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler, + std::string DWPName = ""); + + static std::unique_ptr<DWARFContext> + create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, + uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost); + + /// Loads register info for the architecture of the provided object file. + /// Improves readability of dumped DWARF expressions. Requires the caller to + /// have initialized the relevant target descriptions. + Error loadRegisterInfo(const object::ObjectFile &Obj); + + /// Get address size from CUs. + /// TODO: refactor compile_units() to make this const. + uint8_t getCUAddrSize(); + + /// Dump Error as warning message to stderr. + static void dumpWarning(Error Warning); + + Triple::ArchType getArch() const { + return getDWARFObj().getFile()->getArch(); + } + +private: + /// Return the compile unit which contains instruction with provided + /// address. + DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h new file mode 100644 index 00000000..7c2a159b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -0,0 +1,59 @@ +//===- DWARFDataExtractor.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_DWARFDATAEXTRACTOR_H +#define LLVM_DEBUGINFO_DWARFDATAEXTRACTOR_H + +#include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { +class DWARFObject; + +/// A DataExtractor (typically for an in-memory copy of an object-file section) +/// plus a relocation map for that section, if there is one. +class DWARFDataExtractor : public DataExtractor { + const DWARFObject *Obj = nullptr; + const DWARFSection *Section = nullptr; + +public: + /// Constructor for the normal case of extracting data from a DWARF section. + /// The DWARFSection's lifetime must be at least as long as the extractor's. + DWARFDataExtractor(const DWARFObject &Obj, const DWARFSection &Section, + bool IsLittleEndian, uint8_t AddressSize) + : DataExtractor(Section.Data, IsLittleEndian, AddressSize), Obj(&Obj), + Section(&Section) {} + + /// Constructor for cases when there are no relocations. + DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize) + : DataExtractor(Data, IsLittleEndian, AddressSize) {} + + /// Extracts a value and applies a relocation to the result if + /// one exists for the given offset. + uint64_t getRelocatedValue(uint32_t Size, uint32_t *Off, + uint64_t *SectionIndex = nullptr) const; + + /// Extracts an address-sized value and applies a relocation to the result if + /// one exists for the given offset. + uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const { + return getRelocatedValue(getAddressSize(), Off, SecIx); + } + + /// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding. + /// There is a DWARF encoding that uses a PC-relative adjustment. + /// For these values, \p AbsPosOffset is used to fix them, which should + /// reflect the absolute address of this pointer. + Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t Encoding, + uint64_t AbsPosOffset = 0) const; + + size_t size() const { return Section == nullptr ? 0 : Section->Data.size(); } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDATAEXTRACTOR_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h new file mode 100644 index 00000000..28fd8484 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -0,0 +1,87 @@ +//===- DWARFDebugAbbrev.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_DWARFDEBUGABBREV_H +#define LLVM_DEBUGINFO_DWARFDEBUGABBREV_H + +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/Support/DataExtractor.h" +#include <cstdint> +#include <map> +#include <vector> + +namespace llvm { + +class raw_ostream; + +class DWARFAbbreviationDeclarationSet { + uint32_t Offset; + /// Code of the first abbreviation, if all abbreviations in the set have + /// consecutive codes. UINT32_MAX otherwise. + uint32_t FirstAbbrCode; + std::vector<DWARFAbbreviationDeclaration> Decls; + + using const_iterator = + std::vector<DWARFAbbreviationDeclaration>::const_iterator; + +public: + DWARFAbbreviationDeclarationSet(); + + uint32_t getOffset() const { return Offset; } + void dump(raw_ostream &OS) const; + bool extract(DataExtractor Data, uint32_t *OffsetPtr); + + const DWARFAbbreviationDeclaration * + getAbbreviationDeclaration(uint32_t AbbrCode) const; + + const_iterator begin() const { + return Decls.begin(); + } + + const_iterator end() const { + return Decls.end(); + } + +private: + void clear(); +}; + +class DWARFDebugAbbrev { + using DWARFAbbreviationDeclarationSetMap = + std::map<uint64_t, DWARFAbbreviationDeclarationSet>; + + mutable DWARFAbbreviationDeclarationSetMap AbbrDeclSets; + mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos; + mutable Optional<DataExtractor> Data; + +public: + DWARFDebugAbbrev(); + + const DWARFAbbreviationDeclarationSet * + getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; + + void dump(raw_ostream &OS) const; + void parse() const; + void extract(DataExtractor Data); + + DWARFAbbreviationDeclarationSetMap::const_iterator begin() const { + parse(); + return AbbrDeclSets.begin(); + } + + DWARFAbbreviationDeclarationSetMap::const_iterator end() const { + return AbbrDeclSets.end(); + } + +private: + void clear(); +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGABBREV_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h new file mode 100644 index 00000000..a98bf282 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h @@ -0,0 +1,97 @@ +//===- DWARFDebugAddr.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_DWARFDEBUGADDR_H +#define LLVM_DEBUGINFO_DWARFDEBUGADDR_H + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <map> +#include <vector> + +namespace llvm { + +class Error; +class raw_ostream; + +/// A class representing an address table as specified in DWARF v5. +/// The table consists of a header followed by an array of address values from +/// .debug_addr section. +class DWARFDebugAddrTable { +public: + struct Header { + /// The total length of the entries for this table, not including the length + /// field itself. + uint32_t Length = 0; + /// The DWARF version number. + uint16_t Version = 5; + /// The size in bytes of an address on the target architecture. For + /// segmented addressing, this is the size of the offset portion of the + /// address. + uint8_t AddrSize; + /// The size in bytes of a segment selector on the target architecture. + /// If the target system uses a flat address space, this value is 0. + uint8_t SegSize = 0; + }; + +private: + dwarf::DwarfFormat Format; + uint32_t HeaderOffset; + Header HeaderData; + uint32_t DataSize = 0; + std::vector<uint64_t> Addrs; + +public: + void clear(); + + /// Extract an entire table, including all addresses. + Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr, + uint16_t Version, uint8_t AddrSize, + std::function<void(Error)> WarnCallback); + + uint32_t getHeaderOffset() const { return HeaderOffset; } + uint8_t getAddrSize() const { return HeaderData.AddrSize; } + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; + + /// Return the address based on a given index. + Expected<uint64_t> getAddrEntry(uint32_t Index) const; + + /// Return the size of the table header including the length + /// but not including the addresses. + uint8_t getHeaderSize() const { + switch (Format) { + case dwarf::DwarfFormat::DWARF32: + return 8; // 4 + 2 + 1 + 1 + case dwarf::DwarfFormat::DWARF64: + return 16; // 12 + 2 + 1 + 1 + } + llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64)"); + } + + /// Returns the length of this table, including the length field, or 0 if the + /// length has not been determined (e.g. because the table has not yet been + /// parsed, or there was a problem in parsing). + uint32_t getLength() const; + + /// Verify that the given length is valid for this table. + bool hasValidLength() const { return getLength() != 0; } + + /// Invalidate Length field to stop further processing. + void invalidateLength() { HeaderData.Length = 0; } + + /// Returns the length of the array of addresses. + uint32_t getDataSize() const; +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGADDR_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h new file mode 100644 index 00000000..5b6c578b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h @@ -0,0 +1,75 @@ +//===- DWARFDebugArangeSet.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_DWARFDEBUGARANGESET_H +#define LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/DataExtractor.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +class raw_ostream; + +class DWARFDebugArangeSet { +public: + struct Header { + /// The total length of the entries for that set, not including the length + /// field itself. + uint32_t Length; + /// The offset from the beginning of the .debug_info section of the + /// compilation unit entry referenced by the table. + uint32_t CuOffset; + /// The DWARF version number. + uint16_t Version; + /// The size in bytes of an address on the target architecture. For segmented + /// addressing, this is the size of the offset portion of the address. + uint8_t AddrSize; + /// The size in bytes of a segment descriptor on the target architecture. + /// If the target system uses a flat address space, this value is 0. + uint8_t SegSize; + }; + + struct Descriptor { + uint64_t Address; + uint64_t Length; + + uint64_t getEndAddress() const { return Address + Length; } + void dump(raw_ostream &OS, uint32_t AddressSize) const; + }; + +private: + using DescriptorColl = std::vector<Descriptor>; + using desc_iterator_range = iterator_range<DescriptorColl::const_iterator>; + + uint32_t Offset; + Header HeaderData; + DescriptorColl ArangeDescriptors; + +public: + DWARFDebugArangeSet() { clear(); } + + void clear(); + bool extract(DataExtractor data, uint32_t *offset_ptr); + void dump(raw_ostream &OS) const; + + uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } + + const Header &getHeader() const { return HeaderData; } + + desc_iterator_range descriptors() const { + return desc_iterator_range(ArangeDescriptors.begin(), + ArangeDescriptors.end()); + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h new file mode 100644 index 00000000..6d3af24f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h @@ -0,0 +1,88 @@ +//===- DWARFDebugAranges.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_DWARFDEBUGARANGES_H +#define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/DataExtractor.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +class DWARFContext; + +class DWARFDebugAranges { +public: + void generate(DWARFContext *CTX); + uint32_t findAddress(uint64_t Address) const; + +private: + void clear(); + void extract(DataExtractor DebugArangesData); + + /// Call appendRange multiple times and then call construct. + void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); + void construct(); + + struct Range { + explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL, + uint32_t CUOffset = -1U) + : LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {} + + void setHighPC(uint64_t HighPC) { + if (HighPC == -1ULL || HighPC <= LowPC) + Length = 0; + else + Length = HighPC - LowPC; + } + + uint64_t HighPC() const { + if (Length) + return LowPC + Length; + return -1ULL; + } + + bool containsAddress(uint64_t Address) const { + return LowPC <= Address && Address < HighPC(); + } + + bool operator<(const Range &other) const { + return LowPC < other.LowPC; + } + + uint64_t LowPC; /// Start of address range. + uint32_t Length; /// End of address range (not including this address). + uint32_t CUOffset; /// Offset of the compile unit or die. + }; + + struct RangeEndpoint { + uint64_t Address; + uint32_t CUOffset; + bool IsRangeStart; + + RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart) + : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {} + + bool operator<(const RangeEndpoint &Other) const { + return Address < Other.Address; + } + }; + + using RangeColl = std::vector<Range>; + using RangeCollIterator = RangeColl::const_iterator; + + std::vector<RangeEndpoint> Endpoints; + RangeColl Aranges; + DenseSet<uint32_t> ParsedCUOffsets; +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGARANGES_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h new file mode 100644 index 00000000..d960f4bc --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -0,0 +1,308 @@ +//===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- 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_DWARF_DWARFDEBUGFRAME_H +#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Triple.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/Support/Error.h" +#include <memory> +#include <vector> + +namespace llvm { + +class raw_ostream; + +namespace dwarf { + +/// Represent a sequence of Call Frame Information instructions that, when read +/// in order, construct a table mapping PC to frame state. This can also be +/// referred to as "CFI rules" in DWARF literature to avoid confusion with +/// computer programs in the broader sense, and in this context each instruction +/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5 +/// manual, "6.4.1 Structure of Call Frame Information". +class CFIProgram { +public: + typedef SmallVector<uint64_t, 2> Operands; + + /// An instruction consists of a DWARF CFI opcode and an optional sequence of + /// operands. If it refers to an expression, then this expression has its own + /// sequence of operations and operands handled separately by DWARFExpression. + struct Instruction { + Instruction(uint8_t Opcode) : Opcode(Opcode) {} + + uint8_t Opcode; + Operands Ops; + // Associated DWARF expression in case this instruction refers to one + Optional<DWARFExpression> Expression; + }; + + using InstrList = std::vector<Instruction>; + using iterator = InstrList::iterator; + using const_iterator = InstrList::const_iterator; + + iterator begin() { return Instructions.begin(); } + const_iterator begin() const { return Instructions.begin(); } + iterator end() { return Instructions.end(); } + const_iterator end() const { return Instructions.end(); } + + unsigned size() const { return (unsigned)Instructions.size(); } + bool empty() const { return Instructions.empty(); } + + CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, + Triple::ArchType Arch) + : CodeAlignmentFactor(CodeAlignmentFactor), + DataAlignmentFactor(DataAlignmentFactor), + Arch(Arch) {} + + /// Parse and store a sequence of CFI instructions from Data, + /// starting at *Offset and ending at EndOffset. *Offset is updated + /// to EndOffset upon successful parsing, or indicates the offset + /// where a problem occurred in case an error is returned. + Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset); + + void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, + unsigned IndentLevel = 1) const; + +private: + std::vector<Instruction> Instructions; + const uint64_t CodeAlignmentFactor; + const int64_t DataAlignmentFactor; + Triple::ArchType Arch; + + /// Convenience method to add a new instruction with the given opcode. + void addInstruction(uint8_t Opcode) { + Instructions.push_back(Instruction(Opcode)); + } + + /// Add a new single-operand instruction. + void addInstruction(uint8_t Opcode, uint64_t Operand1) { + Instructions.push_back(Instruction(Opcode)); + Instructions.back().Ops.push_back(Operand1); + } + + /// Add a new instruction that has two operands. + void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { + Instructions.push_back(Instruction(Opcode)); + Instructions.back().Ops.push_back(Operand1); + Instructions.back().Ops.push_back(Operand2); + } + + /// Types of operands to CFI instructions + /// In DWARF, this type is implicitly tied to a CFI instruction opcode and + /// thus this type doesn't need to be explictly written to the file (this is + /// not a DWARF encoding). The relationship of instrs to operand types can + /// be obtained from getOperandTypes() and is only used to simplify + /// instruction printing. + enum OperandType { + OT_Unset, + OT_None, + OT_Address, + OT_Offset, + OT_FactoredCodeOffset, + OT_SignedFactDataOffset, + OT_UnsignedFactDataOffset, + OT_Register, + OT_Expression + }; + + /// Retrieve the array describing the types of operands according to the enum + /// above. This is indexed by opcode. + static ArrayRef<OperandType[2]> getOperandTypes(); + + /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. + void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, + const Instruction &Instr, unsigned OperandIdx, + uint64_t Operand) const; +}; + +/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an +/// FDE. +class FrameEntry { +public: + enum FrameKind { FK_CIE, FK_FDE }; + + FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign, + int64_t DataAlign, Triple::ArchType Arch) + : Kind(K), Offset(Offset), Length(Length), + CFIs(CodeAlign, DataAlign, Arch) {} + + virtual ~FrameEntry() {} + + FrameKind getKind() const { return Kind; } + uint64_t getOffset() const { return Offset; } + uint64_t getLength() const { return Length; } + const CFIProgram &cfis() const { return CFIs; } + CFIProgram &cfis() { return CFIs; } + + /// Dump the instructions in this CFI fragment + virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + bool IsEH) const = 0; + +protected: + const FrameKind Kind; + + /// Offset of this entry in the section. + const uint64_t Offset; + + /// Entry length as specified in DWARF. + const uint64_t Length; + + CFIProgram CFIs; +}; + +/// DWARF Common Information Entry (CIE) +class CIE : public FrameEntry { +public: + // CIEs (and FDEs) are simply container classes, so the only sensible way to + // create them is by providing the full parsed contents in the constructor. + CIE(uint64_t Offset, uint64_t Length, uint8_t Version, + SmallString<8> Augmentation, uint8_t AddressSize, + uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, + int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, + SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, + uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality, + Optional<uint32_t> PersonalityEnc, Triple::ArchType Arch) + : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor, + DataAlignmentFactor, Arch), + Version(Version), Augmentation(std::move(Augmentation)), + AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), + CodeAlignmentFactor(CodeAlignmentFactor), + DataAlignmentFactor(DataAlignmentFactor), + ReturnAddressRegister(ReturnAddressRegister), + AugmentationData(std::move(AugmentationData)), + FDEPointerEncoding(FDEPointerEncoding), + LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality), + PersonalityEnc(PersonalityEnc) {} + + static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; } + + StringRef getAugmentationString() const { return Augmentation; } + uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } + int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } + uint8_t getVersion() const { return Version; } + uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; } + Optional<uint64_t> getPersonalityAddress() const { return Personality; } + Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; } + + uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; } + + uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } + + void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + bool IsEH) const override; + +private: + /// The following fields are defined in section 6.4.1 of the DWARF standard v4 + const uint8_t Version; + const SmallString<8> Augmentation; + const uint8_t AddressSize; + const uint8_t SegmentDescriptorSize; + const uint64_t CodeAlignmentFactor; + const int64_t DataAlignmentFactor; + const uint64_t ReturnAddressRegister; + + // The following are used when the CIE represents an EH frame entry. + const SmallString<8> AugmentationData; + const uint32_t FDEPointerEncoding; + const uint32_t LSDAPointerEncoding; + const Optional<uint64_t> Personality; + const Optional<uint32_t> PersonalityEnc; +}; + +/// DWARF Frame Description Entry (FDE) +class FDE : public FrameEntry { +public: + // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with + // an offset to the CIE (provided by parsing the FDE header). The CIE itself + // is obtained lazily once it's actually required. + FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, + uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, + Optional<uint64_t> LSDAAddress, Triple::ArchType Arch) + : FrameEntry(FK_FDE, Offset, Length, + Cie ? Cie->getCodeAlignmentFactor() : 0, + Cie ? Cie->getDataAlignmentFactor() : 0, + Arch), + LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation), + AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} + + ~FDE() override = default; + + const CIE *getLinkedCIE() const { return LinkedCIE; } + uint64_t getInitialLocation() const { return InitialLocation; } + uint64_t getAddressRange() const { return AddressRange; } + Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; } + + void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + bool IsEH) const override; + + static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } + +private: + /// The following fields are defined in section 6.4.1 of the DWARF standard v3 + const uint64_t LinkedCIEOffset; + const uint64_t InitialLocation; + const uint64_t AddressRange; + const CIE *LinkedCIE; + const Optional<uint64_t> LSDAAddress; +}; + +} // end namespace dwarf + +/// A parsed .debug_frame or .eh_frame section +class DWARFDebugFrame { + const Triple::ArchType Arch; + // True if this is parsing an eh_frame section. + const bool IsEH; + // Not zero for sane pointer values coming out of eh_frame + const uint64_t EHFrameAddress; + + std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries; + using iterator = pointee_iterator<decltype(Entries)::const_iterator>; + + /// Return the entry at the given offset or nullptr. + dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const; + +public: + // If IsEH is true, assume it is a .eh_frame section. Otherwise, + // it is a .debug_frame section. EHFrameAddress should be different + // than zero for correct parsing of .eh_frame addresses when they + // use a PC-relative encoding. + DWARFDebugFrame(Triple::ArchType Arch, + bool IsEH = false, uint64_t EHFrameAddress = 0); + ~DWARFDebugFrame(); + + /// Dump the section data into the given stream. + void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + Optional<uint64_t> Offset) const; + + /// Parse the section from raw data. \p Data is assumed to contain the whole + /// frame section contents to be parsed. + void parse(DWARFDataExtractor Data); + + /// Return whether the section has any entries. + bool empty() const { return Entries.empty(); } + + /// DWARF Frame entries accessors + iterator begin() const { return Entries.begin(); } + iterator end() const { return Entries.end(); } + iterator_range<iterator> entries() const { + return iterator_range<iterator>(Entries.begin(), Entries.end()); + } + + uint64_t getEHFrameAddress() const { return EHFrameAddress; } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h new file mode 100644 index 00000000..f50063b2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -0,0 +1,62 @@ +//===- DWARFDebugInfoEntry.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_DWARFDEBUGINFOENTRY_H +#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include <cstdint> + +namespace llvm { + +class DataExtractor; +class DWARFUnit; + +/// DWARFDebugInfoEntry - A DIE with only the minimum required data. +class DWARFDebugInfoEntry { + /// Offset within the .debug_info of the start of this entry. + uint32_t Offset = 0; + + /// The integer depth of this DIE within the compile unit DIEs where the + /// compile/type unit DIE has a depth of zero. + uint32_t Depth = 0; + + const DWARFAbbreviationDeclaration *AbbrevDecl = nullptr; + +public: + DWARFDebugInfoEntry() = default; + + /// Extracts a debug info entry, which is a child of a given unit, + /// starting at a given offset. If DIE can't be extracted, returns false and + /// doesn't change OffsetPtr. + bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr); + + /// High performance extraction should use this call. + bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr, + const DWARFDataExtractor &DebugInfoData, uint32_t UEndOffset, + uint32_t Depth); + + uint32_t getOffset() const { return Offset; } + uint32_t getDepth() const { return Depth; } + + dwarf::Tag getTag() const { + return AbbrevDecl ? AbbrevDecl->getTag() : dwarf::DW_TAG_null; + } + + bool hasChildren() const { return AbbrevDecl && AbbrevDecl->hasChildren(); } + + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { + return AbbrevDecl; + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h new file mode 100644 index 00000000..9e40c844 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -0,0 +1,356 @@ +//===- DWARFDebugLine.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_DWARFDEBUGLINE_H +#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +#include "llvm/Support/MD5.h" +#include <cstdint> +#include <map> +#include <string> +#include <vector> + +namespace llvm { + +class DWARFUnit; +class raw_ostream; + +class DWARFDebugLine { +public: + struct FileNameEntry { + FileNameEntry() = default; + + DWARFFormValue Name; + uint64_t DirIdx = 0; + uint64_t ModTime = 0; + uint64_t Length = 0; + MD5::MD5Result Checksum; + DWARFFormValue Source; + }; + + /// Tracks which optional content types are present in a DWARF file name + /// entry format. + struct ContentTypeTracker { + ContentTypeTracker() = default; + + /// Whether filename entries provide a modification timestamp. + bool HasModTime = false; + /// Whether filename entries provide a file size. + bool HasLength = false; + /// For v5, whether filename entries provide an MD5 checksum. + bool HasMD5 = false; + /// For v5, whether filename entries provide source text. + bool HasSource = false; + + /// Update tracked content types with \p ContentType. + void trackContentType(dwarf::LineNumberEntryFormat ContentType); + }; + + struct Prologue { + Prologue(); + + /// The size in bytes of the statement information for this compilation unit + /// (not including the total_length field itself). + uint64_t TotalLength; + /// Version, address size (starting in v5), and DWARF32/64 format; these + /// parameters affect interpretation of forms (used in the directory and + /// file tables starting with v5). + dwarf::FormParams FormParams; + /// The number of bytes following the prologue_length field to the beginning + /// of the first byte of the statement program itself. + uint64_t PrologueLength; + /// In v5, size in bytes of a segment selector. + uint8_t SegSelectorSize; + /// The size in bytes of the smallest target machine instruction. Statement + /// program opcodes that alter the address register first multiply their + /// operands by this value. + uint8_t MinInstLength; + /// The maximum number of individual operations that may be encoded in an + /// instruction. + uint8_t MaxOpsPerInst; + /// The initial value of theis_stmtregister. + uint8_t DefaultIsStmt; + /// This parameter affects the meaning of the special opcodes. See below. + int8_t LineBase; + /// This parameter affects the meaning of the special opcodes. See below. + uint8_t LineRange; + /// The number assigned to the first special opcode. + uint8_t OpcodeBase; + /// This tracks which optional file format content types are present. + ContentTypeTracker ContentTypes; + std::vector<uint8_t> StandardOpcodeLengths; + std::vector<DWARFFormValue> IncludeDirectories; + std::vector<FileNameEntry> FileNames; + + const dwarf::FormParams getFormParams() const { return FormParams; } + uint16_t getVersion() const { return FormParams.Version; } + uint8_t getAddressSize() const { return FormParams.AddrSize; } + bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; } + + uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; } + + uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; } + + bool totalLengthIsValid() const; + + /// Length of the prologue in bytes. + uint32_t getLength() const { + return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) + + sizeofPrologueLength(); + } + + /// Length of the line table data in bytes (not including the prologue). + uint32_t getStatementTableLength() const { + return TotalLength + sizeofTotalLength() - getLength(); + } + + int32_t getMaxLineIncrementForSpecialOpcode() const { + return LineBase + (int8_t)LineRange - 1; + } + + void clear(); + void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; + Error parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, + const DWARFContext &Ctx, const DWARFUnit *U = nullptr); + }; + + /// Standard .debug_line state machine structure. + struct Row { + explicit Row(bool DefaultIsStmt = false); + + /// Called after a row is appended to the matrix. + void postAppend(); + void reset(bool DefaultIsStmt); + void dump(raw_ostream &OS) const; + + static void dumpTableHeader(raw_ostream &OS); + + static bool orderByAddress(const Row &LHS, const Row &RHS) { + return LHS.Address < RHS.Address; + } + + /// The program-counter value corresponding to a machine instruction + /// generated by the compiler. + uint64_t Address; + /// An unsigned integer indicating a source line number. Lines are numbered + /// beginning at 1. The compiler may emit the value 0 in cases where an + /// instruction cannot be attributed to any source line. + uint32_t Line; + /// An unsigned integer indicating a column number within a source line. + /// Columns are numbered beginning at 1. The value 0 is reserved to indicate + /// that a statement begins at the 'left edge' of the line. + uint16_t Column; + /// An unsigned integer indicating the identity of the source file + /// corresponding to a machine instruction. + uint16_t File; + /// An unsigned integer representing the DWARF path discriminator value + /// for this location. + uint32_t Discriminator; + /// An unsigned integer whose value encodes the applicable instruction set + /// architecture for the current instruction. + uint8_t Isa; + /// A boolean indicating that the current instruction is the beginning of a + /// statement. + uint8_t IsStmt : 1, + /// A boolean indicating that the current instruction is the + /// beginning of a basic block. + BasicBlock : 1, + /// A boolean indicating that the current address is that of the + /// first byte after the end of a sequence of target machine + /// instructions. + EndSequence : 1, + /// A boolean indicating that the current address is one (of possibly + /// many) where execution should be suspended for an entry breakpoint + /// of a function. + PrologueEnd : 1, + /// A boolean indicating that the current address is one (of possibly + /// many) where execution should be suspended for an exit breakpoint + /// of a function. + EpilogueBegin : 1; + }; + + /// Represents a series of contiguous machine instructions. Line table for + /// each compilation unit may consist of multiple sequences, which are not + /// guaranteed to be in the order of ascending instruction address. + struct Sequence { + Sequence(); + + /// Sequence describes instructions at address range [LowPC, HighPC) + /// and is described by line table rows [FirstRowIndex, LastRowIndex). + uint64_t LowPC; + uint64_t HighPC; + unsigned FirstRowIndex; + unsigned LastRowIndex; + bool Empty; + + void reset(); + + static bool orderByLowPC(const Sequence &LHS, const Sequence &RHS) { + return LHS.LowPC < RHS.LowPC; + } + + bool isValid() const { + return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); + } + + bool containsPC(uint64_t PC) const { return (LowPC <= PC && PC < HighPC); } + }; + + struct LineTable { + LineTable(); + + /// Represents an invalid row + const uint32_t UnknownRowIndex = UINT32_MAX; + + void appendRow(const DWARFDebugLine::Row &R) { Rows.push_back(R); } + + void appendSequence(const DWARFDebugLine::Sequence &S) { + Sequences.push_back(S); + } + + /// Returns the index of the row with file/line info for a given address, + /// or UnknownRowIndex if there is no such row. + uint32_t lookupAddress(uint64_t Address) const; + + bool lookupAddressRange(uint64_t Address, uint64_t Size, + std::vector<uint32_t> &Result) const; + + bool hasFileAtIndex(uint64_t FileIndex) const; + + /// Extracts filename by its index in filename table in prologue. + /// Returns true on success. + bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + std::string &Result) const; + + /// Fills the Result argument with the file and line information + /// corresponding to Address. Returns true on success. + bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + DILineInfo &Result) const; + + void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; + void clear(); + + /// Parse prologue and all rows. + Error parse( + DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, + const DWARFContext &Ctx, const DWARFUnit *U, + std::function<void(Error)> RecoverableErrorCallback, + raw_ostream *OS = nullptr); + + using RowVector = std::vector<Row>; + using RowIter = RowVector::const_iterator; + using SequenceVector = std::vector<Sequence>; + using SequenceIter = SequenceVector::const_iterator; + + struct Prologue Prologue; + RowVector Rows; + SequenceVector Sequences; + + private: + uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, + uint64_t Address) const; + Optional<StringRef> + getSourceByIndex(uint64_t FileIndex, + DILineInfoSpecifier::FileLineInfoKind Kind) const; + }; + + const LineTable *getLineTable(uint32_t Offset) const; + Expected<const LineTable *> getOrParseLineTable( + DWARFDataExtractor &DebugLineData, uint32_t Offset, + const DWARFContext &Ctx, const DWARFUnit *U, + std::function<void(Error)> RecoverableErrorCallback); + + /// Helper to allow for parsing of an entire .debug_line section in sequence. + class SectionParser { + public: + using cu_range = DWARFUnitVector::iterator_range; + using tu_range = DWARFUnitVector::iterator_range; + using LineToUnitMap = std::map<uint64_t, DWARFUnit *>; + + SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, cu_range CUs, + tu_range TUs); + + /// Get the next line table from the section. Report any issues via the + /// callbacks. + /// + /// \param RecoverableErrorCallback - any issues that don't prevent further + /// parsing of the table will be reported through this callback. + /// \param UnrecoverableErrorCallback - any issues that prevent further + /// parsing of the table will be reported through this callback. + /// \param OS - if not null, the parser will print information about the + /// table as it parses it. + LineTable + parseNext( + function_ref<void(Error)> RecoverableErrorCallback, + function_ref<void(Error)> UnrecoverableErrorCallback, + raw_ostream *OS = nullptr); + + /// Skip the current line table and go to the following line table (if + /// present) immediately. + /// + /// \param ErrorCallback - report any prologue parsing issues via this + /// callback. + void skip(function_ref<void(Error)> ErrorCallback); + + /// Indicates if the parser has parsed as much as possible. + /// + /// \note Certain problems with the line table structure might mean that + /// parsing stops before the end of the section is reached. + bool done() const { return Done; } + + /// Get the offset the parser has reached. + uint32_t getOffset() const { return Offset; } + + private: + DWARFUnit *prepareToParse(uint32_t Offset); + void moveToNextTable(uint32_t OldOffset, const Prologue &P); + + LineToUnitMap LineToUnit; + + DWARFDataExtractor &DebugLineData; + const DWARFContext &Context; + uint32_t Offset = 0; + bool Done = false; + }; + +private: + struct ParsingState { + ParsingState(struct LineTable *LT); + + void resetRowAndSequence(); + void appendRowToMatrix(uint32_t Offset); + + /// Line table we're currently parsing. + struct LineTable *LineTable; + /// The row number that starts at zero for the prologue, and increases for + /// each row added to the matrix. + unsigned RowNumber = 0; + struct Row Row; + struct Sequence Sequence; + }; + + using LineTableMapTy = std::map<uint32_t, LineTable>; + using LineTableIter = LineTableMapTy::iterator; + using LineTableConstIter = LineTableMapTy::const_iterator; + + LineTableMapTy LineTableMap; +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGLINE_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h new file mode 100644 index 00000000..dbed9594 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -0,0 +1,115 @@ +//===- DWARFDebugLoc.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_DWARF_DWARFDEBUGLOC_H +#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include <cstdint> + +namespace llvm { +class DWARFUnit; +class MCRegisterInfo; +class raw_ostream; + +class DWARFDebugLoc { +public: + /// A single location within a location list. + struct Entry { + /// The beginning address of the instruction range. + uint64_t Begin; + /// The ending address of the instruction range. + uint64_t End; + /// The location of the variable within the specified range. + SmallVector<char, 4> Loc; + }; + + /// A list of locations that contain one variable. + struct LocationList { + /// The beginning offset where this location list is stored in the debug_loc + /// section. + unsigned Offset; + /// All the locations in which the variable is stored. + SmallVector<Entry, 2> Entries; + /// Dump this list on OS. + void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, + const MCRegisterInfo *MRI, uint64_t BaseAddress, + unsigned Indent) const; + }; + +private: + using LocationLists = SmallVector<LocationList, 4>; + + /// A list of all the variables in the debug_loc section, each one describing + /// the locations in which the variable is stored. + LocationLists Locations; + + unsigned AddressSize; + + bool IsLittleEndian; + +public: + /// Print the location lists found within the debug_loc section. + void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, + Optional<uint64_t> Offset) const; + + /// Parse the debug_loc section accessible via the 'data' parameter using the + /// address size also given in 'data' to interpret the address ranges. + void parse(const DWARFDataExtractor &data); + + /// Return the location list at the given offset or nullptr. + LocationList const *getLocationListAtOffset(uint64_t Offset) const; + + Optional<LocationList> parseOneLocationList(DWARFDataExtractor Data, + uint32_t *Offset); +}; + +class DWARFDebugLoclists { +public: + struct Entry { + uint8_t Kind; + uint64_t Value0; + uint64_t Value1; + SmallVector<char, 4> Loc; + }; + + struct LocationList { + unsigned Offset; + SmallVector<Entry, 2> Entries; + void dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian, + unsigned AddressSize, const MCRegisterInfo *RegInfo, + unsigned Indent) const; + }; + +private: + using LocationLists = SmallVector<LocationList, 4>; + + LocationLists Locations; + + unsigned AddressSize; + + bool IsLittleEndian; + +public: + void parse(DataExtractor data, unsigned Version); + void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo, + Optional<uint64_t> Offset) const; + + /// Return the location list at the given offset or nullptr. + LocationList const *getLocationListAtOffset(uint64_t Offset) const; + + static Optional<LocationList> + parseOneLocationList(DataExtractor Data, unsigned *Offset, unsigned Version); +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h new file mode 100644 index 00000000..a6c12599 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h @@ -0,0 +1,62 @@ +//===- DWARFDebugMacro.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_DWARF_DWARFDEBUGMACRO_H +#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataExtractor.h" +#include <cstdint> + +namespace llvm { + +class raw_ostream; + +class DWARFDebugMacro { + /// A single macro entry within a macro list. + struct Entry { + /// The type of the macro entry. + uint32_t Type; + union { + /// The source line where the macro is defined. + uint64_t Line; + /// Vendor extension constant value. + uint64_t ExtConstant; + }; + + union { + /// The string (name, value) of the macro entry. + const char *MacroStr; + // An unsigned integer indicating the identity of the source file. + uint64_t File; + /// Vendor extension string. + const char *ExtStr; + }; + }; + + using MacroList = SmallVector<Entry, 4>; + + /// A list of all the macro entries in the debug_macinfo section. + MacroList Macros; + +public: + DWARFDebugMacro() = default; + + /// Print the macro list found within the debug_macinfo section. + void dump(raw_ostream &OS) const; + + /// Parse the debug_macinfo section accessible via the 'data' parameter. + void parse(DataExtractor data); + + /// Return whether the section has any entries. + bool empty() const { return Macros.empty(); } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h new file mode 100644 index 00000000..99e91ca9 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h @@ -0,0 +1,80 @@ +//===- DWARFDebugPubTable.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_DWARF_DWARFDEBUGPUBTABLE_H +#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGPUBTABLE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFObject.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +class raw_ostream; + +/// Represents structure for holding and parsing .debug_pub* tables. +class DWARFDebugPubTable { +public: + struct Entry { + /// Section offset from the beginning of the compilation unit. + uint32_t SecOffset; + + /// An entry of the various gnu_pub* debug sections. + dwarf::PubIndexEntryDescriptor Descriptor; + + /// The name of the object as given by the DW_AT_name attribute of the + /// referenced DIE. + StringRef Name; + }; + + /// Each table consists of sets of variable length entries. Each set describes + /// the names of global objects and functions, or global types, respectively, + /// whose definitions are represented by debugging information entries owned + /// by a single compilation unit. + struct Set { + /// The total length of the entries for that set, not including the length + /// field itself. + uint32_t Length; + + /// This number is specific to the name lookup table and is independent of + /// the DWARF version number. + uint16_t Version; + + /// The offset from the beginning of the .debug_info section of the + /// compilation unit header referenced by the set. + uint32_t Offset; + + /// The size in bytes of the contents of the .debug_info section generated + /// to represent that compilation unit. + uint32_t Size; + + std::vector<Entry> Entries; + }; + +private: + std::vector<Set> Sets; + + /// gnu styled tables contains additional information. + /// This flag determines whether or not section we parse is debug_gnu* table. + bool GnuStyle; + +public: + DWARFDebugPubTable(const DWARFObject &Obj, const DWARFSection &Sec, + bool LittleEndian, bool GnuStyle); + + void dump(raw_ostream &OS) const; + + ArrayRef<Set> getData() { return Sets; } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGPUBTABLE_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h new file mode 100644 index 00000000..c1c0f420 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -0,0 +1,84 @@ +//===- DWARFDebugRangeList.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_DWARF_DWARFDEBUGRANGELIST_H +#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H + +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include <cassert> +#include <cstdint> +#include <vector> + +namespace llvm { + +class raw_ostream; + +class DWARFDebugRangeList { +public: + struct RangeListEntry { + /// A beginning address offset. This address offset has the size of an + /// address and is relative to the applicable base address of the + /// compilation unit referencing this range list. It marks the beginning + /// of an address range. + uint64_t StartAddress; + /// An ending address offset. This address offset again has the size of + /// an address and is relative to the applicable base address of the + /// compilation unit referencing this range list. It marks the first + /// address past the end of the address range. The ending address must + /// be greater than or equal to the beginning address. + uint64_t EndAddress; + /// A section index this range belongs to. + uint64_t SectionIndex; + + /// The end of any given range list is marked by an end of list entry, + /// which consists of a 0 for the beginning address offset + /// and a 0 for the ending address offset. + bool isEndOfListEntry() const { + return (StartAddress == 0) && (EndAddress == 0); + } + + /// A base address selection entry consists of: + /// 1. The value of the largest representable address offset + /// (for example, 0xffffffff when the size of an address is 32 bits). + /// 2. An address, which defines the appropriate base address for + /// use in interpreting the beginning and ending address offsets of + /// subsequent entries of the location list. + bool isBaseAddressSelectionEntry(uint8_t AddressSize) const { + assert(AddressSize == 4 || AddressSize == 8); + if (AddressSize == 4) + return StartAddress == -1U; + else + return StartAddress == -1ULL; + } + }; + +private: + /// Offset in .debug_ranges section. + uint32_t Offset; + uint8_t AddressSize; + std::vector<RangeListEntry> Entries; + +public: + DWARFDebugRangeList() { clear(); } + + void clear(); + void dump(raw_ostream &OS) const; + Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr); + const std::vector<RangeListEntry> &getEntries() { return Entries; } + + /// getAbsoluteRanges - Returns absolute address ranges defined by this range + /// list. Has to be passed base address of the compile unit referencing this + /// range list. + DWARFAddressRangesVector + getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr) const; +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h new file mode 100644 index 00000000..c6661a8b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h @@ -0,0 +1,64 @@ +//===- DWARFDebugRnglists.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_DWARFDEBUGRNGLISTS_H +#define LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H + +#include "llvm/ADT/Optional.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFListTable.h" +#include <cstdint> +#include <map> +#include <vector> + +namespace llvm { + +class Error; +class raw_ostream; +class DWARFUnit; + +/// A class representing a single range list entry. +struct RangeListEntry : public DWARFListEntryBase { + /// The values making up the range list entry. Most represent a range with + /// a start and end address or a start address and a length. Others are + /// single value base addresses or end-of-list with no values. The unneeded + /// values are semantically undefined, but initialized to 0. + uint64_t Value0; + uint64_t Value1; + + Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr); + void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, + uint64_t &CurrentBase, DIDumpOptions DumpOpts, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress) const; + bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; } +}; + +/// A class representing a single rangelist. +class DWARFDebugRnglist : public DWARFListType<RangeListEntry> { +public: + /// Build a DWARFAddressRangesVector from a rangelist. + DWARFAddressRangesVector + getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, + DWARFUnit &U) const; +}; + +class DWARFDebugRnglistTable : public DWARFListTableBase<DWARFDebugRnglist> { +public: + DWARFDebugRnglistTable() + : DWARFListTableBase(/* SectionName = */ ".debug_rnglists", + /* HeaderString = */ "ranges:", + /* ListTypeString = */ "range") {} +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDie.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDie.h new file mode 100644 index 00000000..21e68f98 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -0,0 +1,468 @@ +//===- DWARFDie.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_DWARFDIE_H +#define LLVM_DEBUGINFO_DWARFDIE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" +#include "llvm/DebugInfo/DWARF/DWARFAttribute.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include <cassert> +#include <cstdint> +#include <iterator> + +namespace llvm { + +class DWARFUnit; +class raw_ostream; + +//===----------------------------------------------------------------------===// +/// Utility class that carries the DWARF compile/type unit and the debug info +/// entry in an object. +/// +/// When accessing information from a debug info entry we always need to DWARF +/// compile/type unit in order to extract the info correctly as some information +/// is relative to the compile/type unit. Prior to this class the DWARFUnit and +/// the DWARFDebugInfoEntry was passed around separately and there was the +/// possibility for error if the wrong DWARFUnit was used to extract a unit +/// relative offset. This class helps to ensure that this doesn't happen and +/// also simplifies the attribute extraction calls by not having to specify the +/// DWARFUnit for each call. +class DWARFDie { + DWARFUnit *U = nullptr; + const DWARFDebugInfoEntry *Die = nullptr; + +public: + DWARFDie() = default; + DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry *D) : U(Unit), Die(D) {} + + bool isValid() const { return U && Die; } + explicit operator bool() const { return isValid(); } + const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; } + DWARFUnit *getDwarfUnit() const { return U; } + + /// Get the abbreviation declaration for this DIE. + /// + /// \returns the abbreviation declaration or NULL for null tags. + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { + assert(isValid() && "must check validity prior to calling"); + return Die->getAbbreviationDeclarationPtr(); + } + + /// Get the absolute offset into the debug info or types section. + /// + /// \returns the DIE offset or -1U if invalid. + uint32_t getOffset() const { + assert(isValid() && "must check validity prior to calling"); + return Die->getOffset(); + } + + dwarf::Tag getTag() const { + auto AbbrevDecl = getAbbreviationDeclarationPtr(); + if (AbbrevDecl) + return AbbrevDecl->getTag(); + return dwarf::DW_TAG_null; + } + + bool hasChildren() const { + assert(isValid() && "must check validity prior to calling"); + return Die->hasChildren(); + } + + /// Returns true for a valid DIE that terminates a sibling chain. + bool isNULL() const { return getAbbreviationDeclarationPtr() == nullptr; } + + /// Returns true if DIE represents a subprogram (not inlined). + bool isSubprogramDIE() const; + + /// Returns true if DIE represents a subprogram or an inlined subroutine. + bool isSubroutineDIE() const; + + /// Get the parent of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has a parent or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getParent() const; + + /// Get the sibling of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has a sibling or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getSibling() const; + + /// Get the previous sibling of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has a sibling or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getPreviousSibling() const; + + /// Get the first child of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has children or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getFirstChild() const; + + /// Get the last child of this DIE object. + /// + /// \returns a valid null DWARFDie instance if this object has children or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getLastChild() const; + + /// Dump the DIE and all of its attributes to the supplied stream. + /// + /// \param OS the stream to use for output. + /// \param indent the number of characters to indent each line that is output. + void dump(raw_ostream &OS, unsigned indent = 0, + DIDumpOptions DumpOpts = DIDumpOptions()) const; + + /// Convenience zero-argument overload for debugging. + LLVM_DUMP_METHOD void dump() const; + + /// Extract the specified attribute from this DIE. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns an optional DWARFFormValue that will have the form value if the + /// attribute was successfully extracted. + Optional<DWARFFormValue> find(dwarf::Attribute Attr) const; + + /// Extract the first value of any attribute in Attrs from this DIE. + /// + /// Extract the first attribute that matches from this DIE only. This call + /// doesn't look for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. The attributes will be searched + /// linearly in the order they are specified within Attrs. + /// + /// \param Attrs an array of DWARF attribute to look for. + /// \returns an optional that has a valid DWARFFormValue for the first + /// matching attribute in Attrs, or None if none of the attributes in Attrs + /// exist in this DIE. + Optional<DWARFFormValue> find(ArrayRef<dwarf::Attribute> Attrs) const; + + /// Extract the first value of any attribute in Attrs from this DIE and + /// recurse into any DW_AT_specification or DW_AT_abstract_origin referenced + /// DIEs. + /// + /// \param Attrs an array of DWARF attribute to look for. + /// \returns an optional that has a valid DWARFFormValue for the first + /// matching attribute in Attrs, or None if none of the attributes in Attrs + /// exist in this DIE or in any DW_AT_specification or DW_AT_abstract_origin + /// DIEs. + Optional<DWARFFormValue> + findRecursively(ArrayRef<dwarf::Attribute> Attrs) const; + + /// Extract the specified attribute from this DIE as the referenced DIE. + /// + /// Regardless of the reference type, return the correct DWARFDie instance if + /// the attribute exists. The returned DWARFDie object might be from another + /// DWARFUnit, but that is all encapsulated in the new DWARFDie object. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns a valid DWARFDie instance if the attribute exists, or an invalid + /// DWARFDie object if it doesn't. + DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const; + DWARFDie getAttributeValueAsReferencedDie(const DWARFFormValue &V) const; + + /// Extract the range base attribute from this DIE as absolute section offset. + /// + /// This is a utility function that checks for either the DW_AT_rnglists_base + /// or DW_AT_GNU_ranges_base attribute. + /// + /// \returns anm optional absolute section offset value for the attribute. + Optional<uint64_t> getRangesBaseAttribute() const; + + /// Get the DW_AT_high_pc attribute value as an address. + /// + /// In DWARF version 4 and later the high PC can be encoded as an offset from + /// the DW_AT_low_pc. This function takes care of extracting the value as an + /// address or offset and adds it to the low PC if needed and returns the + /// value as an optional in case the DIE doesn't have a DW_AT_high_pc + /// attribute. + /// + /// \param LowPC the low PC that might be needed to calculate the high PC. + /// \returns an optional address value for the attribute. + Optional<uint64_t> getHighPC(uint64_t LowPC) const; + + /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. + /// Returns true if both attributes are present. + bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, + uint64_t &SectionIndex) const; + + /// Get the address ranges for this DIE. + /// + /// Get the hi/low PC range if both attributes are available or exrtracts the + /// non-contiguous address ranges from the DW_AT_ranges attribute. + /// + /// Extracts the range information from this DIE only. This call doesn't look + /// for the range in any DW_AT_specification or DW_AT_abstract_origin DIEs. + /// + /// \returns a address range vector that might be empty if no address range + /// information is available. + Expected<DWARFAddressRangesVector> getAddressRanges() const; + + /// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any + /// of its children. + /// + /// Get the hi/low PC range if both attributes are available or exrtracts the + /// non-contiguous address ranges from the DW_AT_ranges attribute for this DIE + /// and all children. + /// + /// \param Ranges the addres range vector to fill in. + void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const; + + bool addressRangeContainsAddress(const uint64_t Address) const; + + /// If a DIE represents a subprogram (or inlined subroutine), returns its + /// mangled name (or short name, if mangled is missing). This name may be + /// fetched from specification or abstract origin for this subprogram. + /// Returns null if no name is found. + const char *getSubroutineName(DINameKind Kind) const; + + /// Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin + /// references if necessary. Returns null if no name is found. + const char *getName(DINameKind Kind) const; + + /// Returns the declaration line (start line) for a DIE, assuming it specifies + /// a subprogram. This may be fetched from specification or abstract origin + /// for this subprogram by resolving DW_AT_sepcification or + /// DW_AT_abstract_origin references if necessary. + uint64_t getDeclLine() const; + + /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column + /// from DIE (or zeroes if they are missing). This function looks for + /// DW_AT_call attributes in this DIE only, it will not resolve the attribute + /// values in any DW_AT_specification or DW_AT_abstract_origin DIEs. + /// \param CallFile filled in with non-zero if successful, zero if there is no + /// DW_AT_call_file attribute in this DIE. + /// \param CallLine filled in with non-zero if successful, zero if there is no + /// DW_AT_call_line attribute in this DIE. + /// \param CallColumn filled in with non-zero if successful, zero if there is + /// no DW_AT_call_column attribute in this DIE. + /// \param CallDiscriminator filled in with non-zero if successful, zero if + /// there is no DW_AT_GNU_discriminator attribute in this DIE. + void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, + uint32_t &CallColumn, uint32_t &CallDiscriminator) const; + + class attribute_iterator; + + /// Get an iterator range to all attributes in the current DIE only. + /// + /// \returns an iterator range for the attributes of the current DIE. + iterator_range<attribute_iterator> attributes() const; + + class iterator; + + iterator begin() const; + iterator end() const; + + std::reverse_iterator<iterator> rbegin() const; + std::reverse_iterator<iterator> rend() const; + + iterator_range<iterator> children() const; +}; + +class DWARFDie::attribute_iterator + : public iterator_facade_base<attribute_iterator, std::forward_iterator_tag, + const DWARFAttribute> { + /// The DWARF DIE we are extracting attributes from. + DWARFDie Die; + /// The value vended to clients via the operator*() or operator->(). + DWARFAttribute AttrValue; + /// The attribute index within the abbreviation declaration in Die. + uint32_t Index; + + friend bool operator==(const attribute_iterator &LHS, + const attribute_iterator &RHS); + + /// Update the attribute index and attempt to read the attribute value. If the + /// attribute is able to be read, update AttrValue and the Index member + /// variable. If the attribute value is not able to be read, an appropriate + /// error will be set if the Err member variable is non-NULL and the iterator + /// will be set to the end value so iteration stops. + void updateForIndex(const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I); + +public: + attribute_iterator() = delete; + explicit attribute_iterator(DWARFDie D, bool End); + + attribute_iterator &operator++(); + attribute_iterator &operator--(); + explicit operator bool() const { return AttrValue.isValid(); } + const DWARFAttribute &operator*() const { return AttrValue; } +}; + +inline bool operator==(const DWARFDie::attribute_iterator &LHS, + const DWARFDie::attribute_iterator &RHS) { + return LHS.Index == RHS.Index; +} + +inline bool operator!=(const DWARFDie::attribute_iterator &LHS, + const DWARFDie::attribute_iterator &RHS) { + return !(LHS == RHS); +} + +inline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) { + return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() && + LHS.getDwarfUnit() == RHS.getDwarfUnit(); +} + +inline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) { + return !(LHS == RHS); +} + +inline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) { + return LHS.getOffset() < RHS.getOffset(); +} + +class DWARFDie::iterator + : public iterator_facade_base<iterator, std::bidirectional_iterator_tag, + const DWARFDie> { + DWARFDie Die; + + friend std::reverse_iterator<llvm::DWARFDie::iterator>; + friend bool operator==(const DWARFDie::iterator &LHS, + const DWARFDie::iterator &RHS); + +public: + iterator() = default; + + explicit iterator(DWARFDie D) : Die(D) {} + + iterator &operator++() { + Die = Die.getSibling(); + return *this; + } + + iterator &operator--() { + Die = Die.getPreviousSibling(); + return *this; + } + + const DWARFDie &operator*() const { return Die; } +}; + +inline bool operator==(const DWARFDie::iterator &LHS, + const DWARFDie::iterator &RHS) { + return LHS.Die == RHS.Die; +} + +inline bool operator!=(const DWARFDie::iterator &LHS, + const DWARFDie::iterator &RHS) { + return !(LHS == RHS); +} + +// These inline functions must follow the DWARFDie::iterator definition above +// as they use functions from that class. +inline DWARFDie::iterator DWARFDie::begin() const { + return iterator(getFirstChild()); +} + +inline DWARFDie::iterator DWARFDie::end() const { + return iterator(getLastChild()); +} + +inline iterator_range<DWARFDie::iterator> DWARFDie::children() const { + return make_range(begin(), end()); +} + +} // end namespace llvm + +namespace std { + +template <> +class reverse_iterator<llvm::DWARFDie::iterator> + : public llvm::iterator_facade_base< + reverse_iterator<llvm::DWARFDie::iterator>, + bidirectional_iterator_tag, const llvm::DWARFDie> { + +private: + llvm::DWARFDie Die; + bool AtEnd; + +public: + reverse_iterator(llvm::DWARFDie::iterator It) + : Die(It.Die), AtEnd(!It.Die.getPreviousSibling()) { + if (!AtEnd) + Die = Die.getPreviousSibling(); + } + + llvm::DWARFDie::iterator base() const { + return llvm::DWARFDie::iterator(AtEnd ? Die : Die.getSibling()); + } + + reverse_iterator<llvm::DWARFDie::iterator> &operator++() { + assert(!AtEnd && "Incrementing rend"); + llvm::DWARFDie D = Die.getPreviousSibling(); + if (D) + Die = D; + else + AtEnd = true; + return *this; + } + + reverse_iterator<llvm::DWARFDie::iterator> &operator--() { + if (AtEnd) { + AtEnd = false; + return *this; + } + Die = Die.getSibling(); + assert(!Die.isNULL() && "Decrementing rbegin"); + return *this; + } + + const llvm::DWARFDie &operator*() const { + assert(Die.isValid()); + return Die; + } + + // FIXME: We should be able to specify the equals operator as a friend, but + // that causes the compiler to think the operator overload is ambiguous + // with the friend declaration and the actual definition as candidates. + bool equals(const reverse_iterator<llvm::DWARFDie::iterator> &RHS) const { + return Die == RHS.Die && AtEnd == RHS.AtEnd; + } +}; + +} // namespace std + +namespace llvm { + +inline bool operator==(const std::reverse_iterator<DWARFDie::iterator> &LHS, + const std::reverse_iterator<DWARFDie::iterator> &RHS) { + return LHS.equals(RHS); +} + +inline bool operator!=(const std::reverse_iterator<DWARFDie::iterator> &LHS, + const std::reverse_iterator<DWARFDie::iterator> &RHS) { + return !(LHS == RHS); +} + +inline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rbegin() const { + return llvm::make_reverse_iterator(end()); +} + +inline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rend() const { + return llvm::make_reverse_iterator(begin()); +} + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDIE_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFExpression.h new file mode 100644 index 00000000..8049094c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -0,0 +1,152 @@ +//===--- DWARFExpression.h - DWARF Expression handling ----------*- 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_DWARFEXPRESSION_H +#define LLVM_DEBUGINFO_DWARFEXPRESSION_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { +class DWARFUnit; +class MCRegisterInfo; +class raw_ostream; + +class DWARFExpression { +public: + class iterator; + + /// This class represents an Operation in the Expression. Each operation can + /// have up to 2 oprerands. + /// + /// An Operation can be in Error state (check with isError()). This + /// means that it couldn't be decoded successfully and if it is the + /// case, all others fields contain undefined values. + class Operation { + public: + /// Size and signedness of expression operations' operands. + enum Encoding : uint8_t { + Size1 = 0, + Size2 = 1, + Size4 = 2, + Size8 = 3, + SizeLEB = 4, + SizeAddr = 5, + SizeRefAddr = 6, + SizeBlock = 7, ///< Preceding operand contains block size + SignBit = 0x8, + SignedSize1 = SignBit | Size1, + SignedSize2 = SignBit | Size2, + SignedSize4 = SignBit | Size4, + SignedSize8 = SignBit | Size8, + SignedSizeLEB = SignBit | SizeLEB, + SizeNA = 0xFF ///< Unused operands get this encoding. + }; + + enum DwarfVersion : uint8_t { + DwarfNA, ///< Serves as a marker for unused entries + Dwarf2 = 2, + Dwarf3, + Dwarf4 + }; + + /// Description of the encoding of one expression Op. + struct Description { + DwarfVersion Version; ///< Dwarf version where the Op was introduced. + Encoding Op[2]; ///< Encoding for Op operands, or SizeNA. + + Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA, + Encoding Op2 = SizeNA) + : Version(Version) { + Op[0] = Op1; + Op[1] = Op2; + } + }; + + private: + friend class DWARFExpression::iterator; + uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>. + Description Desc; + bool Error; + uint32_t EndOffset; + uint64_t Operands[2]; + + public: + Description &getDescription() { return Desc; } + uint8_t getCode() { return Opcode; } + uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; } + uint32_t getEndOffset() { return EndOffset; } + bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize, + uint32_t Offset); + bool isError() { return Error; } + bool print(raw_ostream &OS, const DWARFExpression *U, + const MCRegisterInfo *RegInfo, bool isEH); + }; + + /// An iterator to go through the expression operations. + class iterator + : public iterator_facade_base<iterator, std::forward_iterator_tag, + Operation> { + friend class DWARFExpression; + const DWARFExpression *Expr; + uint32_t Offset; + Operation Op; + iterator(const DWARFExpression *Expr, uint32_t Offset) + : Expr(Expr), Offset(Offset) { + Op.Error = + Offset >= Expr->Data.getData().size() || + !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset); + } + + public: + class Operation &operator++() { + Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset; + Op.Error = + Offset >= Expr->Data.getData().size() || + !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset); + return Op; + } + + class Operation &operator*() { + return Op; + } + + // Comparison operators are provided out of line. + friend bool operator==(const iterator &, const iterator &); + }; + + DWARFExpression(DataExtractor Data, uint16_t Version, uint8_t AddressSize) + : Data(Data), Version(Version), AddressSize(AddressSize) { + assert(AddressSize == 8 || AddressSize == 4); + } + + iterator begin() const { return iterator(this, 0); } + iterator end() const { return iterator(this, Data.getData().size()); } + + void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, + bool IsEH = false) const; + +private: + DataExtractor Data; + uint16_t Version; + uint8_t AddressSize; +}; + +inline bool operator==(const DWARFExpression::iterator &LHS, + const DWARFExpression::iterator &RHS) { + return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset; +} + +inline bool operator!=(const DWARFExpression::iterator &LHS, + const DWARFExpression::iterator &RHS) { + return !(LHS == RHS); +} +} +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFFormValue.h new file mode 100644 index 00000000..e092d96b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -0,0 +1,298 @@ +//===- DWARFFormValue.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_DWARFFORMVALUE_H +#define LLVM_DEBUGINFO_DWARFFORMVALUE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include <cstdint> + +namespace llvm { + +class DWARFContext; +class DWARFUnit; +class raw_ostream; + +class DWARFFormValue { +public: + enum FormClass { + FC_Unknown, + FC_Address, + FC_Block, + FC_Constant, + FC_String, + FC_Flag, + FC_Reference, + FC_Indirect, + FC_SectionOffset, + FC_Exprloc + }; + +private: + struct ValueType { + ValueType() { uval = 0; } + + union { + uint64_t uval; + int64_t sval; + const char *cstr; + }; + const uint8_t *data = nullptr; + uint64_t SectionIndex; /// Section index for reference forms. + }; + + dwarf::Form Form; /// Form for this value. + ValueType Value; /// Contains all data for the form. + const DWARFUnit *U = nullptr; /// Remember the DWARFUnit at extract time. + const DWARFContext *C = nullptr; /// Context for extract time. +public: + DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {} + + dwarf::Form getForm() const { return Form; } + uint64_t getRawUValue() const { return Value.uval; } + void setForm(dwarf::Form F) { Form = F; } + void setUValue(uint64_t V) { Value.uval = V; } + void setSValue(int64_t V) { Value.sval = V; } + void setPValue(const char *V) { Value.cstr = V; } + + void setBlockValue(const ArrayRef<uint8_t> &Data) { + Value.data = Data.data(); + setUValue(Data.size()); + } + + bool isFormClass(FormClass FC) const; + const DWARFUnit *getUnit() const { return U; } + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; + void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, + SectionedAddress SA) const; + static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, + DIDumpOptions DumpOpts, uint64_t SectionIndex); + + /// Extracts a value in \p Data at offset \p *OffsetPtr. The information + /// in \p FormParams is needed to interpret some forms. The optional + /// \p Context and \p Unit allows extracting information if the form refers + /// to other sections (e.g., .debug_str). + bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, + dwarf::FormParams FormParams, + const DWARFContext *Context = nullptr, + const DWARFUnit *Unit = nullptr); + + bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, + dwarf::FormParams FormParams, const DWARFUnit *U) { + return extractValue(Data, OffsetPtr, FormParams, nullptr, U); + } + + bool isInlinedCStr() const { + return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr; + } + + /// getAsFoo functions below return the extracted value as Foo if only + /// DWARFFormValue has form class is suitable for representing Foo. + Optional<uint64_t> getAsReference() const; + Optional<uint64_t> getAsUnsignedConstant() const; + Optional<int64_t> getAsSignedConstant() const; + Optional<const char *> getAsCString() const; + Optional<uint64_t> getAsAddress() const; + Optional<SectionedAddress> getAsSectionedAddress() const; + Optional<uint64_t> getAsSectionOffset() const; + Optional<ArrayRef<uint8_t>> getAsBlock() const; + Optional<uint64_t> getAsCStringOffset() const; + Optional<uint64_t> getAsReferenceUVal() const; + + /// Skip a form's value in \p DebugInfoData at the offset specified by + /// \p OffsetPtr. + /// + /// Skips the bytes for the current form and updates the offset. + /// + /// \param DebugInfoData The data where we want to skip the value. + /// \param OffsetPtr A reference to the offset that will be updated. + /// \param Params DWARF parameters to help interpret forms. + /// \returns true on success, false if the form was not skipped. + bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr, + const dwarf::FormParams Params) const { + return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params); + } + + /// Skip a form's value in \p DebugInfoData at the offset specified by + /// \p OffsetPtr. + /// + /// Skips the bytes for the specified form and updates the offset. + /// + /// \param Form The DW_FORM enumeration that indicates the form to skip. + /// \param DebugInfoData The data where we want to skip the value. + /// \param OffsetPtr A reference to the offset that will be updated. + /// \param FormParams DWARF parameters to help interpret forms. + /// \returns true on success, false if the form was not skipped. + static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData, + uint32_t *OffsetPtr, + const dwarf::FormParams FormParams); + +private: + void dumpString(raw_ostream &OS) const; +}; + +namespace dwarf { + +/// Take an optional DWARFFormValue and try to extract a string value from it. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \returns an optional value that contains a value if the form value +/// was valid and was a string. +inline Optional<const char *> toString(const Optional<DWARFFormValue> &V) { + if (V) + return V->getAsCString(); + return None; +} + +/// Take an optional DWARFFormValue and extract a string value from it. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \param Default the default value to return in case of failure. +/// \returns the string value or Default if the V doesn't have a value or the +/// form value's encoding wasn't a string. +inline const char *toString(const Optional<DWARFFormValue> &V, + const char *Default) { + return toString(V).getValueOr(Default); +} + +/// Take an optional DWARFFormValue and try to extract an unsigned constant. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \returns an optional value that contains a value if the form value +/// was valid and has a unsigned constant form. +inline Optional<uint64_t> toUnsigned(const Optional<DWARFFormValue> &V) { + if (V) + return V->getAsUnsignedConstant(); + return None; +} + +/// Take an optional DWARFFormValue and extract a unsigned constant. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \param Default the default value to return in case of failure. +/// \returns the extracted unsigned value or Default if the V doesn't have a +/// value or the form value's encoding wasn't an unsigned constant form. +inline uint64_t toUnsigned(const Optional<DWARFFormValue> &V, + uint64_t Default) { + return toUnsigned(V).getValueOr(Default); +} + +/// Take an optional DWARFFormValue and try to extract an reference. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \returns an optional value that contains a value if the form value +/// was valid and has a reference form. +inline Optional<uint64_t> toReference(const Optional<DWARFFormValue> &V) { + if (V) + return V->getAsReference(); + return None; +} + +/// Take an optional DWARFFormValue and extract a reference. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \param Default the default value to return in case of failure. +/// \returns the extracted reference value or Default if the V doesn't have a +/// value or the form value's encoding wasn't a reference form. +inline uint64_t toReference(const Optional<DWARFFormValue> &V, + uint64_t Default) { + return toReference(V).getValueOr(Default); +} + +/// Take an optional DWARFFormValue and try to extract an signed constant. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \returns an optional value that contains a value if the form value +/// was valid and has a signed constant form. +inline Optional<int64_t> toSigned(const Optional<DWARFFormValue> &V) { + if (V) + return V->getAsSignedConstant(); + return None; +} + +/// Take an optional DWARFFormValue and extract a signed integer. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \param Default the default value to return in case of failure. +/// \returns the extracted signed integer value or Default if the V doesn't +/// have a value or the form value's encoding wasn't a signed integer form. +inline int64_t toSigned(const Optional<DWARFFormValue> &V, int64_t Default) { + return toSigned(V).getValueOr(Default); +} + +/// Take an optional DWARFFormValue and try to extract an address. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \returns an optional value that contains a value if the form value +/// was valid and has a address form. +inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue> &V) { + if (V) + return V->getAsAddress(); + return None; +} + +inline Optional<SectionedAddress> +toSectionedAddress(const Optional<DWARFFormValue> &V) { + if (V) + return V->getAsSectionedAddress(); + return None; +} + +/// Take an optional DWARFFormValue and extract a address. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \param Default the default value to return in case of failure. +/// \returns the extracted address value or Default if the V doesn't have a +/// value or the form value's encoding wasn't an address form. +inline uint64_t toAddress(const Optional<DWARFFormValue> &V, uint64_t Default) { + return toAddress(V).getValueOr(Default); +} + +/// Take an optional DWARFFormValue and try to extract an section offset. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \returns an optional value that contains a value if the form value +/// was valid and has a section offset form. +inline Optional<uint64_t> toSectionOffset(const Optional<DWARFFormValue> &V) { + if (V) + return V->getAsSectionOffset(); + return None; +} + +/// Take an optional DWARFFormValue and extract a section offset. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \param Default the default value to return in case of failure. +/// \returns the extracted section offset value or Default if the V doesn't +/// have a value or the form value's encoding wasn't a section offset form. +inline uint64_t toSectionOffset(const Optional<DWARFFormValue> &V, + uint64_t Default) { + return toSectionOffset(V).getValueOr(Default); +} + +/// Take an optional DWARFFormValue and try to extract block data. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \returns an optional value that contains a value if the form value +/// was valid and has a block form. +inline Optional<ArrayRef<uint8_t>> toBlock(const Optional<DWARFFormValue> &V) { + if (V) + return V->getAsBlock(); + return None; +} + +} // end namespace dwarf + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFFORMVALUE_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h new file mode 100644 index 00000000..38cd42dd --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h @@ -0,0 +1,82 @@ +//===- DWARFGdbIndex.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_DWARF_DWARFGDBINDEX_H +#define LLVM_DEBUGINFO_DWARF_DWARFGDBINDEX_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataExtractor.h" +#include <cstdint> +#include <utility> + +namespace llvm { + +class raw_ostream; + +class DWARFGdbIndex { + uint32_t Version; + + uint32_t CuListOffset; + uint32_t TuListOffset; + uint32_t AddressAreaOffset; + uint32_t SymbolTableOffset; + uint32_t ConstantPoolOffset; + + struct CompUnitEntry { + uint64_t Offset; /// Offset of a CU in the .debug_info section. + uint64_t Length; /// Length of that CU. + }; + SmallVector<CompUnitEntry, 0> CuList; + + struct TypeUnitEntry { + uint64_t Offset; + uint64_t TypeOffset; + uint64_t TypeSignature; + }; + SmallVector<TypeUnitEntry, 0> TuList; + + struct AddressEntry { + uint64_t LowAddress; /// The low address. + uint64_t HighAddress; /// The high address. + uint32_t CuIndex; /// The CU index. + }; + SmallVector<AddressEntry, 0> AddressArea; + + struct SymTableEntry { + uint32_t NameOffset; /// Offset of the symbol's name in the constant pool. + uint32_t VecOffset; /// Offset of the CU vector in the constant pool. + }; + SmallVector<SymTableEntry, 0> SymbolTable; + + /// Each value is CU index + attributes. + SmallVector<std::pair<uint32_t, SmallVector<uint32_t, 0>>, 0> + ConstantPoolVectors; + + StringRef ConstantPoolStrings; + uint32_t StringPoolOffset; + + void dumpCUList(raw_ostream &OS) const; + void dumpTUList(raw_ostream &OS) const; + void dumpAddressArea(raw_ostream &OS) const; + void dumpSymbolTable(raw_ostream &OS) const; + void dumpConstantPool(raw_ostream &OS) const; + + bool parseImpl(DataExtractor Data); + +public: + void dump(raw_ostream &OS); + void parse(DataExtractor Data); + + bool HasContent = false; + bool HasError = false; +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFGDBINDEX_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFListTable.h new file mode 100644 index 00000000..6c13db3d --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -0,0 +1,283 @@ +//===- DWARFListTable.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_DWARFLISTTABLE_H +#define LLVM_DEBUGINFO_DWARFLISTTABLE_H + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdint> +#include <map> +#include <vector> + +namespace llvm { + +/// A base class for DWARF list entries, such as range or location list +/// entries. +struct DWARFListEntryBase { + /// The offset at which the entry is located in the section. + uint32_t Offset; + /// The DWARF encoding (DW_RLE_* or DW_LLE_*). + uint8_t EntryKind; + /// The index of the section this entry belongs to. + uint64_t SectionIndex; +}; + +/// A base class for lists of entries that are extracted from a particular +/// section, such as range lists or location lists. +template <typename ListEntryType> class DWARFListType { + using EntryType = ListEntryType; + using ListEntries = std::vector<EntryType>; + +protected: + ListEntries Entries; + +public: + const ListEntries &getEntries() const { return Entries; } + bool empty() const { return Entries.empty(); } + void clear() { Entries.clear(); } + Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End, + uint32_t *OffsetPtr, StringRef SectionName, + StringRef ListStringName); +}; + +/// A class representing the header of a list table such as the range list +/// table in the .debug_rnglists section. +class DWARFListTableHeader { + struct Header { + /// The total length of the entries for this table, not including the length + /// field itself. + uint32_t Length = 0; + /// The DWARF version number. + uint16_t Version; + /// The size in bytes of an address on the target architecture. For + /// segmented addressing, this is the size of the offset portion of the + /// address. + uint8_t AddrSize; + /// The size in bytes of a segment selector on the target architecture. + /// If the target system uses a flat address space, this value is 0. + uint8_t SegSize; + /// The number of offsets that follow the header before the range lists. + uint32_t OffsetEntryCount; + }; + + Header HeaderData; + /// The offset table, which contains offsets to the individual list entries. + /// It is used by forms such as DW_FORM_rnglistx. + /// FIXME: Generate the table and use the appropriate forms. + std::vector<uint32_t> Offsets; + /// The table's format, either DWARF32 or DWARF64. + dwarf::DwarfFormat Format; + /// The offset at which the header (and hence the table) is located within + /// its section. + uint32_t HeaderOffset; + /// The name of the section the list is located in. + StringRef SectionName; + /// A characterization of the list for dumping purposes, e.g. "range" or + /// "location". + StringRef ListTypeString; + +public: + DWARFListTableHeader(StringRef SectionName, StringRef ListTypeString) + : SectionName(SectionName), ListTypeString(ListTypeString) {} + + void clear() { + HeaderData = {}; + Offsets.clear(); + } + uint32_t getHeaderOffset() const { return HeaderOffset; } + uint8_t getAddrSize() const { return HeaderData.AddrSize; } + uint32_t getLength() const { return HeaderData.Length; } + uint16_t getVersion() const { return HeaderData.Version; } + StringRef getSectionName() const { return SectionName; } + StringRef getListTypeString() const { return ListTypeString; } + dwarf::DwarfFormat getFormat() const { return Format; } + + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; + Optional<uint32_t> getOffsetEntry(uint32_t Index) const { + if (Index < Offsets.size()) + return Offsets[Index]; + return None; + } + + /// Extract the table header and the array of offsets. + Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr); + + /// Returns the length of the table, including the length field, or 0 if the + /// length has not been determined (e.g. because the table has not yet been + /// parsed, or there was a problem in parsing). + uint32_t length() const; +}; + +/// A class representing a table of lists as specified in the DWARF v5 +/// standard for location lists and range lists. The table consists of a header +/// followed by an array of offsets into a DWARF section, followed by zero or +/// more list entries. The list entries are kept in a map where the keys are +/// the lists' section offsets. +template <typename DWARFListType> class DWARFListTableBase { + DWARFListTableHeader Header; + /// A mapping between file offsets and lists. It is used to find a particular + /// list based on an offset (obtained from DW_AT_ranges, for example). + std::map<uint32_t, DWARFListType> ListMap; + /// This string is displayed as a heading before the list is dumped + /// (e.g. "ranges:"). + StringRef HeaderString; + +protected: + DWARFListTableBase(StringRef SectionName, StringRef HeaderString, + StringRef ListTypeString) + : Header(SectionName, ListTypeString), HeaderString(HeaderString) {} + +public: + void clear() { + Header.clear(); + ListMap.clear(); + } + /// Extract the table header and the array of offsets. + Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) { + return Header.extract(Data, OffsetPtr); + } + /// Extract an entire table, including all list entries. + Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr); + /// Look up a list based on a given offset. Extract it and enter it into the + /// list map if necessary. + Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset); + + uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); } + uint8_t getAddrSize() const { return Header.getAddrSize(); } + + void dump(raw_ostream &OS, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts = {}) const; + + /// Return the contents of the offset entry designated by a given index. + Optional<uint32_t> getOffsetEntry(uint32_t Index) const { + return Header.getOffsetEntry(Index); + } + /// Return the size of the table header including the length but not including + /// the offsets. This is dependent on the table format, which is unambiguously + /// derived from parsing the table. + uint8_t getHeaderSize() const { + switch (Header.getFormat()) { + case dwarf::DwarfFormat::DWARF32: + return 12; + case dwarf::DwarfFormat::DWARF64: + return 20; + } + llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64"); + } + + uint32_t length() { return Header.length(); } +}; + +template <typename DWARFListType> +Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data, + uint32_t *OffsetPtr) { + clear(); + if (Error E = extractHeaderAndOffsets(Data, OffsetPtr)) + return E; + + Data.setAddressSize(Header.getAddrSize()); + uint32_t End = getHeaderOffset() + Header.length(); + while (*OffsetPtr < End) { + DWARFListType CurrentList; + uint32_t Off = *OffsetPtr; + if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr, + Header.getSectionName(), + Header.getListTypeString())) + return E; + ListMap[Off] = CurrentList; + } + + assert(*OffsetPtr == End && + "mismatch between expected length of table and length " + "of extracted data"); + return Error::success(); +} + +template <typename ListEntryType> +Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data, + uint32_t HeaderOffset, uint32_t End, + uint32_t *OffsetPtr, + StringRef SectionName, + StringRef ListTypeString) { + if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End) + return createStringError(errc::invalid_argument, + "invalid %s list offset 0x%" PRIx32, + ListTypeString.data(), *OffsetPtr); + Entries.clear(); + while (*OffsetPtr < End) { + ListEntryType Entry; + if (Error E = Entry.extract(Data, End, OffsetPtr)) + return E; + Entries.push_back(Entry); + if (Entry.isSentinel()) + return Error::success(); + } + return createStringError(errc::illegal_byte_sequence, + "no end of list marker detected at end of %s table " + "starting at offset 0x%" PRIx32, + SectionName.data(), HeaderOffset); +} + +template <typename DWARFListType> +void DWARFListTableBase<DWARFListType>::dump( + raw_ostream &OS, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts) const { + Header.dump(OS, DumpOpts); + OS << HeaderString << "\n"; + + // Determine the length of the longest encoding string we have in the table, + // so we can align the output properly. We only need this in verbose mode. + size_t MaxEncodingStringLength = 0; + if (DumpOpts.Verbose) { + for (const auto &List : ListMap) + for (const auto &Entry : List.second.getEntries()) + MaxEncodingStringLength = + std::max(MaxEncodingStringLength, + dwarf::RangeListEncodingString(Entry.EntryKind).size()); + } + + uint64_t CurrentBase = 0; + for (const auto &List : ListMap) + for (const auto &Entry : List.second.getEntries()) + Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase, + DumpOpts, LookupPooledAddress); +} + +template <typename DWARFListType> +Expected<DWARFListType> +DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data, + uint32_t Offset) { + auto Entry = ListMap.find(Offset); + if (Entry != ListMap.end()) + return Entry->second; + + // Extract the list from the section and enter it into the list map. + DWARFListType List; + uint32_t End = getHeaderOffset() + Header.length(); + uint32_t StartingOffset = Offset; + if (Error E = + List.extract(Data, getHeaderOffset(), End, &Offset, + Header.getSectionName(), Header.getListTypeString())) + return std::move(E); + ListMap[StartingOffset] = List; + return List; +} + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFLISTTABLE_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFObject.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFObject.h new file mode 100644 index 00000000..1bba74a2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFObject.h @@ -0,0 +1,85 @@ +//===- DWARFObject.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_DWARF_DWARFOBJECT_H +#define LLVM_DEBUGINFO_DWARF_DWARFOBJECT_H + +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/Object/ObjectFile.h" + +namespace llvm { +// This is responsible for low level access to the object file. It +// knows how to find the required sections and compute relocated +// values. +// The default implementations of the get<Section> methods return dummy values. +// This is to allow clients that only need some of those to implement just the +// ones they need. We can't use unreachable for as many cases because the parser +// implementation is eager and will call some of these methods even if the +// result is not used. +class DWARFObject { + DWARFSection Dummy; + +public: + virtual ~DWARFObject() = default; + virtual StringRef getFileName() const { llvm_unreachable("unimplemented"); } + virtual const object::ObjectFile *getFile() const { return nullptr; } + virtual ArrayRef<SectionName> getSectionNames() const { return {}; } + virtual bool isLittleEndian() const = 0; + virtual uint8_t getAddressSize() const { llvm_unreachable("unimplemented"); } + virtual void + forEachInfoSections(function_ref<void(const DWARFSection &)> F) const {} + virtual void + forEachTypesSections(function_ref<void(const DWARFSection &)> F) const {} + virtual StringRef getAbbrevSection() const { return ""; } + virtual const DWARFSection &getLocSection() const { return Dummy; } + virtual const DWARFSection &getLoclistsSection() const { return Dummy; } + virtual StringRef getARangeSection() const { return ""; } + virtual StringRef getDebugFrameSection() const { return ""; } + virtual StringRef getEHFrameSection() const { return ""; } + virtual const DWARFSection &getLineSection() const { return Dummy; } + virtual StringRef getLineStringSection() const { return ""; } + virtual StringRef getStringSection() const { return ""; } + virtual const DWARFSection &getRangeSection() const { return Dummy; } + virtual const DWARFSection &getRnglistsSection() const { return Dummy; } + virtual StringRef getMacinfoSection() const { return ""; } + virtual const DWARFSection &getPubNamesSection() const { return Dummy; } + virtual const DWARFSection &getPubTypesSection() const { return Dummy; } + virtual const DWARFSection &getGnuPubNamesSection() const { return Dummy; } + virtual const DWARFSection &getGnuPubTypesSection() const { return Dummy; } + virtual const DWARFSection &getStringOffsetSection() const { return Dummy; } + virtual void + forEachInfoDWOSections(function_ref<void(const DWARFSection &)> F) const {} + virtual void + forEachTypesDWOSections(function_ref<void(const DWARFSection &)> F) const {} + virtual StringRef getAbbrevDWOSection() const { return ""; } + virtual const DWARFSection &getLineDWOSection() const { return Dummy; } + virtual const DWARFSection &getLocDWOSection() const { return Dummy; } + virtual StringRef getStringDWOSection() const { return ""; } + virtual const DWARFSection &getStringOffsetDWOSection() const { + return Dummy; + } + virtual const DWARFSection &getRangeDWOSection() const { return Dummy; } + virtual const DWARFSection &getRnglistsDWOSection() const { return Dummy; } + virtual const DWARFSection &getAddrSection() const { return Dummy; } + virtual const DWARFSection &getAppleNamesSection() const { return Dummy; } + virtual const DWARFSection &getAppleTypesSection() const { return Dummy; } + virtual const DWARFSection &getAppleNamespacesSection() const { + return Dummy; + } + virtual const DWARFSection &getDebugNamesSection() const { return Dummy; } + virtual const DWARFSection &getAppleObjCSection() const { return Dummy; } + virtual StringRef getCUIndexSection() const { return ""; } + virtual StringRef getGdbIndexSection() const { return ""; } + virtual StringRef getTUIndexSection() const { return ""; } + virtual Optional<RelocAddrEntry> find(const DWARFSection &Sec, + uint64_t Pos) const = 0; +}; + +} // namespace llvm +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h new file mode 100644 index 00000000..a8f5b284 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h @@ -0,0 +1,33 @@ +//===- DWARFRelocMap.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_DWARF_DWARFRELOCMAP_H +#define LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H + +#include "llvm/ADT/DenseMap.h" +#include <cstdint> + +namespace llvm { + +/// RelocAddrEntry contains relocated value and section index. +/// Section index is -1LL if relocation points to absolute symbol. +struct RelocAddrEntry { + uint64_t SectionIndex; + uint64_t Value; +}; + +/// In place of applying the relocations to the data we've read from disk we use +/// a separate mapping table to the side and checking that at locations in the +/// dwarf where we expect relocated values. This adds a bit of complexity to the +/// dwarf parsing/extraction at the benefit of not allocating memory for the +/// entire size of the debug info sections. +using RelocAddrMap = DenseMap<uint64_t, RelocAddrEntry>; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFSection.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFSection.h new file mode 100644 index 00000000..bb000461 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -0,0 +1,32 @@ +//===- DWARFSection.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_DWARF_DWARFSECTION_H +#define LLVM_DEBUGINFO_DWARF_DWARFSECTION_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +struct DWARFSection { + StringRef Data; +}; + +struct SectionName { + StringRef Name; + bool IsNameUnique; +}; + +struct SectionedAddress { + uint64_t Address; + uint64_t SectionIndex; +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFSECTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h new file mode 100644 index 00000000..90d89375 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -0,0 +1,46 @@ +//===- DWARFTypeUnit.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_DWARF_DWARFTYPEUNIT_H +#define LLVM_DEBUGINFO_DWARF_DWARFTYPEUNIT_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" +#include "llvm/Support/DataExtractor.h" +#include <cstdint> + +namespace llvm { + +class DWARFContext; +class DWARFDebugAbbrev; +struct DWARFSection; +class raw_ostream; + +class DWARFTypeUnit : public DWARFUnit { +public: + DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, + StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, + const DWARFSection &LS, bool LE, bool IsDWO, + const DWARFUnitVector &UnitVector) + : DWARFUnit(Context, Section, Header, DA, RS, LocSection, SS, SOS, AOS, + LS, LE, IsDWO, UnitVector) {} + + uint64_t getTypeHash() const { return getHeader().getTypeHash(); } + uint32_t getTypeOffset() const { return getHeader().getTypeOffset(); } + + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; + // Enable LLVM-style RTTI. + static bool classof(const DWARFUnit *U) { return U->isTypeUnit(); } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFTYPEUNIT_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFUnit.h new file mode 100644 index 00000000..e82ce8ed --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -0,0 +1,511 @@ +//===- DWARFUnit.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_DWARF_DWARFUNIT_H +#define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" +#include "llvm/Support/DataExtractor.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <map> +#include <memory> +#include <utility> +#include <vector> + +namespace llvm { + +class DWARFAbbreviationDeclarationSet; +class DWARFContext; +class DWARFDebugAbbrev; +class DWARFUnit; + +/// Base class describing the header of any kind of "unit." Some information +/// is specific to certain unit types. We separate this class out so we can +/// parse the header before deciding what specific kind of unit to construct. +class DWARFUnitHeader { + // Offset within section. + uint32_t Offset = 0; + // Version, address size, and DWARF format. + dwarf::FormParams FormParams; + uint32_t Length = 0; + uint64_t AbbrOffset = 0; + + // For DWO units only. + const DWARFUnitIndex::Entry *IndexEntry = nullptr; + + // For type units only. + uint64_t TypeHash = 0; + uint32_t TypeOffset = 0; + + // For v5 split or skeleton compile units only. + Optional<uint64_t> DWOId; + + // Unit type as parsed, or derived from the section kind. + uint8_t UnitType = 0; + + // Size as parsed. uint8_t for compactness. + uint8_t Size = 0; + +public: + /// Parse a unit header from \p debug_info starting at \p offset_ptr. + bool extract(DWARFContext &Context, const DWARFDataExtractor &debug_info, + uint32_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO, + const DWARFUnitIndex *Index = nullptr, + const DWARFUnitIndex::Entry *Entry = nullptr); + uint32_t getOffset() const { return Offset; } + const dwarf::FormParams &getFormParams() const { return FormParams; } + uint16_t getVersion() const { return FormParams.Version; } + dwarf::DwarfFormat getFormat() const { return FormParams.Format; } + uint8_t getAddressByteSize() const { return FormParams.AddrSize; } + uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); } + uint8_t getDwarfOffsetByteSize() const { + return FormParams.getDwarfOffsetByteSize(); + } + uint32_t getLength() const { return Length; } + uint64_t getAbbrOffset() const { return AbbrOffset; } + Optional<uint64_t> getDWOId() const { return DWOId; } + void setDWOId(uint64_t Id) { + assert((!DWOId || *DWOId == Id) && "setting DWOId to a different value"); + DWOId = Id; + } + const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; } + uint64_t getTypeHash() const { return TypeHash; } + uint32_t getTypeOffset() const { return TypeOffset; } + uint8_t getUnitType() const { return UnitType; } + bool isTypeUnit() const { + return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type; + } + uint8_t getSize() const { return Size; } + // FIXME: Support DWARF64. + uint32_t getNextUnitOffset() const { return Offset + Length + 4; } +}; + +const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, + DWARFSectionKind Kind); + +/// Describe a collection of units. Intended to hold all units either from +/// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo. +class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1> { + std::function<std::unique_ptr<DWARFUnit>(uint32_t, DWARFSectionKind, + const DWARFSection *, + const DWARFUnitIndex::Entry *)> + Parser; + int NumInfoUnits = -1; + +public: + using UnitVector = SmallVectorImpl<std::unique_ptr<DWARFUnit>>; + using iterator = typename UnitVector::iterator; + using iterator_range = llvm::iterator_range<typename UnitVector::iterator>; + + DWARFUnit *getUnitForOffset(uint32_t Offset) const; + DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E); + + /// Read units from a .debug_info or .debug_types section. Calls made + /// before finishedInfoUnits() are assumed to be for .debug_info sections, + /// calls after finishedInfoUnits() are for .debug_types sections. Caller + /// must not mix calls to addUnitsForSection and addUnitsForDWOSection. + void addUnitsForSection(DWARFContext &C, const DWARFSection &Section, + DWARFSectionKind SectionKind); + /// Read units from a .debug_info.dwo or .debug_types.dwo section. Calls + /// made before finishedInfoUnits() are assumed to be for .debug_info.dwo + /// sections, calls after finishedInfoUnits() are for .debug_types.dwo + /// sections. Caller must not mix calls to addUnitsForSection and + /// addUnitsForDWOSection. + void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection, + DWARFSectionKind SectionKind, bool Lazy = false); + + /// Add an existing DWARFUnit to this UnitVector. This is used by the DWARF + /// verifier to process unit separately. + DWARFUnit *addUnit(std::unique_ptr<DWARFUnit> Unit); + + /// Returns number of all units held by this instance. + unsigned getNumUnits() const { return size(); } + /// Returns number of units from all .debug_info[.dwo] sections. + unsigned getNumInfoUnits() const { + return NumInfoUnits == -1 ? size() : NumInfoUnits; + } + /// Returns number of units from all .debug_types[.dwo] sections. + unsigned getNumTypesUnits() const { return size() - NumInfoUnits; } + /// Indicate that parsing .debug_info[.dwo] is done, and remaining units + /// will be from .debug_types[.dwo]. + void finishedInfoUnits() { NumInfoUnits = size(); } + +private: + void addUnitsImpl(DWARFContext &Context, const DWARFObject &Obj, + const DWARFSection &Section, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, + StringRef SS, const DWARFSection &SOS, + const DWARFSection *AOS, const DWARFSection &LS, bool LE, + bool IsDWO, bool Lazy, DWARFSectionKind SectionKind); +}; + +/// Represents base address of the CU. +/// Represents a unit's contribution to the string offsets table. +struct StrOffsetsContributionDescriptor { + uint64_t Base = 0; + /// The contribution size not including the header. + uint64_t Size = 0; + /// Format and version. + dwarf::FormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32}; + + StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size, + uint8_t Version, dwarf::DwarfFormat Format) + : Base(Base), Size(Size), FormParams({Version, 0, Format}) {} + + uint8_t getVersion() const { return FormParams.Version; } + dwarf::DwarfFormat getFormat() const { return FormParams.Format; } + uint8_t getDwarfOffsetByteSize() const { + return FormParams.getDwarfOffsetByteSize(); + } + /// Determine whether a contribution to the string offsets table is + /// consistent with the relevant section size and that its length is + /// a multiple of the size of one of its entries. + Optional<StrOffsetsContributionDescriptor> + validateContributionSize(DWARFDataExtractor &DA); +}; + +class DWARFUnit { + DWARFContext &Context; + /// Section containing this DWARFUnit. + const DWARFSection &InfoSection; + + DWARFUnitHeader Header; + const DWARFDebugAbbrev *Abbrev; + const DWARFSection *RangeSection; + uint32_t RangeSectionBase; + /// We either keep track of the location list section or its data, depending + /// on whether we are handling a split DWARF section or not. + union { + const DWARFSection *LocSection; + StringRef LocSectionData; + }; + const DWARFSection &LineSection; + StringRef StringSection; + const DWARFSection &StringOffsetSection; + const DWARFSection *AddrOffsetSection; + uint32_t AddrOffsetSectionBase = 0; + bool isLittleEndian; + bool IsDWO; + const DWARFUnitVector &UnitVector; + + /// Start, length, and DWARF format of the unit's contribution to the string + /// offsets table (DWARF v5). + Optional<StrOffsetsContributionDescriptor> StringOffsetsTableContribution; + + /// A table of range lists (DWARF v5 and later). + Optional<DWARFDebugRnglistTable> RngListTable; + + mutable const DWARFAbbreviationDeclarationSet *Abbrevs; + llvm::Optional<SectionedAddress> BaseAddr; + /// The compile unit debug information entry items. + std::vector<DWARFDebugInfoEntry> DieArray; + + /// Map from range's start address to end address and corresponding DIE. + /// IntervalMap does not support range removal, as a result, we use the + /// std::map::upper_bound for address range lookup. + std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap; + + using die_iterator_range = + iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>; + + std::shared_ptr<DWARFUnit> DWO; + + uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) { + auto First = DieArray.data(); + assert(Die >= First && Die < First + DieArray.size()); + return Die - First; + } + +protected: + const DWARFUnitHeader &getHeader() const { return Header; } + + /// Size in bytes of the parsed unit header. + uint32_t getHeaderSize() const { return Header.getSize(); } + + /// Find the unit's contribution to the string offsets table and determine its + /// length and form. The given offset is expected to be derived from the unit + /// DIE's DW_AT_str_offsets_base attribute. + Optional<StrOffsetsContributionDescriptor> + determineStringOffsetsTableContribution(DWARFDataExtractor &DA); + + /// Find the unit's contribution to the string offsets table and determine its + /// length and form. The given offset is expected to be 0 in a dwo file or, + /// in a dwp file, the start of the unit's contribution to the string offsets + /// table section (as determined by the index table). + Optional<StrOffsetsContributionDescriptor> + determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA); + +public: + DWARFUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, + StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, + const DWARFSection &LS, bool LE, bool IsDWO, + const DWARFUnitVector &UnitVector); + + virtual ~DWARFUnit(); + + bool isDWOUnit() const { return IsDWO; } + DWARFContext& getContext() const { return Context; } + const DWARFSection &getInfoSection() const { return InfoSection; } + const DWARFSection *getLocSection() const { return LocSection; } + StringRef getLocSectionData() const { return LocSectionData; } + uint32_t getOffset() const { return Header.getOffset(); } + const dwarf::FormParams &getFormParams() const { + return Header.getFormParams(); + } + uint16_t getVersion() const { return Header.getVersion(); } + uint8_t getAddressByteSize() const { return Header.getAddressByteSize(); } + uint8_t getRefAddrByteSize() const { return Header.getRefAddrByteSize(); } + uint8_t getDwarfOffsetByteSize() const { + return Header.getDwarfOffsetByteSize(); + } + uint32_t getLength() const { return Header.getLength(); } + uint8_t getUnitType() const { return Header.getUnitType(); } + bool isTypeUnit() const { return Header.isTypeUnit(); } + uint32_t getNextUnitOffset() const { return Header.getNextUnitOffset(); } + const DWARFSection &getLineSection() const { return LineSection; } + StringRef getStringSection() const { return StringSection; } + const DWARFSection &getStringOffsetSection() const { + return StringOffsetSection; + } + + void setAddrOffsetSection(const DWARFSection *AOS, uint32_t Base) { + AddrOffsetSection = AOS; + AddrOffsetSectionBase = Base; + } + + /// Recursively update address to Die map. + void updateAddressDieMap(DWARFDie Die); + + void setRangesSection(const DWARFSection *RS, uint32_t Base) { + RangeSection = RS; + RangeSectionBase = Base; + } + + Optional<SectionedAddress> getAddrOffsetSectionItem(uint32_t Index) const; + Optional<uint64_t> getStringOffsetSectionItem(uint32_t Index) const; + + DWARFDataExtractor getDebugInfoExtractor() const; + + DataExtractor getStringExtractor() const { + return DataExtractor(StringSection, false, 0); + } + + /// Extract the range list referenced by this compile unit from the + /// .debug_ranges section. If the extraction is unsuccessful, an error + /// is returned. Successful extraction requires that the compile unit + /// has already been extracted. + Error extractRangeList(uint32_t RangeListOffset, + DWARFDebugRangeList &RangeList) const; + void clear(); + + const Optional<StrOffsetsContributionDescriptor> & + getStringOffsetsTableContribution() const { + return StringOffsetsTableContribution; + } + + uint8_t getDwarfStringOffsetsByteSize() const { + assert(StringOffsetsTableContribution); + return StringOffsetsTableContribution->getDwarfOffsetByteSize(); + } + + uint64_t getStringOffsetsBase() const { + assert(StringOffsetsTableContribution); + return StringOffsetsTableContribution->Base; + } + + const DWARFAbbreviationDeclarationSet *getAbbreviations() const; + + static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) { + switch (UnitType) { + case dwarf::DW_UT_compile: + return Tag == dwarf::DW_TAG_compile_unit; + case dwarf::DW_UT_type: + return Tag == dwarf::DW_TAG_type_unit; + case dwarf::DW_UT_partial: + return Tag == dwarf::DW_TAG_partial_unit; + case dwarf::DW_UT_skeleton: + return Tag == dwarf::DW_TAG_skeleton_unit; + case dwarf::DW_UT_split_compile: + case dwarf::DW_UT_split_type: + return dwarf::isUnitType(Tag); + } + return false; + } + + /// Return the number of bytes for the header of a unit of + /// UnitType type. + /// + /// This function must be called with a valid unit type which in + /// DWARF5 is defined as one of the following six types. + static uint32_t getDWARF5HeaderSize(uint8_t UnitType) { + switch (UnitType) { + case dwarf::DW_UT_compile: + case dwarf::DW_UT_partial: + return 12; + case dwarf::DW_UT_skeleton: + case dwarf::DW_UT_split_compile: + return 20; + case dwarf::DW_UT_type: + case dwarf::DW_UT_split_type: + return 24; + } + llvm_unreachable("Invalid UnitType."); + } + + llvm::Optional<SectionedAddress> getBaseAddress(); + + DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { + extractDIEsIfNeeded(ExtractUnitDIEOnly); + if (DieArray.empty()) + return DWARFDie(); + return DWARFDie(this, &DieArray[0]); + } + + const char *getCompilationDir(); + Optional<uint64_t> getDWOId() { + extractDIEsIfNeeded(/*CUDieOnly*/ true); + return getHeader().getDWOId(); + } + void setDWOId(uint64_t NewID) { Header.setDWOId(NewID); } + + /// Return a vector of address ranges resulting from a (possibly encoded) + /// range list starting at a given offset in the appropriate ranges section. + Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint32_t Offset); + + /// Return a vector of address ranges retrieved from an encoded range + /// list whose offset is found via a table lookup given an index (DWARF v5 + /// and later). + Expected<DWARFAddressRangesVector> findRnglistFromIndex(uint32_t Index); + + /// Return a rangelist's offset based on an index. The index designates + /// an entry in the rangelist table's offset array and is supplied by + /// DW_FORM_rnglistx. + Optional<uint32_t> getRnglistOffset(uint32_t Index) { + if (RngListTable) + return RngListTable->getOffsetEntry(Index); + return None; + } + + Expected<DWARFAddressRangesVector> collectAddressRanges(); + + /// Returns subprogram DIE with address range encompassing the provided + /// address. The pointer is alive as long as parsed compile unit DIEs are not + /// cleared. + DWARFDie getSubroutineForAddress(uint64_t Address); + + /// getInlinedChainForAddress - fetches inlined chain for a given address. + /// Returns empty chain if there is no subprogram containing address. The + /// chain is valid as long as parsed compile unit DIEs are not cleared. + void getInlinedChainForAddress(uint64_t Address, + SmallVectorImpl<DWARFDie> &InlinedChain); + + /// Return the DWARFUnitVector containing this unit. + const DWARFUnitVector &getUnitVector() const { return UnitVector; } + + /// Returns the number of DIEs in the unit. Parses the unit + /// if necessary. + unsigned getNumDIEs() { + extractDIEsIfNeeded(false); + return DieArray.size(); + } + + /// Return the index of a DIE inside the unit's DIE vector. + /// + /// It is illegal to call this method with a DIE that hasn't be + /// created by this unit. In other word, it's illegal to call this + /// method on a DIE that isn't accessible by following + /// children/sibling links starting from this unit's getUnitDIE(). + uint32_t getDIEIndex(const DWARFDie &D) { + return getDIEIndex(D.getDebugInfoEntry()); + } + + /// Return the DIE object at the given index. + DWARFDie getDIEAtIndex(unsigned Index) { + assert(Index < DieArray.size()); + return DWARFDie(this, &DieArray[Index]); + } + + DWARFDie getParent(const DWARFDebugInfoEntry *Die); + DWARFDie getSibling(const DWARFDebugInfoEntry *Die); + DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die); + DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die); + DWARFDie getLastChild(const DWARFDebugInfoEntry *Die); + + /// Return the DIE object for a given offset inside the + /// unit's DIE vector. + /// + /// The unit needs to have its DIEs extracted for this method to work. + DWARFDie getDIEForOffset(uint32_t Offset) { + extractDIEsIfNeeded(false); + assert(!DieArray.empty()); + auto it = std::lower_bound( + DieArray.begin(), DieArray.end(), Offset, + [](const DWARFDebugInfoEntry &LHS, uint32_t Offset) { + return LHS.getOffset() < Offset; + }); + if (it != DieArray.end() && it->getOffset() == Offset) + return DWARFDie(this, &*it); + return DWARFDie(); + } + + uint32_t getLineTableOffset() const { + if (auto IndexEntry = Header.getIndexEntry()) + if (const auto *Contrib = IndexEntry->getOffset(DW_SECT_LINE)) + return Contrib->Offset; + return 0; + } + + die_iterator_range dies() { + extractDIEsIfNeeded(false); + return die_iterator_range(DieArray.begin(), DieArray.end()); + } + + virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0; +private: + /// Size in bytes of the .debug_info data associated with this compile unit. + size_t getDebugInfoSize() const { + return Header.getLength() + 4 - getHeaderSize(); + } + + /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it + /// hasn't already been done. Returns the number of DIEs parsed at this call. + size_t extractDIEsIfNeeded(bool CUDieOnly); + + /// extractDIEsToVector - Appends all parsed DIEs to a vector. + void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, + std::vector<DWARFDebugInfoEntry> &DIEs) const; + + /// clearDIEs - Clear parsed DIEs to keep memory usage low. + void clearDIEs(bool KeepCUDie); + + /// parseDWO - Parses .dwo file for current compile unit. Returns true if + /// it was actually constructed. + bool parseDWO(); +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h new file mode 100644 index 00000000..fc8c707c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h @@ -0,0 +1,105 @@ +//===- DWARFUnitIndex.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_DWARF_DWARFUNITINDEX_H +#define LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataExtractor.h" +#include <cstdint> +#include <memory> + +namespace llvm { + +class raw_ostream; + +enum DWARFSectionKind { + DW_SECT_INFO = 1, + DW_SECT_TYPES, + DW_SECT_ABBREV, + DW_SECT_LINE, + DW_SECT_LOC, + DW_SECT_STR_OFFSETS, + DW_SECT_MACINFO, + DW_SECT_MACRO, +}; + +class DWARFUnitIndex { + struct Header { + uint32_t Version; + uint32_t NumColumns; + uint32_t NumUnits; + uint32_t NumBuckets = 0; + + bool parse(DataExtractor IndexData, uint32_t *OffsetPtr); + void dump(raw_ostream &OS) const; + }; + +public: + class Entry { + public: + struct SectionContribution { + uint32_t Offset; + uint32_t Length; + }; + + private: + const DWARFUnitIndex *Index; + uint64_t Signature; + std::unique_ptr<SectionContribution[]> Contributions; + friend class DWARFUnitIndex; + + public: + const SectionContribution *getOffset(DWARFSectionKind Sec) const; + const SectionContribution *getOffset() const; + + const SectionContribution *getOffsets() const { + return Contributions.get(); + } + + uint64_t getSignature() const { return Signature; } + }; + +private: + struct Header Header; + + DWARFSectionKind InfoColumnKind; + int InfoColumn = -1; + std::unique_ptr<DWARFSectionKind[]> ColumnKinds; + std::unique_ptr<Entry[]> Rows; + mutable std::vector<Entry *> OffsetLookup; + + static StringRef getColumnHeader(DWARFSectionKind DS); + + bool parseImpl(DataExtractor IndexData); + +public: + DWARFUnitIndex(DWARFSectionKind InfoColumnKind) + : InfoColumnKind(InfoColumnKind) {} + + explicit operator bool() const { return Header.NumBuckets; } + + bool parse(DataExtractor IndexData); + void dump(raw_ostream &OS) const; + + const Entry *getFromOffset(uint32_t Offset) const; + const Entry *getFromHash(uint64_t Offset) const; + + ArrayRef<DWARFSectionKind> getColumnKinds() const { + return makeArrayRef(ColumnKinds.get(), Header.NumColumns); + } + + ArrayRef<Entry> getRows() const { + return makeArrayRef(Rows.get(), Header.NumBuckets); + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H diff --git a/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFVerifier.h new file mode 100644 index 00000000..f1268f22 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -0,0 +1,336 @@ +//===- DWARFVerifier.h ----------------------------------------------------===// +// +// 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_DWARF_DWARFVERIFIER_H +#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H + +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" + +#include <cstdint> +#include <map> +#include <set> + +namespace llvm { +class raw_ostream; +struct DWARFAttribute; +class DWARFContext; +class DWARFDie; +class DWARFUnit; +class DWARFCompileUnit; +class DWARFDataExtractor; +class DWARFDebugAbbrev; +class DataExtractor; +struct DWARFSection; + +/// A class that verifies DWARF debug information given a DWARF Context. +class DWARFVerifier { +public: + /// A class that keeps the address range information for a single DIE. + struct DieRangeInfo { + DWARFDie Die; + + /// Sorted DWARFAddressRanges. + std::vector<DWARFAddressRange> Ranges; + + /// Sorted DWARFAddressRangeInfo. + std::set<DieRangeInfo> Children; + + DieRangeInfo() = default; + DieRangeInfo(DWARFDie Die) : Die(Die) {} + + /// Used for unit testing. + DieRangeInfo(std::vector<DWARFAddressRange> Ranges) + : Ranges(std::move(Ranges)) {} + + typedef std::vector<DWARFAddressRange>::const_iterator + address_range_iterator; + typedef std::set<DieRangeInfo>::const_iterator die_range_info_iterator; + + /// Inserts the address range. If the range overlaps with an existing + /// range, the range is *not* added and an iterator to the overlapping + /// range is returned. + /// + /// This is used for finding overlapping ranges within the same DIE. + address_range_iterator insert(const DWARFAddressRange &R); + + /// Finds an address range in the sorted vector of ranges. + address_range_iterator findRange(const DWARFAddressRange &R) const { + auto Begin = Ranges.begin(); + auto End = Ranges.end(); + auto Iter = std::upper_bound(Begin, End, R); + if (Iter != Begin) + --Iter; + return Iter; + } + + /// Inserts the address range info. If any of its ranges overlaps with a + /// range in an existing range info, the range info is *not* added and an + /// iterator to the overlapping range info. + /// + /// This is used for finding overlapping children of the same DIE. + die_range_info_iterator insert(const DieRangeInfo &RI); + + /// Return true if ranges in this object contains all ranges within RHS. + bool contains(const DieRangeInfo &RHS) const; + + /// Return true if any range in this object intersects with any range in + /// RHS. + bool intersects(const DieRangeInfo &RHS) const; + }; + +private: + raw_ostream &OS; + DWARFContext &DCtx; + DIDumpOptions DumpOpts; + /// A map that tracks all references (converted absolute references) so we + /// can verify each reference points to a valid DIE and not an offset that + /// lies between to valid DIEs. + std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets; + uint32_t NumDebugLineErrors = 0; + // Used to relax some checks that do not currently work portably + bool IsObjectFile; + bool IsMachOObject; + + raw_ostream &error() const; + raw_ostream &warn() const; + raw_ostream ¬e() const; + raw_ostream &dump(const DWARFDie &Die, unsigned indent = 0) const; + + /// Verifies the abbreviations section. + /// + /// This function currently checks that: + /// --No abbreviation declaration has more than one attributes with the same + /// name. + /// + /// \param Abbrev Pointer to the abbreviations section we are verifying + /// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo. + /// + /// \returns The number of errors that occurred during verification. + unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev); + + /// Verifies the header of a unit in a .debug_info or .debug_types section. + /// + /// This function currently checks for: + /// - Unit is in 32-bit DWARF format. The function can be modified to + /// support 64-bit format. + /// - The DWARF version is valid + /// - The unit type is valid (if unit is in version >=5) + /// - The unit doesn't extend beyond the containing section + /// - The address size is valid + /// - The offset in the .debug_abbrev section is valid + /// + /// \param DebugInfoData The section data + /// \param Offset A reference to the offset start of the unit. The offset will + /// be updated to point to the next unit in the section + /// \param UnitIndex The index of the unit to be verified + /// \param UnitType A reference to the type of the unit + /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is + /// in 64-bit format. + /// + /// \returns true if the header is verified successfully, false otherwise. + bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData, + uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType, + bool &isUnitDWARF64); + + /// Verifies the header of a unit in a .debug_info or .debug_types section. + /// + /// This function currently verifies: + /// - The debug info attributes. + /// - The debug info form=s. + /// - The presence of a root DIE. + /// - That the root DIE is a unit DIE. + /// - If a unit type is provided, that the unit DIE matches the unit type. + /// - The DIE ranges. + /// - That call site entries are only nested within subprograms with a + /// DW_AT_call attribute. + /// + /// \param Unit The DWARF Unit to verify. + /// + /// \returns The number of errors that occurred during verification. + unsigned verifyUnitContents(DWARFUnit &Unit); + + /// Verifies the unit headers and contents in a .debug_info or .debug_types + /// section. + /// + /// \param S The DWARF Section to verify. + /// \param SectionKind The object-file section kind that S comes from. + /// + /// \returns The number of errors that occurred during verification. + unsigned verifyUnitSection(const DWARFSection &S, + DWARFSectionKind SectionKind); + + /// Verifies that a call site entry is nested within a subprogram with a + /// DW_AT_call attribute. + /// + /// \returns Number of errors that occurred during verification. + unsigned verifyDebugInfoCallSite(const DWARFDie &Die); + + /// Verify that all Die ranges are valid. + /// + /// This function currently checks for: + /// - cases in which lowPC >= highPC + /// + /// \returns Number of errors that occurred during verification. + unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI); + + /// Verifies the attribute's DWARF attribute and its value. + /// + /// This function currently checks for: + /// - DW_AT_ranges values is a valid .debug_ranges offset + /// - DW_AT_stmt_list is a valid .debug_line offset + /// + /// \param Die The DWARF DIE that owns the attribute value + /// \param AttrValue The DWARF attribute value to check + /// + /// \returns NumErrors The number of errors occurred during verification of + /// attributes' values in a unit + unsigned verifyDebugInfoAttribute(const DWARFDie &Die, + DWARFAttribute &AttrValue); + + /// Verifies the attribute's DWARF form. + /// + /// This function currently checks for: + /// - All DW_FORM_ref values that are CU relative have valid CU offsets + /// - All DW_FORM_ref_addr values have valid section offsets + /// - All DW_FORM_strp values have valid .debug_str offsets + /// + /// \param Die The DWARF DIE that owns the attribute value + /// \param AttrValue The DWARF attribute value to check + /// + /// \returns NumErrors The number of errors occurred during verification of + /// attributes' forms in a unit + unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue); + + /// Verifies the all valid references that were found when iterating through + /// all of the DIE attributes. + /// + /// This function will verify that all references point to DIEs whose DIE + /// offset matches. This helps to ensure if a DWARF link phase moved things + /// around, that it doesn't create invalid references by failing to relocate + /// CU relative and absolute references. + /// + /// \returns NumErrors The number of errors occurred during verification of + /// references for the .debug_info and .debug_types sections + unsigned verifyDebugInfoReferences(); + + /// Verify the DW_AT_stmt_list encoding and value and ensure that no + /// compile units that have the same DW_AT_stmt_list value. + void verifyDebugLineStmtOffsets(); + + /// Verify that all of the rows in the line table are valid. + /// + /// This function currently checks for: + /// - addresses within a sequence that decrease in value + /// - invalid file indexes + void verifyDebugLineRows(); + + /// Verify that an Apple-style accelerator table is valid. + /// + /// This function currently checks that: + /// - The fixed part of the header fits in the section + /// - The size of the section is as large as what the header describes + /// - There is at least one atom + /// - The form for each atom is valid + /// - The tag for each DIE in the table is valid + /// - The buckets have a valid index, or they are empty + /// - Each hashdata offset is valid + /// - Each DIE is valid + /// + /// \param AccelSection pointer to the section containing the acceleration table + /// \param StrData pointer to the string section + /// \param SectionName the name of the table we're verifying + /// + /// \returns The number of errors occurred during verification + unsigned verifyAppleAccelTable(const DWARFSection *AccelSection, + DataExtractor *StrData, + const char *SectionName); + + unsigned verifyDebugNamesCULists(const DWARFDebugNames &AccelTable); + unsigned verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI, + const DataExtractor &StrData); + unsigned verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI); + unsigned verifyNameIndexAttribute(const DWARFDebugNames::NameIndex &NI, + const DWARFDebugNames::Abbrev &Abbr, + DWARFDebugNames::AttributeEncoding AttrEnc); + unsigned verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI, + const DWARFDebugNames::NameTableEntry &NTE); + unsigned verifyNameIndexCompleteness(const DWARFDie &Die, + const DWARFDebugNames::NameIndex &NI); + + /// Verify that the DWARF v5 accelerator table is valid. + /// + /// This function currently checks that: + /// - Headers individual Name Indices fit into the section and can be parsed. + /// - Abbreviation tables can be parsed and contain valid index attributes + /// with correct form encodings. + /// - The CU lists reference existing compile units. + /// - The buckets have a valid index, or they are empty. + /// - All names are reachable via the hash table (they have the correct hash, + /// and the hash is in the correct bucket). + /// - Information in the index entries is complete (all required entries are + /// present) and consistent with the debug_info section DIEs. + /// + /// \param AccelSection section containing the acceleration table + /// \param StrData string section + /// + /// \returns The number of errors occurred during verification + unsigned verifyDebugNames(const DWARFSection &AccelSection, + const DataExtractor &StrData); + +public: + DWARFVerifier(raw_ostream &S, DWARFContext &D, + DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE()); + + /// Verify the information in any of the following sections, if available: + /// .debug_abbrev, debug_abbrev.dwo + /// + /// Any errors are reported to the stream that was this object was + /// constructed with. + /// + /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully, + /// false otherwise. + bool handleDebugAbbrev(); + + /// Verify the information in the .debug_info and .debug_types sections. + /// + /// Any errors are reported to the stream that this object was + /// constructed with. + /// + /// \returns true if all sections verify successfully, false otherwise. + bool handleDebugInfo(); + + /// Verify the information in the .debug_line section. + /// + /// Any errors are reported to the stream that was this object was + /// constructed with. + /// + /// \returns true if the .debug_line verifies successfully, false otherwise. + bool handleDebugLine(); + + /// Verify the information in accelerator tables, if they exist. + /// + /// Any errors are reported to the stream that was this object was + /// constructed with. + /// + /// \returns true if the existing Apple-style accelerator tables verify + /// successfully, false otherwise. + bool handleAccelTables(); +}; + +static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS, + const DWARFVerifier::DieRangeInfo &RHS) { + return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die); +} + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H diff --git a/clang-r353983/include/llvm/DebugInfo/MSF/IMSFFile.h b/clang-r353983/include/llvm/DebugInfo/MSF/IMSFFile.h new file mode 100644 index 00000000..7e80f96b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/MSF/IMSFFile.h @@ -0,0 +1,41 @@ +//===- IMSFFile.h - Abstract base class for an MSF file ---------*- 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_MSF_IMSFFILE_H +#define LLVM_DEBUGINFO_MSF_IMSFFILE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> + +namespace llvm { +namespace msf { + +class IMSFFile { +public: + virtual ~IMSFFile() = default; + + virtual uint32_t getBlockSize() const = 0; + virtual uint32_t getBlockCount() const = 0; + + virtual uint32_t getNumStreams() const = 0; + virtual uint32_t getStreamByteSize(uint32_t StreamIndex) const = 0; + virtual ArrayRef<support::ulittle32_t> + getStreamBlockList(uint32_t StreamIndex) const = 0; + + virtual Expected<ArrayRef<uint8_t>> getBlockData(uint32_t BlockIndex, + uint32_t NumBytes) const = 0; + virtual Error setBlockData(uint32_t BlockIndex, uint32_t Offset, + ArrayRef<uint8_t> Data) const = 0; +}; + +} // end namespace msf +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_IMSFFILE_H diff --git a/clang-r353983/include/llvm/DebugInfo/MSF/MSFBuilder.h b/clang-r353983/include/llvm/DebugInfo/MSF/MSFBuilder.h new file mode 100644 index 00000000..282870f5 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/MSF/MSFBuilder.h @@ -0,0 +1,144 @@ +//===- MSFBuilder.h - MSF Directory & Metadata Builder ----------*- 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_MSF_MSFBUILDER_H +#define LLVM_DEBUGINFO_MSF_MSFBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <utility> +#include <vector> + +namespace llvm { +class FileBufferByteStream; +class WritableBinaryStream; +namespace msf { + +class MSFBuilder { +public: + /// Create a new `MSFBuilder`. + /// + /// \param BlockSize The internal block size used by the PDB file. See + /// isValidBlockSize() for a list of valid block sizes. + /// + /// \param MinBlockCount Causes the builder to reserve up front space for + /// at least `MinBlockCount` blocks. This is useful when using `MSFBuilder` + /// to read an existing MSF that you want to write back out later. The + /// original MSF file's SuperBlock contains the exact number of blocks used + /// by the file, so is a good hint as to how many blocks the new MSF file + /// will contain. Furthermore, it is actually necessary in this case. To + /// preserve stability of the file's layout, it is helpful to try to keep + /// all streams mapped to their original block numbers. To ensure that this + /// is possible, space for all blocks must be allocated beforehand so that + /// streams can be assigned to them. + /// + /// \param CanGrow If true, any operation which results in an attempt to + /// locate a free block when all available blocks have been exhausted will + /// allocate a new block, thereby growing the size of the final MSF file. + /// When false, any such attempt will result in an error. This is especially + /// useful in testing scenarios when you know your test isn't going to do + /// anything to increase the size of the file, so having an Error returned if + /// it were to happen would catch a programming error + /// + /// \returns an llvm::Error representing whether the operation succeeded or + /// failed. Currently the only way this can fail is if an invalid block size + /// is specified, or `MinBlockCount` does not leave enough room for the + /// mandatory reserved blocks required by an MSF file. + static Expected<MSFBuilder> create(BumpPtrAllocator &Allocator, + uint32_t BlockSize, + uint32_t MinBlockCount = 0, + bool CanGrow = true); + + /// Request the block map to be at a specific block address. This is useful + /// when editing a MSF and you want the layout to be as stable as possible. + Error setBlockMapAddr(uint32_t Addr); + Error setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks); + void setFreePageMap(uint32_t Fpm); + void setUnknown1(uint32_t Unk1); + + /// Add a stream to the MSF file with the given size, occupying the given + /// list of blocks. This is useful when reading a MSF file and you want a + /// particular stream to occupy the original set of blocks. If the given + /// blocks are already allocated, or if the number of blocks specified is + /// incorrect for the given stream size, this function will return an Error. + Expected<uint32_t> addStream(uint32_t Size, ArrayRef<uint32_t> Blocks); + + /// Add a stream to the MSF file with the given size, occupying any available + /// blocks that the builder decides to use. This is useful when building a + /// new PDB file from scratch and you don't care what blocks a stream occupies + /// but you just want it to work. + Expected<uint32_t> addStream(uint32_t Size); + + /// Update the size of an existing stream. This will allocate or deallocate + /// blocks as needed to match the requested size. This can fail if `CanGrow` + /// was set to false when initializing the `MSFBuilder`. + Error setStreamSize(uint32_t Idx, uint32_t Size); + + /// Get the total number of streams in the MSF layout. This should return 1 + /// for every call to `addStream`. + uint32_t getNumStreams() const; + + /// Get the size of a stream by index. + uint32_t getStreamSize(uint32_t StreamIdx) const; + + /// Get the list of blocks allocated to a particular stream. + ArrayRef<uint32_t> getStreamBlocks(uint32_t StreamIdx) const; + + /// Get the total number of blocks that will be allocated to actual data in + /// this MSF file. + uint32_t getNumUsedBlocks() const; + + /// Get the total number of blocks that exist in the MSF file but are not + /// allocated to any valid data. + uint32_t getNumFreeBlocks() const; + + /// Get the total number of blocks in the MSF file. In practice this is equal + /// to `getNumUsedBlocks() + getNumFreeBlocks()`. + uint32_t getTotalBlockCount() const; + + /// Check whether a particular block is allocated or free. + bool isBlockFree(uint32_t Idx) const; + + /// Finalize the layout and build the headers and structures that describe the + /// MSF layout and can be written directly to the MSF file. + Expected<MSFLayout> generateLayout(); + + /// Write the MSF layout to the underlying file. + Expected<FileBufferByteStream> commit(StringRef Path, MSFLayout &Layout); + + BumpPtrAllocator &getAllocator() { return Allocator; } + +private: + MSFBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow, + BumpPtrAllocator &Allocator); + + Error allocateBlocks(uint32_t NumBlocks, MutableArrayRef<uint32_t> Blocks); + uint32_t computeDirectoryByteSize() const; + + using BlockList = std::vector<uint32_t>; + + BumpPtrAllocator &Allocator; + + bool IsGrowable; + uint32_t FreePageMap; + uint32_t Unknown1 = 0; + uint32_t BlockSize; + uint32_t BlockMapAddr; + BitVector FreeBlocks; + std::vector<uint32_t> DirectoryBlocks; + std::vector<std::pair<uint32_t, BlockList>> StreamData; +}; + +} // end namespace msf +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_MSFBUILDER_H diff --git a/clang-r353983/include/llvm/DebugInfo/MSF/MSFCommon.h b/clang-r353983/include/llvm/DebugInfo/MSF/MSFCommon.h new file mode 100644 index 00000000..83331b14 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/MSF/MSFCommon.h @@ -0,0 +1,161 @@ +//===- MSFCommon.h - Common types and functions for MSF files ---*- 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_MSF_MSFCOMMON_H +#define LLVM_DEBUGINFO_MSF_MSFCOMMON_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace msf { + +static const char Magic[] = {'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', + 't', ' ', 'C', '/', 'C', '+', '+', ' ', + 'M', 'S', 'F', ' ', '7', '.', '0', '0', + '\r', '\n', '\x1a', 'D', 'S', '\0', '\0', '\0'}; + +// The superblock is overlaid at the beginning of the file (offset 0). +// It starts with a magic header and is followed by information which +// describes the layout of the file system. +struct SuperBlock { + char MagicBytes[sizeof(Magic)]; + // The file system is split into a variable number of fixed size elements. + // These elements are referred to as blocks. The size of a block may vary + // from system to system. + support::ulittle32_t BlockSize; + // The index of the free block map. + support::ulittle32_t FreeBlockMapBlock; + // This contains the number of blocks resident in the file system. In + // practice, NumBlocks * BlockSize is equivalent to the size of the MSF + // file. + support::ulittle32_t NumBlocks; + // This contains the number of bytes which make up the directory. + support::ulittle32_t NumDirectoryBytes; + // This field's purpose is not yet known. + support::ulittle32_t Unknown1; + // This contains the block # of the block map. + support::ulittle32_t BlockMapAddr; +}; + +struct MSFLayout { + MSFLayout() = default; + + uint32_t mainFpmBlock() const { + assert(SB->FreeBlockMapBlock == 1 || SB->FreeBlockMapBlock == 2); + return SB->FreeBlockMapBlock; + } + + uint32_t alternateFpmBlock() const { + // If mainFpmBlock is 1, this is 2. If mainFpmBlock is 2, this is 1. + return 3U - mainFpmBlock(); + } + + const SuperBlock *SB = nullptr; + BitVector FreePageMap; + ArrayRef<support::ulittle32_t> DirectoryBlocks; + ArrayRef<support::ulittle32_t> StreamSizes; + std::vector<ArrayRef<support::ulittle32_t>> StreamMap; +}; + +/// Describes the layout of a stream in an MSF layout. A "stream" here +/// is defined as any logical unit of data which may be arranged inside the MSF +/// file as a sequence of (possibly discontiguous) blocks. When we want to read +/// from a particular MSF Stream, we fill out a stream layout structure and the +/// reader uses it to determine which blocks in the underlying MSF file contain +/// the data, so that it can be pieced together in the right order. +class MSFStreamLayout { +public: + uint32_t Length; + std::vector<support::ulittle32_t> Blocks; +}; + +/// Determine the layout of the FPM stream, given the MSF layout. An FPM +/// stream spans 1 or more blocks, each at equally spaced intervals throughout +/// the file. +MSFStreamLayout getFpmStreamLayout(const MSFLayout &Msf, + bool IncludeUnusedFpmData = false, + bool AltFpm = false); + +inline bool isValidBlockSize(uint32_t Size) { + switch (Size) { + case 512: + case 1024: + case 2048: + case 4096: + return true; + } + return false; +} + +// Super Block, Fpm0, Fpm1, and Block Map +inline uint32_t getMinimumBlockCount() { return 4; } + +// Super Block, Fpm0, and Fpm1 are reserved. The Block Map, although required +// need not be at block 3. +inline uint32_t getFirstUnreservedBlock() { return 3; } + +inline uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize) { + return divideCeil(NumBytes, BlockSize); +} + +inline uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize) { + return BlockNumber * BlockSize; +} + +inline uint32_t getFpmIntervalLength(const MSFLayout &L) { + return L.SB->BlockSize; +} + +/// Given an MSF with the specified block size and number of blocks, determine +/// how many pieces the specified Fpm is split into. +/// \p BlockSize - the block size of the MSF +/// \p NumBlocks - the total number of blocks in the MSF +/// \p IncludeUnusedFpmData - When true, this will count every block that is +/// both in the file and matches the form of an FPM block, even if some of +/// those FPM blocks are unused (a single FPM block can describe the +/// allocation status of up to 32,767 blocks, although one appears only +/// every 4,096 blocks). So there are 8x as many blocks that match the +/// form as there are blocks that are necessary to describe the allocation +/// status of the file. When this parameter is false, these extraneous +/// trailing blocks are not counted. +inline uint32_t getNumFpmIntervals(uint32_t BlockSize, uint32_t NumBlocks, + bool IncludeUnusedFpmData, int FpmNumber) { + assert(FpmNumber == 1 || FpmNumber == 2); + if (IncludeUnusedFpmData) { + // This calculation determines how many times a number of the form + // BlockSize * k + N appears in the range [0, NumBlocks). We only need to + // do this when unused data is included, since the number of blocks dwarfs + // the number of fpm blocks. + return divideCeil(NumBlocks - FpmNumber, BlockSize); + } + + // We want the minimum number of intervals required, where each interval can + // represent BlockSize * 8 blocks. + return divideCeil(NumBlocks, 8 * BlockSize); +} + +inline uint32_t getNumFpmIntervals(const MSFLayout &L, + bool IncludeUnusedFpmData = false, + bool AltFpm = false) { + return getNumFpmIntervals(L.SB->BlockSize, L.SB->NumBlocks, + IncludeUnusedFpmData, + AltFpm ? L.alternateFpmBlock() : L.mainFpmBlock()); +} + +Error validateSuperBlock(const SuperBlock &SB); + +} // end namespace msf +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_MSFCOMMON_H diff --git a/clang-r353983/include/llvm/DebugInfo/MSF/MSFError.h b/clang-r353983/include/llvm/DebugInfo/MSF/MSFError.h new file mode 100644 index 00000000..fbc4e692 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/MSF/MSFError.h @@ -0,0 +1,52 @@ +//===- MSFError.h - Error extensions for MSF Files --------------*- 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_MSF_MSFERROR_H +#define LLVM_DEBUGINFO_MSF_MSFERROR_H + +#include "llvm/Support/Error.h" + +#include <string> + +namespace llvm { +namespace msf { +enum class msf_error_code { + unspecified = 1, + insufficient_buffer, + not_writable, + no_stream, + invalid_format, + block_in_use +}; +} // namespace msf +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum<llvm::msf::msf_error_code> : std::true_type {}; +} // namespace std + +namespace llvm { +namespace msf { +const std::error_category &MSFErrCategory(); + +inline std::error_code make_error_code(msf_error_code E) { + return std::error_code(static_cast<int>(E), MSFErrCategory()); +} + +/// Base class for errors originating when parsing raw PDB files +class MSFError : public ErrorInfo<MSFError, StringError> { +public: + using ErrorInfo<MSFError, StringError>::ErrorInfo; // inherit constructors + MSFError(const Twine &S) : ErrorInfo(S, msf_error_code::unspecified) {} + static char ID; +}; +} // namespace msf +} // namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_MSFERROR_H diff --git a/clang-r353983/include/llvm/DebugInfo/MSF/MappedBlockStream.h b/clang-r353983/include/llvm/DebugInfo/MSF/MappedBlockStream.h new file mode 100644 index 00000000..593d781b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/MSF/MappedBlockStream.h @@ -0,0 +1,162 @@ +//==- MappedBlockStream.h - Discontiguous stream data in an MSF --*- 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_MSF_MAPPEDBLOCKSTREAM_H +#define LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryStream.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <memory> +#include <vector> + +namespace llvm { +namespace msf { + +struct MSFLayout; + +/// MappedBlockStream represents data stored in an MSF file into chunks of a +/// particular size (called the Block Size), and whose chunks may not be +/// necessarily contiguous. The arrangement of these chunks MSF the file +/// is described by some other metadata contained within the MSF file. In +/// the case of a standard MSF Stream, the layout of the stream's blocks +/// is described by the MSF "directory", but in the case of the directory +/// itself, the layout is described by an array at a fixed location within +/// the MSF. MappedBlockStream provides methods for reading from and writing +/// to one of these streams transparently, as if it were a contiguous sequence +/// of bytes. +class MappedBlockStream : public BinaryStream { + friend class WritableMappedBlockStream; + +public: + static std::unique_ptr<MappedBlockStream> + createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, + BinaryStreamRef MsfData, BumpPtrAllocator &Allocator); + + static std::unique_ptr<MappedBlockStream> + createIndexedStream(const MSFLayout &Layout, BinaryStreamRef MsfData, + uint32_t StreamIndex, BumpPtrAllocator &Allocator); + + static std::unique_ptr<MappedBlockStream> + createFpmStream(const MSFLayout &Layout, BinaryStreamRef MsfData, + BumpPtrAllocator &Allocator); + + static std::unique_ptr<MappedBlockStream> + createDirectoryStream(const MSFLayout &Layout, BinaryStreamRef MsfData, + BumpPtrAllocator &Allocator); + + support::endianness getEndian() const override { + return support::little; + } + + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) override; + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) override; + + uint32_t getLength() override; + + BumpPtrAllocator &getAllocator() { return Allocator; } + + void invalidateCache(); + + uint32_t getBlockSize() const { return BlockSize; } + uint32_t getNumBlocks() const { return StreamLayout.Blocks.size(); } + uint32_t getStreamLength() const { return StreamLayout.Length; } + +protected: + MappedBlockStream(uint32_t BlockSize, const MSFStreamLayout &StreamLayout, + BinaryStreamRef MsfData, BumpPtrAllocator &Allocator); + +private: + const MSFStreamLayout &getStreamLayout() const { return StreamLayout; } + void fixCacheAfterWrite(uint32_t Offset, ArrayRef<uint8_t> Data) const; + + Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer); + bool tryReadContiguously(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer); + + const uint32_t BlockSize; + const MSFStreamLayout StreamLayout; + BinaryStreamRef MsfData; + + using CacheEntry = MutableArrayRef<uint8_t>; + + // We just store the allocator by reference. We use this to allocate + // contiguous memory for things like arrays or strings that cross a block + // boundary, and this memory is expected to outlive the stream. For example, + // someone could create a stream, read some stuff, then close the stream, and + // we would like outstanding references to fields to remain valid since the + // entire file is mapped anyway. Because of that, the user must supply the + // allocator to allocate broken records from. + BumpPtrAllocator &Allocator; + DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap; +}; + +class WritableMappedBlockStream : public WritableBinaryStream { +public: + static std::unique_ptr<WritableMappedBlockStream> + createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, + WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator); + + static std::unique_ptr<WritableMappedBlockStream> + createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, + uint32_t StreamIndex, BumpPtrAllocator &Allocator); + + static std::unique_ptr<WritableMappedBlockStream> + createDirectoryStream(const MSFLayout &Layout, + WritableBinaryStreamRef MsfData, + BumpPtrAllocator &Allocator); + + static std::unique_ptr<WritableMappedBlockStream> + createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, + BumpPtrAllocator &Allocator, bool AltFpm = false); + + support::endianness getEndian() const override { + return support::little; + } + + Error readBytes(uint32_t Offset, uint32_t Size, + ArrayRef<uint8_t> &Buffer) override; + Error readLongestContiguousChunk(uint32_t Offset, + ArrayRef<uint8_t> &Buffer) override; + uint32_t getLength() override; + + Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override; + + Error commit() override; + + const MSFStreamLayout &getStreamLayout() const { + return ReadInterface.getStreamLayout(); + } + + uint32_t getBlockSize() const { return ReadInterface.getBlockSize(); } + uint32_t getNumBlocks() const { return ReadInterface.getNumBlocks(); } + uint32_t getStreamLength() const { return ReadInterface.getStreamLength(); } + +protected: + WritableMappedBlockStream(uint32_t BlockSize, + const MSFStreamLayout &StreamLayout, + WritableBinaryStreamRef MsfData, + BumpPtrAllocator &Allocator); + +private: + MappedBlockStream ReadInterface; + WritableBinaryStreamRef WriteInterface; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/clang-r353983/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h new file mode 100644 index 00000000..49ba20af --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h @@ -0,0 +1,53 @@ +//===- ConcreteSymbolEnumerator.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_PDB_CONCRETESYMBOLENUMERATOR_H +#define LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H + +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/Casting.h" +#include <algorithm> +#include <cstdint> +#include <memory> + +namespace llvm { +namespace pdb { + +template <typename ChildType> +class ConcreteSymbolEnumerator : public IPDBEnumChildren<ChildType> { +public: + ConcreteSymbolEnumerator(std::unique_ptr<IPDBEnumSymbols> SymbolEnumerator) + : Enumerator(std::move(SymbolEnumerator)) {} + + ~ConcreteSymbolEnumerator() override = default; + + uint32_t getChildCount() const override { + return Enumerator->getChildCount(); + } + + std::unique_ptr<ChildType> getChildAtIndex(uint32_t Index) const override { + std::unique_ptr<PDBSymbol> Child = Enumerator->getChildAtIndex(Index); + return unique_dyn_cast_or_null<ChildType>(Child); + } + + std::unique_ptr<ChildType> getNext() override { + return unique_dyn_cast_or_null<ChildType>(Enumerator->getNext()); + } + + void reset() override { Enumerator->reset(); } + +private: + + std::unique_ptr<IPDBEnumSymbols> Enumerator; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h new file mode 100644 index 00000000..f05b58c5 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h @@ -0,0 +1,33 @@ +//===- DIADataStream.h - DIA implementation of IPDBDataStream ---*- 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_DIA_DIADATASTREAM_H +#define LLVM_DEBUGINFO_PDB_DIA_DIADATASTREAM_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBDataStream.h" + +namespace llvm { +namespace pdb { +class DIADataStream : public IPDBDataStream { +public: + explicit DIADataStream(CComPtr<IDiaEnumDebugStreamData> DiaStreamData); + + uint32_t getRecordCount() const override; + std::string getName() const override; + llvm::Optional<RecordType> getItemAtIndex(uint32_t Index) const override; + bool getNext(RecordType &Record) override; + void reset() override; + +private: + CComPtr<IDiaEnumDebugStreamData> StreamData; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h new file mode 100644 index 00000000..8a00ad45 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h @@ -0,0 +1,36 @@ +//==- DIAEnumDebugStreams.h - DIA Debug Stream Enumerator impl ---*- 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_DIA_DIAENUMDEBUGSTREAMS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMDEBUGSTREAMS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBDataStream.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { +namespace pdb { + +class IPDBDataStream; + +class DIAEnumDebugStreams : public IPDBEnumChildren<IPDBDataStream> { +public: + explicit DIAEnumDebugStreams(CComPtr<IDiaEnumDebugStreams> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + +private: + CComPtr<IDiaEnumDebugStreams> Enumerator; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h new file mode 100644 index 00000000..bd417c07 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h @@ -0,0 +1,35 @@ +//==- DIAEnumFrameData.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_PDB_DIA_DIAENUMFRAMEDATA_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMFRAMEDATA_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBFrameData.h" + +namespace llvm { +namespace pdb { + +class DIAEnumFrameData : public IPDBEnumChildren<IPDBFrameData> { +public: + explicit DIAEnumFrameData(CComPtr<IDiaEnumFrameData> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + +private: + CComPtr<IDiaEnumFrameData> Enumerator; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h new file mode 100644 index 00000000..1f75ca27 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h @@ -0,0 +1,35 @@ +//==- DIAEnumInjectedSources.h - DIA Injected Sources Enumerator -*- 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_DIA_DIAENUMINJECTEDSOURCES_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMINJECTEDSOURCES_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" + +namespace llvm { +namespace pdb { + +class DIAEnumInjectedSources : public IPDBEnumChildren<IPDBInjectedSource> { +public: + explicit DIAEnumInjectedSources( + CComPtr<IDiaEnumInjectedSources> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + +private: + CComPtr<IDiaEnumInjectedSources> Enumerator; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAENUMINJECTEDSOURCES_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h new file mode 100644 index 00000000..8800baac --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h @@ -0,0 +1,35 @@ +//==- DIAEnumLineNumbers.h - DIA Line Number Enumerator impl -----*- 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_DIA_DIAENUMLINENUMBERS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMLINENUMBERS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" + +namespace llvm { +namespace pdb { +class IPDBLineNumber; + +class DIAEnumLineNumbers : public IPDBEnumChildren<IPDBLineNumber> { +public: + explicit DIAEnumLineNumbers(CComPtr<IDiaEnumLineNumbers> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + +private: + CComPtr<IDiaEnumLineNumbers> Enumerator; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h new file mode 100644 index 00000000..be8613bf --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h @@ -0,0 +1,38 @@ +//==- DIAEnumSectionContribs.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_PDB_DIA_DIAENUMSECTIONCONTRIBS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSECTIONCONTRIBS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIAEnumSectionContribs : public IPDBEnumChildren<IPDBSectionContrib> { +public: + explicit DIAEnumSectionContribs( + const DIASession &PDBSession, + CComPtr<IDiaEnumSectionContribs> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + +private: + const DIASession &Session; + CComPtr<IDiaEnumSectionContribs> Enumerator; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAENUMSECTIONCONTRIBS_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h new file mode 100644 index 00000000..61278994 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h @@ -0,0 +1,37 @@ +//==- DIAEnumSourceFiles.h - DIA Source File Enumerator impl -----*- 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_DIA_DIAENUMSOURCEFILES_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSOURCEFILES_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIAEnumSourceFiles : public IPDBEnumChildren<IPDBSourceFile> { +public: + explicit DIAEnumSourceFiles(const DIASession &PDBSession, + CComPtr<IDiaEnumSourceFiles> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + +private: + const DIASession &Session; + CComPtr<IDiaEnumSourceFiles> Enumerator; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h new file mode 100644 index 00000000..f55342ce --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h @@ -0,0 +1,37 @@ +//==- DIAEnumSymbols.h - DIA Symbol Enumerator impl --------------*- 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_DIA_DIAENUMSYMBOLS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSYMBOLS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIAEnumSymbols : public IPDBEnumChildren<PDBSymbol> { +public: + explicit DIAEnumSymbols(const DIASession &Session, + CComPtr<IDiaEnumSymbols> DiaEnumerator); + + uint32_t getChildCount() const override; + std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; + std::unique_ptr<PDBSymbol> getNext() override; + void reset() override; + +private: + const DIASession &Session; + CComPtr<IDiaEnumSymbols> Enumerator; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h new file mode 100644 index 00000000..057cb06f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h @@ -0,0 +1,35 @@ +//===- DIAEnumTables.h - DIA Tables Enumerator Impl -------------*- 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_DIA_DIAENUMTABLES_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMTABLES_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBTable.h" + +namespace llvm { +namespace pdb { +class IPDBTable; + +class DIAEnumTables : public IPDBEnumChildren<IPDBTable> { +public: + explicit DIAEnumTables(CComPtr<IDiaEnumTables> DiaEnumerator); + + uint32_t getChildCount() const override; + std::unique_ptr<IPDBTable> getChildAtIndex(uint32_t Index) const override; + std::unique_ptr<IPDBTable> getNext() override; + void reset() override; + +private: + CComPtr<IDiaEnumTables> Enumerator; +}; +} +} + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAENUMTABLES_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAError.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAError.h new file mode 100644 index 00000000..96d96059 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAError.h @@ -0,0 +1,50 @@ +//===- DIAError.h - Error extensions for PDB DIA implementation -*- 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_DIA_DIAERROR_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAERROR_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +enum class dia_error_code { + unspecified = 1, + could_not_create_impl, + invalid_file_format, + invalid_parameter, + already_loaded, + debug_info_mismatch, +}; +} // namespace pdb +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum<llvm::pdb::dia_error_code> : std::true_type {}; +} // namespace std + +namespace llvm { +namespace pdb { +const std::error_category &DIAErrCategory(); + +inline std::error_code make_error_code(dia_error_code E) { + return std::error_code(static_cast<int>(E), DIAErrCategory()); +} + +/// Base class for errors originating in DIA SDK, e.g. COM calls +class DIAError : public ErrorInfo<DIAError, StringError> { +public: + using ErrorInfo<DIAError, StringError>::ErrorInfo; + DIAError(const Twine &S) : ErrorInfo(S, dia_error_code::unspecified) {} + static char ID; +}; +} // namespace pdb +} // namespace llvm +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h new file mode 100644 index 00000000..c04f7cd0 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h @@ -0,0 +1,38 @@ +//===- DIAFrameData.h - DIA Impl. of IPDBFrameData ---------------- 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_DIA_DIAFRAMEDATA_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAFRAMEDATA_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBFrameData.h" + +namespace llvm { +namespace pdb { + +class DIASession; + +class DIAFrameData : public IPDBFrameData { +public: + explicit DIAFrameData(CComPtr<IDiaFrameData> DiaFrameData); + + uint32_t getAddressOffset() const override; + uint32_t getAddressSection() const override; + uint32_t getLengthBlock() const override; + std::string getProgram() const override; + uint32_t getRelativeVirtualAddress() const override; + uint64_t getVirtualAddress() const override; + +private: + CComPtr<IDiaFrameData> FrameData; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h new file mode 100644 index 00000000..8be06f80 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h @@ -0,0 +1,37 @@ +//===- DIAInjectedSource.h - DIA impl for IPDBInjectedSource ----*- 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_DIA_DIAINJECTEDSOURCE_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAINJECTEDSOURCE_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIAInjectedSource : public IPDBInjectedSource { +public: + explicit DIAInjectedSource(CComPtr<IDiaInjectedSource> DiaSourceFile); + + uint32_t getCrc32() const override; + uint64_t getCodeByteSize() const override; + std::string getFileName() const override; + std::string getObjectFileName() const override; + std::string getVirtualFileName() const override; + PDB_SourceCompression getCompression() const override; + std::string getCode() const override; + +private: + CComPtr<IDiaInjectedSource> SourceFile; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAINJECTEDSOURCE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h new file mode 100644 index 00000000..d8bb2722 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h @@ -0,0 +1,39 @@ +//===- DIALineNumber.h - DIA implementation of IPDBLineNumber ---*- 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_DIA_DIALINENUMBER_H +#define LLVM_DEBUGINFO_PDB_DIA_DIALINENUMBER_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" + +namespace llvm { +namespace pdb { +class DIALineNumber : public IPDBLineNumber { +public: + explicit DIALineNumber(CComPtr<IDiaLineNumber> DiaLineNumber); + + uint32_t getLineNumber() const override; + uint32_t getLineNumberEnd() const override; + uint32_t getColumnNumber() const override; + uint32_t getColumnNumberEnd() const override; + uint32_t getAddressSection() const override; + uint32_t getAddressOffset() const override; + uint32_t getRelativeVirtualAddress() const override; + uint64_t getVirtualAddress() const override; + uint32_t getLength() const override; + uint32_t getSourceFileId() const override; + uint32_t getCompilandId() const override; + bool isStatement() const override; + +private: + CComPtr<IDiaLineNumber> LineNumber; +}; +} +} +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h new file mode 100644 index 00000000..7f201d3a --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -0,0 +1,233 @@ +//===- DIARawSymbol.h - DIA implementation of IPDBRawSymbol ----*- 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_DIA_DIARAWSYMBOL_H +#define LLVM_DEBUGINFO_PDB_DIA_DIARAWSYMBOL_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" + +namespace llvm { +namespace pdb { +class DIASession; +class DIARawSymbol : public IPDBRawSymbol { +public: + DIARawSymbol(const DIASession &PDBSession, CComPtr<IDiaSymbol> DiaSymbol); + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + CComPtr<IDiaSymbol> getDiaSymbol() const { return Symbol; } + + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildrenByAddr(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t Section, uint32_t Offset) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint64_t VA) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const override; + + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const override; + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByRVA(uint32_t RVA) const override; + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByVA(uint64_t VA) const override; + + std::unique_ptr<IPDBEnumLineNumbers> findInlineeLines() const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, + uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override; + + void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const override; + void getFrontEndVersion(VersionInfo &Version) const override; + void getBackEndVersion(VersionInfo &Version) const override; + PDB_MemberAccess getAccess() const override; + uint32_t getAddressOffset() const override; + uint32_t getAddressSection() const override; + uint32_t getAge() const override; + SymIndexId getArrayIndexTypeId() const override; + uint32_t getBaseDataOffset() const override; + uint32_t getBaseDataSlot() const override; + SymIndexId getBaseSymbolId() const override; + PDB_BuiltinType getBuiltinType() const override; + uint32_t getBitPosition() const override; + PDB_CallingConv getCallingConvention() const override; + SymIndexId getClassParentId() const override; + std::string getCompilerName() const override; + uint32_t getCount() const override; + uint32_t getCountLiveRanges() const override; + PDB_Lang getLanguage() const override; + SymIndexId getLexicalParentId() const override; + std::string getLibraryName() const override; + uint32_t getLiveRangeStartAddressOffset() const override; + uint32_t getLiveRangeStartAddressSection() const override; + uint32_t getLiveRangeStartRelativeVirtualAddress() const override; + codeview::RegisterId getLocalBasePointerRegisterId() const override; + SymIndexId getLowerBoundId() const override; + uint32_t getMemorySpaceKind() const override; + std::string getName() const override; + uint32_t getNumberOfAcceleratorPointerTags() const override; + uint32_t getNumberOfColumns() const override; + uint32_t getNumberOfModifiers() const override; + uint32_t getNumberOfRegisterIndices() const override; + uint32_t getNumberOfRows() const override; + std::string getObjectFileName() const override; + uint32_t getOemId() const override; + SymIndexId getOemSymbolId() const override; + uint32_t getOffsetInUdt() const override; + PDB_Cpu getPlatform() const override; + uint32_t getRank() const override; + codeview::RegisterId getRegisterId() const override; + uint32_t getRegisterType() const override; + uint32_t getRelativeVirtualAddress() const override; + uint32_t getSamplerSlot() const override; + uint32_t getSignature() const override; + uint32_t getSizeInUdt() const override; + uint32_t getSlot() const override; + std::string getSourceFileName() const override; + std::unique_ptr<IPDBLineNumber> getSrcLineOnTypeDefn() const override; + uint32_t getStride() const override; + SymIndexId getSubTypeId() const override; + std::string getSymbolsFileName() const override; + SymIndexId getSymIndexId() const override; + uint32_t getTargetOffset() const override; + uint32_t getTargetRelativeVirtualAddress() const override; + uint64_t getTargetVirtualAddress() const override; + uint32_t getTargetSection() const override; + uint32_t getTextureSlot() const override; + uint32_t getTimeStamp() const override; + uint32_t getToken() const override; + SymIndexId getTypeId() const override; + uint32_t getUavSlot() const override; + std::string getUndecoratedName() const override; + std::string getUndecoratedNameEx(PDB_UndnameFlags Flags) const override; + SymIndexId getUnmodifiedTypeId() const override; + SymIndexId getUpperBoundId() const override; + Variant getValue() const override; + uint32_t getVirtualBaseDispIndex() const override; + uint32_t getVirtualBaseOffset() const override; + SymIndexId getVirtualTableShapeId() const override; + std::unique_ptr<PDBSymbolTypeBuiltin> + getVirtualBaseTableType() const override; + PDB_DataKind getDataKind() const override; + PDB_SymType getSymTag() const override; + codeview::GUID getGuid() const override; + int32_t getOffset() const override; + int32_t getThisAdjust() const override; + int32_t getVirtualBasePointerOffset() const override; + PDB_LocType getLocationType() const override; + PDB_Machine getMachineType() const override; + codeview::ThunkOrdinal getThunkOrdinal() const override; + uint64_t getLength() const override; + uint64_t getLiveRangeLength() const override; + uint64_t getVirtualAddress() const override; + PDB_UdtType getUdtKind() const override; + bool hasConstructor() const override; + bool hasCustomCallingConvention() const override; + bool hasFarReturn() const override; + bool isCode() const override; + bool isCompilerGenerated() const override; + bool isConstType() const override; + bool isEditAndContinueEnabled() const override; + bool isFunction() const override; + bool getAddressTaken() const override; + bool getNoStackOrdering() const override; + bool hasAlloca() const override; + bool hasAssignmentOperator() const override; + bool hasCTypes() const override; + bool hasCastOperator() const override; + bool hasDebugInfo() const override; + bool hasEH() const override; + bool hasEHa() const override; + bool hasInlAsm() const override; + bool hasInlineAttribute() const override; + bool hasInterruptReturn() const override; + bool hasFramePointer() const override; + bool hasLongJump() const override; + bool hasManagedCode() const override; + bool hasNestedTypes() const override; + bool hasNoInlineAttribute() const override; + bool hasNoReturnAttribute() const override; + bool hasOptimizedCodeDebugInfo() const override; + bool hasOverloadedOperator() const override; + bool hasSEH() const override; + bool hasSecurityChecks() const override; + bool hasSetJump() const override; + bool hasStrictGSCheck() const override; + bool isAcceleratorGroupSharedLocal() const override; + bool isAcceleratorPointerTagLiveRange() const override; + bool isAcceleratorStubFunction() const override; + bool isAggregated() const override; + bool isIntroVirtualFunction() const override; + bool isCVTCIL() const override; + bool isConstructorVirtualBase() const override; + bool isCxxReturnUdt() const override; + bool isDataAligned() const override; + bool isHLSLData() const override; + bool isHotpatchable() const override; + bool isIndirectVirtualBaseClass() const override; + bool isInterfaceUdt() const override; + bool isIntrinsic() const override; + bool isLTCG() const override; + bool isLocationControlFlowDependent() const override; + bool isMSILNetmodule() const override; + bool isMatrixRowMajor() const override; + bool isManagedCode() const override; + bool isMSILCode() const override; + bool isMultipleInheritance() const override; + bool isNaked() const override; + bool isNested() const override; + bool isOptimizedAway() const override; + bool isPacked() const override; + bool isPointerBasedOnSymbolValue() const override; + bool isPointerToDataMember() const override; + bool isPointerToMemberFunction() const override; + bool isPureVirtual() const override; + bool isRValueReference() const override; + bool isRefUdt() const override; + bool isReference() const override; + bool isRestrictedType() const override; + bool isReturnValue() const override; + bool isSafeBuffers() const override; + bool isScoped() const override; + bool isSdl() const override; + bool isSingleInheritance() const override; + bool isSplitted() const override; + bool isStatic() const override; + bool hasPrivateSymbols() const override; + bool isUnalignedType() const override; + bool isUnreached() const override; + bool isValueUdt() const override; + bool isVirtual() const override; + bool isVirtualBaseClass() const override; + bool isVirtualInheritance() const override; + bool isVolatileType() const override; + bool wasInlined() const override; + std::string getUnused() const override; + +private: + const DIASession &Session; + CComPtr<IDiaSymbol> Symbol; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h new file mode 100644 index 00000000..0972831e --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h @@ -0,0 +1,54 @@ +//===- DIASectionContrib.h - DIA Impl. of IPDBSectionContrib ------ 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_DIA_DIASECTIONCONTRIB_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASECTIONCONTRIB_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIASectionContrib : public IPDBSectionContrib { +public: + explicit DIASectionContrib(const DIASession &PDBSession, + CComPtr<IDiaSectionContrib> DiaSection); + + std::unique_ptr<PDBSymbolCompiland> getCompiland() const override; + uint32_t getAddressSection() const override; + uint32_t getAddressOffset() const override; + uint32_t getRelativeVirtualAddress() const override; + uint64_t getVirtualAddress() const override; + uint32_t getLength() const override; + bool isNotPaged() const override; + bool hasCode() const override; + bool hasCode16Bit() const override; + bool hasInitializedData() const override; + bool hasUninitializedData() const override; + bool isRemoved() const override; + bool hasComdat() const override; + bool isDiscardable() const override; + bool isNotCached() const override; + bool isShared() const override; + bool isExecutable() const override; + bool isReadable() const override; + bool isWritable() const override; + uint32_t getDataCrc32() const override; + uint32_t getRelocationsCrc32() const override; + uint32_t getCompilandId() const override; + +private: + const DIASession &Session; + CComPtr<IDiaSectionContrib> Section; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIASECTIONCONTRIB_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASession.h new file mode 100644 index 00000000..6f62e606 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -0,0 +1,93 @@ +//===- DIASession.h - DIA implementation of IPDBSession ---------*- 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_DIA_DIASESSION_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/Support/Error.h" + +#include <system_error> + +namespace llvm { +class StringRef; + +namespace pdb { +class DIASession : public IPDBSession { +public: + explicit DIASession(CComPtr<IDiaSession> DiaSession); + + static Error createFromPdb(StringRef Path, + std::unique_ptr<IPDBSession> &Session); + static Error createFromExe(StringRef Path, + std::unique_ptr<IPDBSession> &Session); + + uint64_t getLoadAddress() const override; + bool setLoadAddress(uint64_t Address) override; + std::unique_ptr<PDBSymbolExe> getGlobalScope() override; + std::unique_ptr<PDBSymbol> getSymbolById(SymIndexId SymbolId) const override; + + bool addressForVA(uint64_t VA, uint32_t &Section, + uint32_t &Offset) const override; + bool addressForRVA(uint32_t RVA, uint32_t &Section, + uint32_t &Offset) const override; + + std::unique_ptr<PDBSymbol> + findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override; + std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA, + PDB_SymType Type) const override; + std::unique_ptr<PDBSymbol> + findSymbolBySectOffset(uint32_t Section, uint32_t Offset, + PDB_SymType Type) const override; + + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbers(const PDBSymbolCompiland &Compiland, + const IPDBSourceFile &File) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, + uint32_t Length) const override; + + std::unique_ptr<IPDBEnumSourceFiles> + findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBSourceFile> + findOneSourceFile(const PDBSymbolCompiland *Compiland, + llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> + findCompilandsForSourceFile(llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<PDBSymbolCompiland> + findOneCompilandForSourceFile(llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override; + std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland( + const PDBSymbolCompiland &Compiland) const override; + std::unique_ptr<IPDBSourceFile> + getSourceFileById(uint32_t FileId) const override; + + std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override; + + std::unique_ptr<IPDBEnumTables> getEnumTables() const override; + + std::unique_ptr<IPDBEnumInjectedSources> getInjectedSources() const override; + + std::unique_ptr<IPDBEnumSectionContribs> getSectionContribs() const override; + + std::unique_ptr<IPDBEnumFrameData> getFrameData() const override; +private: + CComPtr<IDiaSession> Session; +}; +} // namespace pdb +} // namespace llvm +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h new file mode 100644 index 00000000..96edfc9f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h @@ -0,0 +1,40 @@ +//===- DIASourceFile.h - DIA implementation of IPDBSourceFile ---*- 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_DIA_DIASOURCEFILE_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASOURCEFILE_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIASourceFile : public IPDBSourceFile { +public: + explicit DIASourceFile(const DIASession &Session, + CComPtr<IDiaSourceFile> DiaSourceFile); + + std::string getFileName() const override; + uint32_t getUniqueId() const override; + std::string getChecksum() const override; + PDB_Checksum getChecksumType() const override; + std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> + getCompilands() const override; + + CComPtr<IDiaSourceFile> getDiaFile() const { return SourceFile; } + +private: + const DIASession &Session; + CComPtr<IDiaSourceFile> SourceFile; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASupport.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASupport.h new file mode 100644 index 00000000..1a7c2f3a --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIASupport.h @@ -0,0 +1,33 @@ +//===- DIASupport.h - Common header includes for DIA ------------*- 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 +// +//===----------------------------------------------------------------------===// +// Common defines and header includes for all LLVMDebugInfoPDBDIA. The +// definitions here configure the necessary #defines and include system headers +// in the proper order for using DIA. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H + +// Require at least Vista +#define NTDDI_VERSION NTDDI_VISTA +#define _WIN32_WINNT _WIN32_WINNT_VISTA +#define WINVER _WIN32_WINNT_VISTA +#ifndef NOMINMAX +#define NOMINMAX +#endif + +// atlbase.h has to come before windows.h +#include <atlbase.h> +#include <windows.h> + +// DIA headers must come after windows headers. +#include <cvconst.h> +#include <dia2.h> +#include <diacreate.h> + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIATable.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIATable.h new file mode 100644 index 00000000..65396a04 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIATable.h @@ -0,0 +1,31 @@ +//===- DIATable.h - DIA implementation of IPDBTable -------------*- 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_DIA_DIATABLE_H +#define LLVM_DEBUGINFO_PDB_DIA_DIATABLE_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBTable.h" + +namespace llvm { +namespace pdb { +class DIATable : public IPDBTable { +public: + explicit DIATable(CComPtr<IDiaTable> DiaTable); + + uint32_t getItemCount() const override; + std::string getName() const override; + PDB_TableType getTableType() const override; + +private: + CComPtr<IDiaTable> Table; +}; +} +} + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIATABLE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h new file mode 100644 index 00000000..5e01d8f1 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h @@ -0,0 +1,30 @@ +//===- DIAUtils.h - Utility functions for working with DIA ------*- 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_DIA_DIAUTILS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAUTILS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/ConvertUTF.h" + +template <typename Obj> +std::string invokeBstrMethod(Obj &Object, + HRESULT (__stdcall Obj::*Func)(BSTR *)) { + CComBSTR Str16; + HRESULT Result = (Object.*Func)(&Str16); + if (S_OK != Result) + return std::string(); + + std::string Str8; + llvm::ArrayRef<char> StrBytes(reinterpret_cast<char *>(Str16.m_str), + Str16.ByteLength()); + llvm::convertUTF16ToUTF8String(StrBytes, Str8); + return Str8; +} + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAUTILS_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/GenericError.h b/clang-r353983/include/llvm/DebugInfo/PDB/GenericError.h new file mode 100644 index 00000000..ec85d92d --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/GenericError.h @@ -0,0 +1,51 @@ +//===- GenericError.h - system_error extensions for PDB ---------*- 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_ERROR_H +#define LLVM_DEBUGINFO_PDB_ERROR_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { + +enum class pdb_error_code { + invalid_utf8_path = 1, + dia_sdk_not_present, + dia_failed_loading, + signature_out_of_date, + external_cmdline_ref, + unspecified, +}; +} // namespace pdb +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum<llvm::pdb::pdb_error_code> : std::true_type {}; +} // namespace std + +namespace llvm { +namespace pdb { +const std::error_category &PDBErrCategory(); + +inline std::error_code make_error_code(pdb_error_code E) { + return std::error_code(static_cast<int>(E), PDBErrCategory()); +} + +/// Base class for errors originating when parsing raw PDB files +class PDBError : public ErrorInfo<PDBError, StringError> { +public: + using ErrorInfo<PDBError, StringError>::ErrorInfo; // inherit constructors + PDBError(const Twine &S) : ErrorInfo(S, pdb_error_code::unspecified) {} + static char ID; +}; +} // namespace pdb +} // namespace llvm +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBDataStream.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBDataStream.h new file mode 100644 index 00000000..4d0589a8 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBDataStream.h @@ -0,0 +1,39 @@ +//===- IPDBDataStream.h - base interface for child enumerator ---*- 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_IPDBDATASTREAM_H +#define LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include <cstdint> +#include <string> + +namespace llvm { +namespace pdb { + +/// IPDBDataStream defines an interface used to represent a stream consisting +/// of a name and a series of records whose formats depend on the particular +/// stream type. +class IPDBDataStream { +public: + using RecordType = SmallVector<uint8_t, 32>; + + virtual ~IPDBDataStream(); + + virtual uint32_t getRecordCount() const = 0; + virtual std::string getName() const = 0; + virtual Optional<RecordType> getItemAtIndex(uint32_t Index) const = 0; + virtual bool getNext(RecordType &Record) = 0; + virtual void reset() = 0; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h new file mode 100644 index 00000000..bfa67d39 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h @@ -0,0 +1,48 @@ +//===- IPDBEnumChildren.h - base interface for child enumerator -*- 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_IPDBENUMCHILDREN_H +#define LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H + +#include <cassert> +#include <cstdint> +#include <memory> + +namespace llvm { +namespace pdb { + +template <typename ChildType> class IPDBEnumChildren { +public: + using ChildTypePtr = std::unique_ptr<ChildType>; + using MyType = IPDBEnumChildren<ChildType>; + + virtual ~IPDBEnumChildren() = default; + + virtual uint32_t getChildCount() const = 0; + virtual ChildTypePtr getChildAtIndex(uint32_t Index) const = 0; + virtual ChildTypePtr getNext() = 0; + virtual void reset() = 0; +}; + +template <typename ChildType> +class NullEnumerator : public IPDBEnumChildren<ChildType> { + virtual uint32_t getChildCount() const override { return 0; } + virtual std::unique_ptr<ChildType> + getChildAtIndex(uint32_t Index) const override { + return nullptr; + } + virtual std::unique_ptr<ChildType> getNext() override { + return nullptr; + } + virtual void reset() override {} +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBFrameData.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBFrameData.h new file mode 100644 index 00000000..24138b38 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBFrameData.h @@ -0,0 +1,35 @@ +//===- IPDBFrameData.h - base interface for frame data ----------*- 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_IPDBFRAMEDATA_H +#define LLVM_DEBUGINFO_PDB_IPDBFRAMEDATA_H + +#include <cstdint> +#include <string> + +namespace llvm { +namespace pdb { + +/// IPDBFrameData defines an interface used to represent a frame data of some +/// code block. +class IPDBFrameData { +public: + virtual ~IPDBFrameData(); + + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getLengthBlock() const = 0; + virtual std::string getProgram() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint64_t getVirtualAddress() const = 0; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h new file mode 100644 index 00000000..56e85d1f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h @@ -0,0 +1,41 @@ +//===- IPDBInjectedSource.h - base class for PDB injected file --*- 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_IPDBINJECTEDSOURCE_H +#define LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H + +#include "PDBTypes.h" +#include "llvm/Support/raw_ostream.h" +#include <memory> +#include <string> + +namespace llvm { +class raw_ostream; + +namespace pdb { + +/// IPDBInjectedSource defines an interface used to represent source files +/// which were injected directly into the PDB file during the compilation +/// process. This is used, for example, to add natvis files to a PDB, but +/// in theory could be used to add arbitrary source code. +class IPDBInjectedSource { +public: + virtual ~IPDBInjectedSource(); + + virtual uint32_t getCrc32() const = 0; + virtual uint64_t getCodeByteSize() const = 0; + virtual std::string getFileName() const = 0; + virtual std::string getObjectFileName() const = 0; + virtual std::string getVirtualFileName() const = 0; + virtual PDB_SourceCompression getCompression() const = 0; + virtual std::string getCode() const = 0; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBLineNumber.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBLineNumber.h new file mode 100644 index 00000000..77e88999 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBLineNumber.h @@ -0,0 +1,36 @@ +//===- IPDBLineNumber.h - base interface for PDB line no. info ---*- 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_IPDBLINENUMBER_H +#define LLVM_DEBUGINFO_PDB_IPDBLINENUMBER_H + +#include "PDBTypes.h" + +namespace llvm { +namespace pdb { +class IPDBLineNumber { +public: + virtual ~IPDBLineNumber(); + + virtual uint32_t getLineNumber() const = 0; + virtual uint32_t getLineNumberEnd() const = 0; + virtual uint32_t getColumnNumber() const = 0; + virtual uint32_t getColumnNumberEnd() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual uint32_t getLength() const = 0; + virtual uint32_t getSourceFileId() const = 0; + virtual uint32_t getCompilandId() const = 0; + virtual bool isStatement() const = 0; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h new file mode 100644 index 00000000..b24e712e --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -0,0 +1,263 @@ +//===- IPDBRawSymbol.h - base interface for PDB symbol 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H +#define LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H + +#include "PDBTypes.h" +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include <memory> + +namespace llvm { +class raw_ostream; + +namespace pdb { + +class IPDBSession; +class PDBSymbolTypeVTable; +class PDBSymbolTypeVTableShape; + +enum class PdbSymbolIdField : uint32_t { + None = 0, + SymIndexId = 1 << 0, + LexicalParent = 1 << 1, + ClassParent = 1 << 2, + Type = 1 << 3, + UnmodifiedType = 1 << 4, + All = 0xFFFFFFFF, + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ All) +}; + +void dumpSymbolIdField(raw_ostream &OS, StringRef Name, SymIndexId Value, + int Indent, const IPDBSession &Session, + PdbSymbolIdField FieldId, PdbSymbolIdField ShowFlags, + PdbSymbolIdField RecurseFlags); + +/// IPDBRawSymbol defines an interface used to represent an arbitrary symbol. +/// It exposes a monolithic interface consisting of accessors for the union of +/// all properties that are valid for any symbol type. This interface is then +/// wrapped by a concrete class which exposes only those set of methods valid +/// for this particular symbol type. See PDBSymbol.h for more details. +class IPDBRawSymbol { +public: + virtual ~IPDBRawSymbol(); + + virtual void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const = 0; + + virtual std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type) const = 0; + + virtual std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> + findChildrenByAddr(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t Section, uint32_t Offset) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> + findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint64_t VA) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const = 0; + + virtual std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByRVA(uint32_t RVA) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByVA(uint64_t VA) const = 0; + + virtual std::unique_ptr<IPDBEnumLineNumbers> findInlineeLines() const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, + uint32_t Length) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByVA(uint64_t VA, uint32_t Length) const = 0; + + virtual void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const = 0; + virtual void getBackEndVersion(VersionInfo &Version) const = 0; + virtual PDB_MemberAccess getAccess() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAge() const = 0; + virtual SymIndexId getArrayIndexTypeId() const = 0; + virtual uint32_t getBaseDataOffset() const = 0; + virtual uint32_t getBaseDataSlot() const = 0; + virtual SymIndexId getBaseSymbolId() const = 0; + virtual PDB_BuiltinType getBuiltinType() const = 0; + virtual uint32_t getBitPosition() const = 0; + virtual PDB_CallingConv getCallingConvention() const = 0; + virtual SymIndexId getClassParentId() const = 0; + virtual std::string getCompilerName() const = 0; + virtual uint32_t getCount() const = 0; + virtual uint32_t getCountLiveRanges() const = 0; + virtual void getFrontEndVersion(VersionInfo &Version) const = 0; + virtual PDB_Lang getLanguage() const = 0; + virtual SymIndexId getLexicalParentId() const = 0; + virtual std::string getLibraryName() const = 0; + virtual uint32_t getLiveRangeStartAddressOffset() const = 0; + virtual uint32_t getLiveRangeStartAddressSection() const = 0; + virtual uint32_t getLiveRangeStartRelativeVirtualAddress() const = 0; + virtual codeview::RegisterId getLocalBasePointerRegisterId() const = 0; + virtual SymIndexId getLowerBoundId() const = 0; + virtual uint32_t getMemorySpaceKind() const = 0; + virtual std::string getName() const = 0; + virtual uint32_t getNumberOfAcceleratorPointerTags() const = 0; + virtual uint32_t getNumberOfColumns() const = 0; + virtual uint32_t getNumberOfModifiers() const = 0; + virtual uint32_t getNumberOfRegisterIndices() const = 0; + virtual uint32_t getNumberOfRows() const = 0; + virtual std::string getObjectFileName() const = 0; + virtual uint32_t getOemId() const = 0; + virtual SymIndexId getOemSymbolId() const = 0; + virtual uint32_t getOffsetInUdt() const = 0; + virtual PDB_Cpu getPlatform() const = 0; + virtual uint32_t getRank() const = 0; + virtual codeview::RegisterId getRegisterId() const = 0; + virtual uint32_t getRegisterType() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint32_t getSamplerSlot() const = 0; + virtual uint32_t getSignature() const = 0; + virtual uint32_t getSizeInUdt() const = 0; + virtual uint32_t getSlot() const = 0; + virtual std::string getSourceFileName() const = 0; + virtual std::unique_ptr<IPDBLineNumber> + getSrcLineOnTypeDefn() const = 0; + virtual uint32_t getStride() const = 0; + virtual SymIndexId getSubTypeId() const = 0; + virtual std::string getSymbolsFileName() const = 0; + virtual SymIndexId getSymIndexId() const = 0; + virtual uint32_t getTargetOffset() const = 0; + virtual uint32_t getTargetRelativeVirtualAddress() const = 0; + virtual uint64_t getTargetVirtualAddress() const = 0; + virtual uint32_t getTargetSection() const = 0; + virtual uint32_t getTextureSlot() const = 0; + virtual uint32_t getTimeStamp() const = 0; + virtual uint32_t getToken() const = 0; + virtual SymIndexId getTypeId() const = 0; + virtual uint32_t getUavSlot() const = 0; + virtual std::string getUndecoratedName() const = 0; + virtual std::string getUndecoratedNameEx(PDB_UndnameFlags Flags) const = 0; + virtual SymIndexId getUnmodifiedTypeId() const = 0; + virtual SymIndexId getUpperBoundId() const = 0; + virtual Variant getValue() const = 0; + virtual uint32_t getVirtualBaseDispIndex() const = 0; + virtual uint32_t getVirtualBaseOffset() const = 0; + virtual std::unique_ptr<PDBSymbolTypeBuiltin> + getVirtualBaseTableType() const = 0; + virtual SymIndexId getVirtualTableShapeId() const = 0; + virtual PDB_DataKind getDataKind() const = 0; + virtual PDB_SymType getSymTag() const = 0; + virtual codeview::GUID getGuid() const = 0; + virtual int32_t getOffset() const = 0; + virtual int32_t getThisAdjust() const = 0; + virtual int32_t getVirtualBasePointerOffset() const = 0; + virtual PDB_LocType getLocationType() const = 0; + virtual PDB_Machine getMachineType() const = 0; + virtual codeview::ThunkOrdinal getThunkOrdinal() const = 0; + virtual uint64_t getLength() const = 0; + virtual uint64_t getLiveRangeLength() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual PDB_UdtType getUdtKind() const = 0; + virtual bool hasConstructor() const = 0; + virtual bool hasCustomCallingConvention() const = 0; + virtual bool hasFarReturn() const = 0; + virtual bool isCode() const = 0; + virtual bool isCompilerGenerated() const = 0; + virtual bool isConstType() const = 0; + virtual bool isEditAndContinueEnabled() const = 0; + virtual bool isFunction() const = 0; + virtual bool getAddressTaken() const = 0; + virtual bool getNoStackOrdering() const = 0; + virtual bool hasAlloca() const = 0; + virtual bool hasAssignmentOperator() const = 0; + virtual bool hasCTypes() const = 0; + virtual bool hasCastOperator() const = 0; + virtual bool hasDebugInfo() const = 0; + virtual bool hasEH() const = 0; + virtual bool hasEHa() const = 0; + virtual bool hasFramePointer() const = 0; + virtual bool hasInlAsm() const = 0; + virtual bool hasInlineAttribute() const = 0; + virtual bool hasInterruptReturn() const = 0; + virtual bool hasLongJump() const = 0; + virtual bool hasManagedCode() const = 0; + virtual bool hasNestedTypes() const = 0; + virtual bool hasNoInlineAttribute() const = 0; + virtual bool hasNoReturnAttribute() const = 0; + virtual bool hasOptimizedCodeDebugInfo() const = 0; + virtual bool hasOverloadedOperator() const = 0; + virtual bool hasSEH() const = 0; + virtual bool hasSecurityChecks() const = 0; + virtual bool hasSetJump() const = 0; + virtual bool hasStrictGSCheck() const = 0; + virtual bool isAcceleratorGroupSharedLocal() const = 0; + virtual bool isAcceleratorPointerTagLiveRange() const = 0; + virtual bool isAcceleratorStubFunction() const = 0; + virtual bool isAggregated() const = 0; + virtual bool isIntroVirtualFunction() const = 0; + virtual bool isCVTCIL() const = 0; + virtual bool isConstructorVirtualBase() const = 0; + virtual bool isCxxReturnUdt() const = 0; + virtual bool isDataAligned() const = 0; + virtual bool isHLSLData() const = 0; + virtual bool isHotpatchable() const = 0; + virtual bool isIndirectVirtualBaseClass() const = 0; + virtual bool isInterfaceUdt() const = 0; + virtual bool isIntrinsic() const = 0; + virtual bool isLTCG() const = 0; + virtual bool isLocationControlFlowDependent() const = 0; + virtual bool isMSILNetmodule() const = 0; + virtual bool isMatrixRowMajor() const = 0; + virtual bool isManagedCode() const = 0; + virtual bool isMSILCode() const = 0; + virtual bool isMultipleInheritance() const = 0; + virtual bool isNaked() const = 0; + virtual bool isNested() const = 0; + virtual bool isOptimizedAway() const = 0; + virtual bool isPacked() const = 0; + virtual bool isPointerBasedOnSymbolValue() const = 0; + virtual bool isPointerToDataMember() const = 0; + virtual bool isPointerToMemberFunction() const = 0; + virtual bool isPureVirtual() const = 0; + virtual bool isRValueReference() const = 0; + virtual bool isRefUdt() const = 0; + virtual bool isReference() const = 0; + virtual bool isRestrictedType() const = 0; + virtual bool isReturnValue() const = 0; + virtual bool isSafeBuffers() const = 0; + virtual bool isScoped() const = 0; + virtual bool isSdl() const = 0; + virtual bool isSingleInheritance() const = 0; + virtual bool isSplitted() const = 0; + virtual bool isStatic() const = 0; + virtual bool hasPrivateSymbols() const = 0; + virtual bool isUnalignedType() const = 0; + virtual bool isUnreached() const = 0; + virtual bool isValueUdt() const = 0; + virtual bool isVirtual() const = 0; + virtual bool isVirtualBaseClass() const = 0; + virtual bool isVirtualInheritance() const = 0; + virtual bool isVolatileType() const = 0; + virtual bool wasInlined() const = 0; + virtual std::string getUnused() const = 0; +}; + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h new file mode 100644 index 00000000..c5cf4bbe --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h @@ -0,0 +1,49 @@ +//==- IPDBSectionContrib.h - Interfaces for PDB SectionContribs --*- 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_IPDBSECTIONCONTRIB_H +#define LLVM_DEBUGINFO_PDB_IPDBSECTIONCONTRIB_H + +#include "PDBTypes.h" + +namespace llvm { +namespace pdb { + +/// IPDBSectionContrib defines an interface used to represent section +/// contributions whose information are stored in the PDB. +class IPDBSectionContrib { +public: + virtual ~IPDBSectionContrib(); + + virtual std::unique_ptr<PDBSymbolCompiland> getCompiland() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual uint32_t getLength() const = 0; + virtual bool isNotPaged() const = 0; + virtual bool hasCode() const = 0; + virtual bool hasCode16Bit() const = 0; + virtual bool hasInitializedData() const = 0; + virtual bool hasUninitializedData() const = 0; + virtual bool isRemoved() const = 0; + virtual bool hasComdat() const = 0; + virtual bool isDiscardable() const = 0; + virtual bool isNotCached() const = 0; + virtual bool isShared() const = 0; + virtual bool isExecutable() const = 0; + virtual bool isReadable() const = 0; + virtual bool isWritable() const = 0; + virtual uint32_t getDataCrc32() const = 0; + virtual uint32_t getRelocationsCrc32() const = 0; + virtual uint32_t getCompilandId() const = 0; +}; +} +} + +#endif // LLVM_DEBUGINFO_PDB_IPDBSECTIONCONTRIB_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBSession.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBSession.h new file mode 100644 index 00000000..aa8d9c76 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -0,0 +1,100 @@ +//===- IPDBSession.h - base interface for a PDB symbol context --*- 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_IPDBSESSION_H +#define LLVM_DEBUGINFO_PDB_IPDBSESSION_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include <memory> + +namespace llvm { +namespace pdb { +class PDBSymbolCompiland; +class PDBSymbolExe; + +/// IPDBSession defines an interface used to provide a context for querying +/// debug information from a debug data source (for example, a PDB). +class IPDBSession { +public: + virtual ~IPDBSession(); + + virtual uint64_t getLoadAddress() const = 0; + virtual bool setLoadAddress(uint64_t Address) = 0; + virtual std::unique_ptr<PDBSymbolExe> getGlobalScope() = 0; + virtual std::unique_ptr<PDBSymbol> + getSymbolById(SymIndexId SymbolId) const = 0; + + virtual bool addressForVA(uint64_t VA, uint32_t &Section, + uint32_t &Offset) const = 0; + virtual bool addressForRVA(uint32_t RVA, uint32_t &Section, + uint32_t &Offset) const = 0; + + template <typename T> + std::unique_ptr<T> getConcreteSymbolById(SymIndexId SymbolId) const { + return unique_dyn_cast_or_null<T>(getSymbolById(SymbolId)); + } + + virtual std::unique_ptr<PDBSymbol> + findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0; + virtual std::unique_ptr<PDBSymbol> + findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const = 0; + virtual std::unique_ptr<PDBSymbol> + findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, + PDB_SymType Type) const = 0; + + virtual std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbers(const PDBSymbolCompiland &Compiland, + const IPDBSourceFile &File) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, + uint32_t Length) const = 0; + + virtual std::unique_ptr<IPDBEnumSourceFiles> + findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const = 0; + virtual std::unique_ptr<IPDBSourceFile> + findOneSourceFile(const PDBSymbolCompiland *Compiland, + llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const = 0; + virtual std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> + findCompilandsForSourceFile(llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const = 0; + virtual std::unique_ptr<PDBSymbolCompiland> + findOneCompilandForSourceFile(llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const = 0; + + virtual std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const = 0; + virtual std::unique_ptr<IPDBEnumSourceFiles> + getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0; + virtual std::unique_ptr<IPDBSourceFile> + getSourceFileById(uint32_t FileId) const = 0; + + virtual std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const = 0; + + virtual std::unique_ptr<IPDBEnumTables> getEnumTables() const = 0; + + virtual std::unique_ptr<IPDBEnumInjectedSources> + getInjectedSources() const = 0; + + virtual std::unique_ptr<IPDBEnumSectionContribs> + getSectionContribs() const = 0; + + virtual std::unique_ptr<IPDBEnumFrameData> + getFrameData() const = 0; +}; +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBSourceFile.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBSourceFile.h new file mode 100644 index 00000000..d7e49fb7 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBSourceFile.h @@ -0,0 +1,39 @@ +//===- IPDBSourceFile.h - base interface for a PDB source file --*- 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_IPDBSOURCEFILE_H +#define LLVM_DEBUGINFO_PDB_IPDBSOURCEFILE_H + +#include "PDBTypes.h" +#include <memory> +#include <string> + +namespace llvm { +class raw_ostream; + +namespace pdb { + +/// IPDBSourceFile defines an interface used to represent source files whose +/// information are stored in the PDB. +class IPDBSourceFile { +public: + virtual ~IPDBSourceFile(); + + void dump(raw_ostream &OS, int Indent) const; + + virtual std::string getFileName() const = 0; + virtual uint32_t getUniqueId() const = 0; + virtual std::string getChecksum() const = 0; + virtual PDB_Checksum getChecksumType() const = 0; + virtual std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> + getCompilands() const = 0; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/IPDBTable.h b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBTable.h new file mode 100644 index 00000000..55ca230d --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/IPDBTable.h @@ -0,0 +1,27 @@ +//===- IPDBTable.h - Base Interface for a PDB Symbol Context ----*- 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_IPDBTABLE_H +#define LLVM_DEBUGINFO_PDB_IPDBTABLE_H + +#include "PDBTypes.h" + +namespace llvm { +namespace pdb { +class IPDBTable { +public: + virtual ~IPDBTable(); + + virtual std::string getName() const = 0; + virtual uint32_t getItemCount() const = 0; + virtual PDB_TableType getTableType() const = 0; +}; +} +} + +#endif // LLVM_DEBUGINFO_PDB_IPDBTABLE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h new file mode 100644 index 00000000..568f0c98 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h @@ -0,0 +1,71 @@ +//===- DbiModuleDescriptor.h - PDB module information -----------*- 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_RAW_DBIMODULEDESCRIPTOR_H +#define LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTOR_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { + +namespace pdb { + +class DbiModuleDescriptor { + friend class DbiStreamBuilder; + +public: + DbiModuleDescriptor(); + DbiModuleDescriptor(const DbiModuleDescriptor &Info); + ~DbiModuleDescriptor(); + + static Error initialize(BinaryStreamRef Stream, DbiModuleDescriptor &Info); + + bool hasECInfo() const; + uint16_t getTypeServerIndex() const; + uint16_t getModuleStreamIndex() const; + uint32_t getSymbolDebugInfoByteSize() const; + uint32_t getC11LineInfoByteSize() const; + uint32_t getC13LineInfoByteSize() const; + uint32_t getNumberOfFiles() const; + uint32_t getSourceFileNameIndex() const; + uint32_t getPdbFilePathNameIndex() const; + + StringRef getModuleName() const; + StringRef getObjFileName() const; + + uint32_t getRecordLength() const; + + const SectionContrib &getSectionContrib() const; + +private: + StringRef ModuleName; + StringRef ObjFileName; + const ModuleInfoHeader *Layout = nullptr; +}; + +} // end namespace pdb + +template <> struct VarStreamArrayExtractor<pdb::DbiModuleDescriptor> { + Error operator()(BinaryStreamRef Stream, uint32_t &Length, + pdb::DbiModuleDescriptor &Info) { + if (auto EC = pdb::DbiModuleDescriptor::initialize(Stream, Info)) + return EC; + Length = Info.getRecordLength(); + return Error::success(); + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTOR_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h new file mode 100644 index 00000000..4f5d28bb --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -0,0 +1,106 @@ +//===- DbiModuleDescriptorBuilder.h - PDB module information ----*- 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_RAW_DBIMODULEDESCRIPTORBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTORBUILDER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <string> +#include <vector> + +namespace llvm { +class BinaryStreamWriter; + +namespace codeview { +class DebugSubsectionRecordBuilder; +} + +namespace msf { +class MSFBuilder; +struct MSFLayout; +} +namespace pdb { + +class DbiModuleDescriptorBuilder { + friend class DbiStreamBuilder; + +public: + DbiModuleDescriptorBuilder(StringRef ModuleName, uint32_t ModIndex, + msf::MSFBuilder &Msf); + ~DbiModuleDescriptorBuilder(); + + DbiModuleDescriptorBuilder(const DbiModuleDescriptorBuilder &) = delete; + DbiModuleDescriptorBuilder & + operator=(const DbiModuleDescriptorBuilder &) = delete; + + void setPdbFilePathNI(uint32_t NI); + void setObjFileName(StringRef Name); + void setFirstSectionContrib(const SectionContrib &SC); + void addSymbol(codeview::CVSymbol Symbol); + void addSymbolsInBulk(ArrayRef<uint8_t> BulkSymbols); + + void + addDebugSubsection(std::shared_ptr<codeview::DebugSubsection> Subsection); + + void + addDebugSubsection(const codeview::DebugSubsectionRecord &SubsectionContents); + + uint16_t getStreamIndex() const; + StringRef getModuleName() const { return ModuleName; } + StringRef getObjFileName() const { return ObjFileName; } + + unsigned getModuleIndex() const { return Layout.Mod; } + + ArrayRef<std::string> source_files() const { + return makeArrayRef(SourceFiles); + } + + uint32_t calculateSerializedLength() const; + + /// Return the offset within the module symbol stream of the next symbol + /// record passed to addSymbol. Add four to account for the signature. + uint32_t getNextSymbolOffset() const { return SymbolByteSize + 4; } + + void finalize(); + Error finalizeMsfLayout(); + + Error commit(BinaryStreamWriter &ModiWriter, const msf::MSFLayout &MsfLayout, + WritableBinaryStreamRef MsfBuffer); + +private: + uint32_t calculateC13DebugInfoSize() const; + + void addSourceFile(StringRef Path); + msf::MSFBuilder &MSF; + + uint32_t SymbolByteSize = 0; + uint32_t PdbFilePathNI = 0; + std::string ModuleName; + std::string ObjFileName; + std::vector<std::string> SourceFiles; + std::vector<ArrayRef<uint8_t>> Symbols; + + std::vector<std::unique_ptr<codeview::DebugSubsectionRecordBuilder>> + C13Builders; + + ModuleInfoHeader Layout; +}; + +} // end namespace pdb + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTORBUILDER_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h new file mode 100644 index 00000000..14223273 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h @@ -0,0 +1,117 @@ +//===- DbiModuleList.h - PDB module information list ------------*- 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_NATIVE_DBIMODULELIST_H +#define LLVM_DEBUGINFO_PDB_NATIVE_DBIMODULELIST_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstddef> +#include <cstdint> +#include <iterator> +#include <vector> + +namespace llvm { +namespace pdb { + +class DbiModuleList; +struct FileInfoSubstreamHeader; + +class DbiModuleSourceFilesIterator + : public iterator_facade_base<DbiModuleSourceFilesIterator, + std::random_access_iterator_tag, StringRef> { + using BaseType = + iterator_facade_base<DbiModuleSourceFilesIterator, + std::random_access_iterator_tag, StringRef>; + +public: + DbiModuleSourceFilesIterator(const DbiModuleList &Modules, uint32_t Modi, + uint16_t Filei); + DbiModuleSourceFilesIterator() = default; + DbiModuleSourceFilesIterator & + operator=(const DbiModuleSourceFilesIterator &R) = default; + + bool operator==(const DbiModuleSourceFilesIterator &R) const; + + const StringRef &operator*() const { return ThisValue; } + StringRef &operator*() { return ThisValue; } + + bool operator<(const DbiModuleSourceFilesIterator &RHS) const; + std::ptrdiff_t operator-(const DbiModuleSourceFilesIterator &R) const; + DbiModuleSourceFilesIterator &operator+=(std::ptrdiff_t N); + DbiModuleSourceFilesIterator &operator-=(std::ptrdiff_t N); + +private: + void setValue(); + + bool isEnd() const; + bool isCompatible(const DbiModuleSourceFilesIterator &R) const; + bool isUniversalEnd() const; + + StringRef ThisValue; + const DbiModuleList *Modules{nullptr}; + uint32_t Modi{0}; + uint16_t Filei{0}; +}; + +class DbiModuleList { + friend DbiModuleSourceFilesIterator; + +public: + Error initialize(BinaryStreamRef ModInfo, BinaryStreamRef FileInfo); + + Expected<StringRef> getFileName(uint32_t Index) const; + uint32_t getModuleCount() const; + uint32_t getSourceFileCount() const; + uint16_t getSourceFileCount(uint32_t Modi) const; + + iterator_range<DbiModuleSourceFilesIterator> + source_files(uint32_t Modi) const; + + DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const; + +private: + Error initializeModInfo(BinaryStreamRef ModInfo); + Error initializeFileInfo(BinaryStreamRef FileInfo); + + VarStreamArray<DbiModuleDescriptor> Descriptors; + + FixedStreamArray<support::little32_t> FileNameOffsets; + FixedStreamArray<support::ulittle16_t> ModFileCountArray; + + // For each module, there are multiple filenames, which can be obtained by + // knowing the index of the file. Given the index of the file, one can use + // that as an offset into the FileNameOffsets array, which contains the + // absolute offset of the file name in NamesBuffer. Thus, for each module + // we store the first index in the FileNameOffsets array for this module. + // The number of files for the corresponding module is stored in + // ModFileCountArray. + std::vector<uint32_t> ModuleInitialFileIndex; + + // In order to provide random access into the Descriptors array, we iterate it + // once up front to find the offsets of the individual items and store them in + // this array. + std::vector<uint32_t> ModuleDescriptorOffsets; + + const FileInfoSubstreamHeader *FileInfoHeader = nullptr; + + BinaryStreamRef ModInfoSubstream; + BinaryStreamRef FileInfoSubstream; + BinaryStreamRef NamesBuffer; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_DBIMODULELIST_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiStream.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiStream.h new file mode 100644 index 00000000..7d75c159 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiStream.h @@ -0,0 +1,138 @@ +//===- DbiStream.h - PDB Dbi Stream (Stream 3) Access -----------*- 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_RAW_PDBDBISTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H + +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace object { +struct FpoData; +struct coff_section; +} + +namespace pdb { +class DbiStreamBuilder; +class PDBFile; +class ISectionContribVisitor; + +class DbiStream { + friend class DbiStreamBuilder; + +public: + explicit DbiStream(std::unique_ptr<BinaryStream> Stream); + ~DbiStream(); + Error reload(PDBFile *Pdb); + + PdbRaw_DbiVer getDbiVersion() const; + uint32_t getAge() const; + uint16_t getPublicSymbolStreamIndex() const; + uint16_t getGlobalSymbolStreamIndex() const; + + uint16_t getFlags() const; + bool isIncrementallyLinked() const; + bool hasCTypes() const; + bool isStripped() const; + + uint16_t getBuildNumber() const; + uint16_t getBuildMajorVersion() const; + uint16_t getBuildMinorVersion() const; + + uint16_t getPdbDllRbld() const; + uint32_t getPdbDllVersion() const; + + uint32_t getSymRecordStreamIndex() const; + + PDB_Machine getMachineType() const; + + const DbiStreamHeader *getHeader() const { return Header; } + + BinarySubstreamRef getSectionContributionData() const; + BinarySubstreamRef getSecMapSubstreamData() const; + BinarySubstreamRef getModiSubstreamData() const; + BinarySubstreamRef getFileInfoSubstreamData() const; + BinarySubstreamRef getTypeServerMapSubstreamData() const; + BinarySubstreamRef getECSubstreamData() const; + + /// If the given stream type is present, returns its stream index. If it is + /// not present, returns InvalidStreamIndex. + uint32_t getDebugStreamIndex(DbgHeaderType Type) const; + + const DbiModuleList &modules() const; + + FixedStreamArray<object::coff_section> getSectionHeaders() const; + + bool hasOldFpoRecords() const; + FixedStreamArray<object::FpoData> getOldFpoRecords() const; + bool hasNewFpoRecords() const; + const codeview::DebugFrameDataSubsectionRef &getNewFpoRecords() const; + + FixedStreamArray<SecMapEntry> getSectionMap() const; + void visitSectionContributions(ISectionContribVisitor &Visitor) const; + + Expected<StringRef> getECName(uint32_t NI) const; + +private: + Error initializeSectionContributionData(); + Error initializeSectionHeadersData(PDBFile *Pdb); + Error initializeSectionMapData(); + Error initializeOldFpoRecords(PDBFile *Pdb); + Error initializeNewFpoRecords(PDBFile *Pdb); + + Expected<std::unique_ptr<msf::MappedBlockStream>> + createIndexedStreamForHeaderType(PDBFile *Pdb, DbgHeaderType Type) const; + + std::unique_ptr<BinaryStream> Stream; + + PDBStringTable ECNames; + + BinarySubstreamRef SecContrSubstream; + BinarySubstreamRef SecMapSubstream; + BinarySubstreamRef ModiSubstream; + BinarySubstreamRef FileInfoSubstream; + BinarySubstreamRef TypeServerMapSubstream; + BinarySubstreamRef ECSubstream; + + DbiModuleList Modules; + + FixedStreamArray<support::ulittle16_t> DbgStreams; + + PdbRaw_DbiSecContribVer SectionContribVersion = + PdbRaw_DbiSecContribVer::DbiSecContribVer60; + FixedStreamArray<SectionContrib> SectionContribs; + FixedStreamArray<SectionContrib2> SectionContribs2; + FixedStreamArray<SecMapEntry> SectionMap; + + std::unique_ptr<msf::MappedBlockStream> SectionHeaderStream; + FixedStreamArray<object::coff_section> SectionHeaders; + + std::unique_ptr<msf::MappedBlockStream> OldFpoStream; + FixedStreamArray<object::FpoData> OldFpoRecords; + + std::unique_ptr<msf::MappedBlockStream> NewFpoStream; + codeview::DebugFrameDataSubsectionRef NewFpoRecords; + + const DbiStreamHeader *Header; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h new file mode 100644 index 00000000..d9be238a --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -0,0 +1,142 @@ +//===- DbiStreamBuilder.h - PDB Dbi Stream Creation -------------*- 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_RAW_PDBDBISTREAMBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAMBUILDER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/Support/Error.h" + +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace codeview { +struct FrameData; +} +namespace msf { +class MSFBuilder; +} +namespace object { +struct coff_section; +struct FpoData; +} +namespace pdb { +class DbiStream; +struct DbiStreamHeader; +class DbiModuleDescriptorBuilder; +class PDBFile; + +class DbiStreamBuilder { +public: + DbiStreamBuilder(msf::MSFBuilder &Msf); + ~DbiStreamBuilder(); + + DbiStreamBuilder(const DbiStreamBuilder &) = delete; + DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete; + + void setVersionHeader(PdbRaw_DbiVer V); + void setAge(uint32_t A); + void setBuildNumber(uint16_t B); + void setBuildNumber(uint8_t Major, uint8_t Minor); + void setPdbDllVersion(uint16_t V); + void setPdbDllRbld(uint16_t R); + void setFlags(uint16_t F); + void setMachineType(PDB_Machine M); + void setMachineType(COFF::MachineTypes M); + void setSectionMap(ArrayRef<SecMapEntry> SecMap); + + // Add given bytes as a new stream. + Error addDbgStream(pdb::DbgHeaderType Type, ArrayRef<uint8_t> Data); + + uint32_t addECName(StringRef Name); + + uint32_t calculateSerializedLength() const; + + void setGlobalsStreamIndex(uint32_t Index); + void setPublicsStreamIndex(uint32_t Index); + void setSymbolRecordStreamIndex(uint32_t Index); + void addNewFpoData(const codeview::FrameData &FD); + void addOldFpoData(const object::FpoData &Fpo); + + Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName); + Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File); + Expected<uint32_t> getSourceFileNameIndex(StringRef FileName); + + Error finalizeMsfLayout(); + + Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer); + + void addSectionContrib(const SectionContrib &SC) { + SectionContribs.emplace_back(SC); + } + + // A helper function to create a Section Map from a COFF section header. + static std::vector<SecMapEntry> + createSectionMap(ArrayRef<llvm::object::coff_section> SecHdrs); + +private: + struct DebugStream { + std::function<Error(BinaryStreamWriter &)> WriteFn; + uint32_t Size = 0; + uint16_t StreamNumber = kInvalidStreamIndex; + }; + + Error finalize(); + uint32_t calculateModiSubstreamSize() const; + uint32_t calculateNamesOffset() const; + uint32_t calculateSectionContribsStreamSize() const; + uint32_t calculateSectionMapStreamSize() const; + uint32_t calculateFileInfoSubstreamSize() const; + uint32_t calculateNamesBufferSize() const; + uint32_t calculateDbgStreamsSize() const; + + Error generateFileInfoSubstream(); + + msf::MSFBuilder &Msf; + BumpPtrAllocator &Allocator; + + Optional<PdbRaw_DbiVer> VerHeader; + uint32_t Age; + uint16_t BuildNumber; + uint16_t PdbDllVersion; + uint16_t PdbDllRbld; + uint16_t Flags; + PDB_Machine MachineType; + uint32_t GlobalsStreamIndex = kInvalidStreamIndex; + uint32_t PublicsStreamIndex = kInvalidStreamIndex; + uint32_t SymRecordStreamIndex = kInvalidStreamIndex; + + const DbiStreamHeader *Header; + + std::vector<std::unique_ptr<DbiModuleDescriptorBuilder>> ModiList; + + Optional<codeview::DebugFrameDataSubsection> NewFpoData; + std::vector<object::FpoData> OldFpoData; + + StringMap<uint32_t> SourceFileNames; + + PDBStringTableBuilder ECNamesBuilder; + WritableBinaryStreamRef NamesBuffer; + MutableBinaryByteStream FileInfoBuffer; + std::vector<SectionContrib> SectionContribs; + ArrayRef<SecMapEntry> SectionMap; + std::array<Optional<DebugStream>, (int)DbgHeaderType::Max> DbgStreams; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/EnumTables.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/EnumTables.h new file mode 100644 index 00000000..70161fad --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/EnumTables.h @@ -0,0 +1,21 @@ +//===- 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_PDB_RAW_ENUMTABLES_H +#define LLVM_DEBUGINFO_PDB_RAW_ENUMTABLES_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/ScopedPrinter.h" + +namespace llvm { +namespace pdb { +ArrayRef<EnumEntry<uint16_t>> getOMFSegMapDescFlagNames(); +} +} + +#endif // LLVM_DEBUGINFO_PDB_RAW_ENUMTABLES_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/Formatters.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/Formatters.h new file mode 100644 index 00000000..29c957ee --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/Formatters.h @@ -0,0 +1,44 @@ +//===- 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_PDB_NATIVE_FORMATTERS_H +#define LLVM_DEBUGINFO_PDB_NATIVE_FORMATTERS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/Formatters.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/FormatProviders.h" + +#define FORMAT_CASE(Value, Name) \ + case Value: \ + Stream << Name; \ + break; + +namespace llvm { +template <> struct format_provider<pdb::PdbRaw_ImplVer> { + static void format(const pdb::PdbRaw_ImplVer &V, llvm::raw_ostream &Stream, + StringRef Style) { + switch (V) { + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC110, "VC110") + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC140, "VC140") + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC2, "VC2") + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC4, "VC4") + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC41, "VC41") + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC50, "VC50") + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC70, "VC70") + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC70Dep, "VC70Dep") + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC80, "VC80") + FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC98, "VC98") + } + } +}; +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h new file mode 100644 index 00000000..a4979560 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h @@ -0,0 +1,80 @@ +//===- GSIStreamBuilder.h - PDB Publics/Globals Stream Creation -*- 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_RAW_GSISTREAMBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_GSISTREAMBUILDER_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryItemStream.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +namespace llvm { + +template <> struct BinaryItemTraits<codeview::CVSymbol> { + static size_t length(const codeview::CVSymbol &Item) { + return Item.RecordData.size(); + } + static ArrayRef<uint8_t> bytes(const codeview::CVSymbol &Item) { + return Item.RecordData; + } +}; + +namespace msf { +class MSFBuilder; +struct MSFLayout; +} // namespace msf +namespace pdb { +struct GSIHashStreamBuilder; + +class GSIStreamBuilder { + +public: + explicit GSIStreamBuilder(msf::MSFBuilder &Msf); + ~GSIStreamBuilder(); + + GSIStreamBuilder(const GSIStreamBuilder &) = delete; + GSIStreamBuilder &operator=(const GSIStreamBuilder &) = delete; + + Error finalizeMsfLayout(); + + Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer); + + uint32_t getPublicsStreamIndex() const; + uint32_t getGlobalsStreamIndex() const; + uint32_t getRecordStreamIdx() const { return RecordStreamIdx; } + + void addPublicSymbol(const codeview::PublicSym32 &Pub); + + void addGlobalSymbol(const codeview::ProcRefSym &Sym); + void addGlobalSymbol(const codeview::DataSym &Sym); + void addGlobalSymbol(const codeview::ConstantSym &Sym); + void addGlobalSymbol(const codeview::CVSymbol &Sym); + +private: + uint32_t calculatePublicsHashStreamSize() const; + uint32_t calculateGlobalsHashStreamSize() const; + Error commitSymbolRecordStream(WritableBinaryStreamRef Stream); + Error commitPublicsHashStream(WritableBinaryStreamRef Stream); + Error commitGlobalsHashStream(WritableBinaryStreamRef Stream); + + uint32_t RecordStreamIdx = kInvalidStreamIndex; + msf::MSFBuilder &Msf; + std::unique_ptr<GSIHashStreamBuilder> PSH; + std::unique_ptr<GSIHashStreamBuilder> GSH; +}; +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h new file mode 100644 index 00000000..404baaa2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h @@ -0,0 +1,87 @@ +//===- GlobalsStream.h - PDB Index of Symbols by Name -----------*- 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_RAW_GLOBALS_STREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_GLOBALS_STREAM_H + +#include "llvm/ADT/iterator.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class DbiStream; +class PDBFile; +class SymbolStream; + +/// Iterator over hash records producing symbol record offsets. Abstracts away +/// the fact that symbol record offsets on disk are off-by-one. +class GSIHashIterator + : public iterator_adaptor_base< + GSIHashIterator, FixedStreamArrayIterator<PSHashRecord>, + std::random_access_iterator_tag, const uint32_t> { +public: + template <typename T> + GSIHashIterator(T &&v) + : GSIHashIterator::iterator_adaptor_base(std::forward<T &&>(v)) {} + + uint32_t operator*() const { + uint32_t Off = this->I->Off; + return --Off; + } +}; + +/// From https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.cpp +enum : unsigned { IPHR_HASH = 4096 }; + +/// A readonly view of a hash table used in the globals and publics streams. +/// Most clients will only want to iterate this to get symbol record offsets +/// into the PDB symbol stream. +class GSIHashTable { +public: + const GSIHashHeader *HashHdr; + FixedStreamArray<PSHashRecord> HashRecords; + FixedStreamArray<support::ulittle32_t> HashBitmap; + FixedStreamArray<support::ulittle32_t> HashBuckets; + std::array<int32_t, IPHR_HASH + 1> BucketMap; + + Error read(BinaryStreamReader &Reader); + + uint32_t getVerSignature() const { return HashHdr->VerSignature; } + uint32_t getVerHeader() const { return HashHdr->VerHdr; } + uint32_t getHashRecordSize() const { return HashHdr->HrSize; } + uint32_t getNumBuckets() const { return HashHdr->NumBuckets; } + + typedef GSIHashHeader iterator; + GSIHashIterator begin() const { return GSIHashIterator(HashRecords.begin()); } + GSIHashIterator end() const { return GSIHashIterator(HashRecords.end()); } +}; + +class GlobalsStream { +public: + explicit GlobalsStream(std::unique_ptr<msf::MappedBlockStream> Stream); + ~GlobalsStream(); + const GSIHashTable &getGlobalsTable() const { return GlobalsTable; } + Error reload(); + + std::vector<std::pair<uint32_t, codeview::CVSymbol>> + findRecordsByName(StringRef Name, const SymbolStream &Symbols) const; + +private: + GSIHashTable GlobalsTable; + std::unique_ptr<msf::MappedBlockStream> Stream; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/Hash.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/Hash.h new file mode 100644 index 00000000..b048d878 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/Hash.h @@ -0,0 +1,26 @@ +//===- Hash.h - PDB hash functions ------------------------------*- 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_NATIVE_HASH_H +#define LLVM_DEBUGINFO_PDB_NATIVE_HASH_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include <cstdint> + +namespace llvm { +namespace pdb { + +uint32_t hashStringV1(StringRef Str); +uint32_t hashStringV2(StringRef Str); +uint32_t hashBufferV8(ArrayRef<uint8_t> Data); + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_HASH_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/HashTable.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/HashTable.h new file mode 100644 index 00000000..e8f08c68 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/HashTable.h @@ -0,0 +1,334 @@ +//===- HashTable.h - PDB Hash 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_PDB_NATIVE_HASHTABLE_H +#define LLVM_DEBUGINFO_PDB_NATIVE_HASHTABLE_H + +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/iterator.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <iterator> +#include <utility> +#include <vector> + +namespace llvm { + +class BinaryStreamReader; +class BinaryStreamWriter; + +namespace pdb { + +Error readSparseBitVector(BinaryStreamReader &Stream, SparseBitVector<> &V); +Error writeSparseBitVector(BinaryStreamWriter &Writer, SparseBitVector<> &Vec); + +template <typename ValueT, typename TraitsT> class HashTable; + +template <typename ValueT, typename TraitsT> +class HashTableIterator + : public iterator_facade_base<HashTableIterator<ValueT, TraitsT>, + std::forward_iterator_tag, + std::pair<uint32_t, ValueT>> { + friend HashTable<ValueT, TraitsT>; + + HashTableIterator(const HashTable<ValueT, TraitsT> &Map, uint32_t Index, + bool IsEnd) + : Map(&Map), Index(Index), IsEnd(IsEnd) {} + +public: + HashTableIterator(const HashTable<ValueT, TraitsT> &Map) : Map(&Map) { + int I = Map.Present.find_first(); + if (I == -1) { + Index = 0; + IsEnd = true; + } else { + Index = static_cast<uint32_t>(I); + IsEnd = false; + } + } + + HashTableIterator &operator=(const HashTableIterator &R) { + Map = R.Map; + return *this; + } + bool operator==(const HashTableIterator &R) const { + if (IsEnd && R.IsEnd) + return true; + if (IsEnd != R.IsEnd) + return false; + + return (Map == R.Map) && (Index == R.Index); + } + const std::pair<uint32_t, ValueT> &operator*() const { + assert(Map->Present.test(Index)); + return Map->Buckets[Index]; + } + HashTableIterator &operator++() { + while (Index < Map->Buckets.size()) { + ++Index; + if (Map->Present.test(Index)) + return *this; + } + + IsEnd = true; + return *this; + } + +private: + bool isEnd() const { return IsEnd; } + uint32_t index() const { return Index; } + + const HashTable<ValueT, TraitsT> *Map; + uint32_t Index; + bool IsEnd; +}; + +template <typename T> struct PdbHashTraits {}; + +template <> struct PdbHashTraits<uint32_t> { + uint32_t hashLookupKey(uint32_t N) const { return N; } + uint32_t storageKeyToLookupKey(uint32_t N) const { return N; } + uint32_t lookupKeyToStorageKey(uint32_t N) { return N; } +}; + +template <typename ValueT, typename TraitsT = PdbHashTraits<ValueT>> +class HashTable { + using iterator = HashTableIterator<ValueT, TraitsT>; + friend iterator; + + struct Header { + support::ulittle32_t Size; + support::ulittle32_t Capacity; + }; + + using BucketList = std::vector<std::pair<uint32_t, ValueT>>; + +public: + HashTable() { Buckets.resize(8); } + + explicit HashTable(TraitsT Traits) : HashTable(8, std::move(Traits)) {} + HashTable(uint32_t Capacity, TraitsT Traits) : Traits(Traits) { + Buckets.resize(Capacity); + } + + Error load(BinaryStreamReader &Stream) { + const Header *H; + if (auto EC = Stream.readObject(H)) + return EC; + if (H->Capacity == 0) + return make_error<RawError>(raw_error_code::corrupt_file, + "Invalid Hash Table Capacity"); + if (H->Size > maxLoad(H->Capacity)) + return make_error<RawError>(raw_error_code::corrupt_file, + "Invalid Hash Table Size"); + + Buckets.resize(H->Capacity); + + if (auto EC = readSparseBitVector(Stream, Present)) + return EC; + if (Present.count() != H->Size) + return make_error<RawError>(raw_error_code::corrupt_file, + "Present bit vector does not match size!"); + + if (auto EC = readSparseBitVector(Stream, Deleted)) + return EC; + if (Present.intersects(Deleted)) + return make_error<RawError>(raw_error_code::corrupt_file, + "Present bit vector interesects deleted!"); + + for (uint32_t P : Present) { + if (auto EC = Stream.readInteger(Buckets[P].first)) + return EC; + const ValueT *Value; + if (auto EC = Stream.readObject(Value)) + return EC; + Buckets[P].second = *Value; + } + + return Error::success(); + } + + uint32_t calculateSerializedLength() const { + uint32_t Size = sizeof(Header); + + constexpr int BitsPerWord = 8 * sizeof(uint32_t); + + int NumBitsP = Present.find_last() + 1; + int NumBitsD = Deleted.find_last() + 1; + + uint32_t NumWordsP = alignTo(NumBitsP, BitsPerWord) / BitsPerWord; + uint32_t NumWordsD = alignTo(NumBitsD, BitsPerWord) / BitsPerWord; + + // Present bit set number of words (4 bytes), followed by that many actual + // words (4 bytes each). + Size += sizeof(uint32_t); + Size += NumWordsP * sizeof(uint32_t); + + // Deleted bit set number of words (4 bytes), followed by that many actual + // words (4 bytes each). + Size += sizeof(uint32_t); + Size += NumWordsD * sizeof(uint32_t); + + // One (Key, ValueT) pair for each entry Present. + Size += (sizeof(uint32_t) + sizeof(ValueT)) * size(); + + return Size; + } + + Error commit(BinaryStreamWriter &Writer) const { + Header H; + H.Size = size(); + H.Capacity = capacity(); + if (auto EC = Writer.writeObject(H)) + return EC; + + if (auto EC = writeSparseBitVector(Writer, Present)) + return EC; + + if (auto EC = writeSparseBitVector(Writer, Deleted)) + return EC; + + for (const auto &Entry : *this) { + if (auto EC = Writer.writeInteger(Entry.first)) + return EC; + if (auto EC = Writer.writeObject(Entry.second)) + return EC; + } + return Error::success(); + } + + void clear() { + Buckets.resize(8); + Present.clear(); + Deleted.clear(); + } + + bool empty() const { return size() == 0; } + uint32_t capacity() const { return Buckets.size(); } + uint32_t size() const { return Present.count(); } + + iterator begin() const { return iterator(*this); } + iterator end() const { return iterator(*this, 0, true); } + + /// Find the entry whose key has the specified hash value, using the specified + /// traits defining hash function and equality. + template <typename Key> iterator find_as(const Key &K) const { + uint32_t H = Traits.hashLookupKey(K) % capacity(); + uint32_t I = H; + Optional<uint32_t> FirstUnused; + do { + if (isPresent(I)) { + if (Traits.storageKeyToLookupKey(Buckets[I].first) == K) + return iterator(*this, I, false); + } else { + if (!FirstUnused) + FirstUnused = I; + // Insertion occurs via linear probing from the slot hint, and will be + // inserted at the first empty / deleted location. Therefore, if we are + // probing and find a location that is neither present nor deleted, then + // nothing must have EVER been inserted at this location, and thus it is + // not possible for a matching value to occur later. + if (!isDeleted(I)) + break; + } + I = (I + 1) % capacity(); + } while (I != H); + + // The only way FirstUnused would not be set is if every single entry in the + // table were Present. But this would violate the load factor constraints + // that we impose, so it should never happen. + assert(FirstUnused); + return iterator(*this, *FirstUnused, true); + } + + /// Set the entry using a key type that the specified Traits can convert + /// from a real key to an internal key. + template <typename Key> bool set_as(const Key &K, ValueT V) { + return set_as_internal(K, std::move(V), None); + } + + template <typename Key> ValueT get(const Key &K) const { + auto Iter = find_as(K); + assert(Iter != end()); + return (*Iter).second; + } + +protected: + bool isPresent(uint32_t K) const { return Present.test(K); } + bool isDeleted(uint32_t K) const { return Deleted.test(K); } + + TraitsT Traits; + BucketList Buckets; + mutable SparseBitVector<> Present; + mutable SparseBitVector<> Deleted; + +private: + /// Set the entry using a key type that the specified Traits can convert + /// from a real key to an internal key. + template <typename Key> + bool set_as_internal(const Key &K, ValueT V, Optional<uint32_t> InternalKey) { + auto Entry = find_as(K); + if (Entry != end()) { + assert(isPresent(Entry.index())); + assert(Traits.storageKeyToLookupKey(Buckets[Entry.index()].first) == K); + // We're updating, no need to do anything special. + Buckets[Entry.index()].second = V; + return false; + } + + auto &B = Buckets[Entry.index()]; + assert(!isPresent(Entry.index())); + assert(Entry.isEnd()); + B.first = InternalKey ? *InternalKey : Traits.lookupKeyToStorageKey(K); + B.second = V; + Present.set(Entry.index()); + Deleted.reset(Entry.index()); + + grow(); + + assert((find_as(K)) != end()); + return true; + } + + static uint32_t maxLoad(uint32_t capacity) { return capacity * 2 / 3 + 1; } + + void grow() { + uint32_t S = size(); + uint32_t MaxLoad = maxLoad(capacity()); + if (S < maxLoad(capacity())) + return; + assert(capacity() != UINT32_MAX && "Can't grow Hash table!"); + + uint32_t NewCapacity = (capacity() <= INT32_MAX) ? MaxLoad * 2 : UINT32_MAX; + + // Growing requires rebuilding the table and re-hashing every item. Make a + // copy with a larger capacity, insert everything into the copy, then swap + // it in. + HashTable NewMap(NewCapacity, Traits); + for (auto I : Present) { + auto LookupKey = Traits.storageKeyToLookupKey(Buckets[I].first); + NewMap.set_as_internal(LookupKey, Buckets[I].second, Buckets[I].first); + } + + Buckets.swap(NewMap.Buckets); + std::swap(Present, NewMap.Present); + std::swap(Deleted, NewMap.Deleted); + assert(capacity() == NewCapacity); + assert(size() == S); + } +}; + +} // end namespace pdb + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_HASHTABLE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h new file mode 100644 index 00000000..717dce2f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h @@ -0,0 +1,29 @@ +//===- ISectionContribVisitor.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_PDB_RAW_ISECTIONCONTRIBVISITOR_H +#define LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H + +namespace llvm { +namespace pdb { + +struct SectionContrib; +struct SectionContrib2; + +class ISectionContribVisitor { +public: + virtual ~ISectionContribVisitor() = default; + + virtual void visit(const SectionContrib &C) = 0; + virtual void visit(const SectionContrib2 &C) = 0; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/InfoStream.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/InfoStream.h new file mode 100644 index 00000000..315b0935 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/InfoStream.h @@ -0,0 +1,74 @@ +//===- InfoStream.h - PDB Info Stream (Stream 1) Access ---------*- 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_RAW_PDBINFOSTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H + +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/DebugInfo/CodeView/GUID.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" + +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class InfoStreamBuilder; +class PDBFile; + +class InfoStream { + friend class InfoStreamBuilder; + +public: + InfoStream(std::unique_ptr<BinaryStream> Stream); + + Error reload(); + + uint32_t getStreamSize() const; + + const InfoStreamHeader *getHeader() const { return Header; } + + bool containsIdStream() const; + PdbRaw_ImplVer getVersion() const; + uint32_t getSignature() const; + uint32_t getAge() const; + codeview::GUID getGuid() const; + uint32_t getNamedStreamMapByteSize() const; + + PdbRaw_Features getFeatures() const; + ArrayRef<PdbRaw_FeatureSig> getFeatureSignatures() const; + + const NamedStreamMap &getNamedStreams() const; + + BinarySubstreamRef getNamedStreamsBuffer() const; + + Expected<uint32_t> getNamedStreamIndex(llvm::StringRef Name) const; + StringMap<uint32_t> named_streams() const; + +private: + std::unique_ptr<BinaryStream> Stream; + + const InfoStreamHeader *Header; + + BinarySubstreamRef SubNamedStreams; + + std::vector<PdbRaw_FeatureSig> FeatureSignatures; + PdbRaw_Features Features = PdbFeatureNone; + + uint32_t NamedStreamMapByteSize = 0; + + NamedStreamMap NamedStreams; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h new file mode 100644 index 00000000..208a37c4 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h @@ -0,0 +1,76 @@ +//===- InfoStreamBuilder.h - PDB Info Stream Creation -----------*- 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_RAW_PDBINFOSTREAMBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAMBUILDER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/Error.h" + +#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" + +namespace llvm { +class WritableBinaryStreamRef; + +namespace msf { +class MSFBuilder; +} +namespace pdb { +class PDBFile; +class NamedStreamMap; + +class InfoStreamBuilder { +public: + InfoStreamBuilder(msf::MSFBuilder &Msf, NamedStreamMap &NamedStreams); + InfoStreamBuilder(const InfoStreamBuilder &) = delete; + InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete; + + void setVersion(PdbRaw_ImplVer V); + void addFeature(PdbRaw_FeatureSig Sig); + + // If this is true, the PDB contents are hashed and this hash is used as + // PDB GUID and as Signature. The age is always 1. + void setHashPDBContentsToGUID(bool B); + + // These only have an effect if hashPDBContentsToGUID() is false. + void setSignature(uint32_t S); + void setAge(uint32_t A); + void setGuid(codeview::GUID G); + + bool hashPDBContentsToGUID() const { return HashPDBContentsToGUID; } + uint32_t getAge() const { return Age; } + codeview::GUID getGuid() const { return Guid; } + Optional<uint32_t> getSignature() const { return Signature; } + + uint32_t finalize(); + + Error finalizeMsfLayout(); + + Error commit(const msf::MSFLayout &Layout, + WritableBinaryStreamRef Buffer) const; + +private: + msf::MSFBuilder &Msf; + + std::vector<PdbRaw_FeatureSig> Features; + PdbRaw_ImplVer Ver; + uint32_t Age; + Optional<uint32_t> Signature; + codeview::GUID Guid; + + bool HashPDBContentsToGUID = false; + + NamedStreamMap &NamedStreams; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h new file mode 100644 index 00000000..161aa32f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h @@ -0,0 +1,90 @@ +//===- ModuleDebugStream.h - PDB Module Info Stream Access ------*- 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_NATIVE_MODULEDEBUGSTREAM_H +#define LLVM_DEBUGINFO_PDB_NATIVE_MODULEDEBUGSTREAM_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <memory> + +namespace llvm { +namespace pdb { + +class DbiModuleDescriptor; + +class ModuleDebugStreamRef { + using DebugSubsectionIterator = codeview::DebugSubsectionArray::Iterator; + +public: + ModuleDebugStreamRef(const DbiModuleDescriptor &Module, + std::unique_ptr<msf::MappedBlockStream> Stream); + ModuleDebugStreamRef(ModuleDebugStreamRef &&Other) = default; + ModuleDebugStreamRef(const ModuleDebugStreamRef &Other) = default; + ~ModuleDebugStreamRef(); + + Error reload(); + + uint32_t signature() const { return Signature; } + + iterator_range<codeview::CVSymbolArray::Iterator> + symbols(bool *HadError) const; + + const codeview::CVSymbolArray &getSymbolArray() const { return SymbolArray; } + const codeview::CVSymbolArray + getSymbolArrayForScope(uint32_t ScopeBegin) const; + + BinarySubstreamRef getSymbolsSubstream() const; + BinarySubstreamRef getC11LinesSubstream() const; + BinarySubstreamRef getC13LinesSubstream() const; + BinarySubstreamRef getGlobalRefsSubstream() const; + + ModuleDebugStreamRef &operator=(ModuleDebugStreamRef &&Other) = delete; + + codeview::CVSymbol readSymbolAtOffset(uint32_t Offset) const; + + iterator_range<DebugSubsectionIterator> subsections() const; + codeview::DebugSubsectionArray getSubsectionsArray() const { + return Subsections; + } + + bool hasDebugSubsections() const; + + Error commit(); + + Expected<codeview::DebugChecksumsSubsectionRef> + findChecksumsSubsection() const; + +private: + DbiModuleDescriptor Mod; + + uint32_t Signature; + + std::shared_ptr<msf::MappedBlockStream> Stream; + + codeview::CVSymbolArray SymbolArray; + + BinarySubstreamRef SymbolsSubstream; + BinarySubstreamRef C11LinesSubstream; + BinarySubstreamRef C13LinesSubstream; + BinarySubstreamRef GlobalRefsSubstream; + + codeview::DebugSubsectionArray Subsections; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_MODULEDEBUGSTREAM_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h new file mode 100644 index 00000000..c49d7963 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h @@ -0,0 +1,72 @@ +//===- NamedStreamMap.h - PDB Named Stream Map ------------------*- 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_NATIVE_NAMEDSTREAMMAP_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NAMEDSTREAMMAP_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/PDB/Native/HashTable.h" +#include "llvm/Support/Error.h" +#include <cstdint> + +namespace llvm { + +class BinaryStreamReader; +class BinaryStreamWriter; + +namespace pdb { + +class NamedStreamMap; + +struct NamedStreamMapTraits { + NamedStreamMap *NS; + + explicit NamedStreamMapTraits(NamedStreamMap &NS); + uint16_t hashLookupKey(StringRef S) const; + StringRef storageKeyToLookupKey(uint32_t Offset) const; + uint32_t lookupKeyToStorageKey(StringRef S); +}; + +class NamedStreamMap { + friend class NamedStreamMapBuilder; + +public: + NamedStreamMap(); + + Error load(BinaryStreamReader &Stream); + Error commit(BinaryStreamWriter &Writer) const; + uint32_t calculateSerializedLength() const; + + uint32_t size() const; + bool get(StringRef Stream, uint32_t &StreamNo) const; + void set(StringRef Stream, uint32_t StreamNo); + + uint32_t appendStringData(StringRef S); + StringRef getString(uint32_t Offset) const; + uint32_t hashString(uint32_t Offset) const; + + StringMap<uint32_t> entries() const; + +private: + NamedStreamMapTraits HashTraits; + /// Closed hash table from Offset -> StreamNumber, where Offset is the offset + /// of the stream name in NamesBuffer. + HashTable<support::ulittle32_t, NamedStreamMapTraits> OffsetIndexMap; + + /// Buffer of string data. + std::vector<char> NamesBuffer; +}; + +} // end namespace pdb + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NAMEDSTREAMMAP_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h new file mode 100644 index 00000000..50d43764 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h @@ -0,0 +1,39 @@ +//===- NativeCompilandSymbol.h - native impl for compiland syms -*- 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_NATIVE_NATIVECOMPILANDSYMBOL_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVECOMPILANDSYMBOL_H + +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" + +namespace llvm { +namespace pdb { + +class NativeCompilandSymbol : public NativeRawSymbol { +public: + NativeCompilandSymbol(NativeSession &Session, SymIndexId SymbolId, + DbiModuleDescriptor MI); + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + PDB_SymType getSymTag() const override; + bool isEditAndContinueEnabled() const override; + SymIndexId getLexicalParentId() const override; + std::string getLibraryName() const override; + std::string getName() const override; + +private: + DbiModuleDescriptor Module; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h new file mode 100644 index 00000000..073878af --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h @@ -0,0 +1,42 @@ +//==- NativeEnumGlobals.h - Native Global Enumerator impl --------*- 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_NATIVE_NATIVEENUMGLOBALS_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMGLOBALS_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +#include <vector> + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeEnumGlobals : public IPDBEnumChildren<PDBSymbol> { +public: + NativeEnumGlobals(NativeSession &Session, + std::vector<codeview::SymbolKind> Kinds); + + uint32_t getChildCount() const override; + std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; + std::unique_ptr<PDBSymbol> getNext() override; + void reset() override; + +private: + std::vector<uint32_t> MatchOffsets; + uint32_t Index; + NativeSession &Session; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h new file mode 100644 index 00000000..94f1ee18 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h @@ -0,0 +1,35 @@ +//==- NativeEnumModules.h - Native Module Enumerator impl --------*- 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_NATIVE_NATIVEENUMMODULES_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMMODULES_H + +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeEnumModules : public IPDBEnumChildren<PDBSymbol> { +public: + NativeEnumModules(NativeSession &Session, uint32_t Index = 0); + + uint32_t getChildCount() const override; + std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; + std::unique_ptr<PDBSymbol> getNext() override; + void reset() override; + +private: + NativeSession &Session; + uint32_t Index; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h new file mode 100644 index 00000000..25c56567 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h @@ -0,0 +1,47 @@ +//==- NativeEnumTypes.h - Native Type Enumerator impl ------------*- 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_NATIVE_NATIVEENUMTYPES_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMTYPES_H + +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +#include <vector> + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeEnumTypes : public IPDBEnumChildren<PDBSymbol> { +public: + NativeEnumTypes(NativeSession &Session, + codeview::LazyRandomTypeCollection &TypeCollection, + std::vector<codeview::TypeLeafKind> Kinds); + + NativeEnumTypes(NativeSession &Session, + std::vector<codeview::TypeIndex> Indices); + + uint32_t getChildCount() const override; + std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; + std::unique_ptr<PDBSymbol> getNext() override; + void reset() override; + +private: + std::vector<codeview::TypeIndex> Matches; + uint32_t Index; + NativeSession &Session; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h new file mode 100644 index 00000000..280358d0 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h @@ -0,0 +1,40 @@ +//===- NativeExeSymbol.h - native impl for PDBSymbolExe ---------*- 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_NATIVE_NATIVEEXESYMBOL_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEEXESYMBOL_H + +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class DbiStream; + +class NativeExeSymbol : public NativeRawSymbol { + // EXE symbol is the authority on the various symbol types. + DbiStream *Dbi = nullptr; + +public: + NativeExeSymbol(NativeSession &Session, SymIndexId Id); + + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type) const override; + + uint32_t getAge() const override; + std::string getSymbolsFileName() const override; + codeview::GUID getGuid() const override; + bool hasCTypes() const override; + bool hasPrivateSymbols() const override; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h new file mode 100644 index 00000000..4133be22 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h @@ -0,0 +1,240 @@ +//==- NativeRawSymbol.h - Native implementation of IPDBRawSymbol -*- 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_NATIVE_NATIVERAWSYMBOL_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVERAWSYMBOL_H + +#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" +#include <cstdint> +#include <memory> + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeRawSymbol : public IPDBRawSymbol { + friend class SymbolCache; + virtual void initialize() {} + +public: + NativeRawSymbol(NativeSession &PDBSession, PDB_SymType Tag, + SymIndexId SymbolId); + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildrenByAddr(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t Section, uint32_t Offset) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint64_t VA) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const override; + + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const override; + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByRVA(uint32_t RVA) const override; + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByVA(uint64_t VA) const override; + + std::unique_ptr<IPDBEnumLineNumbers> findInlineeLines() const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, + uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override; + + void getDataBytes(SmallVector<uint8_t, 32> &Bytes) const override; + void getFrontEndVersion(VersionInfo &Version) const override; + void getBackEndVersion(VersionInfo &Version) const override; + PDB_MemberAccess getAccess() const override; + uint32_t getAddressOffset() const override; + uint32_t getAddressSection() const override; + uint32_t getAge() const override; + SymIndexId getArrayIndexTypeId() const override; + uint32_t getBaseDataOffset() const override; + uint32_t getBaseDataSlot() const override; + SymIndexId getBaseSymbolId() const override; + PDB_BuiltinType getBuiltinType() const override; + uint32_t getBitPosition() const override; + PDB_CallingConv getCallingConvention() const override; + SymIndexId getClassParentId() const override; + std::string getCompilerName() const override; + uint32_t getCount() const override; + uint32_t getCountLiveRanges() const override; + PDB_Lang getLanguage() const override; + SymIndexId getLexicalParentId() const override; + std::string getLibraryName() const override; + uint32_t getLiveRangeStartAddressOffset() const override; + uint32_t getLiveRangeStartAddressSection() const override; + uint32_t getLiveRangeStartRelativeVirtualAddress() const override; + codeview::RegisterId getLocalBasePointerRegisterId() const override; + SymIndexId getLowerBoundId() const override; + uint32_t getMemorySpaceKind() const override; + std::string getName() const override; + uint32_t getNumberOfAcceleratorPointerTags() const override; + uint32_t getNumberOfColumns() const override; + uint32_t getNumberOfModifiers() const override; + uint32_t getNumberOfRegisterIndices() const override; + uint32_t getNumberOfRows() const override; + std::string getObjectFileName() const override; + uint32_t getOemId() const override; + SymIndexId getOemSymbolId() const override; + uint32_t getOffsetInUdt() const override; + PDB_Cpu getPlatform() const override; + uint32_t getRank() const override; + codeview::RegisterId getRegisterId() const override; + uint32_t getRegisterType() const override; + uint32_t getRelativeVirtualAddress() const override; + uint32_t getSamplerSlot() const override; + uint32_t getSignature() const override; + uint32_t getSizeInUdt() const override; + uint32_t getSlot() const override; + std::string getSourceFileName() const override; + std::unique_ptr<IPDBLineNumber> getSrcLineOnTypeDefn() const override; + uint32_t getStride() const override; + SymIndexId getSubTypeId() const override; + std::string getSymbolsFileName() const override; + SymIndexId getSymIndexId() const override; + uint32_t getTargetOffset() const override; + uint32_t getTargetRelativeVirtualAddress() const override; + uint64_t getTargetVirtualAddress() const override; + uint32_t getTargetSection() const override; + uint32_t getTextureSlot() const override; + uint32_t getTimeStamp() const override; + uint32_t getToken() const override; + SymIndexId getTypeId() const override; + uint32_t getUavSlot() const override; + std::string getUndecoratedName() const override; + std::string getUndecoratedNameEx(PDB_UndnameFlags Flags) const override; + SymIndexId getUnmodifiedTypeId() const override; + SymIndexId getUpperBoundId() const override; + Variant getValue() const override; + uint32_t getVirtualBaseDispIndex() const override; + uint32_t getVirtualBaseOffset() const override; + SymIndexId getVirtualTableShapeId() const override; + std::unique_ptr<PDBSymbolTypeBuiltin> + getVirtualBaseTableType() const override; + PDB_DataKind getDataKind() const override; + PDB_SymType getSymTag() const override; + codeview::GUID getGuid() const override; + int32_t getOffset() const override; + int32_t getThisAdjust() const override; + int32_t getVirtualBasePointerOffset() const override; + PDB_LocType getLocationType() const override; + PDB_Machine getMachineType() const override; + codeview::ThunkOrdinal getThunkOrdinal() const override; + uint64_t getLength() const override; + uint64_t getLiveRangeLength() const override; + uint64_t getVirtualAddress() const override; + PDB_UdtType getUdtKind() const override; + bool hasConstructor() const override; + bool hasCustomCallingConvention() const override; + bool hasFarReturn() const override; + bool isCode() const override; + bool isCompilerGenerated() const override; + bool isConstType() const override; + bool isEditAndContinueEnabled() const override; + bool isFunction() const override; + bool getAddressTaken() const override; + bool getNoStackOrdering() const override; + bool hasAlloca() const override; + bool hasAssignmentOperator() const override; + bool hasCTypes() const override; + bool hasCastOperator() const override; + bool hasDebugInfo() const override; + bool hasEH() const override; + bool hasEHa() const override; + bool hasInlAsm() const override; + bool hasInlineAttribute() const override; + bool hasInterruptReturn() const override; + bool hasFramePointer() const override; + bool hasLongJump() const override; + bool hasManagedCode() const override; + bool hasNestedTypes() const override; + bool hasNoInlineAttribute() const override; + bool hasNoReturnAttribute() const override; + bool hasOptimizedCodeDebugInfo() const override; + bool hasOverloadedOperator() const override; + bool hasSEH() const override; + bool hasSecurityChecks() const override; + bool hasSetJump() const override; + bool hasStrictGSCheck() const override; + bool isAcceleratorGroupSharedLocal() const override; + bool isAcceleratorPointerTagLiveRange() const override; + bool isAcceleratorStubFunction() const override; + bool isAggregated() const override; + bool isIntroVirtualFunction() const override; + bool isCVTCIL() const override; + bool isConstructorVirtualBase() const override; + bool isCxxReturnUdt() const override; + bool isDataAligned() const override; + bool isHLSLData() const override; + bool isHotpatchable() const override; + bool isIndirectVirtualBaseClass() const override; + bool isInterfaceUdt() const override; + bool isIntrinsic() const override; + bool isLTCG() const override; + bool isLocationControlFlowDependent() const override; + bool isMSILNetmodule() const override; + bool isMatrixRowMajor() const override; + bool isManagedCode() const override; + bool isMSILCode() const override; + bool isMultipleInheritance() const override; + bool isNaked() const override; + bool isNested() const override; + bool isOptimizedAway() const override; + bool isPacked() const override; + bool isPointerBasedOnSymbolValue() const override; + bool isPointerToDataMember() const override; + bool isPointerToMemberFunction() const override; + bool isPureVirtual() const override; + bool isRValueReference() const override; + bool isRefUdt() const override; + bool isReference() const override; + bool isRestrictedType() const override; + bool isReturnValue() const override; + bool isSafeBuffers() const override; + bool isScoped() const override; + bool isSdl() const override; + bool isSingleInheritance() const override; + bool isSplitted() const override; + bool isStatic() const override; + bool hasPrivateSymbols() const override; + bool isUnalignedType() const override; + bool isUnreached() const override; + bool isValueUdt() const override; + bool isVirtual() const override; + bool isVirtualBaseClass() const override; + bool isVirtualInheritance() const override; + bool isVolatileType() const override; + bool wasInlined() const override; + std::string getUnused() const override; + +protected: + NativeSession &Session; + PDB_SymType Tag; + SymIndexId SymbolId; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVERAWSYMBOL_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeSession.h new file mode 100644 index 00000000..ee7d8cde --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -0,0 +1,116 @@ +//===- NativeSession.h - Native implementation of IPDBSession ---*- 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_NATIVE_NATIVESESSION_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESESSION_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" + +namespace llvm { +class MemoryBuffer; +namespace pdb { +class PDBFile; +class NativeExeSymbol; + +class NativeSession : public IPDBSession { +public: + NativeSession(std::unique_ptr<PDBFile> PdbFile, + std::unique_ptr<BumpPtrAllocator> Allocator); + ~NativeSession() override; + + static Error createFromPdb(std::unique_ptr<MemoryBuffer> MB, + std::unique_ptr<IPDBSession> &Session); + static Error createFromExe(StringRef Path, + std::unique_ptr<IPDBSession> &Session); + + uint64_t getLoadAddress() const override; + bool setLoadAddress(uint64_t Address) override; + std::unique_ptr<PDBSymbolExe> getGlobalScope() override; + std::unique_ptr<PDBSymbol> getSymbolById(SymIndexId SymbolId) const override; + + bool addressForVA(uint64_t VA, uint32_t &Section, + uint32_t &Offset) const override; + bool addressForRVA(uint32_t RVA, uint32_t &Section, + uint32_t &Offset) const override; + + std::unique_ptr<PDBSymbol> + findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override; + std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA, + PDB_SymType Type) const override; + std::unique_ptr<PDBSymbol> + findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, + PDB_SymType Type) const override; + + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbers(const PDBSymbolCompiland &Compiland, + const IPDBSourceFile &File) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, + uint32_t Length) const override; + + std::unique_ptr<IPDBEnumSourceFiles> + findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBSourceFile> + findOneSourceFile(const PDBSymbolCompiland *Compiland, + llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> + findCompilandsForSourceFile(llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<PDBSymbolCompiland> + findOneCompilandForSourceFile(llvm::StringRef Pattern, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override; + std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland( + const PDBSymbolCompiland &Compiland) const override; + std::unique_ptr<IPDBSourceFile> + getSourceFileById(uint32_t FileId) const override; + + std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override; + + std::unique_ptr<IPDBEnumTables> getEnumTables() const override; + + std::unique_ptr<IPDBEnumInjectedSources> getInjectedSources() const override; + + std::unique_ptr<IPDBEnumSectionContribs> getSectionContribs() const override; + + std::unique_ptr<IPDBEnumFrameData> getFrameData() const override; + + PDBFile &getPDBFile() { return *Pdb; } + const PDBFile &getPDBFile() const { return *Pdb; } + + NativeExeSymbol &getNativeGlobalScope() const; + SymbolCache &getSymbolCache() { return Cache; } + const SymbolCache &getSymbolCache() const { return Cache; } + +private: + void initializeExeSymbol(); + + std::unique_ptr<PDBFile> Pdb; + std::unique_ptr<BumpPtrAllocator> Allocator; + + SymbolCache Cache; + SymIndexId ExeSymbol = 0; +}; +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h new file mode 100644 index 00000000..06358509 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h @@ -0,0 +1,50 @@ +//===- NativeSymbolEnumerator.h - info about enumerator values --*- 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_NATIVE_NATIVESYMBOLENUMERATOR_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESYMBOLENUMERATOR_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { +class NativeTypeEnum; + +class NativeSymbolEnumerator : public NativeRawSymbol { +public: + NativeSymbolEnumerator(NativeSession &Session, SymIndexId Id, + const NativeTypeEnum &Parent, + codeview::EnumeratorRecord Record); + + ~NativeSymbolEnumerator() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + SymIndexId getClassParentId() const override; + SymIndexId getLexicalParentId() const override; + std::string getName() const override; + SymIndexId getTypeId() const override; + PDB_DataKind getDataKind() const override; + PDB_LocType getLocationType() const override; + bool isConstType() const override; + bool isVolatileType() const override; + bool isUnalignedType() const override; + Variant getValue() const override; + +protected: + const NativeTypeEnum &Parent; + codeview::EnumeratorRecord Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h new file mode 100644 index 00000000..262864fd --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h @@ -0,0 +1,49 @@ +//===- NativeTypeArray.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_PDB_NATIVE_NATIVETYPEARRAY_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEARRAY_H + +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeTypeArray : public NativeRawSymbol { +public: + NativeTypeArray(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::ArrayRecord Record); + ~NativeTypeArray() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + SymIndexId getArrayIndexTypeId() const override; + + bool isConstType() const override; + bool isUnalignedType() const override; + bool isVolatileType() const override; + + uint32_t getCount() const override; + SymIndexId getTypeId() const override; + uint64_t getLength() const override; + +protected: + codeview::ArrayRecord Record; + codeview::TypeIndex Index; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h new file mode 100644 index 00000000..8bb09f05 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h @@ -0,0 +1,49 @@ +//===- NativeTypeBuiltin.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_PDB_NATIVE_NATIVETYPEBUILTIN_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEBUILTIN_H + +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" + +#include "llvm/DebugInfo/PDB/PDBTypes.h" + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeTypeBuiltin : public NativeRawSymbol { +public: + NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id, + codeview::ModifierOptions Mods, PDB_BuiltinType T, + uint64_t L); + ~NativeTypeBuiltin() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + PDB_SymType getSymTag() const override; + + PDB_BuiltinType getBuiltinType() const override; + bool isConstType() const override; + uint64_t getLength() const override; + bool isUnalignedType() const override; + bool isVolatileType() const override; + +protected: + NativeSession &Session; + codeview::ModifierOptions Mods; + PDB_BuiltinType Type; + uint64_t Length; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h new file mode 100644 index 00000000..2068c88f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h @@ -0,0 +1,74 @@ +//===- NativeTypeEnum.h - info about enum type ------------------*- 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_NATIVE_NATIVETYPEENUM_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeBuiltin; + +class NativeTypeEnum : public NativeRawSymbol { +public: + NativeTypeEnum(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::EnumRecord Record); + + NativeTypeEnum(NativeSession &Session, SymIndexId Id, + NativeTypeEnum &UnmodifiedType, + codeview::ModifierRecord Modifier); + ~NativeTypeEnum() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type) const override; + + PDB_BuiltinType getBuiltinType() const override; + PDB_SymType getSymTag() const override; + SymIndexId getUnmodifiedTypeId() const override; + bool hasConstructor() const override; + bool hasAssignmentOperator() const override; + bool hasCastOperator() const override; + uint64_t getLength() const override; + std::string getName() const override; + bool isConstType() const override; + bool isVolatileType() const override; + bool isUnalignedType() const override; + bool isNested() const override; + bool hasOverloadedOperator() const override; + bool hasNestedTypes() const override; + bool isIntrinsic() const override; + bool isPacked() const override; + bool isScoped() const override; + SymIndexId getTypeId() const override; + bool isRefUdt() const override; + bool isValueUdt() const override; + bool isInterfaceUdt() const override; + + const NativeTypeBuiltin &getUnderlyingBuiltinType() const; + const codeview::EnumRecord &getEnumRecord() const { return *Record; } + +protected: + codeview::TypeIndex Index; + Optional<codeview::EnumRecord> Record; + NativeTypeEnum *UnmodifiedType = nullptr; + Optional<codeview::ModifierRecord> Modifiers; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h new file mode 100644 index 00000000..a7ea287d --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h @@ -0,0 +1,73 @@ +//===- NativeTypeFunctionSig.h - info about function signature ---*- 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_NATIVE_NATIVETYPEFUNCTIONSIG_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEFUNCTIONSIG_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeUDT; + +class NativeTypeFunctionSig : public NativeRawSymbol { +protected: + void initialize() override; + +public: + NativeTypeFunctionSig(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::ProcedureRecord Proc); + + NativeTypeFunctionSig(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, + codeview::MemberFunctionRecord MemberFunc); + + ~NativeTypeFunctionSig() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type) const override; + + SymIndexId getClassParentId() const override; + PDB_CallingConv getCallingConvention() const override; + uint32_t getCount() const override; + SymIndexId getTypeId() const override; + int32_t getThisAdjust() const override; + bool hasConstructor() const override; + bool isConstType() const override; + bool isConstructorVirtualBase() const override; + bool isCxxReturnUdt() const override; + bool isUnalignedType() const override; + bool isVolatileType() const override; + +private: + void initializeArgList(codeview::TypeIndex ArgListTI); + + union { + codeview::MemberFunctionRecord MemberFunc; + codeview::ProcedureRecord Proc; + }; + + SymIndexId ClassParentId = 0; + codeview::TypeIndex Index; + codeview::ArgListRecord ArgList; + bool IsMemberFunction = false; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
\ No newline at end of file diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h new file mode 100644 index 00000000..446f77db --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h @@ -0,0 +1,60 @@ +//===- NativeTypePointer.h - info about pointer type -------------*- 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_NATIVE_NATIVETYPEPOINTER_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypePointer : public NativeRawSymbol { +public: + // Create a pointer record for a simple type. + NativeTypePointer(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI); + + // Create a pointer record for a non-simple type. + NativeTypePointer(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::PointerRecord PR); + ~NativeTypePointer() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + SymIndexId getClassParentId() const override; + bool isConstType() const override; + uint64_t getLength() const override; + bool isReference() const override; + bool isRValueReference() const override; + bool isPointerToDataMember() const override; + bool isPointerToMemberFunction() const override; + SymIndexId getTypeId() const override; + bool isRestrictedType() const override; + bool isVolatileType() const override; + bool isUnalignedType() const override; + + bool isSingleInheritance() const override; + bool isMultipleInheritance() const override; + bool isVirtualInheritance() const override; + +protected: + bool isMemberPointer() const; + codeview::TypeIndex TI; + Optional<codeview::PointerRecord> Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
\ No newline at end of file diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h new file mode 100644 index 00000000..fe8a6f7f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h @@ -0,0 +1,41 @@ +//===- NativeTypeTypedef.h - info about typedef ------------------*- 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_NATIVE_NATIVETYPETYPEDEF_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPETYPEDEF_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeTypedef : public NativeRawSymbol { +public: + // Create a pointer record for a non-simple type. + NativeTypeTypedef(NativeSession &Session, SymIndexId Id, + codeview::UDTSym Typedef); + + ~NativeTypeTypedef() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::string getName() const override; + SymIndexId getTypeId() const override; + +protected: + codeview::UDTSym Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
\ No newline at end of file diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h new file mode 100644 index 00000000..8f4dee3e --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h @@ -0,0 +1,73 @@ +//===- NativeTypeUDT.h - info about class/struct type ------------*- 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_NATIVE_NATIVETYPEUDT_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeUDT : public NativeRawSymbol { +public: + NativeTypeUDT(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::ClassRecord Class); + + NativeTypeUDT(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::UnionRecord Union); + + NativeTypeUDT(NativeSession &Session, SymIndexId Id, + NativeTypeUDT &UnmodifiedType, + codeview::ModifierRecord Modifier); + + ~NativeTypeUDT() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::string getName() const override; + SymIndexId getLexicalParentId() const override; + SymIndexId getUnmodifiedTypeId() const override; + SymIndexId getVirtualTableShapeId() const override; + uint64_t getLength() const override; + PDB_UdtType getUdtKind() const override; + bool hasConstructor() const override; + bool isConstType() const override; + bool hasAssignmentOperator() const override; + bool hasCastOperator() const override; + bool hasNestedTypes() const override; + bool hasOverloadedOperator() const override; + bool isInterfaceUdt() const override; + bool isIntrinsic() const override; + bool isNested() const override; + bool isPacked() const override; + bool isRefUdt() const override; + bool isScoped() const override; + bool isValueUdt() const override; + bool isUnalignedType() const override; + bool isVolatileType() const override; + +protected: + codeview::TypeIndex Index; + + Optional<codeview::ClassRecord> Class; + Optional<codeview::UnionRecord> Union; + NativeTypeUDT *UnmodifiedType = nullptr; + codeview::TagRecord *Tag = nullptr; + Optional<codeview::ModifierRecord> Modifiers; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H
\ No newline at end of file diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h new file mode 100644 index 00000000..4ec0f9bf --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h @@ -0,0 +1,45 @@ +//===- NativeTypeVTShape.h - info about virtual table shape ------*- 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_NATIVE_NATIVETYPEVTSHAPE_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEVTSHAPE_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeVTShape : public NativeRawSymbol { +public: + // Create a pointer record for a non-simple type. + NativeTypeVTShape(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::VFTableShapeRecord SR); + + ~NativeTypeVTShape() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + bool isConstType() const override; + bool isVolatileType() const override; + bool isUnalignedType() const override; + uint32_t getCount() const override; + +protected: + codeview::TypeIndex TI; + codeview::VFTableShapeRecord Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEVTSHAPE_H
\ No newline at end of file diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBFile.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBFile.h new file mode 100644 index 00000000..cb9bd071 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBFile.h @@ -0,0 +1,143 @@ +//===- PDBFile.h - Low level interface to a PDB file ------------*- 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_RAW_PDBFILE_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBFILE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/DebugInfo/MSF/IMSFFile.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" + +#include <memory> + +namespace llvm { + +class BinaryStream; + +namespace msf { +class MappedBlockStream; +} + +namespace pdb { +class DbiStream; +class GlobalsStream; +class InfoStream; +class PDBStringTable; +class PDBFileBuilder; +class PublicsStream; +class SymbolStream; +class TpiStream; + +class PDBFile : public msf::IMSFFile { + friend PDBFileBuilder; + +public: + PDBFile(StringRef Path, std::unique_ptr<BinaryStream> PdbFileBuffer, + BumpPtrAllocator &Allocator); + ~PDBFile() override; + + StringRef getFileDirectory() const; + StringRef getFilePath() const; + + uint32_t getFreeBlockMapBlock() const; + uint32_t getUnknown1() const; + + uint32_t getBlockSize() const override; + uint32_t getBlockCount() const override; + uint32_t getNumDirectoryBytes() const; + uint32_t getBlockMapIndex() const; + uint32_t getNumDirectoryBlocks() const; + uint64_t getBlockMapOffset() const; + + uint32_t getNumStreams() const override; + uint32_t getMaxStreamSize() const; + uint32_t getStreamByteSize(uint32_t StreamIndex) const override; + ArrayRef<support::ulittle32_t> + getStreamBlockList(uint32_t StreamIndex) const override; + uint32_t getFileSize() const; + + Expected<ArrayRef<uint8_t>> getBlockData(uint32_t BlockIndex, + uint32_t NumBytes) const override; + Error setBlockData(uint32_t BlockIndex, uint32_t Offset, + ArrayRef<uint8_t> Data) const override; + + ArrayRef<support::ulittle32_t> getStreamSizes() const { + return ContainerLayout.StreamSizes; + } + ArrayRef<ArrayRef<support::ulittle32_t>> getStreamMap() const { + return ContainerLayout.StreamMap; + } + + const msf::MSFLayout &getMsfLayout() const { return ContainerLayout; } + BinaryStreamRef getMsfBuffer() const { return *Buffer; } + + ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const; + + std::unique_ptr<msf::MappedBlockStream> createIndexedStream(uint16_t SN); + + msf::MSFStreamLayout getStreamLayout(uint32_t StreamIdx) const; + msf::MSFStreamLayout getFpmStreamLayout() const; + + Error parseFileHeaders(); + Error parseStreamData(); + + Expected<InfoStream &> getPDBInfoStream(); + Expected<DbiStream &> getPDBDbiStream(); + Expected<GlobalsStream &> getPDBGlobalsStream(); + Expected<TpiStream &> getPDBTpiStream(); + Expected<TpiStream &> getPDBIpiStream(); + Expected<PublicsStream &> getPDBPublicsStream(); + Expected<SymbolStream &> getPDBSymbolStream(); + Expected<PDBStringTable &> getStringTable(); + + BumpPtrAllocator &getAllocator() { return Allocator; } + + bool hasPDBDbiStream() const; + bool hasPDBGlobalsStream(); + bool hasPDBInfoStream() const; + bool hasPDBIpiStream() const; + bool hasPDBPublicsStream(); + bool hasPDBSymbolStream(); + bool hasPDBTpiStream() const; + bool hasPDBStringTable(); + + uint32_t getPointerSize(); + +private: + Expected<std::unique_ptr<msf::MappedBlockStream>> + safelyCreateIndexedStream(const msf::MSFLayout &Layout, + BinaryStreamRef MsfData, + uint32_t StreamIndex) const; + + std::string FilePath; + BumpPtrAllocator &Allocator; + + std::unique_ptr<BinaryStream> Buffer; + + msf::MSFLayout ContainerLayout; + + std::unique_ptr<GlobalsStream> Globals; + std::unique_ptr<InfoStream> Info; + std::unique_ptr<DbiStream> Dbi; + std::unique_ptr<TpiStream> Tpi; + std::unique_ptr<TpiStream> Ipi; + std::unique_ptr<PublicsStream> Publics; + std::unique_ptr<SymbolStream> Symbols; + std::unique_ptr<msf::MappedBlockStream> DirectoryStream; + std::unique_ptr<msf::MappedBlockStream> StringTableStream; + std::unique_ptr<PDBStringTable> Strings; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h new file mode 100644 index 00000000..72000bdc --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h @@ -0,0 +1,110 @@ +//===- PDBFileBuilder.h - PDB File Creation ---------------------*- 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_RAW_PDBFILEBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBFILEBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" + +#include <memory> +#include <vector> + +namespace llvm { +namespace msf { +class MSFBuilder; +} +namespace pdb { +class DbiStreamBuilder; +class InfoStreamBuilder; +class GSIStreamBuilder; +class TpiStreamBuilder; + +class PDBFileBuilder { +public: + explicit PDBFileBuilder(BumpPtrAllocator &Allocator); + ~PDBFileBuilder(); + PDBFileBuilder(const PDBFileBuilder &) = delete; + PDBFileBuilder &operator=(const PDBFileBuilder &) = delete; + + Error initialize(uint32_t BlockSize); + + msf::MSFBuilder &getMsfBuilder(); + InfoStreamBuilder &getInfoBuilder(); + DbiStreamBuilder &getDbiBuilder(); + TpiStreamBuilder &getTpiBuilder(); + TpiStreamBuilder &getIpiBuilder(); + PDBStringTableBuilder &getStringTableBuilder(); + GSIStreamBuilder &getGsiBuilder(); + + // If HashPDBContentsToGUID is true on the InfoStreamBuilder, Guid is filled + // with the computed PDB GUID on return. + Error commit(StringRef Filename, codeview::GUID *Guid); + + Expected<uint32_t> getNamedStreamIndex(StringRef Name) const; + Error addNamedStream(StringRef Name, StringRef Data); + void addInjectedSource(StringRef Name, std::unique_ptr<MemoryBuffer> Buffer); + +private: + struct InjectedSourceDescriptor { + // The full name of the stream that contains the contents of this injected + // source. This is built as a concatenation of the literal "/src/files" + // plus the "vname". + std::string StreamName; + + // The exact name of the file name as specified by the user. + uint32_t NameIndex; + + // The string table index of the "vname" of the file. As far as we + // understand, this is the same as the name, except it is lowercased and + // forward slashes are converted to backslashes. + uint32_t VNameIndex; + std::unique_ptr<MemoryBuffer> Content; + }; + + Error finalizeMsfLayout(); + Expected<uint32_t> allocateNamedStream(StringRef Name, uint32_t Size); + + void commitFpm(WritableBinaryStream &MsfBuffer, const msf::MSFLayout &Layout); + void commitInjectedSources(WritableBinaryStream &MsfBuffer, + const msf::MSFLayout &Layout); + void commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer, + const msf::MSFLayout &Layout); + + BumpPtrAllocator &Allocator; + + std::unique_ptr<msf::MSFBuilder> Msf; + std::unique_ptr<InfoStreamBuilder> Info; + std::unique_ptr<DbiStreamBuilder> Dbi; + std::unique_ptr<GSIStreamBuilder> Gsi; + std::unique_ptr<TpiStreamBuilder> Tpi; + std::unique_ptr<TpiStreamBuilder> Ipi; + + PDBStringTableBuilder Strings; + StringTableHashTraits InjectedSourceHashTraits; + HashTable<SrcHeaderBlockEntry, StringTableHashTraits> InjectedSourceTable; + + SmallVector<InjectedSourceDescriptor, 2> InjectedSources; + + NamedStreamMap NamedStreams; + DenseMap<uint32_t, std::string> NamedStreamData; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h new file mode 100644 index 00000000..57f0b64a --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h @@ -0,0 +1,64 @@ +//===- PDBStringTable.h - PDB 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_PDB_RAW_PDBSTRINGTABLE_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBSTRINGTABLE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { +class BinaryStreamReader; + +namespace msf { +class MappedBlockStream; +} + +namespace pdb { + +struct PDBStringTableHeader; + +class PDBStringTable { +public: + Error reload(BinaryStreamReader &Reader); + + uint32_t getByteSize() const; + uint32_t getNameCount() const; + uint32_t getHashVersion() const; + uint32_t getSignature() const; + + Expected<StringRef> getStringForID(uint32_t ID) const; + Expected<uint32_t> getIDForString(StringRef Str) const; + + FixedStreamArray<support::ulittle32_t> name_ids() const; + + const codeview::DebugStringTableSubsectionRef &getStringTable() const; + +private: + Error readHeader(BinaryStreamReader &Reader); + Error readStrings(BinaryStreamReader &Reader); + Error readHashTable(BinaryStreamReader &Reader); + Error readEpilogue(BinaryStreamReader &Reader); + + const PDBStringTableHeader *Header = nullptr; + codeview::DebugStringTableSubsectionRef Strings; + FixedStreamArray<support::ulittle32_t> IDs; + uint32_t NameCount = 0; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_STRINGTABLE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h new file mode 100644 index 00000000..57267ef5 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h @@ -0,0 +1,71 @@ +//===- PDBStringTableBuilder.h - PDB String Table Builder -------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file creates the "/names" stream. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSTRINGTABLEBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBSTRINGTABLEBUILDER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/Support/Error.h" +#include <vector> + +namespace llvm { +class BinaryStreamWriter; +class WritableBinaryStreamRef; + +namespace msf { +struct MSFLayout; +} + +namespace pdb { + +class PDBFileBuilder; +class PDBStringTableBuilder; + +struct StringTableHashTraits { + PDBStringTableBuilder *Table; + + explicit StringTableHashTraits(PDBStringTableBuilder &Table); + uint32_t hashLookupKey(StringRef S) const; + StringRef storageKeyToLookupKey(uint32_t Offset) const; + uint32_t lookupKeyToStorageKey(StringRef S); +}; + +class PDBStringTableBuilder { +public: + // If string S does not exist in the string table, insert it. + // Returns the ID for S. + uint32_t insert(StringRef S); + + uint32_t getIdForString(StringRef S) const; + StringRef getStringForId(uint32_t Id) const; + + uint32_t calculateSerializedSize() const; + Error commit(BinaryStreamWriter &Writer) const; + + void setStrings(const codeview::DebugStringTableSubsection &Strings); + +private: + uint32_t calculateHashTableSize() const; + Error writeHeader(BinaryStreamWriter &Writer) const; + Error writeStrings(BinaryStreamWriter &Writer) const; + Error writeHashTable(BinaryStreamWriter &Writer) const; + Error writeEpilogue(BinaryStreamWriter &Writer) const; + + codeview::DebugStringTableSubsection Strings; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_PDBSTRINGTABLEBUILDER_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/PublicsStream.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PublicsStream.h new file mode 100644 index 00000000..ee28d108 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/PublicsStream.h @@ -0,0 +1,59 @@ +//===- PublicsStream.h - PDB Public Symbol Stream -------- ------*- 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_RAW_PUBLICSSTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class DbiStream; +struct GSIHashHeader; +class PDBFile; + +class PublicsStream { +public: + PublicsStream(std::unique_ptr<msf::MappedBlockStream> Stream); + ~PublicsStream(); + Error reload(); + + uint32_t getSymHash() const; + uint16_t getThunkTableSection() const; + uint32_t getThunkTableOffset() const; + const GSIHashTable &getPublicsTable() const { return PublicsTable; } + FixedStreamArray<support::ulittle32_t> getAddressMap() const { + return AddressMap; + } + FixedStreamArray<support::ulittle32_t> getThunkMap() const { + return ThunkMap; + } + FixedStreamArray<SectionOffset> getSectionOffsets() const { + return SectionOffsets; + } + +private: + std::unique_ptr<msf::MappedBlockStream> Stream; + GSIHashTable PublicsTable; + FixedStreamArray<support::ulittle32_t> AddressMap; + FixedStreamArray<support::ulittle32_t> ThunkMap; + FixedStreamArray<SectionOffset> SectionOffsets; + + const PublicsStreamHeader *Header; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/RawConstants.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/RawConstants.h new file mode 100644 index 00000000..0dde5ef6 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/RawConstants.h @@ -0,0 +1,118 @@ +//===- RawConstants.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_PDB_RAW_PDBRAWCONSTANTS_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H + +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include <cstdint> + +namespace llvm { +namespace pdb { + +const uint16_t kInvalidStreamIndex = 0xFFFF; + +enum PdbRaw_ImplVer : uint32_t { + PdbImplVC2 = 19941610, + PdbImplVC4 = 19950623, + PdbImplVC41 = 19950814, + PdbImplVC50 = 19960307, + PdbImplVC98 = 19970604, + PdbImplVC70Dep = 19990604, // deprecated + PdbImplVC70 = 20000404, + PdbImplVC80 = 20030901, + PdbImplVC110 = 20091201, + PdbImplVC140 = 20140508, +}; + +enum class PdbRaw_SrcHeaderBlockVer : uint32_t { SrcVerOne = 19980827 }; + +enum class PdbRaw_FeatureSig : uint32_t { + VC110 = PdbImplVC110, + VC140 = PdbImplVC140, + NoTypeMerge = 0x4D544F4E, + MinimalDebugInfo = 0x494E494D, +}; + +enum PdbRaw_Features : uint32_t { + PdbFeatureNone = 0x0, + PdbFeatureContainsIdStream = 0x1, + PdbFeatureMinimalDebugInfo = 0x2, + PdbFeatureNoTypeMerging = 0x4, + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ PdbFeatureNoTypeMerging) +}; + +enum PdbRaw_DbiVer : uint32_t { + PdbDbiVC41 = 930803, + PdbDbiV50 = 19960307, + PdbDbiV60 = 19970606, + PdbDbiV70 = 19990903, + PdbDbiV110 = 20091201 +}; + +enum PdbRaw_TpiVer : uint32_t { + PdbTpiV40 = 19950410, + PdbTpiV41 = 19951122, + PdbTpiV50 = 19961031, + PdbTpiV70 = 19990903, + PdbTpiV80 = 20040203, +}; + +enum PdbRaw_DbiSecContribVer : uint32_t { + DbiSecContribVer60 = 0xeffe0000 + 19970605, + DbiSecContribV2 = 0xeffe0000 + 20140516 +}; + +enum SpecialStream : uint32_t { + // Stream 0 contains the copy of previous version of the MSF directory. + // We are not currently using it, but technically if we find the main + // MSF is corrupted, we could fallback to it. + OldMSFDirectory = 0, + + StreamPDB = 1, + StreamTPI = 2, + StreamDBI = 3, + StreamIPI = 4, + + kSpecialStreamCount +}; + +enum class DbgHeaderType : uint16_t { + FPO, + Exception, + Fixup, + OmapToSrc, + OmapFromSrc, + SectionHdr, + TokenRidMap, + Xdata, + Pdata, + NewFPO, + SectionHdrOrig, + Max +}; + +enum class OMFSegDescFlags : uint16_t { + None = 0, + Read = 1 << 0, // Segment is readable. + Write = 1 << 1, // Segment is writable. + Execute = 1 << 2, // Segment is executable. + AddressIs32Bit = 1 << 3, // Descriptor describes a 32-bit linear address. + IsSelector = 1 << 8, // Frame represents a selector. + IsAbsoluteAddress = 1 << 9, // Frame represents an absolute address. + IsGroup = 1 << 10, // If set, descriptor represents a group. + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IsGroup) +}; + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/RawError.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/RawError.h new file mode 100644 index 00000000..aadb64c2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/RawError.h @@ -0,0 +1,58 @@ +//===- RawError.h - Error extensions for raw PDB implementation -*- 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_RAW_RAWERROR_H +#define LLVM_DEBUGINFO_PDB_RAW_RAWERROR_H + +#include "llvm/Support/Error.h" + +#include <string> + +namespace llvm { +namespace pdb { +enum class raw_error_code { + unspecified = 1, + feature_unsupported, + invalid_format, + corrupt_file, + insufficient_buffer, + no_stream, + index_out_of_bounds, + invalid_block_address, + duplicate_entry, + no_entry, + not_writable, + stream_too_long, + invalid_tpi_hash, +}; +} // namespace pdb +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum<llvm::pdb::raw_error_code> : std::true_type {}; +} // namespace std + +namespace llvm { +namespace pdb { +const std::error_category &RawErrCategory(); + +inline std::error_code make_error_code(raw_error_code E) { + return std::error_code(static_cast<int>(E), RawErrCategory()); +} + +/// Base class for errors originating when parsing raw PDB files +class RawError : public ErrorInfo<RawError, StringError> { +public: + using ErrorInfo<RawError, StringError>::ErrorInfo; // inherit constructors + RawError(const Twine &S) : ErrorInfo(S, raw_error_code::unspecified) {} + static char ID; +}; +} // namespace pdb +} // namespace llvm +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/RawTypes.h new file mode 100644 index 00000000..84b0cb39 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -0,0 +1,350 @@ +//===- RawTypes.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_PDB_RAW_RAWTYPES_H +#define LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H + +#include "llvm/DebugInfo/CodeView/GUID.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace pdb { +// This struct is defined as "SO" in langapi/include/pdb.h. +struct SectionOffset { + support::ulittle32_t Off; + support::ulittle16_t Isect; + char Padding[2]; +}; + +/// Header of the hash tables found in the globals and publics sections. +/// Based on GSIHashHdr in +/// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h +struct GSIHashHeader { + enum : unsigned { + HdrSignature = ~0U, + HdrVersion = 0xeffe0000 + 19990810, + }; + support::ulittle32_t VerSignature; + support::ulittle32_t VerHdr; + support::ulittle32_t HrSize; + support::ulittle32_t NumBuckets; +}; + +// This is HRFile. +struct PSHashRecord { + support::ulittle32_t Off; // Offset in the symbol record stream + support::ulittle32_t CRef; +}; + +// This struct is defined as `SC` in include/dbicommon.h +struct SectionContrib { + support::ulittle16_t ISect; + char Padding[2]; + support::little32_t Off; + support::little32_t Size; + support::ulittle32_t Characteristics; + support::ulittle16_t Imod; + char Padding2[2]; + support::ulittle32_t DataCrc; + support::ulittle32_t RelocCrc; +}; + +// This struct is defined as `SC2` in include/dbicommon.h +struct SectionContrib2 { + // To guarantee SectionContrib2 is standard layout, we cannot use inheritance. + SectionContrib Base; + support::ulittle32_t ISectCoff; +}; + +// This corresponds to the `OMFSegMap` structure. +struct SecMapHeader { + support::ulittle16_t SecCount; // Number of segment descriptors in table + support::ulittle16_t SecCountLog; // Number of logical segment descriptors +}; + +// This corresponds to the `OMFSegMapDesc` structure. The definition is not +// present in the reference implementation, but the layout is derived from +// code that accesses the fields. +struct SecMapEntry { + support::ulittle16_t Flags; // Descriptor flags. See OMFSegDescFlags + support::ulittle16_t Ovl; // Logical overlay number. + support::ulittle16_t Group; // Group index into descriptor array. + support::ulittle16_t Frame; + support::ulittle16_t SecName; // Byte index of the segment or group name + // in the sstSegName table, or 0xFFFF. + support::ulittle16_t ClassName; // Byte index of the class name in the + // sstSegName table, or 0xFFFF. + support::ulittle32_t Offset; // Byte offset of the logical segment + // within the specified physical segment. + // If group is set in flags, offset is the + // offset of the group. + support::ulittle32_t SecByteLength; // Byte count of the segment or group. +}; + +/// Some of the values are stored in bitfields. Since this needs to be portable +/// across compilers and architectures (big / little endian in particular) we +/// can't use the actual structures below, but must instead do the shifting +/// and masking ourselves. The struct definitions are provided for reference. +struct DbiFlags { + /// uint16_t IncrementalLinking : 1; // True if linked incrementally + /// uint16_t IsStripped : 1; // True if private symbols were + /// stripped. + /// uint16_t HasCTypes : 1; // True if linked with /debug:ctypes. + /// uint16_t Reserved : 13; + static const uint16_t FlagIncrementalMask = 0x0001; + static const uint16_t FlagStrippedMask = 0x0002; + static const uint16_t FlagHasCTypesMask = 0x0004; +}; + +struct DbiBuildNo { + /// uint16_t MinorVersion : 8; + /// uint16_t MajorVersion : 7; + /// uint16_t NewVersionFormat : 1; + static const uint16_t BuildMinorMask = 0x00FF; + static const uint16_t BuildMinorShift = 0; + + static const uint16_t BuildMajorMask = 0x7F00; + static const uint16_t BuildMajorShift = 8; + + static const uint16_t NewVersionFormatMask = 0x8000; +}; + +/// The fixed size header that appears at the beginning of the DBI Stream. +struct DbiStreamHeader { + support::little32_t VersionSignature; + support::ulittle32_t VersionHeader; + + /// How "old" is this DBI Stream. Should match the age of the PDB InfoStream. + support::ulittle32_t Age; + + /// Global symbol stream # + support::ulittle16_t GlobalSymbolStreamIndex; + + /// See DbiBuildNo structure. + support::ulittle16_t BuildNumber; + + /// Public symbols stream # + support::ulittle16_t PublicSymbolStreamIndex; + + /// version of mspdbNNN.dll + support::ulittle16_t PdbDllVersion; + + /// Symbol records stream # + support::ulittle16_t SymRecordStreamIndex; + + /// rbld number of mspdbNNN.dll + support::ulittle16_t PdbDllRbld; + + /// Size of module info stream + support::little32_t ModiSubstreamSize; + + /// Size of sec. contrib stream + support::little32_t SecContrSubstreamSize; + + /// Size of sec. map substream + support::little32_t SectionMapSize; + + /// Size of file info substream + support::little32_t FileInfoSize; + + /// Size of type server map + support::little32_t TypeServerSize; + + /// Index of MFC Type Server + support::ulittle32_t MFCTypeServerIndex; + + /// Size of DbgHeader info + support::little32_t OptionalDbgHdrSize; + + /// Size of EC stream (what is EC?) + support::little32_t ECSubstreamSize; + + /// See DbiFlags enum. + support::ulittle16_t Flags; + + /// See PDB_MachineType enum. + support::ulittle16_t MachineType; + + /// Pad to 64 bytes + support::ulittle32_t Reserved; +}; +static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!"); + +/// The header preceeding the File Info Substream of the DBI stream. +struct FileInfoSubstreamHeader { + /// Total # of modules, should match number of records in the ModuleInfo + /// substream. + support::ulittle16_t NumModules; + + /// Total # of source files. This value is not accurate because PDB actually + /// supports more than 64k source files, so we ignore it and compute the value + /// from other stream fields. + support::ulittle16_t NumSourceFiles; + + /// Following this header the File Info Substream is laid out as follows: + /// ulittle16_t ModIndices[NumModules]; + /// ulittle16_t ModFileCounts[NumModules]; + /// ulittle32_t FileNameOffsets[NumSourceFiles]; + /// char Names[][NumSourceFiles]; + /// with the caveat that `NumSourceFiles` cannot be trusted, so + /// it is computed by summing the `ModFileCounts` array. +}; + +struct ModInfoFlags { + /// uint16_t fWritten : 1; // True if DbiModuleDescriptor is dirty + /// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?) + /// uint16_t unused : 6; // Reserved + /// uint16_t iTSM : 8; // Type Server Index for this module + static const uint16_t HasECFlagMask = 0x2; + + static const uint16_t TypeServerIndexMask = 0xFF00; + static const uint16_t TypeServerIndexShift = 8; +}; + +/// The header preceeding each entry in the Module Info substream of the DBI +/// stream. Corresponds to the type MODI in the reference implementation. +struct ModuleInfoHeader { + /// Currently opened module. This field is a pointer in the reference + /// implementation, but that won't work on 64-bit systems, and anyway it + /// doesn't make sense to read a pointer from a file. For now it is unused, + /// so just ignore it. + support::ulittle32_t Mod; + + /// First section contribution of this module. + SectionContrib SC; + + /// See ModInfoFlags definition. + support::ulittle16_t Flags; + + /// Stream Number of module debug info + support::ulittle16_t ModDiStream; + + /// Size of local symbol debug info in above stream + support::ulittle32_t SymBytes; + + /// Size of C11 line number info in above stream + support::ulittle32_t C11Bytes; + + /// Size of C13 line number info in above stream + support::ulittle32_t C13Bytes; + + /// Number of files contributing to this module + support::ulittle16_t NumFiles; + + /// Padding so the next field is 4-byte aligned. + char Padding1[2]; + + /// Array of [0..NumFiles) DBI name buffer offsets. In the reference + /// implementation this field is a pointer. But since you can't portably + /// serialize a pointer, on 64-bit platforms they copy all the values except + /// this one into the 32-bit version of the struct and use that for + /// serialization. Regardless, this field is unused, it is only there to + /// store a pointer that can be accessed at runtime. + support::ulittle32_t FileNameOffs; + + /// Name Index for src file name + support::ulittle32_t SrcFileNameNI; + + /// Name Index for path to compiler PDB + support::ulittle32_t PdbFilePathNI; + + /// Following this header are two zero terminated strings. + /// char ModuleName[]; + /// char ObjFileName[]; +}; + +// This is PSGSIHDR struct defined in +// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h +struct PublicsStreamHeader { + support::ulittle32_t SymHash; + support::ulittle32_t AddrMap; + support::ulittle32_t NumThunks; + support::ulittle32_t SizeOfThunk; + support::ulittle16_t ISectThunkTable; + char Padding[2]; + support::ulittle32_t OffThunkTable; + support::ulittle32_t NumSections; +}; + +// The header preceeding the global TPI stream. +// This corresponds to `HDR` in PDB/dbi/tpi.h. +struct TpiStreamHeader { + struct EmbeddedBuf { + support::little32_t Off; + support::ulittle32_t Length; + }; + + support::ulittle32_t Version; + support::ulittle32_t HeaderSize; + support::ulittle32_t TypeIndexBegin; + support::ulittle32_t TypeIndexEnd; + support::ulittle32_t TypeRecordBytes; + + // The following members correspond to `TpiHash` in PDB/dbi/tpi.h. + support::ulittle16_t HashStreamIndex; + support::ulittle16_t HashAuxStreamIndex; + support::ulittle32_t HashKeySize; + support::ulittle32_t NumHashBuckets; + + EmbeddedBuf HashValueBuffer; + EmbeddedBuf IndexOffsetBuffer; + EmbeddedBuf HashAdjBuffer; +}; + +const uint32_t MinTpiHashBuckets = 0x1000; +const uint32_t MaxTpiHashBuckets = 0x40000; + +/// The header preceeding the global PDB Stream (Stream 1) +struct InfoStreamHeader { + support::ulittle32_t Version; + support::ulittle32_t Signature; + support::ulittle32_t Age; + codeview::GUID Guid; +}; + +/// The header preceeding the /names stream. +struct PDBStringTableHeader { + support::ulittle32_t Signature; // PDBStringTableSignature + support::ulittle32_t HashVersion; // 1 or 2 + support::ulittle32_t ByteSize; // Number of bytes of names buffer. +}; + +const uint32_t PDBStringTableSignature = 0xEFFEEFFE; + +/// The header preceding the /src/headerblock stream. +struct SrcHeaderBlockHeader { + support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration. + support::ulittle32_t Size; // Size of entire stream. + uint64_t FileTime; // Time stamp (Windows FILETIME format). + support::ulittle32_t Age; // Age + uint8_t Padding[44]; // Pad to 64 bytes. +}; +static_assert(sizeof(SrcHeaderBlockHeader) == 64, "Incorrect struct size!"); + +/// A single file record entry within the /src/headerblock stream. +struct SrcHeaderBlockEntry { + support::ulittle32_t Size; // Record Length. + support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration. + support::ulittle32_t CRC; // CRC of the original file contents. + support::ulittle32_t FileSize; // Size of original source file. + support::ulittle32_t FileNI; // String table index of file name. + support::ulittle32_t ObjNI; // String table index of object name. + support::ulittle32_t VFileNI; // String table index of virtual file name. + uint8_t Compression; // PDB_SourceCompression enumeration. + uint8_t IsVirtual; // Is this a virtual file (injected)? + short Padding; // Pad to 4 bytes. + char Reserved[8]; +}; + +static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!"); + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/SymbolCache.h new file mode 100644 index 00000000..0b15ab47 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -0,0 +1,147 @@ +//==- SymbolCache.h - Cache of native symbols and ids ------------*- 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_NATIVE_SYMBOLCACHE_H +#define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/Support/Allocator.h" + +#include <memory> +#include <vector> + +namespace llvm { +namespace pdb { +class DbiStream; +class PDBFile; + +class SymbolCache { + NativeSession &Session; + DbiStream *Dbi = nullptr; + + /// Cache of all stable symbols, indexed by SymIndexId. Just because a + /// symbol has been parsed does not imply that it will be stable and have + /// an Id. Id allocation is an implementation, with the only guarantee + /// being that once an Id is allocated, the symbol can be assumed to be + /// cached. + std::vector<std::unique_ptr<NativeRawSymbol>> Cache; + + /// For type records from the TPI stream which have been paresd and cached, + /// stores a mapping to SymIndexId of the cached symbol. + DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId; + + /// For field list members which have been parsed and cached, stores a mapping + /// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the + /// cached symbol. + DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId> + FieldListMembersToSymbolId; + + /// List of SymIndexIds for each compiland, indexed by compiland index as they + /// appear in the PDB file. + std::vector<SymIndexId> Compilands; + + /// Map from global symbol offset to SymIndexId. + DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId; + + SymIndexId createSymbolPlaceholder() { + SymIndexId Id = Cache.size(); + Cache.push_back(nullptr); + return Id; + } + + template <typename ConcreteSymbolT, typename CVRecordT, typename... Args> + SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT, + Args &&... ConstructorArgs) { + CVRecordT Record; + if (auto EC = + codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) { + consumeError(std::move(EC)); + return 0; + } + + return createSymbol<ConcreteSymbolT>( + TI, std::move(Record), std::forward<Args>(ConstructorArgs)...); + } + + SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI, + codeview::CVType CVT); + + SymIndexId createSimpleType(codeview::TypeIndex TI, + codeview::ModifierOptions Mods); + +public: + SymbolCache(NativeSession &Session, DbiStream *Dbi); + + template <typename ConcreteSymbolT, typename... Args> + SymIndexId createSymbol(Args &&... ConstructorArgs) { + SymIndexId Id = Cache.size(); + + // Initial construction must not access the cache, since it must be done + // atomically. + auto Result = llvm::make_unique<ConcreteSymbolT>( + Session, Id, std::forward<Args>(ConstructorArgs)...); + Result->SymbolId = Id; + + NativeRawSymbol *NRS = static_cast<NativeRawSymbol *>(Result.get()); + Cache.push_back(std::move(Result)); + + // After the item is in the cache, we can do further initialization which + // is then allowed to access the cache. + NRS->initialize(); + return Id; + } + + std::unique_ptr<IPDBEnumSymbols> + createTypeEnumerator(codeview::TypeLeafKind Kind); + + std::unique_ptr<IPDBEnumSymbols> + createTypeEnumerator(std::vector<codeview::TypeLeafKind> Kinds); + + std::unique_ptr<IPDBEnumSymbols> + createGlobalsEnumerator(codeview::SymbolKind Kind); + + SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); + + template <typename ConcreteSymbolT, typename... Args> + SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI, + uint32_t Index, + Args &&... ConstructorArgs) { + SymIndexId SymId = Cache.size(); + std::pair<codeview::TypeIndex, uint32_t> Key{FieldListTI, Index}; + auto Result = FieldListMembersToSymbolId.try_emplace(Key, SymId); + if (Result.second) + SymId = + createSymbol<ConcreteSymbolT>(std::forward<Args>(ConstructorArgs)...); + else + SymId = Result.first->second; + return SymId; + } + + SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset); + + std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index); + uint32_t getNumCompilands() const; + + std::unique_ptr<PDBSymbol> getSymbolById(SymIndexId SymbolId) const; + + NativeRawSymbol &getNativeSymbolById(SymIndexId SymbolId) const; + + template <typename ConcreteT> + ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const { + return static_cast<ConcreteT &>(getNativeSymbolById(SymbolId)); + } +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/SymbolStream.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/SymbolStream.h new file mode 100644 index 00000000..4fe1bd97 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/SymbolStream.h @@ -0,0 +1,47 @@ +//===- SymbolStream.cpp - PDB Symbol Stream Access --------------*- 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_RAW_PDBSYMBOLSTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" + +#include "llvm/Support/Error.h" + +namespace llvm { +namespace msf { +class MappedBlockStream; +} +namespace pdb { +class PDBFile; + +class SymbolStream { +public: + SymbolStream(std::unique_ptr<msf::MappedBlockStream> Stream); + ~SymbolStream(); + Error reload(); + + const codeview::CVSymbolArray &getSymbolArray() const { + return SymbolRecords; + } + + codeview::CVSymbol readRecord(uint32_t Offset) const; + + iterator_range<codeview::CVSymbolArray::Iterator> + getSymbols(bool *HadError) const; + + Error commit(); + +private: + codeview::CVSymbolArray SymbolRecords; + std::unique_ptr<msf::MappedBlockStream> Stream; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/TpiHashing.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/TpiHashing.h new file mode 100644 index 00000000..4ac60a80 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/TpiHashing.h @@ -0,0 +1,71 @@ +//===- TpiHashing.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_PDB_TPIHASHING_H +#define LLVM_DEBUGINFO_PDB_TPIHASHING_H + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { + +Expected<uint32_t> hashTypeRecord(const llvm::codeview::CVType &Type); + +struct TagRecordHash { + explicit TagRecordHash(codeview::ClassRecord CR, uint32_t Full, + uint32_t Forward) + : FullRecordHash(Full), ForwardDeclHash(Forward), Class(std::move(CR)) { + State = 0; + } + + explicit TagRecordHash(codeview::EnumRecord ER, uint32_t Full, + uint32_t Forward) + : FullRecordHash(Full), ForwardDeclHash(Forward), Enum(std::move(ER)) { + State = 1; + } + + explicit TagRecordHash(codeview::UnionRecord UR, uint32_t Full, + uint32_t Forward) + : FullRecordHash(Full), ForwardDeclHash(Forward), Union(std::move(UR)) { + State = 2; + } + + uint32_t FullRecordHash; + uint32_t ForwardDeclHash; + + codeview::TagRecord &getRecord() { + switch (State) { + case 0: + return Class; + case 1: + return Enum; + case 2: + return Union; + } + llvm_unreachable("unreachable!"); + } + +private: + union { + codeview::ClassRecord Class; + codeview::EnumRecord Enum; + codeview::UnionRecord Union; + }; + + uint8_t State = 0; +}; + +/// Given a CVType referring to a class, structure, union, or enum, compute +/// the hash of its forward decl and full decl. +Expected<TagRecordHash> hashTagRecord(const codeview::CVType &Type); + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_TPIHASHING_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/TpiStream.h new file mode 100644 index 00000000..1b7fd2d5 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/TpiStream.h @@ -0,0 +1,97 @@ +//===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ------*- 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_RAW_PDBTPISTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/HashTable.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/raw_ostream.h" + +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class LazyRandomTypeCollection; +} +namespace msf { +class MappedBlockStream; +} +namespace pdb { +class PDBFile; + +class TpiStream { + friend class TpiStreamBuilder; + +public: + TpiStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream); + ~TpiStream(); + Error reload(); + + PdbRaw_TpiVer getTpiVersion() const; + + uint32_t TypeIndexBegin() const; + uint32_t TypeIndexEnd() const; + uint32_t getNumTypeRecords() const; + uint16_t getTypeHashStreamIndex() const; + uint16_t getTypeHashStreamAuxIndex() const; + + uint32_t getHashKeySize() const; + uint32_t getNumHashBuckets() const; + FixedStreamArray<support::ulittle32_t> getHashValues() const; + FixedStreamArray<codeview::TypeIndexOffset> getTypeIndexOffsets() const; + HashTable<support::ulittle32_t> &getHashAdjusters(); + + codeview::CVTypeRange types(bool *HadError) const; + const codeview::CVTypeArray &typeArray() const { return TypeRecords; } + + codeview::LazyRandomTypeCollection &typeCollection() { return *Types; } + + Expected<codeview::TypeIndex> + findFullDeclForForwardRef(codeview::TypeIndex ForwardRefTI) const; + + std::vector<codeview::TypeIndex> findRecordsByName(StringRef Name) const; + + codeview::CVType getType(codeview::TypeIndex Index); + + BinarySubstreamRef getTypeRecordsSubstream() const; + + Error commit(); + + void buildHashMap(); + + bool supportsTypeLookup() const; + +private: + PDBFile &Pdb; + std::unique_ptr<msf::MappedBlockStream> Stream; + + std::unique_ptr<codeview::LazyRandomTypeCollection> Types; + + BinarySubstreamRef TypeRecordsSubstream; + + codeview::CVTypeArray TypeRecords; + + std::unique_ptr<BinaryStream> HashStream; + FixedStreamArray<support::ulittle32_t> HashValues; + FixedStreamArray<codeview::TypeIndexOffset> TypeIndexOffsets; + HashTable<support::ulittle32_t> HashAdjusters; + + std::vector<std::vector<codeview::TypeIndex>> HashMap; + + const TpiStreamHeader *Header; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h b/clang-r353983/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h new file mode 100644 index 00000000..72d98e9c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h @@ -0,0 +1,89 @@ +//===- TpiStreamBuilder.h - PDB Tpi Stream Creation -------------*- 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_RAW_PDBTPISTREAMBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAMBUILDER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryItemStream.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" + +#include <vector> + +namespace llvm { +class BinaryByteStream; +class WritableBinaryStreamRef; + +template <> struct BinaryItemTraits<llvm::codeview::CVType> { + static size_t length(const codeview::CVType &Item) { return Item.length(); } + static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) { + return Item.data(); + } +}; + +namespace codeview { +class TypeRecord; +} +namespace msf { +class MSFBuilder; +struct MSFLayout; +} +namespace pdb { +class PDBFile; +class TpiStream; +struct TpiStreamHeader; + +class TpiStreamBuilder { +public: + explicit TpiStreamBuilder(msf::MSFBuilder &Msf, uint32_t StreamIdx); + ~TpiStreamBuilder(); + + TpiStreamBuilder(const TpiStreamBuilder &) = delete; + TpiStreamBuilder &operator=(const TpiStreamBuilder &) = delete; + + void setVersionHeader(PdbRaw_TpiVer Version); + void addTypeRecord(ArrayRef<uint8_t> Type, Optional<uint32_t> Hash); + + Error finalizeMsfLayout(); + + uint32_t getRecordCount() const { return TypeRecords.size(); } + + Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer); + + uint32_t calculateSerializedLength(); + +private: + uint32_t calculateHashBufferSize() const; + uint32_t calculateIndexOffsetSize() const; + Error finalize(); + + msf::MSFBuilder &Msf; + BumpPtrAllocator &Allocator; + + size_t TypeRecordBytes = 0; + + PdbRaw_TpiVer VerHeader = PdbRaw_TpiVer::PdbTpiV80; + std::vector<ArrayRef<uint8_t>> TypeRecords; + std::vector<uint32_t> TypeHashes; + std::vector<codeview::TypeIndexOffset> TypeIndexOffsets; + uint32_t HashStreamIndex = kInvalidStreamIndex; + std::unique_ptr<BinaryByteStream> HashValueStream; + + const TpiStreamHeader *Header; + uint32_t Idx; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDB.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDB.h new file mode 100644 index 00000000..6d734dc2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDB.h @@ -0,0 +1,31 @@ +//===- PDB.h - base header file for creating a PDB reader -------*- 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_PDB_H +#define LLVM_DEBUGINFO_PDB_PDB_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/Error.h" +#include <memory> + +namespace llvm { +namespace pdb { + +class IPDBSession; + +Error loadDataForPDB(PDB_ReaderType Type, StringRef Path, + std::unique_ptr<IPDBSession> &Session); + +Error loadDataForEXE(PDB_ReaderType Type, StringRef Path, + std::unique_ptr<IPDBSession> &Session); + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDB_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBContext.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBContext.h new file mode 100644 index 00000000..e404e07f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBContext.h @@ -0,0 +1,64 @@ +//===-- PDBContext.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_PDB_PDBCONTEXT_H +#define LLVM_DEBUGINFO_PDB_PDBCONTEXT_H + +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include <cstdint> +#include <memory> +#include <string> + +namespace llvm { + +namespace object { +class COFFObjectFile; +} // end namespace object + +namespace pdb { + + /// PDBContext + /// This data structure is the top level entity that deals with PDB debug + /// information parsing. This data structure exists only when there is a + /// need for a transparent interface to different debug information formats + /// (e.g. PDB and DWARF). More control and power over the debug information + /// access can be had by using the PDB interfaces directly. + class PDBContext : public DIContext { + public: + PDBContext(const object::COFFObjectFile &Object, + std::unique_ptr<IPDBSession> PDBSession); + PDBContext(PDBContext &) = delete; + PDBContext &operator=(PDBContext &) = delete; + + static bool classof(const DIContext *DICtx) { + return DICtx->getKind() == CK_PDB; + } + + void dump(raw_ostream &OS, DIDumpOptions DIDumpOpts) override; + + DILineInfo getLineInfoForAddress( + uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange( + uint64_t Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress( + uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + + private: + std::string getFunctionName(uint64_t Address, DINameKind NameKind) const; + std::unique_ptr<IPDBSession> Session; + }; + +} // end namespace pdb + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBCONTEXT_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBExtras.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBExtras.h new file mode 100644 index 00000000..b9a8d8f6 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -0,0 +1,59 @@ +//===- PDBExtras.h - helper functions and classes for PDBs ------*- 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_PDBEXTRAS_H +#define LLVM_DEBUGINFO_PDB_PDBEXTRAS_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/raw_ostream.h" + +#include <unordered_map> + +namespace llvm { + +class raw_ostream; + +namespace pdb { + +using TagStats = std::unordered_map<PDB_SymType, int>; + +raw_ostream &operator<<(raw_ostream &OS, const PDB_VariantType &Value); +raw_ostream &operator<<(raw_ostream &OS, const PDB_CallingConv &Conv); +raw_ostream &operator<<(raw_ostream &OS, const PDB_BuiltinType &Type); +raw_ostream &operator<<(raw_ostream &OS, const PDB_DataKind &Data); +raw_ostream &operator<<(raw_ostream &OS, const codeview::RegisterId &Reg); +raw_ostream &operator<<(raw_ostream &OS, const PDB_LocType &Loc); +raw_ostream &operator<<(raw_ostream &OS, const codeview::ThunkOrdinal &Thunk); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang); +raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag); +raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access); +raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Machine &Machine); +raw_ostream &operator<<(raw_ostream &OS, + const PDB_SourceCompression &Compression); + +raw_ostream &operator<<(raw_ostream &OS, const Variant &Value); +raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version); +raw_ostream &operator<<(raw_ostream &OS, const TagStats &Stats); + + +template <typename T> +void dumpSymbolField(raw_ostream &OS, StringRef Name, T Value, int Indent) { + OS << "\n"; + OS.indent(Indent); + OS << Name << ": " << Value; +} + + +} // end namespace pdb + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBEXTRAS_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymDumper.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymDumper.h new file mode 100644 index 00000000..f81b15f2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymDumper.h @@ -0,0 +1,78 @@ +//===- PDBSymDumper.h - base interface for PDB symbol 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_PDB_PDBSYMDUMPER_H +#define LLVM_DEBUGINFO_PDB_PDBSYMDUMPER_H + +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymDumper { +public: + PDBSymDumper(bool ShouldRequireImpl); + virtual ~PDBSymDumper(); + + virtual void dump(const PDBSymbolAnnotation &Symbol); + virtual void dump(const PDBSymbolBlock &Symbol); + virtual void dump(const PDBSymbolCompiland &Symbol); + virtual void dump(const PDBSymbolCompilandDetails &Symbol); + virtual void dump(const PDBSymbolCompilandEnv &Symbol); + virtual void dump(const PDBSymbolCustom &Symbol); + virtual void dump(const PDBSymbolData &Symbol); + virtual void dump(const PDBSymbolExe &Symbol); + virtual void dump(const PDBSymbolFunc &Symbol); + virtual void dump(const PDBSymbolFuncDebugEnd &Symbol); + virtual void dump(const PDBSymbolFuncDebugStart &Symbol); + virtual void dump(const PDBSymbolLabel &Symbol); + virtual void dump(const PDBSymbolPublicSymbol &Symbol); + virtual void dump(const PDBSymbolThunk &Symbol); + virtual void dump(const PDBSymbolTypeArray &Symbol); + virtual void dump(const PDBSymbolTypeBaseClass &Symbol); + virtual void dump(const PDBSymbolTypeBuiltin &Symbol); + virtual void dump(const PDBSymbolTypeCustom &Symbol); + virtual void dump(const PDBSymbolTypeDimension &Symbol); + virtual void dump(const PDBSymbolTypeEnum &Symbol); + virtual void dump(const PDBSymbolTypeFriend &Symbol); + virtual void dump(const PDBSymbolTypeFunctionArg &Symbol); + virtual void dump(const PDBSymbolTypeFunctionSig &Symbol); + virtual void dump(const PDBSymbolTypeManaged &Symbol); + virtual void dump(const PDBSymbolTypePointer &Symbol); + virtual void dump(const PDBSymbolTypeTypedef &Symbol); + virtual void dump(const PDBSymbolTypeUDT &Symbol); + virtual void dump(const PDBSymbolTypeVTable &Symbol); + virtual void dump(const PDBSymbolTypeVTableShape &Symbol); + virtual void dump(const PDBSymbolUnknown &Symbol); + virtual void dump(const PDBSymbolUsingNamespace &Symbol); + + virtual void dumpRight(const PDBSymbolTypeArray &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeBaseClass &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeBuiltin &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeCustom &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeDimension &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeEnum &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeFriend &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeFunctionArg &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeFunctionSig &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeManaged &Symbol) {} + virtual void dumpRight(const PDBSymbolTypePointer &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeTypedef &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeUDT &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeVTable &Symbol) {} + virtual void dumpRight(const PDBSymbolTypeVTableShape &Symbol) {} + +private: + bool RequireImpl; +}; +} +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbol.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbol.h new file mode 100644 index 00000000..d9004a88 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -0,0 +1,171 @@ +//===- PDBSymbol.h - base class for user-facing symbol 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOL_H + +#include "ConcreteSymbolEnumerator.h" +#include "IPDBRawSymbol.h" +#include "PDBExtras.h" +#include "PDBTypes.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Casting.h" + +#define FORWARD_SYMBOL_METHOD(MethodName) \ + auto MethodName() const->decltype(RawSymbol->MethodName()) { \ + return RawSymbol->MethodName(); \ + } + +#define FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(ConcreteType, PrivateName, \ + PublicName) \ + auto PublicName##Id() const->decltype(RawSymbol->PrivateName##Id()) { \ + return RawSymbol->PrivateName##Id(); \ + } \ + std::unique_ptr<ConcreteType> PublicName() const { \ + uint32_t Id = PublicName##Id(); \ + return getConcreteSymbolByIdHelper<ConcreteType>(Id); \ + } + +#define FORWARD_SYMBOL_ID_METHOD_WITH_NAME(PrivateName, PublicName) \ + FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(PDBSymbol, PrivateName, \ + PublicName) + +#define FORWARD_SYMBOL_ID_METHOD(MethodName) \ + FORWARD_SYMBOL_ID_METHOD_WITH_NAME(MethodName, MethodName) + +namespace llvm { + +class StringRef; +class raw_ostream; + +namespace pdb { +class IPDBRawSymbol; +class IPDBSession; + +#define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \ +private: \ + using PDBSymbol::PDBSymbol; \ + friend class PDBSymbol; \ + \ +public: \ + static const PDB_SymType Tag = TagValue; \ + static bool classof(const PDBSymbol *S) { return S->getSymTag() == Tag; } + +#define DECLARE_PDB_SYMBOL_CUSTOM_TYPE(Condition) \ +private: \ + using PDBSymbol::PDBSymbol; \ + friend class PDBSymbol; \ + \ +public: \ + static bool classof(const PDBSymbol *S) { return Condition; } + +/// PDBSymbol defines the base of the inheritance hierarchy for concrete symbol +/// types (e.g. functions, executables, vtables, etc). All concrete symbol +/// types inherit from PDBSymbol and expose the exact set of methods that are +/// valid for that particular symbol type, as described in the Microsoft +/// reference "Lexical and Class Hierarchy of Symbol Types": +/// https://msdn.microsoft.com/en-us/library/370hs6k4.aspx +class PDBSymbol { + static std::unique_ptr<PDBSymbol> createSymbol(const IPDBSession &PDBSession, + PDB_SymType Tag); + +protected: + explicit PDBSymbol(const IPDBSession &PDBSession); + PDBSymbol(PDBSymbol &&Other); + +public: + static std::unique_ptr<PDBSymbol> + create(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> RawSymbol); + static std::unique_ptr<PDBSymbol> create(const IPDBSession &PDBSession, + IPDBRawSymbol &RawSymbol); + + template <typename ConcreteT> + static std::unique_ptr<ConcreteT> + createAs(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> RawSymbol) { + std::unique_ptr<PDBSymbol> S = create(PDBSession, std::move(RawSymbol)); + return unique_dyn_cast_or_null<ConcreteT>(std::move(S)); + } + template <typename ConcreteT> + static std::unique_ptr<ConcreteT> createAs(const IPDBSession &PDBSession, + IPDBRawSymbol &RawSymbol) { + std::unique_ptr<PDBSymbol> S = create(PDBSession, RawSymbol); + return unique_dyn_cast_or_null<ConcreteT>(std::move(S)); + } + + virtual ~PDBSymbol(); + + /// Dumps the contents of a symbol a raw_ostream. By default this will just + /// call dump() on the underlying RawSymbol, which allows us to discover + /// unknown properties, but individual implementations of PDBSymbol may + /// override the behavior to only dump known fields. + virtual void dump(PDBSymDumper &Dumper) const = 0; + + /// For certain PDBSymbolTypes, dumps additional information for the type that + /// normally goes on the right side of the symbol. + virtual void dumpRight(PDBSymDumper &Dumper) const {} + + void defaultDump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowFlags, + PdbSymbolIdField RecurseFlags) const; + void dumpProperties() const; + void dumpChildStats() const; + + PDB_SymType getSymTag() const; + uint32_t getSymIndexId() const; + + template <typename T> std::unique_ptr<T> findOneChild() const { + auto Enumerator(findAllChildren<T>()); + if (!Enumerator) + return nullptr; + return Enumerator->getNext(); + } + + template <typename T> + std::unique_ptr<ConcreteSymbolEnumerator<T>> findAllChildren() const { + auto BaseIter = RawSymbol->findChildren(T::Tag); + if (!BaseIter) + return nullptr; + return llvm::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter)); + } + std::unique_ptr<IPDBEnumSymbols> findAllChildren(PDB_SymType Type) const; + std::unique_ptr<IPDBEnumSymbols> findAllChildren() const; + + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const; + std::unique_ptr<IPDBEnumSymbols> findChildrenByRVA(PDB_SymType Type, + StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t RVA) const; + std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const; + + const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; } + IPDBRawSymbol &getRawSymbol() { return *RawSymbol; } + + const IPDBSession &getSession() const { return Session; } + + std::unique_ptr<IPDBEnumSymbols> getChildStats(TagStats &Stats) const; + +protected: + std::unique_ptr<PDBSymbol> getSymbolByIdHelper(uint32_t Id) const; + + template <typename ConcreteType> + std::unique_ptr<ConcreteType> getConcreteSymbolByIdHelper(uint32_t Id) const { + return unique_dyn_cast_or_null<ConcreteType>(getSymbolByIdHelper(Id)); + } + + const IPDBSession &Session; + std::unique_ptr<IPDBRawSymbol> OwnedRawSymbol; + IPDBRawSymbol *RawSymbol = nullptr; +}; + +} // namespace llvm +} + +#endif diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h new file mode 100644 index 00000000..c76466a9 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h @@ -0,0 +1,35 @@ +//===- PDBSymbolAnnotation.h - Accessors for querying PDB annotations ---*-===// +// +// 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_PDBSYMBOLANNOTATION_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolAnnotation : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Annotation) + +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getDataKind) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + // FORWARD_SYMBOL_METHOD(getValue) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; +} +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h new file mode 100644 index 00000000..cf471450 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h @@ -0,0 +1,37 @@ +//===- PDBSymbolBlock.h - Accessors for querying PDB blocks -------------*-===// +// +// 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_PDBSYMBOLBLOCK_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +namespace pdb { + +class PDBSymbolBlock : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Block) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; +} +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h new file mode 100644 index 00000000..ca8b39d0 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h @@ -0,0 +1,37 @@ +//===- PDBSymbolCompiland.h - Accessors for querying PDB compilands -----*-===// +// +// 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_PDBSYMBOLCOMPILAND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include <string> + +namespace llvm { + +class raw_ostream; + +namespace pdb { + +class PDBSymbolCompiland : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Compiland) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getLibraryName) + FORWARD_SYMBOL_METHOD(getName) + + std::string getSourceFileName() const; + std::string getSourceFileFullPath() const; +}; +} +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h new file mode 100644 index 00000000..b82bb6c0 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h @@ -0,0 +1,52 @@ +//===- PDBSymbolCompilandDetails.h - PDB compiland details ------*- 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_PDBSYMBOLCOMPILANDDETAILS_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDDETAILS_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolCompilandDetails : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandDetails) +public: + void dump(PDBSymDumper &Dumper) const override; + + void getFrontEndVersion(VersionInfo &Version) const { + RawSymbol->getFrontEndVersion(Version); + } + + void getBackEndVersion(VersionInfo &Version) const { + RawSymbol->getBackEndVersion(Version); + } + + FORWARD_SYMBOL_METHOD(getCompilerName) + FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled) + FORWARD_SYMBOL_METHOD(hasDebugInfo) + FORWARD_SYMBOL_METHOD(hasManagedCode) + FORWARD_SYMBOL_METHOD(hasSecurityChecks) + FORWARD_SYMBOL_METHOD(isCVTCIL) + FORWARD_SYMBOL_METHOD(isDataAligned) + FORWARD_SYMBOL_METHOD(isHotpatchable) + FORWARD_SYMBOL_METHOD(isLTCG) + FORWARD_SYMBOL_METHOD(isMSILNetmodule) + FORWARD_SYMBOL_METHOD(getLanguage) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getPlatform) + FORWARD_SYMBOL_METHOD(getSourceFileName) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBFUNCTION_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h new file mode 100644 index 00000000..61607a03 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h @@ -0,0 +1,32 @@ +//===- PDBSymbolCompilandEnv.h - compiland environment variables *- 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_PDBSYMBOLCOMPILANDENV_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { +class PDBSymbolCompilandEnv : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandEnv) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getName) + std::string getValue() const; +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h new file mode 100644 index 00000000..75a86411 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h @@ -0,0 +1,35 @@ +//===- PDBSymbolCustom.h - compiler-specific 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class raw_ostream; + +namespace pdb { +/// PDBSymbolCustom represents symbols that are compiler-specific and do not +/// fit anywhere else in the lexical hierarchy. +/// https://msdn.microsoft.com/en-us/library/d88sf09h.aspx +class PDBSymbolCustom : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Custom) +public: + void dump(PDBSymDumper &Dumper) const override; + + void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes); +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolData.h new file mode 100644 index 00000000..7e9b69d7 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolData.h @@ -0,0 +1,59 @@ +//===- PDBSymbolData.h - PDB data (e.g. variable) accessors -----*- 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_PDBSYMBOLDATA_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H + +#include "IPDBLineNumber.h" +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +namespace pdb { + +class PDBSymbolData : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getAddressTaken) + FORWARD_SYMBOL_METHOD(getBitPosition) + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(isCompilerGenerated) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getDataKind) + FORWARD_SYMBOL_METHOD(isAggregated) + FORWARD_SYMBOL_METHOD(isSplitted) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(getRegisterId) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSlot) + FORWARD_SYMBOL_METHOD(getToken) + FORWARD_SYMBOL_ID_METHOD(getType) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getValue) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(isVolatileType) + + std::unique_ptr<IPDBEnumLineNumbers> getLineNumbers() const; + uint32_t getCompilandId() const; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolExe.h new file mode 100644 index 00000000..1a9fb240 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolExe.h @@ -0,0 +1,44 @@ +//===- PDBSymbolExe.h - Accessors for querying executables in a PDB ----*-===// +// +// 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_PDBSYMBOLEXE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +namespace pdb { + +class PDBSymbolExe : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Exe) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAge) + FORWARD_SYMBOL_METHOD(getGuid) + FORWARD_SYMBOL_METHOD(hasCTypes) + FORWARD_SYMBOL_METHOD(hasPrivateSymbols) + FORWARD_SYMBOL_METHOD(getMachineType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSignature) + FORWARD_SYMBOL_METHOD(getSymbolsFileName) + + uint32_t getPointerByteSize() const; + +private: + void dumpChildren(raw_ostream &OS, StringRef Label, PDB_SymType ChildType, + int Indent) const; +}; +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h new file mode 100644 index 00000000..6be27c8d --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -0,0 +1,85 @@ +//===- PDBSymbolFunc.h - class representing a function instance -*- 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_PDBSYMBOLFUNC_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H + +#include "IPDBLineNumber.h" +#include "PDBSymbol.h" +#include "PDBSymbolTypeFunctionSig.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +namespace pdb { + +class PDBSymbolFunc : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function) +public: + void dump(PDBSymDumper &Dumper) const override; + + bool isDestructor() const; + + std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> getArguments() const; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(isCompilerGenerated) + FORWARD_SYMBOL_METHOD(isConstructorVirtualBase) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(isCxxReturnUdt) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasAlloca) + FORWARD_SYMBOL_METHOD(hasEH) + FORWARD_SYMBOL_METHOD(hasEHa) + FORWARD_SYMBOL_METHOD(hasInlAsm) + FORWARD_SYMBOL_METHOD(hasLongJump) + FORWARD_SYMBOL_METHOD(hasSEH) + FORWARD_SYMBOL_METHOD(hasSecurityChecks) + FORWARD_SYMBOL_METHOD(hasSetJump) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isIntroVirtualFunction) + FORWARD_SYMBOL_METHOD(hasInlineAttribute) + FORWARD_SYMBOL_METHOD(isNaked) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getLocalBasePointerRegisterId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(hasFramePointer) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getNoStackOrdering) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(isPureVirtual) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getToken) + FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(PDBSymbolTypeFunctionSig, getType, + getSignature) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getUndecoratedName) + FORWARD_SYMBOL_METHOD(isVirtual) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) + FORWARD_SYMBOL_METHOD(isVolatileType) + + std::unique_ptr<IPDBEnumLineNumbers> getLineNumbers() const; + uint32_t getCompilandId() const; +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h new file mode 100644 index 00000000..7152249c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h @@ -0,0 +1,46 @@ +//===- PDBSymbolFuncDebugEnd.h - function end bounds info -------*- 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_PDBSYMBOLFUNCDEBUGEND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +namespace pdb { + +class PDBSymbolFuncDebugEnd : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugEnd) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h new file mode 100644 index 00000000..3125c271 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h @@ -0,0 +1,45 @@ +//===- PDBSymbolFuncDebugStart.h - function start bounds info ---*- 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_PDBSYMBOLFUNCDEBUGSTART_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolFuncDebugStart : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugStart) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h new file mode 100644 index 00000000..3625e23f --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h @@ -0,0 +1,45 @@ +//===- PDBSymbolLabel.h - label info ----------------------------*- 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_PDBSYMBOLLABEL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolLabel : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Label) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h new file mode 100644 index 00000000..e2b2545d --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h @@ -0,0 +1,43 @@ +//===- PDBSymbolPublicSymbol.h - public symbol info -------------*- 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_PDBSYMBOLPUBLICSYMBOL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolPublicSymbol : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PublicSymbol) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(isCode) + FORWARD_SYMBOL_METHOD(isFunction) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(isManagedCode) + FORWARD_SYMBOL_METHOD(isMSILCode) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getUndecoratedName) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h new file mode 100644 index 00000000..274de8b0 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h @@ -0,0 +1,52 @@ +//===- PDBSymbolThunk.h - Support for querying PDB thunks ---------------*-===// +// +// 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_PDBSYMBOLTHUNK_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolThunk : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Thunk) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(isIntroVirtualFunction) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isPureVirtual) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getTargetOffset) + FORWARD_SYMBOL_METHOD(getTargetRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getTargetVirtualAddress) + FORWARD_SYMBOL_METHOD(getTargetSection) + FORWARD_SYMBOL_METHOD(getThunkOrdinal) + FORWARD_SYMBOL_ID_METHOD(getType) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVirtual) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h new file mode 100644 index 00000000..c0215c9e --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h @@ -0,0 +1,40 @@ +//===- PDBSymbolTypeArray.h - array type information ------------*- 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_PDBSYMBOLTYPEARRAY_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeArray : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType) +public: + void dump(PDBSymDumper &Dumper) const override; + void dumpRight(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_ID_METHOD(getArrayIndexType) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getRank) + FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getElementType) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h new file mode 100644 index 00000000..bab292ee --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h @@ -0,0 +1,59 @@ +//===- PDBSymbolTypeBaseClass.h - base class type information ---*- 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_PDBSYMBOLTYPEBASECLASS_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeBaseClass : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BaseClass) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(isIndirectVirtualBaseClass) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_ID_METHOD(getType) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + + FORWARD_SYMBOL_METHOD(isVirtualBaseClass) + FORWARD_SYMBOL_METHOD(getVirtualBaseDispIndex) + FORWARD_SYMBOL_METHOD(getVirtualBasePointerOffset) + // FORWARD_SYMBOL_METHOD(getVirtualBaseTableType) + FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h new file mode 100644 index 00000000..7d94c3c9 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h @@ -0,0 +1,36 @@ +//===- PDBSymbolTypeBuiltin.h - builtin type information --------*- 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_PDBSYMBOLTYPEBUILTIN_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeBuiltin : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BuiltinType) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h new file mode 100644 index 00000000..dc647aff --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h @@ -0,0 +1,32 @@ +//===- PDBSymbolTypeCustom.h - custom compiler type information -*- 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_PDBSYMBOLTYPECUSTOM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeCustom : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CustomType) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getOemId) + FORWARD_SYMBOL_METHOD(getOemSymbolId) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h new file mode 100644 index 00000000..7a9e4378 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h @@ -0,0 +1,32 @@ +//===- PDBSymbolTypeDimension.h - array dimension type info -----*- 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_PDBSYMBOLTYPEDIMENSION_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeDimension : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Dimension) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLowerBoundId) + FORWARD_SYMBOL_METHOD(getUpperBoundId) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h new file mode 100644 index 00000000..3ac72801 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h @@ -0,0 +1,52 @@ +//===- PDBSymbolTypeEnum.h - enum type info ---------------------*- 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_PDBSYMBOLTYPEENUM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H + +#include "IPDBLineNumber.h" +#include "PDBSymbol.h" +#include "PDBSymbolTypeBuiltin.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeEnum : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Enum) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_ID_METHOD(getUnmodifiedType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSrcLineOnTypeDefn) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(PDBSymbolTypeBuiltin, getType, + getUnderlyingType) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h new file mode 100644 index 00000000..c4d9dd63 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h @@ -0,0 +1,33 @@ +//===- PDBSymbolTypeFriend.h - friend type info -----------------*- 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_PDBSYMBOLTYPEFRIEND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeFriend : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Friend) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_ID_METHOD(getType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h new file mode 100644 index 00000000..22d36234 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h @@ -0,0 +1,33 @@ +//===- PDBSymbolTypeFunctionArg.h - function arg type info ------*- 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_PDBSYMBOLTYPEFUNCTIONARG_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeFunctionArg : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionArg) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_ID_METHOD(getType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h new file mode 100644 index 00000000..a1491ca2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -0,0 +1,47 @@ +//===- PDBSymbolTypeFunctionSig.h - function signature type info *- 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_PDBSYMBOLTYPEFUNCTIONSIG_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeFunctionSig : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig) +public: + std::unique_ptr<IPDBEnumSymbols> getArguments() const; + + void dump(PDBSymDumper &Dumper) const override; + void dumpRight(PDBSymDumper &Dumper) const override; + void dumpArgList(raw_ostream &OS) const; + + bool isCVarArgs() const; + + FORWARD_SYMBOL_METHOD(getCallingConvention) + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_ID_METHOD(getUnmodifiedType) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + // FORWARD_SYMBOL_METHOD(getObjectPointerType) + FORWARD_SYMBOL_METHOD(getThisAdjust) + FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getReturnType) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h new file mode 100644 index 00000000..6bc70bca --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h @@ -0,0 +1,31 @@ +//===- PDBSymbolTypeManaged.h - managed type info ---------------*- 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_PDBSYMBOLTYPEMANAGED_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeManaged : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ManagedType) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getName) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h new file mode 100644 index 00000000..b36f459e --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -0,0 +1,43 @@ +//===- PDBSymbolTypePointer.h - pointer type info ---------------*- 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_PDBSYMBOLTYPEPOINTER_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypePointer : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType) +public: + void dump(PDBSymDumper &Dumper) const override; + void dumpRight(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(isReference) + FORWARD_SYMBOL_METHOD(isRValueReference) + FORWARD_SYMBOL_METHOD(isPointerToDataMember) + FORWARD_SYMBOL_METHOD(isPointerToMemberFunction) + FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getPointeeType) + FORWARD_SYMBOL_METHOD(isRestrictedType) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h new file mode 100644 index 00000000..2712d061 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h @@ -0,0 +1,50 @@ +//===- PDBSymbolTypeTypedef.h - typedef type info ---------------*- 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_PDBSYMBOLTYPETYPEDEF_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeTypedef : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Typedef) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isReference) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_ID_METHOD(getType) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h new file mode 100644 index 00000000..3e73ad7a --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -0,0 +1,53 @@ +//===- PDBSymbolTypeUDT.h - UDT type info -----------------------*- 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_PDBSYMBOLTYPEUDT_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H + +#include "IPDBLineNumber.h" +#include "IPDBSession.h" +#include "PDBSymbol.h" +#include "PDBSymbolTypeBaseClass.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +namespace pdb { + +class PDBSymbolTypeUDT : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_ID_METHOD(getUnmodifiedType) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSrcLineOnTypeDefn) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape) + FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(getAccess) +}; +} +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h new file mode 100644 index 00000000..e8161d31 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h @@ -0,0 +1,37 @@ +//===- PDBSymbolTypeVTable.h - VTable type info -----------------*- 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_PDBSYMBOLTYPEVTABLE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeVTable : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTable) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_ID_METHOD(getClassParent) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_ID_METHOD(getType) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h new file mode 100644 index 00000000..61406086 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h @@ -0,0 +1,35 @@ +//===- PDBSymbolTypeVTableShape.h - VTable shape info -----------*- 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_PDBSYMBOLTYPEVTABLESHAPE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolTypeVTableShape : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTableShape) +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h new file mode 100644 index 00000000..cc29d38c --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h @@ -0,0 +1,30 @@ +//===- PDBSymbolUnknown.h - unknown symbol type -----------------*- 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_PDBSYMBOLUNKNOWN_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H + +#include "PDBSymbol.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolUnknown : public PDBSymbol { + DECLARE_PDB_SYMBOL_CUSTOM_TYPE(S->getSymTag() == PDB_SymType::None || + S->getSymTag() >= PDB_SymType::Max) + +public: + void dump(PDBSymDumper &Dumper) const override; +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h new file mode 100644 index 00000000..fd812cb2 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h @@ -0,0 +1,33 @@ +//===- PDBSymbolUsingNamespace.h - using namespace info ---------*- 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_PDBSYMBOLUSINGNAMESPACE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; +namespace pdb { + +class PDBSymbolUsingNamespace : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UsingNamespace) + +public: + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_METHOD(getName) +}; + +} // namespace llvm +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/PDBTypes.h b/clang-r353983/include/llvm/DebugInfo/PDB/PDBTypes.h new file mode 100644 index 00000000..6d26b64d --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -0,0 +1,467 @@ +//===- PDBTypes.h - Defines enums for various fields contained in PDB ----====// +// +// 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_PDBTYPES_H +#define LLVM_DEBUGINFO_PDB_PDBTYPES_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBFrameData.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include <cctype> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <functional> + +namespace llvm { +namespace pdb { + +typedef uint32_t SymIndexId; + +class IPDBDataStream; +class IPDBInjectedSource; +class IPDBLineNumber; +class IPDBSectionContrib; +class IPDBSourceFile; +class IPDBTable; +class PDBSymDumper; +class PDBSymbol; +class PDBSymbolExe; +class PDBSymbolCompiland; +class PDBSymbolCompilandDetails; +class PDBSymbolCompilandEnv; +class PDBSymbolFunc; +class PDBSymbolBlock; +class PDBSymbolData; +class PDBSymbolAnnotation; +class PDBSymbolLabel; +class PDBSymbolPublicSymbol; +class PDBSymbolTypeUDT; +class PDBSymbolTypeEnum; +class PDBSymbolTypeFunctionSig; +class PDBSymbolTypePointer; +class PDBSymbolTypeArray; +class PDBSymbolTypeBuiltin; +class PDBSymbolTypeTypedef; +class PDBSymbolTypeBaseClass; +class PDBSymbolTypeFriend; +class PDBSymbolTypeFunctionArg; +class PDBSymbolFuncDebugStart; +class PDBSymbolFuncDebugEnd; +class PDBSymbolUsingNamespace; +class PDBSymbolTypeVTableShape; +class PDBSymbolTypeVTable; +class PDBSymbolCustom; +class PDBSymbolThunk; +class PDBSymbolTypeCustom; +class PDBSymbolTypeManaged; +class PDBSymbolTypeDimension; +class PDBSymbolUnknown; + +using IPDBEnumSymbols = IPDBEnumChildren<PDBSymbol>; +using IPDBEnumSourceFiles = IPDBEnumChildren<IPDBSourceFile>; +using IPDBEnumDataStreams = IPDBEnumChildren<IPDBDataStream>; +using IPDBEnumLineNumbers = IPDBEnumChildren<IPDBLineNumber>; +using IPDBEnumTables = IPDBEnumChildren<IPDBTable>; +using IPDBEnumInjectedSources = IPDBEnumChildren<IPDBInjectedSource>; +using IPDBEnumSectionContribs = IPDBEnumChildren<IPDBSectionContrib>; +using IPDBEnumFrameData = IPDBEnumChildren<IPDBFrameData>; + +/// Specifies which PDB reader implementation is to be used. Only a value +/// of PDB_ReaderType::DIA is currently supported, but Native is in the works. +enum class PDB_ReaderType { + DIA = 0, + Native = 1, +}; + +/// An enumeration indicating the type of data contained in this table. +enum class PDB_TableType { + TableInvalid = 0, + Symbols, + SourceFiles, + LineNumbers, + SectionContribs, + Segments, + InjectedSources, + FrameData, + InputAssemblyFiles, + Dbg +}; + +/// Defines flags used for enumerating child symbols. This corresponds to the +/// NameSearchOptions enumeration which is documented here: +/// https://msdn.microsoft.com/en-us/library/yat28ads.aspx +enum PDB_NameSearchFlags { + NS_Default = 0x0, + NS_CaseSensitive = 0x1, + NS_CaseInsensitive = 0x2, + NS_FileNameExtMatch = 0x4, + NS_Regex = 0x8, + NS_UndecoratedName = 0x10, + + // For backward compatibility. + NS_CaseInFileNameExt = NS_CaseInsensitive | NS_FileNameExtMatch, + NS_CaseRegex = NS_Regex | NS_CaseSensitive, + NS_CaseInRex = NS_Regex | NS_CaseInsensitive +}; + +/// Specifies the hash algorithm that a source file from a PDB was hashed with. +/// This corresponds to the CV_SourceChksum_t enumeration and are documented +/// here: https://msdn.microsoft.com/en-us/library/e96az21x.aspx +enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2, SHA256 = 3 }; + +/// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx +using PDB_Cpu = codeview::CPUType; + +enum class PDB_Machine { + Invalid = 0xffff, + Unknown = 0x0, + Am33 = 0x13, + Amd64 = 0x8664, + Arm = 0x1C0, + ArmNT = 0x1C4, + Ebc = 0xEBC, + x86 = 0x14C, + Ia64 = 0x200, + M32R = 0x9041, + Mips16 = 0x266, + MipsFpu = 0x366, + MipsFpu16 = 0x466, + PowerPC = 0x1F0, + PowerPCFP = 0x1F1, + R4000 = 0x166, + SH3 = 0x1A2, + SH3DSP = 0x1A3, + SH4 = 0x1A6, + SH5 = 0x1A8, + Thumb = 0x1C2, + WceMipsV2 = 0x169 +}; + +enum class PDB_SourceCompression { + None, + RunLengthEncoded, + Huffman, + LZ, +}; + +/// 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 +using PDB_CallingConv = codeview::CallingConvention; + +/// These values correspond to the CV_CFL_LANG enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx +using PDB_Lang = codeview::SourceLanguage; + +/// These values correspond to the DataKind enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/b2x2t313.aspx +enum class PDB_DataKind { + Unknown, + Local, + StaticLocal, + Param, + ObjectPtr, + FileStatic, + Global, + Member, + StaticMember, + Constant +}; + +/// These values correspond to the SymTagEnum enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/bkedss5f.aspx +enum class PDB_SymType { + None, + Exe, + Compiland, + CompilandDetails, + CompilandEnv, + Function, + Block, + Data, + Annotation, + Label, + PublicSymbol, + UDT, + Enum, + FunctionSig, + PointerType, + ArrayType, + BuiltinType, + Typedef, + BaseClass, + Friend, + FunctionArg, + FuncDebugStart, + FuncDebugEnd, + UsingNamespace, + VTableShape, + VTable, + Custom, + Thunk, + CustomType, + ManagedType, + Dimension, + CallSite, + InlineSite, + BaseInterface, + VectorType, + MatrixType, + HLSLType, + Caller, + Callee, + Export, + HeapAllocationSite, + CoffGroup, + Inlinee, + Max +}; + +/// These values correspond to the LocationType enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/f57kaez3.aspx +enum class PDB_LocType { + Null, + Static, + TLS, + RegRel, + ThisRel, + Enregistered, + BitField, + Slot, + IlRel, + MetaData, + Constant, + RegRelAliasIndir, + Max +}; + +/// These values correspond to the UdtKind enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/wcstk66t.aspx +enum class PDB_UdtType { Struct, Class, Union, Interface }; + +/// These values correspond to the StackFrameTypeEnum enumeration, and are +/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx. +enum class PDB_StackFrameType : uint16_t { + FPO, + KernelTrap, + KernelTSS, + EBP, + FrameData, + Unknown = 0xffff +}; + +/// These values correspond to the MemoryTypeEnum enumeration, and are +/// documented here: https://msdn.microsoft.com/en-us/library/ms165609.aspx. +enum class PDB_MemoryType : uint16_t { + Code, + Data, + Stack, + HeapCode, + Any = 0xffff +}; + +/// These values correspond to the Basictype enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx +enum class PDB_BuiltinType { + None = 0, + Void = 1, + Char = 2, + WCharT = 3, + Int = 6, + UInt = 7, + Float = 8, + BCD = 9, + Bool = 10, + Long = 13, + ULong = 14, + Currency = 25, + Date = 26, + Variant = 27, + Complex = 28, + Bitfield = 29, + BSTR = 30, + HResult = 31, + Char16 = 32, + Char32 = 33 +}; + +/// These values correspond to the flags that can be combined to control the +/// return of an undecorated name for a C++ decorated name, and are documented +/// here: https://msdn.microsoft.com/en-us/library/kszfk0fs.aspx +enum PDB_UndnameFlags : uint32_t { + Undname_Complete = 0x0, + Undname_NoLeadingUnderscores = 0x1, + Undname_NoMsKeywords = 0x2, + Undname_NoFuncReturns = 0x4, + Undname_NoAllocModel = 0x8, + Undname_NoAllocLang = 0x10, + Undname_Reserved1 = 0x20, + Undname_Reserved2 = 0x40, + Undname_NoThisType = 0x60, + Undname_NoAccessSpec = 0x80, + Undname_NoThrowSig = 0x100, + Undname_NoMemberType = 0x200, + Undname_NoReturnUDTModel = 0x400, + Undname_32BitDecode = 0x800, + Undname_NameOnly = 0x1000, + Undname_TypeOnly = 0x2000, + Undname_HaveParams = 0x4000, + Undname_NoECSU = 0x8000, + Undname_NoIdentCharCheck = 0x10000, + Undname_NoPTR64 = 0x20000 +}; + +enum class PDB_MemberAccess { Private = 1, Protected = 2, Public = 3 }; + +struct VersionInfo { + uint32_t Major; + uint32_t Minor; + uint32_t Build; + uint32_t QFE; +}; + +enum PDB_VariantType { + Empty, + Unknown, + Int8, + Int16, + Int32, + Int64, + Single, + Double, + UInt8, + UInt16, + UInt32, + UInt64, + Bool, + String +}; + +struct Variant { + Variant() = default; + + explicit Variant(bool V) : Type(PDB_VariantType::Bool) { Value.Bool = V; } + explicit Variant(int8_t V) : Type(PDB_VariantType::Int8) { Value.Int8 = V; } + explicit Variant(int16_t V) : Type(PDB_VariantType::Int16) { + Value.Int16 = V; + } + explicit Variant(int32_t V) : Type(PDB_VariantType::Int32) { + Value.Int32 = V; + } + explicit Variant(int64_t V) : Type(PDB_VariantType::Int64) { + Value.Int64 = V; + } + explicit Variant(float V) : Type(PDB_VariantType::Single) { + Value.Single = V; + } + explicit Variant(double V) : Type(PDB_VariantType::Double) { + Value.Double = V; + } + explicit Variant(uint8_t V) : Type(PDB_VariantType::UInt8) { + Value.UInt8 = V; + } + explicit Variant(uint16_t V) : Type(PDB_VariantType::UInt16) { + Value.UInt16 = V; + } + explicit Variant(uint32_t V) : Type(PDB_VariantType::UInt32) { + Value.UInt32 = V; + } + explicit Variant(uint64_t V) : Type(PDB_VariantType::UInt64) { + Value.UInt64 = V; + } + + Variant(const Variant &Other) { + *this = Other; + } + + ~Variant() { + if (Type == PDB_VariantType::String) + delete[] Value.String; + } + + PDB_VariantType Type = PDB_VariantType::Empty; + union { + bool Bool; + int8_t Int8; + int16_t Int16; + int32_t Int32; + int64_t Int64; + float Single; + double Double; + uint8_t UInt8; + uint16_t UInt16; + uint32_t UInt32; + uint64_t UInt64; + char *String; + } Value; + +#define VARIANT_EQUAL_CASE(Enum) \ + case PDB_VariantType::Enum: \ + return Value.Enum == Other.Value.Enum; + + bool operator==(const Variant &Other) const { + if (Type != Other.Type) + return false; + switch (Type) { + VARIANT_EQUAL_CASE(Bool) + VARIANT_EQUAL_CASE(Int8) + VARIANT_EQUAL_CASE(Int16) + VARIANT_EQUAL_CASE(Int32) + VARIANT_EQUAL_CASE(Int64) + VARIANT_EQUAL_CASE(Single) + VARIANT_EQUAL_CASE(Double) + VARIANT_EQUAL_CASE(UInt8) + VARIANT_EQUAL_CASE(UInt16) + VARIANT_EQUAL_CASE(UInt32) + VARIANT_EQUAL_CASE(UInt64) + VARIANT_EQUAL_CASE(String) + default: + return true; + } + } + +#undef VARIANT_EQUAL_CASE + + bool operator!=(const Variant &Other) const { return !(*this == Other); } + Variant &operator=(const Variant &Other) { + if (this == &Other) + return *this; + if (Type == PDB_VariantType::String) + delete[] Value.String; + Type = Other.Type; + Value = Other.Value; + if (Other.Type == PDB_VariantType::String && + Other.Value.String != nullptr) { + Value.String = new char[strlen(Other.Value.String) + 1]; + ::strcpy(Value.String, Other.Value.String); + } + return *this; + } +}; + +} // end namespace pdb +} // end namespace llvm + +namespace std { + +template <> struct hash<llvm::pdb::PDB_SymType> { + using argument_type = llvm::pdb::PDB_SymType; + using result_type = std::size_t; + + result_type operator()(const argument_type &Arg) const { + return std::hash<int>()(static_cast<int>(Arg)); + } +}; + +} // end namespace std + +#endif // LLVM_DEBUGINFO_PDB_PDBTYPES_H diff --git a/clang-r353983/include/llvm/DebugInfo/PDB/UDTLayout.h b/clang-r353983/include/llvm/DebugInfo/PDB/UDTLayout.h new file mode 100644 index 00000000..c67b093b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/PDB/UDTLayout.h @@ -0,0 +1,181 @@ +//===- UDTLayout.h - UDT layout info ----------------------------*- 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_UDTLAYOUT_H +#define LLVM_DEBUGINFO_PDB_UDTLAYOUT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include <cstdint> +#include <memory> +#include <string> +#include <vector> + +namespace llvm { +namespace pdb { + +class BaseClassLayout; +class ClassLayout; +class UDTLayoutBase; + +class LayoutItemBase { +public: + LayoutItemBase(const UDTLayoutBase *Parent, const PDBSymbol *Symbol, + const std::string &Name, uint32_t OffsetInParent, + uint32_t Size, bool IsElided); + virtual ~LayoutItemBase() = default; + + uint32_t deepPaddingSize() const; + virtual uint32_t immediatePadding() const { return 0; } + virtual uint32_t tailPadding() const; + + const UDTLayoutBase *getParent() const { return Parent; } + StringRef getName() const { return Name; } + uint32_t getOffsetInParent() const { return OffsetInParent; } + uint32_t getSize() const { return SizeOf; } + uint32_t getLayoutSize() const { return LayoutSize; } + const PDBSymbol *getSymbol() const { return Symbol; } + const BitVector &usedBytes() const { return UsedBytes; } + bool isElided() const { return IsElided; } + virtual bool isVBPtr() const { return false; } + + uint32_t containsOffset(uint32_t Off) const { + uint32_t Begin = getOffsetInParent(); + uint32_t End = Begin + getSize(); + return (Off >= Begin && Off < End); + } + +protected: + const PDBSymbol *Symbol = nullptr; + const UDTLayoutBase *Parent = nullptr; + BitVector UsedBytes; + std::string Name; + uint32_t OffsetInParent = 0; + uint32_t SizeOf = 0; + uint32_t LayoutSize = 0; + bool IsElided = false; +}; + +class VBPtrLayoutItem : public LayoutItemBase { +public: + VBPtrLayoutItem(const UDTLayoutBase &Parent, + std::unique_ptr<PDBSymbolTypeBuiltin> Sym, uint32_t Offset, + uint32_t Size); + + bool isVBPtr() const override { return true; } + +private: + std::unique_ptr<PDBSymbolTypeBuiltin> Type; +}; + +class DataMemberLayoutItem : public LayoutItemBase { +public: + DataMemberLayoutItem(const UDTLayoutBase &Parent, + std::unique_ptr<PDBSymbolData> DataMember); + + const PDBSymbolData &getDataMember(); + bool hasUDTLayout() const; + const ClassLayout &getUDTLayout() const; + +private: + std::unique_ptr<PDBSymbolData> DataMember; + std::unique_ptr<ClassLayout> UdtLayout; +}; + +class VTableLayoutItem : public LayoutItemBase { +public: + VTableLayoutItem(const UDTLayoutBase &Parent, + std::unique_ptr<PDBSymbolTypeVTable> VTable); + + uint32_t getElementSize() const { return ElementSize; } + +private: + uint32_t ElementSize = 0; + std::unique_ptr<PDBSymbolTypeVTable> VTable; +}; + +class UDTLayoutBase : public LayoutItemBase { + template <typename T> using UniquePtrVector = std::vector<std::unique_ptr<T>>; + +public: + UDTLayoutBase(const UDTLayoutBase *Parent, const PDBSymbol &Sym, + const std::string &Name, uint32_t OffsetInParent, uint32_t Size, + bool IsElided); + + uint32_t tailPadding() const override; + ArrayRef<LayoutItemBase *> layout_items() const { return LayoutItems; } + ArrayRef<BaseClassLayout *> bases() const { return AllBases; } + ArrayRef<BaseClassLayout *> regular_bases() const { return NonVirtualBases; } + ArrayRef<BaseClassLayout *> virtual_bases() const { return VirtualBases; } + uint32_t directVirtualBaseCount() const { return DirectVBaseCount; } + ArrayRef<std::unique_ptr<PDBSymbolFunc>> funcs() const { return Funcs; } + ArrayRef<std::unique_ptr<PDBSymbol>> other_items() const { return Other; } + +protected: + bool hasVBPtrAtOffset(uint32_t Off) const; + void initializeChildren(const PDBSymbol &Sym); + + void addChildToLayout(std::unique_ptr<LayoutItemBase> Child); + + uint32_t DirectVBaseCount = 0; + + UniquePtrVector<PDBSymbol> Other; + UniquePtrVector<PDBSymbolFunc> Funcs; + UniquePtrVector<LayoutItemBase> ChildStorage; + std::vector<LayoutItemBase *> LayoutItems; + + std::vector<BaseClassLayout *> AllBases; + ArrayRef<BaseClassLayout *> NonVirtualBases; + ArrayRef<BaseClassLayout *> VirtualBases; + + VTableLayoutItem *VTable = nullptr; + VBPtrLayoutItem *VBPtr = nullptr; +}; + +class BaseClassLayout : public UDTLayoutBase { +public: + BaseClassLayout(const UDTLayoutBase &Parent, uint32_t OffsetInParent, + bool Elide, std::unique_ptr<PDBSymbolTypeBaseClass> Base); + + const PDBSymbolTypeBaseClass &getBase() const { return *Base; } + bool isVirtualBase() const { return IsVirtualBase; } + bool isEmptyBase() { return SizeOf == 1 && LayoutSize == 0; } + +private: + std::unique_ptr<PDBSymbolTypeBaseClass> Base; + bool IsVirtualBase; +}; + +class ClassLayout : public UDTLayoutBase { +public: + explicit ClassLayout(const PDBSymbolTypeUDT &UDT); + explicit ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT); + + ClassLayout(ClassLayout &&Other) = default; + + const PDBSymbolTypeUDT &getClass() const { return UDT; } + uint32_t immediatePadding() const override; + +private: + BitVector ImmediateUsedBytes; + std::unique_ptr<PDBSymbolTypeUDT> OwnedStorage; + const PDBSymbolTypeUDT &UDT; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_UDTLAYOUT_H diff --git a/clang-r353983/include/llvm/DebugInfo/Symbolize/DIPrinter.h b/clang-r353983/include/llvm/DebugInfo/Symbolize/DIPrinter.h new file mode 100644 index 00000000..71663f30 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/Symbolize/DIPrinter.h @@ -0,0 +1,53 @@ +//===- llvm/DebugInfo/Symbolize/DIPrinter.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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the DIPrinter class, which is responsible for printing +// structures defined in DebugInfo/DIContext.h +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H +#define LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +struct DILineInfo; +class DIInliningInfo; +struct DIGlobal; + +namespace symbolize { + +class DIPrinter { + raw_ostream &OS; + bool PrintFunctionNames; + bool PrintPretty; + int PrintSourceContext; + bool Verbose; + bool Basenames; + + void print(const DILineInfo &Info, bool Inlined); + void printContext(const std::string &FileName, int64_t Line); + +public: + DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true, + bool PrintPretty = false, int PrintSourceContext = 0, + bool Verbose = false, bool Basenames = false) + : OS(OS), PrintFunctionNames(PrintFunctionNames), + PrintPretty(PrintPretty), PrintSourceContext(PrintSourceContext), + Verbose(Verbose), Basenames(Basenames) {} + + DIPrinter &operator<<(const DILineInfo &Info); + DIPrinter &operator<<(const DIInliningInfo &Info); + DIPrinter &operator<<(const DIGlobal &Global); +}; +} +} + +#endif + diff --git a/clang-r353983/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h b/clang-r353983/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h new file mode 100644 index 00000000..f0862d0b --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h @@ -0,0 +1,46 @@ +//===- SymbolizableModule.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 +// +//===----------------------------------------------------------------------===// +// +// This file declares the SymbolizableModule interface. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEMODULE_H +#define LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEMODULE_H + +#include "llvm/DebugInfo/DIContext.h" +#include <cstdint> + +namespace llvm { +namespace symbolize { + +using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind; + +class SymbolizableModule { +public: + virtual ~SymbolizableModule() = default; + + virtual DILineInfo symbolizeCode(uint64_t ModuleOffset, + FunctionNameKind FNKind, + bool UseSymbolTable) const = 0; + virtual DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset, + FunctionNameKind FNKind, + bool UseSymbolTable) const = 0; + virtual DIGlobal symbolizeData(uint64_t ModuleOffset) const = 0; + + // Return true if this is a 32-bit x86 PE COFF module. + virtual bool isWin32Module() const = 0; + + // Returns the preferred base of the module, i.e. where the loader would place + // it in memory assuming there were no conflicts. + virtual uint64_t getModulePreferredBase() const = 0; +}; + +} // end namespace symbolize +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEMODULE_H diff --git a/clang-r353983/include/llvm/DebugInfo/Symbolize/Symbolize.h b/clang-r353983/include/llvm/DebugInfo/Symbolize/Symbolize.h new file mode 100644 index 00000000..4e57fe43 --- /dev/null +++ b/clang-r353983/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -0,0 +1,125 @@ +//===- Symbolize.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 +// +//===----------------------------------------------------------------------===// +// +// Header for LLVM symbolization library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H +#define LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H + +#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Error.h" +#include <algorithm> +#include <cstdint> +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { +namespace symbolize { + +using namespace object; + +using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind; + +class LLVMSymbolizer { +public: + struct Options { + FunctionNameKind PrintFunctions; + bool UseSymbolTable : 1; + bool Demangle : 1; + bool RelativeAddresses : 1; + std::string DefaultArch; + std::vector<std::string> DsymHints; + std::string FallbackDebugPath; + + Options(FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, + bool UseSymbolTable = true, bool Demangle = true, + bool RelativeAddresses = false, std::string DefaultArch = "", + std::string FallbackDebugPath = "") + : PrintFunctions(PrintFunctions), UseSymbolTable(UseSymbolTable), + Demangle(Demangle), RelativeAddresses(RelativeAddresses), + DefaultArch(std::move(DefaultArch)), + FallbackDebugPath(std::move(FallbackDebugPath)) {} + }; + + LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {} + + ~LLVMSymbolizer() { + flush(); + } + + Expected<DILineInfo> symbolizeCode(const std::string &ModuleName, + uint64_t ModuleOffset, + StringRef DWPName = ""); + Expected<DIInliningInfo> symbolizeInlinedCode(const std::string &ModuleName, + uint64_t ModuleOffset, + StringRef DWPName = ""); + Expected<DIGlobal> symbolizeData(const std::string &ModuleName, + uint64_t ModuleOffset); + void flush(); + + static std::string + DemangleName(const std::string &Name, + const SymbolizableModule *DbiModuleDescriptor); + +private: + // Bundles together object file with code/data and object file with + // corresponding debug info. These objects can be the same. + using ObjectPair = std::pair<ObjectFile *, ObjectFile *>; + + /// Returns a SymbolizableModule or an error if loading debug info failed. + /// Only one attempt is made to load a module, and errors during loading are + /// only reported once. Subsequent calls to get module info for a module that + /// failed to load will return nullptr. + Expected<SymbolizableModule *> + getOrCreateModuleInfo(const std::string &ModuleName, StringRef DWPName = ""); + + ObjectFile *lookUpDsymFile(const std::string &Path, + const MachOObjectFile *ExeObj, + const std::string &ArchName); + ObjectFile *lookUpDebuglinkObject(const std::string &Path, + const ObjectFile *Obj, + const std::string &ArchName); + + /// Returns pair of pointers to object and debug object. + Expected<ObjectPair> getOrCreateObjectPair(const std::string &Path, + const std::string &ArchName); + + /// Return a pointer to object file at specified path, for a specified + /// architecture (e.g. if path refers to a Mach-O universal binary, only one + /// object file from it will be returned). + Expected<ObjectFile *> getOrCreateObject(const std::string &Path, + const std::string &ArchName); + + std::map<std::string, std::unique_ptr<SymbolizableModule>> Modules; + + /// Contains cached results of getOrCreateObjectPair(). + std::map<std::pair<std::string, std::string>, ObjectPair> + ObjectPairForPathArch; + + /// Contains parsed binary for each path, or parsing error. + std::map<std::string, OwningBinary<Binary>> BinaryForPath; + + /// Parsed object file for path/architecture pair, where "path" refers + /// to Mach-O universal binary. + std::map<std::pair<std::string, std::string>, std::unique_ptr<ObjectFile>> + ObjectForUBPathAndArch; + + Options Opts; +}; + +} // end namespace symbolize +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H |
