use core::{
fmt,
ops::{Deref, DerefMut},
};
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Architecture {
Unknown,
Aarch64,
#[allow(non_camel_case_types)]
Aarch64_Ilp32,
Alpha,
Arm,
Avr,
Bpf,
Csky,
E2K32,
E2K64,
I386,
X86_64,
#[allow(non_camel_case_types)]
X86_64_X32,
Hexagon,
Hppa,
LoongArch32,
LoongArch64,
M68k,
Mips,
Mips64,
#[allow(non_camel_case_types)]
Mips64_N32,
Msp430,
PowerPc,
PowerPc64,
Riscv32,
Riscv64,
S390x,
Sbf,
Sharc,
Sparc,
Sparc32Plus,
Sparc64,
SuperH,
Wasm32,
Wasm64,
Xtensa,
}
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SubArchitecture {
Arm64E,
Arm64EC,
}
impl Architecture {
pub fn address_size(self) -> Option<AddressSize> {
match self {
Architecture::Unknown => None,
Architecture::Aarch64 => Some(AddressSize::U64),
Architecture::Aarch64_Ilp32 => Some(AddressSize::U32),
Architecture::Alpha => Some(AddressSize::U64),
Architecture::Arm => Some(AddressSize::U32),
Architecture::Avr => Some(AddressSize::U8),
Architecture::Bpf => Some(AddressSize::U64),
Architecture::Csky => Some(AddressSize::U32),
Architecture::E2K32 => Some(AddressSize::U32),
Architecture::E2K64 => Some(AddressSize::U64),
Architecture::I386 => Some(AddressSize::U32),
Architecture::X86_64 => Some(AddressSize::U64),
Architecture::X86_64_X32 => Some(AddressSize::U32),
Architecture::Hexagon => Some(AddressSize::U32),
Architecture::Hppa => Some(AddressSize::U32),
Architecture::LoongArch32 => Some(AddressSize::U32),
Architecture::LoongArch64 => Some(AddressSize::U64),
Architecture::M68k => Some(AddressSize::U32),
Architecture::Mips => Some(AddressSize::U32),
Architecture::Mips64 => Some(AddressSize::U64),
Architecture::Mips64_N32 => Some(AddressSize::U32),
Architecture::Msp430 => Some(AddressSize::U16),
Architecture::PowerPc => Some(AddressSize::U32),
Architecture::PowerPc64 => Some(AddressSize::U64),
Architecture::Riscv32 => Some(AddressSize::U32),
Architecture::Riscv64 => Some(AddressSize::U64),
Architecture::S390x => Some(AddressSize::U64),
Architecture::Sbf => Some(AddressSize::U64),
Architecture::Sharc => Some(AddressSize::U32),
Architecture::Sparc => Some(AddressSize::U32),
Architecture::Sparc32Plus => Some(AddressSize::U32),
Architecture::Sparc64 => Some(AddressSize::U64),
Architecture::Wasm32 => Some(AddressSize::U32),
Architecture::Wasm64 => Some(AddressSize::U64),
Architecture::Xtensa => Some(AddressSize::U32),
Architecture::SuperH => Some(AddressSize::U32),
}
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
#[repr(u8)]
pub enum AddressSize {
U8 = 1,
U16 = 2,
U32 = 4,
U64 = 8,
}
impl AddressSize {
#[inline]
pub fn bytes(self) -> u8 {
self as u8
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum BinaryFormat {
Coff,
Elf,
MachO,
Pe,
Wasm,
Xcoff,
}
impl BinaryFormat {
pub fn native_object() -> BinaryFormat {
if cfg!(target_os = "windows") {
BinaryFormat::Coff
} else if cfg!(target_os = "macos") {
BinaryFormat::MachO
} else {
BinaryFormat::Elf
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SectionKind {
Unknown,
Text,
Data,
ReadOnlyData,
ReadOnlyDataWithRel,
ReadOnlyString,
UninitializedData,
Common,
Tls,
UninitializedTls,
TlsVariables,
OtherString,
Other,
Debug,
DebugString,
Linker,
Note,
Metadata,
Elf(u32),
}
impl SectionKind {
pub fn is_bss(self) -> bool {
self == SectionKind::UninitializedData
|| self == SectionKind::UninitializedTls
|| self == SectionKind::Common
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ComdatKind {
Unknown,
Any,
NoDuplicates,
SameSize,
ExactMatch,
Largest,
Newest,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SymbolKind {
Unknown,
Text,
Data,
Section,
File,
Label,
Tls,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SymbolScope {
Unknown,
Compilation,
Linkage,
Dynamic,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum RelocationKind {
Unknown,
None,
Absolute,
Relative,
Got,
GotRelative,
GotBaseRelative,
GotBaseOffset,
PltRelative,
ImageOffset,
SectionOffset,
SectionIndex,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum RelocationEncoding {
Unknown,
Generic,
X86Signed,
X86RipRelative,
X86RipRelativeMovq,
X86Branch,
S390xDbl,
AArch64Call,
LoongArchBranch,
SharcTypeA,
SharcTypeB,
E2KLit,
E2KDisp,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum FileFlags {
None,
Elf {
os_abi: u8,
abi_version: u8,
e_flags: u32,
},
MachO {
flags: u32,
},
Coff {
characteristics: u16,
},
Xcoff {
f_flags: u16,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SegmentFlags {
None,
Elf {
p_flags: u32,
},
MachO {
flags: u32,
maxprot: u32,
initprot: u32,
},
Coff {
characteristics: u32,
},
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Permissions {
bits: u8,
}
impl core::fmt::Debug for Permissions {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"{}{}{}",
if self.readable() { 'R' } else { '-' },
if self.writable() { 'W' } else { '-' },
if self.executable() { 'X' } else { '-' },
)
}
}
impl Permissions {
const R: u8 = 1 << 0;
const W: u8 = 1 << 1;
const X: u8 = 1 << 2;
pub fn new(readable: bool, writable: bool, executable: bool) -> Self {
let mut bits = 0;
if readable {
bits |= Self::R;
}
if writable {
bits |= Self::W;
}
if executable {
bits |= Self::X;
}
Permissions { bits }
}
#[inline]
pub fn readable(&self) -> bool {
self.bits & Self::R != 0
}
#[inline]
pub fn writable(&self) -> bool {
self.bits & Self::W != 0
}
#[inline]
pub fn executable(&self) -> bool {
self.bits & Self::X != 0
}
#[inline]
pub fn readonly(&self) -> bool {
self.readable() && !self.writable()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SectionFlags {
None,
Elf {
sh_flags: u64,
},
MachO {
flags: u32,
},
Coff {
characteristics: u32,
},
Xcoff {
s_flags: u32,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SymbolFlags<Section, Symbol> {
None,
Elf {
st_info: u8,
st_other: u8,
},
MachO {
n_desc: u16,
},
CoffSection {
selection: u8,
associative_section: Option<Section>,
},
Xcoff {
n_sclass: u8,
x_smtyp: u8,
x_smclas: u8,
containing_csect: Option<Symbol>,
},
}
impl<Section, Symbol> SymbolFlags<Section, Symbol> {
pub fn elf_visibility(&self) -> Option<u8> {
match self {
SymbolFlags::Elf { st_other, .. } => Some(st_other & 0x3),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum RelocationFlags {
Generic {
kind: RelocationKind,
encoding: RelocationEncoding,
size: u8,
},
Elf {
r_type: u32,
},
MachO {
r_type: u8,
r_pcrel: bool,
r_length: u8,
},
Coff {
typ: u16,
},
Xcoff {
r_rtype: u8,
r_rsize: u8,
},
}
#[allow(unused)]
#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct SkipDebugList<T>(pub T);
impl<T> fmt::Debug for SkipDebugList<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[..]")
}
}
impl<T> Deref for SkipDebugList<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for SkipDebugList<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}