Merge branch 'arm-dynlink' into 'master'

Fix missing symbols for ARM dynamic linking

See merge request redox-os/relibc!763
This commit is contained in:
Jeremy Soller
2025-12-10 06:16:16 -07:00
3 changed files with 93 additions and 17 deletions
+3 -4
View File
@@ -110,13 +110,13 @@ SECTIONS
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
/* .init_array :
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} */
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
@@ -248,9 +248,8 @@ SECTIONS
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
* that may reference use thread local storage.
*
* .init_array also depends on TLS and is discarded as we don't need it.
* .init_array need to be not discarded unlike x86_64 linker variant
*/
*(.gnu.linkonce.tb.*) *(.tcommon)
*(.init_array)
}
}
+88 -13
View File
@@ -1,29 +1,104 @@
use crate::{platform::types::*, raw_cell::RawCell};
// TODO: Implement cxa_finalize and uncomment this
use crate::platform::types::*;
use alloc::vec::Vec;
use core::{cell::RefCell, ptr};
use spin::Mutex;
#[derive(Clone, Copy)]
struct CxaAtExitFunc {
//func: extern "C" fn(*mut c_void),
//arg: *mut c_void,
//dso: *mut c_void,
func: extern "C" fn(*mut c_void),
arg: usize,
dso: usize,
}
static CXA_ATEXIT_FUNCS: RawCell<[Option<CxaAtExitFunc>; 32]> = RawCell::new([None; 32]);
#[derive(Clone, Copy)]
struct CxaThreadAtExitFunc {
func: extern "C" fn(*mut c_void),
obj: *mut c_void,
dso: *mut c_void,
}
static CXA_ATEXIT_FUNCS: Mutex<Vec<Option<CxaAtExitFunc>>> = Mutex::new(Vec::new());
#[thread_local]
static DTORS: RefCell<Vec<CxaThreadAtExitFunc>> = RefCell::new(Vec::new());
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __cxa_atexit(
func_opt: Option<extern "C" fn(*mut c_void)>,
func: Option<extern "C" fn(*mut c_void)>,
arg: *mut c_void,
dso: *mut c_void,
) -> c_int {
for i in 0..CXA_ATEXIT_FUNCS.unsafe_ref().len() {
if CXA_ATEXIT_FUNCS.unsafe_ref()[i].is_none() {
CXA_ATEXIT_FUNCS.unsafe_mut()[i] =
func_opt.map(|func| CxaAtExitFunc {} /*{ func, arg, dso }*/);
let Some(func) = func else {
return 0;
};
let entry = CxaAtExitFunc {
func,
arg: arg as usize,
dso: dso as usize,
};
let mut funcs = CXA_ATEXIT_FUNCS.lock();
for slot in funcs.iter_mut() {
if slot.is_none() {
*slot = Some(entry);
return 0;
}
}
-1
// No empty slots
funcs.push(Some(entry));
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __cxa_finalize(dso: *mut c_void) {
let mut funcs = CXA_ATEXIT_FUNCS.lock();
let dso_usize = dso as usize;
for slot in funcs.iter_mut().rev() {
if let Some(entry) = slot.as_ref() {
if dso.is_null() || entry.dso == dso_usize {
if let Some(entry_to_run) = slot.take() {
(entry_to_run.func)(entry_to_run.arg as *mut c_void);
}
}
}
}
// clean up remaining list
if dso.is_null() {
funcs.clear();
} else {
funcs.retain(|opt| opt.is_some());
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __cxa_thread_atexit_impl(
func: extern "C" fn(*mut c_void),
obj: *mut c_void,
dso: *mut c_void,
) {
let entry = CxaThreadAtExitFunc { func, obj, dso };
DTORS.borrow_mut().push(entry);
}
// called internally
pub unsafe fn __cxa_thread_finalize() {
let mut dtors = DTORS.borrow_mut();
while let Some(entry) = dtors.pop() {
(entry.func)(entry.obj);
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn _ITM_deregisterTMCloneTable(_ptr: *mut c_void) {
// No-op
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn _ITM_registerTMCloneTable(_ptr: *mut c_void, _len: usize) {
// No-op
}
+2
View File
@@ -302,6 +302,8 @@ pub unsafe extern "C" fn __relibc_internal_pthread_cleanup_pop(execute: c_int) {
}
pub(crate) unsafe fn run_destructor_stack() {
unsafe { crate::cxa::__cxa_thread_finalize() };
let mut ptr = CLEANUP_LL_HEAD.get();
while !ptr.is_null() {