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 Below(u64),
60 Above(u64),
61 Is(u64),
62 IsNot(u64),
63}
64
65#[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 } else {
181 }
183 }
184 res
185 }
186}