use crate::{
Result,
arch::NativeArch,
elf::ElfPhdr,
input::Path,
relocation::{Relocatable, RelocateArgs, RelocationArch, RelocationHandler, Relocator},
};
use super::{LoadedCore, LoadedExec, RawDylib, RawExec};
#[cfg(feature = "object")]
use super::{LoadedObject, RawObject};
#[derive(Debug)]
pub enum RawElf<D, Arch = crate::arch::NativeArch>
where
D: 'static,
Arch: RelocationArch,
{
Dylib(RawDylib<D, Arch>),
Exec(RawExec<D, Arch>),
#[cfg(feature = "object")]
Object(RawObject<D, Arch>),
}
#[derive(Debug, Clone)]
pub enum LoadedElf<D: 'static, Arch: RelocationArch = NativeArch> {
Dylib(LoadedCore<D, Arch>),
Exec(LoadedExec<D, Arch>),
#[cfg(feature = "object")]
Object(LoadedObject<D, Arch>),
}
impl<D: 'static, Arch: RelocationArch> RawElf<D, Arch> {
pub fn relocator(self) -> Relocator<Self, (), (), D, Arch>
where
Self: Relocatable<D, Arch = Arch>,
{
Relocator::new().with_object(self)
}
#[inline]
pub fn path(&self) -> &Path {
match self {
RawElf::Dylib(dylib) => dylib.path(),
RawElf::Exec(exec) => exec.path(),
#[cfg(feature = "object")]
RawElf::Object(object) => object.path(),
}
}
#[inline]
pub fn name(&self) -> &str {
match self {
RawElf::Dylib(dylib) => dylib.name(),
RawElf::Exec(exec) => exec.name(),
#[cfg(feature = "object")]
RawElf::Object(object) => object.name(),
}
}
#[inline]
pub fn mapped_len(&self) -> usize {
match self {
RawElf::Dylib(dylib) => dylib.mapped_len(),
RawElf::Exec(exec) => exec.mapped_len(),
#[cfg(feature = "object")]
RawElf::Object(object) => object.mapped_len(),
}
}
#[inline]
pub fn contains_addr(&self, addr: usize) -> bool {
match self {
RawElf::Dylib(dylib) => dylib.contains_addr(addr),
RawElf::Exec(exec) => exec.contains_addr(addr),
#[cfg(feature = "object")]
RawElf::Object(object) => object.contains_addr(addr),
}
}
#[inline]
pub fn entry(&self) -> usize {
match self {
RawElf::Dylib(dylib) => dylib.entry(),
RawElf::Exec(exec) => exec.entry(),
#[cfg(feature = "object")]
RawElf::Object(_) => 0,
}
}
#[inline]
pub fn interp(&self) -> Option<&str> {
match self {
RawElf::Dylib(dylib) => dylib.interp(),
RawElf::Exec(exec) => exec.interp(),
#[cfg(feature = "object")]
RawElf::Object(_) => None,
}
}
#[inline]
pub fn phdrs(&self) -> Option<&[ElfPhdr<Arch::Layout>]> {
match self {
RawElf::Dylib(dylib) => Some(dylib.phdrs()),
RawElf::Exec(exec) => exec.phdrs(),
#[cfg(feature = "object")]
RawElf::Object(_) => None,
}
}
#[inline]
pub fn base(&self) -> usize {
match self {
RawElf::Dylib(dylib) => dylib.base(),
RawElf::Exec(exec) => exec.base(),
#[cfg(feature = "object")]
RawElf::Object(object) => object.base(),
}
}
}
impl<D: 'static, Arch: RelocationArch> LoadedElf<D, Arch> {
#[inline]
pub fn into_dylib(self) -> Option<LoadedCore<D, Arch>> {
match self {
LoadedElf::Dylib(dylib) => Some(dylib),
_ => None,
}
}
#[inline]
pub fn into_exec(self) -> Option<LoadedExec<D, Arch>> {
match self {
LoadedElf::Exec(exec) => Some(exec),
_ => None,
}
}
#[cfg(feature = "object")]
#[inline]
pub fn into_object(self) -> Option<LoadedObject<D, Arch>> {
match self {
LoadedElf::Object(object) => Some(object),
_ => None,
}
}
#[inline]
pub fn as_dylib(&self) -> Option<&LoadedCore<D, Arch>> {
match self {
LoadedElf::Dylib(dylib) => Some(dylib),
_ => None,
}
}
#[inline]
pub fn as_exec(&self) -> Option<&LoadedExec<D, Arch>> {
match self {
LoadedElf::Exec(exec) => Some(exec),
_ => None,
}
}
#[cfg(feature = "object")]
#[inline]
pub fn as_object(&self) -> Option<&LoadedObject<D, Arch>> {
match self {
LoadedElf::Object(object) => Some(object),
_ => None,
}
}
#[inline]
pub fn path(&self) -> &Path {
match self {
LoadedElf::Dylib(dylib) => dylib.path(),
LoadedElf::Exec(exec) => exec.path(),
#[cfg(feature = "object")]
LoadedElf::Object(object) => object.path(),
}
}
#[inline]
pub fn name(&self) -> &str {
match self {
LoadedElf::Dylib(dylib) => dylib.name(),
LoadedElf::Exec(exec) => exec.name(),
#[cfg(feature = "object")]
LoadedElf::Object(object) => object.name(),
}
}
#[inline]
pub fn mapped_len(&self) -> usize {
match self {
LoadedElf::Dylib(dylib) => dylib.mapped_len(),
LoadedElf::Exec(exec) => exec.mapped_len(),
#[cfg(feature = "object")]
LoadedElf::Object(object) => object.mapped_len(),
}
}
#[inline]
pub fn contains_addr(&self, addr: usize) -> bool {
match self {
LoadedElf::Dylib(dylib) => dylib.contains_addr(addr),
LoadedElf::Exec(exec) => exec.contains_addr(addr),
#[cfg(feature = "object")]
LoadedElf::Object(object) => object.contains_addr(addr),
}
}
}
impl<D: 'static, Arch: RelocationArch> Relocatable<D> for RawElf<D, Arch> {
type Output = LoadedElf<D, Arch>;
type Arch = Arch;
fn relocate<PreH, PostH>(
self,
args: RelocateArgs<'_, D, Arch, PreH, PostH>,
) -> Result<Self::Output>
where
PreH: RelocationHandler<Arch> + ?Sized,
PostH: RelocationHandler<Arch> + ?Sized,
{
match self {
RawElf::Dylib(dylib) => Ok(LoadedElf::Dylib(Relocatable::relocate(dylib, args)?)),
RawElf::Exec(exec) => Ok(LoadedElf::Exec(Relocatable::relocate(exec, args)?)),
#[cfg(feature = "object")]
RawElf::Object(relocatable) => {
Ok(LoadedElf::Object(Relocatable::relocate(relocatable, args)?))
}
}
}
}