Skip to main content

proka_exec/
sections.rs

1//! The definitions of section entry.
2use crate::{HEADER_SIZE, SECTION_SIZE};
3use core::ops::Index;
4
5/// A section entry.
6#[repr(C, packed)]
7#[derive(Debug, Clone, Copy)]
8pub struct Section {
9    /// The section name (16 bytes max).
10    pub name: [u8; 16],
11
12    /// Assign is this section loadable
13    pub is_loadable: bool,
14
15    /// Assign is this section executable
16    pub is_execable: bool,
17
18    /// The offset of the section start.
19    pub base: u32,
20
21    /// The length of the section.
22    pub length: u32,
23
24    /// Reserved bits
25    pub _reserved: [u8; 6],
26}
27
28impl Section {
29    /// Convert this object to array.
30    #[inline]
31    pub const fn to_array(&self) -> [u8; SECTION_SIZE] {
32        // SAFETY: used `#[repr(C)]`
33        unsafe { core::ptr::read(self as *const Self as *const [u8; SECTION_SIZE]) }
34    }
35
36    /// Validate is this section not corrupted.
37    #[inline]
38    pub fn validate(&self) -> bool {
39        // Length cannot be 0
40        let length_ok = self.length != 0;
41
42        // First check: base must >= 128+32
43        let base_ok = self.base as usize >= (HEADER_SIZE + SECTION_SIZE);
44
45        length_ok || base_ok
46    }
47}
48
49/// The iterator of each sections
50#[derive(Debug, Clone, Copy)]
51pub struct SectionIter<'a> {
52    buf: &'a [u8],
53    total: u16,
54    current: u16,
55}
56impl<'a> SectionIter<'a> {
57    pub(crate) fn new(buf: &'a [u8], total: u16, current: u16) -> Self {
58        Self {
59            buf,
60            total,
61            current,
62        }
63    }
64}
65
66/// Iterator implementations.
67impl<'a> Iterator for SectionIter<'a> {
68    type Item = Section;
69
70    fn next(&mut self) -> Option<Self::Item> {
71        // Check: is current over than total
72        if self.current >= self.total {
73            return None;
74        }
75
76        let base = HEADER_SIZE + self.current as usize * SECTION_SIZE;
77        let buf = &self.buf[base..base + SECTION_SIZE];
78
79        // Now convert it
80        let section = unsafe { *(buf.as_ptr() as *const Section) };
81
82        // Plus current value and return
83        self.current += 1;
84        Some(section)
85    }
86}
87
88/// The index implementations.
89///
90/// # Panics
91/// This will panic if your index is over than the length.
92impl Index<usize> for SectionIter<'_> {
93    type Output = Section;
94
95    fn index(&self, index: usize) -> &Self::Output {
96        // Check: Is index out if bounds
97        if index >= self.total as usize {
98            panic!("proka-exec: index out of bounds, the max size is {}, but index {} was got.", self.total, index)
99        }
100
101        // Calculate target
102        let base = HEADER_SIZE;
103        let target = base + index * SECTION_SIZE;
104
105        // Get and convert
106        let buf = &self.buf[target..target + SECTION_SIZE];
107        unsafe { &*(buf.as_ptr() as *const Section) }
108    }
109}