diff options
-rw-r--r-- | src/long_mode/display.rs | 15 | ||||
-rw-r--r-- | src/long_mode/mod.rs | 26 | ||||
-rw-r--r-- | src/protected_mode/mod.rs | 26 | ||||
-rw-r--r-- | test/long_mode/operand.rs | 15 | ||||
-rw-r--r-- | test/protected_mode/operand.rs | 14 |
5 files changed, 75 insertions, 21 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index b1fb7f8..d042119 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -3308,17 +3308,6 @@ impl Instruction { } } -const MEM_SIZE_STRINGS: [&'static str; 64] = [ - "byte", "word", "BUG", "dword", "BUG", "BUG", "BUG", "qword", - "far", "mword", "BUG", "BUG", "BUG", "BUG", "BUG", "xmmword", - "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", - "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "ymmword", - "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", - "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", - "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", - "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "ptr", "zmmword", -]; - fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { if instr.prefixes.lock() { write!(out, "lock ")?; @@ -3345,7 +3334,7 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors: let x = Operand::from_spec(instr, instr.operands[0]); if x.is_memory() { - out.write_str(MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?; + out.write_str(super::MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?; out.write_str(" ")?; } @@ -3365,7 +3354,7 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors: out.write_str(", ")?; let x = Operand::from_spec(instr, instr.operands[i as usize]); if x.is_memory() { - out.write_str(MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?; + out.write_str(super::MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?; out.write_str(" ")?; } if let Some(prefix) = instr.segment_override_for_op(i) { diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index f2b2b57..4babca3 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -2757,9 +2757,9 @@ pub struct InstDecoder { } impl InstDecoder { - /// Instantiates an x86_64 decoder that decodes the bare minimum of x86_64. + /// instantiates an x86_64 decoder that decodes the bare minimum of x86_64. /// - /// Pedantic and only decodes what the spec says is well-defined, rejecting undefined sequences + /// pedantic and only decodes what the spec says is well-defined, rejecting undefined sequences /// and any instructions defined by extensions. pub fn minimal() -> Self { InstDecoder { @@ -2767,6 +2767,15 @@ impl InstDecoder { } } + /// helper to decode an instruction directly from a byte slice. + /// + /// this lets callers avoid the work of setting up a [`yaxpeax_arch::U8Reader`] for the slice + /// to decode. + pub fn decode_slice(&self, data: &[u8]) -> Result<Instruction, DecodeError> { + let mut reader = yaxpeax_arch::U8Reader::new(data); + self.decode(&mut reader) + } + pub fn sse3(&self) -> bool { self.flags & (1 << 0) != 0 } @@ -4194,6 +4203,17 @@ impl Default for Instruction { } } +const MEM_SIZE_STRINGS: [&'static str; 64] = [ + "byte", "word", "BUG", "dword", "BUG", "BUG", "BUG", "qword", + "far", "mword", "BUG", "BUG", "BUG", "BUG", "BUG", "xmmword", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "ymmword", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "ptr", "zmmword", +]; + pub struct MemoryAccessSize { size: u8, } @@ -4207,7 +4227,7 @@ impl MemoryAccessSize { } pub fn size_name(&self) -> &'static str { - "name_strings" + MEM_SIZE_STRINGS[self.size as usize - 1] } } diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 589d7a3..a088ad6 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -2684,9 +2684,9 @@ pub struct InstDecoder { } impl InstDecoder { - /// Instantiates an x86 decoder that decodes the bare minimum of protected-mode x86. + /// instantiates an x86 decoder that decodes the bare minimum of protected-mode x86. /// - /// Pedantic and only decodes what the spec says is well-defined, rejecting undefined sequences + /// pedantic and only decodes what the spec says is well-defined, rejecting undefined sequences /// and any instructions defined by extensions. pub fn minimal() -> Self { InstDecoder { @@ -2694,6 +2694,15 @@ impl InstDecoder { } } + /// helper to decode an instruction directly from a byte slice. + /// + /// this lets callers avoid the work of setting up a [`yaxpeax_arch::U8Reader`] for the slice + /// to decode. + pub fn decode_slice(&self, data: &[u8]) -> Result<Instruction, DecodeError> { + let mut reader = yaxpeax_arch::U8Reader::new(data); + self.decode(&mut reader) + } + pub fn sse3(&self) -> bool { self.flags & (1 << 0) != 0 } @@ -4103,6 +4112,17 @@ impl Default for Instruction { } } +const MEM_SIZE_STRINGS: [&'static str; 64] = [ + "byte", "word", "BUG", "dword", "far", "ptr", "BUG", "qword", + "BUG", "mword", "BUG", "BUG", "BUG", "BUG", "BUG", "xmmword", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "ymmword", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "ptr", "zmmword", +]; + pub struct MemoryAccessSize { size: u8, } @@ -4116,7 +4136,7 @@ impl MemoryAccessSize { } pub fn size_name(&self) -> &'static str { - "name_strings" + MEM_SIZE_STRINGS[self.size as usize - 1] } } diff --git a/test/long_mode/operand.rs b/test/long_mode/operand.rs index 77ce256..5a51ef3 100644 --- a/test/long_mode/operand.rs +++ b/test/long_mode/operand.rs @@ -1,4 +1,4 @@ -use yaxpeax_x86::long_mode::{Operand, RegSpec}; +use yaxpeax_x86::long_mode::{InstDecoder, MemoryAccessSize, Operand, RegSpec}; #[test] fn register_widths() { @@ -12,5 +12,18 @@ fn register_widths() { #[test] fn memory_widths() { + // the register operand directly doesn't report a size - it comes from the `Instruction` for + // which this is an operand. assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), None); + + fn mem_size_of(data: &[u8]) -> MemoryAccessSize { + let decoder = InstDecoder::default(); + decoder.decode_slice(data).unwrap().mem_size().unwrap() + } + + // and checking the memory size direcly reports correct names + assert_eq!(mem_size_of(&[0x32, 0x00]).size_name(), "byte"); + assert_eq!(mem_size_of(&[0x66, 0x33, 0x00]).size_name(), "word"); + assert_eq!(mem_size_of(&[0x33, 0x00]).size_name(), "dword"); + assert_eq!(mem_size_of(&[0x48, 0x33, 0x00]).size_name(), "qword"); } diff --git a/test/protected_mode/operand.rs b/test/protected_mode/operand.rs index 028cb8f..b2d3624 100644 --- a/test/protected_mode/operand.rs +++ b/test/protected_mode/operand.rs @@ -1,4 +1,4 @@ -use yaxpeax_x86::protected_mode::{Operand, RegSpec}; +use yaxpeax_x86::protected_mode::{InstDecoder, MemoryAccessSize, Operand, RegSpec}; #[test] fn register_widths() { @@ -11,5 +11,17 @@ fn register_widths() { #[test] fn memory_widths() { + // the register operand directly doesn't report a size - it comes from the `Instruction` for + // which this is an operand. assert_eq!(Operand::RegDeref(RegSpec::esp()).width(), None); + + fn mem_size_of(data: &[u8]) -> MemoryAccessSize { + let decoder = InstDecoder::default(); + decoder.decode_slice(data).unwrap().mem_size().unwrap() + } + + // and checking the memory size direcly reports correct names + assert_eq!(mem_size_of(&[0x32, 0x00]).size_name(), "byte"); + assert_eq!(mem_size_of(&[0x66, 0x33, 0x00]).size_name(), "word"); + assert_eq!(mem_size_of(&[0x33, 0x00]).size_name(), "dword"); } |