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