xref: /drstd/dlibc/src/unix/header/dlfcn/mod.rs (revision 0fe3ff0054d3aec7fbf9bddecfecb10bc7d23a51)
1 //! dlfcn implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/dlfcn.h.html
2 
3 use core::{
4     ptr, str,
5     sync::atomic::{AtomicUsize, Ordering},
6 };
7 use crate::unix::c_str::*;
8 use crate::ld_so::tcb::Tcb;
9 
10 static ERROR_NOT_SUPPORTED: &'static CStr = c_str!("dlfcn not supported");
11 
12 #[thread_local]
13 static ERROR: AtomicUsize = AtomicUsize::new(0);
14 
15 #[no_mangle]
16 pub unsafe extern "C" fn dladdr(_addr: *mut ::c_void, info: *mut ::Dl_info) -> ::c_int {
17     //TODO
18     (*info).dli_fname = ptr::null();
19     (*info).dli_fbase = ptr::null_mut();
20     (*info).dli_sname = ptr::null();
21     (*info).dli_saddr = ptr::null_mut();
22     0
23 }
24 
25 #[no_mangle]
26 pub unsafe extern "C" fn dlopen(cfilename: *const ::c_char, _flags: ::c_int) -> *mut ::c_void {
27     //TODO support all sort of flags
28 
29     let filename = if cfilename.is_null() {
30         None
31     } else {
32         Some(str::from_utf8_unchecked(
33             CStr::from_ptr(cfilename).to_bytes(),
34         ))
35     };
36 
37     let tcb = match Tcb::current() {
38         Some(tcb) => tcb,
39         None => {
40             ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
41             return ptr::null_mut();
42         }
43     };
44     if tcb.linker_ptr.is_null() {
45         ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
46         return ptr::null_mut();
47     }
48     let mut linker = (&*tcb.linker_ptr).lock();
49 
50     let cbs_c = linker.cbs.clone();
51     let cbs = cbs_c.borrow();
52 
53     let id = match (cbs.load_library)(&mut linker, filename) {
54         Err(_err) => {
55             ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
56             return ptr::null_mut();
57         }
58         Ok(id) => id,
59     };
60 
61     id as *mut ::c_void
62 }
63 
64 #[no_mangle]
65 pub unsafe extern "C" fn dlsym(handle: *mut ::c_void, symbol: *const ::c_char) -> *mut ::c_void {
66     if symbol.is_null() {
67         ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
68         return ptr::null_mut();
69     }
70 
71     let symbol_str = str::from_utf8_unchecked(CStr::from_ptr(symbol).to_bytes());
72 
73     let tcb = match Tcb::current() {
74         Some(tcb) => tcb,
75         None => {
76             ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
77             return ptr::null_mut();
78         }
79     };
80 
81     if tcb.linker_ptr.is_null() {
82         ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
83         return ptr::null_mut();
84     }
85 
86     let linker = (&*tcb.linker_ptr).lock();
87     let cbs_c = linker.cbs.clone();
88     let cbs = cbs_c.borrow();
89     match (cbs.get_sym)(&linker, handle as usize, symbol_str) {
90         Some(sym) => sym,
91         _ => {
92             ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
93             ptr::null_mut()
94         }
95     }
96 }
97 
98 #[no_mangle]
99 pub unsafe extern "C" fn dlclose(handle: *mut ::c_void) -> ::c_int {
100     let tcb = match Tcb::current() {
101         Some(tcb) => tcb,
102         None => {
103             ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
104             return -1;
105         }
106     };
107 
108     if tcb.linker_ptr.is_null() {
109         ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
110         return -1;
111     };
112     let mut linker = (&*tcb.linker_ptr).lock();
113     let cbs_c = linker.cbs.clone();
114     let cbs = cbs_c.borrow();
115     (cbs.unload)(&mut linker, handle as usize);
116     0
117 }
118 
119 #[no_mangle]
120 pub extern "C" fn dlerror() -> *mut ::c_char {
121     ERROR.swap(0, Ordering::SeqCst) as *mut ::c_char
122 }
123