elf_loader 0.15.1

A no_std-friendly ELF loader, runtime linker, and JIT linker for Rust.
Documentation
//! Shared-object image types.
//!
//! Use [`RawDylib`] for a mapped-but-unrelocated shared object. Relocation returns
//! the common [`LoadedCore`] representation.

use crate::{
    Result,
    elf::{ElfDyn, ElfPhdr},
    image::{ElfCore, LoadedCore, RawDynamic},
    input::Path,
    relocation::{Relocatable, RelocateArgs, RelocationArch, RelocationHandler, Relocator},
    tls::{TlsModuleId, TlsTpOffset},
};
use core::{fmt::Debug, ptr::NonNull};

/// A mapped but unrelocated shared object.
///
/// Values of this type are returned by [`crate::Loader::load_dylib`]. They expose
/// ELF metadata immediately and can later be turned into a [`LoadedCore`] by running
/// relocation.
///
/// The optional `Arch` type parameter selects the target architecture used by
/// [`Relocator::relocate`]. By default it is [`crate::arch::NativeArch`].
pub struct RawDylib<D, Arch = crate::arch::NativeArch>
where
    D: 'static,
    Arch: RelocationArch,
{
    /// The common part containing basic ELF object information.
    pub(crate) inner: RawDynamic<D, Arch>,
}

impl<D, Arch: RelocationArch> Debug for RawDylib<D, Arch> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("RawDylib")
            .field("name", &self.inner.name())
            .field("needed_libs", &self.inner.needed_libs())
            .finish()
    }
}

impl<D: 'static, Arch: RelocationArch> Relocatable<D> for RawDylib<D, Arch> {
    type Output = LoadedCore<D, Arch>;
    type Arch = Arch;

    fn relocate<PreH, PostH>(
        self,
        args: RelocateArgs<'_, D, Arch, PreH, PostH>,
    ) -> Result<Self::Output>
    where
        PreH: RelocationHandler<Arch> + ?Sized,
        PostH: RelocationHandler<Arch> + ?Sized,
    {
        Relocatable::relocate(self.inner, args)
    }
}

impl<D, Arch: RelocationArch> RawDylib<D, Arch> {
    /// Creates a new `RawDylib` from a `RawDynamic`.
    #[inline]
    pub fn from_dynamic(inner: RawDynamic<D, Arch>) -> Self {
        Self { inner }
    }

    /// Converts this `RawDylib` into a `RawDynamic`.
    #[inline]
    pub fn into_dynamic(self) -> RawDynamic<D, Arch> {
        self.inner
    }

    /// Gets the entry point of the ELF object.
    #[inline]
    pub fn entry(&self) -> usize {
        self.inner.entry()
    }

    /// Gets the core component reference of the ELF object.
    #[inline]
    pub fn core_ref(&self) -> &ElfCore<D, Arch> {
        self.inner.core_ref()
    }

    /// Gets the core component of the ELF object.
    #[inline]
    pub fn core(&self) -> ElfCore<D, Arch> {
        self.inner.core()
    }

    /// Converts this object into its core component.
    #[inline]
    pub fn into_core(self) -> ElfCore<D, Arch> {
        self.inner.into_core()
    }

    /// Whether lazy binding is enabled for the current ELF object
    #[inline]
    pub fn is_lazy(&self) -> bool {
        self.inner.is_lazy()
    }

    /// Returns the TLS module id assigned to this image, when registered.
    pub fn tls_mod_id(&self) -> Option<TlsModuleId> {
        self.inner.tls_mod_id()
    }

    /// Returns the static TLS thread-pointer offset, when assigned.
    pub fn tls_tp_offset(&self) -> Option<TlsTpOffset> {
        self.inner.tls_tp_offset()
    }

    /// Returns the DT_RPATH value.
    #[inline]
    pub fn rpath(&self) -> Option<&str> {
        self.inner.rpath()
    }

    /// Returns the DT_RUNPATH value.
    #[inline]
    pub fn runpath(&self) -> Option<&str> {
        self.inner.runpath()
    }

    /// Returns the DT_SONAME value.
    #[inline]
    pub fn soname(&self) -> Option<&str> {
        self.inner.soname()
    }

    /// Returns the PT_INTERP value.
    #[inline]
    pub fn interp(&self) -> Option<&str> {
        self.inner.interp()
    }

    /// Returns the loader source path or caller-provided source identifier.
    #[inline]
    pub fn path(&self) -> &Path {
        self.inner.path()
    }

    /// Returns the ELF module identity used for diagnostics.
    #[inline]
    pub fn name(&self) -> &str {
        self.inner.name()
    }

    /// Returns the program headers of the ELF object.
    pub fn phdrs(&self) -> &[ElfPhdr<Arch::Layout>] {
        self.inner.phdrs()
    }

    /// Returns the base address of the loaded ELF object.
    pub fn base(&self) -> usize {
        self.inner.base()
    }

    /// Returns the length of the bounding runtime span covered by mapped slices.
    pub fn mapped_len(&self) -> usize {
        self.inner.mapped_len()
    }

    /// Returns the lowest runtime address covered by this object's mapped slices.
    pub(crate) fn mapped_base(&self) -> usize {
        self.inner.mapped_base()
    }

    /// Returns whether `addr` is inside one of this object's mapped slices.
    pub fn contains_addr(&self, addr: usize) -> bool {
        self.inner.contains_addr(addr)
    }

    /// Returns the list of needed library names from the dynamic section.
    pub fn needed_libs(&self) -> &[&str] {
        self.inner.needed_libs()
    }

    /// Returns the dynamic section pointer.
    pub fn dynamic_ptr(&self) -> Option<NonNull<ElfDyn<Arch::Layout>>> {
        self.inner.dynamic_ptr()
    }

    /// Returns a reference to the user data.
    pub fn user_data(&self) -> &D {
        self.inner.user_data()
    }

    /// Returns a mutable reference to the user data.
    #[inline]
    pub fn user_data_mut(&mut self) -> Option<&mut D> {
        self.inner.user_data_mut()
    }

    /// Creates a relocation builder for this shared object.
    pub fn relocator(self) -> Relocator<Self, (), (), D, Arch> {
        Relocator::new().with_object(self)
    }
}