A pure-Rust ELF dynamic linker, dlopen compatibility layer, and experimental Linux rtld.
dlopen-rs provides a Rust-friendly dynamic library loading API and exports libc-compatible entry points such as dlopen, dlsym, dladdr, and dl_iterate_phdr. The project moves ELF loading, dependency resolution, relocation, symbol lookup, and TLS management into Rust, while steadily growing an rtld implementation that can eventually replace glibc ld.so.
- Dynamic loading: Load ELF shared objects from paths or in-memory bytes.
- Dependency resolution: Handle
DT_NEEDED,RPATH,RUNPATH,ld.so.cache, and common system search paths. - Symbol lookup: Provide Rust APIs and C ABI entry points, including global lookup, dependency scopes,
RTLD_NEXT, andRTLD_DEFAULT. - Relocation: Support regular dynamic relocations, PLT/GOT relocation, lazy binding, and RELR.
- TLS: Support dynamic TLS, static TLS registration, and initial-thread TLS needed during rtld startup.
no_std: Run the core loading path withoutstd, with an optional Linux syscall backend viause-syscall.- Replacement rtld: Build an experimental ELF interpreter that advertises itself as
ld-linux-x86-64.so.2.
| Area | Status |
|---|---|
Rust ElfLibrary API |
Usable |
| libc-compatible dlopen/dlsym/dladdr/dl_iterate_phdr | Usable |
LD_PRELOAD compatibility library |
Usable |
no_std + syscall loading path |
Usable, still being refined |
| Replacement rtld | Experimental, focused on x86_64 Linux/glibc compatibility |
For regular Rust programs:
[dependencies]
dlopen-rs = "0.8.0"For no_std with the syscall backend:
[dependencies]
dlopen-rs = { version = "0.8.0", default-features = false, features = ["use-syscall"] }Build the example shared object first:
cargo build --release -p example_dylibThen run the dlopen-rs example:
cargo run --release --example dlopenCore usage:
use dlopen_rs::{ElfLibrary, OpenFlags, Result};
fn main() -> Result<()> {
let lib = ElfLibrary::dlopen("./target/release/libexample.so", OpenFlags::RTLD_LAZY)?;
let add = unsafe { lib.get::<fn(i32, i32) -> i32>("add")? };
println!("add(1, 1) = {}", add(1, 1));
Ok(())
}The cdylib crate builds a libc dlopen-family compatibility library:
cargo build --release -p cdylib
cargo build --release -p example_dylib
cargo build --release --example preload
RUST_LOG=trace \
LD_PRELOAD=./target/release/libdlopen.so \
./target/release/examples/preloadThis is useful for checking how well dlopen-rs can interpose existing dlopen/dlsym calls.
The rtld crate builds an experimental ELF interpreter intended to grow into a replacement for glibc ld-linux-x86-64.so.2:
cargo build-rtldArtifacts are written to:
target/x86_64-unknown-linux-none/release/librtld.so
target/x86_64-unknown-linux-none/release/ld-linux-x86-64.so.2
This path uses x86_64-unknown-linux-none, -Z build-std=core,alloc,compiler_builtins, and custom linker arguments. Use a nightly toolchain, or another toolchain capable of -Z build-std, when building this target.
The repository defines Cargo aliases that keep host/std checks separate from rtld/no_std checks:
cargo check-host
cargo check-rtld
cargo build-rtldCommon validation set:
cargo check-host
cargo check-rtld
cargo check --no-default-features --lib
cargo check --no-default-features --features use-syscall --lib
cargo test --test rtld_artifact rtld_artifact_has_interpreter_shape| Feature | Default | Description |
|---|---|---|
std |
Yes | Enables standard library integration, host initialization, and ctor support. |
use-syscall |
No | Uses the Linux syscall backend, mainly for no_std and rtld paths. |
version |
No | Enables ELF symbol version support. |
| Architecture | Dynamic Loading | Lazy Binding | Replacement rtld |
|---|---|---|---|
| x86_64 Linux | Supported | Supported | Experimental |
| aarch64 | Supported | Supported | Not enabled |
| riscv64 | Supported | Some paths still being validated | Not enabled |
src/ Rust API, C ABI, loader/register core logic
src/rtld.rs no_std rtld entry points and rtld-specific TLS glue
src/host_init.rs std/host import of objects already loaded by the host ld.so
cdylib/ LD_PRELOAD compatibility library
rtld/ replacement ld.so artifact crate
rtld/impl/ no_std rtld implementation
example-dylib/ example shared object
examples/ API and LD_PRELOAD examples
tests/ integration tests and rtld artifact checks
Licensed under the Apache License 2.0.
Issues and pull requests are welcome. For GDB/r_debug/link_map related debugging notes, see TroubleshootingGdb.md.
Minimum Supported Rust Version (MSRV): 1.93.0 or higher.