]> git.proxmox.com Git - qemu.git/commitdiff
basic signal handling
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 23 Mar 2003 01:06:05 +0000 (01:06 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 23 Mar 2003 01:06:05 +0000 (01:06 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@41 c046a42c-6fe2-441c-8c8c-71466251a162

Makefile
TODO
linux-user/main.c
linux-user/qemu.h
linux-user/signal.c
linux-user/syscall.c
linux-user/syscall_defs.h
ops_template.h
syscall-i386.h

index ea67590c3cb8165e830eeee0eb037a8b1706d2ac..9f1d31c364fabb612e2a19559b868b6028215765 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -36,7 +36,7 @@ LDFLAGS+=-p
 main.o: CFLAGS+=-p
 endif
 
-OBJS= elfload.o main.o thunk.o syscall.o libgemu.a
+OBJS= elfload.o main.o thunk.o syscall.o signal.o libgemu.a
 
 LIBOBJS+=translate-i386.o op-i386.o exec-i386.o
 # NOTE: the disassembler code is only needed for debugging
diff --git a/TODO b/TODO
index 5c7c963df31e790df1deceabf547bfdf07511639..64384834a19da65d0188c34d79d9a3a5094c8ceb 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,5 +1,7 @@
+- asynchronous signal interrupt / clear synchronous signal handling
+- add eflags restore in emulator
+- finish signal handing (fp87 state)
 - verify thread support (clone() and various locks)
-- signals
 - optimize translated cache chaining (DLL PLT-like system)
 - vm86 syscall support
 - overrides/16bit for string ops
index cd08c474c458ea386e76403b1bec1d679b365150..bcaa4be161ec4ab46e34438c4321b439041a4835 100644 (file)
@@ -81,10 +81,6 @@ int cpu_x86_inl(int addr)
     return 0;
 }
 
-/* default linux values for the selectors */
-#define __USER_CS      (0x23)
-#define __USER_DS      (0x2B)
-
 void write_dt(void *ptr, unsigned long addr, unsigned long limit, 
               int seg32_bit)
 {
@@ -135,6 +131,7 @@ void cpu_loop(struct CPUX86State *env)
                     (long)pc, err);
             abort();
         }
+        process_pending_signals(env);
     }
 }
 
@@ -199,6 +196,7 @@ int main(int argc, char **argv)
 
     target_set_brk((char *)info->brk);
     syscall_init();
+    signal_init();
 
     env = cpu_x86_init();
 
index ae86176c35bdc6691a714abf517e81d102fadc37..77e9ecadd9a2b9e1aceed23dc4bf2a5f735cf3a1 100644 (file)
@@ -3,6 +3,12 @@
 
 #include "thunk.h"
 
+#ifdef TARGET_I386
+
+/* default linux values for the selectors */
+#define __USER_CS      (0x23)
+#define __USER_DS      (0x2B)
+
 struct target_pt_regs {
        long ebx;
        long ecx;
@@ -21,6 +27,8 @@ struct target_pt_regs {
        int  xss;
 };
 
+#endif
+
 /* This struct is used to hold certain information about the image.
  * Basically, it replicates in user space what would be certain
  * task_struct fields in the kernel
@@ -53,5 +61,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
 void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
 struct CPUX86State;
 void cpu_loop(struct CPUX86State *env);
+void process_pending_signals(void *cpu_env);
+void signal_init(void);
 
 #endif
index 2e0d5995531492fe51d66095723aa3e0fec26d84..61baf995ae2ccbb26ac1fad276e2b982eab5848c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Emulation of Linux signal handling
+ *  Emulation of Linux signals
  * 
  *  Copyright (c) 2003 Fabrice Bellard
  *
  */
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 #include <stdarg.h>
 #include <signal.h>
+#include <errno.h>
 #include <sys/ucontext.h>
 
-/* Algorithm strongly inspired from em86 : we queue the signals so
-   that we can handle them at precise points in the emulated code. */
+#include "gemu.h"
+
+#include "syscall_defs.h"
+
+#ifdef TARGET_I386
+#include "cpu-i386.h"
+#include "syscall-i386.h"
+#endif
+
+/* signal handling inspired from em86. */
+
+//#define DEBUG_SIGNAL
+
+#define MAX_SIGQUEUE_SIZE 1024
+
+struct sigqueue {
+    struct sigqueue *next;
+    siginfo_t info;
+};
 
 struct emulated_sigaction {
     struct target_sigaction sa;
-    int nb_pending;
-    struct target_siginfo info;
+    int pending; /* true if signal is pending */
+    struct sigqueue *first;
+    struct sigqueue info; /* in order to always have memory for the
+                             first signal, we put it here */
 };
 
-struct emulated_sigaction sigact_table[NSIG];
-int signal_pending;
+static struct emulated_sigaction sigact_table[TARGET_NSIG];
+static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
+static struct sigqueue *first_free; /* first free siginfo queue entry */
+static int signal_pending; /* non zero if a signal may be pending */
 
+static void host_signal_handler(int host_signum, siginfo_t *info, 
+                                void *puc);
+
+/* XXX: do it properly */
 static inline int host_to_target_signal(int sig)
 {
     return sig;
@@ -45,6 +72,51 @@ static inline int target_to_host_signal(int sig)
     return sig;
 }
 
+void host_to_target_sigset(target_sigset_t *d, sigset_t *s)
+{
+    int i;
+    for(i = 0;i < TARGET_NSIG_WORDS; i++) {
+        d->sig[i] = tswapl(((unsigned long *)s)[i]);
+    }
+}
+
+void target_to_host_sigset(sigset_t *d, target_sigset_t *s)
+{
+    int i;
+    for(i = 0;i < TARGET_NSIG_WORDS; i++) {
+        ((unsigned long *)d)[i] = tswapl(s->sig[i]);
+    }
+}
+
+void host_to_target_old_sigset(target_ulong *old_sigset, 
+                               const sigset_t *sigset)
+{
+    *old_sigset = tswap32(*(unsigned long *)sigset & 0xffffffff);
+}
+
+void target_to_host_old_sigset(sigset_t *sigset, 
+                               const target_ulong *old_sigset)
+{
+    sigemptyset(sigset);
+    *(unsigned long *)sigset = tswapl(*old_sigset);
+}
+
+/* XXX: finish it */
+void host_to_target_siginfo(target_siginfo_t *tinfo, siginfo_t *info)
+{
+    tinfo->si_signo = tswap32(info->si_signo);
+    tinfo->si_errno = tswap32(info->si_errno);
+    tinfo->si_code = tswap32(info->si_code);
+}
+
+/* XXX: finish it */
+void target_to_host_siginfo(siginfo_t *info, target_siginfo_t *tinfo)
+{
+    info->si_signo = tswap32(tinfo->si_signo);
+    info->si_errno = tswap32(tinfo->si_errno);
+    info->si_code = tswap32(tinfo->si_code);
+}
+
 void signal_init(void)
 {
     struct sigaction act;
@@ -55,51 +127,664 @@ void signal_init(void)
     act.sa_flags = SA_SIGINFO;
     act.sa_sigaction = host_signal_handler;
     for(i = 1; i < NSIG; i++) {
-       sigaction(i, &sa, NULL);
+       sigaction(i, &act, NULL);
     }
     
     memset(sigact_table, 0, sizeof(sigact_table));
+
+    first_free = &sigqueue_table[0];
+    for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) 
+        sigqueue_table[i].next = &sigqueue_table[i + 1];
+    sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;
+}
+
+/* signal queue handling */
+
+static inline struct sigqueue *alloc_sigqueue(void)
+{
+    struct sigqueue *q = first_free;
+    if (!q)
+        return NULL;
+    first_free = q->next;
+    return q;
 }
 
