sleigh_rs/semantic/inner/
mod.rs

1use std::collections::HashMap;
2
3use crate::semantic::meaning::{AttachLiteral, AttachNumber, AttachVarnode};
4use crate::semantic::{
5    AttachLiteralId, AttachNumberId, AttachVarnodeId, BitrangeId, ContextId,
6    GlobalScope, PcodeMacroId, SpaceId, TableId, TokenFieldId, TokenId,
7    UserFunctionId, VarnodeId,
8};
9use crate::syntax::define::TokenFieldAttribute;
10use crate::{
11    syntax, Endian, NumberNonZeroUnsigned, NumberUnsigned, SleighError, Span,
12    IDENT_EPSILON, IDENT_INSTRUCTION, IDENT_INST_NEXT, IDENT_INST_START,
13};
14
15use super::space::Space;
16use super::token::Token;
17use super::user_function::UserFunction;
18use super::varnode::{Bitrange, Varnode};
19use super::{Epsilon, InstNext, InstStart, PrintBase, ValueFmt};
20
21pub mod attach;
22pub mod disassembly;
23pub mod display;
24pub mod execution;
25pub mod pattern;
26pub mod pcode_macro;
27pub mod space;
28pub mod table;
29pub mod token;
30pub mod varnode;
31pub mod with_block;
32
33use self::execution::FieldSize;
34use self::pattern::Pattern;
35use self::pcode_macro::PcodeMacro;
36use self::table::Table;
37use self::token::TokenField;
38use self::varnode::Context;
39use self::with_block::WithBlockCurrent;
40
41#[derive(Copy, Clone, Debug)]
42pub struct PrintFlags {
43    ///flag if signed was set
44    pub signed_set: bool,
45    ///flag if hex or dec was set
46    pub base: Option<PrintBase>,
47}
48
49impl PrintFlags {
50    pub fn from_token_att<'a>(
51        src: &Span,
52        att: impl Iterator<Item = &'a TokenFieldAttribute>,
53    ) -> Result<Self, SleighError> {
54        let (mut signed_set, mut base) = (false, None);
55        for att in att {
56            use syntax::define::TokenFieldAttribute::*;
57            match att {
58                Hex if base.is_none() => base = Some(PrintBase::Hex),
59                Dec if base.is_none() => base = Some(PrintBase::Dec),
60                Hex | Dec => {
61                    return Err(SleighError::TokenFieldAttachDup(src.clone()))
62                }
63                Signed if !signed_set => signed_set = true,
64                Signed => {
65                    return Err(SleighError::TokenFieldAttDup(src.clone()))
66                }
67            }
68        }
69        Ok(Self { signed_set, base })
70    }
71    pub fn is_set(&self) -> bool {
72        self.signed_set || self.base.is_some()
73    }
74}
75
76impl From<PrintFlags> for ValueFmt {
77    fn from(flags: PrintFlags) -> Self {
78        //if signed is set, this is signed, otherwise is unsigned
79        let signed = flags.signed_set;
80        //use the set base, if unset, use the default: hex
81        let base = flags.base.unwrap_or(PrintBase::Hex);
82        ValueFmt { signed, base }
83    }
84}
85
86pub trait SolverStatus<T: SolverStatus = Self> {
87    fn iam_not_finished_location(
88        &mut self,
89        location: &Span,
90        file: &'static str,
91        line: u32,
92    );
93    fn i_did_a_thing(&mut self);
94    fn we_finished(&self) -> bool;
95    fn we_did_a_thing(&self) -> bool;
96    fn unfinished_locations(&self) -> &[(Span, &'static str, u32)];
97    fn combine(&mut self, other: &Self);
98}
99
100#[derive(Clone, Copy, Debug)]
101pub struct Solved {
102    did_a_thing: bool,
103    finished: bool,
104}
105
106impl SolverStatus for Solved {
107    fn iam_not_finished_location(
108        &mut self,
109        _location: &Span,
110        _file: &'static str,
111        _line: u32,
112    ) {
113        self.finished = false;
114    }
115    fn i_did_a_thing(&mut self) {
116        self.did_a_thing = true;
117    }
118    fn we_finished(&self) -> bool {
119        self.finished
120    }
121    fn we_did_a_thing(&self) -> bool {
122        self.did_a_thing
123    }
124    fn unfinished_locations(&self) -> &[(Span, &'static str, u32)] {
125        &[]
126    }
127    fn combine(&mut self, other: &Self) {
128        self.did_a_thing |= other.we_did_a_thing();
129        self.finished &= other.we_finished();
130    }
131}
132
133impl Default for Solved {
134    fn default() -> Self {
135        Self {
136            did_a_thing: false,
137            finished: true,
138        }
139    }
140}
141
142#[derive(Clone, Debug, Default)]
143pub struct SolvedLocation {
144    solved: Solved,
145    locations: Vec<(Span, &'static str, u32)>,
146}
147
148impl SolverStatus for SolvedLocation {
149    fn iam_not_finished_location(
150        &mut self,
151        location: &Span,
152        file: &'static str,
153        line: u32,
154    ) {
155        self.solved.iam_not_finished_location(location, file, line);
156        self.locations.push((location.clone(), file, line));
157    }
158    fn i_did_a_thing(&mut self) {
159        self.solved.i_did_a_thing();
160    }
161    fn we_finished(&self) -> bool {
162        self.solved.we_finished()
163    }
164    fn we_did_a_thing(&self) -> bool {
165        self.solved.we_did_a_thing()
166    }
167    fn unfinished_locations(&self) -> &[(Span, &'static str, u32)] {
168        &self.locations
169    }
170    fn combine(&mut self, other: &Self) {
171        self.solved.combine(&other.solved);
172        self.locations
173            .extend(other.unfinished_locations().iter().cloned());
174    }
175}
176
177#[derive(Debug)]
178pub struct Sleigh {
179    /// the default address space
180    pub default_space: Option<SpaceId>,
181    pub instruction_table: TableId,
182
183    //data that will be passed to the final struct
184    /// processor endian
185    pub endian: Option<Endian>,
186    /// memory access alignemnt
187    pub alignment: Option<NumberUnsigned>,
188    /// all the unique ident types, such Tables, Macros, Varnodes, etc.
189    pub global_scope: HashMap<String, GlobalScope>,
190
191    pub spaces: Vec<Space>,
192    pub varnodes: Vec<Varnode>,
193    pub contexts: Vec<Context>,
194    pub bitranges: Vec<Bitrange>,
195    pub tokens: Vec<Token>,
196    pub token_fields: Vec<TokenField>,
197    pub user_functions: Vec<UserFunction>,
198    pub pcode_macros: Vec<PcodeMacro>,
199    pub tables: Vec<Table>,
200
201    pub attach_varnodes: Vec<AttachVarnode>,
202    pub attach_literals: Vec<AttachLiteral>,
203    pub attach_numbers: Vec<AttachNumber>,
204}
205
206impl Sleigh {
207    pub fn space(&self, space: SpaceId) -> &Space {
208        &self.spaces[space.0]
209    }
210    pub fn varnode(&self, varnode: VarnodeId) -> &Varnode {
211        &self.varnodes[varnode.0]
212    }
213    pub fn context(&self, context: ContextId) -> &Context {
214        &self.contexts[context.0]
215    }
216    pub fn context_mut(&mut self, context: ContextId) -> &mut Context {
217        &mut self.contexts[context.0]
218    }
219    pub fn bitrange(&self, bitrange: BitrangeId) -> &Bitrange {
220        &self.bitranges[bitrange.0]
221    }
222    pub fn token(&self, token: TokenId) -> &Token {
223        &self.tokens[token.0]
224    }
225    pub fn token_field(&self, token_field: TokenFieldId) -> &TokenField {
226        &self.token_fields[token_field.0]
227    }
228    pub fn token_field_mut(
229        &mut self,
230        token_field: TokenFieldId,
231    ) -> &mut TokenField {
232        &mut self.token_fields[token_field.0]
233    }
234    pub fn user_function(
235        &self,
236        user_function: UserFunctionId,
237    ) -> &UserFunction {
238        &self.user_functions[user_function.0]
239    }
240    pub fn pcode_macro(&self, pcode_macro: PcodeMacroId) -> &PcodeMacro {
241        &self.pcode_macros[pcode_macro.0]
242    }
243    pub fn table(&self, table: TableId) -> &Table {
244        &self.tables[table.0]
245    }
246    pub fn table_mut(&mut self, table: TableId) -> &mut Table {
247        &mut self.tables[table.0]
248    }
249    pub fn attach_varnode(&self, id: AttachVarnodeId) -> &AttachVarnode {
250        &self.attach_varnodes[id.0]
251    }
252    pub fn attach_number(&self, id: AttachNumberId) -> &AttachNumber {
253        &self.attach_numbers[id.0]
254    }
255    pub fn attach_literal(&self, id: AttachLiteralId) -> &AttachLiteral {
256        &self.attach_literals[id.0]
257    }
258    pub fn default_space(&self) -> Option<SpaceId> {
259        self.default_space
260    }
261    pub fn get_global(&self, name: &str) -> Option<GlobalScope> {
262        self.global_scope.get(name).copied()
263    }
264    pub fn set_endian(&mut self, endian: Endian) -> Result<(), SleighError> {
265        self.endian
266            .replace(endian)
267            .map(|_old| Err(SleighError::EndianMultiple))
268            .unwrap_or(Ok(()))
269    }
270    pub fn set_alignment(
271        &mut self,
272        align: syntax::define::Alignment,
273    ) -> Result<(), SleighError> {
274        self.alignment
275            .replace(align.0)
276            .map(|_| Err(SleighError::AlignmentMultiple))
277            .unwrap_or(Ok(()))
278    }
279    fn process(
280        &mut self,
281        with_block_current: &mut WithBlockCurrent,
282        syntax: syntax::Sleigh,
283    ) -> Result<(), SleighError> {
284        for assertation in syntax.assertations.into_iter() {
285            use syntax::define::Define::*;
286            use syntax::Assertation::*;
287            match assertation {
288                Define(Endian(endian)) => self.set_endian(endian)?,
289                Define(Alignment(x)) => self.set_alignment(x)?,
290                Define(Space(x)) => self.create_space(x)?,
291                Define(Varnode(x)) => self.create_memory(x)?,
292                Define(Bitrange(x)) => self.create_bitrange(x)?,
293                Define(UserFunction(x)) => self.create_user_function(x)?,
294                Define(Context(x)) => self.create_context(x)?,
295                Define(Token(x)) => self.create_token(x)?,
296                Attach(x) => self.attach_meaning(x)?,
297                TableConstructor(x) => {
298                    self.insert_table_constructor(with_block_current, x)?
299                }
300                PcodeMacro(x) => self.create_pcode_macro(x)?,
301                WithBlock(with_block) => {
302                    //TODO remove this clone
303                    let body = with_block_current.push(with_block);
304                    self.process(with_block_current, body)?;
305                    with_block_current.pop();
306                }
307            }
308        }
309        Ok(())
310    }
311
312    pub fn addr_bytes(&self) -> Option<NumberNonZeroUnsigned> {
313        let space_id = self.default_space?;
314        let space = self.space(space_id);
315        Some(space.addr_bytes)
316    }
317
318    pub fn new(syntax: syntax::Sleigh) -> Result<Self, SleighError> {
319        let instruction_table =
320            Table::new_empty(true, IDENT_INSTRUCTION.to_owned());
321        let instruction_table_id = TableId(0);
322        let mut sleigh = Sleigh {
323            tables: vec![instruction_table],
324            global_scope: HashMap::from([
325                (
326                    IDENT_INST_START.to_string(),
327                    GlobalScope::InstStart(InstStart),
328                ),
329                (IDENT_INST_NEXT.to_string(), GlobalScope::InstNext(InstNext)),
330                (IDENT_EPSILON.to_string(), GlobalScope::Epsilon(Epsilon)),
331                (
332                    IDENT_INSTRUCTION.to_string(),
333                    GlobalScope::Table(instruction_table_id),
334                ),
335            ]),
336            instruction_table: instruction_table_id,
337            default_space: None,
338            endian: None,
339            alignment: None,
340            spaces: vec![],
341            varnodes: vec![],
342            contexts: vec![],
343            bitranges: vec![],
344            tokens: vec![],
345            token_fields: vec![],
346            user_functions: vec![],
347            pcode_macros: vec![],
348            attach_varnodes: vec![],
349            attach_literals: vec![],
350            attach_numbers: vec![],
351        };
352
353        sleigh.process(&mut WithBlockCurrent::default(), syntax)?;
354
355        Ok(sleigh)
356    }
357}