1 //
2 // Copyright © 2020 Intel Corporation
3 //
4 // SPDX-License-Identifier: Apache-2.0
5 //
6
7 use iced_x86::*;
8
9 use crate::arch::emulator::{EmulationError, PlatformEmulator, PlatformError};
10 use crate::arch::x86::emulator::CpuStateManager;
11 use crate::arch::x86::Exception;
12
13 pub mod cmp;
14 pub mod mov;
15 pub mod movs;
16 pub mod or;
17 pub mod stos;
18
get_op<T: CpuStateManager>( insn: &Instruction, op_index: u32, op_size: usize, state: &T, platform: &dyn PlatformEmulator<CpuState = T>, ) -> Result<u64, PlatformError>19 fn get_op<T: CpuStateManager>(
20 insn: &Instruction,
21 op_index: u32,
22 op_size: usize,
23 state: &T,
24 platform: &dyn PlatformEmulator<CpuState = T>,
25 ) -> Result<u64, PlatformError> {
26 if insn.op_count() < op_index + 1 {
27 return Err(PlatformError::InvalidOperand(anyhow!(
28 "Invalid operand {:?}",
29 op_index
30 )));
31 }
32
33 if !matches!(op_size, 1 | 2 | 4 | 8) {
34 return Err(PlatformError::InvalidOperand(anyhow!(
35 "Invalid operand size {:?}",
36 op_size
37 )));
38 }
39
40 let value = match insn
41 .try_op_kind(op_index)
42 .map_err(|e| PlatformError::InvalidOperand(e.into()))?
43 {
44 OpKind::Register => state.read_reg(
45 insn.try_op_register(op_index)
46 .map_err(|e| PlatformError::InvalidOperand(e.into()))?,
47 )?,
48 OpKind::Memory => {
49 let addr = memory_operand_address(insn, state, false)?;
50 let mut memory: [u8; 8] = [0; 8];
51 platform.read_memory(addr, &mut memory[0..op_size])?;
52 <u64>::from_le_bytes(memory)
53 }
54 OpKind::Immediate8 => insn.immediate8() as u64,
55 OpKind::Immediate8to16 => insn.immediate8to16() as u64,
56 OpKind::Immediate8to32 => insn.immediate8to32() as u64,
57 OpKind::Immediate8to64 => insn.immediate8to64() as u64,
58 OpKind::Immediate16 => insn.immediate16() as u64,
59 OpKind::Immediate32 => insn.immediate32() as u64,
60 OpKind::Immediate32to64 => insn.immediate32to64() as u64,
61 OpKind::Immediate64 => insn.immediate64(),
62 k => return Err(PlatformError::InvalidOperand(anyhow!("{:?}", k))),
63 };
64
65 Ok(value)
66 }
67
set_op<T: CpuStateManager>( insn: &Instruction, op_index: u32, op_size: usize, state: &mut T, platform: &mut dyn PlatformEmulator<CpuState = T>, value: u64, ) -> Result<(), PlatformError>68 fn set_op<T: CpuStateManager>(
69 insn: &Instruction,
70 op_index: u32,
71 op_size: usize,
72 state: &mut T,
73 platform: &mut dyn PlatformEmulator<CpuState = T>,
74 value: u64,
75 ) -> Result<(), PlatformError> {
76 if insn.op_count() < op_index + 1 {
77 return Err(PlatformError::InvalidOperand(anyhow!(
78 "Invalid operand {:?}",
79 op_index
80 )));
81 }
82
83 if !matches!(op_size, 1 | 2 | 4 | 8) {
84 return Err(PlatformError::InvalidOperand(anyhow!(
85 "Invalid operand size {:?}",
86 op_size
87 )));
88 }
89
90 match insn
91 .try_op_kind(op_index)
92 .map_err(|e| PlatformError::InvalidOperand(e.into()))?
93 {
94 OpKind::Register => state.write_reg(
95 insn.try_op_register(op_index)
96 .map_err(|e| PlatformError::InvalidOperand(e.into()))?,
97 value,
98 )?,
99 OpKind::Memory => {
100 let addr = memory_operand_address(insn, state, true)?;
101 platform.write_memory(addr, &value.to_le_bytes()[..op_size])?;
102 }
103 k => return Err(PlatformError::InvalidOperand(anyhow!("{:?}", k))),
104 };
105
106 Ok(())
107 }
108
109 // Returns the linear a.k.a. virtual address for a memory operand.
memory_operand_address<T: CpuStateManager>( insn: &Instruction, state: &T, write: bool, ) -> Result<u64, PlatformError>110 fn memory_operand_address<T: CpuStateManager>(
111 insn: &Instruction,
112 state: &T,
113 write: bool,
114 ) -> Result<u64, PlatformError> {
115 let mut address: u64 = 0;
116
117 if insn.memory_base() != iced_x86::Register::None {
118 let base: u64 = state.read_reg(insn.memory_base())?;
119 address = address.wrapping_add(base);
120 }
121
122 if insn.memory_index() != iced_x86::Register::None {
123 let mut index: u64 = state.read_reg(insn.memory_index())?;
124 index = index.wrapping_mul(insn.memory_index_scale() as u64);
125
126 address = address.wrapping_add(index);
127 }
128
129 address = address.wrapping_add(insn.memory_displacement64());
130
131 // Translate to a linear address.
132 state.linearize(insn.memory_segment(), address, write)
133 }
134
135 pub trait InstructionHandler<T: CpuStateManager> {
emulate( &self, insn: &Instruction, state: &mut T, platform: &mut dyn PlatformEmulator<CpuState = T>, ) -> Result<(), EmulationError<Exception>>136 fn emulate(
137 &self,
138 insn: &Instruction,
139 state: &mut T,
140 platform: &mut dyn PlatformEmulator<CpuState = T>,
141 ) -> Result<(), EmulationError<Exception>>;
142 }
143