signal.c (66fb9763af9cd743158957e8c9c2559d922b1c22) signal.c (9de5e440b9f6a6c6305c0b81d1df4ddcc5a4b966)
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

--- 13 unchanged lines hidden (view full) ---

22#include <string.h>
23#include <stdarg.h>
24#include <signal.h>
25#include <errno.h>
26#include <sys/ucontext.h>
27
28#include "gemu.h"
29
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

--- 13 unchanged lines hidden (view full) ---

22#include <string.h>
23#include <stdarg.h>
24#include <signal.h>
25#include <errno.h>
26#include <sys/ucontext.h>
27
28#include "gemu.h"
29
30#include "syscall_defs.h"
31
32#ifdef TARGET_I386
33#include "cpu-i386.h"
34#include "syscall-i386.h"
35#endif
36
37/* signal handling inspired from em86. */
38
39//#define DEBUG_SIGNAL
40
41#define MAX_SIGQUEUE_SIZE 1024
42
43struct sigqueue {
44 struct sigqueue *next;
30/* signal handling inspired from em86. */
31
32//#define DEBUG_SIGNAL
33
34#define MAX_SIGQUEUE_SIZE 1024
35
36struct sigqueue {
37 struct sigqueue *next;
45 siginfo_t info;
38 target_siginfo_t info;
46};
47
48struct emulated_sigaction {
49 struct target_sigaction sa;
50 int pending; /* true if signal is pending */
51 struct sigqueue *first;
52 struct sigqueue info; /* in order to always have memory for the
53 first signal, we put it here */

--- 42 unchanged lines hidden (view full) ---

96
97void target_to_host_old_sigset(sigset_t *sigset,
98 const target_ulong *old_sigset)
99{
100 sigemptyset(sigset);
101 *(unsigned long *)sigset = tswapl(*old_sigset);
102}
103
39};
40
41struct emulated_sigaction {
42 struct target_sigaction sa;
43 int pending; /* true if signal is pending */
44 struct sigqueue *first;
45 struct sigqueue info; /* in order to always have memory for the
46 first signal, we put it here */

--- 42 unchanged lines hidden (view full) ---

89
90void target_to_host_old_sigset(sigset_t *sigset,
91 const target_ulong *old_sigset)
92{
93 sigemptyset(sigset);
94 *(unsigned long *)sigset = tswapl(*old_sigset);
95}
96
104/* XXX: finish it */
105void host_to_target_siginfo(target_siginfo_t *tinfo, siginfo_t *info)
97/* siginfo conversion */
98
99static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
100 const siginfo_t *info)
106{
101{
107 tinfo->si_signo = tswap32(info->si_signo);
102 int sig;
103 sig = host_to_target_signal(info->si_signo);
104 tinfo->si_signo = sig;
105 tinfo->si_errno = 0;
106 tinfo->si_code = 0;
107 if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) {
108 /* should never come here, but who knows. The information for
109 the target is irrelevant */
110 tinfo->_sifields._sigfault._addr = 0;
111 } else if (sig >= TARGET_SIGRTMIN) {
112 tinfo->_sifields._rt._pid = info->si_pid;
113 tinfo->_sifields._rt._uid = info->si_uid;
114 /* XXX: potential problem if 64 bit */
115 tinfo->_sifields._rt._sigval.sival_ptr =
116 (target_ulong)info->si_value.sival_ptr;
117 }
118}
119
120static void tswap_siginfo(target_siginfo_t *tinfo,
121 const target_siginfo_t *info)
122{
123 int sig;
124 sig = info->si_signo;
125 tinfo->si_signo = tswap32(sig);
108 tinfo->si_errno = tswap32(info->si_errno);
109 tinfo->si_code = tswap32(info->si_code);
126 tinfo->si_errno = tswap32(info->si_errno);
127 tinfo->si_code = tswap32(info->si_code);
128 if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) {
129 tinfo->_sifields._sigfault._addr =
130 tswapl(info->_sifields._sigfault._addr);
131 } else if (sig >= TARGET_SIGRTMIN) {
132 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
133 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
134 tinfo->_sifields._rt._sigval.sival_ptr =
135 tswapl(info->_sifields._rt._sigval.sival_ptr);
136 }
110}
111
137}
138
112/* XXX: finish it */
113void target_to_host_siginfo(siginfo_t *info, target_siginfo_t *tinfo)
139
140void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
114{
141{
142 host_to_target_siginfo_noswap(tinfo, info);
143 tswap_siginfo(tinfo, tinfo);
144}
145
146/* XXX: we support only POSIX RT signals are used. */
147/* XXX: find a solution for 64 bit (additionnal malloced data is needed) */
148void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
149{
115 info->si_signo = tswap32(tinfo->si_signo);
116 info->si_errno = tswap32(tinfo->si_errno);
117 info->si_code = tswap32(tinfo->si_code);
150 info->si_signo = tswap32(tinfo->si_signo);
151 info->si_errno = tswap32(tinfo->si_errno);
152 info->si_code = tswap32(tinfo->si_code);
153 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
154 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
155 info->si_value.sival_ptr =
156 (void *)tswapl(tinfo->_sifields._rt._sigval.sival_ptr);
118}
119
120void signal_init(void)
121{
122 struct sigaction act;
123 int i;
124
157}
158
159void signal_init(void)
160{
161 struct sigaction act;
162 int i;
163
125 /* set all host signal handlers */
126 sigemptyset(&act.sa_mask);
164 /* set all host signal handlers. ALL signals are blocked during
165 the handlers to serialize them. */
166 sigfillset(&act.sa_mask);
127 act.sa_flags = SA_SIGINFO;
128 act.sa_sigaction = host_signal_handler;
129 for(i = 1; i < NSIG; i++) {
130 sigaction(i, &act, NULL);
131 }
132
133 memset(sigact_table, 0, sizeof(sigact_table));
134

--- 15 unchanged lines hidden (view full) ---

150}
151
152static inline void free_sigqueue(struct sigqueue *q)
153{
154 q->next = first_free;
155 first_free = q;
156}
157
167 act.sa_flags = SA_SIGINFO;
168 act.sa_sigaction = host_signal_handler;
169 for(i = 1; i < NSIG; i++) {
170 sigaction(i, &act, NULL);
171 }
172
173 memset(sigact_table, 0, sizeof(sigact_table));
174

--- 15 unchanged lines hidden (view full) ---

190}
191
192static inline void free_sigqueue(struct sigqueue *q)
193{
194 q->next = first_free;
195 first_free = q;
196}
197
158static int queue_signal(struct emulated_sigaction *k, int sig, siginfo_t *info)
198/* abort execution with signal */
199void __attribute((noreturn)) force_sig(int sig)
159{
200{
160 struct sigqueue *q, **pq;
161
162 pq = &k->first;
163 if (!k->pending || sig < TARGET_SIGRTMIN) {
164 /* first signal or non real time signal */
165 q = &k->info;
166 } else {
167 q = alloc_sigqueue();
168 if (!q)
169 return -EAGAIN;
170 while (*pq != NULL)
171 pq = &(*pq)->next;
172 }
173 *pq = q;
174 q->info = *info;
175 q->next = NULL;
176 k->pending = 1;
177 /* signal that a new signal is pending */
178 signal_pending = 1;
179 return 0;
180}
181
182void force_sig(int sig)
183{
184 int host_sig;
201 int host_sig;
185 /* abort execution with signal */
186 host_sig = target_to_host_signal(sig);
187 fprintf(stderr, "gemu: uncaught target signal %d (%s) - exiting\n",
188 sig, strsignal(host_sig));
202 host_sig = target_to_host_signal(sig);
203 fprintf(stderr, "gemu: uncaught target signal %d (%s) - exiting\n",
204 sig, strsignal(host_sig));
205#if 1
189 _exit(-host_sig);
206 _exit(-host_sig);
207#else
208 {
209 struct sigaction act;
210 sigemptyset(&act.sa_mask);
211 act.sa_flags = SA_SIGINFO;
212 act.sa_sigaction = SIG_DFL;
213 sigaction(SIGABRT, &act, NULL);
214 abort();
215 }
216#endif
190}
191
217}
218
192
193static void host_signal_handler(int host_signum, siginfo_t *info,
194 void *puc)
219/* queue a signal so that it will be send to the virtual CPU as soon
220 as possible */
221int queue_signal(int sig, target_siginfo_t *info)
195{
196 struct emulated_sigaction *k;
222{
223 struct emulated_sigaction *k;
197 int sig;
224 struct sigqueue *q, **pq;
198 target_ulong handler;
199
225 target_ulong handler;
226
200 /* get target signal number */
201 sig = host_to_target_signal(host_signum);
202 if (sig < 1 || sig > TARGET_NSIG)
203 return;
204 k = &sigact_table[sig - 1];
205#ifdef DEBUG_SIGNAL
206 fprintf(stderr, "gemu: got signal %d\n", sig);
227#if defined(DEBUG_SIGNAL)
228 fprintf(stderr, "queue_sigal: sig=%d\n",
229 sig);
207#endif
230#endif
231 k = &sigact_table[sig - 1];
208 handler = k->sa._sa_handler;
209 if (handler == TARGET_SIG_DFL) {
210 /* default handler : ignore some signal. The other are fatal */
211 if (sig != TARGET_SIGCHLD &&
212 sig != TARGET_SIGURG &&
213 sig != TARGET_SIGWINCH) {
214 force_sig(sig);
232 handler = k->sa._sa_handler;
233 if (handler == TARGET_SIG_DFL) {
234 /* default handler : ignore some signal. The other are fatal */
235 if (sig != TARGET_SIGCHLD &&
236 sig != TARGET_SIGURG &&
237 sig != TARGET_SIGWINCH) {
238 force_sig(sig);
239 } else {
240 return 0; /* indicate ignored */
215 }
216 } else if (handler == TARGET_SIG_IGN) {
217 /* ignore signal */
241 }
242 } else if (handler == TARGET_SIG_IGN) {
243 /* ignore signal */
244 return 0;
218 } else if (handler == TARGET_SIG_ERR) {
219 force_sig(sig);
220 } else {
245 } else if (handler == TARGET_SIG_ERR) {
246 force_sig(sig);
247 } else {
221 queue_signal(k, sig, info);
248 pq = &k->first;
249 if (sig < TARGET_SIGRTMIN) {
250 /* if non real time signal, we queue exactly one signal */
251 if (!k->pending)
252 q = &k->info;
253 else
254 return 0;
255 } else {
256 if (!k->pending) {
257 /* first signal */
258 q = &k->info;
259 } else {
260 q = alloc_sigqueue();
261 if (!q)
262 return -EAGAIN;
263 while (*pq != NULL)
264 pq = &(*pq)->next;
265 }
266 }
267 *pq = q;
268 q->info = *info;
269 q->next = NULL;
270 k->pending = 1;
271 /* signal that a new signal is pending */
272 signal_pending = 1;
273 return 1; /* indicates that the signal was queued */
222 }
223}
224
274 }
275}
276
277#if defined(DEBUG_SIGNAL)
278#ifdef __i386__
279static void dump_regs(struct ucontext *uc)
280{
281 fprintf(stderr,
282 "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
283 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
284 "EFL=%08x EIP=%08x\n",
285 uc->uc_mcontext.gregs[EAX],
286 uc->uc_mcontext.gregs[EBX],
287 uc->uc_mcontext.gregs[ECX],
288 uc->uc_mcontext.gregs[EDX],
289 uc->uc_mcontext.gregs[ESI],
290 uc->uc_mcontext.gregs[EDI],
291 uc->uc_mcontext.gregs[EBP],
292 uc->uc_mcontext.gregs[ESP],
293 uc->uc_mcontext.gregs[EFL],
294 uc->uc_mcontext.gregs[EIP]);
295}
296#else
297static void dump_regs(struct ucontext *uc)
298{
299}
300#endif
301
302#endif
303
304static void host_signal_handler(int host_signum, siginfo_t *info,
305 void *puc)
306{
307 int sig;
308 target_siginfo_t tinfo;
309
310 /* the CPU emulator uses some host signals to detect exceptions,
311 we we forward to it some signals */
312 if (host_signum == SIGSEGV || host_signum == SIGBUS) {
313 if (cpu_x86_signal_handler(host_signum, info, puc))
314 return;
315 }
316
317 /* get target signal number */
318 sig = host_to_target_signal(host_signum);
319 if (sig < 1 || sig > TARGET_NSIG)
320 return;
321#if defined(DEBUG_SIGNAL)
322 fprintf(stderr, "gemu: got signal %d\n", sig);
323 dump_regs(puc);
324#endif
325 host_to_target_siginfo_noswap(&tinfo, info);
326 if (queue_signal(sig, &tinfo) == 1) {
327 /* interrupt the virtual CPU as soon as possible */
328 cpu_x86_interrupt(global_env);
329 }
330}
331
225int do_sigaction(int sig, const struct target_sigaction *act,
226 struct target_sigaction *oact)
227{
228 struct emulated_sigaction *k;
229
230 if (sig < 1 || sig > TARGET_NSIG)
231 return -EINVAL;
232 k = &sigact_table[sig - 1];

--- 150 unchanged lines hidden (view full) ---

383
384
385#define __copy_to_user(dst, src, size)\
386({\
387 memcpy(dst, src, size);\
388 0;\
389})
390
332int do_sigaction(int sig, const struct target_sigaction *act,
333 struct target_sigaction *oact)
334{
335 struct emulated_sigaction *k;
336
337 if (sig < 1 || sig > TARGET_NSIG)
338 return -EINVAL;
339 k = &sigact_table[sig - 1];

--- 150 unchanged lines hidden (view full) ---

490
491
492#define __copy_to_user(dst, src, size)\
493({\
494 memcpy(dst, src, size);\
495 0;\
496})
497
391static inline int copy_siginfo_to_user(target_siginfo_t *tinfo, siginfo_t *info)
498static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,
499 const target_siginfo_t *info)
392{
500{
393 host_to_target_siginfo(tinfo, info);
501 tswap_siginfo(tinfo, info);
394 return 0;
395}
396
397/* XXX: save x87 state */
398static int
399setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
400 CPUX86State *env, unsigned long mask)
401{

--- 124 unchanged lines hidden (view full) ---

526 return;
527
528give_sigsegv:
529 if (sig == TARGET_SIGSEGV)
530 ka->sa._sa_handler = TARGET_SIG_DFL;
531 force_sig(TARGET_SIGSEGV /* , current */);
532}
533
502 return 0;
503}
504
505/* XXX: save x87 state */
506static int
507setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
508 CPUX86State *env, unsigned long mask)
509{

--- 124 unchanged lines hidden (view full) ---

634 return;
635
636give_sigsegv:
637 if (sig == TARGET_SIGSEGV)
638 ka->sa._sa_handler = TARGET_SIG_DFL;
639 force_sig(TARGET_SIGSEGV /* , current */);
640}
641
534static void setup_rt_frame(int sig, struct emulated_sigaction *ka, siginfo_t *info,
642static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
643 target_siginfo_t *info,
535 target_sigset_t *set, CPUX86State *env)
536{
537 struct rt_sigframe *frame;
538 int err = 0;
539
540 frame = get_sigframe(ka, env, sizeof(*frame));
541
542#if 0

--- 186 unchanged lines hidden (view full) ---

729}
730
731#endif
732
733void process_pending_signals(void *cpu_env)
734{
735 int sig;
736 target_ulong handler;
644 target_sigset_t *set, CPUX86State *env)
645{
646 struct rt_sigframe *frame;
647 int err = 0;
648
649 frame = get_sigframe(ka, env, sizeof(*frame));
650
651#if 0

--- 186 unchanged lines hidden (view full) ---

838}
839
840#endif
841
842void process_pending_signals(void *cpu_env)
843{
844 int sig;
845 target_ulong handler;
737 target_sigset_t set;
846 sigset_t set, old_set;
847 target_sigset_t target_old_set;
738 struct emulated_sigaction *k;
739 struct sigqueue *q;
740
741 if (!signal_pending)
742 return;
743
744 k = sigact_table;
745 for(sig = 1; sig <= TARGET_NSIG; sig++) {

--- 23 unchanged lines hidden (view full) ---

769 sig != TARGET_SIGWINCH) {
770 force_sig(sig);
771 }
772 } else if (handler == TARGET_SIG_IGN) {
773 /* ignore sig */
774 } else if (handler == TARGET_SIG_ERR) {
775 force_sig(sig);
776 } else {
848 struct emulated_sigaction *k;
849 struct sigqueue *q;
850
851 if (!signal_pending)
852 return;
853
854 k = sigact_table;
855 for(sig = 1; sig <= TARGET_NSIG; sig++) {

--- 23 unchanged lines hidden (view full) ---

879 sig != TARGET_SIGWINCH) {
880 force_sig(sig);
881 }
882 } else if (handler == TARGET_SIG_IGN) {
883 /* ignore sig */
884 } else if (handler == TARGET_SIG_ERR) {
885 force_sig(sig);
886 } else {
777 set = k->sa.sa_mask;
778 /* send the signal to the CPU */
887 /* compute the blocked signals during the handler execution */
888 target_to_host_sigset(&set, &k->sa.sa_mask);
889 /* SA_NODEFER indicates that the current signal should not be
890 blocked during the handler */
891 if (!(k->sa.sa_flags & TARGET_SA_NODEFER))
892 sigaddset(&set, target_to_host_signal(sig));
893
894 /* block signals in the handler using Linux */
895 sigprocmask(SIG_BLOCK, &set, &old_set);
896 /* save the previous blocked signal state to restore it at the
897 end of the signal execution (see do_sigreturn) */
898 host_to_target_sigset(&target_old_set, &old_set);
899
900 /* prepare the stack frame of the virtual CPU */
779 if (k->sa.sa_flags & TARGET_SA_SIGINFO)
901 if (k->sa.sa_flags & TARGET_SA_SIGINFO)
780 setup_rt_frame(sig, k, &q->info, &set, cpu_env);
902 setup_rt_frame(sig, k, &q->info, &target_old_set, cpu_env);
781 else
903 else
782 setup_frame(sig, k, &set, cpu_env);
904 setup_frame(sig, k, &target_old_set, cpu_env);
783 if (k->sa.sa_flags & TARGET_SA_RESETHAND)
784 k->sa._sa_handler = TARGET_SIG_DFL;
785 }
786 if (q != &k->info)
787 free_sigqueue(q);
788}
789
790
905 if (k->sa.sa_flags & TARGET_SA_RESETHAND)
906 k->sa._sa_handler = TARGET_SIG_DFL;
907 }
908 if (q != &k->info)
909 free_sigqueue(q);
910}
911
912