#![no_std]
#![warn(
clippy::unnecessary_wraps,
clippy::unnecessary_lazy_evaluations,
clippy::collapsible_if,
clippy::cast_lossless,
clippy::explicit_iter_loop,
clippy::manual_assert,
clippy::needless_question_mark,
clippy::needless_return,
clippy::needless_update,
clippy::redundant_clone,
clippy::redundant_else,
clippy::redundant_static_lifetimes
)]
#![allow(
clippy::len_without_is_empty,
clippy::unnecessary_cast,
clippy::uninit_vec
)]
extern crate alloc;
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "riscv32",
target_arch = "loongarch64",
target_arch = "x86",
target_arch = "arm",
)))]
compile_error!("unsupport arch");
#[cfg(all(
any(feature = "fs", feature = "mmap"),
not(any(feature = "use-libc", feature = "use-syscall"))
))]
compile_error!("use at least one of libc and syscall");
#[cfg(all(feature = "use-libc", feature = "use-syscall"))]
compile_error!("only one of use-libc and use-syscall can be used");
pub mod arch;
pub mod dynamic;
mod format;
mod loader;
mod macros;
pub mod mmap;
pub mod object;
mod relocation;
pub mod segment;
mod symbol;
#[cfg(feature = "version")]
mod version;
use alloc::{
boxed::Box,
string::{String, ToString},
};
use core::{
any::Any,
fmt::{Debug, Display},
};
use object::*;
use relocation::{ElfRelocation, GLOBAL_SCOPE};
use segment::ELFRelro;
pub use elf::abi;
pub use format::dylib::{ElfDylib, RelocatedDylib, Symbol};
pub use format::exec::{ElfExec, RelocatedExec};
pub use format::{CoreComponent, CoreComponentRef, Elf, UserData};
pub use loader::Loader;
pub use relocation::find_symdef;
#[derive(Debug)]
pub enum Error {
#[cfg(feature = "fs")]
IOError { msg: String },
MmapError { msg: String },
RelocateError {
msg: String,
custom_err: Box<dyn Any + Send + Sync>,
},
ParseDynamicError { msg: &'static str },
ParseEhdrError { msg: String },
ParsePhdrError {
msg: String,
custom_err: Box<dyn Any + Send + Sync>,
},
}
impl Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
#[cfg(feature = "fs")]
Error::IOError { msg } => write!(f, "{msg}"),
Error::MmapError { msg } => write!(f, "{msg}"),
Error::RelocateError { msg, .. } => write!(f, "{msg}"),
Error::ParseDynamicError { msg } => write!(f, "{msg}"),
Error::ParseEhdrError { msg } => write!(f, "{msg}"),
Error::ParsePhdrError { msg, .. } => write!(f, "{msg}"),
}
}
}
impl core::error::Error for Error {}
#[cfg(feature = "fs")]
#[cold]
#[inline(never)]
fn io_error(msg: impl ToString) -> Error {
Error::IOError {
msg: msg.to_string(),
}
}
#[cold]
#[inline(never)]
fn relocate_error(msg: impl ToString, custom_err: Box<dyn Any + Send + Sync>) -> Error {
Error::RelocateError {
msg: msg.to_string(),
custom_err,
}
}
#[cold]
#[inline(never)]
fn parse_dynamic_error(msg: &'static str) -> Error {
Error::ParseDynamicError { msg }
}
#[cold]
#[inline(never)]
fn parse_ehdr_error(msg: impl ToString) -> Error {
Error::ParseEhdrError {
msg: msg.to_string(),
}
}
#[cold]
#[inline(never)]
fn parse_phdr_error(msg: impl ToString, custom_err: Box<dyn Any + Send + Sync>) -> Error {
Error::ParsePhdrError {
msg: msg.to_string(),
custom_err,
}
}
pub unsafe fn set_global_scope(f: fn(&str) -> Option<*const ()>) {
GLOBAL_SCOPE.store(f as usize, core::sync::atomic::Ordering::Release);
}
pub type Result<T> = core::result::Result<T, Error>;