diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index 928fff297d..86a9892568 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -95,7 +95,7 @@ pub fn copy_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> { Ok(()) } -unsafe extern "sysv64" fn fork_impl(initial_rsp: *mut usize, args: &ForkArgs) -> usize { +unsafe extern "sysv64" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usize { Error::mux(fork_inner(initial_rsp, args)) } @@ -131,8 +131,8 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" stmxcsr [rsp+32] fnstcw [rsp+40] - mov rdi, rsp - // rsi: &ForkArgs + // rdi: &ForkArgs + mov rsi, rsp call {fork_impl} add rsp, 96 diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 02e8d690b4..3ee2ec1d1b 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -183,15 +183,9 @@ pub(crate) fn read_proc_meta(proc: &FdGuard) -> syscall::Result { let _ = syscall::read(**proc, &mut bytes)?; Ok(*plain::from_bytes::(&bytes).unwrap()) } -pub unsafe fn initialize( - #[cfg(feature = "proc")] proc_fd: FdGuard, - #[cfg(feature = "proc")] thr_fd: FdGuard, -) { +pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { #[cfg(feature = "proc")] - let metadata = { - RtTcb::current().thr_fd.get().write(Some(thr_fd)); - read_proc_meta(&proc_fd).unwrap() - }; + let metadata = read_proc_meta(&proc_fd).unwrap(); #[cfg(not(feature = "proc"))] // Bootstrap mode, don't associate proc fds with PIDs diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 0cf57f1b67..84a50d6fae 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -55,6 +55,10 @@ pub struct ExtraInfo<'a> { pub sigprocmask: u64, /// File mode creation mask (POSIX) pub umask: u32, + /// Thread handle + pub thr_fd: usize, + /// Process handle + pub proc_fd: usize, } pub fn fexec_impl( @@ -373,7 +377,12 @@ where push(AT_REDOX_INHERITED_SIGPROCMASK)?; push(extrainfo.umask as usize)?; - push(AT_REDOX_UMASK); + push(AT_REDOX_UMASK)?; + + push(extrainfo.thr_fd as usize)?; + push(AT_REDOX_THR_FD)?; + push(extrainfo.proc_fd as usize)?; + push(AT_REDOX_PROC_FD)?; push(0)?; diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index bf1df86639..a1a429090d 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -692,7 +692,10 @@ impl Linker { tcb.append_masters(tcb_masters); // Copy the master data into the static TLS block. tcb.copy_masters().map_err(|_| DlError::Malformed)?; - tcb.activate(); + tcb.activate( + #[cfg(target_os = "redox")] + todo!(), + ); #[cfg(target_os = "redox")] { diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs index eb3bb8c369..d3d726df5d 100644 --- a/src/ld_so/mod.rs +++ b/src/ld_so/mod.rs @@ -41,7 +41,10 @@ static mut STATIC_TCB_MASTER: Master = Master { }; #[inline(never)] -pub fn static_init(sp: &'static Stack) { +pub fn static_init( + sp: &'static Stack, + #[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard, +) { const SIZEOF_PHDR64: usize = mem::size_of::>(); const SIZEOF_PHDR32: usize = mem::size_of::>(); @@ -120,7 +123,10 @@ pub fn static_init(sp: &'static Stack) { tcb.masters_len = mem::size_of::(); tcb.copy_masters() .expect_notls("failed to copy TLS master data"); - tcb.activate(); + tcb.activate( + #[cfg(target_os = "redox")] + thr_fd, + ); } //TODO: Warning on multiple TLS sections? @@ -130,7 +136,10 @@ pub fn static_init(sp: &'static Stack) { } #[cfg(any(target_os = "linux", target_os = "redox"))] -pub unsafe fn init(sp: &'static Stack) { +pub unsafe fn init( + sp: &'static Stack, + #[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard, +) { let tp: usize; #[cfg(target_os = "linux")] @@ -151,11 +160,8 @@ pub unsafe fn init(sp: &'static Stack) { { let mut env = syscall::EnvRegisters::default(); - let file = syscall::open( - "/scheme/thisproc/current/regs/env", - syscall::O_CLOEXEC | syscall::O_RDONLY, - ) - .expect_notls("failed to open handle for process registers"); + let file = syscall::dup(*thr_fd, b"regs/env") + .expect_notls("failed to open handle for process registers"); let _ = syscall::read(file, &mut env).expect_notls("failed to read gsbase"); @@ -167,11 +173,8 @@ pub unsafe fn init(sp: &'static Stack) { { let mut env = syscall::EnvRegisters::default(); - let file = syscall::open( - "/scheme/thisproc/current/regs/env", - syscall::O_CLOEXEC | syscall::O_RDONLY, - ) - .expect_notls("failed to open handle for process registers"); + let file = syscall::dup(*thr_fd, b"regs/env") + .expect_notls("failed to open handle for process registers"); let _ = syscall::read(file, &mut env).expect_notls("failed to read fsbase"); @@ -188,7 +191,11 @@ pub unsafe fn init(sp: &'static Stack) { } if tp == 0 { - static_init(sp); + static_init( + sp, + #[cfg(target_os = "redox")] + thr_fd, + ); } } diff --git a/src/ld_so/tcb.rs b/src/ld_so/tcb.rs index 66fa39fb61..1191b7c1b3 100644 --- a/src/ld_so/tcb.rs +++ b/src/ld_so/tcb.rs @@ -202,8 +202,14 @@ impl Tcb { } /// Activate TLS - pub unsafe fn activate(&mut self) { - Self::os_arch_activate(&self.os_specific, self.tls_end as usize, self.tls_len); + pub unsafe fn activate(&mut self, #[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard) { + Self::os_arch_activate( + &self.os_specific, + self.tls_end as usize, + self.tls_len, + #[cfg(target_os = "redox")] + thr_fd, + ); } pub fn setup_dtv(&mut self, n: usize) { @@ -327,7 +333,13 @@ impl Tcb { } #[cfg(target_os = "redox")] - unsafe fn os_arch_activate(os: &OsSpecific, tls_end: usize, tls_len: usize) { + unsafe fn os_arch_activate( + os: &OsSpecific, + tls_end: usize, + tls_len: usize, + thr_fd: redox_rt::proc::FdGuard, + ) { + os.thr_fd.get().write(Some(thr_fd)); redox_rt::tcb_activate(os, tls_end, tls_len) } } diff --git a/src/platform/auxv_defs.rs b/src/platform/auxv_defs.rs index 7b817dc517..5f6dad136b 100644 --- a/src/platform/auxv_defs.rs +++ b/src/platform/auxv_defs.rs @@ -49,11 +49,11 @@ pub const AT_REDOX_INITIAL_DEFAULT_SCHEME_PTR: usize = 38; #[cfg(target_os = "redox")] pub const AT_REDOX_INITIAL_DEFAULT_SCHEME_LEN: usize = 39; -#[cfg(target_os = "redox")] -pub const AT_REDOX_PROC_FD: usize = 39; - -#[cfg(target_os = "redox")] -pub const AT_REDOX_THR_FD: usize = 39; - #[cfg(target_os = "redox")] pub const AT_REDOX_UMASK: usize = 40; + +#[cfg(target_os = "redox")] +pub const AT_REDOX_PROC_FD: usize = 41; + +#[cfg(target_os = "redox")] +pub const AT_REDOX_THR_FD: usize = 42; diff --git a/src/platform/mod.rs b/src/platform/mod.rs index b1d08dd2e6..016f4eec36 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -280,21 +280,40 @@ impl Write for CountingWriter { // get_auxv. #[cold] -pub unsafe fn get_auxvs(mut ptr: *const usize) -> Box<[[usize; 2]]> { - //traverse the stack and collect argument environment variables - let mut auxvs = Vec::new(); +unsafe fn auxv_iter<'a>(ptr: *const usize) -> impl Iterator + 'a { + struct St(*const usize); + impl Iterator for St { + type Item = [usize; 2]; - while *ptr != self::auxv_defs::AT_NULL { - let kind = ptr.read(); - ptr = ptr.add(1); - let value = ptr.read(); - ptr = ptr.add(1); - auxvs.push([kind, value]); + fn next(&mut self) -> Option { + unsafe { + if self.0.read() == self::auxv_defs::AT_NULL { + return None; + } + let kind = self.0.read(); + let value = self.0.add(1).read(); + self.0 = self.0.add(2); + + Some([kind, value]) + } + } } + St(ptr) +} + +#[cold] +pub unsafe fn get_auxvs(ptr: *const usize) -> Box<[[usize; 2]]> { + //traverse the stack and collect argument environment variables + let mut auxvs = auxv_iter(ptr).collect::>(); auxvs.sort_unstable_by_key(|[kind, _]| *kind); auxvs.into_boxed_slice() } +// TODO: Find an auxv replacement for Redox's execv protocol +#[cold] +pub unsafe fn get_auxv_raw(ptr: *const usize, requested_kind: usize) -> Option { + auxv_iter(ptr).find_map(|[kind, value]| Some(value).filter(|_| kind == requested_kind)) +} pub fn get_auxv(auxvs: &[[usize; 2]], key: usize) -> Option { auxvs .binary_search_by_key(&key, |[entry_key, _]| *entry_key) @@ -311,13 +330,10 @@ pub unsafe fn init(auxvs: Box<[[usize; 2]]>) { use redox_rt::proc::FdGuard; use syscall::MODE_PERM; - let (Some(thr_fd), Some(proc_fd)) = ( - get_auxv(&auxvs, AT_REDOX_THR_FD), - get_auxv(&auxvs, AT_REDOX_PROC_FD), - ) else { + let Some(proc_fd) = get_auxv(&auxvs, AT_REDOX_PROC_FD) else { panic!("Missing proc and thread fd!"); }; - redox_rt::initialize(FdGuard::new(proc_fd), FdGuard::new(thr_fd)); + redox_rt::initialize(FdGuard::new(proc_fd)); if let (Some(cwd_ptr), Some(cwd_len)) = ( get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_PTR), diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index be047a25bf..4d8cc1a97e 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -319,6 +319,8 @@ pub fn execve( sigignmask: 0, sigprocmask, umask: redox_rt::sys::get_umask(), + thr_fd: **RtTcb::current().thread_fd(), + proc_fd: **redox_rt::current_proc_fd(), }; fexec_impl( exec_fd_guard, diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs index d7b97fe1de..b41a19d5cc 100644 --- a/src/pthread/mod.rs +++ b/src/pthread/mod.rs @@ -210,19 +210,16 @@ unsafe extern "C" fn new_thread_shim( mutex1: *const Mutex>, mutex2: *const Mutex, ) -> ! { + let tid = (*(&*mutex1).lock()).assume_init(); + if let Some(tcb) = tcb.as_mut() { - tcb.activate(); + tcb.activate( + #[cfg(target_os = "redox")] + redox_rt::proc::FdGuard::new(tid.thread_fd), + ); } let procmask = (&*mutex2).as_ptr().read(); - let tid = (*(&*mutex1).lock()).assume_init(); - - #[cfg(target_os = "redox")] - (*tcb) - .os_specific - .thr_fd - .get() - .write(Some(redox_rt::proc::FdGuard::new(tid.thread_fd))); if let Some(tcb) = tcb.as_mut() { tcb.copy_masters().unwrap(); diff --git a/src/start.rs b/src/start.rs index 3d56738632..faca8b65ec 100644 --- a/src/start.rs +++ b/src/start.rs @@ -2,6 +2,7 @@ use alloc::{boxed::Box, vec::Vec}; use core::{intrinsics, ptr}; +use generic_rt::ExpectTlsFree; use crate::{ header::{libgen, stdio, stdlib}, @@ -141,8 +142,18 @@ pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! { // Ensure correct host system before executing more system calls relibc_verify_host(); + #[cfg(target_os = "redox")] + let thr_fd = redox_rt::proc::FdGuard::new( + crate::platform::get_auxv_raw(sp.auxv().cast(), redox_rt::auxv_defs::AT_REDOX_THR_FD) + .expect_notls("no thread fd present"), + ); + // Initialize TLS, if necessary - ld_so::init(sp); + ld_so::init( + sp, + #[cfg(target_os = "redox")] + thr_fd, + ); // Set up the right allocator... // if any memory rust based memory allocation happen before this step .. we are doomed.