llvm/tools/llvm-readobj/CodeView.h
Reid Kleckner fb30f09c13 [readobj] Expand CodeView dumping functionality
This rewrites and expands the existing codeview dumping functionality in
llvm-readobj using techniques similar to those in lib/Object. This defines a
number of new records and enums useful for reading memory mapped codeview
sections in COFF objects.

The dumper is intended as a testing tool for LLVM as it grows more codeview
output capabilities.

Reviewers: majnemer

Differential Revision: http://reviews.llvm.org/D16104

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257658 91177308-0d34-0410-b5e6-96231b3b80d8
2016-01-13 19:32:35 +00:00

572 lines
15 KiB
C++

//===-- 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