From df210a88a18d6cf432e823d542e6ae094bca9ae6 Mon Sep 17 00:00:00 2001 From: oiupoyt Date: Tue, 29 Sep 2026 17:06:18 +0530 Subject: [PATCH] feat(core): implement failing stub trampoline and host dlsym resolver --- crates/molotov-core/src/lib.rs | 1 + crates/molotov-core/src/trampoline.rs | 21 ++++++++++++++++++++ crates/molotov-core/tests/trampoline_test.rs | 17 ++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 crates/molotov-core/src/trampoline.rs create mode 100644 crates/molotov-core/tests/trampoline_test.rs diff --git a/crates/molotov-core/src/lib.rs b/crates/molotov-core/src/lib.rs index efd42d7..51bc3ae 100644 --- a/crates/molotov-core/src/lib.rs +++ b/crates/molotov-core/src/lib.rs @@ -4,3 +4,4 @@ pub mod elf; pub mod mmap; pub mod reloc; pub mod symbols; +pub mod trampoline; diff --git a/crates/molotov-core/src/trampoline.rs b/crates/molotov-core/src/trampoline.rs new file mode 100644 index 0000000..6c00a9d --- /dev/null +++ b/crates/molotov-core/src/trampoline.rs @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +use std::ffi::CString; + +pub extern "C" fn generic_failing_stub() -> i32 { + // ENOSYS is errno 38 on Linux x86_64 + -38 +} + +pub fn resolve_symbol_address(symbol: &str) -> Result { + // 1. Host lookup via dlsym + let c_name = CString::new(symbol).map_err(|e| e.to_string())?; + let host_ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c_name.as_ptr()) }; + + if !host_ptr.is_null() { + Ok(host_ptr as u64) + } else { + // 2. Return explicit failure stub trampoline (never fake 0) + tracing::warn!("Resolving unimplemented symbol '{}' to generic_failing_stub (-ENOSYS)", symbol); + Ok(generic_failing_stub as *const () as u64) + } +} diff --git a/crates/molotov-core/tests/trampoline_test.rs b/crates/molotov-core/tests/trampoline_test.rs new file mode 100644 index 0000000..370ebcc --- /dev/null +++ b/crates/molotov-core/tests/trampoline_test.rs @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +use molotov_core::trampoline::resolve_symbol_address; + +#[test] +fn test_resolve_standard_host_symbol() { + let addr = resolve_symbol_address("malloc").expect("malloc should resolve to host glibc"); + assert_ne!(addr, 0); +} + +#[test] +fn test_unimplemented_stub_returns_failing_function() { + let stub_fn = resolve_symbol_address("unimplemented_android_telemetry") + .expect("Should resolve to a failing stub trampoline"); + let func: extern "C" fn() -> i32 = unsafe { std::mem::transmute(stub_fn) }; + let ret = func(); + assert_eq!(ret, -38, "Stub must return -ENOSYS (-38), never fake 0 or success"); +}