File:  [Qemu by Fabrice Bellard] / qemu / darwin-user / signal.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:55:09 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    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., 51 Franklin Street - Fifth Floor, Boston,
   19:  *  MA 02110-1301, USA.
   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"
   40: #include "qemu-common.h"
   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: 
   59: static struct sigaltstack target_sigaltstack_used = {
   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 */
  136: void QEMU_NORETURN force_sig(int sig)
  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 */
  203:     if (host_signum == SIGSEGV || host_signum == SIGBUS) {
  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