+static inline void free_sigqueue(struct sigqueue *q)
+{
+    q->next = first_free;
+    first_free = q;
+}
+
+static int queue_signal(struct emulated_sigaction *k, int sig, siginfo_t *info)
+{
+    struct sigqueue *q, **pq;
+
+    pq = &k->first;
+    if (!k->pending || sig < TARGET_SIGRTMIN) {
+        /* first signal or non real time signal */
+        q = &k->info;
+    } else {
+        q = alloc_sigqueue();
+        if (!q)
+            return -EAGAIN;
+        while (*pq != NULL)
+            pq = &(*pq)->next;
+    }
+    *pq = q;
+    q->info = *info;
+    q->next = NULL;
+    k->pending = 1;
+    /* signal that a new signal is pending */
+    signal_pending = 1;
+    return 0;
+}
+
+void force_sig(int sig)
+{
+    int host_sig;
+    /* abort execution with signal */
+    host_sig = target_to_host_signal(sig);
+    fprintf(stderr, "gemu: uncaught target signal %d (%s) - exiting\n", 
+            sig, strsignal(host_sig));
+    _exit(-host_sig);
+}
+
+
 static void host_signal_handler(int host_signum, siginfo_t *info, 
                                 void *puc)
 {
-    struct ucontext *uc = puc;
-    int signum;
+    struct emulated_sigaction *k;
+    int sig;
+    target_ulong handler;
+
     /* get target signal number */
-    signum = host_to_target(host_signum);
-    if (signum >= TARGET_NSIG)
+    sig = host_to_target_signal(host_signum);
+    if (sig < 1 || sig > TARGET_NSIG)
         return;
-    /* we save the old mask */
-    
-    
+    k = &sigact_table[sig - 1];
+#ifdef DEBUG_SIGNAL
+    fprintf(stderr, "gemu: got signal %d\n", sig);
+#endif
+    handler = k->sa._sa_handler;
+    if (handler == TARGET_SIG_DFL) {
+        /* default handler : ignore some signal. The other are fatal */
+        if (sig != TARGET_SIGCHLD && 
+            sig != TARGET_SIGURG && 
+            sig != TARGET_SIGWINCH) {
+            force_sig(sig);
+        }
+    } else if (handler == TARGET_SIG_IGN) {
+        /* ignore signal */
+    } else if (handler == TARGET_SIG_ERR) {
+        force_sig(sig);
+    } else {
+        queue_signal(k, sig, info);
+    }
+}
+
+int do_sigaction(int sig, const struct target_sigaction *act,
+                 struct target_sigaction *oact)
+{
+    struct emulated_sigaction *k;
+
+    if (sig < 1 || sig > TARGET_NSIG)
+        return -EINVAL;
+    k = &sigact_table[sig - 1];
+#if defined(DEBUG_SIGNAL) && 0
+    fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n", 
+            sig, (int)act, (int)oact);
+#endif
+    if (oact) {
+        oact->_sa_handler = tswapl(k->sa._sa_handler);
+        oact->sa_flags = tswapl(k->sa.sa_flags);
+        oact->sa_restorer = tswapl(k->sa.sa_restorer);
+        oact->sa_mask = k->sa.sa_mask;
+    }
+    if (act) {
+        k->sa._sa_handler = tswapl(act->_sa_handler);
+        k->sa.sa_flags = tswapl(act->sa_flags);
+        k->sa.sa_restorer = tswapl(act->sa_restorer);
+        k->sa.sa_mask = act->sa_mask;
+    }
+    return 0;
+}
+
+#ifdef TARGET_I386
+
+/* from the Linux kernel */
+
+struct target_fpreg {
+       uint16_t significand[4];
+       uint16_t exponent;
+};
+
+struct target_fpxreg {
+       uint16_t significand[4];
+       uint16_t exponent;
+       uint16_t padding[3];
+};
+
+struct target_xmmreg {
+       target_ulong element[4];
+};
+
+struct target_fpstate {
+       /* Regular FPU environment */
+       target_ulong    cw;
+       target_ulong    sw;
+       target_ulong    tag;
+       target_ulong    ipoff;
+       target_ulong    cssel;
+       target_ulong    dataoff;
+       target_ulong    datasel;
+       struct target_fpreg     _st[8];
+       uint16_t        status;
+       uint16_t        magic;          /* 0xffff = regular FPU data only */
+
+       /* FXSR FPU environment */
+       target_ulong    _fxsr_env[6];   /* FXSR FPU env is ignored */
+       target_ulong    mxcsr;
+       target_ulong    reserved;
+       struct target_fpxreg    _fxsr_st[8];    /* FXSR FPU reg data is ignored */
+       struct target_xmmreg    _xmm[8];
+       target_ulong    padding[56];
+};
+
+#define X86_FXSR_MAGIC         0x0000
+
+struct target_sigcontext {
+       uint16_t gs, __gsh;
+       uint16_t fs, __fsh;
+       uint16_t es, __esh;
+       uint16_t ds, __dsh;
+       target_ulong edi;
+       target_ulong esi;
+       target_ulong ebp;
+       target_ulong esp;
+       target_ulong ebx;
+       target_ulong edx;
+       target_ulong ecx;
+       target_ulong eax;
+       target_ulong trapno;
+       target_ulong err;
+       target_ulong eip;
+       uint16_t cs, __csh;
+       target_ulong eflags;
+       target_ulong esp_at_signal;
+       uint16_t ss, __ssh;
+        target_ulong fpstate; /* pointer */
+       target_ulong oldmask;
+       target_ulong cr2;
+};
+
+typedef struct target_sigaltstack {
+       target_ulong ss_sp;
+       int ss_flags;
+       target_ulong ss_size;
+} target_stack_t;
+
+struct target_ucontext {
+        target_ulong     uc_flags;
+       target_ulong      uc_link;
+       target_stack_t    uc_stack;
+       struct target_sigcontext uc_mcontext;
+       target_sigset_t   uc_sigmask;   /* mask last for extensibility */
+};
+
+struct sigframe
+{
+    target_ulong pretcode;
+    int sig;
+    struct target_sigcontext sc;
+    struct target_fpstate fpstate;
+    target_ulong extramask[TARGET_NSIG_WORDS-1];
+    char retcode[8];
+};
+
+struct rt_sigframe
+{
+    target_ulong pretcode;
+    int sig;
+    target_ulong pinfo;
+    target_ulong puc;
+    struct target_siginfo info;
+    struct target_ucontext uc;
+    struct target_fpstate fpstate;
+    char retcode[8];
+};
+
+/*
+ * Set up a signal frame.
+ */
+
+#define __put_user(x,ptr)\
+({\
+    int size = sizeof(*ptr);\
+    switch(size) {\
+    case 1:\
+        stb(ptr, (typeof(*ptr))(x));\
+        break;\
+    case 2:\
+        stw(ptr, (typeof(*ptr))(x));\
+        break;\
+    case 4:\
+        stl(ptr, (typeof(*ptr))(x));\
+        break;\
+    case 8:\
+        stq(ptr, (typeof(*ptr))(x));\
+        break;\
+    default:\
+        abort();\
+    }\
+    0;\
+})
+
+#define get_user(val, ptr) (typeof(*ptr))(*(ptr))
+
+
+#define __copy_to_user(dst, src, size)\
+({\
+    memcpy(dst, src, size);\
+    0;\
+})
+
+static inline int copy_siginfo_to_user(target_siginfo_t *tinfo, siginfo_t *info)
+{
+    host_to_target_siginfo(tinfo, info);
+    return 0;
+}
+
+/* XXX: save x87 state */
+static int
+setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
+                CPUX86State *env, unsigned long mask)
+{
+       int err = 0;
+
+       err |= __put_user(env->segs[R_GS], (unsigned int *)&sc->gs);
+       err |= __put_user(env->segs[R_FS], (unsigned int *)&sc->fs);
+       err |= __put_user(env->segs[R_ES], (unsigned int *)&sc->es);
+       err |= __put_user(env->segs[R_DS], (unsigned int *)&sc->ds);
+       err |= __put_user(env->regs[R_EDI], &sc->edi);
+       err |= __put_user(env->regs[R_ESI], &sc->esi);
+       err |= __put_user(env->regs[R_EBP], &sc->ebp);
+       err |= __put_user(env->regs[R_ESP], &sc->esp);
+       err |= __put_user(env->regs[R_EBX], &sc->ebx);
+       err |= __put_user(env->regs[R_EDX], &sc->edx);
+       err |= __put_user(env->regs[R_ECX], &sc->ecx);
+       err |= __put_user(env->regs[R_EAX], &sc->eax);
+       err |= __put_user(/*current->thread.trap_no*/ 0, &sc->trapno);
+       err |= __put_user(/*current->thread.error_code*/ 0, &sc->err);
+       err |= __put_user(env->eip, &sc->eip);
+       err |= __put_user(env->segs[R_CS], (unsigned int *)&sc->cs);
+       err |= __put_user(env->eflags, &sc->eflags);
+       err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal);
+       err |= __put_user(env->segs[R_SS], (unsigned int *)&sc->ss);
+#if 0
+       tmp = save_i387(fpstate);
+       if (tmp < 0)
+         err = 1;
+       else
+         err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
+#else
+        err |= __put_user(0, &sc->fpstate);
+#endif
+       /* non-iBCS2 extensions.. */
+       err |= __put_user(mask, &sc->oldmask);
+       err |= __put_user(/*current->thread.cr2*/ 0, &sc->cr2);
+
+       return err;
 }
 
