Skip to content

Commit

Permalink
Merge pull request #71 from Jujstme/unity_il2cpp
Browse files Browse the repository at this point in the history
[Unity] Various edits in the Unity code
  • Loading branch information
CryZe authored Jan 28, 2024
2 parents e826a95 + f256b2e commit 41a371a
Show file tree
Hide file tree
Showing 14 changed files with 1,001 additions and 711 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ time = { version = "0.3.5", default-features = false }

[target.'cfg(target_os = "wasi")'.dependencies]
libm = { version = "0.2.7", optional = true }
wasi = { version = "0.11.0", default-features = false }
wasi = { version = "0.11.0+wasi-snapshot-preview1", default-features = false }

[features]
alloc = []
Expand Down
69 changes: 35 additions & 34 deletions src/deep_pointer.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
//! Support for storing pointer paths for easy dereferencing inside the autosplitter logic.

use arrayvec::ArrayVec;
use core::array;

use bytemuck::CheckedBitPattern;

use crate::{Address, Address32, Address64, Error, Process};
use crate::{Address, Error, PointerSize, Process};

/// An abstraction of a pointer path, usable for easy dereferencing inside an autosplitter logic.
///
/// The maximum depth of the pointer path is given by the generic parameter `CAP`.
/// Of note, `CAP` must be higher or equal to the number of offsets provided in `path`,
/// otherwise calling `new()` on this struct will trigger a ***Panic***.
#[derive(Clone)]
///
/// `CAP` should be higher or equal to the number of offsets provided in `path`.
/// If a higher number of offsets is provided, the pointer path will be truncated
/// according to the value of `CAP`.
#[derive(Copy, Clone)]
pub struct DeepPointer<const CAP: usize> {
base_address: Address,
path: ArrayVec<u64, CAP>,
deref_type: DerefType,
path: [u64; CAP],
depth: usize,
pointer_size: PointerSize,
}

