Implement signal selection in asm, for SA_ONSTACK.
This commit is contained in:
+45
-15
@@ -16,6 +16,7 @@ pub struct SigArea {
|
||||
altstack_top: usize,
|
||||
altstack_bottom: usize,
|
||||
tmp: usize,
|
||||
pub onstack: u64,
|
||||
pub disable_signals_depth: u64,
|
||||
}
|
||||
|
||||
@@ -128,18 +129,41 @@ asmfunction!(__relibc_internal_rlct_clone_ret -> usize: ["
|
||||
"] <= []);
|
||||
|
||||
asmfunction!(__relibc_internal_sigentry: ["
|
||||
// Get offset to TCB
|
||||
mov rax, gs:[0]
|
||||
// First, select signal, always pick first available bit
|
||||
|
||||
// Read first signal word
|
||||
mov rdx, fs:[{tcb_sc_off} + {sc_word}]
|
||||
mov rcx, rdx
|
||||
shr rcx, 32
|
||||
and edx, ecx
|
||||
bsf edx, edx
|
||||
jnz 2f
|
||||
|
||||
// Read second signal word
|
||||
mov rdx, fs:[{tcb_sc_off} + {sc_word} + 8]
|
||||
mov rcx, rdx
|
||||
shr rcx, 32
|
||||
and edx, ecx
|
||||
bsf edx, edx
|
||||
jnz 4f
|
||||
add edx, 32
|
||||
2:
|
||||
// By now we have selected a signal, stored in edx (6-bit). We now need to choose whether or
|
||||
// not to switch to the alternate signal stack. If SA_ONSTACK is clear for this signal, then
|
||||
// skip the sigaltstack logic.
|
||||
bt fs:[{tcb_sa_off} + {sa_onstack}], edx
|
||||
jc 3f
|
||||
|
||||
// If current RSP is above altstack region, switch to altstack
|
||||
mov rdx, [rax + {tcb_sa_off} + {sa_altstack_top}]
|
||||
mov rdx, fs:[{tcb_sa_off} + {sa_altstack_top}]
|
||||
cmp rdx, rsp
|
||||
cmova rsp, rdx
|
||||
|
||||
// If current RSP is below altstack region, also switch to altstack
|
||||
mov rdx, [rax + {tcb_sa_off} + {sa_altstack_bottom}]
|
||||
cmp rdx, rax
|
||||
mov rdx, fs:[{tcb_sa_off} + {sa_altstack_bottom}]
|
||||
cmp rdx, rsp
|
||||
cmovbe rsp, rdx
|
||||
3:
|
||||
|
||||
// Otherwise, the altstack is already active. The sigaltstack being disabled, is equivalent
|
||||
// to setting 'top' to usize::MAX and 'bottom' to 0.
|
||||
@@ -147,16 +171,16 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
// Now that we have a stack, we can finally start initializing the signal stack!
|
||||
|
||||
push 0 // SS
|
||||
push [rax + {tcb_sc_off} + {sc_saved_rsp}]
|
||||
push [rax + {tcb_sc_off} + {sc_saved_rflags}]
|
||||
push fs:[{tcb_sc_off} + {sc_saved_rsp}]
|
||||
push fs:[{tcb_sc_off} + {sc_saved_rflags}]
|
||||
push 0 // CS
|
||||
push [rax + {tcb_sc_off} + {sc_saved_rip}]
|
||||
push fs:[{tcb_sc_off} + {sc_saved_rip}]
|
||||
|
||||
push rdi
|
||||
push rsi
|
||||
push [rax + {tcb_sc_off} + {sc_saved_rdx}]
|
||||
push fs:[{tcb_sc_off} + {sc_saved_rdx}]
|
||||
push rcx
|
||||
push [rax + {tcb_sc_off} + {sc_saved_rax}]
|
||||
push fs:[{tcb_sc_off} + {sc_saved_rax}]
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
@@ -168,12 +192,14 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
push r14
|
||||
push r15
|
||||
|
||||
sub rsp, 4096 + 32
|
||||
push rdx // selected signal
|
||||
|
||||
sub rsp, 4096 + 24
|
||||
|
||||
cld
|
||||
mov rdi, rsp
|
||||
xor eax, eax
|
||||
mov ecx, 4096 + 32
|
||||
mov ecx, 4096 + 24
|
||||
rep stosb
|
||||
|
||||
// TODO: self-modifying?
|
||||
@@ -191,7 +217,7 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
mov edx, eax
|
||||
xrstor [rsp]
|
||||
|
||||
add rsp, 4096 + 32
|
||||
add rsp, 4096 + 24
|
||||
2:
|
||||
pop r15
|
||||
pop r14
|
||||
@@ -209,11 +235,11 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
pop rsi
|
||||
pop rdi
|
||||
|
||||
pop qword ptr gs:[{tcb_sa_off} + {sa_tmp}]
|
||||
pop qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
|
||||
add rsp, 8
|
||||
popfq
|
||||
pop rsp
|
||||
jmp qword ptr gs:[{tcb_sa_off} + {sa_tmp}]
|
||||
jmp qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
|
||||
3:
|
||||
fxsave64 [rsp]
|
||||
|
||||
@@ -222,16 +248,20 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
|
||||
fxrstor64 [rsp]
|
||||
jmp 2b
|
||||
4:
|
||||
// Spurious signal
|
||||
"] <= [
|
||||
inner = sym inner_c,
|
||||
sa_tmp = const offset_of!(SigArea, tmp),
|
||||
sa_altstack_top = const offset_of!(SigArea, altstack_top),
|
||||
sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom),
|
||||
sa_onstack = const offset_of!(SigArea, onstack),
|
||||
sc_saved_rax = const offset_of!(Sigcontrol, saved_scratch_a),
|
||||
sc_saved_rdx = const offset_of!(Sigcontrol, saved_scratch_b),
|
||||
sc_saved_rflags = const offset_of!(Sigcontrol, saved_flags),
|
||||
sc_saved_rip = const offset_of!(Sigcontrol, saved_ip),
|
||||
sc_saved_rsp = const offset_of!(Sigcontrol, saved_sp),
|
||||
sc_word = const offset_of!(Sigcontrol, word),
|
||||
tcb_sa_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, arch),
|
||||
tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control),
|
||||
supports_xsave = sym SUPPORTS_XSAVE,
|
||||
|
||||
+44
-16
@@ -2,7 +2,7 @@ use core::cell::Cell;
|
||||
use core::ffi::c_int;
|
||||
use core::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use syscall::{Error, IntRegisters, Result, SetSighandlerData, SigProcControl, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH};
|
||||
use syscall::{Error, IntRegisters, Result, SetSighandlerData, SigProcControl, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_NOCLDSTOP_BIT, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH};
|
||||
|
||||
use crate::{arch::*, Tcb};
|
||||
use crate::sync::Mutex;
|
||||
@@ -104,16 +104,24 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Sigaction {
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub enum SigactionKind {
|
||||
#[default]
|
||||
Default,
|
||||
|
||||
Ignore,
|
||||
Handled {
|
||||
handler: SignalHandler,
|
||||
mask: u64,
|
||||
flags: SigactionFlags,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Sigaction {
|
||||
pub kind: SigactionKind,
|
||||
pub mask: u64,
|
||||
pub flags: SigactionFlags,
|
||||
}
|
||||
|
||||
pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> {
|
||||
if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) {
|
||||
return Err(Error::new(EINVAL));
|
||||
@@ -125,39 +133,59 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction
|
||||
let old_ignmask = IGNMASK.load(Ordering::Relaxed);
|
||||
|
||||
if let Some(old) = old {
|
||||
// TODO
|
||||
}
|
||||
|
||||
let Some(new) = new else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
match (usize::from(signal), new) {
|
||||
(_, Sigaction::Ignore) | (SIGCHLD | SIGURG | SIGWINCH, Sigaction::Default) => {
|
||||
let sig_group = usize::from(signal) / 32;
|
||||
let sig_bit32 = 1 << ((signal - 1) % 32);
|
||||
|
||||
match (usize::from(signal), new.kind) {
|
||||
(_, SigactionKind::Ignore) | (SIGURG | SIGWINCH, SigactionKind::Default) => {
|
||||
IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed);
|
||||
|
||||
// mark the signal as masked
|
||||
ctl.word[usize::from(signal) / 32].fetch_or(1 << ((signal - 1) % 32), Ordering::Relaxed);
|
||||
ctl.word[sig_group].fetch_or(sig_bit32, Ordering::Relaxed);
|
||||
|
||||
// POSIX specifies that pending signals shall be discarded if set to SIG_IGN by
|
||||
// sigaction.
|
||||
// TODO: handle tmp_disable_signals
|
||||
}
|
||||
// TODO: Handle pending signals before these flags are set.
|
||||
(SIGTSTP, Sigaction::Default) => {
|
||||
(SIGTSTP, SigactionKind::Default) => {
|
||||
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TSTP_IS_STOP_BIT, Ordering::SeqCst);
|
||||
}
|
||||
(SIGTTIN, Sigaction::Default) => {
|
||||
(SIGTTIN, SigactionKind::Default) => {
|
||||
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTIN_IS_STOP_BIT, Ordering::SeqCst);
|
||||
}
|
||||
(SIGTTOU, Sigaction::Default) => {
|
||||
(SIGTTOU, SigactionKind::Default) => {
|
||||
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTOU_IS_STOP_BIT, Ordering::SeqCst);
|
||||
}
|
||||
(SIGCHLD, SigactionKind::Default) => {
|
||||
if new.flags.contains(SigactionFlags::NOCLDSTOP) {
|
||||
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst);
|
||||
} else {
|
||||
PROC_CONTROL_STRUCT.word[0].fetch_and(!SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst);
|
||||
}
|
||||
IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed);
|
||||
|
||||
(_, Sigaction::Default) => (),
|
||||
(_, Sigaction::Handled { .. }) => (),
|
||||
// mark the signal as masked
|
||||
ctl.word[sig_group].fetch_or(sig_bit32, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
(_, SigactionKind::Default) => {
|
||||
IGNMASK.store(old_ignmask & !sig_bit(signal.into()), Ordering::Relaxed);
|
||||
|
||||
// TODO: update mask
|
||||
//ctl.word[usize::from(signal)].fetch_or();
|
||||
},
|
||||
(_, SigactionKind::Handled { .. }) => (),
|
||||
}
|
||||
|
||||
todo!()
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn current_sigctl() -> &'static Sigcontrol {
|
||||
@@ -192,7 +220,7 @@ impl Drop for TmpDisableSignalsGuard {
|
||||
|
||||
bitflags::bitflags! {
|
||||
// Some flags are ignored by the rt, but they match relibc's 1:1 to simplify conversion.
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct SigactionFlags: u32 {
|
||||
const NOCLDSTOP = 1;
|
||||
const NOCLDWAIT = 2;
|
||||
@@ -226,7 +254,7 @@ struct TheDefault {
|
||||
ignmask: u64,
|
||||
}
|
||||
|
||||
static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction::Default; 64]);
|
||||
static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction { flags: SigactionFlags::empty(), mask: 0, kind: SigactionKind::Default }; 64]);
|
||||
static IGNMASK: AtomicU64 = AtomicU64::new(sig_bit(SIGCHLD) | sig_bit(SIGURG) | sig_bit(SIGWINCH));
|
||||
|
||||
static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use core::mem;
|
||||
use redox_rt::signal::{Sigaction, SigactionFlags, SignalHandler};
|
||||
use redox_rt::signal::{Sigaction, SigactionFlags, SigactionKind, SignalHandler};
|
||||
use syscall::{self, Result};
|
||||
|
||||
use super::{
|
||||
@@ -111,49 +111,53 @@ impl PalSignal for Sys {
|
||||
let new_action = c_act.map(|c_act| {
|
||||
let handler = c_act.sa_handler.map_or(0, |f| f as usize);
|
||||
|
||||
if handler == SIG_DFL {
|
||||
Sigaction::Default
|
||||
let kind = if handler == SIG_DFL {
|
||||
SigactionKind::Default
|
||||
} else if handler == SIG_IGN {
|
||||
Sigaction::Ignore
|
||||
SigactionKind::Ignore
|
||||
} else {
|
||||
Sigaction::Handled {
|
||||
SigactionKind::Handled {
|
||||
handler: if c_act.sa_flags & crate::header::signal::SA_SIGINFO as u64 != 0 {
|
||||
SignalHandler { sigaction: unsafe { core::mem::transmute(c_act.sa_handler) } }
|
||||
} else {
|
||||
SignalHandler { handler: c_act.sa_handler }
|
||||
},
|
||||
mask: c_act.sa_mask,
|
||||
flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
|
||||
}
|
||||
};
|
||||
|
||||
Sigaction {
|
||||
kind,
|
||||
mask: c_act.sa_mask,
|
||||
flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
|
||||
}
|
||||
});
|
||||
let mut old_action = c_oact.as_ref().map(|_| Sigaction::Default);
|
||||
let mut old_action = c_oact.as_ref().map(|_| Sigaction::default());
|
||||
|
||||
redox_rt::signal::sigaction(sig, new_action.as_ref(), old_action.as_mut())?;
|
||||
|
||||
if let (Some(c_oact), Some(old_action)) = (c_oact, old_action) {
|
||||
*c_oact = match old_action {
|
||||
Sigaction::Ignore => sigaction {
|
||||
*c_oact = match old_action.kind {
|
||||
SigactionKind::Ignore => sigaction {
|
||||
sa_handler: unsafe { core::mem::transmute(SIG_IGN) },
|
||||
sa_flags: 0,
|
||||
sa_restorer: None,
|
||||
sa_mask: 0,
|
||||
},
|
||||
Sigaction::Default => sigaction {
|
||||
SigactionKind::Default => sigaction {
|
||||
sa_handler: unsafe { core::mem::transmute(SIG_DFL) },
|
||||
sa_flags: 0,
|
||||
sa_restorer: None,
|
||||
sa_mask: 0,
|
||||
},
|
||||
Sigaction::Handled { handler, mask, flags } => sigaction {
|
||||
sa_handler: if flags.contains(SigactionFlags::SIGINFO) {
|
||||
SigactionKind::Handled { handler } => sigaction {
|
||||
sa_handler: if old_action.flags.contains(SigactionFlags::SIGINFO) {
|
||||
unsafe { core::mem::transmute(handler.sigaction) }
|
||||
} else {
|
||||
unsafe { handler.handler }
|
||||
},
|
||||
sa_restorer: None,
|
||||
sa_flags: flags.bits().into(),
|
||||
sa_mask: mask,
|
||||
sa_flags: old_action.flags.bits().into(),
|
||||
sa_mask: old_action.mask,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user