diff options
| author | iximeow <me@iximeow.net> | 2020-01-03 19:07:42 -0800 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-12 17:29:01 -0800 | 
| commit | 34da4b9ceb5f6b2395dbf23ad6afdc5f473d29c2 (patch) | |
| tree | 463cb5b8e6b0123200b90431c06d147ae70222fb | |
| parent | 179d5d9cb7e94851ba69bf67f6d2dfbafa6aa6fe (diff) | |
match changes in arch to have Resulty decode, instead of Option
| -rw-r--r-- | src/armv7.rs | 95 | ||||
| -rw-r--r-- | src/armv8/a64.rs | 93 | ||||
| -rw-r--r-- | test/armv7.rs | 4 | ||||
| -rw-r--r-- | test/armv8/a64.rs | 4 | 
4 files changed, 123 insertions, 73 deletions
| diff --git a/src/armv7.rs b/src/armv7.rs index 7d13c89..06f1287 100644 --- a/src/armv7.rs +++ b/src/armv7.rs @@ -1,7 +1,7 @@  //#[cfg(feature="use-serde")]  //use serde::{Serialize, Deserialize}; -use std::fmt::{Display, Formatter}; +use std::fmt::{self, Display, Formatter};  use yaxpeax_arch::{Arch, Colorize, Colored, ColorSettings, Decoder, LengthedInstruction, ShowContextual, YaxColors}; @@ -437,6 +437,34 @@ pub struct Instruction {      pub s: bool  } +#[derive(Debug, PartialEq)] +pub enum DecodeError { +    ExhaustedInput, +    InvalidOpcode, +    InvalidOperand, +} + +impl fmt::Display for DecodeError { +    fn fmt(&self, f:  &mut fmt::Formatter) -> fmt::Result { +        match self { +            DecodeError::ExhaustedInput => write!(f, "exhausted input"), +            DecodeError::InvalidOpcode => write!(f, "invalid opcode"), +            DecodeError::InvalidOperand => write!(f, "invalid operand"), +        } +    } +} + +impl yaxpeax_arch::DecodeError for DecodeError { +    fn data_exhausted(&self) -> bool { self == &DecodeError::ExhaustedInput } +    fn bad_opcode(&self) -> bool { self == &DecodeError::InvalidOpcode } +    fn bad_operand(&self) -> bool { self == &DecodeError::InvalidOperand } +} + +impl yaxpeax_arch::Instruction for Instruction { +    // TODO: this is wrong!! +    fn well_defined(&self) -> bool { true } +} +  #[allow(non_snake_case)]  impl Instruction {      pub fn blank() -> Instruction { @@ -673,29 +701,25 @@ pub struct InstDecoder {}  #[allow(non_snake_case)]  impl Decoder<Instruction> for InstDecoder { -    fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Option<Instruction> { +    type Error = DecodeError; + +    fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Result<Instruction, Self::Error> {          let mut blank = Instruction::blank(); -        match self.decode_into(&mut blank, bytes) { -            Some(_) => Some(blank), -            None => None -        } +        self.decode_into(&mut blank, bytes).map(|_: ()| blank)      } -    fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Option<()> { -        fn read_word<T: IntoIterator<Item=u8>>(bytes: T) -> Option<u32> { +    fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Result<(), Self::Error> { +        fn read_word<T: IntoIterator<Item=u8>>(bytes: T) -> Result<u32, DecodeError> {              let mut iter = bytes.into_iter();              let instr: u32 = -                ((iter.next()? as u32)      ) | -                ((iter.next()? as u32) << 8 ) | -                ((iter.next()? as u32) << 16) | -                ((iter.next()? as u32) << 24); +                ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u32)      ) | +                ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u32) << 8 ) | +                ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u32) << 16) | +                ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u32) << 24); -            Some(instr) +            Ok(instr)          } -        let word = match read_word(bytes) { -            Some(word) => word, -            None => { return None; } -        }; +        let word = read_word(bytes)?;          let (cond, opc_upper) = {              let top_byte = word >> 24; @@ -736,7 +760,7 @@ impl Decoder<Instruction> for InstDecoder {              } else {                  inst.opcode = Opcode::Incomplete(word);              } -            return Some(()); +            return Ok(());          } else {              inst.condition = ConditionCode::build(cond);          } @@ -784,7 +808,7 @@ impl Decoder<Instruction> for InstDecoder {                              0b010 => {                                  if s {                                      inst.opcode = Opcode::Invalid; -                                    return None; +                                    return Err(DecodeError::InvalidOpcode);                                  }                                  inst.opcode = Opcode::UMAAL;                                  inst.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]); @@ -792,7 +816,7 @@ impl Decoder<Instruction> for InstDecoder {                              0b011 => {                                  if s {                                      inst.opcode = Opcode::Invalid; -                                    return None; +                                    return Err(DecodeError::InvalidOpcode);                                  }                                  inst.opcode = Opcode::MLS;                                  inst.operands = Operands::MulFourRegs(R[3], R[0], R[1], R[2]); @@ -846,7 +870,7 @@ impl Decoder<Instruction> for InstDecoder {                                      },                                      0b10001 | 0b10010 | 0b10011 => {                                          inst.opcode = Opcode::Invalid; -                                        return None; +                                        return Err(DecodeError::InvalidOpcode);                                      }                                      0b10100 => {                                          inst.opcode = Opcode::SWPB; @@ -854,7 +878,7 @@ impl Decoder<Instruction> for InstDecoder {                                      },                                      0b10101 | 0b10110 | 0b10111 => {                                          inst.opcode = Opcode::Invalid; -                                        return None; +                                        return Err(DecodeError::InvalidOpcode);                                      }                                      0b11000 => {                                          inst.opcode = Opcode::STREX; @@ -938,13 +962,13 @@ impl Decoder<Instruction> for InstDecoder {                      // |c o n d|0 0 0 x|x x x x x x x x x x x x x x x x|1 1 0 1|x x x x|                      // page A5-201                                  inst.opcode = Opcode::Incomplete(word); -                                return Some(()); +                                return Ok(());                              }                              0b11 => {                      // |c o n d|0 0 0 x|x x x x x x x x x x x x x x x x|1 1 1 1|x x x x|                      // page A5-201                                  inst.opcode = Opcode::Incomplete(word); -                                return Some(()); +                                return Ok(());                              }                              _ => { unreachable!(); }                          } @@ -975,14 +999,14 @@ impl Decoder<Instruction> for InstDecoder {                                      if opcode & 0b11 == 0b01 {                                          inst.opcode = Opcode::BLX;                                          inst.operands = Operands::OneOperand((word & 0x0f) as u8); -                                        return Some(()); +                                        return Ok(());                                      } else { -                                        return None; +                                        return Err(DecodeError::InvalidOpcode);                                      }                                  },                                  0b100 => {                                      inst.opcode = Opcode::Incomplete(word); -                                    return Some(()); +                                    return Ok(());                                  },                                  0b101 => { @@ -1000,7 +1024,7 @@ impl Decoder<Instruction> for InstDecoder {                              // |c o n d|0 0 0|1 0 x x|0|x x x x|x x x x|x x x x|1|x x|x|x x x x|                              // multiply and multiply-accumulate                               inst.opcode = Opcode::Incomplete(word); -                            return Some(()); +                            return Ok(());                          }                      } else {                          if opcode >= 16 { @@ -1057,7 +1081,7 @@ impl Decoder<Instruction> for InstDecoder {                              if (0b1101 & opcode) == 0b1101 {                                  // these are all invalid                                  inst.opcode = Opcode::Invalid; -                                return None; +                                return Err(DecodeError::InvalidOpcode);                              } else {                                  inst.operands = Operands::ThreeOperandWithShift(Rd, Rn, Rm, ShiftSpec::Register(shift_spec));                              } @@ -1081,7 +1105,7 @@ impl Decoder<Instruction> for InstDecoder {                  // |c o n d|0 0 0|1 0 x x|0|x x x x|x x x x|x x x x x|x x|x|x x x x|                  // misc instructions (page A5-194)                      inst.opcode = Opcode::Incomplete(word); -                    return Some(()); +                    return Ok(());                  } else {                      if opcode >= 16 {                          unreachable!(); @@ -1151,7 +1175,7 @@ impl Decoder<Instruction> for InstDecoder {                              if Rn == 0b1111 {                                  inst.operands = Operands::RegImm(Rt, imm.into());                                  inst.opcode = Opcode::LDR(add, pre, wback); -                                return Some(()); +                                return Ok(());                              }                              Opcode::LDR(add, pre, wback)                          }, @@ -1160,7 +1184,7 @@ impl Decoder<Instruction> for InstDecoder {                              if Rn == 0b1111 {                                  inst.operands = Operands::RegImm(Rt, imm.into());                                  inst.opcode = Opcode::LDRB(add, pre, wback); -                                return Some(()); +                                return Ok(());                              }                              Opcode::LDRB(add, pre, wback)                          }, @@ -1237,7 +1261,7 @@ impl Decoder<Instruction> for InstDecoder {                      };                      inst.operands = Operands::ThreeOperandWithShift(Rn, Rt, Rm, ShiftSpec::Immediate(shift));                  } -                return Some(()); +                return Ok(());              },              0b100 | 0b101 => {                  // branch, branch with link, and block data transfer @@ -1273,11 +1297,11 @@ impl Decoder<Instruction> for InstDecoder {                  // coprocessor instructions and supervisor call                  // page A5-213                  inst.opcode = Opcode::Incomplete(word); -                return Some(()); +                return Ok(());              },              _ => { unreachable!(); }          } -        Some(()) +        Ok(())      }  } @@ -1292,6 +1316,7 @@ pub struct ARMv7;  impl Arch for ARMv7 {      type Address = u32;      type Instruction = Instruction; +    type DecodeError = DecodeError;      type Decoder = InstDecoder;      type Operand = Operands;  } diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index 6dd9d68..0f2af3a 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -1,7 +1,7 @@  //#[cfg(feature="use-serde")]  //use serde::{Serialize, Deserialize}; -use std::fmt::{Display, Formatter}; +use std::fmt::{self, Display, Formatter};  use yaxpeax_arch::{Arch, ColorSettings, Decoder, LengthedInstruction, ShowContextual}; @@ -126,6 +126,34 @@ mod docs {      }  } +#[derive(Debug, PartialEq)] +pub enum DecodeError { +    ExhaustedInput, +    InvalidOpcode, +    InvalidOperand, +} + +impl fmt::Display for DecodeError { +    fn fmt(&self, f:  &mut fmt::Formatter) -> fmt::Result { +        match self { +            DecodeError::ExhaustedInput => write!(f, "exhausted input"), +            DecodeError::InvalidOpcode => write!(f, "invalid opcode"), +            DecodeError::InvalidOperand => write!(f, "invalid operand"), +        } +    } +} + +impl yaxpeax_arch::DecodeError for DecodeError { +    fn data_exhausted(&self) -> bool { self == &DecodeError::ExhaustedInput } +    fn bad_opcode(&self) -> bool { self == &DecodeError::InvalidOpcode } +    fn bad_operand(&self) -> bool { self == &DecodeError::InvalidOperand } +} + +impl yaxpeax_arch::Instruction for Instruction { +    // TODO: this is wrong!! +    fn well_defined(&self) -> bool { true } +} +  #[allow(non_snake_case)]  impl <T: std::fmt::Write> ShowContextual<u64, [Option<String>], T> for Instruction {      fn contextualize(&self, _colors: Option<&ColorSettings>, _address: u64, _context: Option<&[Option<String>]>, out: &mut T) -> std::fmt::Result { @@ -144,6 +172,7 @@ pub struct ARMv8 { }  impl Arch for ARMv8 {      type Address = u64;      type Instruction = Instruction; +    type DecodeError = DecodeError;      type Decoder = InstDecoder;      type Operand = Operand;  } @@ -981,29 +1010,25 @@ pub struct InstDecoder {}  #[allow(non_snake_case)]  impl Decoder<Instruction> for InstDecoder { -    fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Option<Instruction> { +    type Error = DecodeError; + +    fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Result<Instruction, Self::Error> {          let mut blank = Instruction::blank(); -        match self.decode_into(&mut blank, bytes) { -            Some(_) => Some(blank), -            None => None -        } +        self.decode_into(&mut blank, bytes).map(|_: ()| blank)      } -    fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Option<()> { -        fn read_word<T: IntoIterator<Item=u8>>(bytes: T) -> Option<u32> { +    fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Result<(), Self::Error> { +        fn read_word<T: IntoIterator<Item=u8>>(bytes: T) -> Result<u32, DecodeError> {              let mut iter = bytes.into_iter();              let instr: u32 = -                ((iter.next()? as u32)      ) | -                ((iter.next()? as u32) << 8 ) | -                ((iter.next()? as u32) << 16) | -                ((iter.next()? as u32) << 24); +                ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u32)      ) | +                ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u32) << 8 ) | +                ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u32) << 16) | +                ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u32) << 24); -            Some(instr) +            Ok(instr)          } -        let word = match read_word(bytes) { -            Some(word) => word, -            None => { return None; } -        }; +        let word = read_word(bytes)?;          #[derive(Copy, Clone, Debug)]          enum Section { @@ -1079,7 +1104,7 @@ impl Decoder<Instruction> for InstDecoder {                              if opc2 == 0b000000 {                                  inst.opcode = Opcode::Invalid; -                                return Some(()); +                                return Err(DecodeError::InvalidOperand);                              }                              let size_code = match word >> 29 { @@ -1138,7 +1163,7 @@ impl Decoder<Instruction> for InstDecoder {                              if word & 0x20000000 != 0 {                                  inst.opcode = Opcode::Invalid; -                                return Some(()); +                                return Err(DecodeError::InvalidOperand);                              }                              let size = match sf_op | op2 { @@ -1183,7 +1208,7 @@ impl Decoder<Instruction> for InstDecoder {                                  0b1110 |                                  0b1111 => {                                      inst.opcode = Opcode::Invalid; -                                    return Some(()); +                                    return Err(DecodeError::InvalidOpcode);                                  },                                  _ => {                                      unreachable!("sf, op, op2 are four bits total"); @@ -1238,7 +1263,7 @@ impl Decoder<Instruction> for InstDecoder {                                                      // technically this is undefined - do some                                                      // cores do something with this?                                                      inst.opcode = Opcode::Invalid; -                                                    return None; +                                                    return Err(DecodeError::InvalidOperand);                                                  }                                                  inst.opcode = Opcode::PACIZA;                                                  inst.operands = [ @@ -1321,7 +1346,7 @@ impl Decoder<Instruction> for InstDecoder {                              if (word >> 22) & 0x03 != 0 {                                  inst.opcode = Opcode::Invalid; -                                return None; +                                return Err(DecodeError::InvalidOperand);                              }                              let Rd = (word & 0x1f) as u16; @@ -1351,7 +1376,7 @@ impl Decoder<Instruction> for InstDecoder {                              let shift = (word >> 22) & 0x03;                              if shift == 0b11 {                                  inst.opcode = Opcode::Invalid; -                                return None; +                                return Err(DecodeError::InvalidOperand);                              }                              let Rd = (word & 0x1f) as u16; @@ -1361,7 +1386,7 @@ impl Decoder<Instruction> for InstDecoder {                              if size == SizeCode::W && imm6 >= 32 {                                  inst.opcode = Opcode::Invalid; -                                return None; +                                return Err(DecodeError::InvalidOperand);                              }                              inst.operands[0] = Operand::Register(size, Rd); @@ -1467,7 +1492,7 @@ impl Decoder<Instruction> for InstDecoder {                              0b10 |                              0b11 => {                                  inst.opcode = Opcode::Invalid; -                                return None; +                                return Err(DecodeError::InvalidOperand);                              }                              _ => { unreachable!("shift is two bits"); }                          }; @@ -1756,7 +1781,7 @@ impl Decoder<Instruction> for InstDecoder {                                          (0b10, 0b1) => Opcode::LDAXRB,                                          _ => {                                              inst.opcode = Opcode::Invalid; -                                            return None; +                                            return Err(DecodeError::InvalidOpcode);                                          }                                      }                                  } else if size == 0b01 { @@ -1767,7 +1792,7 @@ impl Decoder<Instruction> for InstDecoder {                                          (0b10, 0b1) => Opcode::LDAXRH,                                          _ => {                                              inst.opcode = Opcode::Invalid; -                                            return None; +                                            return Err(DecodeError::InvalidOpcode);                                          }                                      }                                  } else { @@ -1872,7 +1897,7 @@ impl Decoder<Instruction> for InstDecoder {                              (0b11, 0b10, 0b1) => Opcode::LDAR, // 64-bit                              _ => {                                  inst.opcode = Opcode::Invalid; -                                return None; +                                return Err(DecodeError::InvalidOpcode);                              }                          };                          let size_code = if size == 0b11 { @@ -1939,7 +1964,7 @@ impl Decoder<Instruction> for InstDecoder {                              0b11 => {                                  // 11011100_XXXXXXXX_XXXXXXXX_XXXXXXXX                                  inst.opcode = Opcode::Invalid; -                                return None; +                                return Err(DecodeError::InvalidOpcode);                              }                              _ => {                                  unreachable!("opc is two bits"); @@ -2155,7 +2180,7 @@ impl Decoder<Instruction> for InstDecoder {                          if word & 0x200000 != 0 {                              if category != 0b10 {                                  inst.opcode = Opcode::Invalid; -                                return Some(()); +                                return Err(DecodeError::InvalidOpcode);                              } else {                                  // Load/store register (register offset)                                  // C3.3.10 @@ -2236,7 +2261,7 @@ impl Decoder<Instruction> for InstDecoder {                                      0b00 |                                      0b01 => {                                          inst.opcode = Opcode::Invalid; -                                        return Some(()); +                                        return Err(DecodeError::InvalidOpcode);                                      },                                      0b10 => { SizeCode::W }                                      0b11 => { SizeCode::X } @@ -2247,14 +2272,14 @@ impl Decoder<Instruction> for InstDecoder {                                      0b000 |                                      0b001 => {                                          inst.opcode = Opcode::Invalid; -                                        return Some(()); +                                        return Err(DecodeError::InvalidOpcode);                                      },                                      0b010 => { ShiftStyle::UXTW },                                      0b011 => { ShiftStyle::LSL },                                      0b100 |                                      0b101 => {                                          inst.opcode = Opcode::Invalid; -                                        return Some(()); +                                        return Err(DecodeError::InvalidOpcode);                                      },                                      0b110 => { ShiftStyle::SXTW },                                      0b111 => { ShiftStyle::SXTX }, @@ -3013,6 +3038,6 @@ impl Decoder<Instruction> for InstDecoder {              },          }; -        Some(()) +        Ok(())      }  } diff --git a/test/armv7.rs b/test/armv7.rs index 7b0c2b6..fbd71ee 100644 --- a/test/armv7.rs +++ b/test/armv7.rs @@ -403,10 +403,10 @@ pub fn bench_60000_instrs(b: &mut Bencher) {              let mut result = Instruction::blank();              loop {                  match decoder.decode_into(&mut result, &mut iter) { -                    Some(result) => { +                    Ok(result) => {                          test::black_box(&result);                      }, -                    None => { +                    Err(_) => {                          break;                      }                  } diff --git a/test/armv8/a64.rs b/test/armv8/a64.rs index 4886fe1..406b867 100644 --- a/test/armv8/a64.rs +++ b/test/armv8/a64.rs @@ -2335,10 +2335,10 @@ pub fn bench_60000_instrs(b: &mut Bencher) {              let mut result = Instruction::blank();              loop {                  match decoder.decode_into(&mut result, &mut iter) { -                    Some(result) => { +                    Ok(result) => {                          test::black_box(&result);                      }, -                    None => { +                    Err(_) => {                          break;                      }                  } | 
