ms_codeview/syms/
kind.rs

1//! Symbol kind enumeration
2
3#[cfg(doc)]
4use super::BlockHeader;
5
6/// Identifies symbol records.
7///
8/// Symbol records are stored in the Global Symbol Stream and in each per-module symbol stream.
9///
10/// Many symbols can only appear in the Global Symbol Stream or in a per-module symbol stream.
11#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
12pub struct SymKind(pub u16);
13
14macro_rules! sym_kinds {
15    (
16        $( $code:expr, $name:ident; )*
17    ) => {
18        #[allow(missing_docs)]
19        impl SymKind {
20            $(
21                pub const $name: SymKind = SymKind($code);
22            )*
23        }
24
25        static SYM_NAMES: &[(SymKind, &str)] = &[
26            $(
27                (SymKind($code), stringify!($name)),
28            )*
29        ];
30    }
31}
32
33sym_kinds! {
34    0x0001, S_COMPILE;
35    0x0006, S_END;
36    0x0007, S_SKIP;
37    0x0008, S_CVRESERVE;
38    0x0009, S_OBJNAME_ST;
39    0x000d, S_RETURN;
40    // 0x0100..0x0400 is for 16-bit types
41    0x0400, S_PROCREF_ST;
42    0x0401, S_DATAREF_ST;
43    0x0402, S_ALIGN;
44    0x0403, S_LPROCREF_ST;
45    0x0404, S_OEM;
46
47    0x1000, S_TI16_MAX;
48    0x1001, S_REGISTER_ST;
49    0x1002, S_CONSTANT_ST;
50    0x1003, S_UDT_ST;
51    0x1004, S_COBOLUDT_ST;
52    0x1005, S_MANYREG_ST;
53    0x1006, S_BPREL32_ST;
54    0x1007, S_LDATA32_ST;
55    0x1008, S_GDATA32_ST;
56    0x1009, S_PUB32_ST;
57    0x100a, S_LPROC32_ST;
58    0x100b, S_GPROC32_ST;
59    0x100c, S_VFTABLE32;
60    0x100d, S_REGREL32_ST;
61    0x100e, S_LTHREAD32_ST;
62    0x100f, S_GTHREAD32_ST;
63    0x1012, S_FRAMEPROC;
64    0x1019, S_ANNOTATION;
65
66    0x1101, S_OBJNAME;
67    0x1102, S_THUNK32;
68    0x1103, S_BLOCK32;
69    0x1104, S_WITH32;
70    0x1105, S_LABEL32;
71    0x1106, S_REGISTER;
72    0x1107, S_CONSTANT;
73    0x1108, S_UDT;
74    0x1109, S_COBOLUDT;
75    0x110a, S_MANYREG;
76    0x110b, S_BPREL32;
77    0x110c, S_LDATA32;
78    0x110d, S_GDATA32;
79    0x110e, S_PUB32;
80    0x110f, S_LPROC32;
81
82    0x1110, S_GPROC32;
83    0x1111, S_REGREL32;
84    0x1112, S_LTHREAD32;
85    0x1113, S_GTHREAD32;
86    0x1116, S_COMPILE2;
87    0x1117, S_MANYREG2;
88    0x1118, S_LPROCIA64;
89    0x1119, S_GPROCIA64;
90    0x111a, S_LOCALSLOT;
91    0x111b, S_PARAMSLOT;
92    0x111c, S_LMANDATA;
93    0x111d, S_GMANDATA;
94    0x111e, S_MANFRAMEREL;
95    0x111f, S_MANREGISTER;
96
97    0x1120, S_MANSLOT;
98    0x1121, S_MANMANYREG;
99    0x1122, S_MANREGREL;
100    0x1123, S_MANMANYREG2;
101    0x1124, S_UNAMESPACE;
102    0x1125, S_PROCREF;
103    0x1126, S_DATAREF;
104    0x1127, S_LPROCREF;
105    0x1128, S_ANNOTATIONREF;
106    0x1129, S_TOKENREF;
107    0x112a, S_GMANPROC;
108    0x112b, S_LMANPROC;
109    0x112c, S_TRAMPOLINE;
110    0x112d, S_MANCONSTANT;
111    0x112e, S_ATTR_FRAMEREL;
112    0x112f, S_ATTR_REGISTER;
113
114    0x1130, S_ATTR_REGREL;
115    0x1131, S_ATTR_MANYREG;
116    0x1132, S_SEPCODE;
117    0x1133, S_LOCAL_2005;
118    0x1134, S_DEFRANGE_2005;
119    0x1135, S_DEFRANGE2_2005;
120    0x1136, S_SECTION;
121    0x1137, S_COFFGROUP;
122    0x1138, S_EXPORT;
123    0x1139, S_CALLSITEINFO;
124    0x113a, S_FRAMECOOKIE;
125    0x113b, S_DISCARDED;
126    0x113c, S_COMPILE3;
127    0x113d, S_ENVBLOCK;
128    0x113e, S_LOCAL;
129    0x113f, S_DEFRANGE;
130
131    0x1140, S_DEFRANGE_SUBFIELD;
132    0x1141, S_DEFRANGE_REGISTER;
133    0x1142, S_DEFRANGE_FRAMEPOINTER_REL;
134    0x1143, S_DEFRANGE_SUBFIELD_REGISTER;
135    0x1144, S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE;
136    0x1145, S_DEFRANGE_REGISTER_REL;
137    0x1146, S_LPROC32_ID;
138    0x1147, S_GPROC32_ID;
139    0x1148, S_LPROCMIPS_ID;
140    0x1149, S_GPROCMIPS_ID;
141    0x114a, S_LPROCIA64_ID;
142    0x114b, S_GPROCIA64_ID;
143    0x114c, S_BUILDINFO;
144    0x114d, S_INLINESITE;
145    0x114e, S_INLINESITE_END;
146    0x114f, S_PROC_ID_END;
147
148    0x1150, S_DEFRANGE_HLSL;
149    0x1151, S_GDATA_HLSL;
150    0x1152, S_LDATA_HLSL;
151    0x1153, S_FILESTATIC;
152    0x1154, S_LOCAL_DPC_GROUPSHARED;
153    0x1155, S_LPROC32_DPC;
154    0x1156, S_LPROC32_DPC_ID;
155    0x1157, S_DEFRANGE_DPC_PTR_TAG;
156    0x1158, S_DPC_SYM_TAG_MAP;
157    0x1159, S_ARMSWITCHTABLE;
158    0x115a, S_CALLEES;
159    0x115b, S_CALLERS;
160    0x115c, S_POGODATA;
161    0x115d, S_INLINESITE2;
162    0x115e, S_HEAPALLOCSITE;
163    0x115f, S_MOD_TYPEREF;
164
165    0x1160, S_REF_MINIPDB;
166    0x1161, S_PDBMAP;
167    0x1162, S_GDATA_HLSL32;
168    0x1163, S_LDATA_HLSL32;
169    0x1164, S_GDATA_HLSL32_EX;
170    0x1165, S_LDATA_HLSL32_EX;
171    0x1167, S_FASTLINK;
172    0x1168, S_INLINEES;
173    0x1169, S_HOTPATCHFUNC;
174}
175
176impl std::fmt::Debug for SymKind {
177    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
178        if let Ok(index) = SYM_NAMES.binary_search_by_key(self, |ii| ii.0) {
179            <str as std::fmt::Display>::fmt(SYM_NAMES[index].1, f)
180        } else {
181            let b0 = (self.0 & 0xff) as u8;
182            let b1 = (self.0 >> 8) as u8;
183            fn to_c(b: u8) -> char {
184                if (32..=126).contains(&b) {
185                    char::from(b)
186                } else {
187                    '_'
188                }
189            }
190
191            write!(f, "S_(??{:04x} {}{})", self.0, to_c(b1), to_c(b0))
192        }
193    }
194}
195
196#[test]
197fn test_sym_kind_debug() {
198    assert_eq!(format!("{:?}", SymKind::S_GPROC32), "S_GPROC32");
199    assert_eq!(format!("{:?}", SymKind(0x31aa)), "S_(??31aa 1_)");
200}
201
202impl SymKind {
203    /// True if this `SymKind` starts a scope. All symbols that start a block begin with
204    /// [`BlockHeader`].
205    pub fn starts_scope(self) -> bool {
206        matches!(
207            self,
208            SymKind::S_GPROC32
209                | SymKind::S_LPROC32
210                | SymKind::S_LPROC32_DPC
211                | SymKind::S_LPROC32_DPC_ID
212                | SymKind::S_GPROC32_ID
213                | SymKind::S_BLOCK32
214                | SymKind::S_THUNK32
215                | SymKind::S_INLINESITE
216                | SymKind::S_INLINESITE2
217                | SymKind::S_SEPCODE
218                | SymKind::S_GMANPROC
219                | SymKind::S_LMANPROC
220        )
221    }
222
223    /// True if this `SymKind` is a procedure definition.
224    pub fn is_proc(self) -> bool {
225        matches!(
226            self,
227            SymKind::S_GPROC32
228                | SymKind::S_GPROC32_ID
229                | SymKind::S_GPROC32_ST
230                | SymKind::S_LPROC32
231                | SymKind::S_LPROC32_DPC
232                | SymKind::S_LPROC32_DPC_ID
233                | SymKind::S_LPROC32_ID
234                | SymKind::S_LPROC32_ST
235        )
236    }
237
238    /// Indicates whether this `SymKind` ends a scope.
239    ///
240    /// There are no `SymKind` values that both start and end a scope.
241    ///
242    /// In all well-formed symbol streams, every symbol that starts a scope has a matching symbol
243    /// that ends that scope.
244    pub fn ends_scope(self) -> bool {
245        matches!(
246            self,
247            SymKind::S_END | SymKind::S_PROC_ID_END | SymKind::S_INLINESITE_END
248        )
249    }
250
251    /// Returns `true` if this symbol can be the _target_ of a "reference to symbol" in the
252    /// Global Symbol Stream.
253    pub fn is_refsym_target(self) -> bool {
254        matches!(
255            self,
256            SymKind::S_GPROC32
257                | SymKind::S_LPROC32
258                | SymKind::S_GMANPROC
259                | SymKind::S_LMANPROC
260                | SymKind::S_GDATA32
261                | SymKind::S_LDATA32
262                | SymKind::S_ANNOTATION
263        )
264    }
265
266    /// Returns `true` if this symbol can be the _source_ of a "reference to symbol"
267    /// in the Global Symbol Stream.
268    pub fn is_refsym_source(self) -> bool {
269        matches!(
270            self,
271            SymKind::S_LPROCREF
272                | SymKind::S_PROCREF
273                | SymKind::S_ANNOTATIONREF
274                | SymKind::S_TOKENREF
275                | SymKind::S_DATAREF
276        )
277    }
278}