Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
athre0z committed Oct 24, 2023
1 parent 4f874bb commit 4b6e4a8
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 6 deletions.
78 changes: 78 additions & 0 deletions src/encoder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::ops::{Deref, DerefMut};
use crate::{ffi, *};
use crate::ffi::ZydisEncoderEncodeInstruction;

#[repr(transparent)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct EncoderRequest(ffi::EncoderRequest);

impl Deref for EncoderRequest {
type Target = ffi::EncoderRequest;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for EncoderRequest {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl EncoderRequest {
pub fn new32(mnemonic: Mnemonic) -> Self {
Self::new(MachineMode::LONG_COMPAT_32, mnemonic)
}

pub fn new64(mnemonic: Mnemonic) -> Self {
Self::new(MachineMode::LONG_64, mnemonic)
}

/// Create a new encoder request from scratch.
pub fn new(machine_mode: MachineMode, mnemonic: Mnemonic) -> Self {
let mut request: ffi::EncoderRequest = unsafe { core::mem::zeroed() };
request.machine_mode = machine_mode;
request.mnemonic = mnemonic;
Self(request)
}

pub fn encode_into(&self, buf: &mut [u8]) -> Result<usize> {
unsafe {
let mut length = buf.len();
ZydisEncoderEncodeInstruction(&self.0, buf.as_ptr() as _, &mut length).as_result()?;
Ok(length)
}
}

pub fn encode(&self) -> Result<Vec<u8>> {
let mut out = vec![0; MAX_INSTRUCTION_LENGTH];
let length = self.encode_into(&mut out[..])?;
out.resize(length, 0);
Ok(out)
}
}

#[cfg(test)]
mod tests {
use crate::ffi::EncoderOperand;
use super::*;

#[test]
fn encode_int3() {
let req = EncoderRequest::new64(Mnemonic::INT3);
let enc = req.encode().unwrap();
assert_eq!(enc, vec![0xCC]);
}

#[test]
fn encode_mov() {
let mut req = EncoderRequest::new64(Mnemonic::MOV);

req.operand_count = 2;
req.operands[0] = EncoderOperand::

let enc = req.encode().unwrap();
assert_eq!(enc, vec![0xCC]);
}
}
18 changes: 18 additions & 0 deletions src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ pub(crate) const MAX_INSTRUCTION_SEGMENT_COUNT: usize = 9;
/// Maximum number of encoder operands.
pub const ENCODER_MAX_OPERANDS: usize = 5;

/// Combination of all user-encodable prefixes.
pub const ENCODABLE_PREFIXES: u64 = InstructionAttributes::HAS_LOCK.bits()
| InstructionAttributes::HAS_REP.bits()
| InstructionAttributes::HAS_REPE.bits()
| InstructionAttributes::HAS_REPNE.bits()
| InstructionAttributes::HAS_BND.bits()
| InstructionAttributes::HAS_XACQUIRE.bits()
| InstructionAttributes::HAS_XRELEASE.bits()
| InstructionAttributes::HAS_BRANCH_NOT_TAKEN.bits()
| InstructionAttributes::HAS_BRANCH_TAKEN.bits()
| InstructionAttributes::HAS_NOTRACK.bits()
| InstructionAttributes::HAS_SEGMENT_CS.bits()
| InstructionAttributes::HAS_SEGMENT_SS.bits()
| InstructionAttributes::HAS_SEGMENT_DS.bits()
| InstructionAttributes::HAS_SEGMENT_ES.bits()
| InstructionAttributes::HAS_SEGMENT_FS.bits()
| InstructionAttributes::HAS_SEGMENT_GS.bits();

impl Mnemonic {
/// Returns the static string corresponding to this mnemonic.
///
Expand Down
12 changes: 6 additions & 6 deletions src/ffi/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub struct OperandPointer {
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct Operand {
pub struct EncoderOperand {
pub ty: OperandType,
pub reg: OperandRegister,
pub mem: OperandMemory,
Expand Down Expand Up @@ -68,7 +68,7 @@ pub struct MvexFeatures {
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(C)]
pub struct Request {
pub struct EncoderRequest {
pub machine_mode: MachineMode,
pub allowed_encodings: EncodableEncoding,
pub mnemonic: Mnemonic,
Expand All @@ -78,21 +78,21 @@ pub struct Request {
pub address_size_hint: AddressSizeHint,
pub operand_size_hint: OperandSizeHint,
pub operand_count: u8,
pub operands: [Operand; ENCODER_MAX_OPERANDS],
pub operands: [EncoderOperand; ENCODER_MAX_OPERANDS],
pub evex: EvexFeatures,
pub mvex: MvexFeatures,
}

extern "C" {
pub fn ZydisEncoderEncodeInstructionAbsolute(
request: *const Request,
request: *const EncoderRequest,
buffer: *mut c_void,
length: *mut usize,
runtime_address: u64,
) -> Status;

pub fn ZydisEncoderEncodeInstruction(
request: *const Request,
request: *const EncoderRequest,
buffer: *mut c_void,
length: *mut usize,
) -> Status;
Expand All @@ -101,7 +101,7 @@ extern "C" {
instruction: *const DecodedInstruction,
operands: *const DecodedOperand,
operand_count: u8,
request: *mut Request,
request: *mut EncoderRequest,
) -> Status;

pub fn ZydisEncoderNopFill(buffer: *mut c_void, length: usize) -> Status;
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#[macro_use]
mod status;
mod decoder;
#[cfg(feature = "encoder")]
mod encoder;
mod enums;
pub mod ffi;
#[cfg(feature = "formatter")]
Expand All @@ -14,6 +16,8 @@ pub use decoder::*;
pub use enums::*;
#[cfg(feature = "formatter")]
pub use formatter::*;
#[cfg(feature = "encoder")]
pub use encoder::*;
pub use status::*;

/// Returns the version of the zydis C library as a quadruple
Expand Down

0 comments on commit 4b6e4a8

Please sign in to comment.