+/*
+ * Determine which stack to use..
+ */
 
-void process_pending_signals(void)
+static inline void *
+get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
 {
-    int signum;
-    target_ulong _sa_handler;
+       unsigned long esp;
+
+       /* Default to using normal stack */
+       esp = env->regs[R_ESP];
+#if 0
+       /* This is the X/Open sanctioned signal stack switching.  */
+       if (ka->sa.sa_flags & SA_ONSTACK) {
+               if (sas_ss_flags(esp) == 0)
+                       esp = current->sas_ss_sp + current->sas_ss_size;
+       }
+
+       /* This is the legacy signal stack switching. */
+       else if ((regs->xss & 0xffff) != __USER_DS &&
+                !(ka->sa.sa_flags & SA_RESTORER) &&
+                ka->sa.sa_restorer) {
+               esp = (unsigned long) ka->sa.sa_restorer;
+       }
+#endif
+       return (void *)((esp - frame_size) & -8ul);
+}
+
+#define TF_MASK TRAP_FLAG
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+                       target_sigset_t *set, CPUX86State *env)
+{
+       struct sigframe *frame;
+       int err = 0;
+
+       frame = get_sigframe(ka, env, sizeof(*frame));
+
+#if 0
+       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+               goto give_sigsegv;
+#endif
+       err |= __put_user((/*current->exec_domain
+                          && current->exec_domain->signal_invmap
+                          && sig < 32
+                          ? current->exec_domain->signal_invmap[sig]
+                          : */ sig),
+                         &frame->sig);
+       if (err)
+               goto give_sigsegv;
+
+       setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0]);
+       if (err)
+               goto give_sigsegv;
+
+       if (TARGET_NSIG_WORDS > 1) {
+               err |= __copy_to_user(frame->extramask, &set->sig[1],
+                                     sizeof(frame->extramask));
+       }
+       if (err)
+               goto give_sigsegv;
+
+       /* Set up to return from userspace.  If provided, use a stub
+          already in userspace.  */
+       if (ka->sa.sa_flags & TARGET_SA_RESTORER) {
+               err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+       } else {
+               err |= __put_user(frame->retcode, &frame->pretcode);
+               /* This is popl %eax ; movl $,%eax ; int $0x80 */
+               err |= __put_user(0xb858, (short *)(frame->retcode+0));
+               err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
+               err |= __put_user(0x80cd, (short *)(frame->retcode+6));
+       }
+
+       if (err)
+               goto give_sigsegv;
+
+       /* Set up registers for signal handler */
+       env->regs[R_ESP] = (unsigned long) frame;
+       env->eip = (unsigned long) ka->sa._sa_handler;
+
+        cpu_x86_load_seg(env, R_DS, __USER_DS);
+        cpu_x86_load_seg(env, R_ES, __USER_DS);
+        cpu_x86_load_seg(env, R_SS, __USER_DS);
+        cpu_x86_load_seg(env, R_CS, __USER_CS);
+       env->eflags &= ~TF_MASK;
+
+       return;
+
+give_sigsegv:
+       if (sig == TARGET_SIGSEGV)
+               ka->sa._sa_handler = TARGET_SIG_DFL;
+       force_sig(TARGET_SIGSEGV /* , current */);
+}
+
+static void setup_rt_frame(int sig, struct emulated_sigaction *ka, siginfo_t *info,
+                          target_sigset_t *set, CPUX86State *env)
+{
+       struct rt_sigframe *frame;
+       int err = 0;
+
+       frame = get_sigframe(ka, env, sizeof(*frame));
+
+#if 0
+       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+               goto give_sigsegv;
+#endif
+
+       err |= __put_user((/*current->exec_domain
+                          && current->exec_domain->signal_invmap
+                          && sig < 32
+                          ? current->exec_domain->signal_invmap[sig]
+                          : */sig),
+                         &frame->sig);
+       err |= __put_user((target_ulong)&frame->info, &frame->pinfo);
+       err |= __put_user((target_ulong)&frame->uc, &frame->puc);
+       err |= copy_siginfo_to_user(&frame->info, info);
+       if (err)
+               goto give_sigsegv;
 
-    struct emulated_sigaction *esig;
+       /* Create the ucontext.  */
+       err |= __put_user(0, &frame->uc.uc_flags);
+       err |= __put_user(0, &frame->uc.uc_link);
+       err |= __put_user(/*current->sas_ss_sp*/ 0, &frame->uc.uc_stack.ss_sp);
+       err |= __put_user(/* sas_ss_flags(regs->esp) */ 0,
+                         &frame->uc.uc_stack.ss_flags);
+       err |= __put_user(/* current->sas_ss_size */ 0, &frame->uc.uc_stack.ss_size);
+       err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
+                               env, set->sig[0]);
+       err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+       if (err)
+               goto give_sigsegv;
 
