1use super::{ElfCommonPart, Relocated, create_lazy_scope};
2use crate::{
3 CoreComponent, Loader, Result, UserData,
4 arch::ElfPhdr,
5 dynamic::ElfDynamic,
6 loader::Builder,
7 mmap::Mmap,
8 object::{ElfObject, ElfObjectAsync},
9 parse_ehdr_error,
10 relocation::{LazyScope, SymDef, UnknownHandler, relocate_impl},
11 segment::ElfSegments,
12 symbol::{SymbolInfo, SymbolTable},
13};
14use alloc::{boxed::Box, ffi::CString, vec::Vec};
15use core::{fmt::Debug, marker::PhantomData, ops::Deref};
16
17pub struct ElfDylib {
19 inner: ElfCommonPart,
20}
21
22impl Deref for ElfDylib {
23 type Target = ElfCommonPart;
24
25 fn deref(&self) -> &Self::Target {
26 &self.inner
27 }
28}
29
30impl Debug for ElfDylib {
31 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32 f.debug_struct("ElfDylib")
33 .field("name", &self.inner.name())
34 .field("needed_libs", &self.inner.needed_libs())
35 .finish()
36 }
37}
38
39impl ElfDylib {
40 #[inline]
42 pub fn user_data_mut(&mut self) -> Option<&mut UserData> {
43 self.inner.user_data_mut()
44 }
45
46 pub fn easy_relocate<'iter, 'scope, 'find, 'lib, F>(
50 self,
51 scope: impl IntoIterator<Item = &'iter RelocatedDylib<'scope>>,
52 pre_find: &'find F,
53 ) -> Result<RelocatedDylib<'lib>>
54 where
55 F: Fn(&str) -> Option<*const ()>,
56 'scope: 'iter,
57 'iter: 'lib,
58 'find: 'lib,
59 {
60 let iter = scope.into_iter();
61 let mut helper = Vec::new();
62 let local_lazy_scope = if self.is_lazy() {
63 let mut libs = Vec::new();
64 iter.for_each(|lib| {
65 libs.push(lib.downgrade());
66 helper.push(lib);
67 });
68 Some(create_lazy_scope(libs, pre_find))
69 } else {
70 iter.for_each(|lib| {
71 helper.push(lib);
72 });
73 None
74 };
75 self.relocate(
76 helper,
77 pre_find,
78 &mut |_, _, _| Err(Box::new(())),
79 local_lazy_scope,
80 )
81 }
82
83 pub fn relocate<'iter, 'scope, 'find, 'lib, F>(
91 self,
92 scope: impl AsRef<[&'iter RelocatedDylib<'scope>]>,
93 pre_find: &'find F,
94 deal_unknown: &mut UnknownHandler,
95 local_lazy_scope: Option<LazyScope<'lib>>,
96 ) -> Result<RelocatedDylib<'lib>>
97 where
98 F: Fn(&str) -> Option<*const ()>,
99 'scope: 'iter,
100 'iter: 'lib,
101 'find: 'lib,
102 {
103 Ok(RelocatedDylib {
104 inner: relocate_impl(
105 self.inner,
106 scope.as_ref(),
107 pre_find,
108 deal_unknown,
109 local_lazy_scope,
110 )?,
111 })
112 }
113}
114
115impl Builder {
116 pub(crate) fn create_dylib(self, phdrs: &[ElfPhdr]) -> ElfDylib {
117 let inner = self.create_inner(phdrs, true);
118 ElfDylib { inner }
119 }
120}
121
122impl<M: Mmap> Loader<M> {
123 pub fn easy_load_dylib(&mut self, object: impl ElfObject) -> Result<ElfDylib> {
125 self.load_dylib(object, None)
126 }
127
128 pub fn load_dylib(
132 &mut self,
133 mut object: impl ElfObject,
134 lazy_bind: Option<bool>,
135 ) -> Result<ElfDylib> {
136 let ehdr = self.buf.prepare_ehdr(&mut object)?;
137 if !ehdr.is_dylib() {
138 return Err(parse_ehdr_error("file type mismatch"));
139 }
140 let (builder, phdrs) = self.load_impl(ehdr, object, lazy_bind)?;
141 Ok(builder.create_dylib(phdrs))
142 }
143
144 pub async fn load_dylib_async(
148 &mut self,
149 mut object: impl ElfObjectAsync,
150 lazy_bind: Option<bool>,
151 ) -> Result<ElfDylib> {
152 let ehdr = self.buf.prepare_ehdr(&mut object)?;
153 if !ehdr.is_dylib() {
154 return Err(parse_ehdr_error("file type mismatch"));
155 }
156 let (builder, phdrs) = self.load_async_impl(ehdr, object, lazy_bind).await?;
157 Ok(builder.create_dylib(phdrs))
158 }
159}
160
161#[derive(Clone)]
163pub struct RelocatedDylib<'scope> {
164 inner: Relocated<'scope>,
165}
166
167impl Debug for RelocatedDylib<'_> {
168 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
169 self.inner.fmt(f)
170 }
171}
172
173impl Deref for RelocatedDylib<'_> {
174 type Target = CoreComponent;
175
176 fn deref(&self) -> &Self::Target {
177 &self.inner
178 }
179}
180
181impl RelocatedDylib<'_> {
182 #[inline]
186 pub unsafe fn from_core_component(core: CoreComponent) -> Self {
187 RelocatedDylib {
188 inner: Relocated {
189 core,
190 _marker: PhantomData,
191 },
192 }
193 }
194
195 #[inline]
200 pub unsafe fn core_component_ref(&self) -> &CoreComponent {
201 &self.inner
202 }
203
204 #[inline]
207 pub unsafe fn new_uncheck(
208 name: CString,
209 base: usize,
210 dynamic: ElfDynamic,
211 phdrs: &'static [ElfPhdr],
212 segments: ElfSegments,
213 user_data: UserData,
214 ) -> Self {
215 Self {
216 inner: Relocated {
217 core: CoreComponent::from_raw(name, base, dynamic, phdrs, segments, user_data),
218 _marker: PhantomData,
219 },
220 }
221 }
222
223 #[inline]
225 pub fn symtab(&self) -> &SymbolTable {
226 unsafe { self.inner.symtab().unwrap_unchecked() }
227 }
228
229 #[inline]
263 pub unsafe fn get<'lib, T>(&'lib self, name: &str) -> Option<Symbol<'lib, T>> {
264 let syminfo = SymbolInfo::from_str(name, None);
265 let mut precompute = syminfo.precompute();
266 self.symtab()
267 .lookup_filter(&syminfo, &mut precompute)
268 .map(|sym| Symbol {
269 ptr: SymDef {
270 sym: Some(sym),
271 lib: self,
272 }
273 .convert() as _,
274 pd: PhantomData,
275 })
276 }
277
278 #[cfg(feature = "version")]
291 #[inline]
292 pub unsafe fn get_version<'lib, T>(
293 &'lib self,
294 name: &str,
295 version: &str,
296 ) -> Option<Symbol<'lib, T>> {
297 let syminfo = SymbolInfo::from_str(name, Some(version));
298 let mut precompute = syminfo.precompute();
299 self.symtab()
300 .lookup_filter(&syminfo, &mut precompute)
301 .map(|sym| Symbol {
302 ptr: SymDef {
303 sym: Some(sym),
304 lib: self,
305 }
306 .convert() as _,
307 pd: PhantomData,
308 })
309 }
310}
311
312#[derive(Debug, Clone)]
314pub struct Symbol<'lib, T: 'lib> {
315 ptr: *mut (),
316 pd: PhantomData<&'lib T>,
317}
318
319impl<'lib, T> Deref for Symbol<'lib, T> {
320 type Target = T;
321 fn deref(&self) -> &T {
322 unsafe { &*(&self.ptr as *const *mut _ as *const T) }
323 }
324}
325
326impl<'lib, T> Symbol<'lib, T> {
327 pub fn into_raw(self) -> *const () {
328 self.ptr
329 }
330}
331
332unsafe impl<T: Send> Send for Symbol<'_, T> {}
333unsafe impl<T: Sync> Sync for Symbol<'_, T> {}