From 324c58fee142e0ea987d1d23a7e25142dde803d0 Mon Sep 17 00:00:00 2001 From: iximeow Date: Thu, 28 Nov 2019 12:19:00 -0800 Subject: clear operands when decoding instruction, fix length counts operand-clearing should be removable but is a stopgap for decoding only clearing a few entries --- src/lib.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 956d4db..705966c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2481,21 +2481,25 @@ fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> } #[allow(non_snake_case)] -fn read_sib>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8) -> Result { +fn read_sib>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result { let modbits = (modrm >> 6); let addr_width = if instr.prefixes.address_size() { RegisterBank::D } else { RegisterBank::Q }; let sibbyte = match bytes_iter.next() { Some(b) => b, - None => { unsafe { unreachable_unchecked(); } } -// None => { return Err(()); } //Err("Out of bytes".to_string()) +// None => { unsafe { unreachable_unchecked(); } } + None => { return Err(()); } //Err("Out of bytes".to_string()) }; + *length += 1; let op_spec = if (sibbyte & 7) == 0b101 { let disp = if modbits == 0b00 { + *length += 4; read_num(bytes_iter, 4)? as i32 } else if modbits == 0b01 { + *length += 1; read_num(bytes_iter, 1)? as i8 as i32 } else { + *length += 4; read_num(bytes_iter, 4)? as i32 }; @@ -2543,8 +2547,10 @@ fn read_sib>(bytes_iter: &mut T, instr: &mut Instruction, m let disp = if modbits == 0b00 { 0 } else if modbits == 0b01 { + *length += 1; read_num(bytes_iter, 1)? as i8 as i32 } else { + *length += 4; read_num(bytes_iter, 4)? as i32 }; @@ -2576,11 +2582,12 @@ fn read_M>(bytes_iter: &mut T, instr: &mut Instruction, mod let addr_width = if instr.prefixes.address_size() { RegisterBank::D } else { RegisterBank::Q }; let mmm = modrm & 7; let op_spec = if mmm == 4 { - return read_sib(bytes_iter, instr, modrm); + return read_sib(bytes_iter, instr, modrm, length); // let (ss, index, base) = octets_of(sibbyte); // println!("scale: {:b}, index: {:b}, base: {:b}", ss, index, base); } else if mmm == 5 && modbits == 0b00 { + *length += 4; let disp = read_num(bytes_iter, 4)? as i32; instr.modrm_mmm = if addr_width == RegisterBank::Q { RegSpec::rip() } else { RegSpec::eip() }; @@ -2597,8 +2604,10 @@ fn read_M>(bytes_iter: &mut T, instr: &mut Instruction, mod OperandSpec::Deref } else { let disp = if modbits == 0b01 { + *length += 1; read_num(bytes_iter, 1)? as i8 as i32 } else { + *length += 4; read_num(bytes_iter, 4)? as i32 }; if disp == 0 { @@ -2632,6 +2641,7 @@ pub fn read_instr>(mut bytes_iter: T, instruction: &mut Ins // let operand_code = loop { match bytes_iter.next() { Some(b) => { + length += 1; let record = OPCODES[b as usize]; if (b & 0xf0) == 0x40 { prefixes.rex_mut().from(b); @@ -3533,6 +3543,12 @@ fn unlikely_operands>(mut bytes_iter: T, instruction: &mut } pub fn decode_one<'b, T: IntoIterator>(bytes: T, instr: &'b mut Instruction) -> Option<()> { + instr.operands = [ + OperandSpec::Nothing, + OperandSpec::Nothing, + OperandSpec::Nothing, + OperandSpec::Nothing, + ]; let mut bytes_iter = bytes.into_iter(); read_instr(bytes_iter, instr).ok() } -- cgit v1.1