diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 19 | ||||
-rw-r--r-- | src/long_mode/mod.rs | 75 | ||||
-rw-r--r-- | src/protected_mode/mod.rs | 75 | ||||
-rw-r--r-- | src/real_mode/mod.rs | 74 |
4 files changed, 149 insertions, 94 deletions
@@ -12,6 +12,7 @@ //! //! let inst = decoder.decode_slice(&[0x33, 0xc0]).unwrap(); //! +//! #[cfg(features="fmt")] //! assert_eq!("xor eax, eax", inst.to_string()); //! ``` //! @@ -31,13 +32,16 @@ //! //! let inst = decoder.decode_slice(&[0x33, 0x01]).unwrap(); //! +//! #[cfg(features="fmt")] //! assert_eq!("xor eax, dword [rcx]", inst.to_string()); //! //! assert_eq!(Operand::Register(RegSpec::eax()), inst.operand(0)); +//! #[cfg(features="fmt")] //! assert_eq!("eax", inst.operand(0).to_string()); //! assert_eq!(Operand::RegDeref(RegSpec::rcx()), inst.operand(1)); //! //! // an operand in isolation does not know the size of memory it references, if any +//! #[cfg(features="fmt")] //! assert_eq!("[rcx]", inst.operand(1).to_string()); //! //! // and for memory operands, the size must be read from the instruction itself: @@ -45,6 +49,7 @@ //! assert_eq!("dword", mem_size.size_name()); //! //! // `MemoryAccessSize::size_name()` is how its `Display` impl works, as well: +//! #[cfg(features="fmt")] //! assert_eq!("dword", mem_size.to_string()); //! ``` //! @@ -54,12 +59,23 @@ //! mod decoder { //! use yaxpeax_arch::{Arch, AddressDisplay, Decoder, Reader, ReaderBuilder}; //! +//! // have to play some games so this example works right even without `fmt` enabled! +//! #[cfg(feature="fmt")] +//! trait InstBound: std::fmt::Display {} +//! #[cfg(not(feature="fmt"))] +//! trait InstBound {} +//! +//! #[cfg(feature="fmt")] +//! impl <T: std::fmt::Display> InstBound for T {} +//! #[cfg(not(feature="fmt"))] +//! impl <T> InstBound for T {} +//! //! pub fn decode_stream< //! 'data, //! A: yaxpeax_arch::Arch, //! U: ReaderBuilder<A::Address, A::Word>, //! >(data: U) where -//! A::Instruction: std::fmt::Display, +//! A::Instruction: InstBound, //! { //! let mut reader = ReaderBuilder::read_from(data); //! let mut address: A::Address = reader.total_offset(); @@ -69,6 +85,7 @@ //! loop { //! match decode_res { //! Ok(ref inst) => { +//! #[cfg(feature="fmt")] //! println!("{}: {}", address.show(), inst); //! decode_res = decoder.decode(&mut reader); //! address = reader.total_offset(); diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index d2cb2f7..6475d4e 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -888,11 +888,13 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[ /// } /// /// if let Operand::Register(regspec) = instruction.operand(0) { +/// #[cfg(feature="fmt")] /// println!("first operand is {}", regspec); /// show_register_class_info(regspec.class()); /// } /// /// if let Operand::Register(regspec) = instruction.operand(1) { +/// #[cfg(feature="fmt")] /// println!("first operand is {}", regspec); /// show_register_class_info(regspec.class()); /// } @@ -7422,43 +7424,54 @@ impl InnerDescription { } } -impl fmt::Display for InnerDescription { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - InnerDescription::RexPrefix(bits) => { - write!(f, "rex prefix: {}{}{}{}", - if bits & 0x8 != 0 { "w" } else { "-" }, - if bits & 0x4 != 0 { "r" } else { "-" }, - if bits & 0x2 != 0 { "x" } else { "-" }, - if bits & 0x1 != 0 { "b" } else { "-" }, - ) - } - InnerDescription::SegmentPrefix(segment) => { - write!(f, "segment override: {}", segment) - } - InnerDescription::Misc(text) => { - f.write_str(text) - } - InnerDescription::Number(text, num) => { - write!(f, "{}: {:#x}", text, num) - } - InnerDescription::Opcode(opc) => { - write!(f, "opcode `{}`", opc) - } - InnerDescription::OperandCode(OperandCodeWrapper { code }) => { - write!(f, "operand code `{:?}`", code) - } - InnerDescription::RegisterNumber(name, num, reg) => { - write!(f, "`{}` (`{}` selects register number {})", reg, name, num) +cfg_if::cfg_if! { + if #[cfg(feature="fmt")] { + impl fmt::Display for InnerDescription { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + InnerDescription::RexPrefix(bits) => { + write!(f, "rex prefix: {}{}{}{}", + if bits & 0x8 != 0 { "w" } else { "-" }, + if bits & 0x4 != 0 { "r" } else { "-" }, + if bits & 0x2 != 0 { "x" } else { "-" }, + if bits & 0x1 != 0 { "b" } else { "-" }, + ) + } + InnerDescription::SegmentPrefix(segment) => { + write!(f, "segment override: {}", segment) + } + InnerDescription::Misc(text) => { + f.write_str(text) + } + InnerDescription::Number(text, num) => { + write!(f, "{}: {:#x}", text, num) + } + InnerDescription::Opcode(opc) => { + write!(f, "opcode `{}`", opc) + } + InnerDescription::OperandCode(OperandCodeWrapper { code }) => { + write!(f, "operand code `{:?}`", code) + } + InnerDescription::RegisterNumber(name, num, reg) => { + write!(f, "`{}` (`{}` selects register number {})", reg, name, num) + } + InnerDescription::Boundary(desc) => { + write!(f, "{}", desc) + } + } } - InnerDescription::Boundary(desc) => { - write!(f, "{}", desc) + } + } else { + impl fmt::Display for InnerDescription { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("non-fmt build") } } } } -#[derive(Clone, PartialEq, Eq, Debug)] +#[cfg_attr(feature="fmt", derive(Debug))] +#[derive(Clone, PartialEq, Eq)] pub struct FieldDescription { desc: InnerDescription, id: u32, diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 0a6fcf8..dd63d32 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -833,11 +833,13 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[ /// } /// /// if let Operand::Register(regspec) = instruction.operand(0) { +/// #[cfg(feature="fmt")] /// println!("first operand is {}", regspec); /// show_register_class_info(regspec.class()); /// } /// /// if let Operand::Register(regspec) = instruction.operand(1) { +/// #[cfg(feature="fmt")] /// println!("first operand is {}", regspec); /// show_register_class_info(regspec.class()); /// } @@ -7386,7 +7388,8 @@ fn read_0f3a_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { }; } -/// the actual description for a selection of bits involved in decoding an [`long_mode::Instruction`]. +/// the actual description for a selection of bits involved in decoding a +/// [`protected_mode::Instruction`]. /// /// some prefixes are only identified as an `InnerDescription::Misc` string, while some are full /// `InnerDescription::SegmentPrefix(Segment)`. generally, strings should be considered unstable @@ -7439,37 +7442,47 @@ impl InnerDescription { } } -impl fmt::Display for InnerDescription { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - InnerDescription::RexPrefix(bits) => { - write!(f, "rex prefix: {}{}{}{}", - if bits & 0x8 != 0 { "w" } else { "-" }, - if bits & 0x4 != 0 { "r" } else { "-" }, - if bits & 0x2 != 0 { "x" } else { "-" }, - if bits & 0x1 != 0 { "b" } else { "-" }, - ) - } - InnerDescription::SegmentPrefix(segment) => { - write!(f, "segment override: {}", segment) - } - InnerDescription::Misc(text) => { - f.write_str(text) - } - InnerDescription::Number(text, num) => { - write!(f, "{}: {:#x}", text, num) - } - InnerDescription::Opcode(opc) => { - write!(f, "opcode `{}`", opc) - } - InnerDescription::OperandCode(OperandCodeWrapper { code }) => { - write!(f, "operand code `{:?}`", code) - } - InnerDescription::RegisterNumber(name, num, reg) => { - write!(f, "`{}` (`{}` selects register number {})", reg, name, num) +cfg_if::cfg_if! { + if #[cfg(feature = "fmt")] { + impl fmt::Display for InnerDescription { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + InnerDescription::RexPrefix(bits) => { + write!(f, "rex prefix: {}{}{}{}", + if bits & 0x8 != 0 { "w" } else { "-" }, + if bits & 0x4 != 0 { "r" } else { "-" }, + if bits & 0x2 != 0 { "x" } else { "-" }, + if bits & 0x1 != 0 { "b" } else { "-" }, + ) + } + InnerDescription::SegmentPrefix(segment) => { + write!(f, "segment override: {}", segment) + } + InnerDescription::Misc(text) => { + f.write_str(text) + } + InnerDescription::Number(text, num) => { + write!(f, "{}: {:#x}", text, num) + } + InnerDescription::Opcode(opc) => { + write!(f, "opcode `{}`", opc) + } + InnerDescription::OperandCode(OperandCodeWrapper { code }) => { + write!(f, "operand code `{:?}`", code) + } + InnerDescription::RegisterNumber(name, num, reg) => { + write!(f, "`{}` (`{}` selects register number {})", reg, name, num) + } + InnerDescription::Boundary(desc) => { + write!(f, "{}", desc) + } + } } - InnerDescription::Boundary(desc) => { - write!(f, "{}", desc) + } + } else { + impl fmt::Display for InnerDescription { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("non-fmt build") } } } diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 4b8ad6d..d7fda17 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -833,11 +833,13 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[ /// } /// /// if let Operand::Register(regspec) = instruction.operand(0) { +/// #[cfg(feature="fmt")] /// println!("first operand is {}", regspec); /// show_register_class_info(regspec.class()); /// } /// /// if let Operand::Register(regspec) = instruction.operand(1) { +/// #[cfg(feature="fmt")] /// println!("first operand is {}", regspec); /// show_register_class_info(regspec.class()); /// } @@ -7388,7 +7390,7 @@ fn read_0f3a_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { }; } -/// the actual description for a selection of bits involved in decoding an [`long_mode::Instruction`]. +/// the actual description for a selection of bits involved in decoding a [`real_mode::Instruction`]. /// /// some prefixes are only identified as an `InnerDescription::Misc` string, while some are full /// `InnerDescription::SegmentPrefix(Segment)`. generally, strings should be considered unstable @@ -7441,37 +7443,47 @@ impl InnerDescription { } } -impl fmt::Display for InnerDescription { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - InnerDescription::RexPrefix(bits) => { - write!(f, "rex prefix: {}{}{}{}", - if bits & 0x8 != 0 { "w" } else { "-" }, - if bits & 0x4 != 0 { "r" } else { "-" }, - if bits & 0x2 != 0 { "x" } else { "-" }, - if bits & 0x1 != 0 { "b" } else { "-" }, - ) - } - InnerDescription::SegmentPrefix(segment) => { - write!(f, "segment override: {}", segment) - } - InnerDescription::Misc(text) => { - f.write_str(text) - } - InnerDescription::Number(text, num) => { - write!(f, "{}: {:#x}", text, num) - } - InnerDescription::Opcode(opc) => { - write!(f, "opcode `{}`", opc) - } - InnerDescription::OperandCode(OperandCodeWrapper { code }) => { - write!(f, "operand code `{:?}`", code) - } - InnerDescription::RegisterNumber(name, num, reg) => { - write!(f, "`{}` (`{}` selects register number {})", reg, name, num) +cfg_if::cfg_if! { + if #[cfg(feature = "fmt")] { + impl fmt::Display for InnerDescription { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + InnerDescription::RexPrefix(bits) => { + write!(f, "rex prefix: {}{}{}{}", + if bits & 0x8 != 0 { "w" } else { "-" }, + if bits & 0x4 != 0 { "r" } else { "-" }, + if bits & 0x2 != 0 { "x" } else { "-" }, + if bits & 0x1 != 0 { "b" } else { "-" }, + ) + } + InnerDescription::SegmentPrefix(segment) => { + write!(f, "segment override: {}", segment) + } + InnerDescription::Misc(text) => { + f.write_str(text) + } + InnerDescription::Number(text, num) => { + write!(f, "{}: {:#x}", text, num) + } + InnerDescription::Opcode(opc) => { + write!(f, "opcode `{}`", opc) + } + InnerDescription::OperandCode(OperandCodeWrapper { code }) => { + write!(f, "operand code `{:?}`", code) + } + InnerDescription::RegisterNumber(name, num, reg) => { + write!(f, "`{}` (`{}` selects register number {})", reg, name, num) + } + InnerDescription::Boundary(desc) => { + write!(f, "{}", desc) + } + } } - InnerDescription::Boundary(desc) => { - write!(f, "{}", desc) + } + } else { + impl fmt::Display for InnerDescription { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("non-fmt build") } } } |