impl<const CAP: usize> Default for DeepPointer<CAP> {
Expand All @@ -23,59 +27,56 @@ impl<const CAP: usize> Default for DeepPointer<CAP> {
fn default() -> Self {
Self {
base_address: Address::default(),
path: ArrayVec::default(),
deref_type: DerefType::default(),
path: [u64::default(); CAP],
depth: usize::default(),
pointer_size: PointerSize::Bit64,
}
}
}

impl<const CAP: usize> DeepPointer<CAP> {
/// Creates a new DeepPointer and specify the pointer size dereferencing
#[inline]
pub fn new(base_address: Address, deref_type: DerefType, path: &[u64]) -> Self {
assert!(CAP != 0 && CAP >= path.len());
pub fn new(base_address: impl Into<Address>, pointer_size: PointerSize, path: &[u64]) -> Self {
let this_path = {
let mut iter = path.iter();
array::from_fn(|_| iter.next().copied().unwrap_or_default())
};

Self {
base_address,
path: path.iter().cloned().collect(),
deref_type,
base_address: base_address.into(),
path: this_path,
depth: path.len().min(CAP),
pointer_size,
}
}

/// Creates a new DeepPointer with 32bit pointer size dereferencing
pub fn new_32bit(base_address: Address, path: &[u64]) -> Self {
Self::new(base_address, DerefType::Bit32, path)
pub fn new_32bit(base_address: impl Into<Address>, path: &[u64]) -> Self {
Self::new(base_address, PointerSize::Bit32, path)
}

/// Creates a new DeepPointer with 64bit pointer size dereferencing
pub fn new_64bit(base_address: Address, path: &[u64]) -> Self {
Self::new(base_address, DerefType::Bit64, path)
pub fn new_64bit(base_address: impl Into<Address>, path: &[u64]) -> Self {
Self::new(base_address, PointerSize::Bit64, path)
}

/// Dereferences the pointer path, returning the memory address of the value of interest
pub fn deref_offsets(&self, process: &Process) -> Result<Address, Error> {
let mut address = self.base_address;
let (&last, path) = self.path.split_last().ok_or(Error {})?;
let (&last, path) = self.path[..self.depth].split_last().ok_or(Error {})?;
for &offset in path {
address = match self.deref_type {
DerefType::Bit32 => process.read::<Address32>(address + offset)?.into(),
DerefType::Bit64 => process.read::<Address64>(address + offset)?.into(),
};
address = process.read_pointer(address + offset, self.pointer_size)?;
}
Ok(address + last)
}

/// Dereferences the pointer path, returning the value stored at the final memory address
pub fn deref<T: CheckedBitPattern>(&self, process: &Process) -> Result<T, Error> {
process.read(self.deref_offsets(process)?)
process.read_pointer_path(
self.base_address,
self.pointer_size,
&self.path[..self.depth],
)
}
}

/// Describes the pointer size that should be used while deferecencing a pointer path
#[derive(Copy, Clone, Default)]
pub enum DerefType {
/// 4-byte pointer size, used in 32bit processes
Bit32,
/// 8-byte pointer size, used in 64bit processes
#[default]
Bit64,
}
9 changes: 2 additions & 7 deletions src/emulator/gba/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,8 @@ impl Emulator {

self.state.set(state);

if success {
self.ram_base.set(ram_base);
true
} else {
self.ram_base.set(None);
false
}
self.ram_base.set(if success { ram_base } else { None });
success
}

/// Reads any value from the emulated RAM.
Expand Down
13 changes: 10 additions & 3 deletions src/emulator/sms/retroarch.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::{file_format::pe, signature::Signature, Address, Address32, Address64, Process};
use crate::{
file_format::pe, signature::Signature, Address, Address32, Address64, PointerSize, Process,
};

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct State {
Expand Down Expand Up @@ -94,8 +96,9 @@ impl State {
.read::<u8>(ptr + 13 + 0x4 + game.read::<i32>(ptr + 13).ok()? + 3)
.ok()?;
let addr = game
.read_pointer_path64::<Address64>(
.read_pointer_path::<Address64>(
ptr + 0x4 + game.read::<i32>(ptr).ok()?,
PointerSize::Bit64,
&[0x0, 0x0, offset as _],
)
.ok()?;
Expand All @@ -111,7 +114,11 @@ impl State {
.read::<u8>(ptr + 12 + 0x4 + game.read::<i32>(ptr + 12).ok()? + 2)
.ok()?;
let addr = game
.read_pointer_path32::<Address32>(ptr, &[0x0, 0x0, 0x0, offset as _])
.read_pointer_path::<Address32>(
ptr,
PointerSize::Bit32,
&[0x0, 0x0, 0x0, offset as _],
)
.ok()?;
if addr.is_null() {
return None;
Expand Down
11 changes: 10 additions & 1 deletion src/file_format/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use core::{

use bytemuck::{Pod, Zeroable};

use crate::{string::ArrayCString, Address, Endian, Error, FromEndian, Process};
use crate::{string::ArrayCString, Address, Endian, Error, FromEndian, PointerSize, Process};

// Based on:
// https://refspecs.linuxfoundation.org/elf/elf.pdf
Expand Down Expand Up @@ -99,6 +99,15 @@ impl Bitness {
pub fn is_64(self) -> bool {
self == Self::BITNESS_64
}

/// Returns the pointer size for the given bitness.
pub const fn pointer_size(self) -> Option<PointerSize> {
Some(match self {
Self::BITNESS_64 => PointerSize::Bit64,
Self::BITNESS_32 => PointerSize::Bit32,
_ => return None,
})
}
}

/// Segment type identifier for the ELF program header
Expand Down
12 changes: 11 additions & 1 deletion src/file_format/pe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::{fmt, mem};

use bytemuck::{Pod, Zeroable};

use crate::{string::ArrayCString, Address, Error, FromEndian, Process};
use crate::{string::ArrayCString, Address, Error, FromEndian, PointerSize, Process};

// Reference:
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
Expand Down Expand Up @@ -236,6 +236,16 @@ impl MachineType {
pub const THUMB: Self = Self(0x1c2);
/// MIPS little-endian WCE v2
pub const WCEMIPSV2: Self = Self(0x169);

/// Returns the pointer size for the given machine type. Only the most
/// common machine types are supported.
pub const fn pointer_size(self) -> Option<PointerSize> {
Some(match self {
Self::AMD64 | Self::ARM64 | Self::IA64 => PointerSize::Bit64,
Self::I386 | Self::ARM => PointerSize::Bit32,
_ => return None,
})
}
}

/// Reads the size of the image of a module (`exe` or `dll`) from the given
Expand Down
12 changes: 8 additions & 4 deletions src/future/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,19 @@ pub struct UntilProcessCloses<'a, F> {
future: F,
}

impl<F: Future<Output = ()>> Future for UntilProcessCloses<'_, F> {
type Output = ();
impl<T, F: Future<Output = T>> Future for UntilProcessCloses<'_, F> {
type Output = Option<T>;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if !self.process.is_open() {
return Poll::Ready(());
return Poll::Ready(None);
}
// SAFETY: We are simply projecting the Pin.
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().future).poll(cx) }
unsafe {
Pin::new_unchecked(&mut self.get_unchecked_mut().future)
.poll(cx)
.map(Some)
}
}
}

Expand Down
Loading

0 comments on commit 41a371a

Please sign in to comment.