elf_loader 0.14.0

A high-performance, no_std compliant ELF loader and JIT linker for Rust.
Documentation
use crate::{
    Result,
    arch::StaticRelocator,
    elf::ElfRelType,
    image::{LoadedCore, RawObject},
    loader::LifecycleContext,
    relocation::{RelocHelper, RelocationHandler, SymbolLookup},
    segment::section::PltGotSection,
};
use alloc::{boxed::Box, vec::Vec};

pub(crate) struct StaticRelocation {
    relocation: Box<[&'static [ElfRelType]]>,
}

impl StaticRelocation {
    pub(crate) fn new(relocation: Vec<&'static [ElfRelType]>) -> Self {
        Self {
            relocation: relocation.into_boxed_slice(),
        }
    }
}

impl<D: 'static> RawObject<D> {
    pub(crate) fn relocate_impl<PreS, PostS, PreH, PostH>(
        mut self,
        scope: &[LoadedCore<D>],
        pre_find: &PreS,
        post_find: &PostS,
        pre_handler: &PreH,
        post_handler: &PostH,
    ) -> Result<LoadedCore<D>>
    where
        PreS: SymbolLookup + ?Sized,
        PostS: SymbolLookup + ?Sized,
        PreH: RelocationHandler + ?Sized,
        PostH: RelocationHandler + ?Sized,
    {
        #[cfg(feature = "log")]
        log::debug!("Relocating object: {}", self.core.name());

        let mut helper = RelocHelper::new(
            &self.core,
            scope.to_vec(),
            pre_find,
            post_find,
            pre_handler,
            post_handler,
            self.tls_get_addr,
        );
        for reloc in self.relocation.relocation.iter() {
            for rel in *reloc {
                if !helper.handle_pre(rel)? {
                    continue;
                }
                StaticRelocator::relocate(&mut helper, rel, &mut self.pltgot)?;
                if !helper.handle_post(rel)? {
                    continue;
                }
            }
        }

        // Set TLS descriptor arguments collected during relocation
        unsafe {
            self.core.set_tls_desc_args(helper.tls_desc_args);
        }

        (self.mprotect)()?;

        #[cfg(feature = "log")]
        log::trace!("[{}] Executing init functions", self.core.name());
        self.init
            .call(&LifecycleContext::new(None, self.init_array));

        #[cfg(feature = "log")]
        log::info!("Relocation completed for {}", self.core.name());

        Ok(unsafe { LoadedCore::from_core(self.core) })
    }
}

pub(crate) trait StaticReloc {
    fn relocate<D, PreS, PostS, PreH, PostH>(
        helper: &mut RelocHelper<'_, D, PreS, PostS, PreH, PostH>,
        rel: &ElfRelType,
        pltgot: &mut PltGotSection,
    ) -> Result<()>
    where
        PreS: SymbolLookup + ?Sized,
        PostS: SymbolLookup + ?Sized,
        PreH: RelocationHandler + ?Sized,
        PostH: RelocationHandler + ?Sized;

    fn needs_got(_rel_type: u32) -> bool {
        false
    }

    fn needs_plt(_rel_type: u32) -> bool {
        false
    }
}