Skip to main content

proka_exec/
sections.rs

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