9 unstable releases (4 breaking)

new 0.12.0 Apr 6, 2021
0.11.0 Oct 22, 2020
0.10.0 Apr 3, 2020
0.9.0 Nov 26, 2019
0.0.1 Jul 5, 2015

#57 in Operating systems

35 downloads per month

MIT/Apache

27KB
513 lines

Build Status

elfloader

A library to load and relocate ELF files in memory. This library depends only on libcore so it can be used in kernel level code, for example to load user-space programs.

How-to use

Clients will have to implement the ElfLoader trait:

use elfloader::*;

/// A simple ExampleLoader, that implements ElfLoader
/// but does nothing but logging
struct ExampleLoader {
    vbase: u64,
}

impl ElfLoader for ExampleLoader {
    fn allocate(&mut self, load_headers: LoadableHeaders) -> Result<(), &'static str> {
        for header in load_headers {
            info!(
                "allocate base = {:#x} size = {:#x} flags = {}",
                header.virtual_addr(),
                header.mem_size(),
                header.flags()
            );
        }
        Ok(())
    }

    fn relocate(&mut self, entry: &Rela<P64>) -> Result<(), &'static str> {
        let typ = TypeRela64::from(entry.get_type());
        let addr: *mut u64 = (self.vbase + entry.get_offset()) as *mut u64;

        match typ {
            TypeRela64::R_RELATIVE => {
                // This is a relative relocation, add the offset (where we put our
                // binary in the vspace) to the addend and we're done.
                info!(
                    "R_RELATIVE *{:p} = {:#x}",
                    addr,
                    self.vbase + entry.get_addend()
                );
                Ok(())
            }
            _ => Err("Unexpected relocation encountered"),
        }
    }

    fn load(&mut self, flags: Flags, base: VAddr, region: &[u8]) -> Result<(), &'static str> {
        let start = self.vbase + base;
        let end = self.vbase + base + region.len();
        info!("load region into = {:#x} -- {:#x}", start, end);
        Ok(())
    }

    fn tls(
        &mut self,
        tdata_start: VAddr,
        _tdata_length: u64,
        total_size: u64,
        _align: u64
    ) -> Result<(), &'static str> {
        let tls_end = tdata_start +  total_size;
        info!("Initial TLS region is at = {:#x} -- {:#x}", tdata_start, tls_end);
        Ok(())
    }

}

Then, with ElfBinary, a ELF file is loaded using load:

let binary_blob = fs::read("test/test").expect("Can't read binary");
let binary = ElfBinary::new("test", binary_blob.as_slice()).expect("Got proper ELF file");
let mut loader = ExampleLoader::new(0x1000_0000);
binary.load(&mut loader).expect("Can't load the binary?");

Dependencies

~185KB