aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2019-06-23 16:09:26 -0700
committeriximeow <me@iximeow.net>2020-01-12 16:10:13 -0800
commit06b9d518496b90e83ad8b9857973442b978ed3e6 (patch)
tree54bd23c987510f6d726bb817979a438034d101e3
parent66bc9435b54495e24715939e119b059b06231e8b (diff)
begin supporting f30f instructions
fix issue where non-relevant prefixes on 0f opcodes may cause incorrect invalid decodes
-rw-r--r--src/display.rs22
-rw-r--r--src/lib.rs114
-rw-r--r--test/test.rs3
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 <T: std::fmt::Write> Colorize<T> 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 <T: std::fmt::Write> Colorize<T> 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 <T: std::fmt::Write> Colorize<T> 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<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &
}
}
fn read_opcode_f30f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction, prefixes: Prefixes, length: &mut u8) -> Result<OperandCode, String> {
- 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<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction, prefixes: Prefixes, length: &mut u8) -> Result<OperandCode, String> {
match bytes_iter.next() {
@@ -1236,16 +1331,20 @@ fn read_opcode<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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]");