how to use `dlsym()` in Rust

Viewed 191

I'm a bit lost at making dlsym() work in Rust:

  • libc::dlsym() returns a *mut c_void handle to the desired function.
  • To use that handle, I need to cast it to extern fn, but that doesn't seem possible, even though fn (extern or not) appears to be a *mut internally.
  • If I store the handle as *mut extern fn, as I did in the sample program below, I'm effectively storing a *mut as a *mut *mut (see gdb output 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>
0 Answers
Related