use super::lifecycle::{Finalizer, FiniEvent};
use crate::{
Result,
arch::NativeArch,
elf::{ElfRelEntry, ElfRelType, ElfSymbol, HashTable, Lifecycle, SymbolEntry, SymbolTableView},
image::{ElfCore, ModuleScope},
input::Path,
memory::{HostRegion, RegionAccess, VmAddr},
relocation::{RelocationArch, SymDef, find_symdef_impl},
tls::TlsResolver,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HandleResult {
Unhandled,
Handled,
}
impl HandleResult {
#[inline]
pub const fn is_unhandled(self) -> bool {
matches!(self, Self::Unhandled)
}
}
pub struct RelocationEvent<
'a,
D: 'static,
Arch: RelocationArch = NativeArch,
R: RegionAccess = HostRegion,
Tls: TlsResolver<Arch> = (),
H = HashTable<<Arch as RelocationArch>::Layout>,
> {
rel: &'a ElfRelType<Arch>,
lib: &'a ElfCore<D, Arch, R, Tls>,
symbols: SymbolTableView<'a, Arch::Layout, H>,
scope: &'a ModuleScope<Arch, Tls>,
}
impl<'a, D: 'static, Arch: RelocationArch, R: RegionAccess, Tls: TlsResolver<Arch>, H>
RelocationEvent<'a, D, Arch, R, Tls, H>
{
#[inline]
pub(crate) fn new(
rel: &'a ElfRelType<Arch>,
lib: &'a ElfCore<D, Arch, R, Tls>,
symbols: SymbolTableView<'a, Arch::Layout, H>,
scope: &'a ModuleScope<Arch, Tls>,
) -> Self {
Self {
rel,
lib,
symbols,
scope,
}
}
#[inline]
pub fn rel(&self) -> &ElfRelType<Arch> {
self.rel
}
#[inline]
pub fn lib(&self) -> &ElfCore<D, Arch, R, Tls> {
self.lib
}
#[inline]
pub fn scope(&self) -> &ModuleScope<Arch, Tls> {
self.scope
}
#[inline]
pub fn symbol(&self, r_sym: usize) -> SymbolEntry<'a, Arch::Layout> {
self.symbols.symbol_idx(r_sym)
}
#[inline]
pub fn relocation_symbol(&self) -> Option<SymbolEntry<'a, Arch::Layout>> {
let r_sym = self.rel.r_symbol();
(r_sym != 0).then(|| self.symbol(r_sym))
}
#[inline]
pub fn find_symdef(&self, r_sym: usize) -> Option<SymDef<'a, Arch, Tls>> {
let symbol = self.symbol(r_sym);
find_symdef_impl(
self.lib,
self.scope,
symbol.symbol(),
symbol.info(),
self.lib.symbolic(),
)
}
}
pub struct SymbolBindingEvent<
'a,
D: 'static,
Arch: RelocationArch = NativeArch,
R: RegionAccess = HostRegion,
Tls: TlsResolver<Arch> = (),
> {
core: &'a ElfCore<D, Arch, R, Tls>,
rel: Option<&'a ElfRelType<Arch>>,
symbol: &'a ElfSymbol<Arch::Layout>,
symbol_name: &'a str,
resolved: Option<VmAddr>,
}
impl<'a, D: 'static, Arch: RelocationArch, R: RegionAccess, Tls: TlsResolver<Arch>>
SymbolBindingEvent<'a, D, Arch, R, Tls>
{
#[inline]
pub(crate) const fn new(
core: &'a ElfCore<D, Arch, R, Tls>,
rel: Option<&'a ElfRelType<Arch>>,
symbol: &'a ElfSymbol<Arch::Layout>,
symbol_name: &'a str,
resolved: Option<VmAddr>,
) -> Self {
Self {
core,
rel,
symbol,
symbol_name,
resolved,
}
}
#[inline]
pub const fn core(&self) -> &ElfCore<D, Arch, R, Tls> {
self.core
}
#[inline]
pub const fn rel(&self) -> Option<&ElfRelType<Arch>> {
self.rel
}
#[inline]
pub const fn symbol(&self) -> &ElfSymbol<Arch::Layout> {
self.symbol
}
#[inline]
pub const fn symbol_name(&self) -> &'a str {
self.symbol_name
}
#[inline]
pub const fn resolved_addr(&self) -> Option<VmAddr> {
self.resolved
}
#[inline]
pub fn set_resolved_addr(&mut self, addr: VmAddr) {
self.resolved = Some(addr);
}
#[inline]
pub fn clear_resolved_addr(&mut self) {
self.resolved = None;
}
#[inline]
pub(crate) const fn into_resolved_addr(self) -> Option<VmAddr> {
self.resolved
}
}
pub struct DynamicRelocatedEvent<
'a,
D: 'static,
Arch: RelocationArch = NativeArch,
R: RegionAccess = HostRegion,
Tls: TlsResolver<Arch> = (),
> {
core: &'a ElfCore<D, Arch, R, Tls>,
dynamic_addr: VmAddr,
finalizer: Finalizer,
}
impl<'a, D: 'static, Arch: RelocationArch, R: RegionAccess, Tls: TlsResolver<Arch>>
DynamicRelocatedEvent<'a, D, Arch, R, Tls>
{
#[inline]
pub(crate) const fn new(
core: &'a ElfCore<D, Arch, R, Tls>,
dynamic_addr: VmAddr,
finalizer: Finalizer,
) -> Self {
Self {
core,
dynamic_addr,
finalizer,
}
}
#[inline]
pub const fn core(&self) -> &ElfCore<D, Arch, R, Tls> {
self.core
}
#[inline]
pub fn path(&self) -> &Path {
self.core.path()
}
#[inline]
pub fn name(&self) -> &str {
self.core.name()
}
#[inline]
pub fn base(&self) -> VmAddr {
self.core.base()
}
#[inline]
pub const fn dynamic_addr(&self) -> VmAddr {
self.dynamic_addr
}
#[inline]
pub fn fini(&self) -> &Lifecycle {
self.finalizer.lifecycle()
}
#[inline]
pub fn fini_mut(&mut self) -> &mut Lifecycle {
self.finalizer.lifecycle_mut()
}
#[inline]
pub fn set_fini_hook<F>(&mut self, hook: F)
where
F: for<'event> Fn(&mut FiniEvent<'event>) -> Result<()> + Send + Sync + 'static,
{
self.finalizer.set_hook(hook);
}
#[inline]
pub(crate) fn into_finalizer(self) -> Finalizer {
self.finalizer
}
}