yaxpeax_core/arch/x86_64/
mod.rs1use yaxpeax_arch::Arch;
2use yaxpeax_arch::Decoder;
3use arch::DecodeFrom;
4use analyses::control_flow;
5use analyses::static_single_assignment::SSA;
6use analyses::xrefs;
7use memory::MemoryRepr;
8use self::analyses::data_flow::DefaultCallingConvention;
9
10use petgraph::graphmap::GraphMap;
11
12use std::collections::HashMap;
13use std::collections::HashSet;
14use yaxpeax_x86::x86_64;
15use std::rc::Rc;
16use std::cell::RefCell;
17use std::cell::Ref;
18use num_traits::Zero;
19
20use arch::{BaseUpdate, CommentQuery, FunctionLayout, FunctionImpl, FunctionQuery, Symbol, SymbolQuery, Library};
21use data::ValueLocations;
22use data::modifier::InstructionModifiers;
23use timing::Timings;
24
25use ContextRead;
26use ContextWrite;
27
28pub mod analyses;
29pub mod cpu;
30#[cfg(target_os = "linux")]
31pub mod debug;
32pub mod display;
33pub mod semantic;
34
35impl<M: MemoryRepr<Self> + ?Sized> DecodeFrom<M> for x86_64 {
36 fn decode_with_decoder_into<'mem>(
37 decoder: &Self::Decoder,
38 cursor: &crate::memory::repr::ReadCursor<'mem, Self, M>,
39 instr: &mut Self::Instruction
40 ) -> Result<(), Self::DecodeError> {
41 let mut reader = cursor.to_reader();
42 decoder.decode_into(instr, &mut reader)
43 }
44}
45
46#[allow(non_camel_case_types)]
49pub struct x86_64Data {
50pub timings: Timings<<x86_64 as Arch>::Address>,
52 pub preferred_addr: <x86_64 as Arch>::Address,
53 pub contexts: MergedContextTable,
54 pub cfg: control_flow::ControlFlowGraph<<x86_64 as Arch>::Address>,
55 pub ssa: HashMap<<x86_64 as Arch>::Address, (
56 control_flow::ControlFlowGraph<<x86_64 as Arch>::Address>,
57 SSA<x86_64>
58 )>,
59}
60
61pub struct DisplayCtx<'a> {
62 functions: Ref<'a, HashMap<<x86_64 as Arch>::Address, FunctionImpl<<x86_64 as ValueLocations>::Location>>>,
63 comments: &'a HashMap<<x86_64 as Arch>::Address, String>,
64 symbols: &'a HashMap<<x86_64 as Arch>::Address, Symbol>,
65}
66
67impl FunctionQuery<<x86_64 as Arch>::Address> for x86_64Data {
68 type Function = FunctionImpl<<x86_64 as ValueLocations>::Location>;
69 fn function_at(&self, _addr: <x86_64 as Arch>::Address) -> Option<&Self::Function> {
71 unimplemented!("FunctionQuery::function_at for x86_64Data");
72 }
73 fn all_functions(&self) -> Vec<&Self::Function> {
74 unimplemented!("FunctionQuery::all_functions for x86_64Data");
75 }
76}
77
78impl CommentQuery<<x86_64 as Arch>::Address> for MergedContextTable {
79 fn comment_for(&self, addr: <x86_64 as Arch>::Address) -> Option<&str> {
80 self.comments.get(&addr).map(String::as_ref)
81 }
82}
83
84impl FunctionQuery<<x86_64 as Arch>::Address> for MergedContextTable {
85 type Function = FunctionImpl<<x86_64 as ValueLocations>::Location>;
86 fn function_at(&self, _addr: <x86_64 as Arch>::Address) -> Option<&Self::Function> {
88 unimplemented!("FunctionQuery::function_at for MergedContextTable");
89 }
90 fn all_functions(&self) -> Vec<&Self::Function> {
91 unimplemented!("FunctionQuery::all_functions for MergedContextTable");
92 }
93}
94
95impl SymbolQuery<<x86_64 as Arch>::Address> for x86_64Data {
96 fn symbol_for(&self, addr: <x86_64 as Arch>::Address) -> Option<&Symbol> {
97 self.contexts.symbols.get(&addr)
98 }
99 fn symbol_addr(&self, sym: &Symbol) -> Option<<x86_64 as Arch>::Address> {
100 for (k, v) in self.contexts.symbols.iter() {
101 if v == sym {
102 return Some(*k);
103 }
104 }
105
106 None
107 }
108}
109
110impl<'a> FunctionQuery<<x86_64 as Arch>::Address> for DisplayCtx<'a> {
111 type Function = FunctionImpl<<x86_64 as ValueLocations>::Location>;
112 fn function_at(&self, addr: <x86_64 as Arch>::Address) -> Option<&Self::Function> {
113 self.functions.function_at(addr)
114 }
115 fn all_functions(&self) -> Vec<&Self::Function> {
116 self.functions.all_functions()
117 }
118}
119
120impl<'a> CommentQuery<<x86_64 as Arch>::Address> for DisplayCtx<'a> {
121 fn comment_for(&self, addr: <x86_64 as Arch>::Address) -> Option<&str> {
122 self.comments.get(&addr).map(String::as_ref)
123 }
124}
125
126impl<'a> SymbolQuery<<x86_64 as Arch>::Address> for DisplayCtx<'a> {
127 fn symbol_for(&self, addr: <x86_64 as Arch>::Address) -> Option<&Symbol> {
128 self.symbols.get(&addr)
129 }
130 fn symbol_addr(&self, sym: &Symbol) -> Option<<x86_64 as Arch>::Address> {
131 for (k, v) in self.symbols.iter() {
132 if v == sym {
133 return Some(*k);
134 }
135 }
136
137 None
138 }
139}
140
141impl Default for x86_64Data {
142 fn default() -> Self {
143 x86_64Data {
144 timings: Timings::new(),
145 preferred_addr: <x86_64 as Arch>::Address::zero(),
146 contexts: MergedContextTable::create_empty(),
147 cfg: control_flow::ControlFlowGraph::new(),
148 ssa: HashMap::new(),
149 }
150 }
151}
152
153#[derive(Serialize, Deserialize)]
154pub struct MergedContextTable {
155 pub user_contexts: HashMap<<x86_64 as Arch>::Address, Rc<()>>,
156 pub computed_contexts: HashMap<<x86_64 as Arch>::Address, Rc<()>>,
157 pub comments: HashMap<<x86_64 as Arch>::Address, String>,
158 #[serde(skip)]
159 pub call_graph: GraphMap<<x86_64 as Arch>::Address, (), petgraph::Directed>,
160 #[serde(skip)]
161 pub xrefs: xrefs::XRefCollection<<x86_64 as Arch>::Address>,
162 pub symbols: HashMap<<x86_64 as Arch>::Address, Symbol>,
163 #[serde(skip)]
164 pub reverse_symbols: HashMap<Symbol, <x86_64 as Arch>::Address>,
165 pub functions: Rc<RefCell<HashMap<<x86_64 as Arch>::Address, FunctionImpl<<x86_64 as ValueLocations>::Location>>>>,
166 pub function_data: HashMap<<x86_64 as Arch>::Address, RefCell<InstructionModifiers<x86_64>>>,
167 pub function_hints: Vec<<x86_64 as Arch>::Address>,
168 functions_hinted: HashSet<<x86_64 as Arch>::Address>,
169 pub default_abi: Option<DefaultCallingConvention>,
170}
171
172#[derive(Debug)]
173pub struct MergedContext {
174 pub computed: Option<Rc<()>>,
175 pub user: Option<Rc<()>>
176}
177
178impl Default for MergedContextTable {
179 fn default() -> Self {
180 MergedContextTable::create_empty()
181 }
182}
183
184impl MergedContextTable {
185 pub fn fn_count(&self) -> usize {
186 self.functions.borrow().len()
187 }
188 pub fn create_empty() -> MergedContextTable {
189 MergedContextTable {
190 user_contexts: HashMap::new(),
191 computed_contexts: HashMap::new(),
192 comments: HashMap::new(),
193 call_graph: GraphMap::new(),
194 xrefs: xrefs::XRefCollection::new(),
195 functions: Rc::new(RefCell::new(HashMap::new())),
196 function_hints: Vec::new(),
197 functions_hinted: HashSet::new(),
198 symbols: HashMap::new(),
199 reverse_symbols: HashMap::new(),
200 function_data: HashMap::new(),
201 default_abi: Some(DefaultCallingConvention::Microsoft), }
203 }
204
205 pub fn display_ctx(&self) -> DisplayCtx {
206 DisplayCtx {
207 functions: self.functions.borrow(),
208 symbols: &self.symbols,
209 comments: &self.comments,
210 }
211 }
212}
213
214pub type Update = BaseUpdate<x86Update>;
232
233#[derive(Debug)]
234#[allow(non_camel_case_types)]
235pub enum x86Update {
236 AddXRef(xrefs::RefType, xrefs::RefAction, <x86_64 as Arch>::Address),
237 RemoveXRef(xrefs::RefType, xrefs::RefAction, <x86_64 as Arch>::Address),
238 FunctionHint
239}
240
241impl ContextRead<x86_64, MergedContext> for MergedContextTable {
242 fn at(&self, address: &<x86_64 as Arch>::Address) -> MergedContext {
243 MergedContext {
244 user: self.user_contexts.get(address).map(|v| Rc::clone(v)),
245 computed: self.computed_contexts.get(address).map(|v| Rc::clone(v))
246 }
247 }
248}
249
250impl ContextWrite<x86_64, Update> for MergedContextTable {
251 fn put(&mut self, address: <x86_64 as Arch>::Address, update: Update) {
252 match update {
254 BaseUpdate::Specialized(x86Update::FunctionHint) => {
255 if !self.functions.borrow().contains_key(&address) && !self.functions_hinted.contains(&address) {
256self.functions_hinted.insert(address);
258 self.function_hints.push(address)
259 }
260 },
261 BaseUpdate::Specialized(x86Update::AddXRef(tpe, action, dest)) => {
262 self.xrefs.insert_from_code(tpe, action, address, dest);
264 },
265 BaseUpdate::Specialized(x86Update::RemoveXRef(tpe, action, dest)) => {
266 self.xrefs.delete_from_code(tpe, action, address, dest);
267 }
268 BaseUpdate::DefineSymbol(sym) => {
269 if !self.symbols.contains_key(&address) {
271 match Symbol::to_function(&sym) {
272 Some(f) => {
273 if let Some(abi) = self.default_abi {
274 self.functions.borrow_mut().insert(address, f.implement_for(FunctionLayout::for_abi(abi)));
275 } else {
276 self.functions.borrow_mut().insert(address, f.unimplemented());
279 }
280 }
281 None => { }
282 }
283 self.symbols.insert(address, sym.clone());
284 self.reverse_symbols.insert(sym, address);
285 }
286 }
287 BaseUpdate::DefineFunction(f) => {
288 if !self.functions.borrow().contains_key(&address) {
289 self.symbols.insert(address, Symbol(Library::This, f.name.clone()));
290 self.reverse_symbols.insert(Symbol(Library::This, f.name.clone()), address);
291 if let Some(abi) = self.default_abi {
292 self.functions.borrow_mut().insert(address, f.implement_for(FunctionLayout::for_abi(abi)));
293 } else {
294 self.functions.borrow_mut().insert(address, f.unimplemented());
297 }
298 }
299 }
300 BaseUpdate::AddCodeComment(comment) => {
301 self.comments.insert(address, comment);
302 }
303 _ => { }
304 }
305 }
306}