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:
Generated
+4
-4
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user