From 55a0154eace0a852958c40b796206156cad116f9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 19 Aug 2016 07:57:24 -0600 Subject: [PATCH] Switch to goblin as executable parser --- Cargo.toml | 6 +++ arch/x86_64/src/elf.rs | 92 ------------------------------------ arch/x86_64/src/lib.rs | 3 -- kernel/elf.rs | 105 ++++++++--------------------------------- kernel/lib.rs | 1 + 5 files changed, 26 insertions(+), 181 deletions(-) delete mode 100644 arch/x86_64/src/elf.rs diff --git a/Cargo.toml b/Cargo.toml index 1c1afdc..e16f9c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,12 @@ crate-type = ["staticlib"] bitflags = "*" spin = "*" +[dependencies.goblin] +git = "https://github.com/m4b/goblin.git" +crate-type = ["lib"] +default-features = false +features = ["no_mach", "no_mach32", "no_pe", "no_pe32", "no_endian_fd", "pure"] + [dev-dependencies] arch_test = { path = "arch/test" } diff --git a/arch/x86_64/src/elf.rs b/arch/x86_64/src/elf.rs deleted file mode 100644 index 3d2b7e4..0000000 --- a/arch/x86_64/src/elf.rs +++ /dev/null @@ -1,92 +0,0 @@ -pub const ELF_CLASS: u8 = 2; -pub type ElfAddr = u64; -pub type ElfOff = u64; -pub type ElfHalf = u16; -pub type ElfWord = u32; -pub type ElfXword = u64; - -/// An ELF header -#[repr(packed)] -#[derive(Debug)] -pub struct ElfHeader { - /// The "magic number" (4 bytes) - pub magic: [u8; 4], - /// 64 or 32 bit? - pub class: u8, - /// Little (1) or big endianness (2)? - pub endian: u8, - /// The ELF version (set to 1 for default) - pub ver: u8, - /// Operating system ABI (0x03 for Linux) - pub abi: [u8; 2], - /// Unused - pub pad: [u8; 7], - /// Specify whether the object is relocatable, executable, shared, or core (in order). - pub _type: ElfHalf, - /// Instruction set archcitecture - pub machine: ElfHalf, - /// Second version - pub ver_2: ElfWord, - /// The ELF entry - pub entry: ElfAddr, - /// The program header table offset - pub ph_off: ElfOff, - /// The section header table offset - pub sh_off: ElfOff, - /// The flags set - pub flags: ElfWord, - /// The header table length - pub h_len: ElfHalf, - /// The program header table entry length - pub ph_ent_len: ElfHalf, - /// The program head table length - pub ph_len: ElfHalf, - /// The section header table entry length - pub sh_ent_len: ElfHalf, - /// The section header table length - pub sh_len: ElfHalf, - /// The section header table string index - pub sh_str_index: ElfHalf, -} - -/// An ELF segment -#[repr(packed)] -#[derive(Debug)] -pub struct ElfSegment { - pub _type: ElfWord, - pub flags: ElfWord, - pub off: ElfOff, - pub vaddr: ElfAddr, - pub paddr: ElfAddr, - pub file_len: ElfXword, - pub mem_len: ElfXword, - pub align: ElfXword, -} - -/// An ELF section -#[repr(packed)] -#[derive(Debug)] -pub struct ElfSection { - pub name: ElfWord, - pub _type: ElfWord, - pub flags: ElfXword, - pub addr: ElfAddr, - pub off: ElfOff, - pub len: ElfXword, - pub link: ElfWord, - pub info: ElfWord, - pub addr_align: ElfXword, - pub ent_len: ElfXword, -} - -/// An ELF symbol -#[repr(packed)] -#[derive(Debug)] -pub struct ElfSymbol { - pub name: ElfWord, - pub info: u8, - pub other: u8, - pub sh_index: ElfHalf, - pub value: ElfAddr, - pub size: ElfXword, -} diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index ba2391d..e360614 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -119,9 +119,6 @@ macro_rules! interrupt_error { /// ACPI table parsing pub mod acpi; -/// ELF file handling -pub mod elf; - /// Memcpy, memmove, etc. pub mod externs; diff --git a/kernel/elf.rs b/kernel/elf.rs index c223bb1..a89e17f 100644 --- a/kernel/elf.rs +++ b/kernel/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/kernel/lib.rs b/kernel/lib.rs index 474c30e..9ce35de 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -90,6 +90,7 @@ extern crate collections; #[macro_use] extern crate bitflags; +extern crate goblin; extern crate spin; /// Context management