1#![warn(missing_docs)]
2
3use std::error::Error;
9use std::fmt::{ Display, Formatter };
10use std::io::{ Read, Seek, SeekFrom };
11use std::collections::HashMap;
12
13#[macro_use]
14mod macros;
15pub mod types;
16pub mod numeric;
17
18pub mod constants;
19
20use crate::types::*;
21
22pub type ParseElfResult<T> = std::result::Result<T, ParseElfError>;
24
25#[derive(Debug)]
29pub enum ParseElfError {
30 IoError{
32 inner: std::io::Error
34 },
35
36 #[allow(missing_docs)]
37 InvalidSectionType(u32),
38
39 #[allow(missing_docs)]
40 InvalidProgramFlags(u32),
41
42 #[allow(missing_docs)]
43 InvalidProgramHeader(u32),
44
45 #[allow(missing_docs)]
46 InvalidVersion(u32),
47
48 #[allow(missing_docs)]
49 InvalidMachine(u16),
50
51 #[allow(missing_docs)]
52 InvalidElfType(u16),
53
54 #[allow(missing_docs)]
55 InvalidOsAbi(u8),
56
57 #[allow(missing_docs)]
58 InvalidIdentVersion(u8),
59
60 #[allow(missing_docs)]
61 InvalidDataFormat(u8),
62
63 #[allow(missing_docs)]
64 InvalidDataClass(u8),
65
66 InvalidParsingDescriptor,
70}
71
72impl Error for ParseElfError {
73 fn source(&self) -> Option<&(dyn Error + 'static)> {
74 match self {
75 ParseElfError::IoError{ inner } => Some(inner),
76 _ => None,
77 }
78 }
79}
80
81impl Display for ParseElfError {
82 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
83 write!(f, "{:?}", self)
84 }
85}
86
87impl From<std::io::Error> for ParseElfError {
88 fn from(err: std::io::Error) -> ParseElfError {
89 ParseElfError::IoError{ inner: err }
90 }
91}
92
93trait Parslet {
95 fn parse<R: Read + Seek>(reader: &mut R, descriptor: &mut Descriptor) -> ParseElfResult<Self> where Self: Sized;
96}
97
98enum Descriptor {
104 None,
105 Data{ format: DataFormat, class: DataClass },
106}
107
108impl Descriptor {
109 fn data_class(&self) -> ParseElfResult<DataClass> {
110 match self {
111 Descriptor::Data{ class, .. } => Ok(*class),
112 Descriptor::None => Err(ParseElfError::InvalidParsingDescriptor),
113 }
114 }
115
116 fn data_format(&self) -> ParseElfResult<DataFormat> {
117 match self {
118 Descriptor::Data{ format, .. } => Ok(*format),
119 Descriptor::None => Err(ParseElfError::InvalidParsingDescriptor)
120 }
121 }
122}
123
124
125#[derive(Debug)]
130pub struct Elf {
131 header: ElfHeader,
132 sections: Vec<Section>,
133 segments: Vec<Segment>,
134 section_map: HashMap<String, usize>,
135}
136
137impl Elf {
138 pub fn load<P: AsRef<std::path::Path>>(path: P) -> ParseElfResult<Elf> {
150 let file = std::fs::File::open(path)?;
151 let mut buf = std::io::BufReader::new(file);
152
153 Ok(Elf::parse(&mut buf)?)
154 }
155
156 pub fn parse<R: Read + Seek>(reader: &mut R) -> ParseElfResult<Elf> {
172 let mut descriptor = Descriptor::None;
173
174 let header = ElfHeader::parse(reader, &mut descriptor)?;
175 let sections = parse_sections(reader, &mut descriptor, &header)?;
176 let segments = parse_segments(reader, &mut descriptor, &header)?;
177 let mut section_map = HashMap::new();
178
179 associate_string_table(&mut section_map, §ions, &header);
180
181 Ok(Elf{
182 header,
183 sections,
184 segments,
185 section_map
186 })
187 }
188
189 pub fn try_get_section(&self, section_name: &str) -> Option<&Section> {
201 self.sections.get(*self.section_map.get(section_name)?)
202 }
203
204 pub fn header(&self) -> &ElfHeader {
206 &self.header
207 }
208
209 pub fn sections(&self) -> SectionIter {
211 SectionIter {
212 elf: &self,
213 idx: 0
214 }
215 }
216
217 pub fn segments(&self) -> SegmentIter {
219 SegmentIter {
220 elf: &self,
221 idx: 0
222 }
223 }
224}
225
226fn parse_sections<R: Read + Seek>(reader: &mut R, descriptor: &mut Descriptor, header: &ElfHeader) -> ParseElfResult<Vec<Section>> {
228 reader.seek(SeekFrom::Start(header.section_headers_offset()))?;
229 let mut sections = Vec::new();
230 for _ in 0..header.section_header_count() {
231 sections.push(Section::parse(reader, descriptor)?)
232 }
233 Ok(sections)
234}
235
236fn parse_segments<R: Read + Seek>(reader: &mut R, descriptor: &mut Descriptor, header: &ElfHeader) -> ParseElfResult<Vec<Segment>> {
237 reader.seek(SeekFrom::Start(header.program_headers_offset()))?;
238 let mut segments = Vec::new();
239 for _ in 0..header.program_header_count() {
240 segments.push(Segment::parse(reader, descriptor)?)
241 }
242 Ok(segments)
243}
244
245fn associate_string_table(section_map: &mut HashMap<String, usize>, sections: &[Section], header: &ElfHeader) {
246 if let Some(idx) = header.section_name_table_index() {
247 if let SectionData::Strings(table) = §ions[idx].data() {
248 for (i, _section) in sections.iter().enumerate() {
249 let name = table[i].clone();
250 section_map.insert(name, i);
251 }
252 }
253 }
254}
255
256pub struct SectionIter<'a> {
258 elf: &'a Elf,
259 idx: usize,
260}
261
262impl<'a> Iterator for SectionIter<'a> {
263 type Item = &'a Section;
264
265 fn next(&mut self) -> Option<Self::Item> {
266 let item = self.elf.sections.get(self.idx)?;
267 self.idx += 1;
268 Some(item)
269 }
270}
271
272pub struct SegmentIter<'a> {
274 elf: &'a Elf,
275 idx: usize,
276}
277
278impl<'a> Iterator for SegmentIter<'a> {
279 type Item = &'a Segment;
280
281 fn next(&mut self) -> Option<Self::Item> {
282 let item = self.elf.segments.get(self.idx)?;
283 self.idx += 1;
284 Some(item)
285 }
286}
287
288pub mod prelude {
290 pub use crate::numeric::*;
291 pub use crate::types::*;
292 pub use crate::Elf;
293}
294
295#[cfg(test)]
296mod test {
297 use super::*;
298
299 fn _load_example_binary() -> Elf {
300 let elf = Elf::load("examples/example-binary").unwrap();
301 elf
302 }
303
304 #[test]
305 fn get_section_bytes() {
306 let elf = _load_example_binary();
307 let text = elf.try_get_section(".text").unwrap();
308
309 if let SectionData::Bytes(_bytes) = text.data() {
310 }
312 }
313
314 #[test]
315 fn section_iters() {
316 let elf = _load_example_binary();
317
318 for (i, s) in elf.sections().enumerate() {
319 match i {
320 0 => assert_eq!(s.header().section_type(), SectionType::Null),
321 2 => assert_eq!(s.header().section_type(), SectionType::ProgramData),
322 5 => assert_eq!(s.header().section_type(), SectionType::SymbolTable),
323 6 => assert_eq!(s.header().section_type(), SectionType::StringTable),
324 _ => continue
325 }
326 }
327 }
328
329 #[test]
330 fn segment_iters() {
331 let elf = _load_example_binary();
332
333 println!("{:#?}", elf);
334
335 for (i, h) in elf.segments().enumerate() {
336 match i {
337 0 => assert_eq!(h.header().program_header_type(), ProgramHeaderType::Phdr),
338 1 => assert_eq!(h.header().program_header_type(), ProgramHeaderType::Loadable),
339 2 => assert_eq!(h.header().program_header_type(), ProgramHeaderType::Loadable),
340 3 => assert_eq!(h.header().program_header_type(), ProgramHeaderType::GnuStack),
341 4 => assert_eq!(h.header().program_header_type(), ProgramHeaderType::ArmExidx),
342 _ => continue
343 }
344 }
345 }
346}