isr_core/
profile.rs

1use std::borrow::Cow;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    symbols::Symbols,
7    types::{BaseRef, Enum, Struct, Type, Types},
8};
9
10/// Profile.
11///
12/// Contains information about the target architecture, symbols, and types.
13#[derive(Debug, Serialize, Deserialize)]
14pub struct Profile<'a> {
15    /// Target architecture.
16    #[serde(borrow)]
17    architecture: Cow<'a, str>,
18
19    /// Symbols.
20    #[serde(borrow)]
21    symbols: Symbols<'a>,
22
23    /// Types.
24    #[serde(borrow)]
25    types: Types<'a>,
26}
27
28impl<'a> Profile<'a> {
29    /// Creates a new profile.
30    pub fn new(architecture: Cow<'a, str>, symbols: Symbols<'a>, types: Types<'a>) -> Self {
31        Self {
32            architecture,
33            symbols,
34            types,
35        }
36    }
37
38    /// Returns an iterator over the symbols.
39    pub fn symbols(&self) -> impl Iterator<Item = (&str, &u64)> {
40        self.symbols
41            .0
42            .iter()
43            .map(|(name, value)| (name.as_ref(), value))
44    }
45
46    /// Returns the types.
47    pub fn types(&self) -> &Types<'_> {
48        &self.types
49    }
50
51    /// Returns the size of a given type in bytes.
52    pub fn type_size(&self, type_: &Type) -> Option<u64> {
53        match type_ {
54            Type::Base(r) => Some(self.base_size(r)),
55            Type::Enum(r) => self.enum_size(&r.name),
56            Type::Struct(r) => self.struct_size(&r.name),
57            Type::Array(r) => self.type_size(&r.subtype),
58            Type::Pointer(_) => Some(self.pointer_size()),
59            Type::Bitfield(r) => self.type_size(&r.subtype),
60            Type::Function => Some(self.pointer_size()),
61        }
62    }
63
64    /// Returns the size of a base type in bytes.
65    pub fn base_size(&self, base: &BaseRef) -> u64 {
66        match base {
67            BaseRef::Void => 0,
68            BaseRef::Bool | BaseRef::Char | BaseRef::I8 | BaseRef::U8 | BaseRef::F8 => 1,
69            BaseRef::Wchar | BaseRef::I16 | BaseRef::U16 | BaseRef::F16 => 2,
70            BaseRef::I32 | BaseRef::U32 | BaseRef::F32 => 4,
71            BaseRef::I64 | BaseRef::U64 | BaseRef::F64 => 8,
72            BaseRef::I128 | BaseRef::U128 | BaseRef::F128 => 16,
73        }
74    }
75
76    /// Returns the size of an enum type in bytes.
77    pub fn enum_size(&self, name: &str) -> Option<u64> {
78        self.type_size(&self.types.enums.get(name)?.subtype)
79    }
80
81    /// Returns the size of a struct type in bytes.
82    pub fn struct_size(&self, name: &str) -> Option<u64> {
83        self.types.structs.get(name).map(|udt| udt.size)
84    }
85
86    /// Returns the size of a pointer in bytes.
87    pub fn pointer_size(&self) -> u64 {
88        match self.architecture.as_ref() {
89            "X86" | "Arm" => 4,
90            "Amd64" | "Arm64" => 8,
91            _ => panic!("unsupported architecture"),
92        }
93    }
94
95    /// Finds a symbol by name.
96    pub fn find_symbol(&self, symbol_name: &str) -> Option<u64> {
97        self.symbols.0.get(symbol_name).copied()
98    }
99
100    /// Finds an enum by name.
101    pub fn find_enum(&self, type_name: &str) -> Option<&Enum<'_>> {
102        self.types.enums.get(type_name)
103    }
104
105    /// Finds a struct by name.
106    pub fn find_struct(&self, type_name: &str) -> Option<&Struct<'_>> {
107        self.types.structs.get(type_name)
108    }
109}