Add prototype ucontext_t support.

This commit is contained in:
4lDO2
2024-07-30 23:24:42 +02:00
parent b48da5622d
commit abc2ec7bb5
5 changed files with 138 additions and 23 deletions
+3 -3
View File
@@ -222,13 +222,13 @@ asmfunction!(__relibc_internal_sigentry: ["
push eax
push dword ptr gs:[{tcb_sa_off} + {sa_tmp_ptr}]
sub esp, 2 * 4
sub esp, 24
mov ecx, esp
call {inner}
fxrstor [esp + 16]
add esp, 16 + 29 * 16 + 2 * 4
fxrstor [esp + 32]
add esp, 32 + 29 * 16 + 2 * 4
pop ebp
pop esi
+4 -1
View File
@@ -1,5 +1,6 @@
use core::{
mem::offset_of,
ptr::NonNull,
sync::atomic::{AtomicU8, Ordering},
};
@@ -33,6 +34,7 @@ pub struct SigArea {
pub altstack_bottom: usize,
pub disable_signals_depth: u64,
pub last_sig_was_restart: bool,
pub last_sigstack: Option<NonNull<SigStack>>,
}
#[repr(C, align(16))]
@@ -301,11 +303,12 @@ asmfunction!(__relibc_internal_sigentry: ["
5:
push rax // selected signal
push fs:[{tcb_sa_off} + {sa_tmp_ptr}]
sub rsp, 48 // alloc space for ucontext fields
mov rdi, rsp
call {inner}
add rsp, 16
add rsp, 64
fxrstor64 [rsp + 16 * 16]
+38 -17
View File
@@ -1,6 +1,7 @@
use core::{
cell::{Cell, UnsafeCell},
ffi::{c_int, c_void},
ptr::NonNull,
sync::atomic::{AtomicU8, AtomicUsize, Ordering},
};
@@ -22,14 +23,19 @@ pub fn sighandler_function() -> usize {
__relibc_internal_sigentry as usize
}
/// ucontext_t representation
#[repr(C)]
pub struct SigStack {
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
_pad: [usize; 0], // pad to 16 bytes alignment
_pad: [usize; 1], // pad from 7*8 to 64
#[cfg(target_arch = "x86")]
_pad: [usize; 2], // pad to 16 bytes alignment
_pad: [usize; 0], // don't pad from 8*4
pub link: *mut SigStack,
pub old_stack: PosixStackt,
pub old_mask: u64,
sival: usize,
sig_num: usize,
@@ -38,10 +44,35 @@ pub struct SigStack {
// aarch64: 272 bytes (SIMD TODO)
pub regs: ArchIntRegs,
}
#[repr(C)]
pub struct PosixStackt {
pub sp: *mut (),
pub flags: i32,
pub size: usize,
}
#[repr(C)]
// TODO: This struct is for practical reasons locked to Linux's ABI, but avoid redefining
// it here. Alternatively, check at compile time that the structs are equivalent.
pub struct SiginfoAbi {
pub si_signo: i32,
pub si_errno: i32,
pub si_code: i32,
pub si_pid: i32, // pid_t
pub si_uid: i32, // uid_t
pub si_addr: *mut (), // *mut c_void
pub si_status: i32,
pub si_value: usize, // sigval
}
#[inline(always)]
unsafe fn inner(stack: &mut SigStack) {
let os = &Tcb::current().unwrap().os_specific;
let stack_ptr = NonNull::from(&mut *stack);
stack.link = core::mem::replace(&mut (*os.arch.get()).last_sigstack, Some(stack_ptr))
.map_or_else(core::ptr::null_mut, |x| x.as_ptr());
let signals_were_disabled = (*os.arch.get()).disable_signals_depth > 0;
let _targeted_thread_not_process = stack.sig_num >= 64;
@@ -119,21 +150,11 @@ unsafe fn inner(stack: &mut SigStack) {
if sigaction.flags.contains(SigactionFlags::SIGINFO)
&& let Some(sigaction) = handler.sigaction
{
stack.old_mask = ((prev_w1 >> 32) << 32) | (prev_w0 & 0xffff_ffff);
// TODO: stack.old_stack
//let _ = syscall::write(1, alloc::format!("SIGACTION {:p}\n", sigaction).as_bytes());
// TODO: This struct is for practical reasons locked to Linux's ABI, but avoid redefining
// it here. Alternatively, check at compile time that the structs are equivalent.
#[repr(C)]
struct siginfo {
si_signo: c_int,
si_errno: c_int,
si_code: c_int,
si_pid: c_int, // TODO pid_t
si_uid: c_int, // TODO uid_t
si_addr: *mut c_void,
si_status: c_int,
si_value: usize, // TODO union
}
let info = siginfo {
let info = SiginfoAbi {
si_signo: stack.sig_num as c_int,
si_addr: core::ptr::null_mut(),
si_code: 0, // TODO: SIG_QUEUE/SIG_USER/etc
@@ -146,7 +167,7 @@ unsafe fn inner(stack: &mut SigStack) {
sigaction(
stack.sig_num as c_int,
core::ptr::addr_of!(info).cast(),
core::ptr::null_mut(), // TODO
stack as *mut SigStack as *mut (),
);
} else if let Some(handler) = handler.handler {
//let _ = syscall::write(1, alloc::format!("HANDLER {:p}\n", handler).as_bytes());
+42
View File
@@ -14,6 +14,48 @@ use crate::{
},
};
// Mirrors the ucontext_t struct from the libc crate on Linux.
#[repr(C)]
pub struct ucontext_t {
pub uc_flags: c_ulong,
pub uc_link: *mut ucontext_t,
pub uc_stack: stack_t,
pub uc_mcontext: mcontext_t,
pub uc_sigmask: sigset_t,
__private: [u8; 512],
}
#[repr(C)]
pub struct _libc_fpstate {
pub cwd: u16,
pub swd: u16,
pub ftw: u16,
pub fop: u16,
pub rip: u64,
pub rdp: u64,
pub mxcsr: u32,
pub mxcr_mask: u32,
pub _st: [_libc_fpxreg; 8],
pub _xmm: [_libc_xmmreg; 16],
__private: [u64; 12],
}
#[repr(C)]
pub struct _libc_fpxreg {
pub significand: [u16; 4],
pub exponent: u16,
__private: [u16; 3],
}
#[repr(C)]
pub struct _libc_xmmreg {
pub element: [u32; 4],
}
#[repr(C)]
pub struct mcontext_t {
pub gregs: [i64; 23], // TODO: greg_t?
pub fpregs: *mut _libc_fpstate,
__private: [u64; 8],
}
impl PalSignal for Sys {
unsafe fn getitimer(which: c_int, out: *mut itimerval) -> c_int {
e(syscall!(GETITIMER, which, out)) as c_int
+51 -2
View File
@@ -1,5 +1,7 @@
use core::mem;
use redox_rt::signal::{Sigaction, SigactionFlags, SigactionKind, Sigaltstack, SignalHandler};
use core::mem::{self, offset_of};
use redox_rt::signal::{
SigStack, Sigaction, SigactionFlags, SigactionKind, Sigaltstack, SignalHandler,
};
use syscall::{self, Result};
use super::{
@@ -20,6 +22,53 @@ use crate::{
platform::ERRNO,
};
#[repr(C)]
pub struct ucontext_t {
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
_pad: [usize; 1], // pad from 7*8 to 64
#[cfg(target_arch = "x86")]
_pad: [usize; 0], // don't pad from 8*4
pub uc_link: *mut ucontext_t,
pub uc_stack: stack_t,
pub uc_sigmask: sigset_t,
_sival: usize,
_signum: usize,
pub uc_mcontext: mcontext_t,
}
const _: () = {
const fn assert_eq(a: usize, b: usize) {
if a != b {
panic!("compile-time struct verification failed");
}
}
assert_eq(offset_of!(ucontext_t, uc_link), offset_of!(SigStack, link));
assert_eq(
offset_of!(ucontext_t, uc_stack),
offset_of!(SigStack, old_stack),
);
assert_eq(
offset_of!(ucontext_t, uc_sigmask),
offset_of!(SigStack, old_mask),
);
assert_eq(
offset_of!(ucontext_t, uc_mcontext),
offset_of!(SigStack, regs),
);
};
#[repr(C)]
pub struct mcontext_t {
#[cfg(target_arch = "x86")]
_opaque: [u8; 512],
#[cfg(target_arch = "x86-64")]
_opaque: [u8; 864],
#[cfg(target_arch = "aarch64")]
_opaque: [u8; 272],
}
impl PalSignal for Sys {
unsafe fn getitimer(which: c_int, out: *mut itimerval) -> c_int {
let path = match which {