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