aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG5
-rw-r--r--src/long_mode/display.rs4
-rw-r--r--src/long_mode/mod.rs36
-rw-r--r--src/protected_mode/display.rs4
-rw-r--r--src/protected_mode/mod.rs33
-rw-r--r--src/real_mode/display.rs4
-rw-r--r--src/real_mode/mod.rs33
-rw-r--r--test/long_mode/mod.rs3
-rw-r--r--test/protected_mode/mod.rs3
-rw-r--r--test/real_mode/mod.rs3
10 files changed, 116 insertions, 12 deletions
diff --git a/CHANGELOG b/CHANGELOG
index a647897..f4b31e6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,8 @@
+## 1.1.1
+* support `endbr64` and `endbr32`
+ - these are interpretations of `nop` (`0f1e` wide nop), so the only issue
+ with for users <1.1.1 will be `yaxpeax-86` decoding `nop` instead.
+
## 1.1.0
* implement `AnnotatingDecoder` from `yaxpeax-arch=0.2.6` and later.
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index 7c344b7..35b9c1f 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -1405,6 +1405,8 @@ const MNEMONICS: &[&'static str] = &[
"setssbsy",
"clrssbsy",
"rstorssp",
+ "endbr64",
+ "endbr32",
// TDX
"tdcall",
@@ -3220,6 +3222,8 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::SETSSBSY |
Opcode::CLRSSBSY |
Opcode::RSTORSSP |
+ Opcode::ENDBR64 |
+ Opcode::ENDBR32 |
Opcode::AESDEC |
Opcode::AESDECLAST |
Opcode::AESENC |
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 3d6d977..866eb8f 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -2139,6 +2139,8 @@ pub enum Opcode {
SETSSBSY,
CLRSSBSY,
RSTORSSP,
+ ENDBR64,
+ ENDBR32,
// TDX
TDCALL,
@@ -4986,9 +4988,7 @@ enum OperandCode {
ModRM_0x0f73 = OperandCodeBuilder::new().read_modrm().special_case(57).bits(),
ModRM_0xf20f78 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(),
ModRM_0x660f78 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(),
-// ModRM_0x660f12 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(),
-// ModRM_0x660f16 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(),
-// ModRM_0x660f71 = OperandCodeBuilder::new().read_modrm().special_case(60).bits(),
+ ModRM_0xf30f1e = OperandCodeBuilder::new().special_case(60).bits(),
// ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().special_case(61).bits(),
// ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().special_case(62).bits(),
// ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().special_case(63).bits(),
@@ -6372,7 +6372,7 @@ fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
0x1b => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
0x1c => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
0x1d => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
- 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
+ 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::ModRM_0xf30f1e),
0x1f => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
0x20 => OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Cq_0),
@@ -8833,6 +8833,34 @@ fn unlikely_operands<
instruction.operand_count = 3;
}
+ OperandCode::ModRM_0xf30f1e => {
+ let modrm = read_modrm(words)?;
+ match modrm {
+ 0xfa => {
+ instruction.opcode = Opcode::ENDBR64;
+ instruction.operand_count = 0;
+ },
+ 0xfb => {
+ instruction.opcode = Opcode::ENDBR32;
+ instruction.operand_count = 0;
+ },
+ _ => {
+ let (sz, bank) = if instruction.prefixes.rex_unchecked().w() {
+ (8, RegisterBank::Q)
+ } else if !instruction.prefixes.operand_size() {
+ (4, RegisterBank::D)
+ } else {
+ (2, RegisterBank::W)
+ };
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operands[0] = read_E(words, instruction, modrm, sz, sink)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), bank);
+ instruction.operand_count = 2;
+
+ }
+ };
+ }
OperandCode::G_E_xmm_Ub => {
let modrm = read_modrm(words)?;
diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs
index 275a61d..f545111 100644
--- a/src/protected_mode/display.rs
+++ b/src/protected_mode/display.rs
@@ -1406,6 +1406,8 @@ const MNEMONICS: &[&'static str] = &[
"setssbsy",
"clrssbsy",
"rstorssp",
+ "endbr64",
+ "endbr32",
// TDX
"tdcall",
@@ -3233,6 +3235,8 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::SETSSBSY |
Opcode::CLRSSBSY |
Opcode::RSTORSSP |
+ Opcode::ENDBR64 |
+ Opcode::ENDBR32 |
Opcode::AESDEC |
Opcode::AESDECLAST |
Opcode::AESENC |
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index fef1807..232284d 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -2077,6 +2077,8 @@ pub enum Opcode {
SETSSBSY,
CLRSSBSY,
RSTORSSP,
+ ENDBR64,
+ ENDBR32,
// TDX
TDCALL,
@@ -4905,9 +4907,7 @@ enum OperandCode {
ModRM_0x0f73 = OperandCodeBuilder::new().read_modrm().special_case(57).bits(),
ModRM_0xf20f78 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(),
ModRM_0x660f78 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(),
-// ModRM_0x660f12 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(),
-// ModRM_0x660f16 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(),
-// ModRM_0x660f71 = OperandCodeBuilder::new().read_modrm().special_case(60).bits(),
+ ModRM_0xf30f1e = OperandCodeBuilder::new().special_case(60).bits(),
// ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().special_case(61).bits(),
// ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().special_case(62).bits(),
// ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().special_case(63).bits(),
@@ -6393,7 +6393,7 @@ fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
0x1b => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
0x1c => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
0x1d => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
- 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
+ 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::ModRM_0xf30f1e),
0x1f => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
0x20 => OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Cq_0),
@@ -8781,6 +8781,31 @@ fn unlikely_operands<
instruction.operand_count = 3;
}
+ OperandCode::ModRM_0xf30f1e => {
+ let modrm = read_modrm(words)?;
+ match modrm {
+ 0xfa => {
+ instruction.opcode = Opcode::ENDBR64;
+ instruction.operand_count = 0;
+ },
+ 0xfb => {
+ instruction.opcode = Opcode::ENDBR32;
+ instruction.operand_count = 0;
+ },
+ _ => {
+ let (sz, bank) = if !instruction.prefixes.operand_size() {
+ (4, RegisterBank::D)
+ } else {
+ (2, RegisterBank::W)
+ };
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operands[0] = read_E(words, instruction, modrm, sz, sink)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, bank);
+ instruction.operand_count = 2;
+ }
+ };
+ }
OperandCode::G_E_xmm_Ub => {
let modrm = read_modrm(words)?;
diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs
index 10640a4..258f5d9 100644
--- a/src/real_mode/display.rs
+++ b/src/real_mode/display.rs
@@ -1406,6 +1406,8 @@ const MNEMONICS: &[&'static str] = &[
"setssbsy",
"clrssbsy",
"rstorssp",
+ "endbr64",
+ "endbr32",
// TDX
"tdcall",
@@ -3233,6 +3235,8 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::SETSSBSY |
Opcode::CLRSSBSY |
Opcode::RSTORSSP |
+ Opcode::ENDBR64 |
+ Opcode::ENDBR32 |
Opcode::AESDEC |
Opcode::AESDECLAST |
Opcode::AESENC |
diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs
index 45dd7a3..92c0592 100644
--- a/src/real_mode/mod.rs
+++ b/src/real_mode/mod.rs
@@ -2077,6 +2077,8 @@ pub enum Opcode {
SETSSBSY,
CLRSSBSY,
RSTORSSP,
+ ENDBR64,
+ ENDBR32,
// TDX
TDCALL,
@@ -4905,9 +4907,7 @@ enum OperandCode {
ModRM_0x0f73 = OperandCodeBuilder::new().read_modrm().special_case(57).bits(),
ModRM_0xf20f78 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(),
ModRM_0x660f78 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(),
-// ModRM_0x660f12 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(),
-// ModRM_0x660f16 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(),
-// ModRM_0x660f71 = OperandCodeBuilder::new().read_modrm().special_case(60).bits(),
+ ModRM_0xf30f1e = OperandCodeBuilder::new().special_case(60).bits(),
// ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().special_case(61).bits(),
// ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().special_case(62).bits(),
// ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().special_case(63).bits(),
@@ -6395,7 +6395,7 @@ fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
0x1b => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
0x1c => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
0x1d => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
- 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
+ 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::ModRM_0xf30f1e),
0x1f => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev),
0x20 => OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Cq_0),
@@ -8785,6 +8785,31 @@ fn unlikely_operands<
instruction.operand_count = 3;
}
+ OperandCode::ModRM_0xf30f1e => {
+ let modrm = read_modrm(words)?;
+ match modrm {
+ 0xfa => {
+ instruction.opcode = Opcode::ENDBR64;
+ instruction.operand_count = 0;
+ },
+ 0xfb => {
+ instruction.opcode = Opcode::ENDBR32;
+ instruction.operand_count = 0;
+ },
+ _ => {
+ let (sz, bank) = if instruction.prefixes.operand_size() {
+ (4, RegisterBank::D)
+ } else {
+ (2, RegisterBank::W)
+ };
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operands[0] = read_E(words, instruction, modrm, sz, sink)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, bank);
+ instruction.operand_count = 2;
+ }
+ };
+ }
OperandCode::G_E_xmm_Ub => {
let modrm = read_modrm(words)?;
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index dab4e91..1efa74e 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -2677,6 +2677,9 @@ fn prefixed_f20f() {
fn prefixed_f30f() {
test_display(&[0xf3, 0x0f, 0x16, 0xcf], "movshdup xmm1, xmm7");
test_display(&[0xf3, 0x4d, 0x0f, 0x16, 0xcf], "movshdup xmm9, xmm15");
+ test_display(&[0xf3, 0x0f, 0x1e, 0xfa], "endbr64");
+ test_display(&[0xf3, 0x0f, 0x1e, 0xfb], "endbr32");
+ test_display(&[0xf3, 0x0f, 0x1e, 0xfc], "nop esp, edi");
}
#[test]
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index 41ecbb7..4b8ca8d 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -2361,6 +2361,9 @@ fn prefixed_f20f() {
#[test]
fn prefixed_f30f() {
test_display(&[0xf3, 0x0f, 0x16, 0xcf], "movshdup xmm1, xmm7");
+ test_display(&[0xf3, 0x0f, 0x1e, 0xfa], "endbr64");
+ test_display(&[0xf3, 0x0f, 0x1e, 0xfb], "endbr32");
+ test_display(&[0xf3, 0x0f, 0x1e, 0xfc], "nop esp, edi");
}
#[test]
diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs
index dfbe4e8..6dcc3a2 100644
--- a/test/real_mode/mod.rs
+++ b/test/real_mode/mod.rs
@@ -17828,6 +17828,9 @@ fn test_real_mode() {
test_display(&[0xf3, 0x0f, 0x16, 0x0f], "movshdup xmm1, xmmword [bx]");
test_display(&[0xf3, 0x0f, 0x16, 0xcf], "movshdup xmm1, xmm7");
test_display(&[0xf3, 0x0f, 0x16, 0xcf], "movshdup xmm1, xmm7");
+ test_display(&[0xf3, 0x0f, 0x1e, 0xfa], "endbr64");
+ test_display(&[0xf3, 0x0f, 0x1e, 0xfb], "endbr32");
+ test_display(&[0xf3, 0x0f, 0x1e, 0xfc], "nop sp, di");
test_display(&[0xf3, 0x0f, 0x21, 0xc8], "mov eax, dr1");
test_display(&[0xf3, 0x0f, 0x2a, 0x00], "cvtsi2ss xmm0, dword [bx + si]");
test_display(&[0xf3, 0x0f, 0x2a, 0x01], "cvtsi2ss xmm0, dword [bx + di]");