1 // Copyright 2017 pdb Developers
2 //
3 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 // http://opensource.org/licenses/MIT>, at your option. This file may not be
6 // copied, modified, or distributed except according to those terms.
7 
8 // A list of known symbol kinds.
9 // from:
10 //  https://github.com/Microsoft/microsoft-pdb/blob/082c5290e5aff028ae84e43affa8be717aa7af73/include/cvinfo.h#L2735
11 
12 #![allow(unused, non_upper_case_globals, non_camel_case_types)]
13 
14 use std::fmt;
15 
16 use scroll::{ctx::TryFromCtx, Endian};
17 
18 pub const S_COMPILE: u16 = 0x0001; // Compile flags symbol
19 pub const S_REGISTER_16t: u16 = 0x0002; // Register variable
20 pub const S_CONSTANT_16t: u16 = 0x0003; // constant symbol
21 pub const S_UDT_16t: u16 = 0x0004; // User defined type
22 pub const S_SSEARCH: u16 = 0x0005; // Start Search
23 pub const S_END: u16 = 0x0006; // Block procedure "with" or thunk end
24 pub const S_SKIP: u16 = 0x0007; // Reserve symbol space in $$Symbols table
25 pub const S_CVRESERVE: u16 = 0x0008; // Reserved symbol for CV internal use
26 pub const S_OBJNAME_ST: u16 = 0x0009; // path to object file name
27 pub const S_ENDARG: u16 = 0x000a; // end of argument/return list
28 pub const S_COBOLUDT_16t: u16 = 0x000b; // special UDT for cobol that does not symbol pack
29 pub const S_MANYREG_16t: u16 = 0x000c; // multiple register variable
30 pub const S_RETURN: u16 = 0x000d; // return description symbol
31 pub const S_ENTRYTHIS: u16 = 0x000e; // description of this pointer on entry
32 
33 pub const S_BPREL16: u16 = 0x0100; // BP-relative
34 pub const S_LDATA16: u16 = 0x0101; // Module-local symbol
35 pub const S_GDATA16: u16 = 0x0102; // Global data symbol
36 pub const S_PUB16: u16 = 0x0103; // a public symbol
37 pub const S_LPROC16: u16 = 0x0104; // Local procedure start
38 pub const S_GPROC16: u16 = 0x0105; // Global procedure start
39 pub const S_THUNK16: u16 = 0x0106; // Thunk Start
40 pub const S_BLOCK16: u16 = 0x0107; // block start
41 pub const S_WITH16: u16 = 0x0108; // with start
42 pub const S_LABEL16: u16 = 0x0109; // code label
43 pub const S_CEXMODEL16: u16 = 0x010a; // change execution model
44 pub const S_VFTABLE16: u16 = 0x010b; // address of virtual function table
45 pub const S_REGREL16: u16 = 0x010c; // register relative address
46 
47 pub const S_BPREL32_16t: u16 = 0x0200; // BP-relative
48 pub const S_LDATA32_16t: u16 = 0x0201; // Module-local symbol
49 pub const S_GDATA32_16t: u16 = 0x0202; // Global data symbol
50 pub const S_PUB32_16t: u16 = 0x0203; // a public symbol (CV internal reserved)
51 pub const S_LPROC32_16t: u16 = 0x0204; // Local procedure start
52 pub const S_GPROC32_16t: u16 = 0x0205; // Global procedure start
53 pub const S_THUNK32_ST: u16 = 0x0206; // Thunk Start
54 pub const S_BLOCK32_ST: u16 = 0x0207; // block start
55 pub const S_WITH32_ST: u16 = 0x0208; // with start
56 pub const S_LABEL32_ST: u16 = 0x0209; // code label
57 pub const S_CEXMODEL32: u16 = 0x020a; // change execution model
58 pub const S_VFTABLE32_16t: u16 = 0x020b; // address of virtual function table
59 pub const S_REGREL32_16t: u16 = 0x020c; // register relative address
60 pub const S_LTHREAD32_16t: u16 = 0x020d; // local thread storage
61 pub const S_GTHREAD32_16t: u16 = 0x020e; // global thread storage
62 pub const S_SLINK32: u16 = 0x020f; // static link for MIPS EH implementation
63 
64 pub const S_LPROCMIPS_16t: u16 = 0x0300; // Local procedure start
65 pub const S_GPROCMIPS_16t: u16 = 0x0301; // Global procedure start
66 
67 // if these ref symbols have names following then the names are in ST format
68 pub const S_PROCREF_ST: u16 = 0x0400; // Reference to a procedure
69 pub const S_DATAREF_ST: u16 = 0x0401; // Reference to data
70 pub const S_ALIGN: u16 = 0x0402; // Used for page alignment of symbols
71 
72 pub const S_LPROCREF_ST: u16 = 0x0403; // Local Reference to a procedure
73 pub const S_OEM: u16 = 0x0404; // OEM defined symbol
74 
75 // sym records with 32-bit types embedded instead of 16-bit
76 // all have 0x1000 bit set for easy identification
77 // only do the 32-bit target versions since we don't really
78 // care about 16-bit ones anymore.
79 pub const S_TI16_MAX: u16 = 0x1000;
80 
81 pub const S_REGISTER_ST: u16 = 0x1001; // Register variable
82 pub const S_CONSTANT_ST: u16 = 0x1002; // constant symbol
83 pub const S_UDT_ST: u16 = 0x1003; // User defined type
84 pub const S_COBOLUDT_ST: u16 = 0x1004; // special UDT for cobol that does not symbol pack
85 pub const S_MANYREG_ST: u16 = 0x1005; // multiple register variable
86 pub const S_BPREL32_ST: u16 = 0x1006; // BP-relative
87 pub const S_LDATA32_ST: u16 = 0x1007; // Module-local symbol
88 pub const S_GDATA32_ST: u16 = 0x1008; // Global data symbol
89 pub const S_PUB32_ST: u16 = 0x1009; // a public symbol (CV internal reserved)
90 pub const S_LPROC32_ST: u16 = 0x100a; // Local procedure start
91 pub const S_GPROC32_ST: u16 = 0x100b; // Global procedure start
92 pub const S_VFTABLE32: u16 = 0x100c; // address of virtual function table
93 pub const S_REGREL32_ST: u16 = 0x100d; // register relative address
94 pub const S_LTHREAD32_ST: u16 = 0x100e; // local thread storage
95 pub const S_GTHREAD32_ST: u16 = 0x100f; // global thread storage
96 
97 pub const S_LPROCMIPS_ST: u16 = 0x1010; // Local procedure start
98 pub const S_GPROCMIPS_ST: u16 = 0x1011; // Global procedure start
99 
100 pub const S_FRAMEPROC: u16 = 0x1012; // extra frame and proc information
101 pub const S_COMPILE2_ST: u16 = 0x1013; // extended compile flags and info
102 
103 // new symbols necessary for 16-bit enumerates of IA64 registers
104 // and IA64 specific symbols
105 
106 pub const S_MANYREG2_ST: u16 = 0x1014; // multiple register variable
107 pub const S_LPROCIA64_ST: u16 = 0x1015; // Local procedure start (IA64)
108 pub const S_GPROCIA64_ST: u16 = 0x1016; // Global procedure start (IA64)
109 
110 // Local symbols for IL
111 pub const S_LOCALSLOT_ST: u16 = 0x1017; // local IL sym with field for local slot index
112 pub const S_PARAMSLOT_ST: u16 = 0x1018; // local IL sym with field for parameter slot index
113 
114 pub const S_ANNOTATION: u16 = 0x1019; // Annotation string literals
115 
116 // symbols to support managed code debugging
117 pub const S_GMANPROC_ST: u16 = 0x101a; // Global proc
118 pub const S_LMANPROC_ST: u16 = 0x101b; // Local proc
119 pub const S_RESERVED1: u16 = 0x101c; // reserved
120 pub const S_RESERVED2: u16 = 0x101d; // reserved
121 pub const S_RESERVED3: u16 = 0x101e; // reserved
122 pub const S_RESERVED4: u16 = 0x101f; // reserved
123 pub const S_LMANDATA_ST: u16 = 0x1020;
124 pub const S_GMANDATA_ST: u16 = 0x1021;
125 pub const S_MANFRAMEREL_ST: u16 = 0x1022;
126 pub const S_MANREGISTER_ST: u16 = 0x1023;
127 pub const S_MANSLOT_ST: u16 = 0x1024;
128 pub const S_MANMANYREG_ST: u16 = 0x1025;
129 pub const S_MANREGREL_ST: u16 = 0x1026;
130 pub const S_MANMANYREG2_ST: u16 = 0x1027;
131 pub const S_MANTYPREF: u16 = 0x1028; // Index for type referenced by name from metadata
132 pub const S_UNAMESPACE_ST: u16 = 0x1029; // Using namespace
133 
134 // Symbols w/ SZ name fields. All name fields contain utf8 encoded strings.
135 pub const S_ST_MAX: u16 = 0x1100; // starting point for SZ name symbols
136 
137 pub const S_OBJNAME: u16 = 0x1101; // path to object file name
138 pub const S_THUNK32: u16 = 0x1102; // Thunk Start
139 pub const S_BLOCK32: u16 = 0x1103; // block start
140 pub const S_WITH32: u16 = 0x1104; // with start
141 pub const S_LABEL32: u16 = 0x1105; // code label
142 pub const S_REGISTER: u16 = 0x1106; // Register variable
143 pub const S_CONSTANT: u16 = 0x1107; // constant symbol
144 pub const S_UDT: u16 = 0x1108; // User defined type
145 pub const S_COBOLUDT: u16 = 0x1109; // special UDT for cobol that does not symbol pack
146 pub const S_MANYREG: u16 = 0x110a; // multiple register variable
147 pub const S_BPREL32: u16 = 0x110b; // BP-relative
148 pub const S_LDATA32: u16 = 0x110c; // Module-local symbol
149 pub const S_GDATA32: u16 = 0x110d; // Global data symbol
150 pub const S_PUB32: u16 = 0x110e; // a public symbol (CV internal reserved)
151 pub const S_LPROC32: u16 = 0x110f; // Local procedure start
152 pub const S_GPROC32: u16 = 0x1110; // Global procedure start
153 pub const S_REGREL32: u16 = 0x1111; // register relative address
154 pub const S_LTHREAD32: u16 = 0x1112; // local thread storage
155 pub const S_GTHREAD32: u16 = 0x1113; // global thread storage
156 
157 pub const S_LPROCMIPS: u16 = 0x1114; // Local procedure start
158 pub const S_GPROCMIPS: u16 = 0x1115; // Global procedure start
159 pub const S_COMPILE2: u16 = 0x1116; // extended compile flags and info
160 pub const S_MANYREG2: u16 = 0x1117; // multiple register variable
161 pub const S_LPROCIA64: u16 = 0x1118; // Local procedure start (IA64)
162 pub const S_GPROCIA64: u16 = 0x1119; // Global procedure start (IA64)
163 pub const S_LOCALSLOT: u16 = 0x111a; // local IL sym with field for local slot index
164 pub const S_PARAMSLOT: u16 = 0x111b; // local IL sym with field for parameter slot index
165 
166 // symbols to support managed code debugging
167 pub const S_LMANDATA: u16 = 0x111c;
168 pub const S_GMANDATA: u16 = 0x111d;
169 pub const S_MANFRAMEREL: u16 = 0x111e;
170 pub const S_MANREGISTER: u16 = 0x111f;
171 pub const S_MANSLOT: u16 = 0x1120;
172 pub const S_MANMANYREG: u16 = 0x1121;
173 pub const S_MANREGREL: u16 = 0x1122;
174 pub const S_MANMANYREG2: u16 = 0x1123;
175 pub const S_UNAMESPACE: u16 = 0x1124; // Using namespace
176 
177 // ref symbols with name fields
178 pub const S_PROCREF: u16 = 0x1125; // Reference to a procedure
179 pub const S_DATAREF: u16 = 0x1126; // Reference to data
180 pub const S_LPROCREF: u16 = 0x1127; // Local Reference to a procedure
181 pub const S_ANNOTATIONREF: u16 = 0x1128; // Reference to an S_ANNOTATION symbol
182 pub const S_TOKENREF: u16 = 0x1129; // Reference to one of the many MANPROCSYM's
183 
184 // continuation of managed symbols
185 pub const S_GMANPROC: u16 = 0x112a; // Global proc
186 pub const S_LMANPROC: u16 = 0x112b; // Local proc
187 
188 // short light-weight thunks
189 pub const S_TRAMPOLINE: u16 = 0x112c; // trampoline thunks
190 pub const S_MANCONSTANT: u16 = 0x112d; // constants with metadata type info
191 
192 // native attributed local/parms
193 pub const S_ATTR_FRAMEREL: u16 = 0x112e; // relative to virtual frame ptr
194 pub const S_ATTR_REGISTER: u16 = 0x112f; // stored in a register
195 pub const S_ATTR_REGREL: u16 = 0x1130; // relative to register (alternate frame ptr)
196 pub const S_ATTR_MANYREG: u16 = 0x1131; // stored in >1 register
197 
198 // Separated code (from the compiler) support
199 pub const S_SEPCODE: u16 = 0x1132;
200 
201 pub const S_LOCAL_2005: u16 = 0x1133; // defines a local symbol in optimized code
202 pub const S_DEFRANGE_2005: u16 = 0x1134; // defines a single range of addresses in which symbol can be evaluated
203 pub const S_DEFRANGE2_2005: u16 = 0x1135; // defines ranges of addresses in which symbol can be evaluated
204 
205 pub const S_SECTION: u16 = 0x1136; // A COFF section in a PE executable
206 pub const S_COFFGROUP: u16 = 0x1137; // A COFF group
207 pub const S_EXPORT: u16 = 0x1138; // A export
208 
209 pub const S_CALLSITEINFO: u16 = 0x1139; // Indirect call site information
210 pub const S_FRAMECOOKIE: u16 = 0x113a; // Security cookie information
211 
212 pub const S_DISCARDED: u16 = 0x113b; // Discarded by LINK /OPT:REF (experimental see richards)
213 
214 pub const S_COMPILE3: u16 = 0x113c; // Replacement for S_COMPILE2
215 pub const S_ENVBLOCK: u16 = 0x113d; // Environment block split off from S_COMPILE2
216 
217 pub const S_LOCAL: u16 = 0x113e; // defines a local symbol in optimized code
218 pub const S_DEFRANGE: u16 = 0x113f; // defines a single range of addresses in which symbol can be evaluated
219 pub const S_DEFRANGE_SUBFIELD: u16 = 0x1140; // ranges for a subfield
220 
221 pub const S_DEFRANGE_REGISTER: u16 = 0x1141; // ranges for en-registered symbol
222 pub const S_DEFRANGE_FRAMEPOINTER_REL: u16 = 0x1142; // range for stack symbol.
223 pub const S_DEFRANGE_SUBFIELD_REGISTER: u16 = 0x1143; // ranges for en-registered field of symbol
224 pub const S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: u16 = 0x1144; // range for stack symbol span valid full scope of function body gap might apply.
225 pub const S_DEFRANGE_REGISTER_REL: u16 = 0x1145; // range for symbol address as register + offset.
226 
227 // S_PROC symbols that reference ID instead of type
228 pub const S_LPROC32_ID: u16 = 0x1146;
229 pub const S_GPROC32_ID: u16 = 0x1147;
230 pub const S_LPROCMIPS_ID: u16 = 0x1148;
231 pub const S_GPROCMIPS_ID: u16 = 0x1149;
232 pub const S_LPROCIA64_ID: u16 = 0x114a;
233 pub const S_GPROCIA64_ID: u16 = 0x114b;
234 
235 pub const S_BUILDINFO: u16 = 0x114c; // build information.
236 pub const S_INLINESITE: u16 = 0x114d; // inlined function callsite.
237 pub const S_INLINESITE_END: u16 = 0x114e;
238 pub const S_PROC_ID_END: u16 = 0x114f;
239 
240 pub const S_DEFRANGE_HLSL: u16 = 0x1150;
241 pub const S_GDATA_HLSL: u16 = 0x1151;
242 pub const S_LDATA_HLSL: u16 = 0x1152;
243 
244 pub const S_FILESTATIC: u16 = 0x1153;
245 
246 pub const S_LOCAL_DPC_GROUPSHARED: u16 = 0x1154; // DPC groupshared variable
247 pub const S_LPROC32_DPC: u16 = 0x1155; // DPC local procedure start
248 pub const S_LPROC32_DPC_ID: u16 = 0x1156;
249 pub const S_DEFRANGE_DPC_PTR_TAG: u16 = 0x1157; // DPC pointer tag definition range
250 pub const S_DPC_SYM_TAG_MAP: u16 = 0x1158; // DPC pointer tag value to symbol record map
251 
252 pub const S_ARMSWITCHTABLE: u16 = 0x1159;
253 pub const S_CALLEES: u16 = 0x115a;
254 pub const S_CALLERS: u16 = 0x115b;
255 pub const S_POGODATA: u16 = 0x115c;
256 pub const S_INLINESITE2: u16 = 0x115d; // extended inline site information
257 
258 pub const S_HEAPALLOCSITE: u16 = 0x115e; // heap allocation site
259 
260 pub const S_MOD_TYPEREF: u16 = 0x115f; // only generated at link time
261 
262 pub const S_REF_MINIPDB: u16 = 0x1160; // only generated at link time for mini PDB
263 pub const S_PDBMAP: u16 = 0x1161; // only generated at link time for mini PDB
264 
265 pub const S_GDATA_HLSL32: u16 = 0x1162;
266 pub const S_LDATA_HLSL32: u16 = 0x1163;
267 
268 pub const S_GDATA_HLSL32_EX: u16 = 0x1164;
269 pub const S_LDATA_HLSL32_EX: u16 = 0x1165;
270 
271 /// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented
272 /// [on MSDN](https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx).
273 #[non_exhaustive]
274 #[allow(missing_docs)]
275 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
276 pub enum CPUType {
277     Intel8080 = 0x0,
278     Intel8086 = 0x1,
279     Intel80286 = 0x2,
280     Intel80386 = 0x3,
281     Intel80486 = 0x4,
282     Pentium = 0x5,
283     PentiumPro = 0x6,
284     Pentium3 = 0x7,
285     MIPS = 0x10,
286     MIPS16 = 0x11,
287     MIPS32 = 0x12,
288     MIPS64 = 0x13,
289     MIPSI = 0x14,
290     MIPSII = 0x15,
291     MIPSIII = 0x16,
292     MIPSIV = 0x17,
293     MIPSV = 0x18,
294     M68000 = 0x20,
295     M68010 = 0x21,
296     M68020 = 0x22,
297     M68030 = 0x23,
298     M68040 = 0x24,
299     Alpha = 0x30,
300     Alpha21164 = 0x31,
301     Alpha21164A = 0x32,
302     Alpha21264 = 0x33,
303     Alpha21364 = 0x34,
304     PPC601 = 0x40,
305     PPC603 = 0x41,
306     PPC604 = 0x42,
307     PPC620 = 0x43,
308     PPCFP = 0x44,
309     PPCBE = 0x45,
310     SH3 = 0x50,
311     SH3E = 0x51,
312     SH3DSP = 0x52,
313     SH4 = 0x53,
314     SHMedia = 0x54,
315     ARM3 = 0x60,
316     ARM4 = 0x61,
317     ARM4T = 0x62,
318     ARM5 = 0x63,
319     ARM5T = 0x64,
320     ARM6 = 0x65,
321     ARM_XMAC = 0x66,
322     ARM_WMMX = 0x67,
323     ARM7 = 0x68,
324     ARM64 = 0x69,
325     Omni = 0x70,
326     Ia64 = 0x80,
327     Ia64_2 = 0x81,
328     CEE = 0x90,
329     AM33 = 0xa0,
330     M32R = 0xb0,
331     TriCore = 0xc0,
332     X64 = 0xd0,
333     EBC = 0xe0,
334     Thumb = 0xf0,
335     ARMNT = 0xf4,
336     D3D11_Shader = 0x100,
337 }
338 
339 impl fmt::Display for CPUType {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result340     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341         match *self {
342             CPUType::Intel8080 => write!(f, "Intel8080"),
343             CPUType::Intel8086 => write!(f, "Intel8086"),
344             CPUType::Intel80286 => write!(f, "Intel80286"),
345             CPUType::Intel80386 => write!(f, "Intel80386"),
346             CPUType::Intel80486 => write!(f, "Intel80486"),
347             CPUType::Pentium => write!(f, "Pentium"),
348             CPUType::PentiumPro => write!(f, "PentiumPro"),
349             CPUType::Pentium3 => write!(f, "Pentium3"),
350             CPUType::MIPS => write!(f, "MIPS"),
351             CPUType::MIPS16 => write!(f, "MIPS16"),
352             CPUType::MIPS32 => write!(f, "MIPS32"),
353             CPUType::MIPS64 => write!(f, "MIPS64"),
354             CPUType::MIPSI => write!(f, "MIPSI"),
355             CPUType::MIPSII => write!(f, "MIPSII"),
356             CPUType::MIPSIII => write!(f, "MIPSIII"),
357             CPUType::MIPSIV => write!(f, "MIPSIV"),
358             CPUType::MIPSV => write!(f, "MIPSV"),
359             CPUType::M68000 => write!(f, "M68000"),
360             CPUType::M68010 => write!(f, "M68010"),
361             CPUType::M68020 => write!(f, "M68020"),
362             CPUType::M68030 => write!(f, "M68030"),
363             CPUType::M68040 => write!(f, "M68040"),
364             CPUType::Alpha => write!(f, "Alpha"),
365             CPUType::Alpha21164 => write!(f, "Alpha21164"),
366             CPUType::Alpha21164A => write!(f, "Alpha21164A"),
367             CPUType::Alpha21264 => write!(f, "Alpha21264"),
368             CPUType::Alpha21364 => write!(f, "Alpha21364"),
369             CPUType::PPC601 => write!(f, "PPC601"),
370             CPUType::PPC603 => write!(f, "PPC603"),
371             CPUType::PPC604 => write!(f, "PPC604"),
372             CPUType::PPC620 => write!(f, "PPC620"),
373             CPUType::PPCFP => write!(f, "PPCFP"),
374             CPUType::PPCBE => write!(f, "PPCBE"),
375             CPUType::SH3 => write!(f, "SH3"),
376             CPUType::SH3E => write!(f, "SH3E"),
377             CPUType::SH3DSP => write!(f, "SH3DSP"),
378             CPUType::SH4 => write!(f, "SH4"),
379             CPUType::SHMedia => write!(f, "SHMedia"),
380             CPUType::ARM3 => write!(f, "ARM3"),
381             CPUType::ARM4 => write!(f, "ARM4"),
382             CPUType::ARM4T => write!(f, "ARM4T"),
383             CPUType::ARM5 => write!(f, "ARM5"),
384             CPUType::ARM5T => write!(f, "ARM5T"),
385             CPUType::ARM6 => write!(f, "ARM6"),
386             CPUType::ARM_XMAC => write!(f, "ARM_XMAC"),
387             CPUType::ARM_WMMX => write!(f, "ARM_WMMX"),
388             CPUType::ARM7 => write!(f, "ARM7"),
389             CPUType::ARM64 => write!(f, "ARM64"),
390             CPUType::Omni => write!(f, "Omni"),
391             CPUType::Ia64 => write!(f, "Ia64"),
392             CPUType::Ia64_2 => write!(f, "Ia64_2"),
393             CPUType::CEE => write!(f, "CEE"),
394             CPUType::AM33 => write!(f, "AM33"),
395             CPUType::M32R => write!(f, "M32R"),
396             CPUType::TriCore => write!(f, "TriCore"),
397             CPUType::X64 => write!(f, "X64"),
398             CPUType::EBC => write!(f, "EBC"),
399             CPUType::Thumb => write!(f, "Thumb"),
400             CPUType::ARMNT => write!(f, "ARMNT"),
401             CPUType::D3D11_Shader => write!(f, "D3D11_Shader"),
402         }
403     }
404 }
405 
406 impl From<u16> for CPUType {
from(value: u16) -> Self407     fn from(value: u16) -> Self {
408         match value {
409             0x0 => CPUType::Intel8080,
410             0x1 => CPUType::Intel8086,
411             0x2 => CPUType::Intel80286,
412             0x3 => CPUType::Intel80386,
413             0x4 => CPUType::Intel80486,
414             0x5 => CPUType::Pentium,
415             0x6 => CPUType::PentiumPro,
416             0x7 => CPUType::Pentium3,
417             0x10 => CPUType::MIPS,
418             0x11 => CPUType::MIPS16,
419             0x12 => CPUType::MIPS32,
420             0x13 => CPUType::MIPS64,
421             0x14 => CPUType::MIPSI,
422             0x15 => CPUType::MIPSII,
423             0x16 => CPUType::MIPSIII,
424             0x17 => CPUType::MIPSIV,
425             0x18 => CPUType::MIPSV,
426             0x20 => CPUType::M68000,
427             0x21 => CPUType::M68010,
428             0x22 => CPUType::M68020,
429             0x23 => CPUType::M68030,
430             0x24 => CPUType::M68040,
431             0x30 => CPUType::Alpha,
432             0x31 => CPUType::Alpha21164,
433             0x32 => CPUType::Alpha21164A,
434             0x33 => CPUType::Alpha21264,
435             0x34 => CPUType::Alpha21364,
436             0x40 => CPUType::PPC601,
437             0x41 => CPUType::PPC603,
438             0x42 => CPUType::PPC604,
439             0x43 => CPUType::PPC620,
440             0x44 => CPUType::PPCFP,
441             0x45 => CPUType::PPCBE,
442             0x50 => CPUType::SH3,
443             0x51 => CPUType::SH3E,
444             0x52 => CPUType::SH3DSP,
445             0x53 => CPUType::SH4,
446             0x54 => CPUType::SHMedia,
447             0x60 => CPUType::ARM3,
448             0x61 => CPUType::ARM4,
449             0x62 => CPUType::ARM4T,
450             0x63 => CPUType::ARM5,
451             0x64 => CPUType::ARM5T,
452             0x65 => CPUType::ARM6,
453             0x66 => CPUType::ARM_XMAC,
454             0x67 => CPUType::ARM_WMMX,
455             0x68 => CPUType::ARM7,
456             0x69 => CPUType::ARM64,
457             0x70 => CPUType::Omni,
458             0x80 => CPUType::Ia64,
459             0x81 => CPUType::Ia64_2,
460             0x90 => CPUType::CEE,
461             0xa0 => CPUType::AM33,
462             0xb0 => CPUType::M32R,
463             0xc0 => CPUType::TriCore,
464             0xd0 => CPUType::X64,
465             0xe0 => CPUType::EBC,
466             0xf0 => CPUType::Thumb,
467             0xf4 => CPUType::ARMNT,
468             0x100 => CPUType::D3D11_Shader,
469             _ => CPUType::Intel8080, // This enum doesn't have an unknown value, so we just force it to Intel8080 since it's 0x0.
470         }
471     }
472 }
473 
474 impl<'a> TryFromCtx<'a, Endian> for CPUType {
475     type Error = scroll::Error;
476 
try_from_ctx(this: &'a [u8], le: Endian) -> scroll::Result<(Self, usize)>477     fn try_from_ctx(this: &'a [u8], le: Endian) -> scroll::Result<(Self, usize)> {
478         u16::try_from_ctx(this, le).map(|(v, l)| (v.into(), l))
479     }
480 }
481 
482 /// These values correspond to the CV_CFL_LANG enumeration, and are documented
483 /// [on MSDN](https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx).
484 #[non_exhaustive]
485 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
486 pub enum SourceLanguage {
487     /// Application language is C.
488     C = 0x00,
489     /// Application language is C++.
490     Cpp = 0x01,
491     /// Application language is FORTRAN.
492     Fortran = 0x02,
493     /// Application language is Microsoft Macro Assembler.
494     Masm = 0x03,
495     /// Application language is Pascal.
496     Pascal = 0x04,
497     /// Application language is BASIC.
498     Basic = 0x05,
499     /// Application language is COBOL.
500     Cobol = 0x06,
501     /// Application is a linker-generated module.
502     Link = 0x07,
503     /// Application is a resource module converted with CVTRES tool.
504     Cvtres = 0x08,
505     /// Application is a POGO optimized module generated with CVTPGD tool.
506     Cvtpgd = 0x09,
507     /// Application language is C#.
508     CSharp = 0x0a,
509     /// Application language is Visual Basic.
510     VB = 0x0b,
511     /// Application language is intermediate language assembly (that is, Common Language Runtime
512     /// (CLR) assembly).
513     ILAsm = 0x0c,
514     /// Application language is Java.
515     Java = 0x0d,
516     /// Application language is Jscript.
517     JScript = 0x0e,
518     /// Application language is an unknown Microsoft Intermediate Language (MSIL), possibly a result
519     /// of using the [/LTCG (Link-time Code
520     /// Generation)](https://docs.microsoft.com/en-us/cpp/build/reference/ltcg-link-time-code-generation)
521     /// switch.
522     MSIL = 0x0f,
523     /// Application language is High Level Shader Language.
524     HLSL = 0x10,
525 
526     /// The DMD compiler emits 'D' for the CV source language. Microsoft doesn't
527     /// have an enumerator for it yet.
528     D = 0x44,
529 }
530 
531 impl fmt::Display for SourceLanguage {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result532     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
533         match *self {
534             SourceLanguage::C => write!(f, "C"),
535             SourceLanguage::Cpp => write!(f, "Cpp"),
536             SourceLanguage::Fortran => write!(f, "Fortran"),
537             SourceLanguage::Masm => write!(f, "Masm"),
538             SourceLanguage::Pascal => write!(f, "Pascal"),
539             SourceLanguage::Basic => write!(f, "Basic"),
540             SourceLanguage::Cobol => write!(f, "Cobol"),
541             SourceLanguage::Link => write!(f, "Link"),
542             SourceLanguage::Cvtres => write!(f, "Cvtres"),
543             SourceLanguage::Cvtpgd => write!(f, "Cvtpgd"),
544             SourceLanguage::CSharp => write!(f, "CSharp"),
545             SourceLanguage::VB => write!(f, "VB"),
546             SourceLanguage::ILAsm => write!(f, "ILAsm"),
547             SourceLanguage::Java => write!(f, "Java"),
548             SourceLanguage::JScript => write!(f, "JScript"),
549             SourceLanguage::MSIL => write!(f, "MSIL"),
550             SourceLanguage::HLSL => write!(f, "HLSL"),
551             SourceLanguage::D => write!(f, "D"),
552         }
553     }
554 }
555 
556 impl From<u8> for SourceLanguage {
from(value: u8) -> Self557     fn from(value: u8) -> Self {
558         match value {
559             0x00 => SourceLanguage::C,
560             0x01 => SourceLanguage::Cpp,
561             0x02 => SourceLanguage::Fortran,
562             0x03 => SourceLanguage::Masm,
563             0x04 => SourceLanguage::Pascal,
564             0x05 => SourceLanguage::Basic,
565             0x06 => SourceLanguage::Cobol,
566             0x07 => SourceLanguage::Link,
567             0x08 => SourceLanguage::Cvtres,
568             0x09 => SourceLanguage::Cvtpgd,
569             0x0a => SourceLanguage::CSharp,
570             0x0b => SourceLanguage::VB,
571             0x0c => SourceLanguage::ILAsm,
572             0x0d => SourceLanguage::Java,
573             0x0e => SourceLanguage::JScript,
574             0x0f => SourceLanguage::MSIL,
575             0x10 => SourceLanguage::HLSL,
576             0x44 => SourceLanguage::D,
577             _ => SourceLanguage::Masm, // There is no unknown, so we just force to Masm as the default.
578         }
579     }
580 }
581 
582 impl<'a> TryFromCtx<'a, Endian> for SourceLanguage {
583     type Error = scroll::Error;
584 
try_from_ctx(this: &'a [u8], le: Endian) -> scroll::Result<(Self, usize)>585     fn try_from_ctx(this: &'a [u8], le: Endian) -> scroll::Result<(Self, usize)> {
586         u8::try_from_ctx(this, le).map(|(v, l)| (v.into(), l))
587     }
588 }
589