+       /* Set up to return from userspace.  If provided, use a stub
+          already in userspace.  */
+       if (ka->sa.sa_flags & TARGET_SA_RESTORER) {
+               err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+       } else {
+               err |= __put_user(frame->retcode, &frame->pretcode);
+               /* This is movl $,%eax ; int $0x80 */
+               err |= __put_user(0xb8, (char *)(frame->retcode+0));
+               err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
+               err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+       }
+
+       if (err)
+               goto give_sigsegv;
+
+       /* Set up registers for signal handler */
+       env->regs[R_ESP] = (unsigned long) frame;
+       env->eip = (unsigned long) ka->sa._sa_handler;
+
+        cpu_x86_load_seg(env, R_DS, __USER_DS);
+        cpu_x86_load_seg(env, R_ES, __USER_DS);
+        cpu_x86_load_seg(env, R_SS, __USER_DS);
+        cpu_x86_load_seg(env, R_CS, __USER_CS);
+       env->eflags &= ~TF_MASK;
+
+       return;
+
+give_sigsegv:
+       if (sig == TARGET_SIGSEGV)
+               ka->sa._sa_handler = TARGET_SIG_DFL;
+       force_sig(TARGET_SIGSEGV /* , current */);
+}
+
+static int
+restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
+{
+       unsigned int err = 0;
+
+
+        
+#define COPY(x)                err |= __get_user(regs->x, &sc->x)
+
+#define COPY_SEG(seg)                                                  \
+       { unsigned short tmp;                                           \
+         err |= __get_user(tmp, &sc->seg);                             \
+         regs->x##seg = tmp; }
+
+#define COPY_SEG_STRICT(seg)                                           \
+       { unsigned short tmp;                                           \
+         err |= __get_user(tmp, &sc->seg);                             \
+         regs->x##seg = tmp|3; }
+
+#define GET_SEG(seg)                                                   \
+       { unsigned short tmp;                                           \
+         err |= __get_user(tmp, &sc->seg);                             \
+         loadsegment(seg,tmp); }
+
+        cpu_x86_load_seg(env, R_GS, lduw(&sc->gs));
+        cpu_x86_load_seg(env, R_FS, lduw(&sc->fs));
+        cpu_x86_load_seg(env, R_ES, lduw(&sc->es));
+        cpu_x86_load_seg(env, R_DS, lduw(&sc->ds));
+
+        env->regs[R_EDI] = ldl(&sc->edi);
+        env->regs[R_ESI] = ldl(&sc->esi);
+        env->regs[R_EBP] = ldl(&sc->ebp);
+        env->regs[R_ESP] = ldl(&sc->esp);
+        env->regs[R_EBX] = ldl(&sc->ebx);
+        env->regs[R_EDX] = ldl(&sc->edx);
+        env->regs[R_ECX] = ldl(&sc->ecx);
+        env->eip = ldl(&sc->eip);
+
+        cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3);
+        cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3);
+       
+       {
+               unsigned int tmpflags;
+                tmpflags = ldl(&sc->eflags);
+               env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
+                //             regs->orig_eax = -1;            /* disable syscall checks */
+       }
+
+#if 0
+       {
+               struct _fpstate * buf;
+               err |= __get_user(buf, &sc->fpstate);
+               if (buf) {
+                       if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+                               goto badframe;
+                       err |= restore_i387(buf);
+               }
+       }
+#endif
+        *peax = ldl(&sc->eax);
+       return err;
+#if 0
+badframe:
+       return 1;
+#endif
+}
+
+long do_sigreturn(CPUX86State *env)
+{
+    struct sigframe *frame = (struct sigframe *)(env->regs[R_ESP] - 8);
+    target_sigset_t target_set;
+    sigset_t set;
+    int eax, i;
+
+    /* set blocked signals */
+    target_set.sig[0] = frame->sc.oldmask;
+    for(i = 1; i < TARGET_NSIG_WORDS; i++)
+        target_set.sig[i] = frame->extramask[i - 1];
+
+    target_to_host_sigset(&set, &target_set);
+    sigprocmask(SIG_SETMASK, &set, NULL);
+    
+    /* restore registers */
+    if (restore_sigcontext(env, &frame->sc, &eax))
+        goto badframe;
+    return eax;
+
+badframe:
+    force_sig(TARGET_SIGSEGV);
+    return 0;
+}
+
+long do_rt_sigreturn(CPUX86State *env)
+{
+       struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4);
+       target_sigset_t target_set;
+        sigset_t set;
+        //     stack_t st;
+       int eax;
+
+#if 0
+       if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+               goto badframe;
+#endif
+        memcpy(&target_set, &frame->uc.uc_sigmask, sizeof(target_sigset_t));
+
+        target_to_host_sigset(&set, &target_set);
+        sigprocmask(SIG_SETMASK, &set, NULL);
+       
+       if (restore_sigcontext(env, &frame->uc.uc_mcontext, &eax))
+               goto badframe;
+
+#if 0
+       if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+               goto badframe;
+       /* It is more difficult to avoid calling this function than to
+          call it and ignore errors.  */
+       do_sigaltstack(&st, NULL, regs->esp);
+#endif
+       return eax;
+
+badframe:
+       force_sig(TARGET_SIGSEGV);
+       return 0;
+}
+
+#endif
+
+void process_pending_signals(void *cpu_env)
+{
+    int sig;
+    target_ulong handler;
+    target_sigset_t set;
+    struct emulated_sigaction *k;
+    struct sigqueue *q;
+    
     if (!signal_pending)
         return;
 
-    esig = sigact_table;
-    for(signum = 1; signum < TARGET_NSIG; signum++) {
-        if (esig->nb_pending != 0)
+    k = sigact_table;
+    for(sig = 1; sig <= TARGET_NSIG; sig++) {
+        if (k->pending)
             goto handle_signal;
-        esig++;
+        k++;
     }
     /* if no signal is pending, just return */
     signal_pending = 0;
     return;
+
  handle_signal:
-    _sa_handler = esig->sa._sa_handler;
-    if (_sa_handler == TARGET_SIG_DFL) {
-        /* default handling
+#ifdef DEBUG_SIGNAL
+    fprintf(stderr, "gemu: process signal %d\n", sig);
+#endif
+    /* dequeue signal */
+    q = k->first;
+    k->first = q->next;
+    if (!k->first)
+        k->pending = 0;
+
+    handler = k->sa._sa_handler;
+    if (handler == TARGET_SIG_DFL) {
+        /* default handler : ignore some signal. The other are fatal */
+        if (sig != TARGET_SIGCHLD && 
+            sig != TARGET_SIGURG && 
+            sig != TARGET_SIGWINCH) {
+            force_sig(sig);
+        }
+    } else if (handler == TARGET_SIG_IGN) {
+        /* ignore sig */
+    } else if (handler == TARGET_SIG_ERR) {
+        force_sig(sig);
+    } else {
+        set = k->sa.sa_mask;
+        /* send the signal to the CPU */
+        if (k->sa.sa_flags & TARGET_SA_SIGINFO)
+            setup_rt_frame(sig, k, &q->info, &set, cpu_env);
+        else
+            setup_frame(sig, k, &set, cpu_env);
+       if (k->sa.sa_flags & TARGET_SA_RESETHAND)
+            k->sa._sa_handler = TARGET_SIG_DFL;
     }
+    if (q != &k->info)
+        free_sigqueue(q);
+}
 
 
-}
index da54a0a186819ee6ae5bd085c98c00402680cf9b..dbe3de3fdf2c385effef8e63b76b2e45f9e4a8a2 100644 (file)
 #include "syscall-i386.h"
 #endif
 
+void host_to_target_siginfo(target_siginfo_t *tinfo, siginfo_t *info);
+void target_to_host_siginfo(siginfo_t *info, target_siginfo_t *tinfo);
+long do_sigreturn(CPUX86State *env);
+long do_rt_sigreturn(CPUX86State *env);
+
 #define __NR_sys_uname __NR_uname
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_statfs __NR_statfs
 #define __NR_sys_fstatfs __NR_fstatfs
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
+#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
 
 #ifdef __NR_gettid
 _syscall0(int, gettid)
@@ -97,6 +103,9 @@ _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
           loff_t *, res, uint, wh);
 _syscall2(int,sys_statfs,const char *,path,struct kernel_statfs *,buf)
 _syscall2(int,sys_fstatfs,int,fd,struct kernel_statfs *,buf)
