kernel_elf_parser/
info.rs1extern crate alloc;
5use alloc::vec::Vec;
6
7use memory_addr::VirtAddr;
8use page_table_entry::MappingFlags;
9
10use crate::auxv::{AuxvEntry, AuxvType};
11
12pub struct ELFPH {
16 pub offset: usize,
18 pub vaddr: VirtAddr,
20 pub memsz: u64,
22 pub filesz: u64,
24 pub flags: MappingFlags,
26}
27
28pub struct ELFParser<'a> {
30 elf: &'a xmas_elf::ElfFile<'a>,
31 base: usize,
33}
34
35impl<'a> ELFParser<'a> {
36 fn elf_base_addr(elf: &xmas_elf::ElfFile, interp_base: usize) -> Result<usize, &'static str> {
37 match elf.header.pt2.type_().as_type() {
38 xmas_elf::header::Type::Executable => Ok(0),
40 xmas_elf::header::Type::SharedObject => {
42 match elf
43 .program_iter()
44 .filter(|ph| ph.get_type() == Ok(xmas_elf::program::Type::Interp))
45 .count()
46 {
47 0 => Ok(interp_base),
49 1 => Ok(0),
51 _ => Err("Multiple interpreters found"),
52 }
53 }
54 _ => Err("Unsupported ELF type"),
55 }
56 }
57
58 pub fn new(
68 elf: &'a xmas_elf::ElfFile,
69 interp_base: usize,
70 bias: Option<isize>,
71 uspace_base: usize,
72 ) -> Result<Self, &'static str> {
73 if elf.header.pt1.magic.as_slice() != b"\x7fELF" {
74 return Err("invalid elf!");
75 }
76
77 let is_pie = elf.header.pt2.type_().as_type() == xmas_elf::header::Type::SharedObject
79 || (elf.header.pt2.type_().as_type() == xmas_elf::header::Type::Executable
80 && elf
81 .program_iter()
82 .any(|ph| ph.get_type() == Ok(xmas_elf::program::Type::Interp)));
83
84 if !is_pie
86 && elf.program_iter().any(|ph| {
87 ph.get_type() == Ok(xmas_elf::program::Type::Load)
88 && ph.virtual_addr() < uspace_base as u64
89 })
90 {
91 return Err("Invalid ELF base address");
92 }
93
94 let mut base = Self::elf_base_addr(elf, interp_base)?;
95 if is_pie {
96 base = base.wrapping_add(bias.unwrap_or(0) as usize);
97 }
98 Ok(Self { elf, base })
99 }
100
101 pub fn entry(&self) -> usize {
103 self.elf.header.pt2.entry_point() as usize + self.base
104 }
105
106 pub fn phnum(&self) -> usize {
108 self.elf.header.pt2.ph_count() as usize
109 }
110
111 pub fn phent(&self) -> usize {
113 self.elf.header.pt2.ph_entry_size() as usize
114 }
115
116 pub fn phdr(&self) -> usize {
118 self.elf.header.pt2.ph_offset() as usize
119 + self.base
120 + self
121 .elf
122 .program_iter()
123 .find(|ph| ph.get_type() == Ok(xmas_elf::program::Type::Load))
124 .map(|ph| ph.virtual_addr() as usize)
125 .unwrap_or(0)
126 }
127
128 pub fn base(&self) -> usize {
130 self.base
131 }
132
133 pub fn elf(&self) -> &xmas_elf::ElfFile {
135 self.elf
136 }
137
138 pub fn auxv_vector(&self, pagesz: usize) -> [AuxvEntry; 17] {
146 [
147 AuxvEntry::new(AuxvType::PHDR, self.phdr()),
148 AuxvEntry::new(AuxvType::PHENT, self.phent()),
149 AuxvEntry::new(AuxvType::PHNUM, self.phnum()),
150 AuxvEntry::new(AuxvType::PAGESZ, pagesz),
151 AuxvEntry::new(AuxvType::BASE, self.base()),
152 AuxvEntry::new(AuxvType::FLAGS, 0),
153 AuxvEntry::new(AuxvType::ENTRY, self.entry()),
154 AuxvEntry::new(AuxvType::HWCAP, 0),
155 AuxvEntry::new(AuxvType::CLKTCK, 100),
156 AuxvEntry::new(AuxvType::PLATFORM, 0),
157 AuxvEntry::new(AuxvType::UID, 0),
158 AuxvEntry::new(AuxvType::EUID, 0),
159 AuxvEntry::new(AuxvType::GID, 0),
160 AuxvEntry::new(AuxvType::EGID, 0),
161 AuxvEntry::new(AuxvType::RANDOM, 0),
162 AuxvEntry::new(AuxvType::EXECFN, 0),
163 AuxvEntry::new(AuxvType::NULL, 0),
164 ]
165 }
166
167 pub fn ph_load(&self) -> Vec<ELFPH> {
169 let mut segments = Vec::new();
170 self.elf
172 .program_iter()
173 .filter(|ph| ph.get_type() == Ok(xmas_elf::program::Type::Load))
174 .for_each(|ph| {
175 let start_va = ph.virtual_addr() as usize + self.base;
176 let start_offset = ph.offset() as usize;
177 let mut flags = MappingFlags::USER;
178 if ph.flags().is_read() {
179 flags |= MappingFlags::READ;
180 }
181 if ph.flags().is_write() {
182 flags |= MappingFlags::WRITE;
183 }
184 if ph.flags().is_execute() {
185 flags |= MappingFlags::EXECUTE;
186 }
187 segments.push(ELFPH {
188 offset: start_offset,
189 vaddr: VirtAddr::from(start_va),
190 memsz: ph.mem_size(),
191 filesz: ph.file_size(),
192 flags,
193 });
194 });
195 segments
196 }
197}