yaxpeax_core/data/
modifier.rs

1use yaxpeax_arch::Arch;
2
3use data::Direction;
4use data::ValueLocations;
5use arch::AbiDefaults;
6use arch::FunctionImpl;
7use arch::FunctionQuery;
8
9use std::cell::RefCell;
10use std::collections::HashMap;
11use std::rc::Rc;
12
13#[derive(Hash, Debug, Copy, Clone, Eq, PartialEq)]
14pub enum Precedence {
15    Before,
16    After
17}
18
19#[derive(Hash, Debug, Copy, Clone, Eq, PartialEq)]
20pub struct Modifier<Addr, Expr> {
21    location: (Addr, Precedence),
22    modifier: Expr
23}
24
25impl <Addr: Copy + Clone, Expr> Modifier<Addr, Expr> {
26    pub fn location(&self) -> (Addr, Precedence) {
27        self.location.clone()
28    }
29}
30
31pub trait ModifierCollection<A: Arch + ValueLocations> {
32    fn before(&self, addr: A::Address) -> Vec<(Option<A::Location>, Direction)>;
33    fn after(&self, addr: A::Address) -> Vec<(Option<A::Location>, Direction)>;
34    fn between(&self, addr: A::Address, next: A::Address) -> Vec<(Option<A::Location>, Direction)>;
35}
36
37pub struct NoModifiers;
38
39impl <A: Arch + ValueLocations> ModifierCollection<A> for NoModifiers {
40    fn before(&self, _addr: A::Address) -> Vec<(Option<A::Location>, Direction)> {
41        vec![]
42    }
43    fn after(&self, _addr: A::Address) -> Vec<(Option<A::Location>, Direction)> {
44        vec![]
45    }
46    fn between(&self, _addr: A::Address, _next: A::Address) -> Vec<(Option<A::Location>, Direction)> {
47        vec![]
48    }
49}
50
51#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
52pub enum ModifierExpression {
53    /* At some point these should go through MemoSerialize, so these can be arbitrary expressions
54    Below(analyses::data_flow::Data),
55    Above(analyses::data_flow::Data),
56    Is(analyses::data_flow::Data),
57    IsNot(analyses::data_flow::Data)
58    */
59    Below(u64),
60    Above(u64),
61    Is(u64),
62    IsNot(u64),
63}
64
65/// The `Vec<ModifierExpression>` are _conjunctions_. This differs from `ValueSet`, which uses a
66/// sequence of values as disjunctions. This means there's no way to express a sparseset of values
67/// as ModifierExpression, for the time being.
68#[derive(Serialize, Deserialize, Debug)]
69pub struct InstructionModifiers<A: Arch + ValueLocations> where A::Location: AbiDefaults {
70    before: HashMap<A::Address, HashMap<Option<A::Location>, Vec<ModifierExpression>>>,
71    after: HashMap<A::Address, HashMap<Option<A::Location>, Vec<ModifierExpression>>>,
72    #[serde(skip)]
73    between: HashMap<A::Address, HashMap<A::Address, HashMap<Option<A::Location>, Vec<ModifierExpression>>>>,
74    pub calls: HashMap<A::Address, A::Address>,
75    fn_query: Rc<RefCell<HashMap<A::Address, FunctionImpl<A::Location>>>>,
76}
77
78impl<A: Arch + ValueLocations> InstructionModifiers<A> where A::Location: AbiDefaults {
79    pub fn new(fn_query: Rc<RefCell<HashMap<A::Address, FunctionImpl<A::Location>>>>) -> Self {
80        InstructionModifiers {
81            before: HashMap::new(),
82            after: HashMap::new(),
83            between: HashMap::new(),
84            calls: HashMap::new(),
85            fn_query,
86        }
87    }
88
89    pub fn modifiers_between(&self, from: A::Address, to: A::Address) -> Option<&HashMap<Option<A::Location>, Vec<ModifierExpression>>> {
90        self.between.get(&from).and_then(|tos| tos.get(&to))
91    }
92
93    pub fn add_edge_modifier(&mut self, from: A::Address, to: A::Address, loc: Option<A::Location>, expr: ModifierExpression) {
94        let edges: &mut HashMap<A::Address, HashMap<Option<A::Location>, Vec<ModifierExpression>>> = self.between.entry(from).or_insert_with(|| HashMap::new());
95        let edge: &mut HashMap<Option<A::Location>, Vec<ModifierExpression>> = edges.entry(to).or_insert_with(|| HashMap::new());
96        let modifiers: &mut Vec<ModifierExpression> = edge.entry(loc).or_insert_with(|| Vec::new());
97        modifiers.push(expr);
98    }
99}
100
101impl<A: Arch + ValueLocations> ModifierCollection<A> for InstructionModifiers<A> where A::Location: AbiDefaults {
102    fn between(&self, from: A::Address, to: A::Address) -> Vec<(Option<A::Location>, Direction)> {
103        let mut res = vec![];
104        if let Some(modifiers) = self.modifiers_between(from, to) {
105             for (k, vs) in modifiers.iter() {
106                for v in vs {
107                    match v {
108                        ModifierExpression::IsNot(_) |
109                        ModifierExpression::Below(_) |
110                        ModifierExpression::Above(_) => {
111                            res.push((k.to_owned(), Direction::Read));
112                            res.push((k.to_owned(), Direction::Write));
113                        }
114                        ModifierExpression::Is(_) => {
115                            res.push((k.to_owned(), Direction::Write));
116                        }
117                    }
118                }
119            }
120        }
121        res
122   }
123
124    fn before(&self, addr: A::Address) -> Vec<(Option<A::Location>, Direction)> {
125        let mut res = vec![];
126        if let Some(modifiers) = self.before.get(&addr) {
127            for (k, vs) in modifiers.iter() {
128                for v in vs {
129                    match v {
130                        ModifierExpression::IsNot(_) |
131                        ModifierExpression::Below(_) |
132                        ModifierExpression::Above(_) => {
133                            res.push((k.to_owned(), Direction::Read));
134                            res.push((k.to_owned(), Direction::Write));
135                        }
136                        ModifierExpression::Is(_) => {
137                            res.push((k.to_owned(), Direction::Write));
138                        }
139                    }
140                }
141            }
142        }
143        res
144    }
145    fn after(&self, addr: A::Address) -> Vec<(Option<A::Location>, Direction)> {
146        let mut res = vec![];
147        if let Some(modifiers) = self.before.get(&addr) {
148            for (k, vs) in modifiers.iter() {
149                for v in vs {
150                    match v {
151                        ModifierExpression::IsNot(_) |
152                        ModifierExpression::Below(_) |
153                        ModifierExpression::Above(_) => {
154                            res.push((k.to_owned(), Direction::Read));
155                            res.push((k.to_owned(), Direction::Write));
156                        }
157                        ModifierExpression::Is(_) => {
158                            res.push((k.to_owned(), Direction::Write));
159                        }
160                    }
161                }
162            }
163        }
164        if let Some(target) = self.calls.get(&addr) {
165            if let Some(f) = (&*self.fn_query.borrow()).function_at(*target) {
166                let layout = f.layout();
167                for arg in layout.arguments.iter() {
168                    res.push((arg.to_owned(), Direction::Read));
169                }
170                for arg in layout.clobbers.iter() {
171                    res.push((arg.to_owned(), Direction::Write));
172                }
173                for arg in layout.returns.iter() {
174                    res.push((arg.to_owned(), Direction::Write));
175                }
176                if let Some(ret) = &layout.return_address {
177                    res.push((Some(ret.clone()), Direction::Read));
178                }
179                // we can add all the reads/writes of f.
180            } else {
181                // !! log an error somewhere !!
182            }
183        }
184        res
185    }
186}