use super::{Error, Result, RW};
macro_rules! int_enum {
($name: ident as $type: ty: $($variant: ident = $value: expr,)+) => {
impl $name {
pub(super) fn int_value(self) -> $type {
match self {
$(Self::$variant => $value,)+
Self::Custom(value) => value,
}
}
pub(super) fn from_int(value: $type) -> Self {
match value {
$($value => Self::$variant,)+
value => Self::Custom(value),
}
}
}
};
(!$name: ident as $type: ty: $($variant: ident = $value: expr,)+) => {
impl $name {
pub(super) fn int_value(self) -> $type {
match self {
$(Self::$variant => $value,)+
}
}
pub(super) fn from_int(value: $type) -> Result<Self> {
match value {
$($value => Ok(Self::$variant),)+
value => Err(Error::Error(format!("Invalid value for {}: {value}", stringify!($name)))),
}
}
}
};
}
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Class {
ELF32,
#[default]
ELF64,
Custom(u8),
}
int_enum! {
Class as u8:
ELF32 = 1,
ELF64 = 2,
}
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum ByteOrder {
#[default]
LSB,
MSB,
}
int_enum! {
!ByteOrder as u8:
LSB = 1,
MSB = 2,
}
#[cfg(feature = "target-lexicon")]
impl From<target_lexicon::Endianness> for ByteOrder {
fn from(value: target_lexicon::Endianness) -> Self {
match value {
target_lexicon::Endianness::Little => Self::LSB,
target_lexicon::Endianness::Big => Self::MSB,
}
}
}
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum ABI {
#[default]
None,
HPUX,
NetBSD,
Linux,
Hurd,
Solaris,
AIX,
IRIX,
FreeBSD,
Tru64,
Modesto,
OpenBSD,
OpenVMS,
NSK,
AROS,
FenixOS,
CloudABI,
OpenVOS,
Custom(u8),
}
int_enum! {
ABI as u8:
None = 0x00,
HPUX = 0x01,
NetBSD = 0x02,
Linux = 0x03,
Hurd = 0x04,
Solaris = 0x06,
AIX = 0x07,
IRIX = 0x08,
FreeBSD = 0x09,
Tru64 = 0x0A,
Modesto = 0x0B,
OpenBSD = 0x0C,
OpenVMS = 0x0D,
NSK = 0x0E,
AROS = 0x0F,
FenixOS = 0x10,
CloudABI = 0x11,
OpenVOS = 0x12,
}
#[cfg(feature = "target-lexicon")]
impl From<target_lexicon::OperatingSystem> for ABI {
fn from(value: target_lexicon::OperatingSystem) -> Self {
match value {
target_lexicon::OperatingSystem::Unknown => Self::None,
target_lexicon::OperatingSystem::Aix => Self::AIX,
target_lexicon::OperatingSystem::Cloudabi => Self::CloudABI,
target_lexicon::OperatingSystem::Freebsd => Self::FreeBSD,
target_lexicon::OperatingSystem::Linux => Self::Linux,
target_lexicon::OperatingSystem::Netbsd => Self::NetBSD,
target_lexicon::OperatingSystem::None_ => Self::None,
target_lexicon::OperatingSystem::Openbsd => Self::OpenBSD,
target_lexicon::OperatingSystem::Solaris => Self::Solaris,
_ => Self::None,
}
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Type {
Rel,
Exec,
Dyn,
Core,
Custom(u16),
}
int_enum! {
Type as u16:
Rel = 1,
Exec = 2,
Dyn = 3,
Core = 4,
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Machine {
None,
M32,
SPARC,
X86,
M68k,
M88k,
IntelMCU,
Intel80860,
MIPS,
S370,
MipsRS3LE,
PARISC,
Intel80960,
PowerPC,
PowerPC64,
S390,
SPU,
V800,
FR20,
RH32,
RCE,
ARM,
DigitalAlpha,
SuperH,
SPARC9,
TriCore,
ARC,
H8_300,
H8_300H,
H8S,
H8_500,
IA64,
MipsX,
ColdFire,
M68HC12,
MMA,
PCP,
NCPU,
NDR1,
StarCore,
ME16,
ST100,
TinyJ,
X86_64,
SonyDSP,
PDP10,
PDP11,
FX66,
ST9,
ST7,
MC68HC16,
MC68HC11,
MC68HC08,
MC68HC05,
SVx,
ST19,
DigitalVAX,
AxisCommunications,
InfineonTechnologies,
Element14,
LSILogic,
TMS320C6000,
MCSTElbrusE2k,
ARM64,
Z80,
RISCV,
BerkeleyPacketFilter,
WDC65C816,
Custom(u16),
}
int_enum! {
Machine as u16:
None = 0x00,
M32 = 0x01,
SPARC = 0x02,
X86 = 0x03,
M68k = 0x04,
M88k = 0x05,
IntelMCU = 0x06,
Intel80860 = 0x07,
MIPS = 0x08,
S370 = 0x09,
MipsRS3LE = 0x0A,
PARISC = 0x0F,
Intel80960 = 0x13,
PowerPC = 0x14,
PowerPC64 = 0x15,
S390 = 0x16,
SPU = 0x17,
V800 = 0x24,
FR20 = 0x25,
RH32 = 0x26,
RCE = 0x27,
ARM = 0x28,
DigitalAlpha = 0x29,
SuperH = 0x2A,
SPARC9 = 0x2B,
TriCore = 0x2C,
ARC = 0x2D,
H8_300 = 0x2E,
H8_300H = 0x2F,
H8S = 0x30,
H8_500 = 0x31,
IA64 = 0x32,
MipsX = 0x33,
ColdFire = 0x34,
M68HC12 = 0x35,
MMA = 0x36,
PCP = 0x37,
NCPU = 0x38,
NDR1 = 0x39,
StarCore = 0x3A,
ME16 = 0x3B,
ST100 = 0x3C,
TinyJ = 0x3D,
X86_64 = 0x3E,
SonyDSP = 0x3F,
PDP10 = 0x40,
PDP11 = 0x41,
FX66 = 0x42,
ST9 = 0x43,
ST7 = 0x44,
MC68HC16 = 0x45,
MC68HC11 = 0x46,
MC68HC08 = 0x47,
MC68HC05 = 0x48,
SVx = 0x49,
ST19 = 0x4A,
DigitalVAX = 0x4B,
AxisCommunications = 0x4C,
InfineonTechnologies = 0x4D,
Element14 = 0x4E,
LSILogic = 0x4F,
TMS320C6000 = 0x8C,
MCSTElbrusE2k = 0xAF,
ARM64 = 0xB7,
Z80 = 0xDC,
RISCV = 0xF3,
BerkeleyPacketFilter = 0xF7,
WDC65C816 = 0x101,
}
#[cfg(feature = "target-lexicon")]
impl From<target_lexicon::Architecture> for Machine {
fn from(value: target_lexicon::Architecture) -> Self {
match value {
target_lexicon::Architecture::Unknown => Self::None,
target_lexicon::Architecture::Arm(_) => Self::ARM,
target_lexicon::Architecture::Aarch64(_) => Self::ARM64,
target_lexicon::Architecture::X86_32(_) => Self::X86,
target_lexicon::Architecture::M68k => Self::M68k,
target_lexicon::Architecture::Mips32(_) => Self::MIPS,
target_lexicon::Architecture::Mips64(_) => Self::MIPS,
target_lexicon::Architecture::Powerpc => Self::PowerPC,
target_lexicon::Architecture::Powerpc64 => Self::PowerPC64,
target_lexicon::Architecture::Powerpc64le => Self::PowerPC64,
target_lexicon::Architecture::Riscv32(_) => Self::RISCV,
target_lexicon::Architecture::Riscv64(_) => Self::RISCV,
target_lexicon::Architecture::S390x => Self::S390,
target_lexicon::Architecture::Sparc => Self::SPARC,
target_lexicon::Architecture::Sparc64 => Self::SPARC9,
target_lexicon::Architecture::Sparcv9 => Self::SPARC9,
target_lexicon::Architecture::X86_64 => Self::X86_64,
target_lexicon::Architecture::X86_64h => Self::X86_64,
_ => todo!(),
}
}
}
pub trait SizeT: Sized + RW {
fn new(value: u64) -> Self;
fn value(&self) -> u64;
const CLASS: Class;
const ELF_HEADER_SIZE: u16;
const SEGMENT_HEADER_SIZE: u16;
const SECTION_HEADER_SIZE: u16;
const MOVE_PFLAGS: bool;
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum SegmentType {
None,
Load,
Dynamic,
Interpreter,
Note,
ShLib,
Phdr,
Tls,
Custom(u32),
}
int_enum! {
SegmentType as u32:
None = 0x00,
Load = 0x01,
Dynamic = 0x02,
Interpreter = 0x03,
Note = 0x04,
ShLib = 0x05,
Phdr = 0x06,
Tls = 0x07,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum SegmentFlags {
Executable = 0x01,
Writeable = 0x02,
Readable = 0x04,
}