//===-- CodeView.h - On-disk record types for CodeView ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// \brief This file provides data structures useful for consuming on-disk /// CodeView. It is based on information published by Microsoft at /// https://github.com/Microsoft/microsoft-pdb/. /// //===----------------------------------------------------------------------===// // FIXME: Find a home for this in include/llvm/DebugInfo/CodeView/. #ifndef LLVM_READOBJ_CODEVIEW_H #define LLVM_READOBJ_CODEVIEW_H #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/Endian.h" namespace llvm { namespace codeview { /// A Symbols subsection is a sequence of SymRecords. Advancing by 'len' /// bytes will find the next SymRecord. These are the possible types of a /// record. Equivalent to SYM_ENUM_e in cvinfo.h. enum SymType : uint16_t { #define SYMBOL_TYPE(ename, value) ename = value, #include "CVSymbolTypes.def" }; /// Generic record compatible with all symbol records. struct SymRecord { ulittle16_t RecordLength; // Record length, starting from the next field ulittle16_t RecordType; // Record type (SymType) // Symbol data follows. }; /// Corresponds to the CV_PROCFLAGS bitfield. enum ProcFlags : uint8_t { HasFP = 1 << 0, HasIRET = 1 << 1, HasFRET = 1 << 2, IsNoReturn = 1 << 3, IsUnreachable = 1 << 4, HasCustomCallingConv = 1 << 5, IsNoInline = 1 << 6, HasOptimizedDebugInfo = 1 << 7, }; // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or // S_LPROC32_DPC_ID struct ProcSym { ulittle32_t PtrParent; ulittle32_t PtrEnd; ulittle32_t PtrNext; ulittle32_t CodeSize; ulittle32_t DbgStart; ulittle32_t DbgEnd; TypeIndex FunctionType; ulittle32_t CodeOffset; ulittle16_t Segment; uint8_t Flags; // CV_PROCFLAGS // Name: The null-terminated name follows. }; // S_INLINESITE struct InlineSiteSym { ulittle32_t PtrParent; ulittle32_t PtrEnd; TypeIndex Inlinee; // BinaryAnnotations }; // S_LOCAL struct LocalSym { TypeIndex Type; ulittle16_t Flags; enum : uint16_t { 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, }; // Name: The null-terminated name follows. }; // S_BLOCK32 struct BlockSym { ulittle32_t PtrParent; ulittle32_t PtrEnd; ulittle32_t CodeSize; ulittle32_t CodeOffset; ulittle16_t Segment; // Name: The null-terminated name follows. }; // S_LABEL32 struct LabelSym { ulittle32_t CodeOffset; ulittle16_t Segment; uint8_t Flags; // CV_PROCFLAGS // Name: The null-terminated name follows. }; // S_OBJNAME struct ObjNameSym { ulittle32_t Signature; // Name: The null-terminated name follows. }; // S_COMPILE3 struct CompileSym3 { ulittle32_t flags; uint8_t getLanguage() const { return flags & 0xff; } enum Flags : uint32_t { 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, }; ulittle16_t Machine; // CPUType ulittle16_t VersionFrontendMajor; ulittle16_t VersionFrontendMinor; ulittle16_t VersionFrontendBuild; ulittle16_t VersionFrontendQFE; ulittle16_t VersionBackendMajor; ulittle16_t VersionBackendMinor; ulittle16_t VersionBackendBuild; ulittle16_t VersionBackendQFE; // VersionString: The null-terminated version string follows. }; // S_FRAMEPROC struct FrameProcSym { ulittle32_t TotalFrameBytes; ulittle32_t PaddingFrameBytes; ulittle32_t OffsetToPadding; ulittle32_t BytesOfCalleeSavedRegisters; ulittle32_t OffsetOfExceptionHandler; ulittle16_t SectionIdOfExceptionHandler; ulittle32_t Flags; }; // S_CALLSITEINFO struct CallSiteInfoSym { ulittle32_t CodeOffset; ulittle16_t Segment; ulittle16_t Reserved; TypeIndex Type; }; // S_HEAPALLOCSITE struct HeapAllocationSiteSym { ulittle32_t CodeOffset; ulittle16_t Segment; ulittle16_t CallInstructionSize; TypeIndex Type; }; // S_FRAMECOOKIE struct FrameCookieSym { ulittle32_t CodeOffset; ulittle16_t Register; ulittle16_t CookieKind; enum : uint16_t { Copy, XorStackPointer, XorFramePointer, XorR13, }; }; // S_UDT, S_COBOLUDT struct UDTSym { TypeIndex Type; // Type of the UDT // Name: The null-terminated name follows. }; // S_BUILDINFO struct BuildInfoSym { ulittle32_t BuildId; }; // S_BPREL32 struct BPRelativeSym { ulittle32_t Offset; // Offset from the base pointer register TypeIndex Type; // Type of the variable // Name: The null-terminated name follows. }; // S_REGREL32 struct RegRelativeSym { ulittle32_t Offset; // Offset from the register TypeIndex Type; // Type of the variable ulittle16_t Register; // Register to which the variable is relative // Name: The null-terminated name follows. }; // S_CONSTANT, S_MANCONSTANT struct ConstantSym { TypeIndex Type; // Value: The value of the constant. // Name: The null-terminated name follows. }; // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA struct DataSym { TypeIndex Type; ulittle32_t DataOffset; ulittle16_t Segment; // Name: The null-terminated name follows. }; // S_LTHREAD32, S_GTHREAD32 struct ThreadLocalDataSym { TypeIndex Type; ulittle32_t DataOffset; ulittle16_t Segment; // Name: The null-terminated name follows. }; /// Data in the the SUBSEC_FRAMEDATA subection. struct FrameData { ulittle32_t RvaStart; ulittle32_t CodeSize; ulittle32_t LocalSize; ulittle32_t ParamsSize; ulittle32_t MaxStackSize; ulittle32_t FrameFunc; ulittle16_t PrologSize; ulittle16_t SavedRegsSize; ulittle32_t Flags; enum : uint32_t { HasSEH = 1 << 0, HasEH = 1 << 1, IsFunctionStart = 1 << 2, }; }; //===----------------------------------------------------------------------===// // On-disk representation of type information /// Indicates the kind of TypeRecord we're dealing with here. The documentation /// and headers talk about this as the "leaf" type. enum LeafType : uint16_t { #define LEAF_TYPE(name, val) name = val, #include "CVLeafTypes.def" }; // A CodeView type stream is a sequence of TypeRecords. Records larger than // 65536 must chain on to a second record. Each TypeRecord is followed by one of // the leaf types described below. struct TypeRecord { ulittle16_t Len; // Type record length, starting from &Leaf. ulittle16_t Leaf; // Type record kind (LeafType) }; // LF_TYPESERVER2 struct TypeServer2 { char Signature[16]; // GUID ulittle32_t Age; // Name: Name of the PDB as a null-terminated string }; // LF_STRING_ID struct StringId { TypeIndex id; }; // LF_FUNC_ID struct FuncId { TypeIndex ParentScope; TypeIndex FunctionType; // Name: The null-terminated name follows. }; // LF_CLASS, LF_STRUCT, LF_INTERFACE struct ClassType { ulittle16_t MemberCount; // Number of members in FieldList. ulittle16_t Properties; // ClassOptions bitset TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members TypeIndex DerivedFrom; // LF_DERIVED: List of known derived classes TypeIndex VShape; // LF_VTSHAPE: Shape of the vftable // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC integer. // Name: The null-terminated name follows. }; // LF_UNION struct UnionType { ulittle16_t MemberCount; // Number of members in FieldList. ulittle16_t Properties; // ClassOptions bitset TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC integer. // Name: The null-terminated name follows. }; // LF_POINTER struct PointerType { TypeIndex PointeeType; ulittle32_t Attrs; // pointer attributes // if pointer to member: // PointerToMemberTail PointerKind getPtrKind() const { return PointerKind(Attrs & 0x1f); } PointerMode getPtrMode() const { return PointerMode((Attrs >> 5) & 0x07); } bool isFlat() const { return Attrs & (1 << 8); } bool isVolatile() const { return Attrs & (1 << 9); } bool isConst() const { return Attrs & (1 << 10); } bool isUnaligned() const { return Attrs & (1 << 11); } bool isPointerToDataMember() const { return getPtrMode() == PointerMode::PointerToDataMember; } bool isPointerToMemberFunction() const { return getPtrMode() == PointerMode::PointerToMemberFunction; } bool isPointerToMember() const { return isPointerToMemberFunction() || isPointerToDataMember(); } }; struct PointerToMemberTail { TypeIndex ClassType; ulittle16_t Representation; // PointerToMemberRepresentation }; /// In Clang parlance, these are "qualifiers". LF_MODIFIER struct TypeModifier { TypeIndex ModifiedType; ulittle16_t Modifiers; // ModifierOptions }; // LF_VTSHAPE struct VTableShape { // Number of vftable entries. Each method may have more than one entry due to // things like covariant return types. ulittle16_t VFEntryCount; // Descriptors[]: 4-bit virtual method descriptors of type CV_VTS_desc_e. }; // LF_UDT_SRC_LINE struct UDTSrcLine { TypeIndex UDT; // The user-defined type TypeIndex SourceFile; // StringID containing the source filename ulittle32_t LineNumber; }; // LF_ARGLIST, LF_SUBSTR_LIST struct ArgList { ulittle32_t NumArgs; // Number of arguments // ArgTypes[]: Type indicies of arguments }; // LF_BUILDINFO struct BuildInfo { ulittle16_t NumArgs; // Number of arguments // ArgTypes[]: Type indicies of arguments }; // LF_ENUM struct EnumType { ulittle16_t NumEnumerators; // Number of enumerators ulittle16_t Properties; TypeIndex UnderlyingType; TypeIndex FieldListType; // Name: The null-terminated name follows. }; // LF_ARRAY struct ArrayType { TypeIndex ElementType; TypeIndex IndexType; // SizeOf: LF_NUMERIC encoded size in bytes. Not element count! // Name: The null-terminated name follows. }; // LF_VFTABLE struct VFTableType { TypeIndex CompleteClass; // Class that owns this vftable. TypeIndex OverriddenVFTable; // VFTable that this overrides. ulittle32_t VFPtrOffset; // VFPtr offset in CompleteClass ulittle32_t NamesLen; // Length of subsequent names array in bytes. // Names: A sequence of null-terminated strings. First string is vftable // names. }; // LF_MFUNC_ID struct MemberFuncId { TypeIndex ClassType; TypeIndex FunctionType; // Name: The null-terminated name follows. }; // LF_PROCEDURE struct ProcedureType { TypeIndex ReturnType; CallingConvention CallConv; FunctionOptions Options; ulittle16_t NumParameters; TypeIndex ArgListType; }; // LF_MFUNCTION struct MemberFunctionType { TypeIndex ReturnType; TypeIndex ClassType; TypeIndex ThisType; CallingConvention CallConv; FunctionOptions Options; ulittle16_t NumParameters; TypeIndex ArgListType; little32_t ThisAdjustment; }; //===----------------------------------------------------------------------===// // Field list records, which do not include leafs or sizes /// Equvalent to CV_fldattr_t in cvinfo.h. struct MemberAttributes { ulittle16_t Attrs; /// 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)) >> 2); } /// 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; } }; // LF_NESTTYPE struct NestedType { ulittle16_t Pad0; // Should be zero TypeIndex Type; // Type index of nested type // Name: Null-terminated string }; // LF_ONEMETHOD struct OneMethod { MemberAttributes Attrs; TypeIndex Type; // If is introduced virtual method: // VFTableOffset: int32_t offset in vftable // Name: Null-terminated string MethodKind getMethodKind() const { return Attrs.getMethodKind(); } bool isVirtual() const { return Attrs.isVirtual(); } bool isIntroducedVirtual() const { return Attrs.isIntroducedVirtual(); } }; struct MethodListEntry { MemberAttributes Attrs; ulittle16_t Padding; TypeIndex Type; // If is introduced virtual method: // VFTableOffset: int32_t offset in vftable MethodKind getMethodKind() const { return Attrs.getMethodKind(); } bool isVirtual() const { return Attrs.isVirtual(); } bool isIntroducedVirtual() const { return Attrs.isIntroducedVirtual(); } }; /// For method overload sets. LF_METHOD struct OverloadedMethod { ulittle16_t MethodCount; // Size of overload set TypeIndex MethList; // Type index of methods in overload set // Name: Null-terminated string }; // LF_VFUNCTAB struct VirtualFunctionPointer { ulittle16_t Pad0; TypeIndex Type; // Type of vfptr }; // LF_MEMBER struct DataMember { MemberAttributes Attrs; // Access control attributes, etc TypeIndex Type; // FieldOffset: LF_NUMERIC encoded byte offset // Name: Null-terminated string }; // LF_STMEMBER struct StaticDataMember { MemberAttributes Attrs; // Access control attributes, etc TypeIndex Type; // Name: Null-terminated string }; // LF_ENUMERATE struct Enumerator { MemberAttributes Attrs; // Access control attributes, etc // EnumValue: LF_NUMERIC encoded enumerator value // Name: Null-terminated string }; // LF_BCLASS, LF_BINTERFACE struct BaseClass { MemberAttributes Attrs; // Access control attributes, etc TypeIndex BaseType; // Base class type // BaseOffset: LF_NUMERIC encoded byte offset of base from derived. }; // LF_VBCLASS | LV_IVBCLASS struct VirtualBaseClass { MemberAttributes Attrs; // Access control attributes, etc. TypeIndex BaseType; // Base class type TypeIndex VBPtrType; // Virtual base pointer type // VBPtrOffset: Offset of vbptr from vfptr encoded as LF_NUMERIC. // VBTableIndex: Index of vbase within vbtable encoded as LF_NUMERIC. }; } // namespace codeview } // namespace llvm #endif // LLVM_READOBJ_CODEVIEW_H