]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/ppc/unix_signal.c
xnu-1504.9.26.tar.gz
[apple/xnu.git] / bsd / dev / ppc / unix_signal.c
index 4351231010339c142611fb338b357dc10666a927..4ca48b0b75e952c24375705adf55ed3753e7d379 100644 (file)
@@ -160,7 +160,7 @@ ucontext_64to32(struct user_ucontext64 *in, struct ucontext64 *out)
  * NOTE: Source and target may *NOT* overlap!
  */
 static void
-siginfo_64to32(user_siginfo_t *in, siginfo_t *out)
+siginfo_user_to_user32(user_siginfo_t *in, user32_siginfo_t *out)
 {
        out->si_signo   = in->si_signo;
        out->si_errno   = in->si_errno;
@@ -168,9 +168,24 @@ siginfo_64to32(user_siginfo_t *in, siginfo_t *out)
        out->si_pid     = in->si_pid;
        out->si_uid     = in->si_uid;
        out->si_status  = in->si_status;
-       out->si_addr    = CAST_DOWN(void *,in->si_addr);
+       out->si_addr    = CAST_DOWN_EXPLICIT(user32_addr_t,in->si_addr);
        /* following cast works for sival_int because of padding */
-       out->si_value.sival_ptr = CAST_DOWN(void *,in->si_value.sival_ptr);
+       out->si_value.sival_ptr = CAST_DOWN_EXPLICIT(user32_addr_t,in->si_value.sival_ptr);
+       out->si_band    = in->si_band;                  /* range reduction */
+       out->__pad[0]   = in->pad[0];                   /* mcontext.ss.r1 */
+}
+
+static void
+siginfo_user_to_user64(user_siginfo_t *in, user64_siginfo_t *out)
+{
+       out->si_signo   = in->si_signo;
+       out->si_errno   = in->si_errno;
+       out->si_code    = in->si_code;
+       out->si_pid     = in->si_pid;
+       out->si_uid     = in->si_uid;
+       out->si_status  = in->si_status;
+       out->si_addr    = in->si_addr;
+       out->si_value.sival_ptr = in->si_value.sival_ptr;
        out->si_band    = in->si_band;                  /* range reduction */
        out->__pad[0]   = in->pad[0];                   /* mcontext.ss.r1 */
 }
@@ -181,7 +196,7 @@ siginfo_64to32(user_siginfo_t *in, siginfo_t *out)
  */
 
 void
-sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused u_long code)
+sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused uint32_t code)
 {
        kern_return_t kretn;
        struct mcontext mctx;
@@ -397,7 +412,7 @@ sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused u_long
                p_uctx = sp;
 
                /* this is where siginfo goes on stack */
-               sp -= sizeof(user_siginfo_t);
+               sp -= sizeof(user64_siginfo_t);
                p_sinfo = sp;
                
                sp = TRUNC_DOWN64(sp, C_64_PARAMSAVE_LEN+C_64_LINKAGE_LEN, C_64_STK_ALIGN);
@@ -414,7 +429,7 @@ sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused u_long
                p_uctx = sp;
 
                /* this is where siginfo goes on stack */
-               sp -= sizeof(siginfo_t);
+               sp -= sizeof(user32_siginfo_t);
                p_sinfo = sp;
 
                sp = TRUNC_DOWN32(sp, C_32_PARAMSAVE_LEN+C_32_LINKAGE_LEN, C_32_STK_ALIGN);
@@ -442,7 +457,7 @@ sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused u_long
             uctx.uc_mcontext64 = p_mctx;
 
        /* setup siginfo */
-       bzero((caddr_t)&sinfo, sizeof(user_siginfo_t));
+       bzero((caddr_t)&sinfo, sizeof(sinfo));
        sinfo.si_signo = sig;
        if (ctx32 == 0) {
                sinfo.si_addr = mctx64.ss.srr0;
@@ -605,29 +620,75 @@ sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused u_long
 
        /* copy info out to user space */
        if (IS_64BIT_PROCESS(p)) {
+               user64_siginfo_t sinfo64;
+
+               siginfo_user_to_user64(&sinfo,&sinfo64);
+
+#if CONFIG_DTRACE              
+        bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
+
+        ut->t_dtrace_siginfo.si_signo = sinfo.si_signo;
+        ut->t_dtrace_siginfo.si_code = sinfo.si_code;
+        ut->t_dtrace_siginfo.si_pid = sinfo.si_pid;
+        ut->t_dtrace_siginfo.si_uid = sinfo.si_uid;
+        ut->t_dtrace_siginfo.si_status = sinfo.si_status;
+               /* XXX truncates faulting address to void * on K32  */
+        ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo.si_addr);
+
+
+        /* Fire DTrace proc:::fault probe when signal is generated by hardware. */
+        switch (sig) {
+        case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP:
+            DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo));
+            break;
+        default:
+            break;
+        }
 
                /* XXX truncates catcher address to uintptr_t */
