use frida_gum_sys as gum_sys;
extern "C" {
#[allow(improper_ctypes)]
fn gum_linux_parse_ucontext(
context: *const libc::ucontext_t,
cpu_context: *mut gum_sys::GumCpuContext,
);
}
pub struct Backtracer;
impl Backtracer {
fn generate(
backtracer: *mut gum_sys::GumBacktracer,
context: *const gum_sys::GumCpuContext,
) -> Vec<usize> {
let mut return_address_array =
std::mem::MaybeUninit::<gum_sys::_GumReturnAddressArray>::uninit();
unsafe {
gum_sys::gum_backtracer_generate(
backtracer,
context,
return_address_array.as_mut_ptr(),
);
let return_address_array = return_address_array.assume_init();
let mut result = vec![];
for i in 0..return_address_array.len {
result.push(*return_address_array.items.get(i as usize).unwrap() as usize);
}
result
}
}
pub fn accurate() -> Vec<usize> {
Self::generate(
unsafe { gum_sys::gum_backtracer_make_accurate() },
std::ptr::null(),
)
}
pub fn fuzzy() -> Vec<usize> {
Self::generate(
unsafe { gum_sys::gum_backtracer_make_fuzzy() },
std::ptr::null(),
)
}
pub fn accurate_with_context(context: &gum_sys::GumCpuContext) -> Vec<usize> {
Self::generate(
unsafe { gum_sys::gum_backtracer_make_accurate() },
context as *const gum_sys::GumCpuContext,
)
}
pub fn fuzzy_with_context(context: &gum_sys::GumCpuContext) -> Vec<usize> {
Self::generate(
unsafe { gum_sys::gum_backtracer_make_fuzzy() },
context as *const gum_sys::GumCpuContext,
)
}
pub fn accurate_with_signal_context(context: &libc::ucontext_t) -> Vec<usize> {
let mut cpu_context = std::mem::MaybeUninit::<gum_sys::GumCpuContext>::uninit();
unsafe {
gum_linux_parse_ucontext(context as *const libc::ucontext_t, cpu_context.as_mut_ptr());
Self::accurate_with_context(&cpu_context.assume_init())
}
}
pub fn fuzzy_with_signal_context(context: &libc::ucontext_t) -> Vec<usize> {
let mut cpu_context = std::mem::MaybeUninit::<gum_sys::GumCpuContext>::uninit();
unsafe {
gum_linux_parse_ucontext(context as *const libc::ucontext_t, cpu_context.as_mut_ptr());
Self::fuzzy_with_context(&cpu_context.assume_init())
}
}
}