Tizen 2.0 Release
[sdk/emulator/qemu.git] / darwin-user / signal.c
1 /*
2  *  Emulation of Linux signals
3  *
4  *  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
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdarg.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <sys/ucontext.h>
26
27 #ifdef __ia64__
28 #undef uc_mcontext
29 #undef uc_sigmask
30 #undef uc_stack
31 #undef uc_link
32 #endif
33
34 #include "qemu.h"
35 #include "qemu-common.h"
36
37 #define DEBUG_SIGNAL
38
39 #define MAX_SIGQUEUE_SIZE 1024
40
41 struct sigqueue {
42     struct sigqueue *next;
43     target_siginfo_t info;
44 };
45
46 struct emulated_sigaction {
47     struct target_sigaction sa;
48     int pending; /* true if signal is pending */
49     struct sigqueue *first;
50     struct sigqueue info; /* in order to always have memory for the
51                              first signal, we put it here */
52 };
53
54 static struct sigaltstack target_sigaltstack_used = {
55     0, 0, SA_DISABLE
56 };
57
58 static struct emulated_sigaction sigact_table[NSIG];
59 static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
60 static struct sigqueue *first_free; /* first free siginfo queue entry */
61 static int signal_pending; /* non zero if a signal may be pending */
62
63 static void host_signal_handler(int host_signum, siginfo_t *info,
64                                 void *puc);
65
66
67 static inline int host_to_target_signal(int sig)
68 {
69     return sig;
70 }
71
72 static inline int target_to_host_signal(int sig)
73 {
74     return sig;
75 }
76
77 /* siginfo conversion */
78
79
80
81 void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
82 {
83
84 }
85
86 void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
87 {
88
89 }
90
91 void signal_init(void)
92 {
93     struct sigaction act;
94     int i;
95
96     /* set all host signal handlers. ALL signals are blocked during
97        the handlers to serialize them. */
98     sigfillset(&act.sa_mask);
99     act.sa_flags = SA_SIGINFO;
100     act.sa_sigaction = host_signal_handler;
101     for(i = 1; i < NSIG; i++) {
102         sigaction(i, &act, NULL);
103     }
104
105     memset(sigact_table, 0, sizeof(sigact_table));
106
107     first_free = &sigqueue_table[0];
108     for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++)
109         sigqueue_table[i].next = &sigqueue_table[i + 1];
110     sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;
111 }
112
113 /* signal queue handling */
114
115 static inline struct sigqueue *alloc_sigqueue(void)
116 {
117     struct sigqueue *q = first_free;
118     if (!q)
119         return NULL;
120     first_free = q->next;
121     return q;
122 }
123
124 static inline void free_sigqueue(struct sigqueue *q)
125 {
126     q->next = first_free;
127     first_free = q;
128 }
129
130 /* abort execution with signal */
131 void QEMU_NORETURN force_sig(int sig)
132 {
133     int host_sig;
134     host_sig = target_to_host_signal(sig);
135     fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
136             sig, strsignal(host_sig));
137     _exit(-host_sig);
138 }
139
140 /* queue a signal so that it will be send to the virtual CPU as soon
141    as possible */
142 int queue_signal(int sig, target_siginfo_t *info)
143 {
144     struct emulated_sigaction *k;
145     struct sigqueue *q, **pq;
146     target_ulong handler;
147
148 #if defined(DEBUG_SIGNAL)
149     fprintf(stderr, "queue_signal: sig=%d\n",
150             sig);
151 #endif
152     k = &sigact_table[sig - 1];
153     handler = (target_ulong)k->sa.sa_handler;
154     if (handler == SIG_DFL) {
155         /* default handler : ignore some signal. The other are fatal */
156         if (sig != SIGCHLD &&
157             sig != SIGURG &&
158             sig != SIGWINCH) {
159             force_sig(sig);
160         } else {
161             return 0; /* indicate ignored */
162         }
163     } else if (handler == host_to_target_signal(SIG_IGN)) {
164         /* ignore signal */
165         return 0;
166     } else if (handler == host_to_target_signal(SIG_ERR)) {
167         force_sig(sig);
168     } else {
169         pq = &k->first;
170         if (!k->pending) {
171             /* first signal */
172             q = &k->info;
173         } else {
174             q = alloc_sigqueue();
175             if (!q)
176                 return -EAGAIN;
177             while (*pq != NULL)
178                 pq = &(*pq)->next;
179         }
180         *pq = q;
181         q->info = *info;
182         q->next = NULL;
183         k->pending = 1;
184         /* signal that a new signal is pending */
185         signal_pending = 1;
186         return 1; /* indicates that the signal was queued */
187     }
188 }
189
190 static void host_signal_handler(int host_signum, siginfo_t *info,
191                                 void *puc)
192 {
193     int sig;
194     target_siginfo_t tinfo;
195
196     /* the CPU emulator uses some host signals to detect exceptions,
197        we we forward to it some signals */
198     if (host_signum == SIGSEGV || host_signum == SIGBUS) {
199         if (cpu_signal_handler(host_signum, (void*)info, puc))
200             return;
201     }
202
203     /* get target signal number */
204     sig = host_to_target_signal(host_signum);
205     if (sig < 1 || sig > NSIG)
206         return;
207
208 #if defined(DEBUG_SIGNAL)
209         fprintf(stderr, "qemu: got signal %d\n", sig);
210 #endif
211     if (queue_signal(sig, &tinfo) == 1) {
212         /* interrupt the virtual CPU as soon as possible */
213         cpu_exit(global_env);
214     }
215 }
216
217 int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
218 {
219     /* XXX: test errors */
220     if(oss)
221     {
222         oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);
223         oss->ss_size = tswap32(target_sigaltstack_used.ss_size);
224         oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);
225     }
226     if(ss)
227     {
228         target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);
229         target_sigaltstack_used.ss_size = tswap32(ss->ss_size);
230         target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);
231     }
232     return 0;
233 }
234
235 int do_sigaction(int sig, const struct sigaction *act,
236                  struct sigaction *oact)
237 {
238     struct emulated_sigaction *k;
239     struct sigaction act1;
240     int host_sig;
241
242     if (sig < 1 || sig > NSIG)
243         return -EINVAL;
244
245     k = &sigact_table[sig - 1];
246 #if defined(DEBUG_SIGNAL)
247     fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
248             sig, (int)act, (int)oact);
249 #endif
250     if (oact) {
251 #if defined(DEBUG_SIGNAL)
252     fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
253             sig, (int)act, (int)oact);
254 #endif
255
256         oact->sa_handler = tswapl(k->sa.sa_handler);
257         oact->sa_flags = tswapl(k->sa.sa_flags);
258         oact->sa_mask = tswapl(k->sa.sa_mask);
259     }
260     if (act) {
261 #if defined(DEBUG_SIGNAL)
262     fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",
263             act->sa_handler, act->sa_flags, act->sa_mask);
264 #endif
265
266         k->sa.sa_handler = tswapl(act->sa_handler);
267         k->sa.sa_flags = tswapl(act->sa_flags);
268         k->sa.sa_mask = tswapl(act->sa_mask);
269         /* we update the host signal state */
270         host_sig = target_to_host_signal(sig);
271         if (host_sig != SIGSEGV && host_sig != SIGBUS) {
272 #if defined(DEBUG_SIGNAL)
273     fprintf(stderr, "sigaction handler going to call sigaction\n",
274             act->sa_handler, act->sa_flags, act->sa_mask);
275 #endif
276
277             sigfillset(&act1.sa_mask);
278             act1.sa_flags = SA_SIGINFO;
279             if (k->sa.sa_flags & SA_RESTART)
280                 act1.sa_flags |= SA_RESTART;
281             /* NOTE: it is important to update the host kernel signal
282                ignore state to avoid getting unexpected interrupted
283                syscalls */
284             if (k->sa.sa_handler == SIG_IGN) {
285                 act1.sa_sigaction = (void *)SIG_IGN;
286             } else if (k->sa.sa_handler == SIG_DFL) {
287                 act1.sa_sigaction = (void *)SIG_DFL;
288             } else {
289                 act1.sa_sigaction = host_signal_handler;
290             }
291             sigaction(host_sig, &act1, NULL);
292         }
293     }
294     return 0;
295 }
296
297
298 #ifdef TARGET_I386
299
300 static inline void *
301 get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
302 {
303     /* XXX Fix that */
304     if(target_sigaltstack_used.ss_flags & SA_DISABLE)
305     {
306         int esp;
307         /* Default to using normal stack */
308         esp = env->regs[R_ESP];
309
310         return (void *)((esp - frame_size) & -8ul);
311     }
312     else
313     {
314         return target_sigaltstack_used.ss_sp;
315     }
316 }
317
318 static void setup_frame(int sig, struct emulated_sigaction *ka,
319                         void *set, CPUState *env)
320 {
321         void *frame;
322
323     fprintf(stderr, "setup_frame %d\n", sig);
324         frame = get_sigframe(ka, env, sizeof(*frame));
325
326         /* Set up registers for signal handler */
327         env->regs[R_ESP] = (unsigned long) frame;
328         env->eip = (unsigned long) ka->sa.sa_handler;
329
330         env->eflags &= ~TF_MASK;
331
332         return;
333
334 give_sigsegv:
335         if (sig == SIGSEGV)
336                 ka->sa.sa_handler = SIG_DFL;
337         force_sig(SIGSEGV /* , current */);
338 }
339
340 long do_sigreturn(CPUState *env, int num)
341 {
342     int i = 0;
343     struct target_sigcontext *scp = get_int_arg(&i, env);
344     /* XXX Get current signal number */
345     /* XXX Adjust accordin to sc_onstack, sc_mask */
346     if(tswapl(scp->sc_onstack) & 0x1)
347         target_sigaltstack_used.ss_flags |= ~SA_DISABLE;
348     else
349         target_sigaltstack_used.ss_flags &=  SA_DISABLE;
350     int set = tswapl(scp->sc_eax);
351     sigprocmask(SIG_SETMASK, &set, NULL);
352
353     fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));
354     fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));
355     fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));
356
357     env->regs[R_EAX] = tswapl(scp->sc_eax);
358     env->regs[R_EBX] = tswapl(scp->sc_ebx);
359     env->regs[R_ECX] = tswapl(scp->sc_ecx);
360     env->regs[R_EDX] = tswapl(scp->sc_edx);
361     env->regs[R_EDI] = tswapl(scp->sc_edi);
362     env->regs[R_ESI] = tswapl(scp->sc_esi);
363     env->regs[R_EBP] = tswapl(scp->sc_ebp);
364     env->regs[R_ESP] = tswapl(scp->sc_esp);
365     env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);
366     env->eflags = tswapl(scp->sc_eflags);
367     env->eip = tswapl(scp->sc_eip);
368     env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);
369     env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);
370     env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);
371     env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);
372     env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);
373
374     /* Again, because our caller's caller will reset EAX */
375     return env->regs[R_EAX];
376 }
377
378 #else
379
380 static void setup_frame(int sig, struct emulated_sigaction *ka,
381                         void *set, CPUState *env)
382 {
383     fprintf(stderr, "setup_frame: not implemented\n");
384 }
385
386 long do_sigreturn(CPUState *env, int num)
387 {
388     int i = 0;
389     struct target_sigcontext *scp = get_int_arg(&i, env);
390     fprintf(stderr, "do_sigreturn: not implemented\n");
391     return -ENOSYS;
392 }
393
394 #endif
395
396 void process_pending_signals(void *cpu_env)
397 {
398     struct emulated_sigaction *k;
399     struct sigqueue *q;
400     target_ulong handler;
401     int sig;
402
403     if (!signal_pending)
404         return;
405
406     k = sigact_table;
407
408     for(sig = 1; sig <= NSIG; sig++) {
409         if (k->pending)
410             goto handle_signal;
411         k++;
412     }
413
414     /* if no signal is pending, just return */
415     signal_pending = 0;
416     return;
417 handle_signal:
418     #ifdef DEBUG_SIGNAL
419     fprintf(stderr, "qemu: process signal %d\n", sig);
420     #endif
421     /* dequeue signal */
422     q = k->first;
423     k->first = q->next;
424     if (!k->first)
425         k->pending = 0;
426
427     sig = gdb_handlesig (cpu_env, sig);
428     if (!sig) {
429         fprintf (stderr, "Lost signal\n");
430         abort();
431     }
432
433     handler = k->sa.sa_handler;
434     if (handler == SIG_DFL) {
435         /* default handler : ignore some signal. The other are fatal */
436         if (sig != SIGCHLD &&
437             sig != SIGURG &&
438             sig != SIGWINCH) {
439             force_sig(sig);
440         }
441     } else if (handler == SIG_IGN) {
442         /* ignore sig */
443     } else if (handler == SIG_ERR) {
444         force_sig(sig);
445     } else {
446
447         setup_frame(sig, k, 0, cpu_env);
448         if (k->sa.sa_flags & SA_RESETHAND)
449             k->sa.sa_handler = SIG_DFL;
450     }
451     if (q != &k->info)
452         free_sigqueue(q);
453 }