blob: 2f2aa89feb334f3c86ba82168a92f81b2ab2d911 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
19#include <stdlib.h>
20#include <stdio.h>
bellard66fb9762003-03-23 01:06:05 +000021#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000022#include <stdarg.h>
bellard2677e102003-04-10 00:03:27 +000023#include <unistd.h>
bellard66fb9762003-03-23 01:06:05 +000024#include <errno.h>
aurel32603e4fd2009-04-15 16:18:38 +000025#include <assert.h>
bellard31e31b82003-02-18 22:55:36 +000026#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030027#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000028
bellard3ef693a2003-03-23 20:17:16 +000029#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000030#include "qemu-common.h"
Peter Maydellda30d852011-12-05 19:42:18 +000031#include "signal-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000032#include "target_signal.h"
bellard66fb9762003-03-23 01:06:05 +000033
34//#define DEBUG_SIGNAL
35
Peter Maydellda30d852011-12-05 19:42:18 +000036struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000037 .ss_sp = 0,
38 .ss_size = 0,
39 .ss_flags = TARGET_SS_DISABLE,
40};
41
pbrook624f7972008-05-31 16:11:38 +000042static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000043
ths5fafdf22007-09-16 21:08:06 +000044static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000045 void *puc);
46
Arnaud Patard3ca05582009-03-30 01:18:20 +020047static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000048 [SIGHUP] = TARGET_SIGHUP,
49 [SIGINT] = TARGET_SIGINT,
50 [SIGQUIT] = TARGET_SIGQUIT,
51 [SIGILL] = TARGET_SIGILL,
52 [SIGTRAP] = TARGET_SIGTRAP,
53 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000054/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000055 [SIGBUS] = TARGET_SIGBUS,
56 [SIGFPE] = TARGET_SIGFPE,
57 [SIGKILL] = TARGET_SIGKILL,
58 [SIGUSR1] = TARGET_SIGUSR1,
59 [SIGSEGV] = TARGET_SIGSEGV,
60 [SIGUSR2] = TARGET_SIGUSR2,
61 [SIGPIPE] = TARGET_SIGPIPE,
62 [SIGALRM] = TARGET_SIGALRM,
63 [SIGTERM] = TARGET_SIGTERM,
64#ifdef SIGSTKFLT
65 [SIGSTKFLT] = TARGET_SIGSTKFLT,
66#endif
67 [SIGCHLD] = TARGET_SIGCHLD,
68 [SIGCONT] = TARGET_SIGCONT,
69 [SIGSTOP] = TARGET_SIGSTOP,
70 [SIGTSTP] = TARGET_SIGTSTP,
71 [SIGTTIN] = TARGET_SIGTTIN,
72 [SIGTTOU] = TARGET_SIGTTOU,
73 [SIGURG] = TARGET_SIGURG,
74 [SIGXCPU] = TARGET_SIGXCPU,
75 [SIGXFSZ] = TARGET_SIGXFSZ,
76 [SIGVTALRM] = TARGET_SIGVTALRM,
77 [SIGPROF] = TARGET_SIGPROF,
78 [SIGWINCH] = TARGET_SIGWINCH,
79 [SIGIO] = TARGET_SIGIO,
80 [SIGPWR] = TARGET_SIGPWR,
81 [SIGSYS] = TARGET_SIGSYS,
82 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000083 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080084 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000085 To fix this properly we need to do manual signal delivery multiplexed
86 over a single host signal. */
87 [__SIGRTMIN] = __SIGRTMAX,
88 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000089};
Arnaud Patard3ca05582009-03-30 01:18:20 +020090static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000091
pbrook1d9d8b52009-04-16 15:17:02 +000092int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000093{
Arnaud Patard3ca05582009-03-30 01:18:20 +020094 if (sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +000095 return sig;
bellard9e5f5282003-07-13 17:33:54 +000096 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +000097}
98
pbrook4cb05962008-05-30 18:05:19 +000099int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000100{
Arnaud Patard3ca05582009-03-30 01:18:20 +0200101 if (sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000102 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000103 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000104}
105
Anthony Liguoric227f092009-10-01 16:12:16 -0500106static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000107{
108 signum--;
109 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
110 set->sig[signum / TARGET_NSIG_BPW] |= mask;
111}
112
Anthony Liguoric227f092009-10-01 16:12:16 -0500113static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000114{
115 signum--;
116 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
117 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
118}
119
Anthony Liguoric227f092009-10-01 16:12:16 -0500120static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000121 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000122{
123 int i;
pbrookf5545b52008-05-30 22:37:07 +0000124 target_sigemptyset(d);
125 for (i = 1; i <= TARGET_NSIG; i++) {
126 if (sigismember(s, i)) {
127 target_sigaddset(d, host_to_target_signal(i));
128 }
bellard9e5f5282003-07-13 17:33:54 +0000129 }
bellard66fb9762003-03-23 01:06:05 +0000130}
131
Anthony Liguoric227f092009-10-01 16:12:16 -0500132void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000133{
Anthony Liguoric227f092009-10-01 16:12:16 -0500134 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000135 int i;
136
137 host_to_target_sigset_internal(&d1, s);
138 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200139 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000140}
141
Peter Maydellda30d852011-12-05 19:42:18 +0000142void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000143{
144 int i;
pbrookf5545b52008-05-30 22:37:07 +0000145 sigemptyset(d);
146 for (i = 1; i <= TARGET_NSIG; i++) {
147 if (target_sigismember(s, i)) {
148 sigaddset(d, target_to_host_signal(i));
149 }
150 }
bellard66fb9762003-03-23 01:06:05 +0000151}
152
Anthony Liguoric227f092009-10-01 16:12:16 -0500153void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000154{
Anthony Liguoric227f092009-10-01 16:12:16 -0500155 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000156 int i;
157
158 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200159 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000160 target_to_host_sigset_internal(d, &s1);
161}
ths3b46e622007-09-17 08:09:54 +0000162
blueswir1992f48a2007-10-14 16:27:31 +0000163void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000164 const sigset_t *sigset)
165{
Anthony Liguoric227f092009-10-01 16:12:16 -0500166 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000167 host_to_target_sigset(&d, sigset);
168 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000169}
170
ths5fafdf22007-09-16 21:08:06 +0000171void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000172 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000173{
Anthony Liguoric227f092009-10-01 16:12:16 -0500174 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000175 int i;
176
177 d.sig[0] = *old_sigset;
178 for(i = 1;i < TARGET_NSIG_WORDS; i++)
179 d.sig[i] = 0;
180 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000181}
182
bellard9de5e442003-03-23 16:49:39 +0000183/* siginfo conversion */
184
Anthony Liguoric227f092009-10-01 16:12:16 -0500185static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000186 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000187{
bellard9de5e442003-03-23 16:49:39 +0000188 int sig;
189 sig = host_to_target_signal(info->si_signo);
190 tinfo->si_signo = sig;
191 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000192 tinfo->si_code = info->si_code;
ths5fafdf22007-09-16 21:08:06 +0000193 if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
bellard447db212003-05-10 15:10:36 +0000194 sig == SIGBUS || sig == SIGTRAP) {
bellard9de5e442003-03-23 16:49:39 +0000195 /* should never come here, but who knows. The information for
196 the target is irrelevant */
197 tinfo->_sifields._sigfault._addr = 0;
ths7f7f7c82007-07-12 11:02:46 +0000198 } else if (sig == SIGIO) {
199 tinfo->_sifields._sigpoll._fd = info->si_fd;
bellard9de5e442003-03-23 16:49:39 +0000200 } else if (sig >= TARGET_SIGRTMIN) {
201 tinfo->_sifields._rt._pid = info->si_pid;
202 tinfo->_sifields._rt._uid = info->si_uid;
203 /* XXX: potential problem if 64 bit */
ths5fafdf22007-09-16 21:08:06 +0000204 tinfo->_sifields._rt._sigval.sival_ptr =
bellard459a4012007-11-11 19:45:10 +0000205 (abi_ulong)(unsigned long)info->si_value.sival_ptr;
bellard9de5e442003-03-23 16:49:39 +0000206 }
bellard66fb9762003-03-23 01:06:05 +0000207}
208
Peter Maydellda30d852011-12-05 19:42:18 +0000209void tswap_siginfo(target_siginfo_t *tinfo,
210 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000211{
212 int sig;
213 sig = info->si_signo;
214 tinfo->si_signo = tswap32(sig);
215 tinfo->si_errno = tswap32(info->si_errno);
216 tinfo->si_code = tswap32(info->si_code);
ths5fafdf22007-09-16 21:08:06 +0000217 if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
bellard447db212003-05-10 15:10:36 +0000218 sig == SIGBUS || sig == SIGTRAP) {
ths5fafdf22007-09-16 21:08:06 +0000219 tinfo->_sifields._sigfault._addr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200220 tswapal(info->_sifields._sigfault._addr);
ths7f7f7c82007-07-12 11:02:46 +0000221 } else if (sig == SIGIO) {
222 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
bellard9de5e442003-03-23 16:49:39 +0000223 } else if (sig >= TARGET_SIGRTMIN) {
224 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
225 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
ths5fafdf22007-09-16 21:08:06 +0000226 tinfo->_sifields._rt._sigval.sival_ptr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200227 tswapal(info->_sifields._rt._sigval.sival_ptr);
bellard9de5e442003-03-23 16:49:39 +0000228 }
229}
230
231
Anthony Liguoric227f092009-10-01 16:12:16 -0500232void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000233{
234 host_to_target_siginfo_noswap(tinfo, info);
235 tswap_siginfo(tinfo, tinfo);
236}
237
238/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000239/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500240void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000241{
242 info->si_signo = tswap32(tinfo->si_signo);
243 info->si_errno = tswap32(tinfo->si_errno);
244 info->si_code = tswap32(tinfo->si_code);
bellard9de5e442003-03-23 16:49:39 +0000245 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
246 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
ths5fafdf22007-09-16 21:08:06 +0000247 info->si_value.sival_ptr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200248 (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr);
bellard66fb9762003-03-23 01:06:05 +0000249}
250
aurel32ca587a82008-12-18 22:44:13 +0000251static int fatal_signal (int sig)
252{
253 switch (sig) {
254 case TARGET_SIGCHLD:
255 case TARGET_SIGURG:
256 case TARGET_SIGWINCH:
257 /* Ignored by default. */
258 return 0;
259 case TARGET_SIGCONT:
260 case TARGET_SIGSTOP:
261 case TARGET_SIGTSTP:
262 case TARGET_SIGTTIN:
263 case TARGET_SIGTTOU:
264 /* Job control signals. */
265 return 0;
266 default:
267 return 1;
268 }
269}
270
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300271/* returns 1 if given signal should dump core if not handled */
272static int core_dump_signal(int sig)
273{
274 switch (sig) {
275 case TARGET_SIGABRT:
276 case TARGET_SIGFPE:
277 case TARGET_SIGILL:
278 case TARGET_SIGQUIT:
279 case TARGET_SIGSEGV:
280 case TARGET_SIGTRAP:
281 case TARGET_SIGBUS:
282 return (1);
283 default:
284 return (0);
285 }
286}
287
bellard31e31b82003-02-18 22:55:36 +0000288void signal_init(void)
289{
290 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000291 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000292 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000293 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000294
bellard9e5f5282003-07-13 17:33:54 +0000295 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200296 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000297 if (host_to_target_signal_table[i] == 0)
298 host_to_target_signal_table[i] = i;
299 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200300 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000301 j = host_to_target_signal_table[i];
302 target_to_host_signal_table[j] = i;
303 }
ths3b46e622007-09-17 08:09:54 +0000304
bellard9de5e442003-03-23 16:49:39 +0000305 /* set all host signal handlers. ALL signals are blocked during
306 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000307 memset(sigact_table, 0, sizeof(sigact_table));
308
bellard9de5e442003-03-23 16:49:39 +0000309 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000310 act.sa_flags = SA_SIGINFO;
311 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000312 for(i = 1; i <= TARGET_NSIG; i++) {
313 host_sig = target_to_host_signal(i);
314 sigaction(host_sig, NULL, &oact);
315 if (oact.sa_sigaction == (void *)SIG_IGN) {
316 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
317 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
318 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
319 }
320 /* If there's already a handler installed then something has
321 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000322 /* Install some handlers for our own use. We need at least
323 SIGSEGV and SIGBUS, to detect exceptions. We can not just
324 trap all signals because it affects syscall interrupt
325 behavior. But do trap all default-fatal signals. */
326 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000327 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000328 }
bellard31e31b82003-02-18 22:55:36 +0000329}
330
bellard66fb9762003-03-23 01:06:05 +0000331/* signal queue handling */
332
pbrook624f7972008-05-31 16:11:38 +0000333static inline struct sigqueue *alloc_sigqueue(CPUState *env)
bellard66fb9762003-03-23 01:06:05 +0000334{
pbrook624f7972008-05-31 16:11:38 +0000335 TaskState *ts = env->opaque;
336 struct sigqueue *q = ts->first_free;
bellard66fb9762003-03-23 01:06:05 +0000337 if (!q)
338 return NULL;
pbrook624f7972008-05-31 16:11:38 +0000339 ts->first_free = q->next;
bellard66fb9762003-03-23 01:06:05 +0000340 return q;
341}
342
pbrook624f7972008-05-31 16:11:38 +0000343static inline void free_sigqueue(CPUState *env, struct sigqueue *q)
bellard66fb9762003-03-23 01:06:05 +0000344{
pbrook624f7972008-05-31 16:11:38 +0000345 TaskState *ts = env->opaque;
346 q->next = ts->first_free;
347 ts->first_free = q;
bellard66fb9762003-03-23 01:06:05 +0000348}
349
bellard9de5e442003-03-23 16:49:39 +0000350/* abort execution with signal */
Peter Maydellda30d852011-12-05 19:42:18 +0000351void QEMU_NORETURN force_sig(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000352{
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300353 TaskState *ts = (TaskState *)thread_env->opaque;
354 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000355 struct sigaction act;
Riku Voipio66393fb2009-12-04 15:16:32 +0200356 host_sig = target_to_host_signal(target_sig);
357 gdb_signalled(thread_env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000358
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300359 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200360 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300361 stop_all_tasks();
362 core_dumped =
Riku Voipio66393fb2009-12-04 15:16:32 +0200363 ((*ts->bprm->core_dump)(target_sig, thread_env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300364 }
365 if (core_dumped) {
366 /* we already dumped the core of target process, we don't want
367 * a coredump of qemu itself */
368 struct rlimit nodump;
369 getrlimit(RLIMIT_CORE, &nodump);
370 nodump.rlim_cur=0;
371 setrlimit(RLIMIT_CORE, &nodump);
372 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200373 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300374 }
375
Stefan Weil0c587512011-04-28 17:20:32 +0200376 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000377 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
378 * a negative value. To get the proper exit code we need to
379 * actually die from an uncaught signal. Here the default signal
380 * handler is installed, we send ourself a signal and we wait for
381 * it to arrive. */
382 sigfillset(&act.sa_mask);
383 act.sa_handler = SIG_DFL;
384 sigaction(host_sig, &act, NULL);
385
386 /* For some reason raise(host_sig) doesn't send the signal when
387 * statically linked on x86-64. */
388 kill(getpid(), host_sig);
389
390 /* Make sure the signal isn't masked (just reuse the mask inside
391 of act) */
392 sigdelset(&act.sa_mask, host_sig);
393 sigsuspend(&act.sa_mask);
394
395 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000396 abort();
bellard66fb9762003-03-23 01:06:05 +0000397}
398
bellard9de5e442003-03-23 16:49:39 +0000399/* queue a signal so that it will be send to the virtual CPU as soon
400 as possible */
Anthony Liguoric227f092009-10-01 16:12:16 -0500401int queue_signal(CPUState *env, int sig, target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000402{
pbrook624f7972008-05-31 16:11:38 +0000403 TaskState *ts = env->opaque;
404 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000405 struct sigqueue *q, **pq;
blueswir1992f48a2007-10-14 16:27:31 +0000406 abi_ulong handler;
aurel32ca587a82008-12-18 22:44:13 +0000407 int queue;
bellard66fb9762003-03-23 01:06:05 +0000408
bellard9de5e442003-03-23 16:49:39 +0000409#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000410 fprintf(stderr, "queue_signal: sig=%d\n",
bellard9de5e442003-03-23 16:49:39 +0000411 sig);
bellard66fb9762003-03-23 01:06:05 +0000412#endif
pbrook624f7972008-05-31 16:11:38 +0000413 k = &ts->sigtab[sig - 1];
aurel32ca587a82008-12-18 22:44:13 +0000414 queue = gdb_queuesig ();
pbrook624f7972008-05-31 16:11:38 +0000415 handler = sigact_table[sig - 1]._sa_handler;
aurel32ca587a82008-12-18 22:44:13 +0000416 if (!queue && handler == TARGET_SIG_DFL) {
ths60b19692008-11-27 15:47:15 +0000417 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
418 kill(getpid(),SIGSTOP);
419 return 0;
420 } else
bellard66fb9762003-03-23 01:06:05 +0000421 /* default handler : ignore some signal. The other are fatal */
ths5fafdf22007-09-16 21:08:06 +0000422 if (sig != TARGET_SIGCHLD &&
423 sig != TARGET_SIGURG &&
ths60b19692008-11-27 15:47:15 +0000424 sig != TARGET_SIGWINCH &&
425 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +0000426 force_sig(sig);
bellard9de5e442003-03-23 16:49:39 +0000427 } else {
428 return 0; /* indicate ignored */
bellard66fb9762003-03-23 01:06:05 +0000429 }
aurel32ca587a82008-12-18 22:44:13 +0000430 } else if (!queue && handler == TARGET_SIG_IGN) {
bellard66fb9762003-03-23 01:06:05 +0000431 /* ignore signal */
bellard9de5e442003-03-23 16:49:39 +0000432 return 0;
aurel32ca587a82008-12-18 22:44:13 +0000433 } else if (!queue && handler == TARGET_SIG_ERR) {
bellard66fb9762003-03-23 01:06:05 +0000434 force_sig(sig);
435 } else {
bellard9de5e442003-03-23 16:49:39 +0000436 pq = &k->first;
437 if (sig < TARGET_SIGRTMIN) {
438 /* if non real time signal, we queue exactly one signal */
439 if (!k->pending)
440 q = &k->info;
441 else
442 return 0;
443 } else {
444 if (!k->pending) {
445 /* first signal */
446 q = &k->info;
447 } else {
pbrook624f7972008-05-31 16:11:38 +0000448 q = alloc_sigqueue(env);
bellard9de5e442003-03-23 16:49:39 +0000449 if (!q)
450 return -EAGAIN;
451 while (*pq != NULL)
452 pq = &(*pq)->next;
453 }
454 }
455 *pq = q;
456 q->info = *info;
457 q->next = NULL;
458 k->pending = 1;
459 /* signal that a new signal is pending */
pbrook624f7972008-05-31 16:11:38 +0000460 ts->signal_pending = 1;
bellard9de5e442003-03-23 16:49:39 +0000461 return 1; /* indicates that the signal was queued */
462 }
463}
464
ths5fafdf22007-09-16 21:08:06 +0000465static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000466 void *puc)
467{
468 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500469 target_siginfo_t tinfo;
bellard9de5e442003-03-23 16:49:39 +0000470
471 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000472 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000473 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000474 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000475 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000476 return;
477 }
478
479 /* get target signal number */
480 sig = host_to_target_signal(host_signum);
481 if (sig < 1 || sig > TARGET_NSIG)
482 return;
483#if defined(DEBUG_SIGNAL)
bellardbc8a22c2003-03-30 21:02:40 +0000484 fprintf(stderr, "qemu: got signal %d\n", sig);
bellard9de5e442003-03-23 16:49:39 +0000485#endif
486 host_to_target_siginfo_noswap(&tinfo, info);
pbrookd5975362008-06-07 20:50:51 +0000487 if (queue_signal(thread_env, sig, &tinfo) == 1) {
bellard9de5e442003-03-23 16:49:39 +0000488 /* interrupt the virtual CPU as soon as possible */
aurel323098dba2009-03-07 21:28:24 +0000489 cpu_exit(thread_env);
bellard66fb9762003-03-23 01:06:05 +0000490 }
bellard31e31b82003-02-18 22:55:36 +0000491}
492
ths0da46a62007-10-20 20:23:07 +0000493/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000494/* compare linux/kernel/signal.c:do_sigaltstack() */
495abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000496{
497 int ret;
498 struct target_sigaltstack oss;
499
500 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000501 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000502 {
503 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
504 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
505 __put_user(sas_ss_flags(sp), &oss.ss_flags);
506 }
507
bellard579a97f2007-11-11 14:26:47 +0000508 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000509 {
bellard579a97f2007-11-11 14:26:47 +0000510 struct target_sigaltstack *uss;
511 struct target_sigaltstack ss;
thsa04e1342007-09-27 13:57:58 +0000512
ths0da46a62007-10-20 20:23:07 +0000513 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000514 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)
thsa04e1342007-09-27 13:57:58 +0000515 || __get_user(ss.ss_sp, &uss->ss_sp)
516 || __get_user(ss.ss_size, &uss->ss_size)
517 || __get_user(ss.ss_flags, &uss->ss_flags))
518 goto out;
bellard579a97f2007-11-11 14:26:47 +0000519 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000520
ths0da46a62007-10-20 20:23:07 +0000521 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000522 if (on_sig_stack(sp))
523 goto out;
524
ths0da46a62007-10-20 20:23:07 +0000525 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000526 if (ss.ss_flags != TARGET_SS_DISABLE
527 && ss.ss_flags != TARGET_SS_ONSTACK
528 && ss.ss_flags != 0)
529 goto out;
530
531 if (ss.ss_flags == TARGET_SS_DISABLE) {
532 ss.ss_size = 0;
533 ss.ss_sp = 0;
534 } else {
ths0da46a62007-10-20 20:23:07 +0000535 ret = -TARGET_ENOMEM;
thsa04e1342007-09-27 13:57:58 +0000536 if (ss.ss_size < MINSIGSTKSZ)
537 goto out;
538 }
539
540 target_sigaltstack_used.ss_sp = ss.ss_sp;
541 target_sigaltstack_used.ss_size = ss.ss_size;
542 }
543
bellard579a97f2007-11-11 14:26:47 +0000544 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000545 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000546 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000547 goto out;
thsa04e1342007-09-27 13:57:58 +0000548 }
549
550 ret = 0;
551out:
552 return ret;
553}
554
ths0da46a62007-10-20 20:23:07 +0000555/* do_sigaction() return host values and errnos */
bellard66fb9762003-03-23 01:06:05 +0000556int do_sigaction(int sig, const struct target_sigaction *act,
557 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000558{
pbrook624f7972008-05-31 16:11:38 +0000559 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000560 struct sigaction act1;
561 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000562 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000563
ths2a913eb2008-11-27 15:46:25 +0000564 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
bellard66fb9762003-03-23 01:06:05 +0000565 return -EINVAL;
566 k = &sigact_table[sig - 1];
bellard773b93e2004-01-04 17:15:59 +0000567#if defined(DEBUG_SIGNAL)
Blue Swirl0bf9e312009-07-20 17:19:25 +0000568 fprintf(stderr, "sigaction sig=%d act=0x%p, oact=0x%p\n",
569 sig, act, oact);
bellard66fb9762003-03-23 01:06:05 +0000570#endif
571 if (oact) {
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200572 oact->_sa_handler = tswapal(k->_sa_handler);
573 oact->sa_flags = tswapal(k->sa_flags);
ths388bb212007-05-13 13:58:00 +0000574#if !defined(TARGET_MIPS)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200575 oact->sa_restorer = tswapal(k->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000576#endif
pbrook624f7972008-05-31 16:11:38 +0000577 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000578 }
579 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000580 /* FIXME: This is not threadsafe. */
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200581 k->_sa_handler = tswapal(act->_sa_handler);
582 k->sa_flags = tswapal(act->sa_flags);
ths388bb212007-05-13 13:58:00 +0000583#if !defined(TARGET_MIPS)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200584 k->sa_restorer = tswapal(act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000585#endif
pbrook624f7972008-05-31 16:11:38 +0000586 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000587
588 /* we update the host linux signal state */
589 host_sig = target_to_host_signal(sig);
590 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
591 sigfillset(&act1.sa_mask);
592 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000593 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000594 act1.sa_flags |= SA_RESTART;
595 /* NOTE: it is important to update the host kernel signal
596 ignore state to avoid getting unexpected interrupted
597 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000598 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000599 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000600 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000601 if (fatal_signal (sig))
602 act1.sa_sigaction = host_signal_handler;
603 else
604 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000605 } else {
606 act1.sa_sigaction = host_signal_handler;
607 }
ths0da46a62007-10-20 20:23:07 +0000608 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000609 }
bellard66fb9762003-03-23 01:06:05 +0000610 }
ths0da46a62007-10-20 20:23:07 +0000611 return ret;
bellard66fb9762003-03-23 01:06:05 +0000612}
bellard31e31b82003-02-18 22:55:36 +0000613
bellardb346ff42003-06-15 20:05:50 +0000614
bellardb346ff42003-06-15 20:05:50 +0000615
bellard66fb9762003-03-23 01:06:05 +0000616
pbrook624f7972008-05-31 16:11:38 +0000617void process_pending_signals(CPUState *cpu_env)
bellard66fb9762003-03-23 01:06:05 +0000618{
619 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000620 abi_ulong handler;
bellard9de5e442003-03-23 16:49:39 +0000621 sigset_t set, old_set;
Anthony Liguoric227f092009-10-01 16:12:16 -0500622 target_sigset_t target_old_set;
pbrook624f7972008-05-31 16:11:38 +0000623 struct emulated_sigtable *k;
624 struct target_sigaction *sa;
bellard66fb9762003-03-23 01:06:05 +0000625 struct sigqueue *q;
pbrook624f7972008-05-31 16:11:38 +0000626 TaskState *ts = cpu_env->opaque;
ths3b46e622007-09-17 08:09:54 +0000627
pbrook624f7972008-05-31 16:11:38 +0000628 if (!ts->signal_pending)
bellard31e31b82003-02-18 22:55:36 +0000629 return;
630
pbrook624f7972008-05-31 16:11:38 +0000631 /* FIXME: This is not threadsafe. */
632 k = ts->sigtab;
bellard66fb9762003-03-23 01:06:05 +0000633 for(sig = 1; sig <= TARGET_NSIG; sig++) {
634 if (k->pending)
bellard31e31b82003-02-18 22:55:36 +0000635 goto handle_signal;
bellard66fb9762003-03-23 01:06:05 +0000636 k++;
bellard31e31b82003-02-18 22:55:36 +0000637 }
638 /* if no signal is pending, just return */
pbrook624f7972008-05-31 16:11:38 +0000639 ts->signal_pending = 0;
bellard31e31b82003-02-18 22:55:36 +0000640 return;
bellard66fb9762003-03-23 01:06:05 +0000641
bellard31e31b82003-02-18 22:55:36 +0000642 handle_signal:
bellard66fb9762003-03-23 01:06:05 +0000643#ifdef DEBUG_SIGNAL
bellardbc8a22c2003-03-30 21:02:40 +0000644 fprintf(stderr, "qemu: process signal %d\n", sig);
bellard66fb9762003-03-23 01:06:05 +0000645#endif
646 /* dequeue signal */
647 q = k->first;
648 k->first = q->next;
649 if (!k->first)
650 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +0000651
bellard1fddef42005-04-17 19:16:13 +0000652 sig = gdb_handlesig (cpu_env, sig);
653 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +0000654 sa = NULL;
655 handler = TARGET_SIG_IGN;
656 } else {
657 sa = &sigact_table[sig - 1];
658 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +0000659 }
bellard66fb9762003-03-23 01:06:05 +0000660
bellard66fb9762003-03-23 01:06:05 +0000661 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000662 /* default handler : ignore some signal. The other are job control or fatal */
663 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
664 kill(getpid(),SIGSTOP);
665 } else if (sig != TARGET_SIGCHLD &&
666 sig != TARGET_SIGURG &&
667 sig != TARGET_SIGWINCH &&
668 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +0000669 force_sig(sig);
670 }
671 } else if (handler == TARGET_SIG_IGN) {
672 /* ignore sig */
673 } else if (handler == TARGET_SIG_ERR) {
674 force_sig(sig);
675 } else {
bellard9de5e442003-03-23 16:49:39 +0000676 /* compute the blocked signals during the handler execution */
pbrook624f7972008-05-31 16:11:38 +0000677 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +0000678 /* SA_NODEFER indicates that the current signal should not be
679 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +0000680 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +0000681 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +0000682
bellard9de5e442003-03-23 16:49:39 +0000683 /* block signals in the handler using Linux */
684 sigprocmask(SIG_BLOCK, &set, &old_set);
685 /* save the previous blocked signal state to restore it at the
686 end of the signal execution (see do_sigreturn) */
bellard92319442004-06-19 16:58:13 +0000687 host_to_target_sigset_internal(&target_old_set, &old_set);
bellard9de5e442003-03-23 16:49:39 +0000688
bellardbc8a22c2003-03-30 21:02:40 +0000689 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +0000690#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +0000691 {
692 CPUX86State *env = cpu_env;
693 if (env->eflags & VM_MASK)
694 save_v86_state(env);
695 }
696#endif
bellard9de5e442003-03-23 16:49:39 +0000697 /* prepare the stack frame of the virtual CPU */
pbrook624f7972008-05-31 16:11:38 +0000698 if (sa->sa_flags & TARGET_SA_SIGINFO)
699 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +0000700 else
pbrook624f7972008-05-31 16:11:38 +0000701 setup_frame(sig, sa, &target_old_set, cpu_env);
702 if (sa->sa_flags & TARGET_SA_RESETHAND)
703 sa->_sa_handler = TARGET_SIG_DFL;
bellard31e31b82003-02-18 22:55:36 +0000704 }
bellard66fb9762003-03-23 01:06:05 +0000705 if (q != &k->info)
pbrook624f7972008-05-31 16:11:38 +0000706 free_sigqueue(cpu_env, q);
bellard31e31b82003-02-18 22:55:36 +0000707}