1 // dlsym.rs is taken from mio
2 // https://github.com/carllerche/mio/blob/master/src/sys/unix/dlsym.rs
3 
4 use std::marker;
5 use std::mem;
6 use std::sync::atomic::{AtomicUsize, Ordering};
7 
8 use libc;
9 
10 macro_rules! dlsym {
11     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
12         #[allow(bad_style)]
13         static $name: $crate::dlsym::DlSym<unsafe extern fn($($t),*) -> $ret> =
14             $crate::dlsym::DlSym {
15                 name: concat!(stringify!($name), "\0"),
16                 addr: ::std::sync::atomic::AtomicUsize::new(0),
17                 _marker: ::std::marker::PhantomData,
18             };
19     )
20 }
21 
22 pub struct DlSym<F> {
23     pub name: &'static str,
24     pub addr: AtomicUsize,
25     pub _marker: marker::PhantomData<F>,
26 }
27 
28 impl<F> DlSym<F> {
get(&self) -> Option<&F>29     pub fn get(&self) -> Option<&F> {
30         assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
31         unsafe {
32             if self.addr.load(Ordering::SeqCst) == 0 {
33                 self.addr.store(fetch(self.name), Ordering::SeqCst);
34             }
35             if self.addr.load(Ordering::SeqCst) == 1 {
36                 None
37             } else {
38                 mem::transmute::<&AtomicUsize, Option<&F>>(&self.addr)
39             }
40         }
41     }
42 }
43 
fetch(name: &str) -> usize44 unsafe fn fetch(name: &str) -> usize {
45     assert_eq!(name.as_bytes()[name.len() - 1], 0);
46     match libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) as usize {
47         0 => 1,
48         n => n,
49     }
50 }
51