relibc/header/dlfcn/
mod.rs1#![warn(warnings, unused_variables)]
8
9use core::{
10 ptr, str,
11 sync::atomic::{AtomicUsize, Ordering},
12};
13
14use crate::{
15 c_str::CStr,
16 ld_so::{
17 linker::{DlError, ObjectHandle, Resolve, ScopeKind},
18 tcb::Tcb,
19 },
20 platform::types::{c_char, c_int, c_void},
21};
22
23pub const RTLD_LAZY: c_int = 1 << 0;
25pub const RTLD_NOW: c_int = 1 << 1;
27pub const RTLD_NOLOAD: c_int = 1 << 2;
30pub const RTLD_GLOBAL: c_int = 1 << 8;
32pub const RTLD_LOCAL: c_int = 0x0000;
35
36#[allow(clippy::zero_ptr)] pub const RTLD_DEFAULT: *mut c_void = 0 as *mut c_void; static ERROR_NOT_SUPPORTED: &core::ffi::CStr = c"dlfcn not supported";
45
46#[thread_local]
47static ERROR: AtomicUsize = AtomicUsize::new(0);
48
49fn set_last_error(error: DlError) {
50 ERROR.store(error.repr().as_ptr() as usize, Ordering::SeqCst);
51}
52
53#[repr(C)]
55#[allow(non_camel_case_types)]
56pub struct Dl_info_t {
57 dli_fname: *const c_char,
59 dli_fbase: *mut c_void,
61 dli_sname: *const c_char,
63 dli_saddr: *mut c_void,
65}
66
67pub type Dl_info = Dl_info_t;
69
70#[unsafe(no_mangle)]
72pub unsafe extern "C" fn dladdr(_addr: *const c_void, info: *mut Dl_info_t) -> c_int {
73 unsafe {
75 (*info).dli_fname = ptr::null();
76 (*info).dli_fbase = ptr::null_mut();
77 (*info).dli_sname = ptr::null();
78 (*info).dli_saddr = ptr::null_mut();
79 }
80 0
81}
82
83#[unsafe(no_mangle)]
85pub unsafe extern "C" fn dlopen(cfilename: *const c_char, flags: c_int) -> *mut c_void {
86 let resolve = if flags & RTLD_NOW == RTLD_NOW {
88 Resolve::Now
89 } else {
90 Resolve::Lazy
91 };
92
93 let scope = if flags & RTLD_GLOBAL == RTLD_GLOBAL {
94 ScopeKind::Global
95 } else {
96 ScopeKind::Local
97 };
98
99 let noload = flags & RTLD_NOLOAD == RTLD_NOLOAD;
100
101 let filename = if cfilename.is_null() {
102 None
103 } else {
104 unsafe {
105 Some(str::from_utf8_unchecked(
106 CStr::from_ptr(cfilename).to_bytes(),
107 ))
108 }
109 };
110
111 let tcb = match unsafe { Tcb::current() } {
112 Some(tcb) => tcb,
113 None => {
114 ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
115 return ptr::null_mut();
116 }
117 };
118
119 if tcb.linker_ptr.is_null() {
120 ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
121 return ptr::null_mut();
122 }
123
124 let mut linker = unsafe { (*tcb.linker_ptr).lock() };
125
126 let cbs_c = linker.cbs.clone();
127 let cbs = cbs_c.borrow();
128
129 match (cbs.load_library)(&mut linker, filename, resolve, scope, noload) {
130 Ok(handle) => handle.as_ptr().cast_mut(),
131 Err(error) => {
132 set_last_error(error);
133 ptr::null_mut()
134 }
135 }
136}
137
138#[unsafe(no_mangle)]
140pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void {
141 let handle = ObjectHandle::from_ptr(handle);
142
143 if symbol.is_null() {
144 ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
145 return ptr::null_mut();
146 }
147
148 let symbol_str = unsafe { str::from_utf8_unchecked(CStr::from_ptr(symbol).to_bytes()) };
149
150 let tcb = match unsafe { Tcb::current() } {
154 Some(tcb) => tcb,
155 None => {
156 ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
157 return ptr::null_mut();
158 }
159 };
160
161 if tcb.linker_ptr.is_null() {
162 ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
163 return ptr::null_mut();
164 }
165
166 let linker = unsafe { (*tcb.linker_ptr).lock() };
167 let cbs_c = linker.cbs.clone();
168 let cbs = cbs_c.borrow();
169 match (cbs.get_sym)(&linker, handle, symbol_str) {
170 Some(sym) => sym,
171 _ => {
172 ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
173 ptr::null_mut()
174 }
175 }
176}
177
178#[unsafe(no_mangle)]
180pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
181 let tcb = match unsafe { Tcb::current() } {
182 Some(tcb) => tcb,
183 None => {
184 ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
185 return -1;
186 }
187 };
188
189 if tcb.linker_ptr.is_null() {
190 ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
191 return -1;
192 };
193
194 let Some(handle) = ObjectHandle::from_ptr(handle) else {
195 set_last_error(DlError::InvalidHandle);
196 return -1;
197 };
198
199 let mut linker = unsafe { (*tcb.linker_ptr).lock() };
200 let cbs_c = linker.cbs.clone();
201 let cbs = cbs_c.borrow();
202 (cbs.unload)(&mut linker, handle);
203 0
204}
205
206#[unsafe(no_mangle)]
208pub extern "C" fn dlerror() -> *mut c_char {
209 ERROR.swap(0, Ordering::SeqCst) as *mut c_char
210}