diff --git a/elf.rs b/elf.rs index c223bb1..a89e17f 100644 --- a/elf.rs +++ b/elf.rs @@ -2,9 +2,13 @@ use collections::{String, Vec}; -use core::{mem, ptr, str, slice}; +use core::{ptr, str}; -pub use arch::elf::*; +#[cfg(target_arch = "x86")] +use goblin::elf32::{header, program_header}; + +#[cfg(target_arch = "x86_64")] +use goblin::elf64::{header, program_header}; /// An ELF executable pub struct Elf<'a> { @@ -14,26 +18,26 @@ pub struct Elf<'a> { impl<'a> Elf<'a> { /// Create a ELF executable from data pub fn from(data: &'a [u8]) -> Result, String> { - if data.len() < mem::size_of::() { - Err(format!("Elf: Not enough data: {} < {}", data.len(), mem::size_of::())) - } else if &data[..4] != b"\x7FELF" { - Err(format!("Elf: Invalid magic: {:?} != {:?}", &data[..4], b"\x7FELF")) - } else if data.get(4) != Some(&ELF_CLASS) { - Err(format!("Elf: Invalid architecture: {:?} != {:?}", data.get(4), Some(&ELF_CLASS))) + if data.len() < header::SIZEOF_EHDR { + Err(format!("Elf: Not enough data: {} < {}", data.len(), header::SIZEOF_EHDR)) + } else if &data[..header::SELFMAG] != header::ELFMAG { + Err(format!("Elf: Invalid magic: {:?} != {:?}", &data[..4], header::ELFMAG)) + } else if data.get(header::EI_CLASS) != Some(&header::ELFCLASS) { + Err(format!("Elf: Invalid architecture: {:?} != {:?}", data.get(header::EI_CLASS), header::ELFCLASS)) } else { Ok(Elf { data: data }) } } - pub unsafe fn load_segments(&self) -> Vec { + pub unsafe fn load_segments(&self) -> Vec { let mut segments = Vec::new(); - let header = &*(self.data.as_ptr() as usize as *const ElfHeader); + let header = &*(self.data.as_ptr() as usize as *const header::Header); - for i in 0..header.ph_len { - let segment = ptr::read((self.data.as_ptr() as usize + header.ph_off as usize + i as usize * header.ph_ent_len as usize) as *const ElfSegment); + for i in 0..header.e_phnum { + let segment = ptr::read((self.data.as_ptr() as usize + header.e_phoff as usize + i as usize * header.e_phentsize as usize) as *const program_header::ProgramHeader); - if segment._type == 1 || segment._type == 7 { + if segment.p_type == program_header::PT_LOAD || segment.p_type == program_header::PT_TLS { segments.push(segment); } } @@ -43,78 +47,7 @@ impl<'a> Elf<'a> { /// Get the entry field of the header pub unsafe fn entry(&self) -> usize { - let header = &*(self.data.as_ptr() as usize as *const ElfHeader); - header.entry as usize - } - - /// ELF symbol - pub unsafe fn symbol(&self, name: &str) -> usize { - let header = &*(self.data.as_ptr() as usize as *const ElfHeader); - - let sh_str_section = - &*((self.data.as_ptr() as usize + header.sh_off as usize + - header.sh_str_index as usize * - header.sh_ent_len as usize) as *const ElfSection); - - let mut sym_section = &*((self.data.as_ptr() as usize + header.sh_off as usize) as *const ElfSection); - - let mut str_section = &*((self.data.as_ptr() as usize + header.sh_off as usize) as *const ElfSection); - - for i in 0..header.sh_len { - let section = - &*((self.data.as_ptr() as usize + header.sh_off as usize + - i as usize * - header.sh_ent_len as usize) as *const ElfSection); - - let section_name_ptr = - (self.data.as_ptr() as usize + sh_str_section.off as usize + section.name as usize) as *const u8; - let mut section_name_len = 0; - for j in 0..4096 { - section_name_len = j; - if ptr::read(section_name_ptr.offset(j)) == 0 { - break; - } - } - let section_name = - str::from_utf8_unchecked(slice::from_raw_parts(section_name_ptr, - section_name_len as usize)); - - if section_name == ".symtab" { - sym_section = section; - } else if section_name == ".strtab" { - str_section = section; - } - } - - if sym_section.off > 0 && str_section.off > 0 { - if sym_section.ent_len > 0 { - let len = sym_section.len / sym_section.ent_len; - for i in 0..len { - let symbol = &*((self.data.as_ptr() as usize + sym_section.off as usize + i as usize * sym_section.ent_len as usize) as *const ElfSymbol); - - let symbol_name_ptr = - (self.data.as_ptr() as usize + str_section.off as usize + - symbol.name as usize) as *const u8; - let mut symbol_name_len = 0; - for j in 0..4096 { - symbol_name_len = j; - if ptr::read(symbol_name_ptr.offset(j)) == 0 { - break; - } - } - let symbol_name = str::from_utf8_unchecked(slice::from_raw_parts(symbol_name_ptr, symbol_name_len as usize)); - - if name == symbol_name { - return symbol.value as usize; - } - } - } else { - print!("No sym_section ent len\n"); - } - } else { - print!("No sym_section or str_section\n"); - } - - 0 + let header = &*(self.data.as_ptr() as usize as *const header::Header); + header.e_entry as usize } } diff --git a/lib.rs b/lib.rs index 474c30e..9ce35de 100644 --- a/lib.rs +++ b/lib.rs @@ -90,6 +90,7 @@ extern crate collections; #[macro_use] extern crate bitflags; +extern crate goblin; extern crate spin; /// Context management