Skip to main content

lib_unknown/sys/
unix.rs

1//! Unix 系统封装:各平台调用号/标志位(`syscall`)与 `dlopen`/`dlsym` 动态符号解析(`resolve`)。
2//!
3//! 需要启用 `"sys-unix"` 特性。
4#[cfg(feature = "sys-syscall")]
5pub mod syscall;
6
7/// 通过 `dlopen/dlsym` 动态解析共享库符号。
8///
9/// 名称超长(≥256)、含内嵌 `\0` 或解析失败时返回 `None`,不缓存句柄。
10///
11/// # Examples
12///
13/// ```rust,no_run
14/// use lib_unknown::sys::unix::resolve;
15///
16/// let f: Option<unsafe extern "C" fn() -> i32> = resolve("libc.so.6", "getpid");
17/// let _ = f;
18/// ```
19#[inline(never)]
20pub fn resolve<T: Sized + Copy>(dylib: &str, name: &str) -> Option<T> {
21    use core::ffi::c_void;
22    use core::mem;
23
24    unsafe extern "C" {
25        fn dlopen(filename: *const i8, flag: i32) -> *mut c_void;
26        fn dlsym(handle: *mut c_void, symbol: *const i8) -> *mut c_void;
27    }
28    const RTLD_LAZY: i32 = 1;
29    const MAX_LEN: usize = 256;
30
31    if dylib.len() >= MAX_LEN || name.len() >= MAX_LEN {
32        return None;
33    }
34
35    let mut dylib_buf = [0u8; MAX_LEN];
36    let mut name_buf = [0u8; MAX_LEN];
37
38    dylib_buf[..dylib.len()].copy_from_slice(dylib.as_bytes());
39    name_buf[..name.len()].copy_from_slice(name.as_bytes());
40
41    if dylib.as_bytes().contains(&0) || name.as_bytes().contains(&0) {
42        return None;
43    }
44
45    // SAFETY: `dylib_buf` 以输入字节填充、剩余补 0,且已拒绝含内嵌 NUL 的输入,
46    // 故指针指向合法 NUL 结尾字符串,调用期间有效;`dlopen` 为系统提供函数。
47    let handle = unsafe { dlopen(dylib_buf.as_ptr() as *const i8, RTLD_LAZY) };
48    if handle.is_null() {
49        return None;
50    }
51
52    // SAFETY: `handle` 来自成功的 `dlopen`;`name_buf` 同理为合法 NUL 结尾字符串,
53    // 调用期间有效。
54    let sym = unsafe { dlsym(handle, name_buf.as_ptr() as *const i8) };
55    if sym.is_null() {
56        return None;
57    }
58
59    // SAFETY: 已检查 `sym` 非空;调用方以 `T: Sized + Copy` 声明目标签名,
60    // 类型正确性由调用方保证(见函数文档)。
61    Some(unsafe { mem::transmute_copy(&sym) })
62}
63
64#[cfg(test)]
65mod tests {
66    #[test]
67    fn test_() {
68        let _x = c"2222222";
69        let _y = r"2222222";
70    }
71}