From 25df7f699b2662a30086aed0410faf1ab07b1248 Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Wed, 25 Dec 2024 15:31:37 -0500 Subject: [PATCH 01/11] move emu to mod and fix rep vs repe --- Cargo.toml | 1 - src/config.rs | 2 ++ src/{emu.rs => emu/mod.rs} | 30 +++++++++++++++++++++++++----- 3 files changed, 27 insertions(+), 6 deletions(-) rename src/{emu.rs => emu/mod.rs} (99%) diff --git a/Cargo.toml b/Cargo.toml index 33e767f..99e0a7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ documentation = "https://docs.rs/libscemu/0.4.15/libscemu/" repository = "https://github.com/sha0coder/libscemu" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] iced-x86 = "1.19.0" uint = "0.9.5" diff --git a/src/config.rs b/src/config.rs index cf98027..6f048f0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -18,6 +18,7 @@ pub struct Config { pub console2: bool, pub console_addr: u64, pub entry_point: u64, + pub exit_position: u64, pub code_base_addr: u64, pub is_64bits: bool, // 64bits mode pub stack_trace: bool, @@ -50,6 +51,7 @@ impl Config { console2: false, console_addr: 0, entry_point: 0x3c0000, + exit_position: 0, code_base_addr: 0x3c0000, is_64bits: false, stack_trace: false, diff --git a/src/emu.rs b/src/emu/mod.rs similarity index 99% rename from src/emu.rs rename to src/emu/mod.rs index ed0afe1..7338df4 100644 --- a/src/emu.rs +++ b/src/emu/mod.rs @@ -4671,11 +4671,31 @@ impl Emu { self.rep = Some(rep_count + 1); } } - if ins.has_repe_prefix() && !self.flags.f_zf { - self.rep = None; - } - if ins.has_repne_prefix() && self.flags.f_zf { - self.rep = None; + + let is_string_movement = matches!( + ins.mnemonic(), + Mnemonic::Movsb | Mnemonic::Movsw | Mnemonic::Movsd | Mnemonic::Movsq | + Mnemonic::Stosb | Mnemonic::Stosw | Mnemonic::Stosd | Mnemonic::Stosq | + Mnemonic::Lodsb | Mnemonic::Lodsw | Mnemonic::Lodsd | Mnemonic::Lodsq + ); + + let is_string_comparison = matches!( + ins.mnemonic(), + Mnemonic::Cmpsb | Mnemonic::Cmpsw | Mnemonic::Cmpsd | Mnemonic::Cmpsq | + Mnemonic::Scasb | Mnemonic::Scasw | Mnemonic::Scasd | Mnemonic::Scasq + ); + + if is_string_movement { + + } else if is_string_comparison { + if ins.has_repe_prefix() && !self.flags.f_zf { + self.rep = None; + } + if ins.has_repne_prefix() && self.flags.f_zf { + self.rep = None; + } + } else { + unimplemented!("string instruction not supported"); } } From f075c3c998e35a582df989e225e1e8837f4c7aa9 Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Wed, 25 Dec 2024 15:33:12 -0500 Subject: [PATCH 02/11] comment --- src/emu/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/emu/mod.rs b/src/emu/mod.rs index 7338df4..7fd7c33 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -4672,21 +4672,20 @@ impl Emu { } } + // repe and repe are the same on x86 (0xf3) so you have to check if it is movement or comparison let is_string_movement = matches!( ins.mnemonic(), Mnemonic::Movsb | Mnemonic::Movsw | Mnemonic::Movsd | Mnemonic::Movsq | Mnemonic::Stosb | Mnemonic::Stosw | Mnemonic::Stosd | Mnemonic::Stosq | Mnemonic::Lodsb | Mnemonic::Lodsw | Mnemonic::Lodsd | Mnemonic::Lodsq ); - let is_string_comparison = matches!( ins.mnemonic(), Mnemonic::Cmpsb | Mnemonic::Cmpsw | Mnemonic::Cmpsd | Mnemonic::Cmpsq | Mnemonic::Scasb | Mnemonic::Scasw | Mnemonic::Scasd | Mnemonic::Scasq ); - if is_string_movement { - + // do not clear rep if it is a string movement } else if is_string_comparison { if ins.has_repe_prefix() && !self.flags.f_zf { self.rep = None; From 9bfd59734f49ab99d05e3c8fd3d80ea94abdb45b Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Wed, 25 Dec 2024 15:36:12 -0500 Subject: [PATCH 03/11] add exit logic --- src/emu/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/emu/mod.rs b/src/emu/mod.rs index 7fd7c33..e2ac8aa 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -417,7 +417,6 @@ impl Emu { pub fn init(&mut self, clear_registers: bool, clear_flags: bool) { self.pos = 0; - if !atty::is(Stream::Stdout) { self.cfg.nocolors = true; self.colors.disable(); @@ -4422,6 +4421,12 @@ impl Emu { pub fn step(&mut self) -> bool { self.pos += 1; + // exit + if self.cfg.exit_position != 0 && self.pos == self.cfg.exit_position { + log::info!("exit position reached"); + std::process::exit(0); + } + // code let code = match self.maps.get_mem_by_addr(self.regs.rip) { Some(c) => c, @@ -4437,8 +4442,8 @@ impl Emu { // block let block = code.read_from(self.regs.rip).to_vec(); // reduce code block for more speed - // - // decoder + + // decoder let mut decoder; if self.cfg.is_64bits { decoder = Decoder::with_ip(64, &block, self.regs.rip, DecoderOptions::NONE); From 74df5efc132c62dc4080d9c0f4c45f7dfae77860 Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Wed, 25 Dec 2024 15:40:53 -0500 Subject: [PATCH 04/11] add exit logic --- src/emu/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/emu/mod.rs b/src/emu/mod.rs index e2ac8aa..d88d9ec 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -4550,7 +4550,6 @@ impl Emu { //let mut position:usize = 0; //let mut instruction_bytes:Vec = Vec::new(); - self.rep = None; while decoder.can_decode() { if self.rep.is_none() { @@ -4572,6 +4571,11 @@ impl Emu { self.memory_operations.clear(); self.pos += 1; + if self.cfg.exit_position != 0 && self.pos == self.cfg.exit_position { + log::info!("exit position reached"); + std::process::exit(0); + } + if self.exp == self.pos || self.pos == self.bp.get_instruction() || self.bp.get_bp() == addr From 970d5a45633435a4c2348f66ebc3de7856a2f0b1 Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Wed, 25 Dec 2024 15:58:24 -0500 Subject: [PATCH 05/11] add8 change? --- src/emu/flags.rs | 29 +++++++++++++++++++---------- src/emu/mod.rs | 44 +++++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/emu/flags.rs b/src/emu/flags.rs index 1239ccc..44c74e5 100644 --- a/src/emu/flags.rs +++ b/src/emu/flags.rs @@ -396,17 +396,26 @@ impl Flags { } pub fn add8(&mut self, value1: u64, value2: u64) -> u64 { - let unsigned: u16 = value1 as u8 as u16 + value2 as u8 as u16; - - self.f_sf = (unsigned as i8) < 0; - self.f_zf = (unsigned & 0xff) == 0; - self.calc_pf(unsigned as u8); - let (result, carry) = (value2 as u8).overflowing_add(value1 as u8); - let (_, overflow) = (value2 as u8 as i8).overflowing_add(value1 as u8 as i8); - self.f_of = overflow; - self.f_cf = carry; + // First add the values as u8s + let first_result = (value1 as u8).wrapping_add(value2 as u8); + // Then add carry into that result + let result = first_result; + + // Check carry from first addition + let (_, first_carry) = (value2 as u8).overflowing_add(value1 as u8); + // Check carry from carry addition + self.f_cf = first_carry; + + // Similar for overflow - we need to check both steps + let (_, first_overflow) = (value2 as u8 as i8).overflowing_add(value1 as u8 as i8); + self.f_of = first_overflow; + + // Rest of flags based on final result + self.f_sf = (result as i8) < 0; + self.f_zf = result == 0; + self.calc_pf(result); self.calc_af(value1, value2, result as u64, 8); - + result as u64 } diff --git a/src/emu/mod.rs b/src/emu/mod.rs index d88d9ec..a8f4f5b 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -5142,35 +5142,37 @@ impl Emu { Mnemonic::Adc => { self.show_instruction(&self.colors.cyan, &ins); - + assert!(ins.op_count() == 2); - - let cf: u64; - if self.flags.f_cf { - cf = 1 - } else { - cf = 0; - } - - let value0 = match self.get_operand_value(&ins, 0, true) { + + // Get current carry flag value + let cf = if self.flags.f_cf { 1 } else { 0 }; + + // Get the size first to ensure consistent handling + let size = self.get_operand_sz(&ins, 1); + + // Get destination value (first operand) + let dest = match self.get_operand_value(&ins, 0, true) { Some(v) => v, None => return false, }; - - let value1 = match self.get_operand_value(&ins, 1, true) { + + // Get source value (second operand) + let src = match self.get_operand_value(&ins, 1, true) { Some(v) => v, None => return false, }; - - let res: u64; - match self.get_operand_sz(&ins, 1) { - 64 => res = self.flags.add64(value0, value1 + cf), - 32 => res = self.flags.add32(value0, value1 + cf), - 16 => res = self.flags.add16(value0, value1 + cf), - 8 => res = self.flags.add8(value0, value1 + cf), + + // Do the addition with carry + let res = match size { + 64 => self.flags.add64(dest, src + cf), + 32 => self.flags.add32(dest, src + cf), + 16 => self.flags.add16(dest, src + cf), + 8 => self.flags.add8(dest, src + cf), _ => unreachable!("weird size"), - } - + }; + + // Set the result if !self.set_operand_value(&ins, 0, res) { return false; } From 3a8dd4b7f3aa6f6686a3ae4c428ed764d838f9df Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Wed, 25 Dec 2024 16:07:33 -0500 Subject: [PATCH 06/11] needs to be a separate flag? --- src/emu/flags.rs | 25 ++++++++++++------------- src/emu/mod.rs | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/emu/flags.rs b/src/emu/flags.rs index 44c74e5..d2eff67 100644 --- a/src/emu/flags.rs +++ b/src/emu/flags.rs @@ -395,20 +395,19 @@ impl Flags { result as u64 } - pub fn add8(&mut self, value1: u64, value2: u64) -> u64 { - // First add the values as u8s - let first_result = (value1 as u8).wrapping_add(value2 as u8); - // Then add carry into that result - let result = first_result; - - // Check carry from first addition - let (_, first_carry) = (value2 as u8).overflowing_add(value1 as u8); - // Check carry from carry addition - self.f_cf = first_carry; + pub fn add8(&mut self, value1: u64, value2: u64, input_cf: bool) -> u64 { + // Do full addition including carry + let result = (value1 as u8).wrapping_add(value2 as u8).wrapping_add(if input_cf { 1 } else { 0 }); + + // Check carry by doing additions step by step + let (temp, first_carry) = (value2 as u8).overflowing_add(value1 as u8); + let (_, second_carry) = temp.overflowing_add(if input_cf { 1 } else { 0 }); + self.f_cf = first_carry || second_carry; - // Similar for overflow - we need to check both steps - let (_, first_overflow) = (value2 as u8 as i8).overflowing_add(value1 as u8 as i8); - self.f_of = first_overflow; + // Similar for overflow + let (temp_s, first_overflow) = (value2 as u8 as i8).overflowing_add(value1 as u8 as i8); + let (_, second_overflow) = temp_s.overflowing_add(if input_cf { 1 } else { 0 }); + self.f_of = first_overflow || second_overflow; // Rest of flags based on final result self.f_sf = (result as i8) < 0; diff --git a/src/emu/mod.rs b/src/emu/mod.rs index a8f4f5b..eb18cc9 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -5128,10 +5128,10 @@ impl Emu { }; let res: u64 = match self.get_operand_sz(&ins, 1) { - 64 => self.flags.add64(value0, value1), - 32 => self.flags.add32(value0, value1), - 16 => self.flags.add16(value0, value1), - 8 => self.flags.add8(value0, value1), + 64 => self.flags.add64(value0, value1), // TODO: cf as separate argument + 32 => self.flags.add32(value0, value1), // TODO: cf as separate argument + 16 => self.flags.add16(value0, value1), // TODO: cf as separate argument + 8 => self.flags.add8(value0, value1, self.flags.f_cf), _ => unreachable!("weird size"), }; @@ -5165,10 +5165,10 @@ impl Emu { // Do the addition with carry let res = match size { - 64 => self.flags.add64(dest, src + cf), - 32 => self.flags.add32(dest, src + cf), - 16 => self.flags.add16(dest, src + cf), - 8 => self.flags.add8(dest, src + cf), + 64 => self.flags.add64(dest, src + cf), // TODO: cf as separate argument + 32 => self.flags.add32(dest, src + cf), // TODO: cf as separate argument + 16 => self.flags.add16(dest, src + cf), // TODO: cf as separate argument + 8 => self.flags.add8(dest, src, self.flags.f_cf), _ => unreachable!("weird size"), }; @@ -6588,10 +6588,10 @@ impl Emu { } let res: u64 = match self.get_operand_sz(&ins, 1) { - 64 => self.flags.add64(value0, value1), - 32 => self.flags.add32(value0, value1), - 16 => self.flags.add16(value0, value1), - 8 => self.flags.add8(value0, value1), + 64 => self.flags.add64(value0, value1), // TODO: cf as separate argument + 32 => self.flags.add32(value0, value1), // TODO: cf as separate argument + 16 => self.flags.add16(value0, value1), // TODO: cf as separate argument + 8 => self.flags.add8(value0, value1, self.flags.f_cf), _ => unreachable!("weird size"), }; From eebe094b391f391ece9d5a9b969570671f5dcb27 Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Wed, 25 Dec 2024 16:40:26 -0500 Subject: [PATCH 07/11] add8 adc did not work --- src/emu/flags.rs | 30 +++++++++--------------- src/emu/mod.rs | 60 +++++++++++++++++++++++------------------------- 2 files changed, 40 insertions(+), 50 deletions(-) diff --git a/src/emu/flags.rs b/src/emu/flags.rs index d2eff67..1239ccc 100644 --- a/src/emu/flags.rs +++ b/src/emu/flags.rs @@ -395,26 +395,18 @@ impl Flags { result as u64 } - pub fn add8(&mut self, value1: u64, value2: u64, input_cf: bool) -> u64 { - // Do full addition including carry - let result = (value1 as u8).wrapping_add(value2 as u8).wrapping_add(if input_cf { 1 } else { 0 }); - - // Check carry by doing additions step by step - let (temp, first_carry) = (value2 as u8).overflowing_add(value1 as u8); - let (_, second_carry) = temp.overflowing_add(if input_cf { 1 } else { 0 }); - self.f_cf = first_carry || second_carry; - - // Similar for overflow - let (temp_s, first_overflow) = (value2 as u8 as i8).overflowing_add(value1 as u8 as i8); - let (_, second_overflow) = temp_s.overflowing_add(if input_cf { 1 } else { 0 }); - self.f_of = first_overflow || second_overflow; - - // Rest of flags based on final result - self.f_sf = (result as i8) < 0; - self.f_zf = result == 0; - self.calc_pf(result); + pub fn add8(&mut self, value1: u64, value2: u64) -> u64 { + let unsigned: u16 = value1 as u8 as u16 + value2 as u8 as u16; + + self.f_sf = (unsigned as i8) < 0; + self.f_zf = (unsigned & 0xff) == 0; + self.calc_pf(unsigned as u8); + let (result, carry) = (value2 as u8).overflowing_add(value1 as u8); + let (_, overflow) = (value2 as u8 as i8).overflowing_add(value1 as u8 as i8); + self.f_of = overflow; + self.f_cf = carry; self.calc_af(value1, value2, result as u64, 8); - + result as u64 } diff --git a/src/emu/mod.rs b/src/emu/mod.rs index eb18cc9..d88d9ec 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -5128,10 +5128,10 @@ impl Emu { }; let res: u64 = match self.get_operand_sz(&ins, 1) { - 64 => self.flags.add64(value0, value1), // TODO: cf as separate argument - 32 => self.flags.add32(value0, value1), // TODO: cf as separate argument - 16 => self.flags.add16(value0, value1), // TODO: cf as separate argument - 8 => self.flags.add8(value0, value1, self.flags.f_cf), + 64 => self.flags.add64(value0, value1), + 32 => self.flags.add32(value0, value1), + 16 => self.flags.add16(value0, value1), + 8 => self.flags.add8(value0, value1), _ => unreachable!("weird size"), }; @@ -5142,37 +5142,35 @@ impl Emu { Mnemonic::Adc => { self.show_instruction(&self.colors.cyan, &ins); - + assert!(ins.op_count() == 2); - - // Get current carry flag value - let cf = if self.flags.f_cf { 1 } else { 0 }; - - // Get the size first to ensure consistent handling - let size = self.get_operand_sz(&ins, 1); - - // Get destination value (first operand) - let dest = match self.get_operand_value(&ins, 0, true) { + + let cf: u64; + if self.flags.f_cf { + cf = 1 + } else { + cf = 0; + } + + let value0 = match self.get_operand_value(&ins, 0, true) { Some(v) => v, None => return false, }; - - // Get source value (second operand) - let src = match self.get_operand_value(&ins, 1, true) { + + let value1 = match self.get_operand_value(&ins, 1, true) { Some(v) => v, None => return false, }; - - // Do the addition with carry - let res = match size { - 64 => self.flags.add64(dest, src + cf), // TODO: cf as separate argument - 32 => self.flags.add32(dest, src + cf), // TODO: cf as separate argument - 16 => self.flags.add16(dest, src + cf), // TODO: cf as separate argument - 8 => self.flags.add8(dest, src, self.flags.f_cf), + + let res: u64; + match self.get_operand_sz(&ins, 1) { + 64 => res = self.flags.add64(value0, value1 + cf), + 32 => res = self.flags.add32(value0, value1 + cf), + 16 => res = self.flags.add16(value0, value1 + cf), + 8 => res = self.flags.add8(value0, value1 + cf), _ => unreachable!("weird size"), - }; - - // Set the result + } + if !self.set_operand_value(&ins, 0, res) { return false; } @@ -6588,10 +6586,10 @@ impl Emu { } let res: u64 = match self.get_operand_sz(&ins, 1) { - 64 => self.flags.add64(value0, value1), // TODO: cf as separate argument - 32 => self.flags.add32(value0, value1), // TODO: cf as separate argument - 16 => self.flags.add16(value0, value1), // TODO: cf as separate argument - 8 => self.flags.add8(value0, value1, self.flags.f_cf), + 64 => self.flags.add64(value0, value1), + 32 => self.flags.add32(value0, value1), + 16 => self.flags.add16(value0, value1), + 8 => self.flags.add8(value0, value1), _ => unreachable!("weird size"), }; From 8e902af69a71439c3be2d4375251dbafb6d1074a Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Wed, 25 Dec 2024 17:22:22 -0500 Subject: [PATCH 08/11] adc change? --- src/emu/mod.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/emu/mod.rs b/src/emu/mod.rs index d88d9ec..dfdb11f 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -5162,15 +5162,21 @@ impl Emu { None => return false, }; + let rflags = self.flags.dump(); + log::info!("DEBUG: adc value0: 0x{:x}, value1: 0x{:x}, cf: 0x{:x}, rflags: 0x{:x}", value0, value1, cf, rflags); + let res: u64; match self.get_operand_sz(&ins, 1) { - 64 => res = self.flags.add64(value0, value1 + cf), - 32 => res = self.flags.add32(value0, value1 + cf), - 16 => res = self.flags.add16(value0, value1 + cf), - 8 => res = self.flags.add8(value0, value1 + cf), + 64 => res = self.flags.add64(value0, value1.wrapping_add(cf)), + 32 => res = self.flags.add32(value0, (value1 & 0xffffffff).wrapping_add(cf)), + 16 => res = self.flags.add16(value0, (value1 & 0xffff).wrapping_add(cf)), + 8 => res = self.flags.add8(value0, (value1 & 0xff).wrapping_add(cf)), _ => unreachable!("weird size"), } + let rflags = self.flags.dump(); + log::info!("DEBUG: adc res: 0x{:x}, rflags: 0x{:x}", res, rflags); + if !self.set_operand_value(&ins, 0, res) { return false; } @@ -5197,9 +5203,9 @@ impl Emu { let sz = self.get_operand_sz(&ins, 1); match sz { 64 => res = self.flags.sub64(value0, value1.wrapping_add(cf)), - 32 => res = self.flags.sub32(value0, value1.wrapping_add(cf)), - 16 => res = self.flags.sub16(value0, value1.wrapping_add(cf)), - 8 => res = self.flags.sub8(value0, value1.wrapping_add(cf)), + 32 => res = self.flags.sub32(value0, (value1 & 0xffffffff).wrapping_add(cf)), + 16 => res = self.flags.sub16(value0, (value1 & 0xffff).wrapping_add(cf)), + 8 => res = self.flags.sub8(value0, (value1 & 0xff).wrapping_add(cf)), _ => panic!("weird size"), } From 38f5df8bdee39400830b36d54d6ff0415cafb217 Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Thu, 26 Dec 2024 11:44:37 -0500 Subject: [PATCH 09/11] fix add8 --- src/emu/flags.rs | 246 ++++++++++++++++++++++++++++++++-------------- src/emu/mod.rs | 75 +++++--------- src/emu/regs64.rs | 2 +- 3 files changed, 198 insertions(+), 125 deletions(-) diff --git a/src/emu/flags.rs b/src/emu/flags.rs index 1239ccc..42aeac2 100644 --- a/src/emu/flags.rs +++ b/src/emu/flags.rs @@ -86,14 +86,6 @@ impl Flags { } } - pub fn diff(rip: u64, pos: u64, a: Flags, b: Flags) -> String { - let mut output = String::new(); - if a.dump() != b.dump() { - output = format!("rflags: {:x} -> {:x}; ", a.dump(), b.dump()); - } - output - } - pub fn clear(&mut self) { self.f_cf = false; self.f_pf = false; @@ -139,6 +131,83 @@ impl Flags { log::info!("---"); } + pub fn diff(a: Flags, b: Flags) -> String { + let mut output = String::new(); + // f_cf + if a.f_cf != b.f_cf { + output = format!("{}{}: {} -> {} ", output, "cf", a.f_cf, b.f_cf); + } + // f_pf + if a.f_pf != b.f_pf { + output = format!("{}{}: {} -> {} ", output, "pf", a.f_pf, b.f_pf); + } + // f_af + if a.f_af != b.f_af { + output = format!("{}{}: {} -> {} ", output, "af", a.f_af, b.f_af); + } + // f_zf + if a.f_zf != b.f_zf { + output = format!("{}{}: {} -> {} ", output, "zf", a.f_zf, b.f_zf); + } + // f_sf + if a.f_sf != b.f_sf { + output = format!("{}{}: {} -> {} ", output, "sf", a.f_sf, b.f_sf); + } + // f_tf + if a.f_tf != b.f_tf { + output = format!("{}{}: {} -> {} ", output, "tf", a.f_tf, b.f_tf); + } + // f_if + if a.f_if != b.f_if { + output = format!("{}{}: {} -> {} ", output, "if", a.f_if, b.f_if); + } + // f_df + if a.f_df != b.f_df { + output = format!("{}{}: {} -> {} ", output, "df", a.f_df, b.f_df); + } + // f_of + if a.f_of != b.f_of { + output = format!("{}{}: {} -> {} ", output, "of", a.f_of, b.f_of); + } + // f_iopl1 + if a.f_iopl1 != b.f_iopl1 { + output = format!("{}{}: {} -> {} ", output, "iopl1", a.f_iopl1, b.f_iopl1); + } + // f_iopl2 + if a.f_iopl2 != b.f_iopl2 { + output = format!("{}{}: {} -> {} ", output, "iopl2", a.f_iopl2, b.f_iopl2); + } + // f_nt + if a.f_nt != b.f_nt { + output = format!("{}{}: {} -> {} ", output, "nt", a.f_nt, b.f_nt); + } + // f_rf + if a.f_rf != b.f_rf { + output = format!("{}{}: {} -> {} ", output, "rf", a.f_rf, b.f_rf); + } + // f_vm + if a.f_vm != b.f_vm { + output = format!("{}{}: {} -> {} ", output, "vm", a.f_vm, b.f_vm); + } + // f_ac + if a.f_ac != b.f_ac { + output = format!("{}{}: {} -> {} ", output, "ac", a.f_ac, b.f_ac); + } + // f_vif + if a.f_vif != b.f_vif { + output = format!("{}{}: {} -> {} ", output, "vif", a.f_vif, b.f_vif); + } + // f_vip + if a.f_vip != b.f_vip { + output = format!("{}{}: {} -> {} ", output, "vip", a.f_vip, b.f_vip); + } + // f_id + if a.f_id != b.f_id { + output = format!("{}{}: {} -> {} ", output, "id", a.f_id, b.f_id); + } + output + } + pub fn dump(&self) -> u32 { let mut flags: u32 = 0; @@ -336,77 +405,106 @@ impl Flags { //self.f_af = (value1 & 0x0f) + (value2 & 0x0f) > 0x09; } - - - pub fn add64(&mut self, value1: u64, value2: u64) -> u64 { - let unsigned: u128 = value1 as u128 + value2 as u128; - - self.f_sf = (unsigned as i64) < 0; - self.f_zf = (unsigned & 0xffffffff_ffffffff) == 0; - //self.f_pf = (unsigned & 0xff) % 2 == 0; - self.calc_pf(unsigned as u8); - let (result, carry) = (value2).overflowing_add(value1); - let (_, overflow) = (value2 as i64).overflowing_add(value1 as i64); - self.f_of = overflow; - self.f_cf = carry; - self.calc_af(value1, value2, result, 64); + pub fn add64(&mut self, value1: u64, value2: u64, cf: bool, include_carry: bool) -> u64 { + let v1 = value1; + let v2 = value2; + let c = if include_carry { cf as u64 } else { 0 }; - /* - let low_nibble_value1 = value1 & 0xf; - let low_nibble_value2 = value2 & 0xf; - self.f_af = (low_nibble_value1 > 0x7) && (low_nibble_value2 > 0x7); - */ - + let result = v1.wrapping_add(v2).wrapping_add(c); + let sum = v1 as u128 + v2 as u128 + c as u128; + + self.f_cf = sum > 0xFFFFFFFFFFFFFFFF; + self.f_sf = (result as i64) < 0; + self.f_zf = result == 0; + self.calc_pf(result as u8); + + let sign1 = (v1 >> 63) & 1; + let sign2 = (v2 >> 63) & 1; + let signr = (result >> 63) & 1; + self.f_of = (sign1 == sign2) && (sign1 != signr); + + self.calc_af(v1, v2, result, 64); result } - - pub fn add32(&mut self, value1: u64, value2: u64) -> u64 { - let unsigned: u64 = value1 + value2; - - self.f_sf = (unsigned as i32) < 0; - self.f_zf = (unsigned & 0xffffffff) == 0; - //self.f_pf = (unsigned & 0xff) % 2 == 0; - self.calc_pf(unsigned as u8); - let (result, carry) = (value2 as u32).overflowing_add(value1 as u32); - let (_, overflow) = (value2 as u32 as i32).overflowing_add(value1 as u32 as i32); - self.f_of = overflow; - self.f_cf = carry; - self.calc_af(value1, value2, result as u64, 32); - + + pub fn add32(&mut self, value1: u32, value2: u32, cf: bool, include_carry: bool) -> u64 { + let result = if include_carry { + value1.wrapping_add(value2).wrapping_add(cf as u32) + } else { + value1.wrapping_add(value2) + }; + + let sum = if include_carry { + value1 as u64 + value2 as u64 + cf as u64 + } else { + value1 as u64 + value2 as u64 + }; + + self.f_cf = sum > 0xFFFFFFFF; + self.f_sf = (result as i32) < 0; + self.f_zf = result == 0; + self.calc_pf(result as u8); + + let sign1 = (value1 >> 31) & 1; + let sign2 = (value2 >> 31) & 1; + let signr = (result >> 31) & 1; + self.f_of = (sign1 == sign2) && (sign1 != signr); + + self.calc_af(value1 as u64, value2 as u64, result as u64, 32); result as u64 - } - - pub fn add16(&mut self, value1: u64, value2: u64) -> u64 { - if value1 > 0xffff || value2 > 0xffff { - panic!("add16 with a bigger precision"); - } - - let unsigned: u32 = value1 as u32 + value2 as u32; - - self.f_sf = (unsigned as i16) < 0; - self.f_zf = (unsigned & 0xffff) == 0; - self.calc_pf(unsigned as u8); - let (result, carry) = (value2 as u16).overflowing_add(value1 as u16); - let (_, overflow) = (value2 as u16 as i16).overflowing_add(value1 as u16 as i16); - self.f_of = overflow; - self.f_cf = carry; - self.calc_af(value1, value2, result as u64, 16); - + } + + pub fn add16(&mut self, value1: u16, value2: u16, cf: bool, include_carry: bool) -> u64 { + let result = if include_carry { + value1.wrapping_add(value2).wrapping_add(cf as u16) + } else { + value1.wrapping_add(value2) + }; + + let sum = if include_carry { + value1 as u32 + value2 as u32 + cf as u32 + } else { + value1 as u32 + value2 as u32 + }; + + self.f_cf = sum > 0xFFFF; + self.f_sf = (result as i16) < 0; + self.f_zf = result == 0; + self.calc_pf(result as u8); + + let sign1 = (value1 >> 15) & 1; + let sign2 = (value2 >> 15) & 1; + let signr = (result >> 15) & 1; + self.f_of = (sign1 == sign2) && (sign1 != signr); + + self.calc_af(value1 as u64, value2 as u64, result as u64, 16); result as u64 - } - - pub fn add8(&mut self, value1: u64, value2: u64) -> u64 { - let unsigned: u16 = value1 as u8 as u16 + value2 as u8 as u16; - - self.f_sf = (unsigned as i8) < 0; - self.f_zf = (unsigned & 0xff) == 0; - self.calc_pf(unsigned as u8); - let (result, carry) = (value2 as u8).overflowing_add(value1 as u8); - let (_, overflow) = (value2 as u8 as i8).overflowing_add(value1 as u8 as i8); - self.f_of = overflow; - self.f_cf = carry; - self.calc_af(value1, value2, result as u64, 8); - + } + + pub fn add8(&mut self, value1: u8, value2: u8, cf: bool, include_carry: bool) -> u64 { + let result = if include_carry { + value1.wrapping_add(value2).wrapping_add(cf as u8) + } else { + value1.wrapping_add(value2) + }; + + let sum = if include_carry { + value1 as u16 + value2 as u16 + cf as u16 + } else { + value1 as u16 + value2 as u16 + }; + + self.f_cf = sum > 0xFF; + self.f_sf = (result as i8) < 0; + self.f_zf = result == 0; + self.calc_pf(result as u8); + + let sign1 = (value1 >> 7) & 1; + let sign2 = (value2 >> 7) & 1; + let signr = (result >> 7) & 1; + self.f_of = (sign1 == sign2) && (sign1 != signr); + + self.calc_af(value1 as u64, value2 as u64, result as u64, 8); result as u64 } diff --git a/src/emu/mod.rs b/src/emu/mod.rs index dfdb11f..ca5e312 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -4264,35 +4264,16 @@ impl Emu { } pub fn write_to_trace_file(&mut self) { - // 00,00007FFBEF4E5FF0,EB 08,jmp 7FFBEF4E5FFA,rax: 7FFBEF4E5FF0-> 7FFBEF4E5FF0 rbx: 7FFE0385-> 7FFE0385 rcx: 7FFBEE4B0000-> 7FFBEE4B0000 rdx: 1-> 1 rsp: 98EB5DDFF8-> 98EB5DDFF8 rbp: 98EB5DE338-> 98EB5DE338 rsi: 1-> 1 rdi: 7FFE0384-> 7FFE0384 r8: 0-> 0 r9: 0-> 0 r10: A440AE23305F3A70-> A440AE23305F3A70 r11: 98EB5DE068-> 98EB5DE068 r12: 7FFBEF4E5FF0-> 7FFBEF4E5FF0 r13: 1FC18C72DC0-> 1FC18C72DC0 r14: 7FFBEE4B0000-> 7FFBEE4B0000 r15: 0-> 0 rflags: 344-> 246,,OptionalHeader.AddressOfEntryPoint - // 01,00007FFBEF4E5FFA,50,push rax,rsp: 98EB5DDFF8-> 98EB5DDFF0,00000098EB5DDFF0: 7FFC65FF8B8F-> 7FFBEF4E5FF0,rax:GetMsgProc+102D07D let index = self.pos - 1; let instruction = self.instruction.unwrap(); let instruction_bytes = &self.instruction_bytes; + let mut comments = String::new(); + // dump all registers on first, only differences on next let mut registers = String::new(); if index == 0 { - /* - rax: 7FFBEF4E5FF0->7FFBEF4E5FF0 - rbx: 7FFE0385->7FFE0385 - rcx: 7FFBEE4B0000->7FFBEE4B0000 - rdx: 1->1 - rsp: 98EB5DDFF8->98EB5DDFF8 - rbp: 98EB5DE338->98EB5DE338 - rsi: 1->1 - rdi: 7FFE0384->7FFE0384 - r8: 0->0 - r9: 0->0 - r10: A440AE23305F3A70->A440AE23305F3A70 - r11: 98EB5DE068->98EB5DE068 - r12: 7FFBEF4E5FF0->7FFBEF4E5FF0 - r13: 1FC18C72DC0->1FC18C72DC0 - r14: 7FFBEE4B0000->7FFBEE4B0000 - r15: 0->0 - rflags: 344->246 - */ registers = format!("{} rax: {:x}-> {:x}", registers, self.pre_op_regs.rax, self.post_op_regs.rax); registers = format!("{} rbx: {:x}-> {:x}", registers, self.pre_op_regs.rbx, self.post_op_regs.rbx); registers = format!("{} rcx: {:x}-> {:x}", registers, self.pre_op_regs.rcx, self.post_op_regs.rcx); @@ -4311,28 +4292,28 @@ impl Emu { registers = format!("{} r15: {:x}-> {:x}", registers, self.pre_op_regs.r15, self.post_op_regs.r15); } else { registers = Regs64::diff( - self.pre_op_regs.rip, - self.pos - 1, self.pre_op_regs, self.post_op_regs, ); } let mut flags = String::new(); + // dump all flags on first, only differences on next if index == 0 { flags = format!("rflags: {:x}-> {:x}", self.pre_op_flags.dump(), self.post_op_flags.dump()); } else { if self.pre_op_flags.dump() != self.post_op_flags.dump() { flags = format!("rflags: {:x}-> {:x}", self.pre_op_flags.dump(), self.post_op_flags.dump()); + comments = format!("{} {}", comments, Flags::diff(self.pre_op_flags, self.post_op_flags)); } } + // dump all write memory operations let mut memory = String::new(); for memory_op in self.memory_operations.iter() { if memory_op.op == "read" { continue; } - // 00000098EB5DDFF0: 7FFC65FF8B8F-> 7FFBEF4E5FF0 memory = format!("{} {:016X}: {:X}-> {:X}", memory, memory_op.address, memory_op.old_value, memory_op.new_value); } @@ -4346,7 +4327,7 @@ impl Emu { disassembly = self.out, registers = format!("{} {}", registers, flags), memory = memory, - comments = "" + comments = comments ).expect("failed to write to trace file"); } @@ -5128,10 +5109,10 @@ impl Emu { }; let res: u64 = match self.get_operand_sz(&ins, 1) { - 64 => self.flags.add64(value0, value1), - 32 => self.flags.add32(value0, value1), - 16 => self.flags.add16(value0, value1), - 8 => self.flags.add8(value0, value1), + 64 => self.flags.add64(value0, value1, self.flags.f_cf, false), + 32 => self.flags.add32((value0 & 0xffffffff) as u32, (value1 & 0xffffffff) as u32, self.flags.f_cf, false), + 16 => self.flags.add16((value0 & 0xffff) as u16, (value1 & 0xffff) as u16, self.flags.f_cf, false), + 8 => self.flags.add8((value0 & 0xff) as u8, (value1 & 0xff) as u8, self.flags.f_cf, false), _ => unreachable!("weird size"), }; @@ -5145,12 +5126,7 @@ impl Emu { assert!(ins.op_count() == 2); - let cf: u64; - if self.flags.f_cf { - cf = 1 - } else { - cf = 0; - } + let cf = self.flags.f_cf as u64; let value0 = match self.get_operand_value(&ins, 0, true) { Some(v) => v, @@ -5162,20 +5138,19 @@ impl Emu { None => return false, }; - let rflags = self.flags.dump(); - log::info!("DEBUG: adc value0: 0x{:x}, value1: 0x{:x}, cf: 0x{:x}, rflags: 0x{:x}", value0, value1, cf, rflags); + let in_rflags = self.flags.clone(); + log::info!("DEBUG: in: adc value0: 0x{:x}, value1: 0x{:x}, cf: 0x{:x}, rflags: 0x{:x}", value0, value1, cf, in_rflags.dump()); - let res: u64; - match self.get_operand_sz(&ins, 1) { - 64 => res = self.flags.add64(value0, value1.wrapping_add(cf)), - 32 => res = self.flags.add32(value0, (value1 & 0xffffffff).wrapping_add(cf)), - 16 => res = self.flags.add16(value0, (value1 & 0xffff).wrapping_add(cf)), - 8 => res = self.flags.add8(value0, (value1 & 0xff).wrapping_add(cf)), + let res = match self.get_operand_sz(&ins, 1) { + 64 => self.flags.add64(value0, value1, self.flags.f_cf, true), + 32 => self.flags.add32((value0 & 0xffffffff) as u32, (value1 & 0xffffffff) as u32, self.flags.f_cf, true), + 16 => self.flags.add16((value0 & 0xffff) as u16, (value1 & 0xffff) as u16, self.flags.f_cf, true), + 8 => self.flags.add8((value0 & 0xff) as u8, (value1 & 0xff) as u8, self.flags.f_cf, true), _ => unreachable!("weird size"), - } + }; - let rflags = self.flags.dump(); - log::info!("DEBUG: adc res: 0x{:x}, rflags: 0x{:x}", res, rflags); + let out_rflags = self.flags.clone(); + log::info!("DEBUG: out: adc res: 0x{:x}, rflags: 0x{:x} diff: {}", res, out_rflags.dump(), Flags::diff(in_rflags, out_rflags)); if !self.set_operand_value(&ins, 0, res) { return false; @@ -6592,10 +6567,10 @@ impl Emu { } let res: u64 = match self.get_operand_sz(&ins, 1) { - 64 => self.flags.add64(value0, value1), - 32 => self.flags.add32(value0, value1), - 16 => self.flags.add16(value0, value1), - 8 => self.flags.add8(value0, value1), + 64 => self.flags.add64(value0, value1, self.flags.f_cf, false), + 32 => self.flags.add32((value0 & 0xffffffff) as u32, (value1 & 0xffffffff) as u32, self.flags.f_cf, false), + 16 => self.flags.add16((value0 & 0xffff) as u16, (value1 & 0xffff) as u16, self.flags.f_cf, false), + 8 => self.flags.add8((value0 & 0xff) as u8, (value1 & 0xff) as u8, self.flags.f_cf, false), _ => unreachable!("weird size"), }; diff --git a/src/emu/regs64.rs b/src/emu/regs64.rs index 495e0f5..4bc2e30 100644 --- a/src/emu/regs64.rs +++ b/src/emu/regs64.rs @@ -268,7 +268,7 @@ impl Regs64 { } } - pub fn diff(rip: u64, pos: u64, a: Regs64, b: Regs64) -> String { + pub fn diff(a: Regs64, b: Regs64) -> String { let mut output = String::new(); if a.dr0 != b.dr0 { output = format!("{}{}: {:x} -> {:x} ", output, "dr0", a.dr0, b.dr0); From 1c06b4de7886c4f5f6e43bb3839ed606816abfcb Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Thu, 26 Dec 2024 12:20:17 -0500 Subject: [PATCH 10/11] lint --- src/emu/constants.rs | 1 - src/emu/mod.rs | 9 +-------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/emu/constants.rs b/src/emu/constants.rs index d9d2a17..6eff7a4 100644 --- a/src/emu/constants.rs +++ b/src/emu/constants.rs @@ -12,7 +12,6 @@ pub const LIBS32_MAX: u64 = 0x7FFFFFFF; pub const LIBS64_MIN: u64 = 0x7FF000000000; pub const LIBS64_MAX: u64 = 0x7FFFFFFFFFFF; - pub const STATUS_SUCCESS: u64 = 0x00000000; pub const STATUS_ACCESS_DENIED: u64 = 0xC0000022; pub const STATUS_INVALID_HANDLE: u64 = 0xC0000008; diff --git a/src/emu/mod.rs b/src/emu/mod.rs index ca5e312..30540d6 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -818,7 +818,6 @@ impl Emu { // base is setted by image base (if overlapps, alloc) } else { - // user's program if set_entry { if pe64.opt.image_base >= constants::LIBS64_MIN as u64 { @@ -3312,7 +3311,7 @@ impl Emu { } } else { if self.seh == 0 { - log::info!("exception without any SEH handler nor vector configured."); + log::info!("exception without any SEH handler nor vector configured. pos = {}", self.pos); if self.cfg.console_enabled { self.spawn_console(); } @@ -5138,9 +5137,6 @@ impl Emu { None => return false, }; - let in_rflags = self.flags.clone(); - log::info!("DEBUG: in: adc value0: 0x{:x}, value1: 0x{:x}, cf: 0x{:x}, rflags: 0x{:x}", value0, value1, cf, in_rflags.dump()); - let res = match self.get_operand_sz(&ins, 1) { 64 => self.flags.add64(value0, value1, self.flags.f_cf, true), 32 => self.flags.add32((value0 & 0xffffffff) as u32, (value1 & 0xffffffff) as u32, self.flags.f_cf, true), @@ -5149,9 +5145,6 @@ impl Emu { _ => unreachable!("weird size"), }; - let out_rflags = self.flags.clone(); - log::info!("DEBUG: out: adc res: 0x{:x}, rflags: 0x{:x} diff: {}", res, out_rflags.dump(), Flags::diff(in_rflags, out_rflags)); - if !self.set_operand_value(&ins, 0, res) { return false; } From 236e76e86788ffc61c04b6b9ac40a77c69302852 Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Thu, 26 Dec 2024 12:20:29 -0500 Subject: [PATCH 11/11] gateway logs --- src/emu/winapi32.rs | 2 ++ src/emu/winapi64.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/emu/winapi32.rs b/src/emu/winapi32.rs index f0e21c4..500f056 100644 --- a/src/emu/winapi32.rs +++ b/src/emu/winapi32.rs @@ -19,6 +19,8 @@ mod wincrt; use crate::emu; pub fn gateway(addr: u32, name: String, emu: &mut emu::Emu) { + log::info!("winapi32::gateway called with addr: 0x{:x}, name: {}", addr, name); + emu.regs.sanitize32(); let unimplemented_api = match name.as_str() { "kernel32.text" => kernel32::gateway(addr, emu), diff --git a/src/emu/winapi64.rs b/src/emu/winapi64.rs index f99f582..31e24f1 100644 --- a/src/emu/winapi64.rs +++ b/src/emu/winapi64.rs @@ -14,6 +14,8 @@ mod kernelbase; use crate::emu; pub fn gateway(addr: u64, name: String, emu: &mut emu::Emu) { + log::info!("winapi64::gateway called with addr: 0x{:x}, name: {}", addr, name); + let unimplemented_api = match name.as_str() { "kernel32.text" => kernel32::gateway(addr, emu), "kernel32.rdata" => kernel32::gateway(addr, emu),