#![no_std]
pub mod header;
pub mod sections;
pub mod utils;
use header::Header;
use sections::{Section, SectionIter};
pub use utils::*;
pub const HEADER_SIZE: usize = core::mem::size_of::<Header>();
pub const SECTION_SIZE: usize = core::mem::size_of::<Section>();
#[derive(Debug, Clone, Copy)]
pub struct Parser {
buf: &'static [u8],
header: Header,
total_sections: u16,
}
impl Parser {
pub unsafe fn init(buf: &'static [u8]) -> Result<Self, Error> {
let header_raw = &buf[0..HEADER_SIZE]; let header = unsafe { *(header_raw.as_ptr() as *const Header) };
if !header.validate() {
return Err(Error::NotValidExecutable);
}
let len = HEADER_SIZE + header.sections as usize * SECTION_SIZE;
if buf.len() < len {
return Err(Error::ExecutableCorrupted);
}
Ok(Self {
buf,
header,
total_sections: header.sections,
})
}
pub fn validate(&self) -> bool {
let minimal = self.header.min;
let maximum = self.header.max;
for (&min, &max) in minimal.iter().zip(maximum.iter()) {
if min > max {
return false;
}
}
let min_base = HEADER_SIZE + self.header.sections as usize * SECTION_SIZE;
for section in self.sections() {
let base_off = section.base as usize;
let len = section.length as usize;
if base_off < min_base
|| base_off + len > self.buf.len()
|| len == 0
|| !section.validate()
{
return false;
}
}
true
}
#[inline]
pub fn header(&self) -> Header {
self.header
}
#[allow(private_interfaces)]
pub fn sections(&self) -> SectionIter {
SectionIter {
buf: self.buf,
total: self.total_sections,
current: 0,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
NotValidExecutable,
ExecutableCorrupted,
UnknownCharacter,
}