From 23bd0b37482a127c8f954ce7e068a507b9c1e09e Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 26 Sep 2021 00:40:03 -0700 Subject: 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. --- src/armv7.rs | 12 ++++++------ src/armv8/a64.rs | 22 +++++++++++++--------- test/armv8/a64.rs | 19 +++++++++++++++++++ 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 for InstDecoder { } } _ => { - unreachable!(); + unreachable!("op1 is two bits"); } } } else { @@ -2405,7 +2405,7 @@ impl Decoder 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 for InstDecoder { _ => { unreachable!("impossible bit pattern"); } } } - _ => { unreachable!(); } + _ => { unreachable!("op is two bits"); } } } } else { @@ -3004,7 +3004,7 @@ impl Decoder for InstDecoder { inst.operands[3] = Operand::Nothing; } _ => { - unreachable!(); + unreachable!("opcode is masked to two bits here"); } } } @@ -3248,7 +3248,7 @@ impl Decoder for InstDecoder { return Ok(()); } _ => { - unreachable!(); + unreachable!("word masked to two bits"); } } } @@ -3695,7 +3695,7 @@ impl Decoder 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 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 for InstDecoder { }, 0b001 => { // Conditional compare (register/immediate) - unimplemented!(); + return Err(DecodeError::IncompleteDecoder); }, 0b010 => { // Conditional select @@ -1243,7 +1245,7 @@ impl Decoder 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 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 for InstDecoder { } } _ => { - unimplemented!(); + return Err(DecodeError::IncompleteDecoder); } } } }, _ => { // Data processing (3 source) - unimplemented!(); + return Err(DecodeError::IncompleteDecoder); } } } else { @@ -1730,9 +1732,10 @@ impl Decoder 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 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 = ::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 = ::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], -- cgit v1.1