include!("constants_header.rs");
pub trait ElfHeader {
fn e_ident(&self) -> [u8; SIZEOF_IDENT];
fn e_type(&self) -> u16;
fn e_machine(&self) -> u16;
fn e_version(&self) -> u32;
fn e_entry(&self) -> u64;
fn e_phoff(&self) -> u64;
fn e_shoff(&self) -> u64;
fn e_flags(&self) -> u32;
fn e_ehsize(&self) -> u16;
fn e_phentsize(&self) -> u16;
fn e_phnum(&self) -> u16;
fn e_shentsize(&self) -> u16;
fn e_shnum(&self) -> u16;
fn e_shstrndx(&self) -> u16;
}
macro_rules! elf_header {
($size:ident) => {
#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct Header {
pub e_ident: [u8; SIZEOF_IDENT],
pub e_type: u16,
pub e_machine: u16,
pub e_version: u32,
pub e_entry: $size,
pub e_phoff: $size,
pub e_shoff: $size,
pub e_flags: u32,
pub e_ehsize: u16,
pub e_phentsize: u16,
pub e_phnum: u16,
pub e_shentsize: u16,
pub e_shnum: u16,
pub e_shstrndx: u16,
}
}
}
pub const ET_NONE: u16 = 0;
pub const ET_REL: u16 = 1;
pub const ET_EXEC: u16 = 2;
pub const ET_DYN: u16 = 3;
pub const ET_CORE: u16 = 4;
pub const ET_NUM: u16 = 5;
pub const ELFMAG: &'static [u8; 4] = b"\x7FELF";
pub const SELFMAG: usize = 4;
pub const EI_CLASS: usize = 4;
pub const ELFCLASSNONE: u8 = 0;
pub const ELFCLASS32: u8 = 1;
pub const ELFCLASS64: u8 = 2;
pub const ELFCLASSNUM: u8 = 3;
pub const EI_DATA: usize = 5;
pub const ELFDATANONE: u8 = 0;
pub const ELFDATA2LSB: u8 = 1;
pub const ELFDATA2MSB: u8 = 2;
pub const SIZEOF_IDENT: usize = 16;
#[inline]
pub fn class_to_str(et: u8) -> &'static str {
match et {
ELFCLASSNONE => "NONE",
ELFCLASS32 => "ELF32",
ELFCLASS64 => "ELF64",
_ => "UNKNOWN_CLASS",
}
}
#[inline]
pub fn et_to_str(et: u16) -> &'static str {
match et {
ET_NONE => "NONE",
ET_REL => "REL",
ET_EXEC => "EXEC",
ET_DYN => "DYN",
ET_CORE => "CORE",
ET_NUM => "NUM",
_ => "UNKNOWN_ET",
}
}
#[cfg(feature = "std")]
pub use self::impure::*;
#[cfg(feature = "std")]
mod impure {
use super::*;
use std::io;
use std::io::{Seek, Read};
use std::io::SeekFrom::Start;
pub fn peek<R: Read + Seek>(fd: &mut R) -> io::Result<(u8, bool)> {
let mut ident = [0u8; SIZEOF_IDENT];
try!(fd.seek(Start(0)));
match try!(fd.read(&mut ident)) {
SIZEOF_IDENT => {
if &ident[0..SELFMAG] != ELFMAG {
return io_error!("Invalid ELF magic number: {:?}", &ident[0..SELFMAG]);
}
let class = ident[EI_CLASS];
let is_lsb = ident[EI_DATA] == ELFDATA2LSB;
Ok((class, is_lsb))
}
count => {
io_error!("Error: {:?} size is smaller than an ELF identication header",
count)
}
}
}
}
macro_rules! elf_header_from_bytes {
() => {
pub fn from_bytes(bytes: &[u8; SIZEOF_EHDR]) -> &Header {
let header: &Header = unsafe { mem::transmute(bytes) };
header
}
};
}
macro_rules! elf_header_from_fd {
() => {
pub fn from_fd(fd: &mut File) -> io::Result<Header> {
let mut elf_header = [0; SIZEOF_EHDR];
try!(fd.read(&mut elf_header));
Ok(*Header::from_bytes(&elf_header))
}
};
}
macro_rules! elf_header_test_peek {
($class:expr) => {
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn test_peek () {
let v = vec![0x7f, 0x45, 0x4c, 0x46, $class, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x8c];
let mut header = Cursor::new(v);
match peek(&mut header) {
Err(_) => assert!(false),
Ok((class, is_lsb)) => {
assert_eq!(true, is_lsb);
assert_eq!(class, $class)
}
}
}
}
}
}
macro_rules! elf_header_impure_impl {
($header:item) => {
#[cfg(feature = "std")]
pub use self::impure::*;
#[cfg(feature = "std")]
mod impure {
use super::*;
use core::mem;
use core::fmt;
use std::fs::File;
use std::io::{self, Read, Seek};
use std::io::SeekFrom::Start;
impl ElfHeader for Header {
fn e_ident(&self) -> [u8; SIZEOF_IDENT] {
self.e_ident
}
fn e_type(&self) -> u16 {
self.e_type
}
fn e_machine(&self) -> u16 {
self.e_machine
}
fn e_version(&self) -> u32 {
self.e_version
}
fn e_entry(&self) -> u64 {
self.e_entry as u64
}
fn e_phoff(&self) -> u64 {
self.e_phoff as u64
}
fn e_shoff(&self) -> u64 {
self.e_shoff as u64
}
fn e_flags(&self) -> u32 {
self.e_flags
}
fn e_ehsize(&self) -> u16 {
self.e_ehsize
}
fn e_phentsize(&self) -> u16 {
self.e_phentsize
}
fn e_phnum(&self) -> u16 {
self.e_phnum
}
fn e_shentsize(&self) -> u16 {
self.e_shentsize
}
fn e_shnum(&self) -> u16 {
self.e_shnum
}
fn e_shstrndx(&self) -> u16 {
self.e_shstrndx
}
}
impl fmt::Debug for Header {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"e_ident: {:?} e_type: {} e_machine: 0x{:x} e_version: 0x{:x} e_entry: 0x{:x} \
e_phoff: 0x{:x} e_shoff: 0x{:x} e_flags: {:x} e_ehsize: {} e_phentsize: {} \
e_phnum: {} e_shentsize: {} e_shnum: {} e_shstrndx: {}",
self.e_ident,
et_to_str(self.e_type),
self.e_machine,
self.e_version,
self.e_entry,
self.e_phoff,
self.e_shoff,
self.e_flags,
self.e_ehsize,
self.e_phentsize,
self.e_phnum,
self.e_shentsize,
self.e_shnum,
self.e_shstrndx)
}
}
$header
}
};
}