Skip to main content

proka_exec/
lib.rs

1//! # `proka-exec`
2//!
3//! [![Rust Nightly](https://img.shields.io/badge/rust-nightly-orange?style=flat-square&logo=rust)](https://www.rust-lang.org/)
4//! [![License: GPLv3](https://img.shields.io/badge/License-GPLv3-yellow.svg?style=flat-square)](https://opensource.org/license/gpl-3.0)
5//! [![GitHub Stars](https://img.shields.io/github/stars/RainSTR-Studio/proka-exec?style=flat-square)](https://github.com/RainSTR-Studio/proka-exec/stargazers)
6//! [![GitHub Issues](https://img.shields.io/github/issues/RainSTR-Studio/proka-exec?style=flat-square)](https://github.com/RainSTR-Studio/proka-exec/issues)
7//! [![GitHub Pull Requests](https://img.shields.io/github/issues-pr/RainSTR-Studio/proka-exec?style=flat-square)](https://github.com/RainSTR-Studio/proka-exec/pulls)
8//! [![Documentation](https://img.shields.io/badge/docs-prokadoc-brightgreen?style=flat-square)](https://prokadoc.pages.dev/)
9//!
10//! Copyright (C) 2026 RainSTR Studio. All rights reserved.
11//!
12//! ---
13//!
14//! ## Introduction
15//! This crate provides the definitions of headers, section
16//! entrys, and some utils to help you parse the executable
17//! easily.
18//!
19//! ## Steps to use this crate
20//! Before you parse it, you should do these steps:
21//!
22//! - Read the executable file content;
23//! - Make this file's content to a slice (`&'static [u8]`)
24//! - Use [`Parser`] to parse the executable.
25//!
26//! After this, you can do further operations through this parser by
27//! calling its functions.
28//!
29//! ### Note
30//! If you want to do minimal reading, you can just read the header and
31//! section table, other content can be read later;
32//!
33//! Make sure you have read the header and each sections, and they are **NOT** optional!!!
34//!
35//! # LICENSE
36//! This crate is under license [GPL-v3](https://github.com/RainSTR-Studio/proka-exec/blob/main/LICENSE),
37//! and you must follow its rules.
38//!
39//! See [LICENSE](https://github.com/RainSTR-Studio/proka-exec/blob/main/LICENSE) file for more details.
40//!
41//! ## MSRV
42//! This crate's MSRV is `1.85.0` stable.
43#![no_std]
44
45pub mod header;
46pub mod sections;
47pub mod utils;
48
49use header::Header;
50use sections::{Section, SectionIter};
51pub use utils::*;
52
53/// The header size.
54pub const HEADER_SIZE: usize = core::mem::size_of::<Header>();
55
56/// The section entry size
57pub const SECTION_SIZE: usize = core::mem::size_of::<Section>();
58
59/// The parser of the proka executable.
60///
61/// # Usage
62/// To use this parser, you must put an slice into the initializations.
63///
64/// If the content of the proka executable is in memory, the best way
65/// is to use `core::slice::from_raw_parts`.
66#[derive(Debug, Clone, Copy)]
67pub struct Parser {
68    buf: &'static [u8],
69    header: Header,
70    total_sections: u16,
71}
72
73impl Parser {
74    /// Initialize the parser by passing an slice.
75    ///
76    /// # Safety
77    /// You must ensure these before invoking this function:
78    ///
79    ///  - The slice's content is a valid executable;
80    ///  - The slice's pointer is accessable and mapped;
81    ///  - The slice's length is larger than 128 bytes.
82    ///
83    /// If this crate has used by kernel, you need to do mapping
84    /// first, and invoke this.
85    pub unsafe fn init(buf: &'static [u8]) -> Result<Self, Error> {
86        let header_raw = &buf[0..HEADER_SIZE]; // Header length
87        let header = unsafe { *(header_raw.as_ptr() as *const Header) };
88
89        // Check: Validate is this correct executable
90        if !header.validate() {
91            return Err(Error::NotValidExecutable);
92        }
93
94        Ok(Self {
95            buf,
96            header,
97            total_sections: header.sections,
98        })
99    }
100
101    /// Get the header.
102    #[inline]
103    pub fn header(&self) -> Header {
104        self.header
105    }
106
107    /// Get each section table.
108    #[allow(private_interfaces)]
109    pub fn sections(&self) -> SectionIter {
110        SectionIter {
111            buf: self.buf,
112            total: self.total_sections,
113            current: 0,
114        }
115    }
116}
117
118/// The error type of parsing header.
119#[repr(C)]
120#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121pub enum Error {
122    /// The executable is not valid.
123    NotValidExecutable,
124
125    /// An unknown character in UTF-8 was found in
126    /// parsing arrays
127    UnknownCharacter,
128}