I'm a bit lost at making dlsym() work in Rust:
libc::dlsym()returns a*mut c_voidhandle to the desired function.- To use that handle, I need to cast it to
extern fn, but that doesn't seem possible, even thoughfn(externor not) appears to be a*mutinternally. - If I store the handle as
*mut extern fn, as I did in the sample program below, I'm effectively storing a*mutas a*mut *mut(seegdboutput at the end), which, not surprisingly, will produce segfaults.
Sample program, which will segfault when handle is invoked at line 15:
use std::ffi::CString;
fn main() {
let func_name = CString::new("fork").unwrap();
let handle: *mut extern "C" fn() -> libc::pid_t =
unsafe { libc::dlsym(libc::RTLD_NEXT, func_name.as_ptr()).cast() };
if handle.is_null() {
let error_msg = CString::new("dlsym(fork) failed: %s\n").unwrap();
unsafe { libc::printf(error_msg.as_ptr(), libc::dlerror()) };
panic!();
}
let pid = unsafe { (*handle)() };
if pid == 0 {
println!("parent pid = {}", unsafe { libc::getppid() });
} else if pid == -1 {
let error_msg = CString::new("fork() failed").unwrap();
unsafe { libc::perror(error_msg.as_ptr()) };
} else {
println!("child pid = {}", pid);
}
}
gdb output:
(gdb) p handle
$1 = (*mut *mut fn () -> i32) 0x7f40b093b900 <__libc_fork>