Annotation of qemu/darwin-user/signal.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.