From 06b9d518496b90e83ad8b9857973442b978ed3e6 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 23 Jun 2019 16:09:26 -0700 Subject: begin supporting f30f instructions fix issue where non-relevant prefixes on 0f opcodes may cause incorrect invalid decodes --- src/display.rs | 22 +++++++++++ src/lib.rs | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- test/test.rs | 3 ++ 3 files changed, 133 insertions(+), 6 deletions(-) diff --git a/src/display.rs b/src/display.rs index 7dba44d..ca2b2f7 100644 --- a/src/display.rs +++ b/src/display.rs @@ -184,6 +184,13 @@ impl fmt::Display for Opcode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { &Opcode::MOVSS => write!(f, "{}", "movss"), + &Opcode::SQRTSS => write!(f, "{}", "sqrtss"), + &Opcode::ADDSS => write!(f, "{}", "addss"), + &Opcode::SUBSS => write!(f, "{}", "subss"), + &Opcode::MULSS => write!(f, "{}", "mulss"), + &Opcode::DIVSS => write!(f, "{}", "divss"), + &Opcode::MINSS => write!(f, "{}", "minss"), + &Opcode::MAXSS => write!(f, "{}", "maxss"), &Opcode::MOVSD => write!(f, "{}", "movsd"), &Opcode::SQRTSD => write!(f, "{}", "sqrtsd"), &Opcode::ADDSD => write!(f, "{}", "addsd"), @@ -193,6 +200,7 @@ impl fmt::Display for Opcode { &Opcode::MINSD => write!(f, "{}", "minsd"), &Opcode::MAXSD => write!(f, "{}", "maxsd"), &Opcode::MOVDDUP => write!(f, "{}", "movddup"), + &Opcode::MOVSLDUP => write!(f, "{}", "movsldup"), &Opcode::HADDPS => write!(f, "{}", "haddps"), &Opcode::HSUBPS => write!(f, "{}", "hsubps"), &Opcode::ADDSUBPS => write!(f, "{}", "addsubps"), @@ -201,6 +209,9 @@ impl fmt::Display for Opcode { &Opcode::CVTTSD2SI => write!(f, "{}", "cvttsd2si"), &Opcode::CVTSD2SI => write!(f, "{}", "cvtsd2si"), &Opcode::CVTSD2SS => write!(f, "{}", "cvtsd2ss"), + &Opcode::CVTTSS2SI => write!(f, "{}", "cvttss2si"), + &Opcode::CVTSS2SI => write!(f, "{}", "cvtss2si"), + &Opcode::CVTSS2SD => write!(f, "{}", "cvtss2sd"), &Opcode::LDDQU => write!(f, "{}", "lddqu"), &Opcode::STI => write!(f, "{}", "sti"), &Opcode::STD => write!(f, "{}", "std"), @@ -371,7 +382,13 @@ impl Colorize for Opcode { Opcode::SUBSD | Opcode::MULSD | Opcode::DIVSD | + Opcode::SQRTSS | + Opcode::ADDSS | + Opcode::SUBSS | + Opcode::MULSS | + Opcode::DIVSS | Opcode::MOVDDUP | + Opcode::MOVSLDUP | Opcode::HADDPS | Opcode::HSUBPS | Opcode::ADDSUBPS | @@ -444,6 +461,9 @@ impl Colorize for Opcode { Opcode::CVTTSD2SI | Opcode::CVTSD2SI | Opcode::CVTSD2SS | + Opcode::CVTTSS2SI | + Opcode::CVTSS2SI | + Opcode::CVTSS2SD | Opcode::LDDQU | Opcode::CLC | Opcode::CLI | @@ -501,6 +521,8 @@ impl Colorize for Opcode { Opcode::MINSD | Opcode::MAXSD | + Opcode::MINSS | + Opcode::MAXSS | Opcode::CMPS | Opcode::SCAS | Opcode::TEST | diff --git a/src/lib.rs b/src/lib.rs index a935e91..bee1173 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -235,8 +235,15 @@ pub enum Segment { #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Opcode { - MOVSD, MOVSS, + ADDSS, + SUBSS, + MULSS, + DIVSS, + MINSS, + MAXSS, + SQRTSS, + MOVSD, SQRTSD, ADDSD, SUBSD, @@ -244,6 +251,7 @@ pub enum Opcode { DIVSD, MINSD, MAXSD, + MOVSLDUP, MOVDDUP, HADDPS, HSUBPS, @@ -253,6 +261,9 @@ pub enum Opcode { CVTTSD2SI, CVTSD2SI, CVTSD2SS, + CVTTSS2SI, + CVTSS2SI, + CVTSS2SD, LDDQU, MOVZX_b, MOVZX_w, @@ -862,7 +873,91 @@ fn read_opcode_f20f_map>(bytes_iter: &mut T, instruction: & } } fn read_opcode_f30f_map>(bytes_iter: &mut T, instruction: &mut Instruction, prefixes: Prefixes, length: &mut u8) -> Result { - Err("f30f opcode map unsupported".to_string()) + match bytes_iter.next() { + Some(b) => { + *length += 1; + match b { + 0x10 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MOVSS; + Ok(OperandCode::G_E_xmm) + }, + 0x11 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MOVSS; + Ok(OperandCode::E_G_xmm) + }, + 0x12 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MOVSLDUP; + Ok(OperandCode::G_E_xmm) + }, + 0x2a => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::CVTSI2SS; + Ok(OperandCode::G_E_xmm) + }, + 0x2c => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::CVTTSS2SI; + Ok(OperandCode::G_E_xmm) + }, + 0x2d => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::CVTSS2SI; + Ok(OperandCode::G_E_xmm) + }, + 0x51 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::SQRTSS; + Ok(OperandCode::G_E_xmm) + }, + 0x58 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::ADDSS; + Ok(OperandCode::G_E_xmm) + }, + 0x59 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MULSS; + Ok(OperandCode::G_E_xmm) + }, + 0x5a => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::CVTSS2SD; + Ok(OperandCode::G_E_xmm) + }, + 0x5c => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::SUBSS; + Ok(OperandCode::G_E_xmm) + }, + 0x5d => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MINSS; + Ok(OperandCode::G_E_xmm) + }, + 0x5e => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::DIVSS; + Ok(OperandCode::G_E_xmm) + }, + 0x5f => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MAXSS; + Ok(OperandCode::G_E_xmm) + }, + _ => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::Invalid; + Err("Invalid opcode".to_string()) + } + } + } + None => { + Err("No more bytes".to_owned()) + } + } } fn read_opcode_0f_map>(bytes_iter: &mut T, instruction: &mut Instruction, prefixes: Prefixes, length: &mut u8) -> Result { match bytes_iter.next() { @@ -1236,16 +1331,20 @@ fn read_opcode>(bytes_iter: &mut T, instruction: &mut Instr }; }, 0x26 => { - prefixes.set_es() + prefixes.set_es(); + alternate_opcode_map = None; }, 0x2e => { - prefixes.set_cs() + prefixes.set_cs(); + alternate_opcode_map = None; }, 0x36 => { - prefixes.set_ss() + prefixes.set_ss(); + alternate_opcode_map = None; }, 0x3e => { - prefixes.set_ds() + prefixes.set_ds(); + alternate_opcode_map = None; }, 0x06 | 0x07 @@ -1293,9 +1392,11 @@ fn read_opcode>(bytes_iter: &mut T, instruction: &mut Instr }, 0x64 => { prefixes.set_fs(); + alternate_opcode_map = None; }, 0x65 => { prefixes.set_gs(); + alternate_opcode_map = None; }, 0x66 => { prefixes.set_operand_size(); @@ -1303,6 +1404,7 @@ fn read_opcode>(bytes_iter: &mut T, instruction: &mut Instr }, 0x67 => { prefixes.set_address_size(); + alternate_opcode_map = None; }, 0x68 => { instruction.prefixes = prefixes; diff --git a/test/test.rs b/test/test.rs index bc4660c..85288a6 100644 --- a/test/test.rs +++ b/test/test.rs @@ -69,7 +69,9 @@ fn test_E_decode() { #[test] fn test_sse() { test_display(&[0xf2, 0x0f, 0x10, 0x0c, 0xc6], "movsd xmm1, [rsi + rax * 8]"); + test_display(&[0xf3, 0x0f, 0x10, 0x04, 0x86], "movss xmm0, [rsi + rax * 4]"); test_display(&[0xf2, 0x0f, 0x59, 0xc8], "mulsd xmm1, xmm0"); + test_display(&[0xf3, 0x0f, 0x59, 0xc8], "mulss xmm1, xmm0"); test_display(&[0xf2, 0x4f, 0x0f, 0x59, 0xc8], "mulsd xmm9, xmm8"); test_display(&[0xf2, 0x0f, 0x11, 0x0c, 0xc7], "movsd [rdi + rax * 8], xmm1"); } @@ -141,6 +143,7 @@ fn test_push_pop() { #[test] fn test_misc() { + test_display(&[0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00], "nop cs:[rax + rax]"); test_display(&[0x48, 0x8d, 0xa4, 0xc7, 0x20, 0x00, 0x00, 0x12], "lea rsp, [rdi + rax * 8 + 0x12000020]"); test_display(&[0x33, 0xc0], "xor eax, eax"); test_display(&[0x48, 0x8d, 0x53, 0x08], "lea rdx, [rbx + 0x8]"); -- cgit v1.1