Crate yaxpeax_x86[][src]

Expand description

yaxpeax-x86, a decoder for x86-family instruction sets

yaxpeax-x86 provides x86 decoders, for 64-, 32-, and 16-bit modes. yaxpeax-x86 also implements traits defined by yaxpeax_arch, making it suitable for interchangeable use with other yaxpeax-family instruction decoders.

usage

the fastest way to decode an x86 instruction is through amd64::InstDecoder::decode_slice():

let decoder = yaxpeax_x86::amd64::InstDecoder::default();

let inst = decoder.decode_slice(&[0x33, 0xc0]).unwrap();

assert_eq!("xor eax, eax", inst.to_string());

instructions, operands, registers, and generally all decoding structures, are in their mode’s repsective submodule:

all modes have equivalent data available in a decoded instruction. for example, all modes have library-friendly Operand and RegSpec types:

use yaxpeax_x86::amd64::{InstDecoder, Operand, RegSpec};

let decoder = yaxpeax_x86::amd64::InstDecoder::default();

let inst = decoder.decode_slice(&[0x33, 0x01]).unwrap();

assert_eq!("xor eax, dword [rcx]", inst.to_string());

assert_eq!(Operand::Register(RegSpec::eax()), inst.operand(0));
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
assert_eq!("[rcx]", inst.operand(1).to_string());

// and for memory operands, the size must be read from the instruction itself:
let mem_size: yaxpeax_x86::amd64::MemoryAccessSize = inst.mem_size().unwrap();
assert_eq!("dword", mem_size.size_name());

// `MemoryAccessSize::size_name()` is how its `Display` impl works, as well:
assert_eq!("dword", mem_size.to_string());

yaxpeax-x86 can also be used to decode instructions generically through the yaxpeax-arch traits:

mod decoder {
    use yaxpeax_arch::{Arch, AddressDisplay, Decoder, Reader, ReaderBuilder};

    pub fn decode_stream<
        'data,
        A: yaxpeax_arch::Arch,
        U: ReaderBuilder<A::Address, A::Word>,
    >(data: U) where
        A::Instruction: std::fmt::Display,
    {
        let mut reader = ReaderBuilder::read_from(data);
        let mut address: A::Address = reader.total_offset();

        let decoder = A::Decoder::default();
        let mut decode_res = decoder.decode(&mut reader);
        loop {
            match decode_res {
                Ok(ref inst) => {
                    println!("{}: {}", address.show(), inst);
                    decode_res = decoder.decode(&mut reader);
                    address = reader.total_offset();
                }
                Err(e) => {
                    println!("{}: decode error: {}", address.show(), e);
                    break;
                }
            }
        }
    }
}

use yaxpeax_x86::amd64::{Arch as x86_64};
use yaxpeax_arch::{ReaderBuilder, U8Reader};
let data: &[u8] = &[0x55, 0x33, 0xc0, 0x48, 0x8b, 0x02, 0x5d, 0xc3];
decoder::decode_stream::<x86_64, _>(data);

#![no_std]

yaxpeax-x86 supports no_std usage. to be built no_std, yaxpeax-x86 only needs default-features = false in the corresponding Cargo.toml dependency. if formatting is needed with std disabled, it can be re-enabled by explicitly requesting the fmt features like:

yaxpeax-x86 = { version = "*", default-features = false, features = ["fmt"] }

this is how the .so and .a packaging in ffi/ is performed.

Re-exports

pub use long_mode as amd64;
pub use long_mode::Arch as x86_64;
pub use protected_mode::Arch as x86_32;
pub use real_mode::Arch as x86_16;

Modules

Structs