use super::{SymDef, find_symdef_impl};
use crate::{
Result,
elf::ElfRelType,
image::{ElfCore, LoadedCore},
sync::Arc,
};
use alloc::{boxed::Box, vec::Vec};
pub trait SymbolLookup {
fn lookup(&self, name: &str) -> Option<*const ()>;
}
impl<F: ?Sized> SymbolLookup for F
where
F: Fn(&str) -> Option<*const ()>,
{
fn lookup(&self, name: &str) -> Option<*const ()> {
self(name)
}
}
impl<S: SymbolLookup + ?Sized> SymbolLookup for Arc<S> {
fn lookup(&self, name: &str) -> Option<*const ()> {
(**self).lookup(name)
}
}
impl<S: SymbolLookup + ?Sized> SymbolLookup for &Arc<S> {
fn lookup(&self, name: &str) -> Option<*const ()> {
(**self).lookup(name)
}
}
impl SymbolLookup for () {
fn lookup(&self, _name: &str) -> Option<*const ()> {
None
}
}
pub trait RelocationHandler {
fn handle<D>(&self, ctx: &RelocationContext<'_, D>) -> Option<Result<Option<usize>>>;
}
pub struct RelocationContext<'a, D> {
rel: &'a ElfRelType,
lib: &'a ElfCore<D>,
scope: &'a [LoadedCore<D>],
}
impl<'a, D> RelocationContext<'a, D> {
#[inline]
pub(crate) fn new(
rel: &'a ElfRelType,
lib: &'a ElfCore<D>,
scope: &'a [LoadedCore<D>],
) -> Self {
Self { rel, lib, scope }
}
#[inline]
pub fn rel(&self) -> &ElfRelType {
self.rel
}
#[inline]
pub fn lib(&self) -> &ElfCore<D> {
self.lib
}
#[inline]
pub fn scope(&self) -> &[LoadedCore<D>] {
self.scope
}
#[inline]
pub fn find_symdef(&self, r_sym: usize) -> Option<(SymDef<'a, D>, Option<usize>)> {
let symbol = self.lib.symtab();
let (sym, syminfo) = symbol.symbol_idx(r_sym);
find_symdef_impl(self.lib, self.scope, sym, &syminfo)
}
}
impl RelocationHandler for () {
fn handle<D>(&self, _ctx: &RelocationContext<'_, D>) -> Option<Result<Option<usize>>> {
None
}
}
impl<H: RelocationHandler + ?Sized> RelocationHandler for &H {
fn handle<D>(&self, ctx: &RelocationContext<'_, D>) -> Option<Result<Option<usize>>> {
(**self).handle(ctx)
}
}
impl<H: RelocationHandler + ?Sized> RelocationHandler for &mut H {
fn handle<D>(&self, ctx: &RelocationContext<'_, D>) -> Option<Result<Option<usize>>> {
(**self).handle(ctx)
}
}
impl<H: RelocationHandler + ?Sized> RelocationHandler for Box<H> {
fn handle<D>(&self, ctx: &RelocationContext<'_, D>) -> Option<Result<Option<usize>>> {
(**self).handle(ctx)
}
}
impl<H: RelocationHandler + ?Sized> RelocationHandler for Arc<H> {
fn handle<D>(&self, ctx: &RelocationContext<'_, D>) -> Option<Result<Option<usize>>> {
(**self).handle(ctx)
}
}
pub trait SupportLazy {}
pub trait Relocatable<D = ()>: Sized {
type Output;
fn relocate<PreS, PostS, LazyS, PreH, PostH>(
self,
scope: Vec<LoadedCore<D>>,
pre_find: &PreS,
post_find: &PostS,
pre_handler: &PreH,
post_handler: &PostH,
lazy: Option<bool>,
lazy_scope: Option<LazyS>,
) -> Result<Self::Output>
where
PreS: SymbolLookup + ?Sized,
PostS: SymbolLookup + ?Sized,
LazyS: SymbolLookup + Send + Sync + 'static,
PreH: RelocationHandler + ?Sized,
PostH: RelocationHandler + ?Sized;
}