aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-09-26 00:40:03 -0700
committeriximeow <me@iximeow.net>2021-09-26 00:40:03 -0700
commit23bd0b37482a127c8f954ce7e068a507b9c1e09e (patch)
tree634a991f40463f9a1c50b75f5cf4b5ba6e4ef7c0
parent7fee2c5dafb84ee93ddb6a8f582e99d445c82677 (diff)
fix unimplemented code paths panicking as unreachable
only in a64 decoding really; there wasn't an "Incomplete" error at the time, but now there is.
-rw-r--r--src/armv7.rs12
-rw-r--r--src/armv8/a64.rs22
-rw-r--r--test/armv8/a64.rs19
3 files changed, 38 insertions, 15 deletions
diff --git a/src/armv7.rs b/src/armv7.rs
index 64c9a4d..5894bc4 100644
--- a/src/armv7.rs
+++ b/src/armv7.rs
@@ -2280,7 +2280,7 @@ impl Decoder<ARMv7> for InstDecoder {
}
}
_ => {
- unreachable!();
+ unreachable!("op1 is two bits");
}
}
} else {
@@ -2405,7 +2405,7 @@ impl Decoder<ARMv7> for InstDecoder {
Operand::Reg(Reg::from_u8(R[1])),
];
}
- _ => { unreachable!("mul upcode: {:x}", op) }
+ _ => { unreachable!("mul opcode is only three bits, got: {:x}", op) }
}
} else {
// |c o n d|0 0 0 u|x x x x x x x x x x x x x x x x|1 u u 1|x x x x|
@@ -2894,7 +2894,7 @@ impl Decoder<ARMv7> for InstDecoder {
_ => { unreachable!("impossible bit pattern"); }
}
}
- _ => { unreachable!(); }
+ _ => { unreachable!("op is two bits"); }
}
}
} else {
@@ -3004,7 +3004,7 @@ impl Decoder<ARMv7> for InstDecoder {
inst.operands[3] = Operand::Nothing;
}
_ => {
- unreachable!();
+ unreachable!("opcode is masked to two bits here");
}
}
}
@@ -3248,7 +3248,7 @@ impl Decoder<ARMv7> for InstDecoder {
return Ok(());
}
_ => {
- unreachable!();
+ unreachable!("word masked to two bits");
}
}
}
@@ -3695,7 +3695,7 @@ impl Decoder<ARMv7> for InstDecoder {
// low bit of 0b110 or 0b111 corresponds to high bit of op1
return Err(DecodeError::Incomplete);
},
- _ => { unreachable!(); }
+ _ => { unreachable!("opc category is three bits"); }
}
Ok(())
}
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index 16ed9c5..68f2337 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -131,6 +131,7 @@ pub enum DecodeError {
ExhaustedInput,
InvalidOpcode,
InvalidOperand,
+ IncompleteDecoder,
}
impl fmt::Display for DecodeError {
@@ -164,6 +165,7 @@ impl yaxpeax_arch::DecodeError for DecodeError {
DecodeError::ExhaustedInput => "exhausted input",
DecodeError::InvalidOpcode => "invalid opcode",
DecodeError::InvalidOperand => "invalid operand",
+ DecodeError::IncompleteDecoder => "incomplete decoder",
}
}
}
@@ -1089,7 +1091,7 @@ impl Decoder<ARMv8> for InstDecoder {
match section {
Section::DataProcessingSimd |
Section::DataProcessingSimd2 => {
- unreachable!();
+ return Err(DecodeError::IncompleteDecoder);
}
Section::Unallocated => {
inst.opcode = Opcode::Invalid;
@@ -1165,7 +1167,7 @@ impl Decoder<ARMv8> for InstDecoder {
},
0b001 => {
// Conditional compare (register/immediate)
- unimplemented!();
+ return Err(DecodeError::IncompleteDecoder);
},
0b010 => {
// Conditional select
@@ -1243,7 +1245,7 @@ impl Decoder<ARMv8> for InstDecoder {
if ((word >> 30) & 1) == 0 {
// X0X11010_110XXXXX_XXXXXXXX_XXXXXXXX
// Data-processing (2 source)
- unimplemented!();
+ return Err(DecodeError::IncompleteDecoder);
} else {
// X1X11010_110XXXXX_XXXXXXXX_XXXXXXXX
// Data-processing (1 source)
@@ -1256,7 +1258,7 @@ impl Decoder<ARMv8> for InstDecoder {
// however, PAC (added in v8.3) says otherwise.
match opcode2 {
0b00000 => {
- unimplemented!();
+ return Err(DecodeError::IncompleteDecoder);
}
0b00001 => {
match opcode {
@@ -1290,14 +1292,14 @@ impl Decoder<ARMv8> for InstDecoder {
}
}
_ => {
- unimplemented!();
+ return Err(DecodeError::IncompleteDecoder);
}
}
}
},
_ => {
// Data processing (3 source)
- unimplemented!();
+ return Err(DecodeError::IncompleteDecoder);
}
}
} else {
@@ -1730,9 +1732,10 @@ impl Decoder<ARMv8> for InstDecoder {
} else {
inst.opcode = Opcode::Invalid;
}
- unimplemented!("decode Rd: {}, Rn: {}, imms: {}, Rm: {}, No0: {}", Rd, Rn, imms, Rm, No0);
+ // eprintln!("decode Rd: {}, Rn: {}, imms: {}, Rm: {}, No0: {}", Rd, Rn, imms, Rm, No0);
+ return Err(DecodeError::IncompleteDecoder);
}
- _ => { unreachable!() }
+ _ => { unreachable!("group is three bits") }
}
},
Section::LoadStore => {
@@ -2058,7 +2061,8 @@ impl Decoder<ARMv8> for InstDecoder {
// load/store register pair (post-indexed)
// V == 1
let opc_L = ((word >> 22) & 1) | ((word >> 29) & 0x6);
- unreachable!("C3.3.15 V==1, opc_L: {}", opc_L);
+ // eprintln!("C3.3.15 V==1, opc_L: {}", opc_L);
+ return Err(DecodeError::IncompleteDecoder);
},
0b10010 => {
// load/store register pair (offset)
diff --git a/test/armv8/a64.rs b/test/armv8/a64.rs
index 35a255d..6dd9d9b 100644
--- a/test/armv8/a64.rs
+++ b/test/armv8/a64.rs
@@ -1,5 +1,6 @@
use yaxpeax_arch::{Arch, Decoder, LengthedInstruction};
use yaxpeax_arm::armv8::a64::{ARMv8, Instruction, Operand, Opcode, SizeCode, ShiftStyle};
+use yaxpeax_arm::armv8::a64::DecodeError;
fn test_decode(data: [u8; 4], expected: Instruction) {
let mut reader = yaxpeax_arch::U8Reader::new(&data[..]);
@@ -12,6 +13,17 @@ fn test_decode(data: [u8; 4], expected: Instruction) {
);
}
+fn test_err(data: [u8; 4], err: DecodeError) {
+ let mut reader = yaxpeax_arch::U8Reader::new(&data[..]);
+ let result = <ARMv8 as Arch>::Decoder::default().decode(&mut reader);
+ assert_eq!(
+ result, Err(err),
+ "expected IncompleteDecoder error for {:02x}{:02x}{:02x}{:02x}:\n decoded: {:?}\n",
+ data[0], data[1], data[2], data[3],
+ result,
+ );
+}
+
fn test_display(data: [u8; 4], expected: &'static str) {
let mut reader = yaxpeax_arch::U8Reader::new(&data[..]);
let instr = <ARMv8 as Arch>::Decoder::default().decode(&mut reader).unwrap();
@@ -26,6 +38,13 @@ fn test_display(data: [u8; 4], expected: &'static str) {
}
#[test]
+fn test_neon() {
+ // currently, NEON is incompletely implemented in yaxpeax-arm.
+ test_err([0x00, 0x01, 0x27, 0x1e], DecodeError::IncompleteDecoder);
+ test_display([0xe0, 0x03, 0x13, 0xaa], "mov x0, x19");
+}
+
+#[test]
fn test_display_misc() {
test_display(
[0xc0, 0x03, 0x5f, 0xd6],