1pub mod schema;
4pub mod visit;
5
6use crate::schema::{
7 ArchivedArchitecture, ArchivedArray, ArchivedBase, ArchivedBitfield, ArchivedEnum,
8 ArchivedEnumRef, ArchivedField, ArchivedPointer, ArchivedProfile, ArchivedStruct,
9 ArchivedStructKind, ArchivedStructRef, ArchivedType, ArchivedVariant,
10};
11
12pub struct Profile<'a> {
14 inner: &'a ArchivedProfile,
15 rva_to_symbol: Vec<Symbol<'a>>,
16}
17
18#[derive(Debug, Clone, Copy)]
20pub struct Symbol<'a> {
21 pub name: &'a str,
23
24 pub rva: u64,
26}
27
28impl<'a> Profile<'a> {
29 pub fn from_archived(archived: &'a ArchivedProfile) -> Self {
31 let mut rva_to_symbol = archived
32 .symbols
33 .iter()
34 .map(|(name, &rva)| Symbol {
35 name: name.as_ref(),
36 rva: rva.into(),
37 })
38 .collect::<Vec<_>>();
39 rva_to_symbol.sort_unstable_by_key(|entry| entry.rva);
40
41 Self {
42 inner: archived,
43 rva_to_symbol,
44 }
45 }
46
47 pub fn architecture(&self) -> Architecture {
49 Architecture::from_archived(&self.inner.architecture)
50 }
51
52 pub fn enums(&self) -> impl ExactSizeIterator<Item = Enum<'a>> {
54 self.inner.enums.iter().map(|(name, inner)| Enum {
55 name: name.as_ref(),
56 inner,
57 })
58 }
59
60 pub fn structs(&self) -> impl ExactSizeIterator<Item = Struct<'a>> {
62 self.inner.structs.iter().map(|(name, inner)| Struct {
63 name: name.as_ref(),
64 inner,
65 })
66 }
67
68 pub fn symbols(&self) -> impl ExactSizeIterator<Item = Symbol<'a>> {
70 self.inner.symbols.iter().map(|(name, &rva)| Symbol {
71 name: name.as_ref(),
72 rva: rva.into(),
73 })
74 }
75 pub fn type_size(&self, ty: Type<'a>) -> Option<u64> {
77 match ty {
78 Type::Base(v) => Some(v.size()),
79 Type::Enum(v) => self.enum_size(v.name()),
80 Type::Struct(v) => self.struct_size(v.name()),
81 Type::Array(v) => self
82 .type_size(v.subtype())
83 .map(|subtype_size| subtype_size * v.dims().product::<u64>()),
84 Type::Pointer(v) => Some(v.size()),
85 Type::Bitfield(v) => self.type_size(v.subtype()),
86 Type::Function => Some(self.pointer_size()),
87 }
88 }
89
90 pub fn enum_size(&self, name: &str) -> Option<u64> {
92 let ty = Type::from_archived(&self.inner.enums.get(name)?.subtype);
93 self.type_size(ty)
94 }
95
96 pub fn struct_size(&self, name: &str) -> Option<u64> {
98 self.inner.structs.get(name).map(|udt| udt.size.into())
99 }
100
101 pub fn pointer_size(&self) -> u64 {
103 match self.architecture() {
104 Architecture::X86 | Architecture::Arm32 => 4,
105 Architecture::Amd64 | Architecture::Arm64 => 8,
106 Architecture::Unknown => 0,
107 }
108 }
109
110 pub fn find_enum(&self, type_name: &str) -> Option<Enum<'a>> {
112 self.inner
113 .enums
114 .get_key_value(type_name)
115 .map(|(name, inner)| Enum {
116 name: name.as_ref(),
117 inner,
118 })
119 }
120
121 pub fn find_struct(&self, type_name: &str) -> Option<Struct<'a>> {
123 self.inner
124 .structs
125 .get_key_value(type_name)
126 .map(|(name, inner)| Struct {
127 name: name.as_ref(),
128 inner,
129 })
130 }
131
132 pub fn find_symbol(&self, symbol_name: &str) -> Option<u64> {
134 self.inner.symbols.get(symbol_name).map(Into::into)
135 }
136
137 pub fn lookup_symbol(&self, rva: u64) -> Option<Symbol<'a>> {
141 let idx = match self.rva_to_symbol.binary_search_by_key(&rva, |e| e.rva) {
142 Ok(i) => i,
143 Err(0) => return None,
144 Err(i) => i - 1,
145 };
146
147 Some(self.rva_to_symbol[idx])
148 }
149}
150
151#[allow(missing_docs)]
153#[derive(Debug, Clone, Copy, PartialEq, Eq)]
154pub enum Architecture {
155 Unknown,
156 X86,
157 Amd64,
158 Arm32,
159 Arm64,
160}
161
162impl Architecture {
163 fn from_archived(value: &ArchivedArchitecture) -> Self {
164 match value {
165 ArchivedArchitecture::Unknown => Self::Unknown,
166 ArchivedArchitecture::X86 => Self::X86,
167 ArchivedArchitecture::Amd64 => Self::Amd64,
168 ArchivedArchitecture::Arm32 => Self::Arm32,
169 ArchivedArchitecture::Arm64 => Self::Arm64,
170 }
171 }
172}
173
174#[derive(Debug, Clone, Copy)]
176pub struct Enum<'a> {
177 name: &'a str,
178 inner: &'a ArchivedEnum,
179}
180
181impl<'a> Enum<'a> {
182 pub fn name(&self) -> &'a str {
184 self.name
185 }
186
187 pub fn subtype(&self) -> Type<'a> {
189 Type::from_archived(&self.inner.subtype)
190 }
191
192 pub fn fields(&self) -> impl ExactSizeIterator<Item = (&'a str, Variant)> {
194 self.inner
195 .fields
196 .iter()
197 .map(|(name, variant)| (name.as_ref(), Variant::from_archived(variant)))
198 }
199}
200
201#[allow(missing_docs)]
203#[derive(Debug, Clone, Copy, PartialEq, Eq)]
204pub enum Variant {
205 U8(u8),
206 U16(u16),
207 U32(u32),
208 U64(u64),
209 U128(u128),
210 I8(i8),
211 I16(i16),
212 I32(i32),
213 I64(i64),
214 I128(i128),
215}
216
217impl Variant {
218 fn from_archived(value: &ArchivedVariant) -> Self {
219 match value {
220 ArchivedVariant::U8(v) => Self::U8(*v),
221 ArchivedVariant::U16(v) => Self::U16(v.into()),
222 ArchivedVariant::U32(v) => Self::U32(v.into()),
223 ArchivedVariant::U64(v) => Self::U64(v.into()),
224 ArchivedVariant::U128(v) => Self::U128(v.into()),
225 ArchivedVariant::I8(v) => Self::I8(*v),
226 ArchivedVariant::I16(v) => Self::I16(v.into()),
227 ArchivedVariant::I32(v) => Self::I32(v.into()),
228 ArchivedVariant::I64(v) => Self::I64(v.into()),
229 ArchivedVariant::I128(v) => Self::I128(v.into()),
230 }
231 }
232}
233
234#[derive(Debug, Clone, Copy)]
236pub struct Struct<'a> {
237 name: &'a str,
238 inner: &'a ArchivedStruct,
239}
240
241impl<'a> Struct<'a> {
242 pub fn name(&self) -> &'a str {
244 self.name
245 }
246
247 pub fn kind(&self) -> StructKind {
249 StructKind::from_archived(&self.inner.kind)
250 }
251
252 pub fn size(&self) -> u64 {
254 self.inner.size.into()
255 }
256
257 pub fn field(&self, name: &str) -> Option<Field<'a>> {
259 self.inner
260 .fields
261 .get_key_value(name)
262 .map(|(name, field)| Field {
263 name: name.as_ref(),
264 inner: field,
265 })
266 }
267
268 pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'a>> {
270 self.inner.fields.iter().map(|(name, inner)| Field {
271 name: name.as_ref(),
272 inner,
273 })
274 }
275}
276
277#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
279pub enum StructKind {
280 Struct,
282
283 Class,
285
286 Union,
288
289 Interface,
291}
292
293impl StructKind {
294 fn from_archived(value: &ArchivedStructKind) -> Self {
295 match value {
296 ArchivedStructKind::Struct => Self::Struct,
297 ArchivedStructKind::Class => Self::Class,
298 ArchivedStructKind::Union => Self::Union,
299 ArchivedStructKind::Interface => Self::Interface,
300 }
301 }
302}
303
304#[derive(Debug, Clone, Copy)]
306pub struct Field<'a> {
307 name: &'a str,
308 inner: &'a ArchivedField,
309}
310
311impl<'a> Field<'a> {
312 pub fn name(&self) -> &'a str {
314 self.name
315 }
316
317 pub fn offset(&self) -> u64 {
319 self.inner.offset.into()
320 }
321
322 pub fn ty(&self) -> Type<'a> {
324 Type::from_archived(&self.inner.ty)
325 }
326}
327
328#[derive(Debug, Clone, Copy)]
330pub enum Type<'a> {
331 Base(Base),
333
334 Enum(EnumRef<'a>),
336
337 Struct(StructRef<'a>),
339
340 Array(Array<'a>),
342
343 Pointer(Pointer<'a>),
345
346 Bitfield(Bitfield<'a>),
348
349 Function,
351}
352
353impl<'a> Type<'a> {
354 fn from_archived(value: &'a ArchivedType) -> Self {
355 match value {
356 ArchivedType::Base(inner) => Self::Base(Base::from_archived(inner)),
357 ArchivedType::Enum(inner) => Self::Enum(EnumRef { inner }),
358 ArchivedType::Struct(inner) => Self::Struct(StructRef { inner }),
359 ArchivedType::Array(inner) => Self::Array(Array { inner }),
360 ArchivedType::Pointer(inner) => Self::Pointer(Pointer { inner }),
361 ArchivedType::Bitfield(inner) => Self::Bitfield(Bitfield { inner }),
362 ArchivedType::Function => Self::Function,
363 }
364 }
365}
366
367#[allow(missing_docs)]
369#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
370pub enum Base {
371 Void,
373
374 Bool,
376
377 Char8,
379 Char16,
380 Char32,
381
382 I8,
384 I16,
385 I32,
386 I64,
387 I128,
388
389 U8,
391 U16,
392 U32,
393 U64,
394 U128,
395
396 F8,
398 F16,
399 F32,
400 F64,
401 F128,
402}
403
404impl Base {
405 fn from_archived(value: &ArchivedBase) -> Self {
406 match value {
407 ArchivedBase::Void => Self::Void,
408
409 ArchivedBase::Bool => Self::Bool,
410
411 ArchivedBase::Char8 => Self::Char8,
412 ArchivedBase::Char16 => Self::Char16,
413 ArchivedBase::Char32 => Self::Char32,
414
415 ArchivedBase::I8 => Self::I8,
416 ArchivedBase::I16 => Self::I16,
417 ArchivedBase::I32 => Self::I32,
418 ArchivedBase::I64 => Self::I64,
419 ArchivedBase::I128 => Self::I128,
420
421 ArchivedBase::U8 => Self::U8,
422 ArchivedBase::U16 => Self::U16,
423 ArchivedBase::U32 => Self::U32,
424 ArchivedBase::U64 => Self::U64,
425 ArchivedBase::U128 => Self::U128,
426
427 ArchivedBase::F8 => Self::F8,
428 ArchivedBase::F16 => Self::F16,
429 ArchivedBase::F32 => Self::F32,
430 ArchivedBase::F64 => Self::F64,
431 ArchivedBase::F128 => Self::F128,
432 }
433 }
434
435 pub fn size(&self) -> u64 {
437 match self {
438 Self::Void => 0,
439 Self::Char8 | Self::I8 | Self::U8 | Self::F8 | Self::Bool => 1,
440 Self::Char16 | Self::I16 | Self::U16 | Self::F16 => 2,
441 Self::Char32 | Self::I32 | Self::U32 | Self::F32 => 4,
442 Self::I64 | Self::U64 | Self::F64 => 8,
443 Self::I128 | Self::U128 | Self::F128 => 16,
444 }
445 }
446}
447
448#[derive(Debug, Clone, Copy)]
450pub struct EnumRef<'a> {
451 inner: &'a ArchivedEnumRef,
452}
453
454impl<'a> EnumRef<'a> {
455 pub fn name(&self) -> &'a str {
457 &self.inner.name
458 }
459}
460
461#[derive(Debug, Clone, Copy)]
463pub struct StructRef<'a> {
464 inner: &'a ArchivedStructRef,
465}
466
467impl<'a> StructRef<'a> {
468 pub fn name(&self) -> &'a str {
470 &self.inner.name
471 }
472}
473
474#[derive(Debug, Clone, Copy)]
476pub struct Array<'a> {
477 inner: &'a ArchivedArray,
478}
479
480impl<'a> Array<'a> {
481 pub fn subtype(&self) -> Type<'a> {
483 Type::from_archived(self.inner.subtype.as_ref())
484 }
485
486 pub fn dims(&self) -> impl Iterator<Item = u64> + use<'a> {
488 self.inner.dims.iter().map(|&dim| dim.to_native())
489 }
490}
491
492#[derive(Debug, Clone, Copy)]
494pub struct Bitfield<'a> {
495 inner: &'a ArchivedBitfield,
496}
497
498impl<'a> Bitfield<'a> {
499 pub fn subtype(&self) -> Type<'a> {
501 Type::from_archived(self.inner.subtype.as_ref())
502 }
503
504 pub fn bit_length(&self) -> u64 {
506 self.inner.bit_length.into()
507 }
508
509 pub fn bit_position(&self) -> u64 {
511 self.inner.bit_position.into()
512 }
513}
514
515#[derive(Debug, Clone, Copy)]
517pub struct Pointer<'a> {
518 inner: &'a ArchivedPointer,
519}
520
521impl<'a> Pointer<'a> {
522 pub fn subtype(&self) -> Type<'a> {
524 Type::from_archived(self.inner.subtype.as_ref())
525 }
526
527 pub fn size(&self) -> u64 {
529 self.inner.size.into()
530 }
531}