diff options
author | iximeow <me@iximeow.net> | 2021-01-15 14:52:11 -0800 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2021-01-15 14:52:11 -0800 |
commit | f057c712f91b215034fe84fa0f22694aaa8dffb3 (patch) | |
tree | 6c28340154b900ba984ccd188fd7149aa4de6d75 /src | |
parent | 81e9b93aab9217cf7cb508f64b19fc1c0df024b5 (diff) |
fix several missing or invalid decodings among 0f01 opcodes
* `mwaitx`, `monitorx`, `rdpru`, and `clzero` are now supported
* swapgs is no longer decoded in protected mode
* rdpkru and wrpkru are no longer decoded if mod bits != 11
Diffstat (limited to 'src')
-rw-r--r-- | src/long_mode/display.rs | 8 | ||||
-rw-r--r-- | src/long_mode/mod.rs | 36 | ||||
-rw-r--r-- | src/protected_mode/display.rs | 8 | ||||
-rw-r--r-- | src/protected_mode/mod.rs | 42 |
4 files changed, 91 insertions, 3 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index e653399..c3f4413 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -513,6 +513,8 @@ const MNEMONICS: &[&'static str] = &[ "vmxoff", "monitor", "mwait", + "monitorx", + "mwaitx", "clac", "stac", "encls", @@ -527,6 +529,8 @@ const MNEMONICS: &[&'static str] = &[ "enclu", "rdpkru", "wrpkru", + "rdpru", + "clzero", "rdseed", "rdrand", "addps", @@ -2152,6 +2156,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color Opcode::VMXOFF | Opcode::MONITOR | Opcode::MWAIT | + Opcode::MONITORX | + Opcode::MWAITX | Opcode::SKINIT | Opcode::CLGI | Opcode::STGI | @@ -2169,6 +2175,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color Opcode::ENCLU | Opcode::RDPKRU | Opcode::WRPKRU | + Opcode::RDPRU | + Opcode::CLZERO | Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } Opcode::CRC32 | diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index d165e38..f15e2a1 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -1131,6 +1131,8 @@ pub enum Opcode { VMXOFF, MONITOR, MWAIT, + MONITORX, + MWAITX, CLAC, STAC, ENCLS, @@ -1146,6 +1148,9 @@ pub enum Opcode { RDPKRU, WRPKRU, + RDPRU, + CLZERO, + RDSEED, RDRAND, @@ -3278,6 +3283,12 @@ impl InstDecoder { return Err(DecodeError::InvalidOpcode); } } + Opcode::MONITORX | Opcode::MWAITX | // these are gated on the `monitorx` and `mwaitx` cpuid bits, but are AMD-only. + Opcode::CLZERO | Opcode::RDPRU => { // again, gated on specific cpuid bits, but AMD-only. + if !self.amd_quirks() { + return Err(DecodeError::InvalidOpcode); + } + } other => { if !self.bmi1() { if BMI1.contains(&other) { @@ -8049,6 +8060,14 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter instruction.operand_count = 1; instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; } else if r == 5 { + let mod_bits = modrm >> 6; + if mod_bits != 0b11 { + instruction.opcode = Opcode::Invalid; + instruction.operands[0] = OperandSpec::Nothing; + instruction.operand_count = 0; + return Err(DecodeError::InvalidOpcode); + } + let m = modrm & 7; match m { 0b110 => { @@ -8084,6 +8103,23 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter instruction.opcode = Opcode::RDTSCP; instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; + } else if m == 2 { + instruction.opcode = Opcode::MONITORX; + instruction.operands[0] = OperandSpec::Nothing; + instruction.operand_count = 0; + } else if m == 3 { + instruction.opcode = Opcode::MWAITX; + instruction.operands[0] = OperandSpec::Nothing; + instruction.operand_count = 0; + } else if m == 4 { + instruction.opcode = Opcode::CLZERO; + instruction.operands[0] = OperandSpec::Nothing; + instruction.operand_count = 0; + } else if m == 5 { + instruction.opcode = Opcode::RDPRU; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.modrm_rrr = RegSpec::ecx(); + instruction.operand_count = 1; } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs index c92737b..a0161c2 100644 --- a/src/protected_mode/display.rs +++ b/src/protected_mode/display.rs @@ -504,6 +504,8 @@ const MNEMONICS: &[&'static str] = &[ "vmxoff", "monitor", "mwait", + "monitorx", + "mwaitx", "clac", "stac", "encls", @@ -518,6 +520,8 @@ const MNEMONICS: &[&'static str] = &[ "enclu", "rdpkru", "wrpkru", + "rdpru", + "clzero", "rdseed", "rdrand", "addps", @@ -2162,6 +2166,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color Opcode::VMXOFF | Opcode::MONITOR | Opcode::MWAIT | + Opcode::MONITORX | + Opcode::MWAITX | Opcode::SKINIT | Opcode::CLGI | Opcode::STGI | @@ -2179,6 +2185,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color Opcode::ENCLU | Opcode::RDPKRU | Opcode::WRPKRU | + Opcode::RDPRU | + Opcode::CLZERO | Opcode::ARPL | Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index b60ff34..9327f64 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -1036,6 +1036,8 @@ pub enum Opcode { VMXOFF, MONITOR, MWAIT, + MONITORX, + MWAITX, CLAC, STAC, ENCLS, @@ -1051,6 +1053,9 @@ pub enum Opcode { RDPKRU, WRPKRU, + RDPRU, + CLZERO, + RDSEED, RDRAND, @@ -3191,6 +3196,12 @@ impl InstDecoder { return Err(DecodeError::InvalidOpcode); } } + Opcode::MONITORX | Opcode::MWAITX | // these are gated on the `monitorx` and `mwaitx` cpuid bits, but are AMD-only. + Opcode::CLZERO | Opcode::RDPRU => { // again, gated on specific cpuid bits, but AMD-only. + if !self.amd_quirks() { + return Err(DecodeError::InvalidOpcode); + } + } other => { if !self.bmi1() { if BMI1.contains(&other) { @@ -7893,6 +7904,14 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter instruction.operand_count = 1; instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; } else if r == 5 { + let mod_bits = modrm >> 6; + if mod_bits != 0b11 { + instruction.opcode = Opcode::Invalid; + instruction.operands[0] = OperandSpec::Nothing; + instruction.operand_count = 0; + return Err(DecodeError::InvalidOpcode); + } + let m = modrm & 7; match m { 0b110 => { @@ -7921,13 +7940,30 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter let m = modrm & 7; if mod_bits == 0b11 { if m == 0 { - instruction.opcode = Opcode::SWAPGS; - instruction.operands[0] = OperandSpec::Nothing; - instruction.operand_count = 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; instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; + } else if m == 2 { + instruction.opcode = Opcode::MONITORX; + instruction.operands[0] = OperandSpec::Nothing; + instruction.operand_count = 0; + } else if m == 3 { + instruction.opcode = Opcode::MWAITX; + instruction.operands[0] = OperandSpec::Nothing; + instruction.operand_count = 0; + } else if m == 4 { + instruction.opcode = Opcode::CLZERO; + instruction.operands[0] = OperandSpec::Nothing; + instruction.operand_count = 0; + } else if m == 5 { + instruction.opcode = Opcode::RDPRU; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.modrm_rrr = RegSpec::ecx(); + instruction.operand_count = 1; } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); |