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