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

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: 

unix.superglobalmegacorp.com

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