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

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
1.1.1.4 ! root       17:  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
1.1       root       18:  */
                     19: #include <stdlib.h>
                     20: #include <stdio.h>
                     21: #include <string.h>
                     22: #include <stdarg.h>
                     23: #include <unistd.h>
                     24: #include <signal.h>
                     25: #include <errno.h>
                     26: #include <sys/ucontext.h>
                     27: 
                     28: #ifdef __ia64__
                     29: #undef uc_mcontext
                     30: #undef uc_sigmask
                     31: #undef uc_stack
                     32: #undef uc_link
                     33: #endif
                     34: 
                     35: #include <signal.h>
                     36: 
                     37: #include "qemu.h"
1.1.1.3   root       38: #include "qemu-common.h"
1.1       root       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: 
1.1.1.3   root       57: static struct sigaltstack target_sigaltstack_used = {
1.1       root       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 */
1.1.1.3   root      134: void QEMU_NORETURN force_sig(int sig)
1.1       root      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 */
1.1.1.2   root      201:     if (host_signum == SIGSEGV || host_signum == SIGBUS) {
1.1       root      202:         if (cpu_signal_handler(host_signum, (void*)info, puc))
                    203:             return;
                    204:     }
                    205: 
                    206:     /* get target signal number */
                    207:     sig = host_to_target_signal(host_signum);
                    208:     if (sig < 1 || sig > NSIG)
                    209:         return;
                    210: 
                    211: #if defined(DEBUG_SIGNAL)
                    212:        fprintf(stderr, "qemu: got signal %d\n", sig);
                    213: #endif
                    214:     if (queue_signal(sig, &tinfo) == 1) {
                    215:         /* interrupt the virtual CPU as soon as possible */
1.1.1.4 ! root      216:         cpu_exit(global_env);
1.1       root      217:     }
                    218: }
                    219: 
                    220: int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
                    221: {
                    222:     /* XXX: test errors */
                    223:     if(oss)
                    224:     {
                    225:         oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);
                    226:         oss->ss_size = tswap32(target_sigaltstack_used.ss_size);
                    227:         oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);
                    228:     }
                    229:     if(ss)
                    230:     {
                    231:         target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);
                    232:         target_sigaltstack_used.ss_size = tswap32(ss->ss_size);
                    233:         target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);
                    234:     }
                    235:     return 0;
                    236: }
                    237: 
                    238: int do_sigaction(int sig, const struct sigaction *act,
                    239:                  struct sigaction *oact)
                    240: {
                    241:     struct emulated_sigaction *k;
                    242:     struct sigaction act1;
                    243:     int host_sig;
                    244: 
                    245:     if (sig < 1 || sig > NSIG)
                    246:         return -EINVAL;
                    247: 
                    248:     k = &sigact_table[sig - 1];
                    249: #if defined(DEBUG_SIGNAL)
                    250:     fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
                    251:             sig, (int)act, (int)oact);
                    252: #endif
                    253:     if (oact) {
                    254: #if defined(DEBUG_SIGNAL)
                    255:     fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
                    256:             sig, (int)act, (int)oact);
                    257: #endif
                    258: 
                    259:         oact->sa_handler = tswapl(k->sa.sa_handler);
                    260:         oact->sa_flags = tswapl(k->sa.sa_flags);
                    261:         oact->sa_mask = tswapl(k->sa.sa_mask);
                    262:     }
                    263:     if (act) {
                    264: #if defined(DEBUG_SIGNAL)
                    265:     fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",
                    266:             act->sa_handler, act->sa_flags, act->sa_mask);
                    267: #endif
                    268: 
                    269:         k->sa.sa_handler = tswapl(act->sa_handler);
                    270:         k->sa.sa_flags = tswapl(act->sa_flags);
                    271:         k->sa.sa_mask = tswapl(act->sa_mask);
                    272:         /* we update the host signal state */
                    273:         host_sig = target_to_host_signal(sig);
                    274:         if (host_sig != SIGSEGV && host_sig != SIGBUS) {
                    275: #if defined(DEBUG_SIGNAL)
                    276:     fprintf(stderr, "sigaction handler going to call sigaction\n",
                    277:             act->sa_handler, act->sa_flags, act->sa_mask);
                    278: #endif
                    279: 
                    280:             sigfillset(&act1.sa_mask);
                    281:             act1.sa_flags = SA_SIGINFO;
                    282:             if (k->sa.sa_flags & SA_RESTART)
                    283:                 act1.sa_flags |= SA_RESTART;
                    284:             /* NOTE: it is important to update the host kernel signal
                    285:                ignore state to avoid getting unexpected interrupted
                    286:                syscalls */
                    287:             if (k->sa.sa_handler == SIG_IGN) {
                    288:                 act1.sa_sigaction = (void *)SIG_IGN;
                    289:             } else if (k->sa.sa_handler == SIG_DFL) {
                    290:                 act1.sa_sigaction = (void *)SIG_DFL;
                    291:             } else {
                    292:                 act1.sa_sigaction = host_signal_handler;
                    293:             }
                    294:             sigaction(host_sig, &act1, NULL);
                    295:         }
                    296:     }
                    297:     return 0;
                    298: }
                    299: 
                    300: 
                    301: #ifdef TARGET_I386
                    302: 
                    303: static inline void *
                    304: get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
                    305: {
                    306:     /* XXX Fix that */
                    307:     if(target_sigaltstack_used.ss_flags & SA_DISABLE)
                    308:     {
                    309:         int esp;
                    310:         /* Default to using normal stack */
                    311:         esp = env->regs[R_ESP];
                    312: 
                    313:         return (void *)((esp - frame_size) & -8ul);
                    314:     }
                    315:     else
                    316:     {
                    317:         return target_sigaltstack_used.ss_sp;
                    318:     }
                    319: }
                    320: 
                    321: static void setup_frame(int sig, struct emulated_sigaction *ka,
                    322:                        void *set, CPUState *env)
                    323: {
                    324:        void *frame;
                    325:        int i, err = 0;
                    326: 
                    327:     fprintf(stderr, "setup_frame %d\n", sig);
                    328:        frame = get_sigframe(ka, env, sizeof(*frame));
                    329: 
                    330:        /* Set up registers for signal handler */
                    331:        env->regs[R_ESP] = (unsigned long) frame;
                    332:        env->eip = (unsigned long) ka->sa.sa_handler;
                    333: 
                    334:        env->eflags &= ~TF_MASK;
                    335: 
                    336:        return;
                    337: 
                    338: give_sigsegv:
                    339:        if (sig == SIGSEGV)
                    340:                ka->sa.sa_handler = SIG_DFL;
                    341:        force_sig(SIGSEGV /* , current */);
                    342: }
                    343: 
                    344: long do_sigreturn(CPUState *env, int num)
                    345: {
                    346:     int i = 0;
                    347:     struct target_sigcontext *scp = get_int_arg(&i, env);
                    348:     /* XXX Get current signal number */
                    349:     /* XXX Adjust accordin to sc_onstack, sc_mask */
                    350:     if(tswapl(scp->sc_onstack) & 0x1)
                    351:         target_sigaltstack_used.ss_flags |= ~SA_DISABLE;
                    352:     else
                    353:         target_sigaltstack_used.ss_flags &=  SA_DISABLE;
                    354:     int set = tswapl(scp->sc_eax);
                    355:     sigprocmask(SIG_SETMASK, &set, NULL);
                    356: 
                    357:     fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));
                    358:     fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));
                    359:     fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));
                    360: 
                    361:     env->regs[R_EAX] = tswapl(scp->sc_eax);
                    362:     env->regs[R_EBX] = tswapl(scp->sc_ebx);
                    363:     env->regs[R_ECX] = tswapl(scp->sc_ecx);
                    364:     env->regs[R_EDX] = tswapl(scp->sc_edx);
                    365:     env->regs[R_EDI] = tswapl(scp->sc_edi);
                    366:     env->regs[R_ESI] = tswapl(scp->sc_esi);
                    367:     env->regs[R_EBP] = tswapl(scp->sc_ebp);
                    368:     env->regs[R_ESP] = tswapl(scp->sc_esp);
                    369:     env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);
                    370:     env->eflags = tswapl(scp->sc_eflags);
                    371:     env->eip = tswapl(scp->sc_eip);
                    372:     env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);
                    373:     env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);
                    374:     env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);
                    375:     env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);
                    376:     env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);
                    377: 
                    378:     /* Again, because our caller's caller will reset EAX */
                    379:     return env->regs[R_EAX];
                    380: }
                    381: 
                    382: #else
                    383: 
                    384: static void setup_frame(int sig, struct emulated_sigaction *ka,
                    385:                        void *set, CPUState *env)
                    386: {
                    387:     fprintf(stderr, "setup_frame: not implemented\n");
                    388: }
                    389: 
                    390: long do_sigreturn(CPUState *env, int num)
                    391: {
                    392:     int i = 0;
                    393:     struct target_sigcontext *scp = get_int_arg(&i, env);
                    394:     fprintf(stderr, "do_sigreturn: not implemented\n");
                    395:     return -ENOSYS;
                    396: }
                    397: 
                    398: #endif
                    399: 
                    400: void process_pending_signals(void *cpu_env)
                    401: {
                    402:     struct emulated_sigaction *k;
                    403:     struct sigqueue *q;
                    404:     target_ulong handler;
                    405:     int sig;
                    406: 
                    407:     if (!signal_pending)
                    408:         return;
                    409: 
                    410:     k = sigact_table;
                    411: 
                    412:     for(sig = 1; sig <= NSIG; sig++) {
                    413:         if (k->pending)
                    414:             goto handle_signal;
                    415:         k++;
                    416:     }
                    417: 
                    418:     /* if no signal is pending, just return */
                    419:     signal_pending = 0;
                    420:     return;
                    421: handle_signal:
                    422:     #ifdef DEBUG_SIGNAL
                    423:     fprintf(stderr, "qemu: process signal %d\n", sig);
                    424:     #endif
                    425:     /* dequeue signal */
                    426:     q = k->first;
                    427:     k->first = q->next;
                    428:     if (!k->first)
                    429:         k->pending = 0;
                    430: 
                    431:     sig = gdb_handlesig (cpu_env, sig);
                    432:     if (!sig) {
                    433:         fprintf (stderr, "Lost signal\n");
                    434:         abort();
                    435:     }
                    436: 
                    437:     handler = k->sa.sa_handler;
                    438:     if (handler == SIG_DFL) {
                    439:         /* default handler : ignore some signal. The other are fatal */
                    440:         if (sig != SIGCHLD &&
                    441:             sig != SIGURG &&
                    442:             sig != SIGWINCH) {
                    443:             force_sig(sig);
                    444:         }
                    445:     } else if (handler == SIG_IGN) {
                    446:         /* ignore sig */
                    447:     } else if (handler == SIG_ERR) {
                    448:         force_sig(sig);
                    449:     } else {
                    450: 
                    451:         setup_frame(sig, k, 0, cpu_env);
                    452:        if (k->sa.sa_flags & SA_RESETHAND)
                    453:             k->sa.sa_handler = SIG_DFL;
                    454:     }
                    455:     if (q != &k->info)
                    456:         free_sigqueue(q);
                    457: }

unix.superglobalmegacorp.com

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