dlopen_rs/
dl_iterate_phdr.rs1use crate::{register::MANAGER, ElfLibrary, Error, Result};
2use alloc::boxed::Box;
3use core::{
4 ffi::{c_char, c_int, c_ulonglong, c_void, CStr},
5 ptr::null_mut,
6};
7use elf_loader::arch::ElfPhdr;
8
9#[repr(C)]
11pub struct CDlPhdrInfo {
12 pub dlpi_addr: usize,
13 pub dlpi_name: *const c_char,
14 pub dlpi_phdr: *const ElfPhdr,
15 pub dlpi_phnum: u16,
16 pub dlpi_adds: c_ulonglong,
17 pub dlpi_subs: c_ulonglong,
18 pub dlpi_tls_modid: usize,
19 pub dlpi_tls_data: *mut c_void,
20}
21
22pub struct DlPhdrInfo<'lib> {
23 lib_base: usize,
24 lib_name: &'lib CStr,
25 phdrs: &'lib [ElfPhdr],
26 dlpi_adds: c_ulonglong,
27 dlpi_subs: c_ulonglong,
28 tls_modid: usize,
29 tls_data: Option<&'lib [u8]>,
30}
31
32impl DlPhdrInfo<'_> {
33 #[inline]
35 pub fn name(&self) -> &str {
36 self.lib_name.to_str().unwrap()
37 }
38
39 #[inline]
41 pub fn cname(&self) -> &CStr {
42 self.lib_name
43 }
44
45 #[inline]
47 pub fn base(&self) -> usize {
48 self.lib_base
49 }
50
51 #[inline]
53 pub fn phdrs(&self) -> &[ElfPhdr] {
54 self.phdrs
55 }
56}
57
58impl ElfLibrary {
59 pub fn dl_iterate_phdr<F>(mut callback: F) -> Result<()>
61 where
62 F: FnMut(&DlPhdrInfo) -> Result<()>,
63 {
64 let reader = MANAGER.read();
65 for lib in reader.all.values() {
66 let phdrs = lib.relocated_dylib_ref().phdrs();
67 if phdrs.is_empty() {
68 continue;
69 }
70 let info = DlPhdrInfo {
71 lib_base: lib.relocated_dylib_ref().base(),
72 lib_name: lib.relocated_dylib_ref().cname(),
73 phdrs,
74 dlpi_adds: reader.all.len() as _,
75 dlpi_subs: 0,
76 tls_modid: 0,
77 tls_data: None,
78 };
79 callback(&info)?;
80 }
81 Ok(())
82 }
83}
84
85pub(crate) type CallBack =
86 unsafe extern "C" fn(info: *mut CDlPhdrInfo, size: usize, data: *mut c_void) -> c_int;
87
88pub extern "C" fn dl_iterate_phdr(callback: Option<CallBack>, data: *mut c_void) -> c_int {
90 let f = |info: &DlPhdrInfo| {
91 if let Some(callback) = callback {
92 let mut c_info = CDlPhdrInfo {
93 dlpi_addr: info.lib_base,
94 dlpi_name: info.lib_name.as_ptr(),
95 dlpi_phdr: info.phdrs.as_ptr(),
96 dlpi_phnum: info.phdrs.len() as _,
97 dlpi_adds: info.dlpi_adds,
98 dlpi_subs: info.dlpi_subs,
99 dlpi_tls_modid: info.tls_modid,
100 dlpi_tls_data: info
101 .tls_data
102 .map(|data| data.as_ptr() as _)
103 .unwrap_or(null_mut()),
104 };
105 unsafe {
106 let ret = callback(&mut c_info, size_of::<CDlPhdrInfo>(), data);
107 if ret != 0 {
108 return Err(Error::IteratorPhdrError { err: Box::new(ret) });
109 }
110 };
111 }
112 Ok(())
113 };
114 if let Err(Error::IteratorPhdrError { err }) = ElfLibrary::dl_iterate_phdr(f) {
115 *err.downcast::<i32>().unwrap()
116 } else {
117 0
118 }
119}