Skip to content

Commit 03bd8ed

Browse files
committed
feat(relocation):introduce the SupportLazy trait
1 parent 6050858 commit 03bd8ed

File tree

10 files changed

+122
-146
lines changed

10 files changed

+122
-146
lines changed

src/image/kinds/dylib.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
loader::LoadHook,
1313
os::Mmap,
1414
parse_ehdr_error,
15-
relocation::{Relocatable, RelocationHandler, Relocator, SymbolLookup},
15+
relocation::{Relocatable, RelocationHandler, Relocator, SupportLazy, SymbolLookup},
1616
tls::TlsResolver,
1717
};
1818
use alloc::vec::Vec;
@@ -32,6 +32,8 @@ where
3232
pub(crate) inner: DynamicImage<D>,
3333
}
3434

35+
impl<D: 'static> SupportLazy for RawDylib<D> {}
36+
3537
impl<D> Debug for RawDylib<D> {
3638
/// Formats the [`RawDylib`] for debugging purposes.
3739
///
@@ -248,7 +250,10 @@ where
248250
return Err(parse_ehdr_error("file type mismatch"));
249251
}
250252

251-
let phdrs = self.buf.prepare_phdrs(&ehdr, &mut object)?;
253+
let phdrs = self
254+
.buf
255+
.prepare_phdrs(&ehdr, &mut object)?
256+
.unwrap_or_default();
252257

253258
// Load the relocated common part
254259
let builder = self.inner.create_builder::<M, Tls>(ehdr, phdrs, object)?;

src/image/kinds/exec.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::relocation::SupportLazy;
12
use crate::sync::Arc;
23
/// Executable file handling
34
///
@@ -133,6 +134,8 @@ where
133134
pub(crate) inner: ExecImageInner<D>,
134135
}
135136

137+
impl<D: 'static> SupportLazy for RawExec<D> {}
138+
136139
pub(crate) enum ExecImageInner<D>
137140
where
138141
D: 'static,
@@ -260,7 +263,10 @@ where
260263
return Err(parse_ehdr_error("file type mismatch"));
261264
}
262265

263-
let phdrs = self.buf.prepare_phdrs(&ehdr, &mut object)?;
266+
let phdrs = self
267+
.buf
268+
.prepare_phdrs(&ehdr, &mut object)?
269+
.unwrap_or_default();
264270
let has_dynamic = phdrs.iter().any(|phdr| phdr.p_type == PT_DYNAMIC);
265271

266272
let res = if has_dynamic {

src/image/kinds/object.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ where
5959
log::debug!("Loading object: {}", object.file_name());
6060

6161
let ehdr = self.buf.prepare_ehdr(&mut object)?;
62-
let shdrs = self.buf.prepare_shdrs_mut(&ehdr, &mut object)?;
62+
let shdrs = self
63+
.buf
64+
.prepare_shdrs_mut(&ehdr, &mut object)?
65+
.ok_or_else(|| crate::parse_ehdr_error("object file must have section headers"))?;
6366
let builder = self
6467
.inner
6568
.create_object_builder::<M, Tls>(ehdr, shdrs, object)?;

src/image/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ impl<M: Mmap, H: LoadHook, D: Default + 'static> Loader<M, H, D> {
280280
elf::abi::ET_REL => Ok(RawElf::Object(self.load_object_impl(object)?)),
281281
elf::abi::ET_EXEC => Ok(RawElf::Exec(self.load_exec_impl(object)?)),
282282
elf::abi::ET_DYN => {
283-
let phdrs = self.read_phdr(&mut object, &ehdr)?;
283+
let phdrs = self.read_phdr(&mut object, &ehdr)?.unwrap_or_default();
284284
let has_dynamic = phdrs.iter().any(|p| p.p_type == PT_DYNAMIC);
285285
let is_pie = phdrs.iter().any(|p| p.p_type == PT_INTERP) || !has_dynamic;
286286
if is_pie {

src/loader.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,37 +33,43 @@ impl ElfBuf {
3333
&mut self,
3434
ehdr: &ElfHeader,
3535
object: &mut impl ElfReader,
36-
) -> Result<&[ElfPhdr]> {
36+
) -> Result<Option<&[ElfPhdr]>> {
3737
let (phdr_start, phdr_end) = ehdr.phdr_range();
3838
let size = phdr_end - phdr_start;
39+
if size == 0 {
40+
return Ok(None);
41+
}
3942
if size > self.buf.len() {
4043
self.buf.resize(size, 0);
4144
}
4245
object.read(&mut self.buf[..size], phdr_start)?;
4346
unsafe {
44-
Ok(core::slice::from_raw_parts(
47+
Ok(Some(core::slice::from_raw_parts(
4548
self.buf.as_ptr().cast::<ElfPhdr>(),
4649
(phdr_end - phdr_start) / size_of::<ElfPhdr>(),
47-
))
50+
)))
4851
}
4952
}
5053

5154
pub(crate) fn prepare_shdrs_mut(
5255
&mut self,
5356
ehdr: &ElfHeader,
5457
object: &mut impl ElfReader,
55-
) -> Result<&mut [ElfShdr]> {
58+
) -> Result<Option<&mut [ElfShdr]>> {
5659
let (shdr_start, shdr_end) = ehdr.shdr_range();
5760
let size = shdr_end - shdr_start;
61+
if size == 0 {
62+
return Ok(None);
63+
}
5864
if size > self.buf.len() {
5965
self.buf.resize(size, 0);
6066
}
6167
object.read(&mut self.buf[..size], shdr_start)?;
6268
unsafe {
63-
Ok(core::slice::from_raw_parts_mut(
69+
Ok(Some(core::slice::from_raw_parts_mut(
6470
self.buf.as_mut_ptr().cast::<ElfShdr>(),
6571
(shdr_end - shdr_start) / size_of::<ElfShdr>(),
66-
))
72+
)))
6773
}
6874
}
6975
}
@@ -413,7 +419,7 @@ where
413419
&mut self,
414420
object: &mut impl ElfReader,
415421
ehdr: &ElfHeader,
416-
) -> Result<&[ElfPhdr]> {
422+
) -> Result<Option<&[ElfPhdr]>> {
417423
self.buf.prepare_phdrs(ehdr, object)
418424
}
419425
}

