use super::*;
#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
#[repr(C)]
#[derive(Clone, Debug)]
pub struct Decoder {
machine_mode: MachineMode,
stack_width: StackWidth,
decoder_mode: u32,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub enum DecodedOperandKind {
Unused,
Reg(Register),
Mem(MemoryInfo),
Ptr(PointerInfo),
Imm(ImmediateInfo),
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct DecodedOperand {
pub id: u8,
pub visibility: OperandVisibility,
pub action: OperandAction,
pub encoding: OperandEncoding,
pub size: u16,
pub element_type: ElementType,
pub element_size: u16,
pub element_count: u16,
pub attributes: OperandAttributes,
pub kind: DecodedOperandKind,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct MemoryInfo {
pub ty: MemoryOperandType,
pub segment: Register,
pub base: Register,
pub index: Register,
pub scale: u8,
pub disp: DisplacementInfo,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct DisplacementInfo {
pub has_displacement: bool,
pub displacement: i64,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct PointerInfo {
pub segment: u16,
pub offset: u32,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct ImmediateInfo {
pub is_signed: bool,
pub is_relative: bool,
pub value: u64,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct AccessedFlags<FlagType> {
pub tested: FlagType,
pub modified: FlagType,
pub set_0: FlagType,
pub set_1: FlagType,
pub undefined: FlagType,
}
#[cfg_attr(feature = "serialization", derive(Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct DecodedInstruction {
pub machine_mode: MachineMode,
pub mnemonic: Mnemonic,
pub length: u8,
pub encoding: InstructionEncoding,
pub opcode_map: OpcodeMap,
pub opcode: u8,
pub stack_width: u8,
pub operand_width: u8,
pub address_width: u8,
pub operand_count: u8,
pub operand_count_visible: u8,
pub attributes: InstructionAttributes,
pub cpu_flags: &'static AccessedFlags<CpuFlag>,
pub fpu_flags: &'static AccessedFlags<FpuFlag>,
pub avx: AvxInfo,
pub meta: MetaInfo,
pub raw: RawInfo,
}
impl DecodedInstruction {
#[inline]
pub fn calc_absolute_address(&self, address: u64, operand: &DecodedOperand) -> Result<u64> {
unsafe {
let mut addr = 0u64;
ZydisCalcAbsoluteAddress(self, operand, address, &mut addr).as_result()?;
Ok(addr)
}
}
#[inline]
pub fn calc_absolute_address_ex(
&self,
address: u64,
operand: &DecodedOperand,
context: &RegisterContext,
) -> Result<u64> {
unsafe {
let mut addr = 0u64;
ZydisCalcAbsoluteAddressEx(self, operand, address, context, &mut addr).as_result()?;
Ok(addr)
}
}
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct AvxInfo {
pub vector_length: u16,
pub mask_mode: MaskMode,
pub mask_reg: Register,
pub broadcast_static: bool,
pub broadcast_mode: BroadcastMode,
pub rounding_mode: RoundingMode,
pub swizzle_mode: SwizzleMode,
pub conversion_mode: ConversionMode,
pub has_sae: bool,
pub has_eviction_hint: bool,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct MetaInfo {
pub category: InstructionCategory,
pub isa_set: ISASet,
pub isa_ext: ISAExt,
pub branch_type: BranchType,
pub exception_class: ExceptionClass,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct RawInfoRex {
pub W: u8,
pub R: u8,
pub X: u8,
pub B: u8,
pub rex_offset: u8,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct RawInfoXop {
pub aR: u8,
pub X: u8,
pub B: u8,
pub m_mmmm: u8,
pub W: u8,
pub vvvv: u8,
pub L: u8,
pub pp: u8,
pub offset: u8,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct RawInfoVex {
pub R: u8,
pub X: u8,
pub B: u8,
pub mmmm: u8,
pub W: u8,
pub vvvv: u8,
pub L: u8,
pub pp: u8,
pub offset: u8,
pub size: u8,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct RawInfoEvex {
pub R: u8,
pub X: u8,
pub B: u8,
pub R2: u8,
pub mm: u8,
pub W: u8,
pub vvvv: u8,
pub pp: u8,
pub z: u8,
pub L2: u8,
pub L: u8,
pub b: u8,
pub V2: u8,
pub aaa: u8,
pub offset: u8,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct RawInfoMvex {
pub R: u8,
pub X: u8,
pub B: u8,
pub R2: u8,
pub mmmm: u8,
pub W: u8,
pub vvvv: u8,
pub pp: u8,
pub E: u8,
pub SSS: u8,
pub V2: u8,
pub kkk: u8,
pub offset: u8,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct RawInfoModRm {
pub mod_: u8,
pub reg: u8,
pub rm: u8,
pub offset: u8,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct RawInfoSib {
pub scale: u8,
pub index: u8,
pub base: u8,
pub offset: u8,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct RawInfoDisp {
pub value: i64,
pub size: u8,
pub offset: u8,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub enum RawInfoKindSpecific {
Legacy(RawInfoRex),
_3DNOW,
Xop(RawInfoXop),
Vex(RawInfoVex),
Evex(RawInfoEvex),
Mvex(RawInfoMvex),
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct RawInfo {
pub prefix_count: u8,
pub prefixes: [Prefix; MAX_INSTRUCTION_LENGTH],
pub kind_specific: RawInfoKindSpecific,
pub modrm: RawInfoModRm,
pub sib: RawInfoSib,
pub disp: RawInfoDisp,
pub imm: [RawImmediateInfo; 2],
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct RawImmediateInfo {
pub is_signed: bool,
pub is_relative: bool,
pub value: u64,
pub size: u8,
pub offset: u8,
}
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct Prefix {
pub ty: PrefixType,
pub value: u8,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
#[allow(non_snake_case)]
pub struct ContextVectorUnified {
pub W: u8,
pub R: u8,
pub X: u8,
pub B: u8,
pub L: u8,
pub LL: u8,
pub R2: u8,
pub V2: u8,
pub vvvv: u8,
pub mask: u8,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct ContextRegInfo {
pub is_mod_reg: bool,
pub id_reg: u8,
pub id_rm: u8,
pub id_ndsndd: u8,
pub id_base: u8,
pub id_index: u8,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct ContextEvex {
ty: u8,
element_size: u8,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct ContextMvex {
functionality: u8,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct ContextDefinition(u8 );
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct DecoderContext {
definition: *const ContextDefinition,
eosz_index: u8,
easz_index: u8,
vector_unified: ContextVectorUnified,
reg_info: ContextRegInfo,
evex: ContextEvex,
mvex: ContextMvex,
cd8_scal: u8,
}
extern "C" {
pub fn ZydisDecoderInit(
decoder: *mut Decoder,
machine_mode: MachineMode,
stack_width: StackWidth,
) -> Status;
pub fn ZydisDecoderEnableMode(
decoder: *mut Decoder,
mode: DecoderMode,
enabled: bool,
) -> Status;
pub fn ZydisDecoderDecodeFull(
decoder: *const Decoder,
buffer: *const c_void,
length: usize,
instruction: *mut DecodedInstruction,
operands: *mut [DecodedOperand; MAX_OPERAND_COUNT],
) -> Status;
pub fn ZydisDecoderDecodeInstruction(
decoder: *const Decoder,
context: *mut DecoderContext,
buffer: *const c_void,
length: usize,
instruction: *mut DecodedInstruction,
) -> Status;
pub fn ZydisDecoderDecodeOperands(
decoder: *const Decoder,
context: *const DecoderContext,
instruction: *const DecodedInstruction,
operands: *mut DecodedOperand,
operand_count: u8,
) -> Status;
}