1use std::{ffi::CStr, mem::size_of, slice::from_raw_parts};
7
8use crate::{
9 tracer::{CmpExpr, CmpType, CmpValue, TraceEntry},
10 traits::TracerDisassembler,
11};
12use anyhow::{anyhow, bail, Error, Result};
13use libafl::prelude::CmpValues;
14use raw_cstr::AsRawCstr;
15use simics::api::{
16 get_interface, read_phys_memory, sys::instruction_handle_t, Access, ConfObject,
17 CpuInstructionQueryInterface, CpuInstrumentationSubscribeInterface, CycleInterface,
18 IntRegisterInterface, ProcessorInfoV2Interface,
19};
20use yaxpeax_x86::amd64::{ConditionCode, InstDecoder, Instruction, Opcode, Operand};
21
22use super::ArchitectureOperations;
23
24pub(crate) struct X86_64ArchitectureOperations {
25 cpu: *mut ConfObject,
26 disassembler: Disassembler,
27 int_register: IntRegisterInterface,
28 processor_info_v2: ProcessorInfoV2Interface,
29 cpu_instruction_query: CpuInstructionQueryInterface,
30 #[allow(dead_code)]
31 cpu_instrumentation_subscribe: CpuInstrumentationSubscribeInterface,
32 cycle: CycleInterface,
33}
34
35impl ArchitectureOperations for X86_64ArchitectureOperations {
36 const INDEX_SELECTOR_REGISTER: &'static str = "rdi";
37 const ARGUMENT_REGISTER_0: &'static str = "rsi";
38 const ARGUMENT_REGISTER_1: &'static str = "rdx";
39 const ARGUMENT_REGISTER_2: &'static str = "rcx";
40
41 fn new(cpu: *mut ConfObject) -> Result<Self> {
42 let mut processor_info_v2: ProcessorInfoV2Interface = get_interface(cpu)?;
43
44 let arch = unsafe { CStr::from_ptr(processor_info_v2.architecture()?) }
45 .to_str()?
46 .to_string();
47
48 if arch == "x86-64" {
49 let mut int_register: IntRegisterInterface = get_interface(cpu)?;
52 let regs: Vec<u32> = int_register.all_registers()?.try_into()?;
53 let reg_names: Vec<String> = regs
54 .iter()
55 .map(|r| {
56 int_register
57 .get_name(*r as i32)
58 .map_err(|e| anyhow!("Failed to get register name: {e}"))
59 .and_then(|n| {
60 unsafe { CStr::from_ptr(n) }
61 .to_str()
62 .map(|s| s.to_string())
63 .map_err(|e| anyhow!("Failed to convert string: {e}"))
64 })
65 })
66 .collect::<Result<Vec<_>>>()?;
67
68 if reg_names.iter().any(|n| {
69 [
70 "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rip", "rsp", "rbp", "r8", "r9",
71 "r10", "r11", "r12", "r14", "r15",
72 ]
73 .contains(&n.to_ascii_lowercase().as_str())
74 }) {
75 Ok(Self {
76 cpu,
77 disassembler: Disassembler::new(),
78 int_register,
79 processor_info_v2,
80 cpu_instruction_query: get_interface(cpu)?,
81 cpu_instrumentation_subscribe: get_interface(cpu)?,
82 cycle: get_interface(cpu)?,
83 })
84 } else if reg_names.iter().all(|n| {
85 ![
86 "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rip", "rsp", "rbp", "r8", "r9",
87 "r10", "r11", "r12", "r14", "r15",
88 ]
89 .contains(&n.to_ascii_lowercase().as_str())
90 }) {
91 bail!("Architecture reports x86-64 but is not actually x86-64")
92 } else {
93 unreachable!("Register set must either contain a 64-bit register or no registers may be 64-bit");
94 }
95 } else {
96 bail!("Architecture {arch} is not x86-64");
97 }
98 }
99
100 fn new_unchecked(cpu: *mut ConfObject) -> Result<Self>
101 where
102 Self: Sized,
103 {
104 Ok(Self {
105 cpu,
106 disassembler: Disassembler::new(),
107 int_register: get_interface(cpu)?,
108 processor_info_v2: get_interface(cpu)?,
109 cpu_instruction_query: get_interface(cpu)?,
110 cpu_instrumentation_subscribe: get_interface(cpu)?,
111 cycle: get_interface(cpu)?,
112 })
113 }
114
115 fn cpu(&self) -> *mut ConfObject {
116 self.cpu
117 }
118
119 fn disassembler(&mut self) -> &mut dyn TracerDisassembler {
120 &mut self.disassembler
121 }
122
123 fn int_register(&mut self) -> &mut IntRegisterInterface {
124 &mut self.int_register
125 }
126
127 fn processor_info_v2(&mut self) -> &mut ProcessorInfoV2Interface {
128 &mut self.processor_info_v2
129 }
130
131 fn cpu_instruction_query(&mut self) -> &mut CpuInstructionQueryInterface {
132 &mut self.cpu_instruction_query
133 }
134
135 fn cpu_instrumentation_subscribe(&mut self) -> &mut CpuInstrumentationSubscribeInterface {
136 &mut self.cpu_instrumentation_subscribe
137 }
138
139 fn cycle(&mut self) -> &mut CycleInterface {
140 &mut self.cycle
141 }
142
143 fn trace_pc(&mut self, instruction_query: *mut instruction_handle_t) -> Result<TraceEntry> {
144 let instruction_bytes = self
145 .cpu_instruction_query
146 .get_instruction_bytes(instruction_query)?;
147 self.disassembler.disassemble(unsafe {
148 from_raw_parts(instruction_bytes.data, instruction_bytes.size)
149 })?;
150 if self.disassembler.last_was_call()
151 || self.disassembler.last_was_control_flow()
152 || self.disassembler.last_was_ret()
153 {
154 Ok(TraceEntry::builder()
155 .edge(self.processor_info_v2.get_program_counter()?)
156 .build())
157 } else {
158 Ok(TraceEntry::default())
159 }
160 }
161
162 fn trace_cmp(&mut self, instruction_query: *mut instruction_handle_t) -> Result<TraceEntry> {
163 let instruction_bytes = self
164 .cpu_instruction_query
165 .get_instruction_bytes(instruction_query)?;
166 self.disassembler.disassemble(unsafe {
167 from_raw_parts(instruction_bytes.data, instruction_bytes.size)
168 })?;
169 if self.disassembler.last_was_cmp() {
170 let pc = self.processor_info_v2.get_program_counter()?;
171 let mut cmp_values = Vec::new();
172
173 for expr in self.disassembler.cmp() {
174 if let Ok(value) = self.simplify(&expr) {
175 cmp_values.push(value);
176 }
177 }
178
179 let cmp_value = if let (Some(l), Some(r)) = (cmp_values.first(), cmp_values.get(1)) {
180 match (l, r) {
181 (CmpValue::U8(l), CmpValue::U8(r)) => Some(CmpValues::U8((*l, *r))),
182 (CmpValue::I8(l), CmpValue::I8(r)) => Some(CmpValues::U8((
183 u8::from_le_bytes(l.to_le_bytes()),
184 u8::from_le_bytes(r.to_le_bytes()),
185 ))),
186 (CmpValue::U16(l), CmpValue::U16(r)) => Some(CmpValues::U16((*l, *r))),
187 (CmpValue::I16(l), CmpValue::I16(r)) => Some(CmpValues::U16((
188 u16::from_le_bytes(l.to_le_bytes()),
189 u16::from_le_bytes(r.to_le_bytes()),
190 ))),
191 (CmpValue::U32(l), CmpValue::U32(r)) => Some(CmpValues::U32((*l, *r))),
192 (CmpValue::I32(l), CmpValue::I32(r)) => Some(CmpValues::U32((
193 u32::from_le_bytes(l.to_le_bytes()),
194 u32::from_le_bytes(r.to_le_bytes()),
195 ))),
196 (CmpValue::U64(l), CmpValue::U64(r)) => Some(CmpValues::U64((*l, *r))),
197 (CmpValue::I64(l), CmpValue::I64(r)) => Some(CmpValues::U64((
198 u64::from_le_bytes(l.to_le_bytes()),
199 u64::from_le_bytes(r.to_le_bytes()),
200 ))),
201 (CmpValue::Expr(_), CmpValue::Expr(_)) => None,
202 _ => None,
203 }
204 } else {
205 None
206 };
207
208 Ok(TraceEntry::builder()
209 .cmp((
210 pc,
211 self.disassembler.cmp_type(),
212 cmp_value.ok_or_else(|| anyhow!("No cmp value available"))?,
213 ))
214 .build())
215 } else {
216 Ok(TraceEntry::default())
217 }
218 }
219}
220
221impl X86_64ArchitectureOperations {
222 fn simplify(&mut self, expr: &CmpExpr) -> Result<CmpValue> {
223 match expr {
224 CmpExpr::Deref((expr, width)) => {
225 let v = self.simplify(expr)?;
226
227 match v {
228 CmpValue::U64(a) => {
229 let address = self
230 .processor_info_v2
231 .logical_to_physical(a, Access::Sim_Access_Read)?;
232 let casted = match width {
233 Some(1) => CmpValue::U8(
234 read_phys_memory(self.cpu, address.address, size_of::<u8>() as i32)
235 .map_err(|e| {
236 anyhow!("Error reading bytes from {:#x}: {}", a, e)
237 })?
238 .to_le_bytes()[0],
239 ),
240 Some(2) => CmpValue::U16(u16::from_le_bytes(
241 read_phys_memory(
242 self.cpu,
243 address.address,
244 size_of::<u16>() as i32,
245 )
246 .map_err(|e| anyhow!("Error reading bytes from {:#x}: {}", a, e))?
247 .to_le_bytes()[0..size_of::<u16>()]
248 .try_into()?,
249 )),
250 Some(4) => CmpValue::U32(u32::from_le_bytes(
251 read_phys_memory(
252 self.cpu,
253 address.address,
254 size_of::<u32>() as i32,
255 )
256 .map_err(|e| anyhow!("Error reading bytes from {:#x}: {}", a, e))?
257 .to_le_bytes()[0..size_of::<u32>()]
258 .try_into()?,
259 )),
260 Some(8) => CmpValue::U64(u64::from_le_bytes(
261 read_phys_memory(
262 self.cpu,
263 address.address,
264 size_of::<u64>() as i32,
265 )
266 .map_err(|e| anyhow!("Error reading bytes from {:#x}: {}", a, e))?
267 .to_le_bytes(),
268 )),
269 _ => bail!("Can't cast to non-power-of-2 width {:?}", width),
270 };
271 Ok(casted)
272 }
273 _ => bail!("Can't dereference non-address"),
274 }
275 }
276 CmpExpr::Reg((name, width)) => {
277 let reg_number = self.int_register.get_number(name.as_raw_cstr()?)?;
278 let value = self.int_register.read(reg_number).map_err(|e| {
279 anyhow!("Couldn't read register value for register {}: {}", name, e)
280 })?;
281
282 let casted = match width {
283 1 => CmpValue::U8(value.to_le_bytes()[0]),
284 2 => CmpValue::U16(u16::from_le_bytes(
285 value.to_le_bytes()[..size_of::<u16>()]
286 .try_into()
287 .map_err(|e| anyhow!("Error converting to u32 bytes: {}", e))?,
288 )),
289 4 => CmpValue::U32(u32::from_le_bytes(
290 value.to_le_bytes()[..size_of::<u32>()]
291 .try_into()
292 .map_err(|e| anyhow!("Error converting to u32 bytes: {}", e))?,
293 )),
294 8 => CmpValue::U64(u64::from_le_bytes(value.to_le_bytes())),
295 _ => bail!("Can't cast to non-power-of-2 width {}", width),
296 };
297 Ok(casted)
298 }
299 CmpExpr::Mul((l, r)) => {
300 let lv = self.simplify(l)?;
301 let rv = self.simplify(r)?;
302
303 match (lv, rv) {
304 (CmpValue::U8(lu), CmpValue::U8(ru)) => Ok(CmpValue::U8(lu.wrapping_mul(ru))),
305 (CmpValue::U8(lu), CmpValue::I8(ru)) => {
306 Ok(CmpValue::U8((lu as i32).wrapping_mul(ru as i32) as u8))
307 }
308 (CmpValue::U8(lu), CmpValue::U16(ru)) => {
309 Ok(CmpValue::U8((lu as u16).wrapping_mul(ru) as u8))
310 }
311 (CmpValue::U8(lu), CmpValue::I16(ru)) => {
312 Ok(CmpValue::U8((lu as i32).wrapping_mul(ru as i32) as u8))
313 }
314 (CmpValue::U8(lu), CmpValue::U32(ru)) => {
315 Ok(CmpValue::U8((lu as u32).wrapping_mul(ru) as u8))
316 }
317 (CmpValue::U8(lu), CmpValue::I32(ru)) => {
318 Ok(CmpValue::U8((lu as i32).wrapping_mul(ru) as u8))
319 }
320 (CmpValue::U8(lu), CmpValue::U64(ru)) => {
321 Ok(CmpValue::U8((lu as u64).wrapping_mul(ru) as u8))
322 }
323 (CmpValue::U8(lu), CmpValue::I64(ru)) => {
324 Ok(CmpValue::U8((lu as i64).wrapping_mul(ru) as u8))
325 }
326 (CmpValue::I8(lu), CmpValue::U8(ru)) => {
327 Ok(CmpValue::I8((lu as i16).wrapping_mul(ru as i16) as i8))
328 }
329 (CmpValue::I8(lu), CmpValue::I8(ru)) => Ok(CmpValue::I8(lu.wrapping_mul(ru))),
330 (CmpValue::I8(lu), CmpValue::U16(ru)) => {
331 Ok(CmpValue::I8((lu as i32).wrapping_mul(ru as i32) as i8))
332 }
333 (CmpValue::I8(lu), CmpValue::I16(ru)) => {
334 Ok(CmpValue::I8((lu as i16).wrapping_mul(ru) as i8))
335 }
336 (CmpValue::I8(lu), CmpValue::U32(ru)) => {
337 Ok(CmpValue::I8((lu as i64).wrapping_mul(ru as i64) as i8))
338 }
339 (CmpValue::I8(lu), CmpValue::I32(ru)) => {
340 Ok(CmpValue::I8((lu as i64).wrapping_mul(ru as i64) as i8))
341 }
342 (CmpValue::I8(lu), CmpValue::U64(ru)) => {
343 Ok(CmpValue::I8((lu as i64).wrapping_mul(ru as i64) as i8))
344 }
345 (CmpValue::I8(lu), CmpValue::I64(ru)) => {
346 Ok(CmpValue::I8((lu as i64).wrapping_mul(ru) as i8))
347 }
348 (CmpValue::U16(lu), CmpValue::U8(ru)) => {
349 Ok(CmpValue::U16(lu.wrapping_mul(ru as u16)))
350 }
351 (CmpValue::U16(lu), CmpValue::I8(ru)) => {
352 Ok(CmpValue::U16((lu as i32).wrapping_mul(ru as i32) as u16))
353 }
354 (CmpValue::U16(lu), CmpValue::U16(ru)) => {
355 Ok(CmpValue::U16(lu.wrapping_mul(ru)))
356 }
357 (CmpValue::U16(lu), CmpValue::I16(ru)) => {
358 Ok(CmpValue::U16((lu as i32).wrapping_mul(ru as i32) as u16))
359 }
360 (CmpValue::U16(lu), CmpValue::U32(ru)) => {
361 Ok(CmpValue::U16((lu as u32).wrapping_mul(ru) as u16))
362 }
363 (CmpValue::U16(lu), CmpValue::I32(ru)) => {
364 Ok(CmpValue::U16((lu as i32).wrapping_mul(ru) as u16))
365 }
366 (CmpValue::U16(lu), CmpValue::U64(ru)) => {
367 Ok(CmpValue::U16((lu as u64).wrapping_mul(ru) as u16))
368 }
369 (CmpValue::U16(lu), CmpValue::I64(ru)) => {
370 Ok(CmpValue::U16((lu as i64).wrapping_mul(ru) as u16))
371 }
372 (CmpValue::I16(lu), CmpValue::U8(ru)) => {
373 Ok(CmpValue::I16(lu.wrapping_mul(ru as i16)))
374 }
375 (CmpValue::I16(lu), CmpValue::I8(ru)) => {
376 Ok(CmpValue::I16(lu.wrapping_mul(ru as i16)))
377 }
378 (CmpValue::I16(lu), CmpValue::U16(ru)) => {
379 Ok(CmpValue::I16((lu as i32).wrapping_mul(ru as i32) as i16))
380 }
381 (CmpValue::I16(lu), CmpValue::I16(ru)) => {
382 Ok(CmpValue::I16(lu.wrapping_mul(ru)))
383 }
384 (CmpValue::I16(lu), CmpValue::U32(ru)) => {
385 Ok(CmpValue::I16((lu as i64).wrapping_mul(ru as i64) as i16))
386 }
387 (CmpValue::I16(lu), CmpValue::I32(ru)) => {
388 Ok(CmpValue::I16((lu as i32).wrapping_mul(ru) as i16))
389 }
390 (CmpValue::I16(lu), CmpValue::U64(ru)) => {
391 Ok(CmpValue::I16((lu as i64).wrapping_mul(ru as i64) as i16))
392 }
393 (CmpValue::I16(lu), CmpValue::I64(ru)) => {
394 Ok(CmpValue::I16((lu as i64).wrapping_mul(ru) as i16))
395 }
396 (CmpValue::U32(lu), CmpValue::U8(ru)) => {
397 Ok(CmpValue::U32(lu.wrapping_mul(ru as u32)))
398 }
399 (CmpValue::U32(lu), CmpValue::I8(ru)) => {
400 Ok(CmpValue::U32((lu as i64).wrapping_mul(ru as i64) as u32))
401 }
402 (CmpValue::U32(lu), CmpValue::U16(ru)) => {
403 Ok(CmpValue::U32(lu.wrapping_mul(ru as u32)))
404 }
405 (CmpValue::U32(lu), CmpValue::I16(ru)) => {
406 Ok(CmpValue::U32((lu as i64).wrapping_mul(ru as i64) as u32))
407 }
408 (CmpValue::U32(lu), CmpValue::U32(ru)) => {
409 Ok(CmpValue::U32(lu.wrapping_mul(ru)))
410 }
411 (CmpValue::U32(lu), CmpValue::I32(ru)) => {
412 Ok(CmpValue::U32((lu as i64).wrapping_mul(ru as i64) as u32))
413 }
414 (CmpValue::U32(lu), CmpValue::U64(ru)) => {
415 Ok(CmpValue::U32((lu as u64).wrapping_mul(ru) as u32))
416 }
417 (CmpValue::U32(lu), CmpValue::I64(ru)) => {
418 Ok(CmpValue::U32((lu as i64).wrapping_mul(ru) as u32))
419 }
420 (CmpValue::I32(lu), CmpValue::U8(ru)) => {
421 Ok(CmpValue::I32(lu.wrapping_mul(ru as i32)))
422 }
423 (CmpValue::I32(lu), CmpValue::I8(ru)) => {
424 Ok(CmpValue::I32(lu.wrapping_mul(ru as i32)))
425 }
426 (CmpValue::I32(lu), CmpValue::U16(ru)) => {
427 Ok(CmpValue::I32(lu.wrapping_mul(ru as i32)))
428 }
429 (CmpValue::I32(lu), CmpValue::I16(ru)) => {
430 Ok(CmpValue::I32(lu.wrapping_mul(ru as i32)))
431 }
432 (CmpValue::I32(lu), CmpValue::U32(ru)) => {
433 Ok(CmpValue::I32((lu as i64).wrapping_mul(ru as i64) as i32))
434 }
435 (CmpValue::I32(lu), CmpValue::I32(ru)) => {
436 Ok(CmpValue::I32(lu.wrapping_mul(ru)))
437 }
438 (CmpValue::I32(lu), CmpValue::U64(ru)) => {
439 Ok(CmpValue::I32((lu as i64).wrapping_mul(ru as i64) as i32))
440 }
441 (CmpValue::I32(lu), CmpValue::I64(ru)) => {
442 Ok(CmpValue::I32((lu as i64).wrapping_mul(ru) as i32))
443 }
444 (CmpValue::U64(lu), CmpValue::U8(ru)) => {
445 Ok(CmpValue::U64(lu.wrapping_mul(ru as u64)))
446 }
447 (CmpValue::U64(lu), CmpValue::I8(ru)) => {
448 Ok(CmpValue::U64((lu as i64).wrapping_mul(ru as i64) as u64))
449 }
450 (CmpValue::U64(lu), CmpValue::U16(ru)) => {
451 Ok(CmpValue::U64(lu.wrapping_mul(ru as u64)))
452 }
453 (CmpValue::U64(lu), CmpValue::I16(ru)) => {
454 Ok(CmpValue::U64((lu as i64).wrapping_mul(ru as i64) as u64))
455 }
456 (CmpValue::U64(lu), CmpValue::U32(ru)) => {
457 Ok(CmpValue::U64(lu.wrapping_mul(ru as u64)))
458 }
459 (CmpValue::U64(lu), CmpValue::I32(ru)) => {
460 Ok(CmpValue::U64((lu as i64).wrapping_mul(ru as i64) as u64))
461 }
462 (CmpValue::U64(lu), CmpValue::U64(ru)) => {
463 Ok(CmpValue::U64(lu.wrapping_mul(ru)))
464 }
465 (CmpValue::U64(lu), CmpValue::I64(ru)) => {
466 Ok(CmpValue::U64((lu as i64).wrapping_mul(ru) as u64))
467 }
468 (CmpValue::I64(lu), CmpValue::U8(ru)) => {
469 Ok(CmpValue::I64(lu.wrapping_mul(ru as i64)))
470 }
471 (CmpValue::I64(lu), CmpValue::I8(ru)) => {
472 Ok(CmpValue::I64(lu.wrapping_mul(ru as i64)))
473 }
474 (CmpValue::I64(lu), CmpValue::U16(ru)) => {
475 Ok(CmpValue::I64(lu.wrapping_mul(ru as i64)))
476 }
477 (CmpValue::I64(lu), CmpValue::I16(ru)) => {
478 Ok(CmpValue::I64(lu.wrapping_mul(ru as i64)))
479 }
480 (CmpValue::I64(lu), CmpValue::U32(ru)) => {
481 Ok(CmpValue::I64(lu.wrapping_mul(ru as i64)))
482 }
483 (CmpValue::I64(lu), CmpValue::I32(ru)) => {
484 Ok(CmpValue::I64(lu.wrapping_mul(ru as i64)))
485 }
486 (CmpValue::I64(lu), CmpValue::U64(ru)) => {
487 Ok(CmpValue::I64(lu.wrapping_mul(ru as i64)))
488 }
489 (CmpValue::I64(lu), CmpValue::I64(ru)) => {
490 Ok(CmpValue::I64(lu.wrapping_mul(ru)))
491 }
492 _ => bail!("Cannot multiply non-integral types"),
493 }
494 }
495 CmpExpr::Add((l, r)) => {
496 let lv = self.simplify(l)?;
497 let rv = self.simplify(r)?;
498
499 match (lv, rv) {
500 (CmpValue::U8(lu), CmpValue::U8(ru)) => Ok(CmpValue::U8(lu.wrapping_add(ru))),
501 (CmpValue::U8(lu), CmpValue::I8(ru)) => {
502 Ok(CmpValue::U8(lu.wrapping_add_signed(ru)))
503 }
504 (CmpValue::U8(lu), CmpValue::U16(ru)) => {
505 Ok(CmpValue::U8((lu as u16).wrapping_add(ru) as u8))
506 }
507 (CmpValue::U8(lu), CmpValue::I16(ru)) => {
508 Ok(CmpValue::U8((lu as u16).wrapping_add_signed(ru) as u8))
509 }
510 (CmpValue::U8(lu), CmpValue::U32(ru)) => {
511 Ok(CmpValue::U8((lu as u32).wrapping_add(ru) as u8))
512 }
513 (CmpValue::U8(lu), CmpValue::I32(ru)) => {
514 Ok(CmpValue::U8((lu as u32).wrapping_add_signed(ru) as u8))
515 }
516 (CmpValue::U8(lu), CmpValue::U64(ru)) => {
517 Ok(CmpValue::U8((lu as u64).wrapping_add(ru) as u8))
518 }
519 (CmpValue::U8(lu), CmpValue::I64(ru)) => {
520 Ok(CmpValue::U8((lu as u64).wrapping_add_signed(ru) as u8))
521 }
522 (CmpValue::I8(lu), CmpValue::U8(ru)) => {
523 Ok(CmpValue::I8(lu.wrapping_add_unsigned(ru)))
524 }
525 (CmpValue::I8(lu), CmpValue::I8(ru)) => Ok(CmpValue::I8(lu.wrapping_add(ru))),
526 (CmpValue::I8(lu), CmpValue::U16(ru)) => {
527 Ok(CmpValue::I8((lu as i16).wrapping_add_unsigned(ru) as i8))
528 }
529 (CmpValue::I8(lu), CmpValue::I16(ru)) => {
530 Ok(CmpValue::I8((lu as i16).wrapping_add(ru) as i8))
531 }
532 (CmpValue::I8(lu), CmpValue::U32(ru)) => {
533 Ok(CmpValue::I8((lu as i32).wrapping_add_unsigned(ru) as i8))
534 }
535 (CmpValue::I8(lu), CmpValue::I32(ru)) => {
536 Ok(CmpValue::I8((lu as i32).wrapping_add(ru) as i8))
537 }
538 (CmpValue::I8(lu), CmpValue::U64(ru)) => {
539 Ok(CmpValue::I8((lu as i64).wrapping_add_unsigned(ru) as i8))
540 }
541 (CmpValue::I8(lu), CmpValue::I64(ru)) => {
542 Ok(CmpValue::I8((lu as i64).wrapping_add(ru) as i8))
543 }
544 (CmpValue::U16(lu), CmpValue::U8(ru)) => {
545 Ok(CmpValue::U16(lu.wrapping_add(ru as u16)))
546 }
547 (CmpValue::U16(lu), CmpValue::I8(ru)) => {
548 Ok(CmpValue::U16(lu.wrapping_add_signed(ru as i16)))
549 }
550 (CmpValue::U16(lu), CmpValue::U16(ru)) => {
551 Ok(CmpValue::U16(lu.wrapping_add(ru)))
552 }
553 (CmpValue::U16(lu), CmpValue::I16(ru)) => {
554 Ok(CmpValue::U16(lu.wrapping_add_signed(ru)))
555 }
556 (CmpValue::U16(lu), CmpValue::U32(ru)) => {
557 Ok(CmpValue::U16((lu as u32).wrapping_add(ru) as u16))
558 }
559 (CmpValue::U16(lu), CmpValue::I32(ru)) => {
560 Ok(CmpValue::U16((lu as u32).wrapping_add_signed(ru) as u16))
561 }
562 (CmpValue::U16(lu), CmpValue::U64(ru)) => {
563 Ok(CmpValue::U16((lu as u64).wrapping_add(ru) as u16))
564 }
565 (CmpValue::U16(lu), CmpValue::I64(ru)) => {
566 Ok(CmpValue::U16((lu as u64).wrapping_add_signed(ru) as u16))
567 }
568 (CmpValue::I16(lu), CmpValue::U8(ru)) => {
569 Ok(CmpValue::I16(lu.wrapping_add_unsigned(ru as u16)))
570 }
571 (CmpValue::I16(lu), CmpValue::I8(ru)) => {
572 Ok(CmpValue::I16(lu.wrapping_add(ru as i16)))
573 }
574 (CmpValue::I16(lu), CmpValue::U16(ru)) => {
575 Ok(CmpValue::I16(lu.wrapping_add_unsigned(ru)))
576 }
577 (CmpValue::I16(lu), CmpValue::I16(ru)) => {
578 Ok(CmpValue::I16(lu.wrapping_add(ru)))
579 }
580 (CmpValue::I16(lu), CmpValue::U32(ru)) => {
581 Ok(CmpValue::I16((lu as i32).wrapping_add_unsigned(ru) as i16))
582 }
583 (CmpValue::I16(lu), CmpValue::I32(ru)) => {
584 Ok(CmpValue::I16((lu as i32).wrapping_add(ru) as i16))
585 }
586 (CmpValue::I16(lu), CmpValue::U64(ru)) => {
587 Ok(CmpValue::I16((lu as i64).wrapping_add_unsigned(ru) as i16))
588 }
589 (CmpValue::I16(lu), CmpValue::I64(ru)) => {
590 Ok(CmpValue::I16((lu as i64).wrapping_add(ru) as i16))
591 }
592 (CmpValue::U32(lu), CmpValue::U8(ru)) => {
593 Ok(CmpValue::U32(lu.wrapping_add(ru as u32)))
594 }
595 (CmpValue::U32(lu), CmpValue::I8(ru)) => {
596 Ok(CmpValue::U32(lu.wrapping_add_signed(ru as i32)))
597 }
598 (CmpValue::U32(lu), CmpValue::U16(ru)) => {
599 Ok(CmpValue::U32(lu.wrapping_add(ru as u32)))
600 }
601 (CmpValue::U32(lu), CmpValue::I16(ru)) => {
602 Ok(CmpValue::U32(lu.wrapping_add_signed(ru as i32)))
603 }
604 (CmpValue::U32(lu), CmpValue::U32(ru)) => {
605 Ok(CmpValue::U32(lu.wrapping_add(ru)))
606 }
607 (CmpValue::U32(lu), CmpValue::I32(ru)) => {
608 Ok(CmpValue::U32(lu.wrapping_add_signed(ru)))
609 }
610 (CmpValue::U32(lu), CmpValue::U64(ru)) => {
611 Ok(CmpValue::U32((lu as u64).wrapping_add(ru) as u32))
612 }
613 (CmpValue::U32(lu), CmpValue::I64(ru)) => {
614 Ok(CmpValue::U32((lu as u64).wrapping_add_signed(ru) as u32))
615 }
616 (CmpValue::I32(lu), CmpValue::U8(ru)) => {
617 Ok(CmpValue::I32(lu.wrapping_add_unsigned(ru as u32)))
618 }
619 (CmpValue::I32(lu), CmpValue::I8(ru)) => {
620 Ok(CmpValue::I32(lu.wrapping_add(ru as i32)))
621 }
622 (CmpValue::I32(lu), CmpValue::U16(ru)) => {
623 Ok(CmpValue::I32(lu.wrapping_add_unsigned(ru as u32)))
624 }
625 (CmpValue::I32(lu), CmpValue::I16(ru)) => {
626 Ok(CmpValue::I32(lu.wrapping_add(ru as i32)))
627 }
628 (CmpValue::I32(lu), CmpValue::U32(ru)) => {
629 Ok(CmpValue::I32(lu.wrapping_add_unsigned(ru)))
630 }
631 (CmpValue::I32(lu), CmpValue::I32(ru)) => {
632 Ok(CmpValue::I32(lu.wrapping_add(ru)))
633 }
634 (CmpValue::I32(lu), CmpValue::U64(ru)) => {
635 Ok(CmpValue::I32((lu as i64).wrapping_add_unsigned(ru) as i32))
636 }
637 (CmpValue::I32(lu), CmpValue::I64(ru)) => {
638 Ok(CmpValue::I32((lu as i64).wrapping_add(ru) as i32))
639 }
640 (CmpValue::U64(lu), CmpValue::U8(ru)) => {
641 Ok(CmpValue::U64(lu.wrapping_add(ru as u64)))
642 }
643 (CmpValue::U64(lu), CmpValue::I8(ru)) => {
644 Ok(CmpValue::U64(lu.wrapping_add_signed(ru as i64)))
645 }
646 (CmpValue::U64(lu), CmpValue::U16(ru)) => {
647 Ok(CmpValue::U64(lu.wrapping_add(ru as u64)))
648 }
649 (CmpValue::U64(lu), CmpValue::I16(ru)) => {
650 Ok(CmpValue::U64(lu.wrapping_add_signed(ru as i64)))
651 }
652 (CmpValue::U64(lu), CmpValue::U32(ru)) => {
653 Ok(CmpValue::U64(lu.wrapping_add(ru as u64)))
654 }
655 (CmpValue::U64(lu), CmpValue::I32(ru)) => {
656 Ok(CmpValue::U64(lu.wrapping_add_signed(ru as i64)))
657 }
658 (CmpValue::U64(lu), CmpValue::U64(ru)) => {
659 Ok(CmpValue::U64(lu.wrapping_add(ru)))
660 }
661 (CmpValue::U64(lu), CmpValue::I64(ru)) => {
662 Ok(CmpValue::U64(lu.wrapping_add_signed(ru)))
663 }
664 (CmpValue::I64(lu), CmpValue::U8(ru)) => {
665 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru as u64)))
666 }
667 (CmpValue::I64(lu), CmpValue::I8(ru)) => {
668 Ok(CmpValue::I64(lu.wrapping_add(ru as i64)))
669 }
670 (CmpValue::I64(lu), CmpValue::U16(ru)) => {
671 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru as u64)))
672 }
673 (CmpValue::I64(lu), CmpValue::I16(ru)) => {
674 Ok(CmpValue::I64(lu.wrapping_add(ru as i64)))
675 }
676 (CmpValue::I64(lu), CmpValue::U32(ru)) => {
677 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru as u64)))
678 }
679 (CmpValue::I64(lu), CmpValue::I32(ru)) => {
680 Ok(CmpValue::I64(lu.wrapping_add(ru as i64)))
681 }
682 (CmpValue::I64(lu), CmpValue::U64(ru)) => {
683 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru)))
684 }
685 (CmpValue::I64(lu), CmpValue::I64(ru)) => {
686 Ok(CmpValue::I64(lu.wrapping_add(ru)))
687 }
688 _ => bail!("Cannot multiply non-integral types"),
689 }
690 }
691 CmpExpr::U8(_)
692 | CmpExpr::I8(_)
693 | CmpExpr::U16(_)
694 | CmpExpr::I16(_)
695 | CmpExpr::U32(_)
696 | CmpExpr::I32(_)
697 | CmpExpr::U64(_)
698 | CmpExpr::I64(_) => Ok(CmpValue::try_from(expr)?),
699 CmpExpr::Addr(a) => {
700 let address = self
701 .processor_info_v2
702 .logical_to_physical(*a, Access::Sim_Access_Read)?;
703 let bytes: [u8; 8] =
704 read_phys_memory(self.cpu, address.address, size_of::<u64>() as i32)?
705 .to_le_bytes();
706 Ok(CmpValue::U64(u64::from_le_bytes(bytes)))
707 }
708 _ => {
709 bail!("Unsupported expression type")
711 }
712 }
713 }
714}
715
716pub(crate) struct Disassembler {
717 decoder: InstDecoder,
718 last: Option<Instruction>,
719}
720
721impl Disassembler {
722 pub fn new() -> Self {
723 Self {
724 decoder: InstDecoder::default(),
725 last: None,
726 }
727 }
728}
729
730impl Default for Disassembler {
731 fn default() -> Self {
732 Self::new()
733 }
734}
735
736impl TryFrom<(&Operand, Option<u8>)> for CmpExpr {
737 type Error = Error;
738
739 fn try_from(value: (&Operand, Option<u8>)) -> Result<Self> {
740 let width = value.1;
741 let value = value.0;
742
743 let expr = match value {
744 Operand::ImmediateI8 { imm } => CmpExpr::I8(*imm),
745 Operand::ImmediateU8 { imm } => CmpExpr::U8(*imm),
746 Operand::ImmediateI16 { imm } => CmpExpr::I16(*imm),
747 Operand::ImmediateU16 { imm } => CmpExpr::U16(*imm),
748 Operand::ImmediateI32 { imm } => CmpExpr::I32(*imm),
749 Operand::ImmediateU32 { imm } => CmpExpr::U32(*imm),
750 Operand::ImmediateI64 { imm } => CmpExpr::I64(*imm),
751 Operand::ImmediateU64 { imm } => CmpExpr::U64(*imm),
752 Operand::Register { reg } => CmpExpr::Reg((reg.name().to_string(), reg.width())),
753 Operand::AbsoluteU32 { addr } => CmpExpr::Addr(*addr as u64),
754 Operand::AbsoluteU64 { addr } => CmpExpr::Addr(*addr),
755 Operand::MemDeref { base } => CmpExpr::Deref((
756 Box::new(CmpExpr::Reg((base.name().to_string(), base.width()))),
757 width,
758 )),
759 Operand::Disp { base, disp } => CmpExpr::Deref((
760 Box::new(CmpExpr::Add((
761 Box::new(CmpExpr::Reg((base.name().to_string(), base.width()))),
762 Box::new(CmpExpr::I32(*disp)),
763 ))),
764 width,
765 )),
766 Operand::MemIndexScale { index, scale } => CmpExpr::Deref((
767 Box::new(CmpExpr::Mul((
768 Box::new(CmpExpr::Reg((index.name().to_string(), index.width()))),
769 Box::new(CmpExpr::U8(*scale)),
770 ))),
771 width,
772 )),
773 Operand::MemIndexScaleDisp { index, scale, disp } => CmpExpr::Deref((
774 Box::new(CmpExpr::Add((
775 Box::new(CmpExpr::Mul((
776 Box::new(CmpExpr::Reg((index.name().to_string(), index.width()))),
777 Box::new(CmpExpr::U8(*scale)),
778 ))),
779 Box::new(CmpExpr::I32(*disp)),
780 ))),
781 width,
782 )),
783 Operand::MemBaseIndexScale { base, index, scale } => CmpExpr::Deref((
784 Box::new(CmpExpr::Add((
785 Box::new(CmpExpr::Reg((base.name().to_string(), base.width()))),
786 Box::new(CmpExpr::Add((
787 Box::new(CmpExpr::Reg((index.name().to_string(), index.width()))),
788 Box::new(CmpExpr::U8(*scale)),
789 ))),
790 ))),
791 width,
792 )),
793 Operand::MemBaseIndexScaleDisp {
794 base,
795 index,
796 scale,
797 disp,
798 } => CmpExpr::Deref((
799 Box::new(CmpExpr::Add((
800 Box::new(CmpExpr::Add((
801 Box::new(CmpExpr::Reg((base.name().to_string(), base.width()))),
802 Box::new(CmpExpr::Add((
803 Box::new(CmpExpr::Reg((index.name().to_string(), index.width()))),
804 Box::new(CmpExpr::U8(*scale)),
805 ))),
806 ))),
807 Box::new(CmpExpr::I32(*disp)),
808 ))),
809 width,
810 )),
811 _ => {
812 bail!("Unsupported operand type for cmplog");
813 }
814 };
815 Ok(expr)
816 }
817}
818
819impl TracerDisassembler for Disassembler {
820 fn last_was_control_flow(&self) -> bool {
822 if let Some(last) = self.last {
823 if matches!(
824 last.opcode(),
825 Opcode::JMP
826 | Opcode::JA
827 | Opcode::JB
828 | Opcode::JRCXZ
829 | Opcode::JG
830 | Opcode::JGE
831 | Opcode::JL
832 | Opcode::JLE
833 | Opcode::JNA
834 | Opcode::JNB
835 | Opcode::JNO
836 | Opcode::JNP
837 | Opcode::JNS
838 | Opcode::JNZ
839 | Opcode::JO
840 | Opcode::JP
841 | Opcode::JS
842 | Opcode::JZ
843 | Opcode::LOOP
844 | Opcode::LOOPNZ
845 | Opcode::LOOPZ
846 ) {
847 return true;
848 }
849 }
850 false
851 }
852
853 fn last_was_call(&self) -> bool {
855 if let Some(last) = self.last {
856 return matches!(
857 last.opcode(),
858 Opcode::CALL
859 | Opcode::CALLF
860 | Opcode::INT
861 | Opcode::INTO
862 | Opcode::SYSCALL
863 | Opcode::SYSENTER
864 );
865 }
866
867 false
868 }
869
870 fn last_was_ret(&self) -> bool {
872 if let Some(last) = self.last {
873 return matches!(
874 last.opcode(),
875 Opcode::RETF
876 | Opcode::RETURN
877 | Opcode::IRET
878 | Opcode::IRETD
879 | Opcode::IRETQ
880 | Opcode::SYSRET
881 | Opcode::SYSEXIT
882 );
883 }
884
885 false
886 }
887
888 fn last_was_cmp(&self) -> bool {
890 if let Some(last) = self.last {
891 return matches!(
892 last.opcode(),
893 Opcode::CMP
894 | Opcode::CMPPD
895 | Opcode::CMPS
896 | Opcode::CMPSD
897 | Opcode::CMPSS
898 | Opcode::CMPXCHG16B
899 | Opcode::COMISD
900 | Opcode::COMISS
901 | Opcode::FCOM
902 | Opcode::FCOMI
903 | Opcode::FCOMIP
904 | Opcode::FCOMP
905 | Opcode::FCOMPP
906 | Opcode::FICOM
907 | Opcode::FICOMP
908 | Opcode::FTST
909 | Opcode::FUCOM
910 | Opcode::FUCOMI
911 | Opcode::FUCOMIP
912 | Opcode::FUCOMP
913 | Opcode::FXAM
914 | Opcode::PCMPEQB
915 | Opcode::PCMPEQD
916 | Opcode::PCMPEQW
917 | Opcode::PCMPGTB
918 | Opcode::PCMPGTD
919 | Opcode::PCMPGTQ
920 | Opcode::PCMPGTW
921 | Opcode::PMAXSB
922 | Opcode::PMAXSD
923 | Opcode::PMAXUD
924 | Opcode::PMAXUW
925 | Opcode::PMINSB
926 | Opcode::PMINSD
927 | Opcode::PMINUD
928 | Opcode::PMINUW
929 | Opcode::TEST
930 | Opcode::UCOMISD
931 | Opcode::UCOMISS
932 | Opcode::VPCMPB
933 | Opcode::VPCMPD
934 | Opcode::VPCMPQ
935 | Opcode::VPCMPUB
936 | Opcode::VPCMPUD
937 | Opcode::VPCMPUQ
938 | Opcode::VPCMPUW
939 | Opcode::VPCMPW
940 );
941 }
942
943 false
944 }
945
946 fn disassemble(&mut self, bytes: &[u8]) -> Result<()> {
947 if let Ok(insn) = self.decoder.decode_slice(bytes) {
948 self.last = Some(insn);
949 } else {
950 bail!("Could not disassemble {:?}", bytes);
951 }
952
953 Ok(())
954 }
955
956 fn disassemble_to_string(&mut self, bytes: &[u8]) -> Result<String> {
957 if let Ok(insn) = self.decoder.decode_slice(bytes) {
958 Ok(insn.to_string())
959 } else {
960 bail!("Could not disassemble {:?}", bytes);
961 }
962 }
963
964 fn cmp(&self) -> Vec<CmpExpr> {
965 let mut cmp_exprs = Vec::new();
966 if self.last_was_cmp() {
967 if let Some(last) = self.last {
968 for op_idx in 0..last.operand_count() {
969 let op = last.operand(op_idx);
970 let width = if let Some(width) = op.width() {
971 Some(width)
972 } else if let Some(width) = last.mem_size() {
973 width.bytes_size()
974 } else {
975 None
976 };
977 if let Ok(expr) = CmpExpr::try_from((&op, width)) {
978 cmp_exprs.push(expr);
979 }
980 }
981 }
982 }
983 cmp_exprs
984 }
985
986 fn cmp_type(&self) -> Vec<CmpType> {
987 if self.last_was_cmp() {
988 if let Some(last) = self.last {
989 if let Some(condition) = last.opcode().condition() {
990 return match condition {
991 ConditionCode::O => vec![],
993 ConditionCode::NO => vec![],
995 ConditionCode::B => vec![CmpType::Lesser],
997 ConditionCode::AE => vec![CmpType::Greater, CmpType::Equal],
999 ConditionCode::Z => vec![],
1001 ConditionCode::NZ => vec![],
1003 ConditionCode::A => vec![CmpType::Greater],
1005 ConditionCode::BE => vec![CmpType::Lesser, CmpType::Equal],
1007 ConditionCode::S => vec![],
1009 ConditionCode::NS => vec![],
1011 ConditionCode::P => vec![],
1013 ConditionCode::NP => vec![],
1015 ConditionCode::L => vec![CmpType::Lesser],
1017 ConditionCode::GE => vec![CmpType::Greater, CmpType::Equal],
1019 ConditionCode::G => vec![CmpType::Greater],
1021 ConditionCode::LE => vec![CmpType::Lesser, CmpType::Equal],
1023 };
1024 }
1025 }
1026 }
1027
1028 vec![]
1029 }
1030}