1use crate::context::PropU32;
2use crate::context::*;
3use crate::elf::Variant;
4use crate::utils::{as_offset, read, read_n, Pod};
5use core::marker::PhantomData;
6
7#[derive(Debug, Clone)]
8pub enum ParseProgramsError {
9 BrokenHeaders,
10 BadPropertyPhentsize,
11}
12
13#[derive(Debug, Clone)]
14pub enum ParseProgramError {
15 BadPropertyType,
16 BrokenContent,
17}
18
19#[derive(Debug, Clone, Copy)]
20pub struct Programs<'a, T: Context> {
21 data: &'a [u8],
22 offset: usize,
23 num: u16,
24 _maker: PhantomData<T>,
25}
26
27impl<'a, T: Context> Programs<'a, T> {
28 pub fn parse(elf: Variant<'a, T>) -> Result<Option<Programs<'a, T>>, ParseProgramsError> {
29 use ParseProgramsError::*;
30 let data = elf.data();
31 let offset = as_offset::<T>(elf.header().phoff()).ok_or(BrokenHeaders)?;
32 if offset == 0 {
33 return Ok(None);
34 }
35 if elf.header().phentsize() as usize != core::mem::size_of::<ProgramHeader<T>>() {
36 return Err(BadPropertyPhentsize);
37 }
38 let num = elf.header().phnum();
39 read_n::<ProgramHeader<T>>(data, offset, num as usize).ok_or(BrokenHeaders)?;
40 Ok(Some(Self {
41 data,
42 offset,
43 num,
44 _maker: PhantomData,
45 }))
46 }
47 pub fn num(&self) -> u16 {
48 self.num
49 }
50}
51
52pub struct Program<'a, T: Context> {
53 pheader: &'a ProgramHeader<T>,
54 content: &'a [u8],
55}
56
57impl<'a, T: Context> Program<'a, T> {
58 pub fn parse(programs: Programs<'a, T>, index: u16) -> Option<Result<Self, ParseProgramError>> {
59 use ParseProgramError::*;
60 use ProgramType::*;
61 if index >= programs.num {
62 return None;
63 }
64 let offset = programs.offset + index as usize * core::mem::size_of::<ProgramHeader<T>>();
65 fn helper<'a, T: Context>(
66 programs: Programs<'a, T>,
67 offset: usize,
68 ) -> Result<Program<'a, T>, ParseProgramError> {
69 let pheader: &'a ProgramHeader<T> = read(programs.data, offset).unwrap();
70 let typa = pheader.checked_type().ok_or(BadPropertyType)?;
71 if let Null = typa {
72 return Ok(Program {
73 pheader,
74 content: &[],
75 });
76 }
77 let content_offset = as_offset::<T>(pheader.offset()).ok_or(BrokenContent)?;
78 let content_size = as_offset::<T>(pheader.filesz()).ok_or(BrokenContent)?;
79 let content =
80 read_n::<u8>(programs.data, content_offset, content_size).ok_or(BrokenContent)?;
81 Ok(Program { pheader, content })
82 }
83 Some(helper(programs, offset))
84 }
85 pub fn header(&self) -> &'a ProgramHeader<T> {
86 self.pheader
87 }
88 pub fn content(&self) -> &'a [u8] {
89 self.content
90 }
91}
92
93#[repr(C)]
94#[derive(Debug, Clone)]
95pub struct ProgramHeader<T: Context> {
96 pub typa: PropU32,
97 pub flags64: T::PropU32If64,
98 pub offset: T::PropUsize,
99 pub vaddr: T::PropUsize,
100 pub paddr: T::PropUsize,
101 pub filesz: T::PropUsize,
102 pub memsz: T::PropUsize,
103 pub flags32: T::PropU32If32,
104 pub align: T::PropUsize,
105}
106
107impl<T: Context> ProgramHeader<T> {
108 pub fn checked_type(&self) -> Option<ProgramType> {
109 ProgramType::try_from(T::interpret(self.typa)).ok()
110 }
111 pub fn typa(&self) -> ProgramType {
115 self.checked_type().unwrap()
116 }
117 pub fn flags(&self) -> ProgramFlags {
118 T::interpret((self.flags32, self.flags64)).into()
119 }
120 pub fn offset(&self) -> T::Integer {
121 T::interpret(self.offset)
122 }
123 pub fn vaddr(&self) -> T::Integer {
124 T::interpret(self.vaddr)
125 }
126 pub fn paddr(&self) -> T::Integer {
127 T::interpret(self.paddr)
128 }
129 pub fn filesz(&self) -> T::Integer {
130 T::interpret(self.filesz)
131 }
132 pub fn memsz(&self) -> T::Integer {
133 T::interpret(self.memsz)
134 }
135 pub fn align(&self) -> T::Integer {
136 T::interpret(self.align)
137 }
138}
139
140unsafe impl<T: Context> Pod for ProgramHeader<T> {}
141
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143pub enum ProgramType {
144 Null,
146 Load,
148 Dynamic,
150 Interp,
152 Note,
154 Shlib,
156 Phdr,
158 Tls,
160 OsSpecific(u32),
162 ProcessorSpecific(u32),
164}
165
166impl TryFrom<u32> for ProgramType {
167 type Error = ();
168
169 fn try_from(value: u32) -> Result<Self, Self::Error> {
170 use ProgramType::*;
171 match value {
172 0 => Ok(Null),
173 1 => Ok(Load),
174 2 => Ok(Dynamic),
175 3 => Ok(Interp),
176 4 => Ok(Note),
177 5 => Ok(Shlib),
178 6 => Ok(Phdr),
179 7 => Ok(Tls),
180 x @ 0x60000000..=0x6FFFFFFF => Ok(OsSpecific(x)),
181 x @ 0x70000000..=0x7FFFFFFF => Ok(ProcessorSpecific(x)),
182 _ => Err(()),
183 }
184 }
185}
186
187impl From<ProgramType> for u32 {
188 fn from(value: ProgramType) -> Self {
189 use ProgramType::*;
190 match value {
191 Null => 0,
192 Load => 1,
193 Dynamic => 2,
194 Interp => 3,
195 Note => 4,
196 Shlib => 5,
197 Phdr => 6,
198 Tls => 7,
199 OsSpecific(x) => x,
200 ProcessorSpecific(x) => x,
201 }
202 }
203}
204
205#[derive(Debug, Clone, Copy, PartialEq, Eq, From, Into, BitXor, BitAnd, BitOr, LowerHex)]
206pub struct ProgramFlags(pub u32);
207
208impl ProgramFlags {
209 pub const EXECUTE: Self = Self(0x1);
211 pub const WRITE: Self = Self(0x2);
213 pub const READ: Self = Self(0x4);
215 pub const MASKOS: Self = Self(0x0ff00000);
217 pub const MASKPROCESSOR: Self = Self(0xf0000000);
219}