-               DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo,
+               DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
                        void (*)(void), CAST_DOWN(sig_t, catcher));
+#endif /* CONFIG_DTRACE */
 
                if (copyout(&uctx, p_uctx, sizeof(struct user_ucontext64)))
                        goto bad;
-               if (copyout(&sinfo, p_sinfo, sizeof(user_siginfo_t)))
+               if (copyout(&sinfo64, p_sinfo, sizeof(sinfo64)))
                        goto bad;
        } else {
                struct ucontext64 uctx32;
-               siginfo_t sinfo32;
+               user32_siginfo_t sinfo32;
 
                ucontext_64to32(&uctx, &uctx32);
-               siginfo_64to32(&sinfo,&sinfo32);
+               siginfo_user_to_user32(&sinfo,&sinfo32);
+
+#if CONFIG_DTRACE
+        bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
+
+        ut->t_dtrace_siginfo.si_signo = sinfo.si_signo;
+        ut->t_dtrace_siginfo.si_code = sinfo.si_code;
+        ut->t_dtrace_siginfo.si_pid = sinfo.si_pid;
+        ut->t_dtrace_siginfo.si_uid = sinfo.si_uid;
+        ut->t_dtrace_siginfo.si_status = sinfo.si_status;
+        ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo.si_addr);
+
+
+        /* Fire DTrace proc:::fault probe when signal is generated by hardware. */
+        switch (sig) {
+        case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP:
+            DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo));
+            break;
+        default:
+            break;
+        }
 
-               DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo32,
+               DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
                        void (*)(void), CAST_DOWN(sig_t, catcher));
+#endif /* CONFIG_DTRACE */
 
                if (copyout(&uctx32, p_uctx, sizeof(struct ucontext64)))
                        goto bad;
 
-               if (copyout(&sinfo32, p_sinfo, sizeof(siginfo_t)))
+               if (copyout(&sinfo32, p_sinfo, sizeof(sinfo32)))
                        goto bad;
        }
         if ((ctx32 == 0) || dualcontext) {
@@ -661,16 +722,16 @@ sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused u_long
                        panic("sendsig: thread_setstatus failed, ret = %08X\n", kretn);
                }       
        } else {
-               mctx.ss.r3 = CAST_DOWN(unsigned long,catcher);
-               mctx.ss.r4 = (unsigned long)infostyle;
-               mctx.ss.r5 = (unsigned long)sig;
-               mctx.ss.r6 = CAST_DOWN(unsigned long,p_sinfo);
-               mctx.ss.r7 = CAST_DOWN(unsigned long,p_uctx);
+               mctx.ss.r3 = CAST_DOWN(uint32_t,catcher);
+               mctx.ss.r4 = (uint32_t)infostyle;
+               mctx.ss.r5 = (uint32_t)sig;
+               mctx.ss.r6 = CAST_DOWN(uint32_t,p_sinfo);
+               mctx.ss.r7 = CAST_DOWN(uint32_t,p_uctx);
 
-               mctx.ss.srr0 = CAST_DOWN(unsigned long,trampact);
+               mctx.ss.srr0 = CAST_DOWN(uint32_t,trampact);
                /* MSR_EXPORT_MASK_SET */
                mctx.ss.srr1 = get_msr_exportmask();
-               mctx.ss.r1 = CAST_DOWN(unsigned long,sp);
+               mctx.ss.r1 = CAST_DOWN(uint32_t,sp);
                state_count = PPC_THREAD_STATE_COUNT;
                if ((kretn = thread_setstatus(th_act, PPC_THREAD_STATE, (void *)&mctx.ss, state_count))  != KERN_SUCCESS) {
                        panic("sendsig: thread_setstatus failed, ret = %08X\n", kretn);
@@ -719,7 +780,7 @@ sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
        struct sigacts *ps = p->p_sigacts;
        sigset_t mask;  
        user_addr_t action;
-       unsigned long state_count;
+       uint32_t state_count;
        unsigned int state_flavor;
        struct uthread * ut;
        int vec_used = 0;