Switch to goblin as executable parser

This commit is contained in:
Jeremy Soller 2016-08-19 07:57:24 -06:00
parent 5588c38178
commit 55a0154eac
5 changed files with 26 additions and 181 deletions

View file

@ -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<Elf<'a>, String> {
if data.len() < mem::size_of::<ElfHeader>() {
Err(format!("Elf: Not enough data: {} < {}", data.len(), mem::size_of::<ElfHeader>()))
} 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<ElfSegment> {
pub unsafe fn load_segments(&self) -> Vec<program_header::ProgramHeader> {
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
}
}

View file

@ -90,6 +90,7 @@ extern crate collections;
#[macro_use]
extern crate bitflags;
extern crate goblin;
extern crate spin;
/// Context management