aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-07-03 14:41:09 -0700
committeriximeow <me@iximeow.net>2021-07-03 14:43:37 -0700
commit11ce930421ba8b534024f6695dff8fdfd7e47ff0 (patch)
tree465b559f8a58ee74d9af06b4c0c7f82e5d0d3013
parent2b13f206b94e885dd3f58eac96357cb892ea1d1a (diff)
support AMD `sev_snp`
-rw-r--r--README.md2
-rw-r--r--src/long_mode/display.rs8
-rw-r--r--src/long_mode/mod.rs37
-rw-r--r--src/protected_mode/display.rs8
-rw-r--r--src/protected_mode/mod.rs37
-rw-r--r--test/long_mode/mod.rs8
-rw-r--r--test/protected_mode/mod.rs8
7 files changed, 103 insertions, 5 deletions
diff --git a/README.md b/README.md
index e19b8a7..33e88f4 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ the decoders provided by `yaxpeax-x86` are designed to be usable in a `no_std` s
yaxpeax-x86 decodes long-mode (`amd64`/`x86_64`), protected-mode (`x86`/`x86_32`), and real-mode (`x86_16`) instructions. the most part, ISA extensions decode equivalently across modes; this is the full list of extensions that are supported:
-`3dnow`\*, `sse`\*, `sse2`\*, `sse3`, `ssse3`, `sse4.1`, `sse4.2`, `sse4a`, `avx`, `avx2`, `avx512`\*\*, `syscall`, `cmpxchg16b`, `fma3`, `aesni`, `popcnt`, `rdrand`, `xsave`, `sgx`, `monitor`, `movbe`, `sgx`, `bmi1`, `bmi2`, `invpcid`, `mpx`, `adx`, `clflushopt`, `pcommit`, `sha`, `gfni`, `pclmulqdq`, `rdtscp`, `abm`, `xop`, `skinit`, `tbm`, `svm`, `f16c`, `fma4`, `tsx`, `enqcmd`\*\*\*, `uintr`\*\*\*, `keylocker`\*\*\*, `store_direct`\*\*\*, `cet`\*\*\*
+`3dnow`\*, `sse`\*, `sse2`\*, `sse3`, `ssse3`, `sse4.1`, `sse4.2`, `sse4a`, `avx`, `avx2`, `avx512`\*\*, `syscall`, `cmpxchg16b`, `fma3`, `aesni`, `popcnt`, `rdrand`, `xsave`, `sgx`, `monitor`, `movbe`, `sgx`, `bmi1`, `bmi2`, `invpcid`, `mpx`, `adx`, `clflushopt`, `pcommit`, `sha`, `gfni`, `pclmulqdq`, `rdtscp`, `abm`, `xop`, `skinit`, `tbm`, `svm`, `f16c`, `fma4`, `tsx`, `enqcmd`\*\*\*, `uintr`\*\*\*, `keylocker`\*\*\*, `store_direct`\*\*\*, `cet`\*\*\*, `sev/snp`\*\*\*
\*: `3dnow`, `sse`, and `sse2` are non-optional in `x86_64`, so it is not permitted to construct a decoder that rejects them. `x86_32` and `x86_16` could have features to reject these instructions for true `8086` and `i386` compatibility, but currently do not.
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index b9e4a92..b1fb7f8 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -1800,6 +1800,10 @@ const MNEMONICS: &[&'static str] = &[
"vpandnq",
"vpandd",
"vpandq",
+ "psmash",
+ "pvalidate",
+ "rmpadjust",
+ "rmpupdate",
];
impl Opcode {
@@ -3091,6 +3095,10 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::INVLPGA |
Opcode::INVLPGB |
Opcode::TLBSYNC |
+ Opcode::PSMASH |
+ Opcode::PVALIDATE |
+ Opcode::RMPADJUST |
+ Opcode::RMPUPDATE |
Opcode::CPUID |
Opcode::WBINVD |
Opcode::INVD |
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 8ed68fb..9111faa 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -2515,6 +2515,11 @@ pub enum Opcode {
VPANDNQ,
VPANDD,
VPANDQ,
+
+ PSMASH,
+ PVALIDATE,
+ RMPADJUST,
+ RMPUPDATE,
}
impl PartialEq for Instruction {
@@ -9502,7 +9507,21 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
instruction.regs[0] = RegSpec::ecx();
instruction.operand_count = 1;
} else if m == 6 {
- if instruction.prefixes.rep() || instruction.prefixes.repnz() || instruction.prefixes.operand_size() {
+ if instruction.prefixes.rep() {
+ if instruction.prefixes.repnz() || instruction.prefixes.operand_size() {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.opcode = Opcode::RMPADJUST;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.repnz() {
+ if instruction.prefixes.rep() || instruction.prefixes.operand_size() {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.opcode = Opcode::RMPUPDATE;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.operand_size() {
return Err(DecodeError::InvalidOperand);
}
@@ -9515,7 +9534,21 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
instruction.regs[1] = RegSpec::edx();
instruction.regs[3] = RegSpec::ecx();
} else if m == 7 {
- if instruction.prefixes.rep() || instruction.prefixes.repnz() || instruction.prefixes.operand_size() {
+ if instruction.prefixes.rep() {
+ if instruction.prefixes.repnz() || instruction.prefixes.operand_size() {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.opcode = Opcode::PSMASH;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.repnz() {
+ if instruction.prefixes.rep() || instruction.prefixes.operand_size() {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.opcode = Opcode::PVALIDATE;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.operand_size() {
return Err(DecodeError::InvalidOperand);
}
diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs
index 3e0079e..ac869aa 100644
--- a/src/protected_mode/display.rs
+++ b/src/protected_mode/display.rs
@@ -1801,6 +1801,10 @@ const MNEMONICS: &[&'static str] = &[
"vpandnq",
"vpandd",
"vpandq",
+ "psmash",
+ "pvalidate",
+ "rmpadjust",
+ "rmpupdate",
];
impl Opcode {
@@ -3102,6 +3106,10 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::INVLPGA |
Opcode::INVLPGB |
Opcode::TLBSYNC |
+ Opcode::PSMASH |
+ Opcode::PVALIDATE |
+ Opcode::RMPADJUST |
+ Opcode::RMPUPDATE |
Opcode::CPUID |
Opcode::WBINVD |
Opcode::INVD |
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index 936dc08..0497db6 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -2441,6 +2441,11 @@ pub enum Opcode {
VPANDNQ,
VPANDD,
VPANDQ,
+
+ PSMASH,
+ PVALIDATE,
+ RMPADJUST,
+ RMPUPDATE,
}
impl PartialEq for Instruction {
@@ -9322,7 +9327,21 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
instruction.regs[0] = RegSpec::ecx();
instruction.operand_count = 1;
} else if m == 6 {
- if instruction.prefixes.rep() || instruction.prefixes.repnz() || instruction.prefixes.operand_size() {
+ if instruction.prefixes.rep() {
+ if instruction.prefixes.repnz() || instruction.prefixes.operand_size() {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.opcode = Opcode::RMPADJUST;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.repnz() {
+ if instruction.prefixes.rep() || instruction.prefixes.operand_size() {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.opcode = Opcode::RMPUPDATE;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.operand_size() {
return Err(DecodeError::InvalidOperand);
}
@@ -9335,7 +9354,21 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
instruction.regs[1] = RegSpec::edx();
instruction.regs[3] = RegSpec::ecx();
} else if m == 7 {
- if instruction.prefixes.rep() || instruction.prefixes.repnz() || instruction.prefixes.operand_size() {
+ if instruction.prefixes.rep() {
+ if instruction.prefixes.repnz() || instruction.prefixes.operand_size() {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.opcode = Opcode::PSMASH;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.repnz() {
+ if instruction.prefixes.rep() || instruction.prefixes.operand_size() {
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.opcode = Opcode::PVALIDATE;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.operand_size() {
return Err(DecodeError::InvalidOperand);
}
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 6a45b38..4d44694 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -3329,6 +3329,14 @@ fn test_tsxldtrk() {
test_display(&[0xf2, 0x0f, 0x01, 0xe9], "xresldtrk");
}
+#[test]
+fn test_sevsnp() {
+ test_display(&[0xf3, 0x0f, 0x01, 0xff], "psmash");
+ test_display(&[0xf2, 0x0f, 0x01, 0xff], "pvalidate");
+ test_display(&[0xf3, 0x0f, 0x01, 0xfe], "rmpadjust");
+ test_display(&[0xf2, 0x0f, 0x01, 0xfe], "rmpupdate");
+}
+
// some test cases are best just lifted from llvm or gcc.
#[test]
fn from_llvm() {
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index 90b53a6..c742516 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -3026,6 +3026,14 @@ fn test_tsxldtrk() {
test_display(&[0xf2, 0x0f, 0x01, 0xe9], "xresldtrk");
}
+#[test]
+fn test_sevsnp() {
+ test_display(&[0xf3, 0x0f, 0x01, 0xff], "psmash");
+ test_display(&[0xf2, 0x0f, 0x01, 0xff], "pvalidate");
+ test_display(&[0xf3, 0x0f, 0x01, 0xfe], "rmpadjust");
+ test_display(&[0xf2, 0x0f, 0x01, 0xfe], "rmpupdate");
+}
+
// some test cases are best just lifted from llvm or gcc.
#[test]
fn from_llvm() {