Add prototype ucontext_t support.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user