Switch to goblin as executable parser
This commit is contained in:
parent
5588c38178
commit
55a0154eac
|
@ -11,6 +11,12 @@ crate-type = ["staticlib"]
|
||||||
bitflags = "*"
|
bitflags = "*"
|
||||||
spin = "*"
|
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]
|
[dev-dependencies]
|
||||||
arch_test = { path = "arch/test" }
|
arch_test = { path = "arch/test" }
|
||||||
|
|
||||||
|
|
|
@ -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,
|
|
||||||
}
|
|
|
@ -119,9 +119,6 @@ macro_rules! interrupt_error {
|
||||||
/// ACPI table parsing
|
/// ACPI table parsing
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
|
|
||||||
/// ELF file handling
|
|
||||||
pub mod elf;
|
|
||||||
|
|
||||||
/// Memcpy, memmove, etc.
|
/// Memcpy, memmove, etc.
|
||||||
pub mod externs;
|
pub mod externs;
|
||||||
|
|
||||||
|
|
105
kernel/elf.rs
105
kernel/elf.rs
|
@ -2,9 +2,13 @@
|
||||||
|
|
||||||
use collections::{String, Vec};
|
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
|
/// An ELF executable
|
||||||
pub struct Elf<'a> {
|
pub struct Elf<'a> {
|
||||||
|
@ -14,26 +18,26 @@ pub struct Elf<'a> {
|
||||||
impl<'a> Elf<'a> {
|
impl<'a> Elf<'a> {
|
||||||
/// Create a ELF executable from data
|
/// Create a ELF executable from data
|
||||||
pub fn from(data: &'a [u8]) -> Result<Elf<'a>, String> {
|
pub fn from(data: &'a [u8]) -> Result<Elf<'a>, String> {
|
||||||
if data.len() < mem::size_of::<ElfHeader>() {
|
if data.len() < header::SIZEOF_EHDR {
|
||||||
Err(format!("Elf: Not enough data: {} < {}", data.len(), mem::size_of::<ElfHeader>()))
|
Err(format!("Elf: Not enough data: {} < {}", data.len(), header::SIZEOF_EHDR))
|
||||||
} else if &data[..4] != b"\x7FELF" {
|
} else if &data[..header::SELFMAG] != header::ELFMAG {
|
||||||
Err(format!("Elf: Invalid magic: {:?} != {:?}", &data[..4], b"\x7FELF"))
|
Err(format!("Elf: Invalid magic: {:?} != {:?}", &data[..4], header::ELFMAG))
|
||||||
} else if data.get(4) != Some(&ELF_CLASS) {
|
} else if data.get(header::EI_CLASS) != Some(&header::ELFCLASS) {
|
||||||
Err(format!("Elf: Invalid architecture: {:?} != {:?}", data.get(4), Some(&ELF_CLASS)))
|
Err(format!("Elf: Invalid architecture: {:?} != {:?}", data.get(header::EI_CLASS), header::ELFCLASS))
|
||||||
} else {
|
} else {
|
||||||
Ok(Elf { data: data })
|
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 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 {
|
for i in 0..header.e_phnum {
|
||||||
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);
|
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);
|
segments.push(segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,78 +47,7 @@ impl<'a> Elf<'a> {
|
||||||
|
|
||||||
/// Get the entry field of the header
|
/// Get the entry field of the header
|
||||||
pub unsafe fn entry(&self) -> usize {
|
pub unsafe fn entry(&self) -> usize {
|
||||||
let header = &*(self.data.as_ptr() as usize as *const ElfHeader);
|
let header = &*(self.data.as_ptr() as usize as *const header::Header);
|
||||||
header.entry as usize
|
header.e_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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ extern crate collections;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
|
extern crate goblin;
|
||||||
extern crate spin;
|
extern crate spin;
|
||||||
|
|
||||||
/// Context management
|
/// Context management
|
||||||
|
|
Loading…
Reference in a new issue