Merge branch 'manual_redox_tls' into 'master'

Initialize TLS manually on Redox as Linux does.

See merge request redox-os/relibc!340
This commit is contained in:
4lDO2
2021-08-06 13:24:48 +00:00
6 changed files with 97 additions and 50 deletions
Generated
+4 -4
View File
@@ -344,9 +344,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "redox_syscall"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
@@ -366,7 +366,7 @@ dependencies = [
"posix-regex",
"ralloc",
"rand 0.5.6",
"redox_syscall 0.2.9",
"redox_syscall 0.2.10",
"sc",
"spin 0.9.2",
]
@@ -541,7 +541,7 @@ dependencies = [
"cfg-if",
"libc",
"rand 0.8.4",
"redox_syscall 0.2.9",
"redox_syscall 0.2.10",
"remove_dir_all",
"winapi",
]
+1 -1
View File
@@ -39,7 +39,7 @@ optional = true
sc = "0.2.3"
[target.'cfg(target_os = "redox")'.dependencies]
redox_syscall = "0.2.9"
redox_syscall = "0.2.10"
spin = "0.9.0"
[features]
+63 -12
View File
@@ -28,6 +28,41 @@ static mut STATIC_TCB_MASTER: Master = Master {
offset: 0,
};
fn panic_notls(msg: impl core::fmt::Display) -> ! {
eprintln!("panicked in ld.so: {}", msg);
unsafe {
core::intrinsics::abort();
}
}
pub trait ExpectTlsFree {
type Unwrapped;
fn expect_notls(self, msg: &str) -> Self::Unwrapped;
}
impl<T, E: core::fmt::Debug> ExpectTlsFree for Result<T, E> {
type Unwrapped = T;
fn expect_notls(self, msg: &str) -> T {
match self {
Ok(t) => t,
Err(err) => panic_notls(format_args!("expect failed for Result with err: {:?}", err)),
}
}
}
impl<T> ExpectTlsFree for Option<T> {
type Unwrapped = T;
fn expect_notls(self, msg: &str) -> T {
match self {
Some(t) => t,
None => panic_notls("expect failed for Option"),
}
}
}
#[inline(never)]
pub fn static_init(sp: &'static Stack) {
let mut phdr_opt = None;
let mut phent_opt = None;
@@ -50,9 +85,9 @@ pub fn static_init(sp: &'static Stack) {
auxv = unsafe { auxv.add(1) };
}
let phdr = phdr_opt.expect("failed to find AT_PHDR");
let phent = phent_opt.expect("failed to find AT_PHENT");
let phnum = phnum_opt.expect("failed to find AT_PHNUM");
let phdr = phdr_opt.expect_notls("failed to find AT_PHDR");
let phent = phent_opt.expect_notls("failed to find AT_PHENT");
let phnum = phnum_opt.expect_notls("failed to find AT_PHNUM");
for i in 0..phnum {
let ph_addr = phdr + phent * i;
@@ -63,7 +98,7 @@ pub fn static_init(sp: &'static Stack) {
program_header64::SIZEOF_PHDR => {
unsafe { *(ph_addr as *const program_header64::ProgramHeader) }.into()
}
_ => panic!("unknown AT_PHENT size {}", phent),
_ => panic_notls(format_args!("unknown AT_PHENT size {}", phent)),
};
let page_size = Sys::getpagesize();
@@ -84,10 +119,10 @@ pub fn static_init(sp: &'static Stack) {
STATIC_TCB_MASTER.len = ph.p_filesz as usize;
STATIC_TCB_MASTER.offset = valign;
let tcb = Tcb::new(vsize).expect("failed to allocate TCB");
let tcb = Tcb::new(vsize).expect_notls("failed to allocate TCB");
tcb.masters_ptr = &mut STATIC_TCB_MASTER;
tcb.masters_len = mem::size_of::<Master>();
tcb.copy_masters().expect("failed to copy TLS master data");
tcb.copy_masters().expect_notls("failed to copy TLS master data");
tcb.activate();
}
@@ -99,19 +134,35 @@ pub fn static_init(sp: &'static Stack) {
}
}
#[cfg(target_os = "linux")]
#[cfg(any(target_os = "linux", target_os = "redox"))]
pub unsafe fn init(sp: &'static Stack) {
let mut tp = 0usize;
const ARCH_GET_FS: usize = 0x1003;
syscall!(ARCH_PRCTL, ARCH_GET_FS, &mut tp as *mut usize);
#[cfg(target_os = "linux")]
{
const ARCH_GET_FS: usize = 0x1003;
syscall!(ARCH_PRCTL, ARCH_GET_FS, &mut tp as *mut usize);
}
#[cfg(target_os = "redox")]
{
let mut env = syscall::EnvRegisters::default();
let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDONLY)
.expect_notls("failed to open handle for process registers");
let _ = syscall::read(file, &mut env)
.expect_notls("failed to read fsbase");
let _ = syscall::close(file);
tp = env.fsbase as usize;
}
if tp == 0 {
static_init(sp);
}
}
#[cfg(target_os = "redox")]
pub unsafe fn init(_sp: &'static Stack) {}
pub unsafe fn fini() {
if let Some(tcb) = Tcb::current() {
if tcb.linker_ptr != ptr::null_mut() {
+22 -26
View File
@@ -4,7 +4,7 @@ use goblin::error::{Error, Result};
use crate::{
header::sys_mman,
ld_so::linker::Linker,
ld_so::{linker::Linker, ExpectTlsFree},
platform::{Pal, Sys},
sync::mutex::Mutex,
};
@@ -186,30 +186,14 @@ impl Tcb {
Ok(slice::from_raw_parts_mut(ptr as *mut u8, size))
}
/// OS specific code to create a new TLS and TCB - Linux
#[cfg(target_os = "linux")]
/// OS specific code to create a new TLS and TCB - Linux and Redox
#[cfg(any(target_os = "linux", target_os = "redox"))]
unsafe fn os_new(size: usize) -> Result<(&'static mut [u8], &'static mut [u8])> {
let page_size = Sys::getpagesize();
let tls_tcb = Self::map(size + page_size)?;
Ok(tls_tcb.split_at_mut(size))
}
/// OS specific code to create a new TLS and TCB - Redox
#[cfg(target_os = "redox")]
unsafe fn os_new(size: usize) -> Result<(&'static mut [u8], &'static mut [u8])> {
use crate::header::unistd;
//TODO: better method of finding fs offset
let pid = unistd::getpid();
let page_size = Sys::getpagesize();
let tcb_addr = 0xB000_0000 + pid as usize * page_size;
let tls = Self::map(size)?;
Ok((
tls,
//TODO: Consider allocating TCB as part of TLS
slice::from_raw_parts_mut(tcb_addr as *mut u8, page_size),
))
}
/// Architecture specific code to read a usize from the TCB - x86_64
#[inline(always)]
#[cfg(target_arch = "aarch64")]
@@ -230,13 +214,12 @@ impl Tcb {
#[cfg(target_arch = "x86_64")]
unsafe fn arch_read(offset: usize) -> usize {
let value;
llvm_asm!("
mov rax, fs:[rdi]
asm!(
"
: "={rax}"(value)
: "{rdi}"(offset)
:
: "intel"
mov {}, fs:[{}]
",
out(reg) value,
in(reg) offset,
);
value
}
@@ -257,7 +240,20 @@ impl Tcb {
/// OS and architecture specific code to activate TLS - Redox x86_64
#[cfg(all(target_os = "redox", target_arch = "x86_64"))]
unsafe fn os_arch_activate(tp: usize) {
//TODO: Consider setting FS offset to TCB pointer
let mut env = syscall::EnvRegisters::default();
let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDWR)
.expect_notls("failed to open handle for process registers");
let _ = syscall::read(file, &mut env)
.expect_notls("failed to read fsbase");
env.fsbase = tp as u64;
let _ = syscall::write(file, &env)
.expect_notls("failed to write fsbase");
let _ = syscall::close(file);
}
}
+1
View File
@@ -6,6 +6,7 @@
#![feature(asm)]
#![feature(box_into_pin)]
#![feature(c_variadic)]
#![feature(const_btree_new)]
#![feature(const_raw_ptr_deref)]
#![feature(core_intrinsics)]
#![feature(global_asm)]
+6 -7
View File
@@ -2,6 +2,7 @@
use alloc::{boxed::Box, collections::BTreeMap};
use core::{
cell::UnsafeCell,
intrinsics, ptr,
sync::atomic::{AtomicU32, Ordering},
};
@@ -45,16 +46,14 @@ static mut pid_mutexes_lock: Mutex<()> = Mutex::new(());
static mut pid_stacks: Option<BTreeMap<pte_osThreadHandle, (*mut c_void, size_t)>> = None;
static mut pid_stacks_lock: Mutex<()> = Mutex::new(());
// TODO: VecMap/SLOB (speed) / radix tree (speed while allowing randomization for security).
#[thread_local]
static mut LOCALS: *mut BTreeMap<c_uint, *mut c_void> = ptr::null_mut();
static LOCALS: UnsafeCell<BTreeMap<c_uint, *mut c_void>> = UnsafeCell::new(BTreeMap::new());
static NEXT_KEY: AtomicU32 = AtomicU32::new(0);
unsafe fn locals() -> &'static mut BTreeMap<c_uint, *mut c_void> {
if LOCALS.is_null() {
LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
}
&mut *LOCALS
unsafe fn locals<'a>() -> &'a mut BTreeMap<c_uint, *mut c_void> {
&mut *LOCALS.get()
}
// pte_osResult pte_osInit(void)
@@ -403,7 +402,7 @@ pub unsafe extern "C" fn pte_osTlsGetValue(index: c_uint) -> *mut c_void {
#[no_mangle]
pub unsafe extern "C" fn pte_osTlsAlloc(pKey: *mut c_uint) -> pte_osResult {
*pKey = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
*pKey = NEXT_KEY.fetch_add(1, Ordering::Relaxed);
PTE_OS_OK
}