Files
RedBear-OS/src/header/dlfcn/mod.rs
T
Anhad Singh 1db68ab978 feat(ld.so): scopes
Signed-off-by: Anhad Singh <andypython@protonmail.com>
2024-12-24 20:51:53 +11:00

161 lines
4.2 KiB
Rust

//! dlfcn implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/dlfcn.h.html
#![deny(unsafe_op_in_unsafe_fn)]
use core::{
ptr, str,
sync::atomic::{AtomicUsize, Ordering},
};
use crate::{
c_str::CStr,
ld_so::{
linker::{ObjectScope, Resolve},
tcb::Tcb,
},
platform::types::*,
};
pub const RTLD_LAZY: c_int = 1 << 0;
pub const RTLD_NOW: c_int = 1 << 1;
pub const RTLD_NOLOAD: c_int = 1 << 2;
pub const RTLD_GLOBAL: c_int = 1 << 8;
pub const RTLD_LOCAL: c_int = 0x0000;
static ERROR_NOT_SUPPORTED: CStr = c_str!("dlfcn not supported");
#[thread_local]
static ERROR: AtomicUsize = AtomicUsize::new(0);
#[repr(C)]
pub struct Dl_info {
dli_fname: *const c_char,
dli_fbase: *mut c_void,
dli_sname: *const c_char,
dli_saddr: *mut c_void,
}
#[no_mangle]
pub unsafe extern "C" fn dladdr(addr: *mut c_void, info: *mut Dl_info) -> c_int {
//TODO
unsafe {
(*info).dli_fname = ptr::null();
(*info).dli_fbase = ptr::null_mut();
(*info).dli_sname = ptr::null();
(*info).dli_saddr = ptr::null_mut();
}
0
}
#[no_mangle]
pub unsafe extern "C" fn dlopen(cfilename: *const c_char, flags: c_int) -> *mut c_void {
//TODO support all sort of flags
let resolve = if flags & RTLD_NOW == RTLD_NOW {
Resolve::Now
} else {
Resolve::Lazy
};
let scope = if flags & RTLD_GLOBAL == RTLD_GLOBAL {
ObjectScope::Global
} else {
ObjectScope::Local
};
let filename = if cfilename.is_null() {
None
} else {
unsafe {
Some(str::from_utf8_unchecked(
CStr::from_ptr(cfilename).to_bytes(),
))
}
};
let tcb = match unsafe { Tcb::current() } {
Some(tcb) => tcb,
None => {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
}
};
if tcb.linker_ptr.is_null() {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
}
let mut linker = unsafe { (&*tcb.linker_ptr).lock() };
let cbs_c = linker.cbs.clone();
let cbs = cbs_c.borrow();
let id = match (cbs.load_library)(&mut linker, filename, resolve, scope) {
Err(err) => {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
}
Ok(id) => id,
};
id as *mut c_void
}
#[no_mangle]
pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void {
if symbol.is_null() {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
}
let symbol_str = unsafe { str::from_utf8_unchecked(CStr::from_ptr(symbol).to_bytes()) };
let tcb = match unsafe { Tcb::current() } {
Some(tcb) => tcb,
None => {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
}
};
if tcb.linker_ptr.is_null() {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
}
let linker = unsafe { (&*tcb.linker_ptr).lock() };
let cbs_c = linker.cbs.clone();
let cbs = cbs_c.borrow();
match (cbs.get_sym)(&linker, handle as usize, symbol_str) {
Some(sym) => sym,
_ => {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
ptr::null_mut()
}
}
}
#[no_mangle]
pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
let tcb = match unsafe { Tcb::current() } {
Some(tcb) => tcb,
None => {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return -1;
}
};
if tcb.linker_ptr.is_null() {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return -1;
};
let mut linker = unsafe { (&*tcb.linker_ptr).lock() };
let cbs_c = linker.cbs.clone();
let cbs = cbs_c.borrow();
(cbs.unload)(&mut linker, handle as usize);
0
}
#[no_mangle]
pub extern "C" fn dlerror() -> *mut c_char {
ERROR.swap(0, Ordering::SeqCst) as *mut c_char
}