From: Miloš Stojanović <milos.stojano...@rt-rk.com> Add MUX_SIG as a multiplex signal number for all target signals which are out of the host range. Add support for multiplexing in do_sigaction(), process_pending_signals(), target_set_sigmask() and do_target_sigprocmask().
This patch solves the problem of unusable target signals which are out of the host range. This is done by enabling the usage of one of the host signals (MUX_SIG) as a multiplex for all the target signals that are out of range. In order to have the target signal masks available TRACK_TARGET_MASK is defined which enables the tracking of the target signals masks. The table of signal handlers already supports the whole range of target signals. In the do_sigaction() function the signal number of signals which are out of range are replaced by MUX_SIG which bypasses the error from the host system and doesn't interfere with signal handling on the target. Since the MUX_SIG is used as a multiplex, it must never be blocked on host, so support for emulating the blocking of this signal is added. This is done by only blocking MUX_SIG in the target mask and retrieving its status from there when it's needed. Signed-off-by: Miloš Stojanović <milos.stojano...@rt-rk.com> Signed-off-by: Aleksandar Markovic <amarko...@wavecomp.com> --- linux-user/signal.c | 32 ++++++++++++++++++++++++++++++++ linux-user/syscall_defs.h | 20 ++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/linux-user/signal.c b/linux-user/signal.c index 9a73bfa..601de3e 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -291,6 +291,15 @@ int do_target_sigprocmask(int how, const target_sigset_t *target_set, } if (oldset) { *oldset = ts->signal_mask; +#ifdef MUX_SIG + /* + * The emulation of MUX_SIG being blocked is done using the + * target_signal_mask, so the status of MUX_SIG is taken from there. + */ + if (target_sigismember(&ts->target_signal_mask, MUX_SIG) == 1) { + sigaddset(oldset, MUX_SIG); + } +#endif } if (target_set && set) { @@ -331,6 +340,15 @@ int do_target_sigprocmask(int how, const target_sigset_t *target_set, target_sigdelset(&ts->target_signal_mask, SIGSTOP); sigdelset(&ts->signal_mask, SIGKILL); sigdelset(&ts->signal_mask, SIGSTOP); +#ifdef MUX_SIG + /* + * Since MUX_SIG is used for all the target signals out of the host + * range it must never be blocked on host. The emulation of MUX_SIG + * being blocked is done using the target_signal_mask. The status + * of MUX_SIG is taken form the target_signal_mask. + */ + sigdelset(&ts->signal_mask, MUX_SIG); +#endif } return 0; } @@ -355,6 +373,10 @@ void target_set_sigmask(const sigset_t *set, ts->signal_mask = *set; ts->target_signal_mask = *target_set; +#ifdef MUX_SIG + /* MUX_SIG can't be blocked on host */ + sigdelset(&ts->signal_mask, MUX_SIG); +#endif } #endif #endif @@ -929,6 +951,12 @@ int do_sigaction(int sig, const struct target_sigaction *act, /* we update the host linux signal state */ host_sig = target_to_host_signal(sig); +#ifdef MUX_SIG + /* put the out of host range signal into the multiplex */ + if (sig >= _NSIG && sig < TARGET_NSIG) { + host_sig = MUX_SIG; + } +#endif if (host_sig != SIGSEGV && host_sig != SIGBUS) { sigfillset(&act1.sa_mask); act1.sa_flags = SA_SIGINFO; @@ -1141,6 +1169,10 @@ void process_pending_signals(CPUArchState *cpu_env) set = ts->signal_mask; sigdelset(&set, SIGSEGV); sigdelset(&set, SIGBUS); +#ifdef MUX_SIG + /* MUX_SIG can't be blocked on host */ + sigdelset(&ts->signal_mask, MUX_SIG); +#endif sigprocmask(SIG_SETMASK, &set, 0); } ts->in_sigsuspend = 0; diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 64edec2..0c72509 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -387,6 +387,26 @@ struct target_dirent64 { #define TARGET_NSIG_BPW TARGET_ABI_BITS #define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW) +#if _NSIG <= TARGET_NSIG +/* + * MUX_SIG is used as a multiplex signal number - signals that are + * out of the host range and in the target range are sent through it. + * It is defined as the maximal available real-time signal in order to + * comply with the rule that low-numbered signals have highest priority. + * (signals using it will have the same priority but it will be smaller + * than all the other real-time signals) + * SIGRMTAX is avoided so it doesn't interfere with the hack of reversing + * __SIGRTMIN and __SIGRTMAX in the host_to_target_signal_table. + */ +#define MUX_SIG (SIGRTMAX - 1) + +/* + * The target signal masks must be tracked since they are larger than + * the host signal masks. + */ +#define TRACK_TARGET_SIGMASK +#endif + typedef struct { abi_ulong sig[TARGET_NSIG_WORDS]; } target_sigset_t; -- 2.7.4