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 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 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. 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 += 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 *= insn.memory_index_scale() as u64; 125 126 address += 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> { 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 144 macro_rules! insn_format { 145 ($insn:ident) => {{ 146 let mut output = String::new(); 147 let mut formatter = FastFormatter::new(); 148 formatter 149 .options_mut() 150 .set_space_after_operand_separator(true); 151 formatter.format(&$insn, &mut output); 152 153 output 154 }}; 155 } 156