kernel_elf_parser/
info.rs1use alloc::vec::Vec;
4use core::ops::Range;
5
6use xmas_elf::{
7 header::Class,
8 program::{ProgramHeader32, ProgramHeader64},
9};
10
11use crate::auxv::{AuxEntry, AuxType};
12
13pub struct ELFHeadersBuilder<'a>(ELFHeaders<'a>);
14impl<'a> ELFHeadersBuilder<'a> {
15 pub fn new(input: &'a [u8]) -> Result<Self, &'static str> {
16 Ok(Self(ELFHeaders {
17 header: xmas_elf::header::parse_header(input)?,
18 ph: Vec::new(),
19 }))
20 }
21
22 pub fn ph_range(&self) -> Range<u64> {
23 let start = self.0.header.pt2.ph_offset();
24 let size = self.0.header.pt2.ph_entry_size() as u64 * self.0.header.pt2.ph_count() as u64;
25 start..start + size
26 }
27
28 pub fn build(mut self, ph: &[u8]) -> Result<ELFHeaders<'a>, &'static str> {
29 self.0.ph = ph
30 .chunks_exact(self.0.header.pt2.ph_entry_size() as usize)
31 .map(|chunk| match self.0.header.pt1.class() {
32 Class::ThirtyTwo => {
33 let ph: &ProgramHeader32 = zero::read(chunk);
34 ProgramHeader64 {
35 type_: ph.type_,
36 offset: ph.offset as _,
37 virtual_addr: ph.virtual_addr as _,
38 physical_addr: ph.physical_addr as _,
39 file_size: ph.file_size as _,
40 mem_size: ph.mem_size as _,
41 flags: ph.flags,
42 align: ph.align as _,
43 }
44 }
45 Class::SixtyFour => *zero::read(chunk),
46 Class::None | Class::Other(_) => unreachable!(),
47 })
48 .collect();
49 Ok(self.0)
50 }
51}
52
53pub struct ELFHeaders<'a> {
54 pub header: xmas_elf::header::Header<'a>,
55 pub ph: Vec<ProgramHeader64>,
56}
57
58pub struct ELFParser<'a> {
60 headers: &'a ELFHeaders<'a>,
61 base: usize,
63}
64
65impl<'a> ELFParser<'a> {
66 pub fn new(headers: &'a ELFHeaders<'a>, bias: usize) -> Result<Self, &'static str> {
68 let base = if headers.header.pt2.type_().as_type() == xmas_elf::header::Type::SharedObject {
69 bias
70 } else {
71 0
72 };
73 Ok(Self { headers, base })
74 }
75
76 pub fn entry(&self) -> usize {
78 self.headers.header.pt2.entry_point() as usize + self.base
80 }
81
82 pub fn phnum(&self) -> usize {
84 self.headers.header.pt2.ph_count() as usize
85 }
86
87 pub fn phent(&self) -> usize {
89 self.headers.header.pt2.ph_entry_size() as usize
90 }
91
92 pub fn phdr(&self) -> usize {
94 let ph_offset = self.headers.header.pt2.ph_offset() as usize;
95 let header = self
96 .headers
97 .ph
98 .iter()
99 .find(|header| {
100 (header.offset..header.offset + header.file_size).contains(&(ph_offset as u64))
101 })
102 .expect("can not find program header table address in elf");
103 ph_offset - header.offset as usize + header.virtual_addr as usize + self.base
104 }
105
106 pub fn base(&self) -> usize {
108 self.base
109 }
110
111 pub fn headers(&self) -> &'a ELFHeaders<'a> {
112 self.headers
113 }
114
115 pub fn aux_vector(
124 &self,
125 pagesz: usize,
126 ldso_base: Option<usize>,
127 ) -> impl Iterator<Item = AuxEntry> {
128 [
129 (AuxType::PHDR, self.phdr()),
130 (AuxType::PHENT, self.phent()),
131 (AuxType::PHNUM, self.phnum()),
132 (AuxType::PAGESZ, pagesz),
133 (AuxType::ENTRY, self.entry()),
134 ]
135 .into_iter()
136 .chain(ldso_base.into_iter().map(|base| (AuxType::BASE, base)))
137 .map(|(at, val)| AuxEntry::new(at, val))
138 }
139}