+_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
+
+extern int personality(int);
 
 static inline long get_errno(long ret)
 {
@@ -199,18 +208,18 @@ static inline void host_to_target_fds(target_long *target_fds,
 #endif
 }
 
-/* XXX: incorrect for some archs */
-static void host_to_target_old_sigset(target_ulong *old_sigset, 
-                                      const sigset_t *sigset)
+static inline void target_to_host_timeval(struct timeval *tv, 
+                                          struct target_timeval *target_tv)
 {
-    *old_sigset = tswap32(*(unsigned long *)sigset & 0xffffffff);
+    tv->tv_sec = tswapl(target_tv->tv_sec);
+    tv->tv_usec = tswapl(target_tv->tv_usec);
 }
 
-static void target_to_host_old_sigset(sigset_t *sigset
-                                      const target_ulong *old_sigset)
+static inline void host_to_target_timeval(struct target_timeval *target_tv
+                                          struct timeval *tv)
 {
-    sigemptyset(sigset);
-    *(unsigned long *)sigset = tswapl(*old_sigset);
+    target_tv->tv_sec = tswapl(tv->tv_sec);
+    target_tv->tv_usec = tswapl(tv->tv_usec);
 }
 
 
@@ -1042,28 +1051,195 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         ret = get_errno(setsid());
         break;
     case TARGET_NR_sigaction:
-#if 1
         {
-            ret = 0;
+            struct target_old_sigaction *old_act = (void *)arg2;
+            struct target_old_sigaction *old_oact = (void *)arg3;
+            struct target_sigaction act, oact, *pact;
+            if (old_act) {
+                act._sa_handler = old_act->_sa_handler;
+                target_siginitset(&act.sa_mask, old_act->sa_mask);
+                act.sa_flags = old_act->sa_flags;
+                act.sa_restorer = old_act->sa_restorer;
+                pact = &act;
+            } else {
+                pact = NULL;
+            }
+            ret = get_errno(do_sigaction(arg1, pact, &oact));
+            if (!is_error(ret) && old_oact) {
+                old_oact->_sa_handler = oact._sa_handler;
+                old_oact->sa_mask = oact.sa_mask.sig[0];
+                old_oact->sa_flags = oact.sa_flags;
+                old_oact->sa_restorer = oact.sa_restorer;
+            }
         }
         break;
-#else
-        goto unimplemented;
-#endif
+    case TARGET_NR_rt_sigaction:
+        ret = get_errno(do_sigaction(arg1, (void *)arg2, (void *)arg3));
+        break;
     case TARGET_NR_sgetmask:
-        goto unimplemented;
+        {
+            sigset_t cur_set;
+            target_ulong target_set;
+            sigprocmask(0, NULL, &cur_set);
+            host_to_target_old_sigset(&target_set, &cur_set);
+            ret = target_set;
+        }
+        break;
     case TARGET_NR_ssetmask:
-        goto unimplemented;
+        {
+            sigset_t set, oset, cur_set;
+            target_ulong target_set = arg1;
+            sigprocmask(0, NULL, &cur_set);
+            target_to_host_old_sigset(&set, &target_set);
+            sigorset(&set, &set, &cur_set);
+            sigprocmask(SIG_SETMASK, &set, &oset);
+            host_to_target_old_sigset(&target_set, &oset);
+            ret = target_set;
+        }
+        break;
+    case TARGET_NR_sigprocmask:
+        {
+            int how = arg1;
+            sigset_t set, oldset, *set_ptr;
+            target_ulong *pset = (void *)arg2, *poldset = (void *)arg3;
+            
+            if (pset) {
+                switch(how) {
+                case TARGET_SIG_BLOCK:
+                    how = SIG_BLOCK;
+                    break;
+                case TARGET_SIG_UNBLOCK:
+                    how = SIG_UNBLOCK;
+                    break;
+                case TARGET_SIG_SETMASK:
+                    how = SIG_SETMASK;
+                    break;
+                default:
+                    ret = -EINVAL;
+                    goto fail;
+                }
+                target_to_host_old_sigset(&set, pset);
+                set_ptr = &set;
+            } else {
+                how = 0;
+                set_ptr = NULL;
+            }
+            ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
+            if (!is_error(ret) && poldset) {
+                host_to_target_old_sigset(poldset, &oldset);
+            }
+        }
+        break;
+    case TARGET_NR_rt_sigprocmask:
+        {
+            int how = arg1;
+            sigset_t set, oldset, *set_ptr;
+            target_sigset_t *pset = (void *)arg2;
+            target_sigset_t *poldset = (void *)arg3;
+            
+            if (pset) {
+                switch(how) {
+                case TARGET_SIG_BLOCK:
+                    how = SIG_BLOCK;
+                    break;
+                case TARGET_SIG_UNBLOCK:
+                    how = SIG_UNBLOCK;
+                    break;
+                case TARGET_SIG_SETMASK:
+                    how = SIG_SETMASK;
+                    break;
+                default:
+                    ret = -EINVAL;
+                    goto fail;
+                }
+                target_to_host_sigset(&set, pset);
+                set_ptr = &set;
+            } else {
+                how = 0;
+                set_ptr = NULL;
+            }
+            ret = get_errno(sigprocmask(how, set_ptr, &oldset));
+            if (!is_error(ret) && poldset) {
+                host_to_target_sigset(poldset, &oldset);
+            }
+        }
+        break;
+    case TARGET_NR_sigpending:
+        {
+            sigset_t set;
+            ret = get_errno(sigpending(&set));
+            if (!is_error(ret)) {
+                host_to_target_old_sigset((target_ulong *)arg1, &set);
+            }
+        }
+        break;
+    case TARGET_NR_rt_sigpending:
+        {
+            sigset_t set;
+            ret = get_errno(sigpending(&set));
+            if (!is_error(ret)) {
+                host_to_target_sigset((target_sigset_t *)arg1, &set);
+            }
+        }
+        break;
+    case TARGET_NR_sigsuspend:
+        {
+            sigset_t set;
+            target_to_host_old_sigset(&set, (target_ulong *)arg1);
+            ret = get_errno(sigsuspend(&set));
+        }
+        break;
+    case TARGET_NR_rt_sigsuspend:
+        {
+            sigset_t set;
+            target_to_host_sigset(&set, (target_sigset_t *)arg1);
+            ret = get_errno(sigsuspend(&set));
+        }
+        break;
+    case TARGET_NR_rt_sigtimedwait:
+        {
+            target_sigset_t *target_set = (void *)arg1;
+            target_siginfo_t *target_uinfo = (void *)arg2;
+            struct target_timespec *target_uts = (void *)arg3;
+            sigset_t set;
+            struct timespec uts, *puts;
+            siginfo_t uinfo;
+            
+            target_to_host_sigset(&set, target_set);
+            if (target_uts) {
+                puts = &uts;
+                puts->tv_sec = tswapl(target_uts->tv_sec);
+                puts->tv_nsec = tswapl(target_uts->tv_nsec);
+            } else {
+                puts = NULL;
+            }
+            ret = get_errno(sigtimedwait(&set, &uinfo, puts));
+            if (!is_error(ret) && target_uinfo) {
+                host_to_target_siginfo(target_uinfo, &uinfo);
+            }
+        }
+        break;
+    case TARGET_NR_rt_sigqueueinfo:
+        {
+            siginfo_t uinfo;
+            target_to_host_siginfo(&uinfo, (target_siginfo_t *)arg3);
+            ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
+        }
+        break;
+    case TARGET_NR_sigreturn:
+        /* NOTE: ret is eax, so not transcoding must be done */
+        ret = do_sigreturn(cpu_env);
+        break;
+    case TARGET_NR_rt_sigreturn:
+        /* NOTE: ret is eax, so not transcoding must be done */
+        ret = do_rt_sigreturn(cpu_env);
+        break;
     case TARGET_NR_setreuid:
         ret = get_errno(setreuid(arg1, arg2));
         break;
     case TARGET_NR_setregid:
         ret = get_errno(setregid(arg1, arg2));
         break;
-    case TARGET_NR_sigsuspend:
-        goto unimplemented;
-    case TARGET_NR_sigpending:
-        goto unimplemented;
     case TARGET_NR_sethostname:
         ret = get_errno(sethostname((const char *)arg1, arg2));
         break;
@@ -1190,9 +1366,43 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_syslog:
         goto unimplemented;
     case TARGET_NR_setitimer:
-        goto unimplemented;
+        {
+            struct target_itimerval *target_value = (void *)arg2;
+            struct target_itimerval *target_ovalue = (void *)arg3;
+            struct itimerval value, ovalue, *pvalue;
+
+            if (target_value) {
+                pvalue = &value;
+                target_to_host_timeval(&pvalue->it_interval, 
+                                       &target_value->it_interval);
+                target_to_host_timeval(&pvalue->it_value, 
+                                       &target_value->it_value);
+            } else {
+                pvalue = NULL;
+            }
+            ret = get_errno(setitimer(arg1, pvalue, &ovalue));
+            if (!is_error(ret) && target_ovalue) {
+                host_to_target_timeval(&target_ovalue->it_interval, 
+                                       &ovalue.it_interval);
+                host_to_target_timeval(&target_ovalue->it_value, 
+                                       &ovalue.it_value);
+            }
+        }
+        break;
     case TARGET_NR_getitimer:
-        goto unimplemented;
+        {
+            struct target_itimerval *target_value = (void *)arg2;
+            struct itimerval value;
+            
+            ret = get_errno(getitimer(arg1, &value));
+            if (!is_error(ret) && target_value) {
+                host_to_target_timeval(&target_value->it_interval, 
+                                       &value.it_interval);
+                host_to_target_timeval(&target_value->it_value, 
+                                       &value.it_value);
+            }
+        }
+        break;
     case TARGET_NR_stat:
         ret = get_errno(stat((const char *)arg1, &st));
         goto do_stat;
@@ -1279,8 +1489,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_fsync:
         ret = get_errno(fsync(arg1));
         break;
-    case TARGET_NR_sigreturn:
-        goto unimplemented;
     case TARGET_NR_clone:
         ret = get_errno(do_fork(cpu_env, arg1, arg2));
         break;
@@ -1301,39 +1509,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_mprotect:
         ret = get_errno(mprotect((void *)arg1, arg2, arg3));
         break;
-    case TARGET_NR_sigprocmask:
-        {
-            int how = arg1;
-            sigset_t set, oldset, *set_ptr;
-            target_ulong *pset = (void *)arg2, *poldset = (void *)arg3;
-            
-            switch(how) {
-            case TARGET_SIG_BLOCK:
-                how = SIG_BLOCK;
-                break;
-            case TARGET_SIG_UNBLOCK:
-                how = SIG_UNBLOCK;
-                break;
-            case TARGET_SIG_SETMASK:
-                how = SIG_SETMASK;
-                break;
-            default:
-                ret = -EINVAL;
-                goto fail;
-            }
-            
-            if (pset) {
-                target_to_host_old_sigset(&set, pset);
-                set_ptr = &set;
-            } else {
-                set_ptr = NULL;
-            }
-            ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
-            if (!is_error(ret) && poldset) {
-                host_to_target_old_sigset(poldset, &oldset);
-            }
-        }
-        break;
     case TARGET_NR_create_module:
     case TARGET_NR_init_module:
     case TARGET_NR_delete_module:
@@ -1516,13 +1691,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_setresgid:
     case TARGET_NR_getresgid:
     case TARGET_NR_prctl:
-    case TARGET_NR_rt_sigreturn:
-    case TARGET_NR_rt_sigaction:
-    case TARGET_NR_rt_sigprocmask:
-    case TARGET_NR_rt_sigpending:
-    case TARGET_NR_rt_sigtimedwait:
-    case TARGET_NR_rt_sigqueueinfo:
-    case TARGET_NR_rt_sigsuspend:
     case TARGET_NR_pread:
     case TARGET_NR_pwrite:
         goto unimplemented;
index 6b0a714cb7b924fc19ba80a9a7360bf664a8e49e..b83aeacebdda8cb5f06239c32ded6981c6ad3d14 100644 (file)
@@ -29,6 +29,11 @@ struct target_timespec {
     target_long tv_nsec;
 };
 
+struct target_itimerval {
+    struct target_timeval it_interval;
+    struct target_timeval it_value;
+};
+
 struct target_iovec {
     target_long iov_base;   /* Starting address */
     target_long iov_len;   /* Number of bytes */
@@ -113,6 +118,38 @@ typedef struct {
     target_ulong sig[TARGET_NSIG_WORDS];
 } target_sigset_t;
 
+#ifdef BSWAP_NEEDED
+static inline void tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
+{
+    int i;
+    for(i = 0;i < TARGET_NSIG_WORDS; i++)
+        d->sig[i] = tswapl(s->sig[i]);
+}
+#else
+static inline void tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
+{
+    *d = *s;
+}
+#endif
+
+static inline void target_siginitset(target_sigset_t *d, target_ulong set)
+{
+    int i;
+    d->sig[0] = set;
+    for(i = 1;i < TARGET_NSIG_WORDS; i++)
+        d->sig[i] = 0;
+}
+
+void host_to_target_sigset(target_sigset_t *d, sigset_t *s);
+void target_to_host_sigset(sigset_t *d, target_sigset_t *s);
+void host_to_target_old_sigset(target_ulong *old_sigset, 
+                               const sigset_t *sigset);
+void target_to_host_old_sigset(sigset_t *sigset, 
+                               const target_ulong *old_sigset);
+struct target_sigaction;
+int do_sigaction(int sig, const struct target_sigaction *act,
+                 struct target_sigaction *oact);
+
 /* Networking ioctls */
 #define TARGET_SIOCADDRT       0x890B          /* add routing table entry */
 #define TARGET_SIOCDELRT       0x890C          /* delete routing table entry */
index 70ee9f355cefc3322a2b00937a613246604f661b..1a2380041210edfcb8aa3ef277c34a45dfe4540d 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ *  i386 micro operations (included several times to generate
+ *  different operand sizes)
+ * 
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ */
 
 #define DATA_BITS (1 << (3 + SHIFT))
 #define SHIFT_MASK (DATA_BITS - 1)
index 3d270d77540f263d8ad9105278286370531b7349..39bba1a493e45d04c57394ab672815a5321d4137 100644 (file)
@@ -302,20 +302,59 @@ struct target_stat64 {
        unsigned long long      st_ino;
 };
 
-typedef unsigned long old_sigset_t;            /* at least 32 bits */
+#define TARGET_SA_NOCLDSTOP    0x00000001
+#define TARGET_SA_NOCLDWAIT    0x00000002 /* not supported yet */
+#define TARGET_SA_SIGINFO      0x00000004
+#define TARGET_SA_ONSTACK      0x08000000
+#define TARGET_SA_RESTART      0x10000000
+#define TARGET_SA_NODEFER      0x40000000
+#define TARGET_SA_RESETHAND    0x80000000
+#define TARGET_SA_RESTORER     0x04000000
+
+#define TARGET_SIGHUP           1
+#define TARGET_SIGINT           2
+#define TARGET_SIGQUIT          3
+#define TARGET_SIGILL           4
+#define TARGET_SIGTRAP          5
+#define TARGET_SIGABRT          6
+#define TARGET_SIGIOT           6
+#define TARGET_SIGBUS           7
+#define TARGET_SIGFPE           8
+#define TARGET_SIGKILL          9
+#define TARGET_SIGUSR1         10
+#define TARGET_SIGSEGV         11
+#define TARGET_SIGUSR2         12
+#define TARGET_SIGPIPE         13
+#define TARGET_SIGALRM         14
+#define TARGET_SIGTERM         15
+#define TARGET_SIGSTKFLT       16
+#define TARGET_SIGCHLD         17
+#define TARGET_SIGCONT         18
+#define TARGET_SIGSTOP         19
+#define TARGET_SIGTSTP         20
+#define TARGET_SIGTTIN         21
+#define TARGET_SIGTTOU         22
+#define TARGET_SIGURG          23
+#define TARGET_SIGXCPU         24
+#define TARGET_SIGXFSZ         25
+#define TARGET_SIGVTALRM       26
+#define TARGET_SIGPROF         27
+#define TARGET_SIGWINCH                28
+#define TARGET_SIGIO           29
+#define TARGET_SIGRTMIN         32
 
 struct target_old_sigaction {
         target_ulong _sa_handler;
         target_ulong sa_mask;
         target_ulong sa_flags;
-        void (*sa_restorer)(void);
+        target_ulong sa_restorer;
 };
 
 struct target_sigaction {
         target_ulong _sa_handler;
-        target_sigset_t sa_mask;
         target_ulong sa_flags;
         target_ulong sa_restorer;
+        target_sigset_t sa_mask;
 };
 
 typedef union target_sigval {