ms_pdb/types/kind.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
/// Identifies type records. Also called "leaf" records.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Leaf(pub u16);
macro_rules! cv_leaf {
(
$(
$code:expr, $name:ident ;
)*
) => {
#[allow(non_upper_case_globals)]
#[allow(missing_docs)]
impl Leaf {
$(
pub const $name: Leaf = Leaf($code);
)*
}
static LEAF_NAMES: &[(Leaf, &str)] = &[
$(
(Leaf($code), stringify!($name)),
)*
];
}
}
cv_leaf! {
0x0001, LF_MODIFIER_16t;
0x0002, LF_POINTER_16t;
0x0003, LF_ARRAY_16t;
0x0004, LF_CLASS_16t;
0x0005, LF_STRUCTURE_16t;
0x0006, LF_UNION_16t;
0x0007, LF_ENUM_16t;
0x0008, LF_PROCEDURE_16t;
0x0009, LF_MFUNCTION_16t;
0x000a, LF_VTSHAPE;
0x000c, LF_COBOL1;
0x000e, LF_LABEL;
0x000f, LF_NULL;
0x0014, LF_ENDPRECOMP;
0x020c, LF_REFSYM;
0x040b, LF_FRIENDCLS; // (in field list) friend class
0x1001, LF_MODIFIER;
0x1002, LF_POINTER;
0x1008, LF_PROCEDURE;
0x1009, LF_MFUNCTION;
0x100a, LF_COBOL0;
0x100b, LF_BARRAY;
0x100d, LF_VFTPATH;
0x100f, LF_OEM;
0x1011, LF_OEM2;
0x1200, LF_SKIP;
0x1201, LF_ARGLIST;
0x1203, LF_FIELDLIST;
0x1204, LF_DERIVED;
0x1205, LF_BITFIELD;
0x1206, LF_METHODLIST;
0x1207, LF_DIMCONU;
0x1208, LF_DIMCONLU;
0x1209, LF_DIMVARU;
0x120a, LF_DIMVARLU;
0x1400, LF_BCLASS; // (in field list) real (non-virtual) base class
0x1401, LF_VBCLASS; // (in field list) direct virtual base class
0x1402, LF_IVBCLASS; // (in field list) indirect virtual base class
0x1404, LF_INDEX; // (in field list) index to another type record
0x1409, LF_VFUNCTAB; // (in field list) virtual function table pointer
0x140c, LF_VFUNCOFF; // (in field list) virtual function offset
0x1502, LF_ENUMERATE; // (in field list) an enumerator value
0x1503, LF_ARRAY;
0x1504, LF_CLASS;
0x1505, LF_STRUCTURE;
0x1506, LF_UNION;
0x1507, LF_ENUM;
0x1508, LF_DIMARRAY;
0x1509, LF_PRECOMP;
0x150a, LF_ALIAS;
0x150b, LF_DEFARG;
0x150c, LF_FRIENDFCN; // (in field list) friend function
0x150d, LF_MEMBER; // (in field list) data member
0x150e, LF_STMEMBER; // (in field list) static data member
0x150f, LF_METHOD; // (in field list) method group (overloaded methods), not single method
0x1510, LF_NESTEDTYPE; // (in field list) nested type definition
0x1511, LF_ONEMETHOD; // (in field list) a single method
0x1512, LF_NESTEDTYPEEX;// (in field list) nested type extended definition
0x1514, LF_MANAGED;
0x1515, LF_TYPESERVER2;
0x1519, LF_INTERFACE;
0x151d, LF_VFTABLE;
// --- end of types ---
// 0x1601..=0x1607 are only present in IPI stream, not TPI stream.
0x1601, LF_FUNC_ID; // global func ID
0x1602, LF_MFUNC_ID; // member func ID
0x1603, LF_BUILDINFO; // build info: tool, version, command line, src/pdb file
0x1604, LF_SUBSTR_LIST; // similar to LF_ARGLIST, for list of sub strings
0x1605, LF_STRING_ID; // string ID
// source and line on where an UDT is defined
// only generated by compiler
0x1606, LF_UDT_SRC_LINE;
// module, source and line on where an UDT is defined
// only generated by linker
0x1607, LF_UDT_MOD_SRC_LINE;
// The following four kinds were added to the wrong place in this enumeration.
// They should have been added befor LF_TYPE_LAST.
// But now it has been too late to change this :-(
0x1608, LF_CLASS2; // LF_CLASS with 32bit property field
0x1609, LF_STRUCTURE2; // LF_STRUCTURE with 32bit property field
0x160a, LF_UNION2; // LF_UNION with 32bit property field
0x160b, LF_INTERFACE2; // LF_INTERFACE with 32bit property field
// These values are used for encoding numeric constants.
// 0x8000, LF_NUMERIC;
0x8000, LF_CHAR; // i8
0x8001, LF_SHORT; // i16
0x8002, LF_USHORT; // u16
0x8003, LF_LONG; // i32
0x8004, LF_ULONG; // u32
0x8005, LF_REAL32; // f32
0x8006, LF_REAL64; // f64
0x8007, LF_REAL80;
0x8008, LF_REAL128;
0x8009, LF_QUADWORD; // i64
0x800a, LF_UQUADWORD; // u64
0x800b, LF_REAL48;
0x800c, LF_COMPLEX32;
0x800d, LF_COMPLEX64;
0x800e, LF_COMPLEX80;
0x800f, LF_COMPLEX128;
0x8010, LF_VARSTRING; // string prefixed with u16 length
0x8017, LF_OCTWORD; // i128
0x8018, LF_UOCTWORD; // u128
0x8019, LF_DECIMAL;
0x801a, LF_DATE; // 8 bytes
0x801b, LF_UTF8STRING; // NUL-terminated UTF-8 string
0x801c, LF_REAL16;
}
impl std::fmt::Debug for Leaf {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
if let Ok(index) = LEAF_NAMES.binary_search_by_key(self, |ii| ii.0) {
fmt.write_str(LEAF_NAMES[index].1)
} else {
let b0 = (self.0 & 0xff) as u8;
let b1 = (self.0 >> 8) as u8;
fn to_c(b: u8) -> char {
if (32..=126).contains(&b) {
char::from(b)
} else {
'_'
}
}
write!(fmt, "Leaf(??{:04x} {}{})", self.0, to_c(b0), to_c(b1))
}
}
}
impl Leaf {
/// True if this `Leaf` codes for an immediate numeric constant.
pub fn is_immediate_numeric(self) -> bool {
self.0 < 0x8000
}
/// Checks whether this `Leaf` can be used as a type record.
pub fn can_start_record(self) -> bool {
matches!(
self,
Leaf::LF_MODIFIER
| Leaf::LF_POINTER
| Leaf::LF_ARRAY
| Leaf::LF_CLASS
| Leaf::LF_STRUCTURE
| Leaf::LF_UNION
| Leaf::LF_ENUM
| Leaf::LF_PROCEDURE
| Leaf::LF_MFUNCTION
| Leaf::LF_VTSHAPE
| Leaf::LF_COBOL0
| Leaf::LF_COBOL1
| Leaf::LF_BARRAY
| Leaf::LF_LABEL
| Leaf::LF_NULL
| Leaf::LF_DIMARRAY
| Leaf::LF_VFTPATH
| Leaf::LF_PRECOMP
| Leaf::LF_ENDPRECOMP
| Leaf::LF_OEM
| Leaf::LF_OEM2
| Leaf::LF_ALIAS
| Leaf::LF_MANAGED
| Leaf::LF_TYPESERVER2
)
}
/// Checks whether this `Leaf` can be used within a field list record.
pub fn is_nested_leaf(self) -> bool {
matches!(
self,
Leaf::LF_SKIP
| Leaf::LF_ARGLIST
| Leaf::LF_DEFARG
| Leaf::LF_FIELDLIST
| Leaf::LF_DERIVED
| Leaf::LF_BITFIELD
| Leaf::LF_METHODLIST
| Leaf::LF_DIMCONU
| Leaf::LF_DIMCONLU
| Leaf::LF_DIMVARU
| Leaf::LF_DIMVARLU
| Leaf::LF_REFSYM
)
}
/// Indicates whether a given type record can contain references to other type records.
pub fn can_reference_types(self) -> bool {
matches!(
self,
Leaf::LF_MODIFIER
| Leaf::LF_POINTER
| Leaf::LF_ARRAY
| Leaf::LF_CLASS
| Leaf::LF_UNION
| Leaf::LF_ENUM
| Leaf::LF_PROCEDURE
)
}
}