diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index a72b9d40..3aea4d53 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -519,7 +519,7 @@ impl IcicleEmulator { }; } - pub fn read_register(&mut self, reg: registers::X64Register, buffer: &mut [u8]) -> usize { + fn read_generic_register(&mut self, reg: registers::X64Register, buffer: &mut [u8]) -> usize { let reg_node = self.reg.get_node(reg); let res = self.vm.cpu.read_dynamic(pcode::Value::Var(reg_node)); @@ -531,7 +531,58 @@ impl IcicleEmulator { return reg_node.size.into(); } + + fn read_flags(&mut self, data: &mut [u8]) -> usize + { + const REAL_SIZE: usize = std::mem::size_of::(); + let limit: usize = std::mem::size_of::(); + let size = std::cmp::min(REAL_SIZE, limit); + + let flags: u64 = self.reg.get_flags(&mut self.vm.cpu); + + let copy_size = std::cmp::min(data.len(), size); + data[..copy_size].copy_from_slice(&flags.to_ne_bytes()[..copy_size]); + + return limit; + } + + pub fn read_register(&mut self, reg: registers::X64Register, data: &mut [u8]) -> usize { + match reg { + registers::X64Register::Rflags => self.read_flags::(data), + registers::X64Register::Eflags => self.read_flags::(data), + registers::X64Register::Flags => self.read_flags::(data), + _ => self.read_generic_register(reg, data), + } + } + + fn write_flags(&mut self, data: &[u8]) -> usize + { + const REAL_SIZE: usize = std::mem::size_of::(); + let limit: usize = std::mem::size_of::(); + let size = std::cmp::min(REAL_SIZE, limit); + let copy_size = std::cmp::min(data.len(), size); + + let mut buffer = [0u8; REAL_SIZE]; + self.read_flags::(&mut buffer); + + buffer[..copy_size].copy_from_slice(&data[..copy_size]); + + let flags = u64::from_ne_bytes(buffer); + self.reg.set_flags(&mut self.vm.cpu, flags); + + return limit; + } + pub fn write_register(&mut self, reg: registers::X64Register, data: &[u8]) -> usize { + match reg { + registers::X64Register::Rflags => self.write_flags::(data), + registers::X64Register::Eflags => self.write_flags::(data), + registers::X64Register::Flags => self.write_flags::(data), + _ => self.write_generic_register(reg, data), + } + } + + fn write_generic_register(&mut self, reg: registers::X64Register, data: &[u8]) -> usize { let reg_node = self.reg.get_node(reg); let mut buffer = [0u8; 32]; @@ -541,71 +592,25 @@ impl IcicleEmulator { //let value = icicle_cpu::regs::DynamicValue::new(buffer, reg_node.size.into()); //self.vm.cpu.write_trunc(reg_node, value); + let cpu = &mut self.vm.cpu; + match reg_node.size { - 1 => self - .vm - .cpu - .write_var::<[u8; 1]>(reg_node, buffer[..1].try_into().expect("")), - 2 => self - .vm - .cpu - .write_var::<[u8; 2]>(reg_node, buffer[..2].try_into().expect("")), - 3 => self - .vm - .cpu - .write_var::<[u8; 3]>(reg_node, buffer[..3].try_into().expect("")), - 4 => self - .vm - .cpu - .write_var::<[u8; 4]>(reg_node, buffer[..4].try_into().expect("")), - 5 => self - .vm - .cpu - .write_var::<[u8; 5]>(reg_node, buffer[..5].try_into().expect("")), - 6 => self - .vm - .cpu - .write_var::<[u8; 6]>(reg_node, buffer[..6].try_into().expect("")), - 7 => self - .vm - .cpu - .write_var::<[u8; 7]>(reg_node, buffer[..7].try_into().expect("")), - 8 => self - .vm - .cpu - .write_var::<[u8; 8]>(reg_node, buffer[..8].try_into().expect("")), - 9 => self - .vm - .cpu - .write_var::<[u8; 9]>(reg_node, buffer[..9].try_into().expect("")), - 10 => self - .vm - .cpu - .write_var::<[u8; 10]>(reg_node, buffer[..10].try_into().expect("")), - 11 => self - .vm - .cpu - .write_var::<[u8; 11]>(reg_node, buffer[..11].try_into().expect("")), - 12 => self - .vm - .cpu - .write_var::<[u8; 12]>(reg_node, buffer[..12].try_into().expect("")), - 13 => self - .vm - .cpu - .write_var::<[u8; 13]>(reg_node, buffer[..13].try_into().expect("")), - 14 => self - .vm - .cpu - .write_var::<[u8; 14]>(reg_node, buffer[..14].try_into().expect("")), - 15 => self - .vm - .cpu - .write_var::<[u8; 15]>(reg_node, buffer[..15].try_into().expect("")), - 16 => self - .vm - .cpu - .write_var::<[u8; 16]>(reg_node, buffer[..16].try_into().expect("")), + 1 => cpu.write_var::<[u8; 1]>(reg_node, buffer[..1].try_into().unwrap()), + 2 => cpu.write_var::<[u8; 2]>(reg_node, buffer[..2].try_into().unwrap()), + 3 => cpu.write_var::<[u8; 3]>(reg_node, buffer[..3].try_into().unwrap()), + 4 => cpu.write_var::<[u8; 4]>(reg_node, buffer[..4].try_into().unwrap()), + 5 => cpu.write_var::<[u8; 5]>(reg_node, buffer[..5].try_into().unwrap()), + 6 => cpu.write_var::<[u8; 6]>(reg_node, buffer[..6].try_into().unwrap()), + 7 => cpu.write_var::<[u8; 7]>(reg_node, buffer[..7].try_into().unwrap()), + 8 => cpu.write_var::<[u8; 8]>(reg_node, buffer[..8].try_into().unwrap()), + 9 => cpu.write_var::<[u8; 9]>(reg_node, buffer[..9].try_into().unwrap()), + 10 => cpu.write_var::<[u8; 10]>(reg_node, buffer[..10].try_into().unwrap()), + 11 => cpu.write_var::<[u8; 11]>(reg_node, buffer[..11].try_into().unwrap()), + 12 => cpu.write_var::<[u8; 12]>(reg_node, buffer[..12].try_into().unwrap()), + 13 => cpu.write_var::<[u8; 13]>(reg_node, buffer[..13].try_into().unwrap()), + 14 => cpu.write_var::<[u8; 14]>(reg_node, buffer[..14].try_into().unwrap()), + 15 => cpu.write_var::<[u8; 15]>(reg_node, buffer[..15].try_into().unwrap()), + 16 => cpu.write_var::<[u8; 16]>(reg_node, buffer[..16].try_into().unwrap()), _ => panic!("invalid dynamic value size"), } diff --git a/src/icicle/src/registers.rs b/src/icicle/src/registers.rs index 67c3543e..c32243ec 100644 --- a/src/icicle/src/registers.rs +++ b/src/icicle/src/registers.rs @@ -262,7 +262,6 @@ pub(crate) struct X64RegisterNodes { r14: pcode::VarNode, r15: pcode::VarNode, rip: pcode::VarNode, - eflags: pcode::VarNode, cs: pcode::VarNode, ds: pcode::VarNode, es: pcode::VarNode, @@ -467,18 +466,22 @@ pub(crate) struct X64RegisterNodes { mxcsr: pcode::VarNode, fs_base: pcode::VarNode, gs_base: pcode::VarNode, - flags: pcode::VarNode, - rflags: pcode::VarNode, fip: pcode::VarNode, fcs: pcode::VarNode, fdp: pcode::VarNode, fds: pcode::VarNode, fop: pcode::VarNode, + flags: Vec, } impl X64RegisterNodes { pub fn new(arch: &icicle_cpu::Arch) -> Self { let r = |name: &str| arch.sleigh.get_reg(name).unwrap().var; + let nodes = [ + "CF", "F1", "PF", "F3", "AF", "F5", "ZF", "SF", "TF", "IF", "DF", "OF", "IOPL", "NT", + "F15", "RF", "VM", "AC", "VIF", "VIP", "ID", + ]; + Self { rax: r("RAX"), rbx: r("RBX"), @@ -497,7 +500,6 @@ impl X64RegisterNodes { r14: r("R14"), r15: r("R15"), rip: r("RIP"), - eflags: r("eflags"), cs: r("CS"), ds: r("DS"), es: r("ES"), @@ -699,8 +701,6 @@ impl X64RegisterNodes { fpcw: r("FPUControlWord"), fptag: r("FPUTagWord"), mxcsr: r("MXCSR"), - flags: r("flags"), - rflags: r("rflags"), fip: r("FPUInstructionPointer"), fdp: r("FPUDataPointer"), fop: r("FPULastInstructionOpcode"), @@ -709,6 +709,25 @@ impl X64RegisterNodes { //msr: r("MSR"), fs_base: r("FS_OFFSET"), gs_base: r("GS_OFFSET"), + flags: nodes.map(|name: &str| r(name)).to_vec(), + } + } + + pub fn get_flags(&self, cpu: &mut icicle_cpu::Cpu) -> u64 { + let mut res: u64 = 0; + + for (index, element) in self.flags.iter().enumerate() { + let flag = cpu.read_reg(*element); + res |= (flag & 1) << index; + } + + res + } + + pub fn set_flags(&self, cpu: &mut icicle_cpu::Cpu, value: u64) { + for (index, element) in self.flags.iter().enumerate() { + let flag = (value >> index) & 1; + cpu.write_reg(*element, flag); } } @@ -731,7 +750,6 @@ impl X64RegisterNodes { X64Register::R14 => self.r14, X64Register::R15 => self.r15, X64Register::Rip => self.rip, - X64Register::Eflags => self.eflags, X64Register::Cs => self.cs, X64Register::Ds => self.ds, X64Register::Es => self.es, @@ -936,8 +954,6 @@ impl X64RegisterNodes { X64Register::Mxcsr => self.mxcsr, X64Register::FsBase => self.fs_base, X64Register::GsBase => self.gs_base, - X64Register::Flags => self.flags, - X64Register::Rflags => self.rflags, X64Register::Fip => self.fip, X64Register::Fcs => self.fcs, X64Register::Fdp => self.fdp,