Skip to content

Commit

Permalink
simplify some type signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
lenawanel committed Sep 8, 2023
1 parent dce1178 commit 9237902
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 38 deletions.
67 changes: 36 additions & 31 deletions src/emu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,7 @@ impl Emu {
}
OpKind::Memory => {
let address: usize = self.calc_addr(instruction);
Ok(self
.memory
.read_primitive(Virtaddr(address))
.map(T::from_ne_bytes)?)
Ok(self.memory.read_primitive(Virtaddr(address))?)
}
x => todo!("{x:?}"),
}
Expand All @@ -196,9 +193,9 @@ impl Emu {
let mut depth = 0;
'recursive_memory_lookup: while let Ok(new_val) = self
.memory
.read_primitive::<BYTES>(Virtaddr(usize::try_from(val).unwrap()))
.read_primitive(Virtaddr(usize::try_from(val).unwrap()))
{
val = T::from_ne_bytes(new_val);
val = new_val;
let val_addr = usize::try_from(val).unwrap();
print!("\x1b[0m -> ");

Expand Down Expand Up @@ -268,7 +265,7 @@ impl Emu {
self.memory.read_to(
// we currently only support running this on x86 hosts
// so it is fine to assume that a usize has size 8 bytes here
Virtaddr(self.get_reg::<usize, 8>(Register::RIP)),
Virtaddr(self.get_reg(Register::RIP)),
&mut inst_buf,
)?;
unsafe { IP = self.get_reg(Register::RIP) };
Expand All @@ -293,15 +290,15 @@ impl Emu {
}
macro_rules! push {
($expr:expr) => {
let sp = self.get_reg::<u64, 8>(Register::RSP) as usize
let sp = self.get_reg::<usize, 8>(Register::RSP)
- core::mem::size_of_val(&$expr) as usize;
self.memory.write_primitive(Virtaddr(sp), $expr)?;
self.set_reg(sp, Register::RSP);
};
}
macro_rules! pop {
($exp:expr) => {{
let sp = self.get_reg::<u64, 8>(Register::RSP) as usize;
let sp: usize = self.get_reg::<usize, 8>(Register::RSP);
self.set_reg(sp + $exp as usize, Register::RSP);
self.memory.read_primitive(Virtaddr(sp))?
}};
Expand Down Expand Up @@ -433,7 +430,7 @@ impl Emu {
})?
};
}
self.set_reg::<u8, 1>(
self.set_reg(
overflowing as u8 | self.get_reg::<u8, 1>(Register::RFLAGS),
Register::RFLAGS,
);
Expand All @@ -453,7 +450,7 @@ impl Emu {
};
}

self.set_reg::<u8, 1>(
self.set_reg(
overflowing as u8 | self.get_reg::<u8, 1>(Register::RFLAGS),
Register::RFLAGS,
);
Expand Down Expand Up @@ -601,28 +598,28 @@ impl Emu {
}
Mnemonic::Not => {
macro_rules! sized_not {
($typ:ty,$size:literal) => {{
($typ:ty) => {{
let val: $typ = self.get_val(instruction, 0)?;
self.set_val::<$typ, $size>(instruction, 0, !val)?;
self.set_val(instruction, 0, !val)?;
}};
}

match_bitness_ts!(sized_not)
match_bitness_typ!(sized_not)
}
Mnemonic::Neg => {
macro_rules! sized_neg {
($typ:ty,$size:literal) => {{
($typ:ty) => {{
let val: $typ = self.get_val(instruction, 0)?;
self.set_val::<$typ, $size>(instruction, 0, -val)?;
self.set_val(instruction, 0, -val)?;
}};
}

match bitness(instruction) {
Bitness::Eight => sized_neg!(i8, 1),
Bitness::Sixteen => sized_neg!(i16, 2),
Bitness::ThirtyTwo => sized_neg!(i32, 4),
Bitness::SixtyFour => sized_neg!(i64, 8),
Bitness::HundredTwentyEigth => sized_neg!(i128, 16),
Bitness::Eight => sized_neg!(i8),
Bitness::Sixteen => sized_neg!(i16),
Bitness::ThirtyTwo => sized_neg!(i32),
Bitness::SixtyFour => sized_neg!(i64),
Bitness::HundredTwentyEigth => sized_neg!(i128),
}
}
Mnemonic::Or => {
Expand Down Expand Up @@ -675,7 +672,7 @@ impl Emu {
}
Mnemonic::Ret => {
// get the new ip
let new_ip: u64 = u64::from_ne_bytes(pop!(8));
let new_ip: u64 = pop!(8);
#[cfg(debug_assertions)]
{
// println!("{:\t<1$}ret to: {new_ip:#x}", "", call_depth);
Expand Down Expand Up @@ -791,14 +788,14 @@ impl Emu {
+----------------------+
*/
Mnemonic::Cmovne => {
cc! {ne, {
cc! {ne,
match_bitness_typ!(sized_mov)
}}
}
}
Mnemonic::Cmove => {
cc! {e, {
cc! {e,
match_bitness_typ!(sized_mov)
}}
}
}
Mnemonic::Cmova => {
cc! {a,
Expand All @@ -816,9 +813,9 @@ impl Emu {
}
}
Mnemonic::Cmovb => {
cc! {b, {
cc! {b,
match_bitness_typ!(sized_mov)
}}
}
}
Mnemonic::Mov => {
// mov, as documented by https://www.felixcloutier.com/x86/mov
Expand Down Expand Up @@ -852,7 +849,7 @@ impl Emu {
Mnemonic::Pop => {
macro_rules! pop_sized {
($typ:ty, $size:literal) => {{
let val = <$typ>::from_ne_bytes(pop!($size));
let val: $typ = pop!($size);
self.set_val(instruction, 0, val)?;
}};
}
Expand Down Expand Up @@ -1178,7 +1175,9 @@ impl Emu {
// get the displacement first, since any memory acces will have one (even if it's 0)
let mut addr = mem.memory_displacement64() as usize;
// check if there is a memory indexing register like in
// ```x86asm
// call QWORD PTR [r12+r14*8]
// ```
// if that is the case, then multiply the value stored in the register (r14 in the above)
// with its scale (8 in the above case)
// and add the resulting value to the displacement
Expand All @@ -1190,7 +1189,9 @@ impl Emu {
// check if we are indexin a segment register
// if so, add it to the addres
// example:
// ```x86asm
// mov rbx,QWORD PTR fs:0x10
// ```
// here fs is the segment register
if let Some(seg_reg) = seg_from_iced_seg(mem.memory_segment()) {
addr = addr.wrapping_add(self.get_seg(seg_reg) as usize);
Expand All @@ -1199,11 +1200,15 @@ impl Emu {
// check if there is a base register indexing the memory
// if that is the case, add the value stored in the register to the current address
// example:
// ```x86asm
// call QWORD PTR [r12+r14*8]
// ```
// here r12 is the base register
if let Some(base_reg) = reg_from_iced_reg(mem.memory_base()) {
// this can be wrapping, for example you can have
// ```x86asm
// cmp QWORD PTR [rdi-0x8],0x0
// ```
// substracting some displacement (i.e. doing a wrapping add (I could be wrong here))
addr = addr.wrapping_add(self.get_reg::<usize, 8>(base_reg));
}
Expand Down Expand Up @@ -1251,9 +1256,9 @@ impl Emu {
let mut depth = 0;
while let Ok(new_val) = self
.memory
.read_primitive::<8>(Virtaddr(usize::try_from(val).unwrap()))
.read_primitive(Virtaddr(usize::try_from(val).unwrap()))
{
val = u64::from_ne_bytes(new_val);
val = new_val;
print!("\x1b[0m -> \x1b[;96m{val:#x?}");
depth += 1;
if depth > 5 {
Expand Down
17 changes: 10 additions & 7 deletions src/mmu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::path::Path;

use elf::{endian::AnyEndian, ElfBytes};

use crate::symbol_table::SymbolTable;
use crate::{primitive::Primitive, symbol_table::SymbolTable};

pub struct MMU {
memory: Vec<u8>,
Expand Down Expand Up @@ -197,7 +197,11 @@ impl MMU {
}

/// write a primitive type to memory
pub fn write_primitive<T: Copy>(&mut self, addr: Virtaddr, value: T) -> Result<()> {
pub fn write_primitive<T: Primitive<BYTES>, const BYTES: usize>(
&mut self,
addr: Virtaddr,
value: T,
) -> Result<()> {
// check if we are not writing past the memory buffer
if addr.0 + std::mem::size_of::<T>() > self.memory.len() {
return Err(AccessError::AddrOOB);
Expand All @@ -215,9 +219,8 @@ impl MMU {
// the pointer casting here is needed,
// since rust places an restriction of using `std::mem::sizeof::<T>()`
// in the construction of arrays
self.memory[addr.0..addr.0 + std::mem::size_of::<T>()].copy_from_slice(unsafe {
core::slice::from_raw_parts(&value as *const T as *const u8, core::mem::size_of::<T>())
});
self.memory[addr.0..addr.0 + std::mem::size_of::<T>()]
.copy_from_slice(&value.to_ne_bytes());
// self.memory[addr.0..addr.0 + std::mem::size_of::<T>()]
// .copy_from_slice(&value.to_ne_bytes());

Expand Down Expand Up @@ -267,7 +270,7 @@ impl MMU {
}
/// this function reads primitives as [u8; N],
/// this is to circumvent the restriction of using generic const expressions
pub fn read_primitive<const N: usize>(&self, addr: Virtaddr) -> Result<[u8; N]> {
pub fn read_primitive<const N: usize, T: Primitive<N>>(&self, addr: Virtaddr) -> Result<T> {
// check if we are not writing past the memory buffer
let Some(last_addr) = addr.0.checked_add(N) else {
return Err(AccessError::AddrOverflow);
Expand All @@ -287,7 +290,7 @@ impl MMU {
// copy the requested memory
let mut buf = [0u8; N];
buf.copy_from_slice(&self.memory[addr.0..last_addr]);
Ok(buf)
Ok(T::from_ne_bytes(buf))
}

/// get acces to a mutable slice of memory
Expand Down
10 changes: 10 additions & 0 deletions src/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub trait Primitive<const SIZE: usize>:
fn to_u64(self) -> u64;

fn from_ne_bytes(bytes: [u8; SIZE]) -> Self;

fn to_ne_bytes(self) -> [u8; SIZE];
}

macro_rules! impl_primitive {
Expand All @@ -29,12 +31,20 @@ macro_rules! impl_primitive {
fn to_u64(self) -> u64 {
self as u64
}

#[inline(always)]
fn from_ne_bytes(bytes: [u8; $bytes]) -> Self {
// assert!(size == $bytes);
// let bytes = unsafe { core::mem::transmute::<[u8; size], [u8; $bytes]>(bytes) };
Self::from_ne_bytes(bytes)
}

#[inline(always)]
fn to_ne_bytes(self) -> [u8; $bytes] {
// assert!(size == $bytes);
// let bytes = unsafe { core::mem::transmute::<[u8; size], [u8; $bytes]>(bytes) };
<$type>::to_ne_bytes(self)
}
}
};
}
Expand Down

0 comments on commit 9237902

Please sign in to comment.