diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/armv7.rs | 62 | ||||
-rw-r--r-- | src/armv7/thumb.rs | 21 | ||||
-rw-r--r-- | src/armv8/a64.rs | 43 |
3 files changed, 63 insertions, 63 deletions
diff --git a/src/armv7.rs b/src/armv7.rs index b815218..82b7732 100644 --- a/src/armv7.rs +++ b/src/armv7.rs @@ -7,7 +7,7 @@ use std::fmt::{self, Display, Formatter}; -use yaxpeax_arch::{Arch, AddressDiff, Colorize, Decoder, LengthedInstruction, NoColors, ShowContextual, YaxColors}; +use yaxpeax_arch::{Arch, AddressDiff, Colorize, Decoder, LengthedInstruction, Reader, ReadError, NoColors, ShowContextual, YaxColors}; mod thumb; @@ -1565,7 +1565,7 @@ pub struct Instruction { pub thumb: bool, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Copy, Clone)] pub enum DecodeError { ExhaustedInput, InvalidOpcode, @@ -1578,15 +1578,14 @@ pub enum DecodeError { 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"), - DecodeError::Incomplete => write!(f, "incomplete decoder"), - DecodeError::Nonconforming => write!(f, "invalid reserved bits"), - DecodeError::Undefined => write!(f, "undefined encoding"), - DecodeError::Unpredictable => write!(f, "unpredictable instruction"), - } + use yaxpeax_arch::DecodeError; + f.write_str(self.description()) + } +} + +impl From<ReadError> for DecodeError { + fn from(_e: ReadError) -> DecodeError { + DecodeError::ExhaustedInput } } @@ -1596,6 +1595,17 @@ impl yaxpeax_arch::DecodeError for DecodeError { fn bad_operand(&self) -> bool { self == &DecodeError::InvalidOperand || self == &DecodeError::Unpredictable } + fn description(&self) -> &'static str { + match self { + DecodeError::ExhaustedInput => "exhausted input", + DecodeError::InvalidOpcode => "invalid opcode", + DecodeError::InvalidOperand => "invalid operand", + DecodeError::Incomplete => "incomplete decoder", + DecodeError::Nonconforming => "invalid reserved bits", + DecodeError::Undefined => "undefined encoding", + DecodeError::Unpredictable => "unpredictable instruction", + } + } } impl yaxpeax_arch::Instruction for Instruction { @@ -2036,30 +2046,19 @@ impl InstDecoder { } #[allow(non_snake_case)] -impl Decoder<Instruction> for InstDecoder { - type Error = DecodeError; - - fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Result<(), Self::Error> { +impl Decoder<ARMv7> for InstDecoder { + fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(&self, inst: &mut Instruction, words: &mut T) -> Result<(), <ARMv7 as Arch>::DecodeError> { inst.set_w(false); inst.set_wide(false); if self.thumb { - return thumb::decode_into(&self, inst, bytes); + return thumb::decode_into(&self, inst, words); } else { inst.set_thumb(false); } - fn read_word<T: IntoIterator<Item=u8>>(bytes: T) -> Result<u32, DecodeError> { - let mut iter = bytes.into_iter(); - let instr: u32 = - ((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); - - Ok(instr) - } - - let word = read_word(bytes)?; + let mut word_bytes = [0u8; 4]; + words.next_n(&mut word_bytes)?; + let word = u32::from_le_bytes(word_bytes); let (cond, opc_upper) = { let top_byte = word >> 24; @@ -3696,16 +3695,13 @@ impl Decoder<Instruction> for InstDecoder { } } -#[cfg(feature="use-serde")] -#[derive(Debug, Serialize, Deserialize)] -pub struct ARMv7; - -#[cfg(not(feature="use-serde"))] +#[cfg_attr(feature="use-serde", derive(Serialize, Deserialize))] #[derive(Debug)] pub struct ARMv7; impl Arch for ARMv7 { type Address = u32; + type Word = u8; type Instruction = Instruction; type DecodeError = DecodeError; type Decoder = InstDecoder; diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs index 3c480af..8017f01 100644 --- a/src/armv7/thumb.rs +++ b/src/armv7/thumb.rs @@ -1,9 +1,12 @@ // use yaxpeax_arch::{Arch, AddressDiff, Decoder, LengthedInstruction}; +use yaxpeax_arch::Arch; +use armv7::ARMv7; use armv7::ConditionCode; use armv7::DecodeError; use armv7::CReg; use armv7::Reg; +use armv7::Reader; use armv7::RegShift; use armv7::Operand; use armv7::Opcode; @@ -97,20 +100,20 @@ fn DecodeImmShift(reg: u8, ty: u8, imm5: u8) -> RegShift { } #[allow(non_snake_case)] -pub fn decode_into<T: IntoIterator<Item=u8>>(decoder: &InstDecoder, inst: &mut Instruction, bytes: T) -> Result<(), DecodeError> { +pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(decoder: &InstDecoder, inst: &mut Instruction, words: &mut T) -> Result<(), <ARMv7 as Arch>::DecodeError> { // these are cleared in `armv7::InstDecoder::decode_into`. // they must be reset when switching out of thumb decoding or decoding a new thumb instruction, // which that `decode_into` is the entrypoint for in all cases. // inst.set_w(false); // inst.set_wide(false); inst.set_thumb(true); - let mut iter = bytes.into_iter(); - let instr: u16 = - ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u16) ) | - ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u16) << 8 ); + let mut word_bytes = [0u8; 2]; + words.next_n(&mut word_bytes)?; + let word = u16::from_le_bytes(word_bytes); + let instr = word; let mut instr2 = bitarr![Lsb0, u16; 0u16; 16]; - instr2[0..16].store(instr); + instr2[0..16].store(word); let opword = instr2[11..].load::<u16>(); @@ -122,9 +125,9 @@ pub fn decode_into<T: IntoIterator<Item=u8>>(decoder: &InstDecoder, inst: &mut I // 32b instruction - `A6-228, 32-bit Thumb instruction encoding` // opword low bits 01, 10, and 11 correspond to `op1` in table `A6-9` - let lower: u16 = - ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u16) ) | - ((iter.next().ok_or(DecodeError::ExhaustedInput)? as u16) << 8 ); + let mut word_bytes = [0u8; 2]; + words.next_n(&mut word_bytes)?; + let lower = u16::from_le_bytes(word_bytes); let mut lower2 = bitarr![Lsb0, u16; 0u16; 16]; lower2[0..16].store(lower); diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index 11b6499..2ef75d8 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter}; -use yaxpeax_arch::{Arch, AddressDiff, Decoder, LengthedInstruction, ShowContextual, YaxColors}; +use yaxpeax_arch::{Arch, AddressDiff, Decoder, LengthedInstruction, Reader, ReadError, ShowContextual, YaxColors}; #[allow(non_snake_case)] mod docs { @@ -135,11 +135,14 @@ pub enum DecodeError { 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"), - } + use yaxpeax_arch::DecodeError; + f.write_str(self.description()) + } +} + +impl From<ReadError> for DecodeError { + fn from(_e: ReadError) -> DecodeError { + DecodeError::ExhaustedInput } } @@ -147,6 +150,13 @@ 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 } + fn description(&self) -> &'static str { + match self { + DecodeError::ExhaustedInput => "exhausted input", + DecodeError::InvalidOpcode => "invalid opcode", + DecodeError::InvalidOperand => "invalid operand", + } + } } impl yaxpeax_arch::Instruction for Instruction { @@ -171,6 +181,7 @@ pub struct ARMv8 { } pub struct ARMv8 { } impl Arch for ARMv8 { + type Word = u8; type Address = u64; type Instruction = Instruction; type DecodeError = DecodeError; @@ -1014,22 +1025,12 @@ impl Display for Operand { pub struct InstDecoder {} #[allow(non_snake_case)] -impl Decoder<Instruction> for InstDecoder { - type Error = DecodeError; - - 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().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); - - Ok(instr) - } +impl Decoder<ARMv8> for InstDecoder { + fn decode_into<T: Reader<<ARMv8 as Arch>::Address, <ARMv8 as Arch>::Word>>(&self, inst: &mut Instruction, words: &mut T) -> Result<(), <ARMv8 as Arch>::DecodeError> { + let mut word_bytes = [0u8; 4]; + words.next_n(&mut word_bytes)?; + let word = u32::from_le_bytes(word_bytes); - let word = read_word(bytes)?; #[derive(Copy, Clone, Debug)] enum Section { |