android_mem_kit/
il2cpp.rs

1use std::ffi::{CString, c_void};
2use std::sync::OnceLock;
3
4unsafe extern "C" {
5    fn bridge_xdl_open(filename: *const i8) -> *mut c_void;
6    fn bridge_xdl_sym(handle: *mut c_void, symbol: *const i8) -> *mut c_void;
7}
8
9// Wrapper agar pointer bisa Send/Sync
10struct Il2CppHandle(*mut c_void);
11unsafe impl Send for Il2CppHandle {}
12unsafe impl Sync for Il2CppHandle {}
13
14static IL2CPP_HANDLE: OnceLock<Il2CppHandle> = OnceLock::new();
15
16fn get_handle() -> Option<*mut c_void> {
17    // get_or_init mengembalikan referensi ke Il2CppHandle
18    let handle_wrapper = IL2CPP_HANDLE.get_or_init(|| {
19        unsafe {
20            let name = CString::new("libil2cpp.so").unwrap();
21            let handle = bridge_xdl_open(name.as_ptr() as *const i8);
22            
23            // simpan null tidak apa-apa di dalam wrapper
24            if handle.is_null() {
25                Il2CppHandle(std::ptr::null_mut())
26            } else {
27                Il2CppHandle(handle)
28            }
29        }
30    });
31
32    // Ambil nilai pointer dari wrapper
33    let ptr = handle_wrapper.0;
34    if ptr.is_null() {
35        None
36    } else {
37        Some(ptr)
38    }
39}
40
41pub fn resolve_export(symbol_name: &str) -> Option<usize> {
42    let handle = get_handle()?; // Jika None langsung return
43    
44    let c_sym = CString::new(symbol_name).ok()?;
45    unsafe {
46        let addr = bridge_xdl_sym(handle, c_sym.as_ptr() as *const i8);
47        if addr.is_null() {
48            None
49        } else {
50            Some(addr as usize)
51        }
52    }
53}
54
55#[macro_export]
56macro_rules! il2cpp_call {
57    ($func_name:expr, $ret:ty, $($arg:expr),*) => {
58        {
59            static CACHED_ADDR: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
60            let mut addr = CACHED_ADDR.load(std::sync::atomic::Ordering::Relaxed);
61            
62            if addr == 0 {
63                if let Some(a) = $crate::il2cpp::resolve_export($func_name) {
64                    addr = a;
65                    CACHED_ADDR.store(addr, std::sync::atomic::Ordering::Relaxed);
66                }
67            }
68            
69            if addr != 0 {
70                let func: extern "C" fn($($arg),*) -> $ret = std::mem::transmute(addr);
71                Some(func($($arg),*))
72            } else {
73                None
74            }
75        }
76    };
77}