From: Zachary Turner Date: Wed, 10 Apr 2019 18:26:51 +0000 (+0000) Subject: [PDB Docs] Start documenting CodeView Type Records. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=091d3974ccd71dbda7ee88045a2437f57f7447ee;p=llvm [PDB Docs] Start documenting CodeView Type Records. This puts the general layout of the document in place and fully describes 1 simple type record. Followups will fill out more pieces. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358119 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/PDB/CodeViewTypes.rst b/docs/PDB/CodeViewTypes.rst index ad806a70df1..4bef1b5f658 100644 --- a/docs/PDB/CodeViewTypes.rst +++ b/docs/PDB/CodeViewTypes.rst @@ -1,4 +1,261 @@ -===================================== -CodeView Type Records -===================================== +===================================== +CodeView Type Records +===================================== + + +.. contents:: + :local: + +.. _types_intro: + +Introduction +============ + +This document describes the usage and serialization format of the various +CodeView type records that LLVM understands. This document does not describe +every single CodeView type record that is defined. In some cases, this is +because the records are clearly deprecated and can only appear in very old +software (e.g. the 16-bit types). On other cases, it is because the records +have never been observed in practice. This could be because they are only +generated for non-C++ code (e.g. Visual Basic, C#), or because they have been +made obsolete by newer records, or any number of other reasons. However, the +records we describe here should cover 99% of type records that one can expect +to encounter when dealing with modern C++ toolchains. + +Record Categories +================= + +We can think of a sequence of CodeView type records as an array of variable length +`leaf records`. Each such record describes its own length as part of a fixed-size +header, as well as the kind of record it is. Leaf records are either padded to 4 +bytes (if this type stream appears in a TPI/IPI stream of a PDB) or not padded at +all (if this type stream appears in the ``.debug$T`` section of an object file). +Padding is implemented by inserting a decreasing sequence of `<_padding_records>` +that terminates with ``LF_PAD0``. + +The final category of record is a ``member record``. One particular leaf type -- +``LF_FIELDLIST`` -- contains a series of embedded records. While the outer +``LF_FIELDLIST`` describes its length (like any other leaf record), the embedded +records -- called ``member records`` do not. + +.. _leaf_types: + +Leaf Records +------------ + +All leaf records begin with the following 4 byte prefix: + +.. code-block:: c++ + + struct RecordHeader { + uint16_t RecordLen; // Record length, not including this 2 byte field. + uint16_t RecordKind; // Record kind enum. + }; + +LF_POINTER (0x1002) +^^^^^^^^^^^^^^^^^^^ + +**Usage:** Describes a pointer to another type. + +**Layout:** + +.. code-block:: none + + .--------------------.-- +0 + | Referent Type | + .--------------------.-- +4 + | Attributes | + .--------------------.-- +8 + | Member Ptr Info | Only present if |Attributes| indicates this is a member pointer. + .--------------------.-- +E +Attributes is a bitfield with the following layout: + +.. code-block:: none + + .-----------------------------------------------------------------------------------------------------. + | Unused | Flags | Size | Modifiers | Mode | Kind | + .-----------------------------------------------------------------------------------------------------. + | | | | | | | + 0x100 +0x16 +0x13 +0xD +0x8 +0x5 +0x0 + +where the various fields are defined by the following enums: + +.. code-block:: c++ + + 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 + }; + 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 + }; + enum class PointerModifiers : uint8_t { + None = 0x00, // "normal" pointer + Flat32 = 0x01, // "flat" pointer + Volatile = 0x02, // pointer is marked volatile + Const = 0x04, // pointer is marked const + Unaligned = 0x08, // pointer is marked unaligned + Restrict = 0x10, // pointer is marked restrict + }; + enum class PointerFlags : uint8_t { + WinRTSmartPointer = 0x01, // pointer is a WinRT smart pointer + LValueRefThisPointer = 0x02, // pointer is a 'this' pointer of a member function with ref qualifier (e.g. void X::foo() &) + RValueRefThisPointer = 0x04 // pointer is a 'this' pointer of a member function with ref qualifier (e.g. void X::foo() &&) + }; + +The ``Size`` field of the Attributes bitmask is a 1-byte value indicating the +pointer size. For example, a `void*` would have a size of either 4 or 8 depending +on the target architecture. On the other hand, if ``Mode`` indicates that this is +a pointer to member function or pointer to data member, then the size can be any +implementation defined number. + +The ``Member Ptr Info`` field of the ``LF_POINTER`` record is only present if the +attributes indicate that this is a pointer to member. + +Note that "plain" pointers to primitive types are not represented by ``LF_POINTER`` +records, they are indicated by special reserved :ref:`TypeIndex values `. + + + +LF_MODIFIER (0x1001) +^^^^^^^^^^^^^^^^^^^^ + +LF_PROCEDURE (0x1008) +^^^^^^^^^^^^^^^^^^^^^ + +LF_MFUNCTION (0x1009) +^^^^^^^^^^^^^^^^^^^^^ + +LF_LABEL (0x000e) +^^^^^^^^^^^^^^^^^ + +LF_ARGLIST (0x1201) +^^^^^^^^^^^^^^^^^^^ + +LF_FIELDLIST (0x1203) +^^^^^^^^^^^^^^^^^^^^^ + +LF_ARRAY (0x1503) +^^^^^^^^^^^^^^^^^ + +LF_CLASS (0x1504) +^^^^^^^^^^^^^^^^^ + +LF_STRUCTURE (0x1505) +^^^^^^^^^^^^^^^^^^^^^ + +LF_INTERFACE (0x1519) +^^^^^^^^^^^^^^^^^^^^^ + +LF_UNION (0x1506) +^^^^^^^^^^^^^^^^^ + +LF_ENUM (0x1507) +^^^^^^^^^^^^^^^^ + +LF_TYPESERVER2 (0x1515) +^^^^^^^^^^^^^^^^^^^^^^^ + +LF_VFTABLE (0x151d) +^^^^^^^^^^^^^^^^^^^ + +LF_VTSHAPE (0x000a) +^^^^^^^^^^^^^^^^^^^ + +LF_BITFIELD (0x1205) +^^^^^^^^^^^^^^^^^^^^ + +LF_FUNC_ID (0x1601) +^^^^^^^^^^^^^^^^^^^ + +LF_MFUNC_ID (0x1602) +^^^^^^^^^^^^^^^^^^^^ + +LF_BUILDINFO (0x1603) +^^^^^^^^^^^^^^^^^^^^^ + +LF_SUBSTR_LIST (0x1604) +^^^^^^^^^^^^^^^^^^^^^^^ + +LF_STRING_ID (0x1605) +^^^^^^^^^^^^^^^^^^^^^ + +LF_UDT_SRC_LINE (0x1606) +^^^^^^^^^^^^^^^^^^^^^^^^ + +LF_UDT_MOD_SRC_LINE (0x1607) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +LF_METHODLIST (0x1206) +^^^^^^^^^^^^^^^^^^^^^^ + +LF_PRECOMP (0x1509) +^^^^^^^^^^^^^^^^^^^ + +LF_ENDPRECOMP (0x0014) +^^^^^^^^^^^^^^^^^^^^^^ + +.. _member_types: + +Member Records +-------------- + +LF_BCLASS (0x1400) +^^^^^^^^^^^^^^^^^^ + +LF_BINTERFACE (0x151a) +^^^^^^^^^^^^^^^^^^^^^^ + +LF_VBCLASS (0x1401) +^^^^^^^^^^^^^^^^^^^ + +LF_IVBCLASS (0x1402) +^^^^^^^^^^^^^^^^^^^^ + +LF_VFUNCTAB (0x1409) +^^^^^^^^^^^^^^^^^^^^ + +LF_STMEMBER (0x150e) +^^^^^^^^^^^^^^^^^^^^ + +LF_METHOD (0x150f) +^^^^^^^^^^^^^^^^^^ + +LF_MEMBER (0x150d) +^^^^^^^^^^^^^^^^^^ + +LF_NESTTYPE (0x1510) +^^^^^^^^^^^^^^^^^^^^ + +LF_ONEMETHOD (0x1511) +^^^^^^^^^^^^^^^^^^^^^ + +LF_ENUMERATE (0x1502) +^^^^^^^^^^^^^^^^^^^^^ + +LF_INDEX (0x1404) +^^^^^^^^^^^^^^^^^ + +.. _padding_records: + +Padding Records +--------------- + +LF_PADn (0xf0 + n) +^^^^^^^^^^^^^^^^^^