1use crate::{Error, HEADER_SIZE, Result, SECTION_HDR_SIZE, SECTION_INDEX_SIZE, slice_to_str};
3use bitflags::bitflags;
4use bytemuck::{Pod, Zeroable, bytes_of};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum SectionError {
9 LengthError,
13
14 BaseError(u32),
20
21 EntryOffsetOutOfRange(u32, u32),
27}
28
29#[repr(C)]
31#[derive(Debug, Clone, Copy, Pod, Zeroable)]
32pub struct SectionHdr {
33 pub flag: SectionFlag,
35
36 pub _pad1: [u8; 3],
38
39 pub base: u32,
41
42 pub size: u32,
44
45 pub _pad2: [u8; 4],
47}
48
49bitflags! {
50 #[repr(transparent)]
52 #[derive(Debug, Clone, Copy, Pod, Zeroable)]
53 pub struct SectionFlag: u8 {
54 const LOADABLE = 1;
56
57 const EXECABLE = 1 << 1;
59 }
60}
61
62impl SectionHdr {
63 #[inline]
65 pub fn to_array(&self) -> [u8; SECTION_HDR_SIZE] {
66 let mut arr = [0u8; SECTION_HDR_SIZE];
67 arr.copy_from_slice(bytes_of(self));
68 arr
69 }
70
71 #[inline]
73 pub fn validate(&self) -> Result<()> {
74 if self.size == 0 {
76 return Err(Error::SectionError(SectionError::LengthError));
77 }
78
79 Ok(())
80 }
81}
82
83#[repr(C)]
85#[derive(Debug, Clone, Copy, Pod, Zeroable)]
86pub struct SectionIndex {
87 pub base: u32,
89
90 pub name_len: u32,
92}
93
94impl SectionIndex {
95 #[inline]
97 pub fn to_array(&self) -> [u8; SECTION_INDEX_SIZE] {
98 let mut arr = [0u8; SECTION_INDEX_SIZE];
99 arr.copy_from_slice(bytes_of(self));
100 arr
101 }
102}
103
104#[derive(Debug, Clone, Copy)]
106pub struct SectionTable<'a> {
107 buf: &'a [u8],
108 total: u16,
109 current: u16,
110}
111
112impl<'a> SectionTable<'a> {
113 pub(crate) fn new(buf: &'a [u8], total: u16) -> Self {
115 Self {
116 buf,
117 total,
118 current: 0,
119 }
120 }
121
122 pub fn get(&self, index: usize) -> Option<SectionIndex> {
124 if index >= self.total as usize {
126 return None;
127 }
128
129 let offset = HEADER_SIZE + index * SECTION_INDEX_SIZE;
131 let slice = &self.buf[offset..offset + SECTION_INDEX_SIZE];
132
133 let mut section_index = SectionIndex::zeroed();
135 bytemuck::bytes_of_mut(&mut section_index).copy_from_slice(slice);
136 Some(section_index)
137 }
138
139 pub fn get_hdr_secindex(&self, section_index: SectionIndex) -> SectionHdr {
141 let offset = section_index.base as usize;
143 let slice = &self.buf[offset..offset + SECTION_HDR_SIZE];
144
145 let mut hdr = SectionHdr::zeroed();
147 bytemuck::bytes_of_mut(&mut hdr).copy_from_slice(slice);
148 hdr
149 }
150
151 pub fn get_hdr_idx(&self, index: usize) -> Option<SectionHdr> {
153 let section_index = self.get(index)?;
155 Some(self.get_hdr_secindex(section_index))
156 }
157
158 pub fn get_name_secindex(&self, section_index: SectionIndex) -> &str {
160 let offset = section_index.base as usize + SECTION_HDR_SIZE;
162 let content = &self.buf[offset..offset + section_index.name_len as usize];
163 slice_to_str(content).expect("Failed to get section's name")
164 }
165
166 pub fn get_name_idx(&self, index: usize) -> Option<&str> {
168 let section_index = self.get(index)?;
170 Some(self.get_name_secindex(section_index))
171 }
172}
173
174impl<'a> Iterator for SectionTable<'a> {
175 type Item = SectionIndex;
176
177 fn next(&mut self) -> Option<Self::Item> {
178 let result = self.get(self.current as usize)?;
179 self.current += 1;
180 Some(result)
181 }
182}
183
184#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[test]
190 fn test_header_length() {
191 assert_eq!(crate::SECTION_HDR_SIZE, 16);
192 assert_eq!(core::mem::size_of::<SectionHdr>(), 16)
193 }
194}