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 |