dobby-hook-core 0.1.4

Dobby-like low-level inline hook core in Rust
Documentation
use crate::engine::backend;
use crate::error::{Error, Result};
use once_cell::sync::OnceCell;
use std::collections::HashMap;
use std::ffi::c_void;
use std::sync::Mutex;

#[derive(Debug)]
struct HookInfo {
    original: Vec<u8>,
    patch_len: usize,
    trampoline: usize,
    trampoline_size: usize,
}

static HOOKS: OnceCell<Mutex<HashMap<usize, HookInfo>>> = OnceCell::new();
fn hooks() -> &'static Mutex<HashMap<usize, HookInfo>> {
    HOOKS.get_or_init(|| Mutex::new(HashMap::new()))
}

pub(crate) unsafe fn hook(address: *mut c_void, fake_func: *mut c_void) -> Result<*mut c_void> {
    let key = address as usize;
    if hooks().lock().unwrap().contains_key(&key) {
        return Err(Error::AlreadyHooked);
    }
    let build = backend::get().hook_build(address, fake_func)?;
    hooks().lock().unwrap().insert(
        key,
        HookInfo {
            original: build.original,
            patch_len: build.patch_len,
            trampoline: build.trampoline as usize,
            trampoline_size: build.trampoline_size,
        },
    );
    Ok(build.trampoline)
}

pub(crate) unsafe fn destroy(address: *mut c_void) -> Result<()> {
    let key = address as usize;
    let info = hooks()
        .lock()
        .unwrap()
        .remove(&key)
        .ok_or(Error::HookNotFound)?;
    backend::get().hook_destroy(
        address,
        &info.original,
        info.patch_len,
        info.trampoline as *mut c_void,
        info.trampoline_size,
    )
}