use core::{marker::PhantomData, ops::Deref};
use super::LoadedCore;
use crate::{
elf::SymbolInfo,
relocation::{RelocationArch, SymDef},
};
#[derive(Debug, Clone)]
pub struct Symbol<'lib, T: 'lib> {
pub(crate) ptr: *mut (),
pub(crate) pd: PhantomData<&'lib T>,
}
impl<'lib, T> Deref for Symbol<'lib, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*(&self.ptr as *const *mut _ as *const T) }
}
}
impl<'lib, T> Symbol<'lib, T> {
pub fn into_raw(self) -> *const () {
self.ptr
}
}
impl<D: 'static, Arch: RelocationArch> LoadedCore<D, Arch> {
#[inline]
pub unsafe fn get<'lib, T>(&'lib self, name: &str) -> Option<Symbol<'lib, T>> {
let syminfo = SymbolInfo::from_str(name, None);
let mut precompute = syminfo.precompute();
self.symtab()
.lookup_filter(&syminfo, &mut precompute)
.map(|sym| Symbol {
ptr: SymDef::<D, Arch>::new(Some(sym), unsafe { self.core_ref() })
.convert()
.as_mut_ptr(),
pd: PhantomData,
})
}
#[cfg(feature = "version")]
#[inline]
pub unsafe fn get_version<'lib, T>(
&'lib self,
name: &str,
version: &str,
) -> Option<Symbol<'lib, T>> {
let syminfo = SymbolInfo::from_str(name, Some(version));
let mut precompute = syminfo.precompute();
self.symtab()
.lookup_filter(&syminfo, &mut precompute)
.map(|sym| Symbol {
ptr: SymDef::<D, Arch>::new(Some(sym), unsafe { self.core_ref() })
.convert()
.as_mut_ptr(),
pd: PhantomData,
})
}
}
unsafe impl<T: Send> Send for Symbol<'_, T> {}
unsafe impl<T: Sync> Sync for Symbol<'_, T> {}