CodeView Type Records

December 12, 2025 ยท View on GitHub

This file describes the type records used by CodeView.

Type records are variable-length records. Each record begins with a 4-byte header which specifies the length and the "kind" of the record.

struct TypeRecord {
   uint16_t size;
   uint16_t kind;
   uint8_t payload[size - 2];
};

The size field specifies the size in bytes of the record. The size field does not count the size field itself, but it does count the kind field and the payload bytes.

Invariant: The size field is a multiple of 2 and is greater than or equal to 2.

Type records are aligned at 2-byte boundaries. Unfortunately, many type records contain fields that have 4-byte alignment, such as uint32_t. Encoders and decoders must handle misaligned access to those fields, either using unaligned memory accesses or must copy the entire record to a buffer that has a guaranteed alignment.

The kind field specifies how to interpret a type record. In the PDB documentation, this kind field uses the "Leaf Type" enumeration.

Summary of type records

There are several disjoint categories of record kinds:

  • type category: Records that are pointed-to by other parts of the PDB file, such as symbol records. These are the "top-level" type records. These records define a complete type, which is what allows them to be used by symbol records.

  • internal category: Records that are pointed-to by other type records, but which are not pointed-to by any symbol record outside of the TPI stream. This is why these records are called "internal"; these records (along with the records that point to them) describe complex hierarchical structures. Only the "external" records, such as LF_CLASS or LF_ENUM, are directly pointed-to by symbol records.

    These internal records are not, by themselves, complete records. They only have meaning in the context of the hierarchy of records that they occur within. For example, LF_METHODLIST gives a list of methods, but must be associated with (pointed-to by) a record such as LF_CLASS.

  • special records, such as LF_PRECOMP, which are produced by the compiler and are read (and consumed) by the linker.

There are also data structures which use LF_* naming prefixes and the same numbering system as type records, but which are embedded within LF_FIELDLIST records. These "field records" are not type records. They do not use the TypeRecord layout and cannot be found by simply enumerating the type records in the TPI. See LF_FIELDLIST.

KindNameCategoryDescription
0x000aLF_VTSHAPEinternalShape of a virtual function table
0x0014LF_ENDPRECOMPspecialSpecifies end of precompiled types
0x1001LF_MODIFIERtypeModifies a type by applying volatile, const, or unaligned to it
0x1002LF_POINTERtypeDefines a pointer to another type, e.g. FOO*
0x1008LF_PROCEDUREtypeA function signature type
0x1009LF_MFUNCTIONtypeA member function signature type
0x1502LF_ARRAYtypeA fixed-size array, e.g. char FOO[100]
0x1504LF_CLASStypeA class definition
0x1505LF_STRUCTUREtypeA struct definition
0x1506LF_UNIONtypeA union definition
0x1507LF_ENUMtypeAn enum definition
0x1509LF_PRECOMPspecialSpecifies types come from precompiled module
0x1200LF_SKIPinternalReserves space in the type stream, but contains no information
0x1201LF_ARGLISTinternalSpecifies arguments for LF_PROCEDURE or LF_MFUNCTION
0x1203LF_FIELDLISTinternalContains field records for LF_CLASS, LF_STRUCTURE, LF_ENUM, etc.
0x1205LF_BITFIELDSinternalSpecifies a bitfield within another field
0x1206LF_METHODLISTinternalSpecifies a list of methods in an overload group (methods that have the same name but differing signatures)

Summary of item records

Leaf indices referenced from symbols

These are the top-level type record kinds. These records can be pointed-to by symbol records, or by other top-level type records. They define types.