Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

frida-gum: use a singleton gum instance #158

Merged
merged 1 commit into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frida-gum-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod bindings {
pub use bindings::*;

#[cfg(not(any(target_os = "windows", target_os = "android", target_vendor = "apple",)))]
pub use _frida_g_object_unref as g_object_unref;
pub use {_frida_g_object_ref as g_object_ref, _frida_g_object_unref as g_object_unref};

/// A single disassembled CPU instruction.
#[repr(transparent)]
Expand Down
4 changes: 4 additions & 0 deletions frida-gum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ num = { version = "0.4.1", default-features = false }
num-derive = { version = "0.4.2", default-features = false }
num-traits = { version = "0.2.18", default-features = false }
paste = { version = "1", default-features = false }
spin = { version = "0.9.8", default-features = false, features = [
"mutex",
"spin_mutex",
] }

[dev-dependencies]
lazy_static = "1"
Expand Down
27 changes: 19 additions & 8 deletions frida-gum/src/interceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//!
use {
crate::{Error, Gum, NativePointer, Result},
core::{marker::PhantomData, ptr},
core::ptr,
frida_gum_sys as gum_sys,
};

Expand All @@ -21,25 +21,36 @@ mod invocation_listener;
pub use invocation_listener::*;

/// Function hooking engine interface.
pub struct Interceptor<'a> {
pub struct Interceptor {
interceptor: *mut gum_sys::GumInterceptor,
phantom: PhantomData<&'a gum_sys::GumInterceptor>,
_gum: Gum,
}

impl Drop for Interceptor<'_> {
impl Clone for Interceptor {
fn clone(&self) -> Self {
Interceptor {
interceptor: unsafe {
frida_gum_sys::g_object_ref(self.interceptor as *mut _) as *mut _
},
_gum: self._gum.clone(),
}
}
}

impl Drop for Interceptor {
fn drop(&mut self) {
unsafe { frida_gum_sys::g_object_unref(self.interceptor as *mut _) }
}
}

impl<'a> Interceptor<'a> {
impl Interceptor {
/// Obtain an Interceptor handle, ensuring that the runtime is properly initialized. This may
/// be called as many times as needed, and results in a no-op if the Interceptor is
/// already initialized.
pub fn obtain<'b: 'a>(_gum: &'b Gum) -> Interceptor<'b> {
pub fn obtain(gum: &Gum) -> Interceptor {
Interceptor {
interceptor: unsafe { gum_sys::gum_interceptor_obtain() },
phantom: PhantomData,
_gum: gum.clone(),
}
}

Expand Down Expand Up @@ -221,7 +232,7 @@ impl<'a> Interceptor<'a> {
/// Should only be called from within a hook or replacement function.
#[cfg(feature = "invocation-listener")]
#[cfg_attr(docsrs, doc(cfg(feature = "invocation-listener")))]
pub fn current_invocation() -> InvocationContext<'a> {
pub fn current_invocation<'a>() -> InvocationContext<'a> {
InvocationContext::from_raw(unsafe { gum_sys::gum_interceptor_get_current_invocation() })
}

Expand Down
51 changes: 43 additions & 8 deletions frida-gum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ use core::{
};

#[cfg(not(feature = "std"))]
use alloc::string::String;
use alloc::{string::String, sync::Arc};

#[cfg(feature = "std")]
use std::sync::Arc;

pub mod stalker;

Expand Down Expand Up @@ -109,24 +112,56 @@ pub use backtracer::*;
pub type Result<T> = core::result::Result<T, error::Error>;

/// Context required for instantiation of all structures under the Gum namespace.
pub struct Gum;
#[derive(Clone)]
pub struct Gum {
inner: GumSingletonHandle,
}

impl Gum {
/// Obtain a Gum handle, ensuring that the runtime is properly initialized. This may
/// be called as many times as needed, and results in a no-op if the Gum runtime is
/// already initialized.
pub unsafe fn obtain() -> Gum {
frida_gum_sys::gum_init_embedded();
Gum {}
pub fn obtain() -> Self {
let mut singleton = GUM_SINGLETON.lock();
let handle = singleton.get_or_insert_with(|| Arc::new(GumSingleton::obtain()));
Self {
inner: Some(handle.clone()),
}
}
}

impl Drop for Gum {
fn drop(&mut self) {
let instance = self.inner.take().expect("instance taken more than once");
drop(instance);
// If there are no outstanding Gum instances, drop the singleton.
let mut singleton = GUM_SINGLETON.lock();
let Some(it) = singleton.take_if(|it| Arc::strong_count(it) == 1) else {
return;
};
Arc::try_unwrap(it)
.ok()
.expect("should destroy the one instance");
}
}

static GUM_SINGLETON: spin::Mutex<GumSingletonHandle> = spin::Mutex::new(None);

type GumSingletonHandle = Option<Arc<GumSingleton>>;

// A marker type that exists only while Gum is initialized.
struct GumSingleton;

impl Drop for GumSingleton {
fn drop(&mut self) {
unsafe { frida_gum_sys::gum_deinit_embedded() };
}
}

impl GumSingleton {
fn obtain() -> Self {
unsafe { frida_gum_sys::gum_init_embedded() };
Self
}
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct NativePointer(pub *mut c_void);
Expand Down
28 changes: 11 additions & 17 deletions frida-gum/src/stalker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

use {
crate::{Gum, MemoryRange, NativePointer},
core::{ffi::c_void, marker::PhantomData},
core::ffi::c_void,
frida_gum_sys as gum_sys,
};

Expand Down Expand Up @@ -88,12 +88,12 @@ mod observer;
pub use observer::*;

/// Code tracing engine interface.
pub struct Stalker<'a> {
pub struct Stalker {
stalker: *mut frida_gum_sys::GumStalker,
phantom: PhantomData<&'a frida_gum_sys::GumStalker>,
_gum: Gum,
}

impl<'a> Stalker<'a> {
impl Stalker {
/// Checks if the Stalker is supported on the current platform.
pub fn is_supported(_gum: &Gum) -> bool {
unsafe { frida_gum_sys::gum_stalker_is_supported() != 0 }
Expand All @@ -104,12 +104,12 @@ impl<'a> Stalker<'a> {
/// This call has the overhead of checking if the Stalker is
/// available on the current platform, as creating a Stalker on an
/// unsupported platform results in unwanted behaviour.
pub fn new<'b: 'a>(gum: &'b Gum) -> Stalker<'b> {
pub fn new(gum: &Gum) -> Stalker {
assert!(Self::is_supported(gum));

Stalker {
stalker: unsafe { frida_gum_sys::gum_stalker_new() },
phantom: PhantomData,
_gum: gum.clone(),
}
}

Expand All @@ -119,15 +119,12 @@ impl<'a> Stalker<'a> {
/// available on the current platform, as creating a Stalker on an
/// unsupported platform results in unwanted behaviour.
#[cfg(all(target_arch = "aarch64", feature = "stalker-params"))]
pub fn new_with_params<'b>(gum: &'b Gum, ic_entries: u32) -> Stalker
where
'b: 'a,
{
pub fn new_with_params(gum: &Gum, ic_entries: u32) -> Stalker {
assert!(Self::is_supported(gum));

Stalker {
stalker: unsafe { frida_gum_sys::gum_stalker_new_with_params(ic_entries) },
phantom: PhantomData,
_gum: gum.clone(),
}
}

Expand All @@ -137,17 +134,14 @@ impl<'a> Stalker<'a> {
/// available on the current platform, as creating a Stalker on an
/// unsupported platform results in unwanted behaviour.
#[cfg(all(target_arch = "x86_64", feature = "stalker-params"))]
pub fn new_with_params<'b>(gum: &'b Gum, ic_entries: u32, adjacent_blocks: u32) -> Stalker
where
'b: 'a,
{
pub fn new_with_params(gum: &Gum, ic_entries: u32, adjacent_blocks: u32) -> Stalker {
assert!(Self::is_supported(gum));

Stalker {
stalker: unsafe {
frida_gum_sys::gum_stalker_new_with_params(ic_entries, adjacent_blocks)
},
phantom: PhantomData,
_gum: gum.clone(),
}
}

Expand Down Expand Up @@ -303,7 +297,7 @@ impl<'a> Stalker<'a> {
}
}

impl<'a> Drop for Stalker<'a> {
impl Drop for Stalker {
fn drop(&mut self) {
unsafe { gum_sys::g_object_unref(self.stalker as *mut c_void) };
}
Expand Down
Loading