use crate::utils::cow_struct;
use std::borrow::Cow;
use std::fmt;
use std::mem::size_of;
use super::class::Class;
use super::data::DATA;
use super::identification::Indent;
use super::osabit::OSABIT;
use super::types::TYPE;
use super::version::VERSION;
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct x64 {
pub e_ident: [u8; 16],
pub e_type: u16,
pub e_machine: u16,
pub e_version: u32,
pub e_entry: u64,
pub e_phoff: u64,
pub e_shoff: u64,
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,
}
impl x64 {
pub const SIZE: usize = size_of::<Self>();
}
pub fn from_bytes(data: &[u8]) -> Option<Cow<x64>> {
if data.len() < x64::SIZE {
return None;
}
let (header_bytes, _data) = data.split_at(x64::SIZE);
cow_struct::<x64>(header_bytes)
}
impl fmt::Display for x64 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "ELF Hearder:").unwrap();
writeln!(
f,
" Magic: {}",
self.e_ident
.iter()
.map(|hex| format!("{:02X?} ", hex))
.collect::<String>()
)
.unwrap();
let class = match self.e_ident[Indent::CLASS] {
Class::NONE => "Invalid class",
Class::ELF32 => "ELF32",
Class::ELF64 => "ELF64",
_ => "Warning: unknown class",
};
writeln!(f, " Class:\t\t\t\t{},", class).unwrap();
let data_encoding = match self.e_ident[Indent::DATA] {
DATA::NONE => "Unknown data encoding",
DATA::BE => "2's complement, big endian",
DATA::LE => "2's complement, little endian",
_ => "Warning: unknow data encoding",
};
writeln!(f, " Data:\t\t\t\t\t{}", data_encoding).unwrap();
let current = format!("{} (current)", self.e_ident[Indent::VERSION]);
let version = match self.e_ident[Indent::VERSION] {
VERSION::NONE => "Invalid version",
VERSION::CURRENT => current.as_str(),
_ => "Warning: unknow version",
};
writeln!(f, " Version:\t\t\t\t{}", version).unwrap();
let osabit = match self.e_ident[Indent::OSABIT] {
OSABIT::SYSV => "UNIX System V ABI",
OSABIT::HPUX => "HP-UX",
OSABIT::NETBSD => "NetBSD",
OSABIT::GNU => "Object use GNU ELF extensions",
OSABIT::SOLARIS => "Sun Solaris",
OSABIT::AIX => "IBM AIX",
OSABIT::IRIX => "SGI Irix",
OSABIT::FREEBSD => "FreeBSD",
OSABIT::TRU64 => "Compaq tru64 unix",
OSABIT::MODESTO => "Novell Modesto",
OSABIT::OPENBSD => "OpenBSD",
OSABIT::ARM_AEABI => "ARM AEABI",
OSABIT::ARM => "ARM",
OSABIT::STANDALONE => "Standalone embedded application",
_ => "Warning: unknow operating system target",
};
writeln!(f, " OS/ABI:\t\t\t\t{}", osabit).unwrap();
let abi_version_message = match self.e_ident[Indent::ABIVERSION] {
0 => "0",
_ => "Warning: Not compatible with the specification",
};
writeln!(f, " ABI Version:\t\t\t\t{}", abi_version_message).unwrap();
let obj_type = match self.e_type {
TYPE::NONE => "NONE (No file type)",
TYPE::REL => "REL (Relocatable file)",
TYPE::EXEC => "EXEC (Executable file)",
TYPE::DYN => "DYN (Share object file)",
TYPE::CORE => "CORE (Core file)",
_ => "Warning: unknow object file type",
};
writeln!(f, " Type: \t\t\t\t{}", obj_type).unwrap();
return writeln!(f, " Version:\t\t\t\t{:#x}", self.e_version);
}
}