1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! Memory-safe bindings around the platform's dynamic library loading
//! primitives (`dlopen`/`dlsym` on Unix, `LoadLibraryExW`/`GetProcAddress` on
//! Windows).
//!
//! The central guarantee of this crate is that **a symbol can never outlive
//! the library it was loaded from** through safe code:
//!
//! - [`Symbol<'lib, T>`](Symbol) borrows its [`Library`], so the borrow checker
//! rejects dropping the library while a symbol is alive.
//! - [`ArcSymbol<T>`](ArcSymbol) keeps the library alive through an
//! [`Arc`](std::sync::Arc) for when a borrow is impractical (e.g. `'static`
//! storage), without resorting to `transmute`.
//! - Neither type hands out the raw function pointer through safe code:
//! functions are invoked through [`Symbol::call`] (or [`Symbol::with`] for
//! variadic ones), so the pointer cannot be copied out and kept past an
//! unload by accident.
//! - The [`library!`] macro generates a struct that owns the library together
//! with every resolved symbol, using Rust 2024 `unsafe extern` block
//! syntax. This is the shape the `dlsym-gen` tool emits from C headers
//! (see [`codegen`], behind the `codegen` feature).
//!
//! ```no_run
//! # fn main() -> Result<(), dlsym::Error> {
//! use dlsym::Library;
//!
//! // SAFETY: libm has no unsound initialisers.
//! let libm = unsafe { Library::open("libm.so.6")? };
//! // SAFETY: `cos` has this signature in libm.
//! let cos = unsafe { libm.get::<unsafe extern "C" fn(f64) -> f64>(c"cos")? };
//! // SAFETY: `cos` is a pure function, valid for any `f64`.
//! assert_eq!(unsafe { cos.call((0.0,)) }, 1.0);
//!
//! drop(libm); // fine here; moving this above the call would not compile
//! # Ok(()) }
//! ```
//!
//! # Platform notes
//!
//! - **Unloading.** Borrowing only protects your own use of a library. Some
//! libraries leave threads, thread-local destructors or callbacks behind
//! that crash once they are unloaded; see
//! [Libraries that cannot be unloaded](Library#libraries-that-cannot-be-unloaded).
//! - **Thread-local data.** Looking up a C `__thread` / `_Thread_local`
//! variable returns its address *for the calling thread*. Such a data
//! symbol must only be used on the thread that looked it up.
//! - **Error reporting.** Lookups rely on `dlerror` to tell a missing
//! symbol from one whose address is null. Its state is thread-local on
//! glibc, musl, Apple platforms and the BSDs, so concurrent lookups from
//! several threads are fine there.
//! - **Lazy binding.** With `RTLD_LAZY` (see `os::unix::OpenOptions`), a
//! library whose own dependencies are missing may load fine and abort the
//! process later when a function is first called. [`Library::open`] uses
//! `RTLD_NOW` to report such problems upfront.
pub use Error;
pub use AddressInfo;
pub use ;
pub use Bindings;
pub use SymbolName;
pub use ;
pub use ;
/// Convenience alias for results returned by this crate.
pub type Result<T, E = Error> = Result;