dlopen_rs/lib.rs
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
//!A pure-rust library designed for loading ELF dynamic libraries from memory or from files.
//!
//!This library serves four purposes:
//!1. Provide a pure Rust alternative to musl ld.so or glibc ld.so.
//!2. Provide loading ELF dynamic libraries support for `#![no_std]` targets.
//!3. Easily swap out symbols in shared libraries with your own custom symbols at runtime
//!4. Faster than `ld.so` in most cases (loading dynamic libraries and getting symbols)
//!
//!Additional, it integrates seamlessly with the system’s dynamic linker in `std` environments when the `ldso` feature is enabled.
//!Currently, it supports `x86_64`, `RV64`, and `AArch64` architectures.
//!
//! # Examples
//! ```
//! use dlopen_rs::ELFLibrary;
//! use std::path::Path;
//! let path = Path::new("./target/release/libexample.so");
//! let libc = ELFLibrary::sys_load("libc.so.6").unwrap();
//! let libgcc = ELFLibrary::sys_load("libgcc_s.so.1").unwrap();
//! let libexample = ELFLibrary::from_file(path, None)
//! .unwrap()
//! .relocate(&[libgcc, libc])
//! .finish()
//! .unwrap();
//!
//! let add = unsafe {
//! libexample
//! .get::<fn(i32, i32) -> i32>("add")
//! .unwrap()
//! };
//! println!("{}", add(1,1));
//! ```
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[cfg(feature = "debug")]
mod debug;
mod dlopen;
#[cfg(feature = "ldso")]
mod ldso;
mod loader;
mod register;
use alloc::string::{String, ToString};
use core::fmt::Display;
pub use elf_loader::{RelocatedDylib, Symbol};
pub use loader::ElfLibrary;
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "riscv64",
)))]
compile_error!("unsupport arch");
/// dlopen-rs error type
#[derive(Debug)]
pub enum Error {
/// Returned when encountered an io error.
#[cfg(feature = "std")]
IOError { err: std::io::Error },
/// Returned when encountered a loader error.
LoaderError { err: elf_loader::Error },
/// Returned when failed to find a library.
FindLibError { msg: String },
}
impl Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
#[cfg(feature = "std")]
Error::IOError { err } => write!(f, "{err}"),
Error::LoaderError { err } => write!(f, "{err}"),
Error::FindLibError { msg } => write!(f, "{msg}"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::IOError { err } => Some(err),
_ => None,
}
}
}
impl From<elf_loader::Error> for Error {
#[cold]
fn from(value: elf_loader::Error) -> Self {
Error::LoaderError { err: value }
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
#[cold]
fn from(value: std::io::Error) -> Self {
Error::IOError { err: value }
}
}
#[cold]
#[inline(never)]
fn find_lib_error(msg: impl ToString) -> Error {
Error::FindLibError {
msg: msg.to_string(),
}
}
pub type Result<T> = core::result::Result<T, Error>;