@@ -253,6 +253,9 @@ long do_sigreturn(CPUMIPSState *regs)
abi_ulong frame_addr;
sigset_t blocked;
target_sigset_t target_set;
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigset_t target_blocked;
+#endif
int i;
frame_addr = regs->active_tc.gpr[29];
@@ -265,7 +268,12 @@ long do_sigreturn(CPUMIPSState *regs)
}
target_to_host_sigset_internal(&blocked, &target_set);
+#ifdef TRACK_TARGET_SIGMASK
+ tswapal_target_sigset(&target_blocked, &target_set);
+ target_set_sigmask(&blocked, &target_blocked);
+#else
set_sigmask(&blocked);
+#endif
restore_sigcontext(regs, &frame->sf_sc);
@@ -358,6 +366,9 @@ long do_rt_sigreturn(CPUMIPSState *env)
struct target_rt_sigframe *frame;
abi_ulong frame_addr;
sigset_t blocked;
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigset_t target_blocked;
+#endif
frame_addr = env->active_tc.gpr[29];
trace_user_do_rt_sigreturn(env, frame_addr);
@@ -366,7 +377,12 @@ long do_rt_sigreturn(CPUMIPSState *env)
}
target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
+#ifdef TRACK_TARGET_SIGMASK
+ tswapal_target_sigset(&target_blocked, &frame->rs_uc.tuc_sigmask);
+ target_set_sigmask(&blocked, &target_blocked);
+#else
set_sigmask(&blocked);
+#endif
restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
@@ -401,12 +401,18 @@ void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
int target_to_host_signal(int sig);
int host_to_target_signal(int sig);
+void tswapal_target_sigset(target_sigset_t *d, const target_sigset_t *s);
long do_sigreturn(CPUArchState *env);
long do_rt_sigreturn(CPUArchState *env);
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx,
abi_ulong unew_ctx, abi_long ctx_size);
+#ifdef TRACK_TARGET_SIGMASK
+int do_target_sigprocmask(int how, const target_sigset_t *target_set,
+ target_sigset_t *target_oldset,
+ const sigset_t *set, sigset_t *oldset);
+#endif
/**
* block_signals: block all signals while handling this guest syscall
*
@@ -37,7 +37,12 @@ void target_to_host_sigset_internal(sigset_t *d,
const target_sigset_t *s);
void tswap_siginfo(target_siginfo_t *tinfo,
const target_siginfo_t *info);
+#ifndef TRACK_TARGET_SIGMASK
void set_sigmask(const sigset_t *set);
+#else
+void target_set_sigmask(const sigset_t *set,
+ const target_sigset_t *target_set);
+#endif
void force_sig(int sig);
void force_sigsegv(int oldsig);
#if defined(TARGET_ARCH_HAS_SETUP_FRAME)
@@ -103,6 +103,12 @@ static inline void target_sigaddset(target_sigset_t *set, int signum)
set->sig[signum / TARGET_NSIG_BPW] |= mask;
}
+static inline void target_sigdelset(target_sigset_t *set, int signum)
+{
+ abi_ulong mask = (abi_ulong)1 << (--signum % TARGET_NSIG_BPW);
+ set->sig[signum / TARGET_NSIG_BPW] &= ~mask;
+}
+
static inline int target_sigismember(const target_sigset_t *set, int signum)
{
signum--;
@@ -110,6 +116,16 @@ static inline int target_sigismember(const target_sigset_t *set, int signum)
return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
}
+static inline void target_sigorset(target_sigset_t *set,
+ const target_sigset_t *left,
+ const target_sigset_t *right)
+{
+ int i;
+ for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+ set->sig[i] = left->sig[i] | right->sig[i];
+ }
+}
+
void host_to_target_sigset_internal(target_sigset_t *d,
const sigset_t *s)
{
@@ -174,6 +190,33 @@ void target_to_host_old_sigset(sigset_t *sigset,
target_to_host_sigset(sigset, &d);
}
+void target_to_abi_ulong_old_sigset(abi_ulong *old_sigset,
+ const target_sigset_t *target_sigset)
+{
+ target_sigset_t d;
+ tswapal_target_sigset(&d, target_sigset);
+
+ memcpy(old_sigset, &d.sig, sizeof(target_sigset_t));
+}
+
+void abi_ulong_to_target_old_sigset(target_sigset_t *target_sigset,
+ const abi_ulong *old_sigset)
+{
+ target_sigset_t d;
+
+ memcpy(&d.sig, old_sigset, sizeof(target_sigset_t));
+ tswapal_target_sigset(target_sigset, &d);
+}
+
+void tswapal_target_sigset(target_sigset_t *d, const target_sigset_t *s)
+{
+ int i;
+
+ for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+ d->sig[i] = tswapal(s->sig[i]);
+ }
+}
+
int block_signals(void)
{
TaskState *ts = (TaskState *)thread_cpu->opaque;
@@ -236,16 +279,84 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
return 0;
}
+#ifdef TRACK_TARGET_SIGMASK
+int do_target_sigprocmask(int how, const target_sigset_t *target_set,
+ target_sigset_t *target_oldset,
+ const sigset_t *set, sigset_t *oldset)
+{
+ TaskState *ts = (TaskState *)thread_cpu->opaque;
+
+ if (target_oldset) {
+ *target_oldset = ts->target_signal_mask;
+ }
+ if (oldset) {
+ *oldset = ts->signal_mask;
+ }
+
+ if (target_set && set) {
+ int i;
+
+ if (block_signals()) {
+ return -TARGET_ERESTARTSYS;
+ }
+
+ switch (how) {
+ case SIG_BLOCK:
+ target_sigorset(&ts->target_signal_mask, &ts->target_signal_mask,
+ target_set);
+ sigorset(&ts->signal_mask, &ts->signal_mask, set);
+ break;
+ case SIG_UNBLOCK:
+ for (i = 1; i <= TARGET_NSIG; ++i) {
+ if (target_sigismember(target_set, i) == 1) {
+ target_sigdelset(&ts->target_signal_mask, i);
+ }
+ }
+ for (i = 1; i <= NSIG; ++i) {
+ if (sigismember(set, i) == 1) {
+ sigdelset(&ts->signal_mask, i);
+ }
+ }
+ break;
+ case SIG_SETMASK:
+ ts->target_signal_mask = *target_set;
+ ts->signal_mask = *set;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ /* Silently ignore attempts to change blocking status of KILL or STOP */
+ target_sigdelset(&ts->target_signal_mask, SIGKILL);
+ target_sigdelset(&ts->target_signal_mask, SIGSTOP);
+ sigdelset(&ts->signal_mask, SIGKILL);
+ sigdelset(&ts->signal_mask, SIGSTOP);
+ }
+ return 0;
+}
+#endif
+
#if !defined(TARGET_NIOS2)
/* Just set the guest's signal mask to the specified value; the
* caller is assumed to have called block_signals() already.
*/
+#ifndef TRACK_TARGET_SIGMASK
void set_sigmask(const sigset_t *set)
{
TaskState *ts = (TaskState *)thread_cpu->opaque;
ts->signal_mask = *set;
}
+#else
+void target_set_sigmask(const sigset_t *set,
+ const target_sigset_t *target_set)
+{
+ TaskState *ts = (TaskState *)thread_cpu->opaque;
+
+ ts->signal_mask = *set;
+ ts->target_signal_mask = *target_set;
+}
+#endif
#endif
/* sigaltstack management */
@@ -849,6 +960,9 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
abi_ulong handler;
sigset_t set;
target_sigset_t target_old_set;
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigset_t target_set;
+#endif
struct target_sigaction *sa;
TaskState *ts = cpu->opaque;
@@ -886,21 +1000,39 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
} else {
/* compute the blocked signals during the handler execution */
sigset_t *blocked_set;
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigset_t *target_blocked_set;
+ tswapal_target_sigset(&target_set, &sa->sa_mask);
+#endif
target_to_host_sigset(&set, &sa->sa_mask);
/* SA_NODEFER indicates that the current signal should not be
blocked during the handler */
- if (!(sa->sa_flags & TARGET_SA_NODEFER))
+ if (!(sa->sa_flags & TARGET_SA_NODEFER)) {
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigaddset(&target_set, sig);
+#endif
sigaddset(&set, target_to_host_signal(sig));
+ }
/* save the previous blocked signal state to restore it at the
end of the signal execution (see do_sigreturn) */
+#ifdef TRACK_TARGET_SIGMASK
+ target_old_set = ts->target_signal_mask;
+#else
host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
+#endif
/* block signals in the handler */
blocked_set = ts->in_sigsuspend ?
&ts->sigsuspend_mask : &ts->signal_mask;
sigorset(&ts->signal_mask, blocked_set, &set);
+#ifdef TRACK_TARGET_SIGMASK
+ target_blocked_set = ts->in_sigsuspend ?
+ &ts->target_sigsuspend_mask : &ts->target_signal_mask;
+ target_sigorset(&ts->target_signal_mask, target_blocked_set,
+ &target_set);
+#endif
ts->in_sigsuspend = 0;
/* if the CPU is in VM86 mode, we restore the 32 bit values */
@@ -934,7 +1066,11 @@ void process_pending_signals(CPUArchState *cpu_env)
int sig;
TaskState *ts = cpu->opaque;
sigset_t set;
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigset_t *target_blocked_set;
+#else
sigset_t *blocked_set;
+#endif
while (atomic_read(&ts->signal_pending)) {
/* FIXME: This is not threadsafe. */
@@ -952,22 +1088,42 @@ void process_pending_signals(CPUArchState *cpu_env)
* to block a synchronous signal since it could then just end up
* looping round and round indefinitely.
*/
+#ifdef TRACK_TARGET_SIGMASK
+ if (sigismember(&ts->signal_mask, target_to_host_signal(sig)) == 1
+ || target_sigismember(&ts->target_signal_mask, sig) == 1
+ || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
+ sigdelset(&ts->signal_mask, target_to_host_signal(sig));
+ target_sigdelset(&ts->target_signal_mask, sig);
+ sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
+ }
+#else
if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
|| sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
}
+#endif
handle_pending_signal(cpu_env, sig, &ts->sync_signal);
}
for (sig = 1; sig <= TARGET_NSIG; sig++) {
+#ifdef TRACK_TARGET_SIGMASK
+ target_blocked_set = ts->in_sigsuspend ?
+ &ts->target_sigsuspend_mask : &ts->target_signal_mask;
+#else
blocked_set = ts->in_sigsuspend ?
&ts->sigsuspend_mask : &ts->signal_mask;
+#endif
+#ifdef TRACK_TARGET_SIGMASK
+ if (ts->sigtab[sig - 1].pending &&
+ (!target_sigismember(target_blocked_set, sig))) {
+#else
if (ts->sigtab[sig - 1].pending &&
(!sigismember(blocked_set,
target_to_host_signal_table[sig]))) {
+#endif
handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
/* Restart scan from the beginning, as handle_pending_signal
* might have resulted in a new synchronous signal (eg SIGSEGV).
@@ -7871,6 +7871,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR_sgetmask /* not on alpha */
case TARGET_NR_sgetmask:
{
+#ifdef TRACK_TARGET_SIGMASK
+ sigset_t cur_set;
+ target_sigset_t target_set_mask;
+ abi_ulong target_set;
+ ret = do_target_sigprocmask(0, NULL, &target_set_mask,
+ NULL, &cur_set);
+ if (!ret) {
+ target_to_abi_ulong_old_sigset(&target_set, &target_set_mask);
+ ret = target_set;
+ }
+#else
sigset_t cur_set;
abi_ulong target_set;
ret = do_sigprocmask(0, NULL, &cur_set);
@@ -7878,12 +7889,26 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
host_to_target_old_sigset(&target_set, &cur_set);
ret = target_set;
}
+#endif
}
return ret;
#endif
#ifdef TARGET_NR_ssetmask /* not on alpha */
case TARGET_NR_ssetmask:
{
+#ifdef TRACK_TARGET_SIGMASK
+ sigset_t set, oset;
+ target_sigset_t target_set_mask, target_oset;
+ abi_ulong target_set = arg1;
+ target_to_host_old_sigset(&set, &target_set);
+ abi_ulong_to_target_old_sigset(&target_set_mask, &target_set);
+ ret = do_target_sigprocmask(SIG_SETMASK, &target_set_mask,
+ &target_oset, &set, &oset);
+ if (!ret) {
+ target_to_abi_ulong_old_sigset(&target_set, &target_oset);
+ ret = target_set;
+ }
+#else
sigset_t set, oset;
abi_ulong target_set = arg1;
target_to_host_old_sigset(&set, &target_set);
@@ -7892,6 +7917,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
host_to_target_old_sigset(&target_set, &oset);
ret = target_set;
}
+#endif
}
return ret;
#endif
@@ -7900,6 +7926,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
{
#if defined(TARGET_ALPHA)
sigset_t set, oldset;
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigset_t target_set, target_oldset;
+#endif
abi_ulong mask;
int how;
@@ -7919,14 +7948,26 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
mask = arg2;
target_to_host_old_sigset(&set, &mask);
+#ifdef TRACK_TARGET_SIGMASK
+ abi_ulong_to_target_old_sigset(&target_set, &mask);
+
+ ret = do_target_sigprocmask(how, &target_set, &target_oldset,
+ &set, &oldset);
+ if (!is_error(ret)) {
+ target_to_abi_ulong_old_sigset(&mask, &target_oldset);
+#else
ret = do_sigprocmask(how, &set, &oldset);
if (!is_error(ret)) {
host_to_target_old_sigset(&mask, &oldset);
+#endif
ret = mask;
((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
}
#else
sigset_t set, oldset, *set_ptr;
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigset_t target_set, target_oldset, *target_set_ptr;
+#endif
int how;
if (arg2) {
@@ -7946,17 +7987,32 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
return -TARGET_EFAULT;
target_to_host_old_sigset(&set, p);
+#ifdef TRACK_TARGET_SIGMASK
+ abi_ulong_to_target_old_sigset(&target_set, p);
+ target_set_ptr = &target_set;
+#endif
unlock_user(p, arg2, 0);
set_ptr = &set;
} else {
how = 0;
set_ptr = NULL;
+#ifdef TRACK_TARGET_SIGMASK
+ target_set_ptr = NULL;
+ }
+ ret = do_target_sigprocmask(how, target_set_ptr, &target_oldset,
+ set_ptr, &oldset);
+#else
}
ret = do_sigprocmask(how, set_ptr, &oldset);
+#endif
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
return -TARGET_EFAULT;
+#ifdef TRACK_TARGET_SIGMASK
+ target_to_abi_ulong_old_sigset(p, &target_oldset);
+#else
host_to_target_old_sigset(p, &oldset);
+#endif
unlock_user(p, arg3, sizeof(target_sigset_t));
}
#endif
@@ -7967,6 +8023,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
{
int how = arg1;
sigset_t set, oldset, *set_ptr;
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigset_t target_set, target_oldset, *target_set_ptr;
+#endif
if (arg4 != sizeof(target_sigset_t)) {
return -TARGET_EINVAL;
@@ -7989,17 +8048,32 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
return -TARGET_EFAULT;
target_to_host_sigset(&set, p);
+#ifdef TRACK_TARGET_SIGMASK
+ tswapal_target_sigset(&target_set, p);
+ target_set_ptr = &target_set;
+#endif
unlock_user(p, arg2, 0);
set_ptr = &set;
} else {
how = 0;
set_ptr = NULL;
+#ifdef TRACK_TARGET_SIGMASK
+ target_set_ptr = NULL;
+ }
+ ret = do_target_sigprocmask(how, target_set_ptr, &target_oldset,
+ set_ptr, &oldset);
+#else
}
ret = do_sigprocmask(how, set_ptr, &oldset);
+#endif
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
return -TARGET_EFAULT;
+#ifdef TRACK_TARGET_SIGMASK
+ tswapal_target_sigset(p, &target_oldset);
+#else
host_to_target_sigset(p, &oldset);
+#endif
unlock_user(p, arg3, sizeof(target_sigset_t));
}
}
@@ -8047,10 +8121,16 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_ALPHA)
abi_ulong mask = arg1;
target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
+#ifdef TRACK_TARGET_SIGMASK
+ abi_ulong_to_target_old_sigset(&ts->target_sigsuspend_mask, &mask);
+#endif
#else
if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
return -TARGET_EFAULT;
target_to_host_old_sigset(&ts->sigsuspend_mask, p);
+#ifdef TRACK_TARGET_SIGMASK
+ abi_ulong_to_target_old_sigset(&ts->target_sigsuspend_mask, p);
+#endif
unlock_user(p, arg1, 0);
#endif
ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
@@ -8071,6 +8151,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
return -TARGET_EFAULT;
target_to_host_sigset(&ts->sigsuspend_mask, p);
+#ifdef TRACK_TARGET_SIGMASK
+ tswapal_target_sigset(&ts->target_sigsuspend_mask, p);
+#endif
unlock_user(p, arg1, 0);
ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
SIGSET_T_SIZE));
@@ -10351,6 +10434,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
abi_ulong mask;
int how;
sigset_t set, oldset;
+#ifdef TRACK_TARGET_SIGMASK
+ target_sigset_t target_set, target_oldset;
+#endif
switch(arg1) {
case TARGET_SIG_BLOCK:
@@ -10367,9 +10453,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
}
mask = arg2;
target_to_host_old_sigset(&set, &mask);
+#ifdef TRACK_TARGET_SIGMASK
+ abi_ulong_to_target_old_sigset(&target_set, &mask);
+ ret = do_target_sigprocmask(how, &target_set, &target_oldset,
+ &set, &oldset);
+ if (!ret) {
+ target_to_abi_ulong_old_sigset(&mask, &target_oldset);
+#else
ret = do_sigprocmask(how, &set, &oldset);
if (!ret) {
host_to_target_old_sigset(&mask, &oldset);
+#endif
ret = mask;
}
}
@@ -419,6 +419,10 @@ void host_to_target_old_sigset(abi_ulong *old_sigset,
const sigset_t *sigset);
void target_to_host_old_sigset(sigset_t *sigset,
const abi_ulong *old_sigset);
+void target_to_abi_ulong_old_sigset(abi_ulong *old_sigset,
+ const target_sigset_t *target_sigset);
+void abi_ulong_to_target_old_sigset(target_sigset_t *target_sigset,
+ const abi_ulong *old_sigset);
struct target_sigaction;
int do_sigaction(int sig, const struct target_sigaction *act,
struct target_sigaction *oact);