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}