diff options
author | iximeow <me@iximeow.net> | 2021-07-03 10:17:17 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2021-07-03 10:17:17 -0700 |
commit | a4b6304bd0df5fbab311a037d7c04b1ecbef7b14 (patch) | |
tree | 4284a813316d427d65de357d1e0647045c42093a /src/protected_mode/mod.rs | |
parent | e095342c536ce282a80b010ddedcd43900b85f7b (diff) |
port over x86_64 improvements to x86_32
Diffstat (limited to 'src/protected_mode/mod.rs')
-rw-r--r-- | src/protected_mode/mod.rs | 69 |
1 files changed, 20 insertions, 49 deletions
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 46321d1..b7387d9 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -7141,7 +7141,6 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe return Ok(()); } if (modrm & 0b00111000) != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); // Err("Invalid modr/m for opcode 0xc7".to_string()); } @@ -7164,7 +7163,6 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe return Ok(()); } if (modrm & 0b00111000) != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); // Err("Invalid modr/m for opcode 0xc7".to_string()); } @@ -7349,7 +7347,6 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe instruction.operand_count = 2; if instruction.operands[1] == OperandSpec::RegMMM { if op == 20 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { // fix the register to XMM @@ -7588,7 +7585,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y // interpret the c4 as a vex prefix if instruction.prefixes.lock() || instruction.prefixes.operand_size() || instruction.prefixes.rep() || instruction.prefixes.repnz() { // prefixes and then vex is invalid! reject it. - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidPrefixes); } else { vex::three_byte_vex(words, modrm, instruction)?; @@ -7616,7 +7612,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y // interpret the c5 as a vex prefix if instruction.prefixes.lock() || instruction.prefixes.operand_size() || instruction.prefixes.rep() || instruction.prefixes.repnz() { // prefixes and then vex is invalid! reject it. - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidPrefixes); } else { vex::two_byte_vex(words, modrm, instruction)?; @@ -7870,6 +7865,8 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y }; let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 }; let imm = read_num(words, addr_width)?; + instruction.regs[0] = + RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth); instruction.disp = imm; if instruction.prefixes.address_size() { instruction.operands[1] = OperandSpec::DispU16; @@ -8122,7 +8119,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y match r { 1 => { if is_reg { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { instruction.opcode = Opcode::CMPXCHG8B; @@ -8150,7 +8146,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y match r { 1 => { if is_reg { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { instruction.opcode = Opcode::CMPXCHG8B; @@ -8208,7 +8203,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y match r { 1 => { if is_reg { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { instruction.opcode = Opcode::CMPXCHG8B; @@ -8253,7 +8247,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y let opcode = match r { 0b001 => { if is_reg { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { instruction.mem_size = 8; @@ -8262,7 +8255,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y } 0b011 => { if is_reg { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { instruction.mem_size = 63; @@ -8271,7 +8263,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y } 0b100 => { if is_reg { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { instruction.mem_size = 63; @@ -8280,7 +8271,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y } 0b101 => { if is_reg { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { instruction.mem_size = 63; @@ -8304,7 +8294,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y } } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } }; @@ -8356,6 +8345,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.operands[1] = OperandSpec::ImmU8; }, OperandCode::ModRM_0x0f72 => { + if instruction.prefixes.rep() || instruction.prefixes.repnz() { + return Err(DecodeError::InvalidOperand); + } + instruction.operand_count = 2; let modrm = read_modrm(words)?; @@ -8757,7 +8750,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y } OperandCode::Gd_U_xmm => { if instruction.operands[1] != OperandSpec::RegMMM { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } instruction.regs[0].bank = RegisterBank::D; @@ -8774,7 +8766,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.operands[1] = instruction.operands[0]; instruction.operands[0] = mem_oper; if instruction.operands[0] == OperandSpec::RegMMM { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { if instruction.opcode == Opcode::MOVNTSS { @@ -8902,12 +8893,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.opcode = Opcode::VERW; } else if r == 6 { // TODO: this would be jmpe for x86-on-itanium systems. - instruction.opcode = Opcode::Invalid; instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Err(DecodeError::InvalidOperand); } else if r == 7 { - instruction.opcode = Opcode::Invalid; instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Err(DecodeError::InvalidOperand); @@ -8920,6 +8909,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y } } OperandCode::ModRM_0x0f01 => { + if instruction.prefixes.rep() || instruction.prefixes.repnz() { + return Err(DecodeError::InvalidOperand); + } + let opwidth = if instruction.prefixes.operand_size() { 2 } else { @@ -8950,7 +8943,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.opcode = Opcode::VMXOFF; }, _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -8981,7 +8973,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.opcode = Opcode::SEAMCALL; } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -9006,7 +8997,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.opcode = Opcode::ENCLS; } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -9043,7 +9033,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.opcode = Opcode::ENCLU; } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -9106,7 +9095,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.regs[1] = RegSpec::ecx(); }, _ => { - instruction.opcode = Opcode::Invalid; instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Err(DecodeError::InvalidOperand); @@ -9161,7 +9149,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.operand_count = 0; return Ok(()); } else { - instruction.opcode = Opcode::Invalid; instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Err(DecodeError::InvalidOpcode); @@ -9181,7 +9168,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; } else { - instruction.opcode = Opcode::Invalid; instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Err(DecodeError::InvalidOpcode); @@ -9193,7 +9179,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; } else { - instruction.opcode = Opcode::Invalid; instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Err(DecodeError::InvalidOpcode); @@ -9226,7 +9211,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.operand_count = 0; } _ => { - instruction.opcode = Opcode::Invalid; instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Err(DecodeError::InvalidOpcode); @@ -9243,7 +9227,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y if mod_bits == 0b11 { if m == 0 { // swapgs is not valid in modes other than 64-bit - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else if m == 1 { instruction.opcode = Opcode::RDTSCP; @@ -9279,7 +9262,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.opcode = Opcode::TLBSYNC; instruction.operand_count = 0; } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } else { @@ -9308,7 +9290,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y Opcode::CLFLUSHOPT } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } }; @@ -9321,7 +9302,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y Opcode::TPAUSE } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } }; @@ -9345,7 +9325,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.operand_count = 1; } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -9408,7 +9387,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y instruction.operand_count = 1; } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -9446,7 +9424,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y // doesn't say (tested on threadripper) if !decoder.amd_quirks() && !decoder.intel_quirks() { if m != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } } @@ -9457,7 +9434,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y // doesn't say (tested on threadripper) if !decoder.amd_quirks() && !decoder.intel_quirks() { if m != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } } @@ -9468,7 +9444,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y // doesn't say (tested on threadripper) if !decoder.amd_quirks() && !decoder.intel_quirks() { if m != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } } @@ -9506,7 +9481,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y let r = (modrm >> 3) & 7; match r { 0 | 1 | 2 | 3 => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }, 4 => { @@ -9728,7 +9702,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y OperandCode::x87_dd | OperandCode::x87_de | OperandCode::x87_df => { - return decode_x87(decoder, words, instruction, operand_code); + return decode_x87(words, instruction, operand_code); } OperandCode::M_Gv => { // `lea` operands (`Gv_M`) opportunistically reject a register form of `mmm` early, but @@ -9775,14 +9749,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y // entries anyway, so no extra space for the dead arms. instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } }; Ok(()) } -fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(_decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode) -> Result<(), DecodeError> { +fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instruction: &mut Instruction, operand_code: OperandCode) -> Result<(), DecodeError> { #[allow(non_camel_case_types)] enum OperandCodeX87 { Est, @@ -10304,21 +10277,19 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ #[inline] fn read_num<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(bytes: &mut T, width: u8) -> Result<u32, DecodeError> { match width { - 1 => { bytes.next().map(|x| x as u32).ok().ok_or(DecodeError::ExhaustedInput) } + 1 => { bytes.next().ok().ok_or(DecodeError::ExhaustedInput).map(|x| x as u32) } 2 => { - bytes.next().and_then(|b0| { - bytes.next().map(|b1| u16::from_le_bytes([b0, b1]) as u32) - }).ok().ok_or(DecodeError::ExhaustedInput) + let mut buf = [0u8; 2]; + bytes.next_n(&mut buf).ok().ok_or(DecodeError::ExhaustedInput)?; + Ok(u16::from_le_bytes(buf) as u32) } 4 => { - bytes.next() - .and_then(|b0| bytes.next().map(|b1| (b0, b1))) - .and_then(|(b0, b1)| bytes.next().map(|b2| (b0, b1, b2))) - .and_then(|(b0, b1, b2)| bytes.next().map(|b3| u32::from_le_bytes([b0, b1, b2, b3]))) - .ok().ok_or(DecodeError::ExhaustedInput) + let mut buf = [0u8; 4]; + bytes.next_n(&mut buf).ok().ok_or(DecodeError::ExhaustedInput)?; + Ok(u32::from_le_bytes(buf) as u32) } _ => { - panic!("unsupported read size"); + unsafe { unreachable_unchecked(); } } } } |