diff --git a/Cargo.lock b/Cargo.lock index 09b816edf6..ab80fb44fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -343,9 +343,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index 78cf6445fa..f7ff066279 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,7 @@ features = ["c_api"] sc = "0.2.3" [target.'cfg(target_os = "redox")'.dependencies] -redox_syscall = "0.5.5" +redox_syscall = "0.5.8" redox-rt = { path = "redox-rt" } redox-path = "0.2" redox_event = { git = "https://gitlab.redox-os.org/redox-os/event.git", default-features = false, features = ["redox_syscall"] } diff --git a/redox-rt/Cargo.toml b/redox-rt/Cargo.toml index 33502bb75f..a69851747e 100644 --- a/redox-rt/Cargo.toml +++ b/redox-rt/Cargo.toml @@ -12,6 +12,6 @@ description = "Libc-independent runtime for Redox" bitflags = "2" goblin = { version = "0.7", default-features = false, features = ["elf32", "elf64", "endian_fd"] } plain = "0.2" -redox_syscall = "0.5.3" +redox_syscall = "0.5.8" generic-rt = { path = "../generic-rt" } diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index ace6508746..5e95514da1 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -191,10 +191,57 @@ impl Linker { unsafe { if !dlopened { + #[cfg(target_os = "redox")] + let (tcb, old_tcb) = { + use redox_rt::signal::tmp_disable_signals; + + let old_tcb = Tcb::current().expect("failed to get bootstrap TCB"); + let new_tcb = Tcb::new(self.tls_size)?; // This actually allocates TCB, TLS and ABI page. + + // Stash + let new_tls_end = new_tcb.generic.tls_end; + let new_tls_len = new_tcb.generic.tls_len; + let new_tcb_ptr = new_tcb.generic.tcb_ptr; + let new_tcb_len = new_tcb.generic.tcb_len; + + // Unmap just the TCB page. + Sys::munmap(new_tcb as *mut Tcb as *mut c_void, syscall::PAGE_SIZE).unwrap(); + + let new_addr = ptr::addr_of!(*new_tcb) as usize; + + assert_eq!( + syscall::syscall5( + syscall::SYS_MREMAP, + old_tcb as *mut Tcb as usize, + syscall::PAGE_SIZE, + new_addr, + syscall::PAGE_SIZE, + (syscall::MremapFlags::FIXED | syscall::MremapFlags::KEEP_OLD).bits() + | (syscall::MapFlags::PROT_READ | syscall::MapFlags::PROT_WRITE) + .bits(), + ) + .expect("mremap: failed to alias TCB"), + new_addr, + ); + // XXX: New TCB is now at the same physical address as the old TCB. + + let _guard = tmp_disable_signals(); + // Restore + new_tcb.generic.tls_end = new_tls_end; + new_tcb.generic.tls_len = new_tls_len; + new_tcb.generic.tcb_ptr = new_tcb_ptr; + new_tcb.generic.tcb_len = new_tcb_len; + + drop(_guard); + (new_tcb, old_tcb as *mut Tcb as *mut c_void) + }; + + #[cfg(not(target_os = "redox"))] + let tcb = Tcb::new(self.tls_size)?; + // We are now loading the main program or its dependencies. The TLS for all initially // loaded objects reside in the static TLS block. Depending on the architecture, the // static TLS block is either placed before the TP or after the TP. - let tcb = Tcb::new(self.tls_size)?; let tcb_ptr = tcb as *mut Tcb; // Setup the DTVs. @@ -227,6 +274,12 @@ impl Linker { // Copy the master data into the static TLS block. tcb.copy_masters()?; tcb.activate(); + + #[cfg(target_os = "redox")] + { + // Unmap the old TCB. + Sys::munmap(old_tcb, syscall::PAGE_SIZE).unwrap(); + } } else { let tcb = Tcb::current().expect("failed to get current tcb");