use crate::{
arch::NativeArch,
elf::{ElfLayout, ElfSymbol, SymbolLookup, SymbolTable},
memory::ImageMemory,
relocation::RelocationArch,
sync::Arc,
tls::{TlsModuleId, TlsResolver, TlsTpOffset},
};
use alloc::boxed::Box;
use core::any::Any;
pub trait SymbolExports<L: ElfLayout>: Send + Sync {
fn symbols(&self) -> &[ElfSymbol<L>];
fn symbol_name<'exports>(&'exports self, symbol: &ElfSymbol<L>) -> Option<&'exports str>;
fn lookup<'exports>(
&'exports self,
lookup: &mut SymbolLookup<'_>,
) -> Option<&'exports ElfSymbol<L>>;
}
#[inline]
pub(crate) fn exports_handle<L, E>(exports: E) -> Arc<dyn SymbolExports<L>>
where
L: ElfLayout,
E: SymbolExports<L> + 'static,
{
Arc::from(Box::new(exports) as Box<dyn SymbolExports<L>>)
}
impl<L> SymbolExports<L> for SymbolTable<L>
where
L: ElfLayout,
{
#[inline]
fn symbols(&self) -> &[ElfSymbol<L>] {
self.view().symbols()
}
#[inline]
fn symbol_name<'exports>(&'exports self, symbol: &ElfSymbol<L>) -> Option<&'exports str> {
Some(self.strtab().get_str(symbol.st_name()))
}
#[inline]
fn lookup<'exports>(
&'exports self,
lookup: &mut SymbolLookup<'_>,
) -> Option<&'exports ElfSymbol<L>> {
self.view().lookup_filter(lookup)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ModuleTls {
None,
Static {
mod_id: TlsModuleId,
tp_offset: TlsTpOffset,
},
Dynamic {
mod_id: TlsModuleId,
},
}
impl Default for ModuleTls {
#[inline]
fn default() -> Self {
Self::None
}
}
impl ModuleTls {
pub const NONE: Self = Self::None;
#[inline]
pub const fn new(mod_id: Option<TlsModuleId>, tp_offset: Option<TlsTpOffset>) -> Self {
match (mod_id, tp_offset) {
(Some(mod_id), Some(tp_offset)) => Self::Static { mod_id, tp_offset },
(Some(mod_id), None) => Self::Dynamic { mod_id },
_ => Self::None,
}
}
#[inline]
pub const fn mod_id(self) -> Option<TlsModuleId> {
match self {
Self::None => None,
Self::Static { mod_id, .. } | Self::Dynamic { mod_id, .. } => Some(mod_id),
}
}
#[inline]
pub const fn tp_offset(self) -> Option<TlsTpOffset> {
match self {
Self::Static { tp_offset, .. } => Some(tp_offset),
Self::None | Self::Dynamic { .. } => None,
}
}
}
pub trait Module<Arch: RelocationArch = NativeArch, Tls: TlsResolver<Arch> = ()>:
Any + Send + Sync
{
fn name(&self) -> &str;
fn exports(&self) -> &dyn SymbolExports<Arch::Layout>;
fn memory(&self) -> &dyn ImageMemory;
fn tls(&self) -> ModuleTls {
ModuleTls::NONE
}
}
impl<M, Arch, Tls> Module<Arch, Tls> for Arc<M>
where
M: Module<Arch, Tls> + ?Sized + 'static,
Arch: RelocationArch,
Tls: TlsResolver<Arch> + 'static,
{
#[inline]
fn name(&self) -> &str {
(**self).name()
}
#[inline]
fn exports(&self) -> &dyn SymbolExports<Arch::Layout> {
(**self).exports()
}
#[inline]
fn memory(&self) -> &dyn ImageMemory {
(**self).memory()
}
#[inline]
fn tls(&self) -> ModuleTls {
(**self).tls()
}
}