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