src/relocation/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ pub(crate) use utils::{
2727
};
2828

2929
pub use crate::tls::TlsResolver;
30-
pub use traits::{RelocationContext, RelocationHandler, SymbolLookup};
30+
pub use traits::{RelocationContext, RelocationHandler, SupportLazy, SymbolLookup};

src/relocation/static.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::{
99
};
1010
use alloc::{boxed::Box, vec::Vec};
1111

12-
1312
pub(crate) struct StaticRelocation {
1413
relocation: Box<[&'static [ElfRelType]]>,
1514
}
@@ -70,7 +69,8 @@ impl<D: 'static> RawObject<D> {
7069

7170
#[cfg(feature = "log")]
7271
log::trace!("[{}] Executing init functions", self.core.name());
73-
self.init.call(&LifecycleContext::new(None, self.init_array));
72+
self.init
73+
.call(&LifecycleContext::new(None, self.init_array));
7474

7575
#[cfg(feature = "log")]
7676
log::info!("Relocation completed for {}", self.core.name());

src/relocation/traits.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ impl<H: RelocationHandler + ?Sized> RelocationHandler for Arc<H> {
201201
}
202202
}
203203

204+
/// A marker trait for objects that support lazy binding.
205+
pub trait SupportLazy {}
206+
204207
/// A trait for objects that can be relocated.
205208
///
206209
/// Types implementing this trait can undergo symbol resolution and address fixup.

src/relocation/utils.rs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
elf::{ElfRelType, ElfSymbol, SymbolInfo, SymbolTable},
44
image::{ElfCore, LoadedCore},
55
relocate_error,
6-
relocation::{Relocatable, RelocationContext, RelocationHandler, SymbolLookup},
6+
relocation::{Relocatable, RelocationContext, RelocationHandler, SupportLazy, SymbolLookup},
77
sync::Arc,
88
tls::TlsDescDynamicArg,
99
};
@@ -330,6 +330,39 @@ where
330330
}
331331
}
332332

333+
/// Executes the relocation process.
334+
///
335+
/// This method consumes the relocator and returns the relocated ELF object.
336+
/// All configured symbol lookups, handlers, and options are applied.
337+
///
338+
/// # Returns
339+
/// * `Ok(T::Output)` - The successfully relocated ELF object.
340+
/// * `Err(Error)` - If relocation fails for any reason.
341+
pub fn relocate(self) -> Result<T::Output>
342+
where
343+
D: 'static,
344+
{
345+
self.object.relocate(
346+
self.scope,
347+
&self.pre_find,
348+
&self.post_find,
349+
&self.pre_handler,
350+
&self.post_handler,
351+
self.lazy,
352+
self.lazy_scope,
353+
)
354+
}
355+
}
356+
357+
impl<T, PreS, PostS, LazyS, PreH, PostH, D> Relocator<T, PreS, PostS, LazyS, PreH, PostH, D>
358+
where
359+
T: Relocatable<D> + SupportLazy,
360+
PreS: SymbolLookup,
361+
PostS: SymbolLookup,
362+
LazyS: SymbolLookup + Send + Sync + 'static,
363+
PreH: RelocationHandler,
364+
PostH: RelocationHandler,
365+
{
333366
/// Enables or disables lazy binding.
334367
///
335368
/// When enabled, some relocations (typically PLT entries) will be resolved
@@ -359,29 +392,6 @@ where
359392
lazy_scope: Some(scope),
360393
}
361394
}
362-
363-
/// Executes the relocation process.
364-
///
365-
/// This method consumes the relocator and returns the relocated ELF object.
366-
/// All configured symbol lookups, handlers, and options are applied.
367-
///
368-
/// # Returns
369-
/// * `Ok(T::Output)` - The successfully relocated ELF object.
370-
/// * `Err(Error)` - If relocation fails for any reason.
371-
pub fn relocate(self) -> Result<T::Output>
372-
where
373-
D: 'static,
374-
{
375-
self.object.relocate(
376-
self.scope,
377-
&self.pre_find,
378-
&self.post_find,
379-
&self.pre_handler,
380-
&self.post_handler,
381-
self.lazy,
382-
self.lazy_scope,
383-
)
384-
}
385395
}
386396

387397
/// A wrapper type for relocation values, providing type safety and arithmetic operations.

0 commit comments

Comments
 (0)