| # CodeView Type Records | |
| (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 {ref}`padding records <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: | |
| ```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:** | |
| ```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: | |
| ```none | |
| .-----------------------------------------------------------------------------------------------------. | |
| | Unused | Flags | Size | Modifiers | Mode | Kind | | |
| .-----------------------------------------------------------------------------------------------------. | |
| | | | | | | | | |
| 0x100 +0x16 +0x13 +0xD +0x8 +0x5 +0x0 | |
| ``` | |
| where the various fields are defined by the following enums: | |
| ```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 <type_indices>`. | |
| #### 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) |