pdb/tpi/primitive.rs
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
8use crate::common::*;
9use crate::tpi::data::TypeData;
10
11// References for primitive types:
12//
13// cvinfo.h provides an enumeration:
14// https://github.com/Microsoft/microsoft-pdb/blob/082c5290e5aff028ae84e43affa8be717aa7af73/include/cvinfo.h#L328-L750
15//
16// pdbparse.cpp describes them as strings:
17// https://github.com/Microsoft/microsoft-pdb/blob/082c5290e5aff028ae84e43affa8be717aa7af73/pdbdump/pdbdump.cpp#L1896-L1974
18//
19// The most obscure: MSDN Library October 2001 Disk 2 contains a \MSDN\specs.chm file which contains
20// html\S66CD.HTM which actually documents the *format* of the primitive type descriptors rather
21// than just listing them. TypeData::Primitive is designed to model the orthogonal information
22// encoded into the bits of the TypeIndex rather than exploding the matrix like the reference
23// implementations.
24
25/// Represents a primitive type like `void` or `char *`.
26#[derive(Debug, Copy, Clone, PartialEq, Eq)]
27pub struct PrimitiveType {
28 /// The kind of the primitive type.
29 pub kind: PrimitiveKind,
30
31 /// Pointer indirection applied to the primitive type.
32 pub indirection: Option<Indirection>,
33}
34
35/// A simple type.
36#[non_exhaustive]
37#[derive(Debug, Copy, Clone, PartialEq, Eq)]
38pub enum PrimitiveKind {
39 /// Uncharacterized type (no type)
40 NoType,
41
42 /// Void type
43 Void,
44
45 /// Character (byte)
46 Char,
47
48 /// Unsigned character
49 UChar,
50
51 /// "Really a char"
52 RChar,
53
54 /// Wide characters, i.e. 16 bits
55 WChar,
56
57 /// "Really a 16-bit char"
58 RChar16,
59
60 /// "Really a 32-bit char"
61 RChar32,
62
63 /// Signed 8-bit integer
64 I8,
65
66 /// Unsigned 8-bit integer
67 U8,
68
69 /// Signed 16-bit integer
70 Short,
71
72 /// Unsigned 16-bit integer
73 UShort,
74
75 /// Signed 16-bit integer
76 I16,
77
78 /// Unsigned 16-bit integer
79 U16,
80
81 /// Signed 32-bit integer
82 Long,
83
84 /// Unsigned 32-bit inteer
85 ULong,
86
87 /// Signed 32-bit integer
88 I32,
89
90 /// Unsigned 32-bit inteer
91 U32,
92
93 /// Signed 64-bit integer
94 Quad,
95
96 /// Unsigned 64-bit integer
97 UQuad,
98
99 /// Signed 64-bit integer
100 I64,
101
102 /// Unsigned 64-bit integer
103 U64,
104
105 /// Signed 128-bit integer
106 Octa,
107
108 /// Unsigned 128-bit integer
109 UOcta,
110
111 /// Signed 128-bit integer
112 I128,
113
114 /// Unsigned 128-bit integer
115 U128,
116
117 /// 16-bit floating point
118 F16,
119
120 /// 32-bit floating point
121 F32,
122
123 /// 32-bit partial precision floating point
124 F32PP,
125
126 /// 48-bit floating point
127 F48,
128
129 /// 64-bit floating point
130 F64,
131
132 /// 80-bit floating point
133 F80,
134
135 /// 128-bit floating point
136 F128,
137
138 /// 32-bit complex number
139 Complex32,
140
141 /// 64-bit complex number
142 Complex64,
143
144 /// 80-bit complex number
145 Complex80,
146
147 /// 128-bit complex number
148 Complex128,
149
150 /// 8-bit boolean value
151 Bool8,
152
153 /// 16-bit boolean value
154 Bool16,
155
156 /// 32-bit boolean value
157 Bool32,
158
159 /// 16-bit boolean value
160 Bool64,
161
162 /// Windows `HRESULT` error code.
163 ///
164 /// See: <https://docs.microsoft.com/en-us/windows/desktop/seccrypto/common-hresult-values>
165 HRESULT,
166}
167
168/// Pointer mode of primitive types.
169///
170/// This is partially overlapping with [`PointerKind`](crate::PointerKind) for regular pointer type
171/// definitions. While `PointerKind` can specify many more pointer types, including relative
172/// pointers, `Indirection` also contains a 128-bit variant.
173#[derive(Debug, Copy, Clone, PartialEq, Eq)]
174pub enum Indirection {
175 /// 16-bit ("near") pointer.
176 Near16,
177 /// 16:16 far pointer.
178 Far16,
179 /// 16:16 huge pointer.
180 Huge16,
181 /// 32-bit pointer.
182 Near32,
183 /// 48-bit 16:32 pointer.
184 Far32,
185 /// 64-bit near pointer.
186 Near64,
187 /// 128-bit near pointer.
188 Near128,
189}
190
191pub fn type_data_for_primitive(index: TypeIndex) -> Result<TypeData<'static>> {
192 // https://github.com/Microsoft/microsoft-pdb/blob/082c5290e5aff028ae84e43affa8be717aa7af73/include/cvinfo.h#L326-L750
193
194 // primitives live under 0x1000, and we should never reach here for non-primitive indexes
195 assert!(index < TypeIndex(0x1000));
196
197 // indirection is stored in these bits
198 let indirection = match index.0 & 0xf00 {
199 0x000 => None,
200 0x100 => Some(Indirection::Near16),
201 0x200 => Some(Indirection::Far16),
202 0x300 => Some(Indirection::Huge16),
203 0x400 => Some(Indirection::Near32),
204 0x500 => Some(Indirection::Far32),
205 0x600 => Some(Indirection::Near64),
206 0x700 => Some(Indirection::Near128),
207 _ => {
208 return Err(Error::TypeNotFound(index.0));
209 }
210 };
211
212 // primitive types are stored in the lowest octet
213 let kind = match index.0 & 0xff {
214 0x00 => PrimitiveKind::NoType,
215
216 0x03 => PrimitiveKind::Void,
217 0x08 => PrimitiveKind::HRESULT,
218
219 0x10 => PrimitiveKind::Char,
220 0x20 => PrimitiveKind::UChar,
221 0x68 => PrimitiveKind::I8,
222 0x69 => PrimitiveKind::U8,
223
224 0x70 => PrimitiveKind::RChar,
225 0x71 => PrimitiveKind::WChar,
226 0x7a => PrimitiveKind::RChar16,
227 0x7b => PrimitiveKind::RChar32,
228
229 0x11 => PrimitiveKind::Short,
230 0x21 => PrimitiveKind::UShort,
231 0x72 => PrimitiveKind::I16,
232 0x73 => PrimitiveKind::U16,
233
234 0x12 => PrimitiveKind::Long,
235 0x22 => PrimitiveKind::ULong,
236 0x74 => PrimitiveKind::I32,
237 0x75 => PrimitiveKind::U32,
238
239 0x13 => PrimitiveKind::Quad,
240 0x23 => PrimitiveKind::UQuad,
241 0x76 => PrimitiveKind::I64,
242 0x77 => PrimitiveKind::U64,
243
244 0x14 => PrimitiveKind::Octa,
245 0x24 => PrimitiveKind::UOcta,
246 0x78 => PrimitiveKind::I128,
247 0x79 => PrimitiveKind::U128,
248
249 0x46 => PrimitiveKind::F16,
250 0x40 => PrimitiveKind::F32,
251 0x45 => PrimitiveKind::F32PP,
252 0x44 => PrimitiveKind::F48,
253 0x41 => PrimitiveKind::F64,
254 0x42 => PrimitiveKind::F80,
255 0x43 => PrimitiveKind::F128,
256
257 0x50 => PrimitiveKind::Complex32,
258 0x51 => PrimitiveKind::Complex64,
259 0x52 => PrimitiveKind::Complex80,
260 0x53 => PrimitiveKind::Complex128,
261
262 0x30 => PrimitiveKind::Bool8,
263 0x31 => PrimitiveKind::Bool16,
264 0x32 => PrimitiveKind::Bool32,
265 0x33 => PrimitiveKind::Bool64,
266
267 _ => {
268 return Err(Error::TypeNotFound(index.0));
269 }
270 };
271
272 Ok(TypeData::Primitive(PrimitiveType { kind, indirection }))
273}