Esempio n. 1
0
void sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused uint32_t code)
{
    struct mcontext mctx;
    thread_t th_act;
    struct uthread *ut;
    void *tstate;
    int flavor;
    user_addr_t p_mctx = USER_ADDR_NULL;    /* mcontext dest. */
    int infostyle = UC_TRAD;
    mach_msg_type_number_t state_count;
    user_addr_t trampact;
    int oonstack;
    struct user_ucontext32 uctx;
    user_addr_t sp;
    user_addr_t p_uctx;         /* user stack addr top copy ucontext */
    user_siginfo_t sinfo;
    user_addr_t p_sinfo;        /* user stack addr top copy siginfo */
    struct sigacts *ps = p->p_sigacts;
    int stack_size = 0;
    kern_return_t kretn;
    
    th_act = current_thread();
    kprintf("sendsig: Sending signal to thread %p, code %d.\n", th_act, sig);
    return;

    ut = get_bsdthread_info(th_act);

    if (p->p_sigacts->ps_siginfo & sigmask(sig)) {
        infostyle = UC_FLAVOR;
    }

    flavor = ARM_THREAD_STATE;
    tstate = (void *) &mctx.ss;
    state_count = ARM_THREAD_STATE_COUNT;
    if (thread_getstatus(th_act, flavor, (thread_state_t) tstate, &state_count) != KERN_SUCCESS)
        goto bad;

    trampact = ps->ps_trampact[sig];
    oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;

    /*
     * figure out where our new stack lives 
     */
    if ((ut->uu_flag & UT_ALTSTACK) && !oonstack && (ps->ps_sigonstack & sigmask(sig))) {
        sp = ut->uu_sigstk.ss_sp;
        sp += ut->uu_sigstk.ss_size;
        stack_size = ut->uu_sigstk.ss_size;
        ut->uu_sigstk.ss_flags |= SA_ONSTACK;
    } else {
        sp = CAST_USER_ADDR_T(mctx.ss.sp);
    }

    /*
     * context goes first on stack 
     */
    sp -= sizeof(struct ucontext);
    p_uctx = sp;

    /*
     * this is where siginfo goes on stack 
     */
    sp -= sizeof(user32_siginfo_t);
    p_sinfo = sp;

    /*
     * final stack pointer 
     */
    sp = TRUNC_DOWN32(sp, C_32_PARAMSAVE_LEN + C_32_LINKAGE_LEN, C_32_STK_ALIGN);

    uctx.uc_mcsize = (size_t) ((ARM_THREAD_STATE_COUNT) * sizeof(int));
    uctx.uc_onstack = oonstack;
    uctx.uc_sigmask = mask;
    uctx.uc_stack.ss_sp = sp;
    uctx.uc_stack.ss_size = stack_size;
    if (oonstack)
        uctx.uc_stack.ss_flags |= SS_ONSTACK;
    uctx.uc_link = 0;

    /*
     * setup siginfo 
     */
    bzero((caddr_t) & sinfo, sizeof(sinfo));
    sinfo.si_signo = sig;
    sinfo.si_addr = CAST_USER_ADDR_T(mctx.ss.pc);
    sinfo.pad[0] = CAST_USER_ADDR_T(mctx.ss.sp);

    switch (sig) {
    case SIGILL:
        sinfo.si_code = ILL_NOOP;
        break;
    case SIGFPE:
        sinfo.si_code = FPE_NOOP;
        break;
    case SIGBUS:
        sinfo.si_code = BUS_ADRALN;
        break;
    case SIGSEGV:
        sinfo.si_code = SEGV_ACCERR;
        break;
    default:
        {
            int status_and_exitcode;

            /*
             * All other signals need to fill out a minimum set of
             * information for the siginfo structure passed into
             * the signal handler, if SA_SIGINFO was specified.
             *
             * p->si_status actually contains both the status and
             * the exit code; we save it off in its own variable
             * for later breakdown.
             */
            proc_lock(p);
            sinfo.si_pid = p->si_pid;
            p->si_pid = 0;
            status_and_exitcode = p->si_status;
            p->si_status = 0;
            sinfo.si_uid = p->si_uid;
            p->si_uid = 0;
            sinfo.si_code = p->si_code;
            p->si_code = 0;
            proc_unlock(p);
            if (sinfo.si_code == CLD_EXITED) {
                if (WIFEXITED(status_and_exitcode))
                    sinfo.si_code = CLD_EXITED;
                else if (WIFSIGNALED(status_and_exitcode)) {
                    if (WCOREDUMP(status_and_exitcode)) {
                        sinfo.si_code = CLD_DUMPED;
                        status_and_exitcode = W_EXITCODE(status_and_exitcode, status_and_exitcode);
                    } else {
                        sinfo.si_code = CLD_KILLED;
                        status_and_exitcode = W_EXITCODE(status_and_exitcode, status_and_exitcode);
                    }
                }
            }
            /*
             * The recorded status contains the exit code and the
             * signal information, but the information to be passed
             * in the siginfo to the handler is supposed to only
             * contain the status, so we have to shift it out.
             */
            sinfo.si_status = WEXITSTATUS(status_and_exitcode);
            break;
        }
    }

    if (copyout(&uctx, p_uctx, sizeof(struct user_ucontext32)))
        goto bad;

    if (copyout(&sinfo, p_sinfo, sizeof(sinfo)))
        goto bad;

    /*
     * set signal registers, these are probably wrong.. 
     */
    {
        mctx.ss.r[0] = CAST_DOWN(uint32_t, ua_catcher);
        mctx.ss.r[1] = (uint32_t) infostyle;
        mctx.ss.r[2] = (uint32_t) sig;
        mctx.ss.r[3] = CAST_DOWN(uint32_t, p_sinfo);
        mctx.ss.r[4] = CAST_DOWN(uint32_t, p_uctx);
        mctx.ss.pc = CAST_DOWN(uint32_t, trampact);
        mctx.ss.sp = CAST_DOWN(uint32_t, sp);
        state_count = ARM_THREAD_STATE_COUNT;
        printf("sendsig: Sending signal to thread %p, code %d, new pc 0x%08x\n", th_act, sig, trampact);
        if ((kretn = thread_setstatus(th_act, ARM_THREAD_STATE, (void *) &mctx.ss, state_count)) != KERN_SUCCESS) {
            panic("sendsig: thread_setstatus failed, ret = %08X\n", kretn);
        }
    }

    proc_lock(p);
    return;

 bad:
    proc_lock(p);
    SIGACTION(p, SIGILL) = SIG_DFL;
    sig = sigmask(SIGILL);
    p->p_sigignore &= ~sig;
    p->p_sigcatch &= ~sig;
    ut->uu_sigmask &= ~sig;
    /*
     * sendsig is called with signal lock held 
     */
    proc_unlock(p);
    psignal_locked(p, SIGILL);
    proc_lock(p);
    return;
}
Esempio n. 2
0
void sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused uint32_t code)
{
    user_addr_t ua_sp;
    user_addr_t ua_sip;
    user_addr_t trampact;
    user_addr_t ua_uctxp;
    user_addr_t ua_mctxp;
    user_siginfo_t  sinfo32;

    struct uthread *ut;
    struct mcontext mctx32;
    struct user_ucontext32 uctx32;
    struct sigacts *ps = p->p_sigacts;

    void *state;
    arm_thread_state_t *tstate32;
    mach_msg_type_number_t state_count;

    int stack_size = 0;
    int infostyle = UC_TRAD;
    int oonstack, flavor, error;

    proc_unlock(p);

    thread_t thread = current_thread();
    ut = get_bsdthread_info(thread);

    /*
     * Set up thread state info.
     */
    flavor = ARM_THREAD_STATE;
    state = (void *)&mctx32.ss;
    state_count = ARM_THREAD_STATE_COUNT;
    if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
        goto bad;

    flavor = ARM_EXCEPTION_STATE;
    state = (void *)&mctx32.es;
    state_count = ARM_EXCEPTION_STATE_COUNT;
    if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
        goto bad;

    flavor = ARM_VFP_STATE;
    state = (void *)&mctx32.fs;
    state_count = ARM_VFP_STATE_COUNT;
    if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
        goto bad;

    tstate32 = &mctx32.ss;

    /*
     * Set the signal style.
     */
    if (p->p_sigacts->ps_siginfo & sigmask(sig))
        infostyle = UC_FLAVOR;

    /*
     * Get the signal disposition.
     */
    trampact = ps->ps_trampact[sig];

    /*
     * Figure out where our new stack lives.
     */
    oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;
    if ((ut->uu_flag & UT_ALTSTACK) && !oonstack && (ps->ps_sigonstack & sigmask(sig))) {
        ua_sp = ut->uu_sigstk.ss_sp;
        ua_sp += ut->uu_sigstk.ss_size;
        stack_size = ut->uu_sigstk.ss_size;
        ut->uu_sigstk.ss_flags |= SA_ONSTACK;
    } else {
        ua_sp = tstate32->sp;
    }

    /*
     * Set up the stack.
     */
    ua_sp -= UC_FLAVOR_SIZE;
    ua_mctxp = ua_sp;

    ua_sp -= sizeof(struct user_ucontext32);
    ua_uctxp = ua_sp;

    ua_sp -= sizeof(siginfo_t);
    ua_sip = ua_sp;

    /*
     * Align the stack pointer.
     */
    ua_sp = TRUNC_DOWN32(ua_sp, C_32_STK_ALIGN);

    /*
     * Build the signal context to be used by sigreturn.
     */
    uctx32.uc_onstack = oonstack;
    uctx32.uc_sigmask = mask;
    uctx32.uc_stack.ss_sp = ua_sp;
    uctx32.uc_stack.ss_size = stack_size;

    if (oonstack)
            uctx32.uc_stack.ss_flags |= SS_ONSTACK;

    uctx32.uc_link = 0;

    uctx32.uc_mcsize = UC_FLAVOR_SIZE;

    uctx32.uc_mcontext = ua_mctxp;

    /*
     * init siginfo
     */
    bzero((caddr_t)&sinfo32, sizeof(user_siginfo_t));

    sinfo32.si_signo = sig;
    sinfo32.pad[0]  = tstate32->sp;
    sinfo32.si_addr = tstate32->lr;

    switch (sig) {
        case SIGILL:
            sinfo32.si_code = ILL_NOOP;
            break;
        case SIGFPE:
            sinfo32.si_code = FPE_NOOP;
            break;
        case SIGBUS:
            sinfo32.si_code = BUS_ADRALN;
            break;
        case SIGSEGV:
            sinfo32.si_code = SEGV_ACCERR;
            break;
        default:
            {
                int status_and_exitcode;

                /*
                 * All other signals need to fill out a minimum set of
                 * information for the siginfo structure passed into
                 * the signal handler, if SA_SIGINFO was specified.
                 *
                 * p->si_status actually contains both the status and
                 * the exit code; we save it off in its own variable
                 * for later breakdown.
                 */
                proc_lock(p);
                sinfo32.si_pid = p->si_pid;
                p->si_pid = 0;
                status_and_exitcode = p->si_status;
                p->si_status = 0;
                sinfo32.si_uid = p->si_uid;
                p->si_uid = 0;
                sinfo32.si_code = p->si_code;
                p->si_code = 0;
                proc_unlock(p);
                if (sinfo32.si_code == CLD_EXITED) {
                    if (WIFEXITED(status_and_exitcode))
                        sinfo32.si_code = CLD_EXITED;
                    else if (WIFSIGNALED(status_and_exitcode)) {
                        if (WCOREDUMP(status_and_exitcode)) {
                            sinfo32.si_code = CLD_DUMPED;
                            status_and_exitcode = W_EXITCODE(status_and_exitcode, status_and_exitcode);
                        } else {
                            sinfo32.si_code = CLD_KILLED;
                            status_and_exitcode = W_EXITCODE(status_and_exitcode, status_and_exitcode);
                        }
                    }
                }
                /*
                 * The recorded status contains the exit code and the
                 * signal information, but the information to be passed
                 * in the siginfo to the handler is supposed to only
                 * contain the status, so we have to shift it out.
                 */
                sinfo32.si_status = WEXITSTATUS(status_and_exitcode);
                break;
            }
    }

    /*
     * Copy out context info.
     */
    if (copyout((caddr_t)&uctx32, ua_uctxp, sizeof(struct user_ucontext32)) != KERN_SUCCESS)
        goto bad;
    if (copyout((caddr_t)&sinfo32, ua_sip, sizeof(user_siginfo_t)) != KERN_SUCCESS)
        goto bad;
    if (copyout((caddr_t)&mctx32, ua_mctxp, sizeof(struct mcontext)) != KERN_SUCCESS)
        goto bad;
    if (copyout((caddr_t)&ua_uctxp, ua_sp, sizeof(user_addr_t)) != KERN_SUCCESS)
        goto bad;

    /*
     * Set up regsiters for the trampoline.
     */
    tstate32->r[0] = ua_catcher;
    tstate32->r[1] = infostyle;
    tstate32->r[2] = sig;
    tstate32->r[3] = ua_sip;
    tstate32->sp = ua_sp;

    if (trampact & 0x01) {
        tstate32->lr = trampact;
        tstate32->cpsr = 0x10;      /* User mode */
    } else {
        trampact &= ~0x01;
        tstate32->lr = trampact;
        tstate32->cpsr = 0x10;      /* User mode */
        tstate32->cpsr |= (1 << 5); /* T-bit */
    }

    /*
     * Call the trampoline.
     */
    flavor = ARM_THREAD_STATE;
    state_count = ARM_THREAD_STATE_COUNT;
    state = (void *)tstate32;
    if ((error = thread_setstatus(thread, flavor, (thread_state_t)state, state_count)) != KERN_SUCCESS)
        panic("sendsig: thread_setstatus failed, ret = %08X\n", error);

    proc_lock(p);

    return;

bad:
    proc_lock(p);
    SIGACTION(p, SIGILL) = SIG_DFL;
    sig = sigmask(SIGILL);
    p->p_sigignore &= ~sig;
    p->p_sigcatch &= ~sig;
    ut->uu_sigmask &= ~sig;

    /*
     * sendsig is called with signal lock held
     */
    proc_unlock(p);
    psignal_locked(p, SIGILL);
    proc_lock(p);

    return;
}
Esempio n. 3
0
void
sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused u_long code)
{
	kern_return_t kretn;
	struct mcontext mctx;
	user_addr_t p_mctx = USER_ADDR_NULL;		/* mcontext dest. */
	struct mcontext64 mctx64;
	user_addr_t p_mctx64 = USER_ADDR_NULL;		/* mcontext dest. */
	struct user_ucontext64 uctx;
	user_addr_t p_uctx;		/* user stack addr top copy ucontext */
	user_siginfo_t sinfo;
	user_addr_t p_sinfo;		/* user stack addr top copy siginfo */
	struct sigacts *ps = p->p_sigacts;
	int oonstack;
	user_addr_t sp;
	mach_msg_type_number_t state_count;
	thread_t th_act;
	struct uthread *ut;
	int infostyle = UC_TRAD;
	int dualcontext =0;
	user_addr_t trampact;
	int vec_used = 0;
	int stack_size = 0;
	void * tstate;
	int flavor;
        int ctx32 = 1;

	th_act = current_thread();
	ut = get_bsdthread_info(th_act);

	/*
	 * XXX We conditionalize type passed here based on SA_SIGINFO, but
	 * XXX we always send up all the information, regardless; perhaps
	 * XXX this should not be conditionalized?  Defer making this change
	 * XXX now, due to possible tools impact.
	 */
	if (p->p_sigacts->ps_siginfo & sigmask(sig)) {
		/*
		 * If SA_SIGINFO is set, then we must provide the user
		 * process both a siginfo_t and a context argument.  We call
		 * this "FLAVORED", as opposed to "TRADITIONAL", which doesn't
		 * expect a context.  "DUAL" is a type of "FLAVORED".
		 */
		if (is_64signalregset()) {
			/*
			 * If this is a 64 bit CPU, we must include a 64 bit
			 * context in the data we pass to user space; we may
			 * or may not also include a 32 bit context at the
			 * same time, for non-leaf functions.
			 *
			 * The user may also explicitly choose to not receive
			 * a 32 bit context, at their option; we only allow
			 * this to happen on 64 bit processors, for obvious
			 * reasons.
			 */
			if (IS_64BIT_PROCESS(p) ||
			    (p->p_sigacts->ps_64regset & sigmask(sig))) {
				 /*
				  * For a 64 bit process, there is no 32 bit
				  * context.
				  */
				ctx32 = 0;
				infostyle = UC_FLAVOR64;
			} else {
				/*
				 * For a 32 bit process on a 64 bit CPU, we
				 * may have 64 bit leaf functions, so we need
				 * both contexts.
				 */
				dualcontext = 1;
				infostyle = UC_DUAL;
			}
		} else {
			/*
			 * If this is a 32 bit CPU, then we only have a 32 bit
			 * context to contend with.
			 */
			infostyle = UC_FLAVOR;
		}
        } else {
		/*
		 * If SA_SIGINFO is not set, then we have a traditional style
		 * call which does not need additional context passed.  The
		 * default is 32 bit traditional.
		 *
		 * XXX The second check is redundant on PPC32; keep it anyway.
		 */
		if (is_64signalregset() || IS_64BIT_PROCESS(p)) {
			/*
			 * However, if this is a 64 bit CPU, we need to change
			 * this to 64 bit traditional, and drop the 32 bit
			 * context.
			 */
			ctx32 = 0;
			infostyle = UC_TRAD64;
		}
	}

	proc_unlock(p);

	/* I need this for SIGINFO anyway */
	flavor = PPC_THREAD_STATE;
	tstate = (void *)&mctx.ss;
	state_count = PPC_THREAD_STATE_COUNT;
	if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count)  != KERN_SUCCESS)
		goto bad;

	if ((ctx32 == 0) || dualcontext) {
		flavor = PPC_THREAD_STATE64;
		tstate = (void *)&mctx64.ss;
		state_count = PPC_THREAD_STATE64_COUNT;
                if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count)  != KERN_SUCCESS)
                    goto bad;
	}

        if ((ctx32 == 1) || dualcontext) {
                flavor = PPC_EXCEPTION_STATE;
		tstate = (void *)&mctx.es;
		state_count = PPC_EXCEPTION_STATE_COUNT;
                if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count)  != KERN_SUCCESS)
                    goto bad;
       } 
       
	if ((ctx32 == 0) || dualcontext) {
 		flavor = PPC_EXCEPTION_STATE64;
		tstate = (void *)&mctx64.es;
		state_count = PPC_EXCEPTION_STATE64_COUNT;
       
                if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count)  != KERN_SUCCESS)
                    goto bad;
                
        }
       

        if ((ctx32 == 1) || dualcontext) {
                flavor = PPC_FLOAT_STATE;
		tstate = (void *)&mctx.fs;
		state_count = PPC_FLOAT_STATE_COUNT;
                if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count)  != KERN_SUCCESS)
                    goto bad;
       } 
       
	if ((ctx32 == 0) || dualcontext) {
 		flavor = PPC_FLOAT_STATE;
		tstate = (void *)&mctx64.fs;
		state_count = PPC_FLOAT_STATE_COUNT;
                       if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count)  != KERN_SUCCESS)
                    goto bad;
                
        }


	if (find_user_vec_curr()) {
		vec_used = 1;

                if ((ctx32 == 1) || dualcontext) {
                    flavor = PPC_VECTOR_STATE;
                    tstate = (void *)&mctx.vs;
                    state_count = PPC_VECTOR_STATE_COUNT;
                    if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count)  != KERN_SUCCESS)
                    goto bad;
                    infostyle += 5;
            } 
       
            if ((ctx32 == 0) || dualcontext) {
                    flavor = PPC_VECTOR_STATE;
                    tstate = (void *)&mctx64.vs;
                    state_count = PPC_VECTOR_STATE_COUNT;
                    if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count)  != KERN_SUCCESS)
                        goto bad;
                    infostyle += 5;
           }
	}  

	trampact = ps->ps_trampact[sig];
	oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;

	/* figure out where our new stack lives */
	if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
		(ps->ps_sigonstack & sigmask(sig))) {
		sp = ut->uu_sigstk.ss_sp;
		sp += ut->uu_sigstk.ss_size;
		stack_size = ut->uu_sigstk.ss_size;
		ut->uu_sigstk.ss_flags |= SA_ONSTACK;
	}
	else {
		if (ctx32 == 0)
			sp = mctx64.ss.r1;
		else
			sp = CAST_USER_ADDR_T(mctx.ss.r1);
	}

	
	/* put siginfo on top */
        
	/* preserve RED ZONE area */
	if (IS_64BIT_PROCESS(p))
		sp = TRUNC_DOWN64(sp, C_64_REDZONE_LEN, C_64_STK_ALIGN);
	else
		sp = TRUNC_DOWN32(sp, C_32_REDZONE_LEN, C_32_STK_ALIGN);

        /* next are the saved registers */
        if ((ctx32 == 0) || dualcontext) {
            sp -= sizeof(struct mcontext64);
            p_mctx64 = sp;
        }
        if ((ctx32 == 1) || dualcontext) {
            sp -= sizeof(struct mcontext);
            p_mctx = sp;
        }    
        
	if (IS_64BIT_PROCESS(p)) {
		/* context goes first on stack */
		sp -= sizeof(struct user_ucontext64);
		p_uctx = sp;

		/* this is where siginfo goes on stack */
		sp -= sizeof(user_siginfo_t);
		p_sinfo = sp;
		
		sp = TRUNC_DOWN64(sp, C_64_PARAMSAVE_LEN+C_64_LINKAGE_LEN, C_64_STK_ALIGN);
	} else {
		/*
		 * struct ucontext and struct ucontext64 are identical in
		 * size and content; the only difference is the internal
		 * pointer type for the last element, which makes no
		 * difference for the copyout().
		 */

		/* context goes first on stack */
		sp -= sizeof(struct ucontext64);
		p_uctx = sp;

		/* this is where siginfo goes on stack */
		sp -= sizeof(siginfo_t);
		p_sinfo = sp;

		sp = TRUNC_DOWN32(sp, C_32_PARAMSAVE_LEN+C_32_LINKAGE_LEN, C_32_STK_ALIGN);
	}

	uctx.uc_onstack = oonstack;
	uctx.uc_sigmask = mask;
	uctx.uc_stack.ss_sp = sp;
	uctx.uc_stack.ss_size = stack_size;
	if (oonstack)
		uctx.uc_stack.ss_flags |= SS_ONSTACK;
		
	uctx.uc_link = 0;
	if (ctx32 == 0)
		uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE64_COUNT + PPC_THREAD_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int));
	else
		uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE_COUNT + PPC_THREAD_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int));
	
	if (vec_used) 
		uctx.uc_mcsize += (size_t)(PPC_VECTOR_STATE_COUNT * sizeof(int));
        
	if (ctx32 == 0)
             uctx.uc_mcontext64 = p_mctx64;
       else
            uctx.uc_mcontext64 = p_mctx;

	/* setup siginfo */
	bzero((caddr_t)&sinfo, sizeof(user_siginfo_t));
	sinfo.si_signo = sig;
	if (ctx32 == 0) {
		sinfo.si_addr = mctx64.ss.srr0;
		sinfo.pad[0] = mctx64.ss.r1;
	} else {
		sinfo.si_addr = CAST_USER_ADDR_T(mctx.ss.srr0);
		sinfo.pad[0] = CAST_USER_ADDR_T(mctx.ss.r1);
	}

	switch (sig) {
		case SIGILL:
			/*
			 * If it's 64 bit and not a dual context, mctx will
			 * contain uninitialized data, so we have to use
			 * mctx64 here.
			 */
			if(ctx32 == 0) {
				if (mctx64.ss.srr1 & (1 << (31 - SRR1_PRG_ILL_INS_BIT)))
					sinfo.si_code = ILL_ILLOPC;
				else if (mctx64.ss.srr1 & (1 << (31 - SRR1_PRG_PRV_INS_BIT)))
					sinfo.si_code = ILL_PRVOPC;
				else if (mctx64.ss.srr1 & (1 << (31 - SRR1_PRG_TRAP_BIT)))
					sinfo.si_code = ILL_ILLTRP;
				else
					sinfo.si_code = ILL_NOOP;
			} else {
				if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_ILL_INS_BIT)))
					sinfo.si_code = ILL_ILLOPC;
				else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_PRV_INS_BIT)))
					sinfo.si_code = ILL_PRVOPC;
				else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_TRAP_BIT)))
					sinfo.si_code = ILL_ILLTRP;
				else
					sinfo.si_code = ILL_NOOP;
			}
			break;
		case SIGFPE:
#define FPSCR_VX	2
#define FPSCR_OX	3
#define FPSCR_UX	4
#define FPSCR_ZX	5
#define FPSCR_XX	6
			/*
			 * If it's 64 bit and not a dual context, mctx will
			 * contain uninitialized data, so we have to use
			 * mctx64 here.
			 */
			if(ctx32 == 0) {
				if (mctx64.fs.fpscr & (1 << (31 - FPSCR_VX)))
					sinfo.si_code = FPE_FLTINV;
				else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_OX)))
					sinfo.si_code = FPE_FLTOVF;
				else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_UX)))
					sinfo.si_code = FPE_FLTUND;
				else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_ZX)))
					sinfo.si_code = FPE_FLTDIV;
				else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_XX)))
					sinfo.si_code = FPE_FLTRES;
				else
					sinfo.si_code = FPE_NOOP;
			} else {
				if (mctx.fs.fpscr & (1 << (31 - FPSCR_VX)))
					sinfo.si_code = FPE_FLTINV;
				else if (mctx.fs.fpscr & (1 << (31 - FPSCR_OX)))
					sinfo.si_code = FPE_FLTOVF;
				else if (mctx.fs.fpscr & (1 << (31 - FPSCR_UX)))
					sinfo.si_code = FPE_FLTUND;
				else if (mctx.fs.fpscr & (1 << (31 - FPSCR_ZX)))
					sinfo.si_code = FPE_FLTDIV;
				else if (mctx.fs.fpscr & (1 << (31 - FPSCR_XX)))
					sinfo.si_code = FPE_FLTRES;
				else
					sinfo.si_code = FPE_NOOP;
			}
			break;

		case SIGBUS:
			if (ctx32 == 0) {
				sinfo.si_addr = mctx64.es.dar;
			} else {
				sinfo.si_addr = CAST_USER_ADDR_T(mctx.es.dar);
			}
			/* on ppc we generate only if EXC_PPC_UNALIGNED */
			sinfo.si_code = BUS_ADRALN;
			break;

		case SIGSEGV:
			/*
			 * If it's 64 bit and not a dual context, mctx will
			 * contain uninitialized data, so we have to use
			 * mctx64 here.
			 */
			if (ctx32 == 0) {
				sinfo.si_addr = mctx64.es.dar;
				/* First check in srr1 and then in dsisr */
				if (mctx64.ss.srr1 & (1 << (31 - DSISR_PROT_BIT)))
					sinfo.si_code = SEGV_ACCERR;
				else if (mctx64.es.dsisr & (1 << (31 - DSISR_PROT_BIT)))
					sinfo.si_code = SEGV_ACCERR;
				else
					sinfo.si_code = SEGV_MAPERR;
			} else {
				sinfo.si_addr = CAST_USER_ADDR_T(mctx.es.dar);
				/* First check in srr1 and then in dsisr */
				if (mctx.ss.srr1 & (1 << (31 - DSISR_PROT_BIT)))
					sinfo.si_code = SEGV_ACCERR;
				else if (mctx.es.dsisr & (1 << (31 - DSISR_PROT_BIT)))
					sinfo.si_code = SEGV_ACCERR;
				else
					sinfo.si_code = SEGV_MAPERR;
			}
			break;
		default:
		{
			int status_and_exitcode;

			/*
			 * All other signals need to fill out a minimum set of
			 * information for the siginfo structure passed into
			 * the signal handler, if SA_SIGINFO was specified.
			 *
			 * p->si_status actually contains both the status and
			 * the exit code; we save it off in its own variable
			 * for later breakdown.
			 */
			proc_lock(p);
			sinfo.si_pid = p->si_pid;
			p->si_pid = 0;
			status_and_exitcode = p->si_status;
			p->si_status = 0;
			sinfo.si_uid = p->si_uid;
			p->si_uid = 0;
			sinfo.si_code = p->si_code;
			p->si_code = 0;
			proc_unlock(p);
			if (sinfo.si_code == CLD_EXITED) {
				if (WIFEXITED(status_and_exitcode)) 
					sinfo.si_code = CLD_EXITED;
				else if (WIFSIGNALED(status_and_exitcode)) {
					if (WCOREDUMP(status_and_exitcode)) {
						sinfo.si_code = CLD_DUMPED;
						status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
					} else {
						sinfo.si_code = CLD_KILLED;
						status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
					}
				}
			}
			/*
			 * The recorded status contains the exit code and the
			 * signal information, but the information to be passed
			 * in the siginfo to the handler is supposed to only
			 * contain the status, so we have to shift it out.
			 */
			sinfo.si_status = WEXITSTATUS(status_and_exitcode);
			break;
		}
	}


	/* copy info out to user space */
	if (IS_64BIT_PROCESS(p)) {

		/* XXX truncates catcher address to uintptr_t */
		DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo,
			void (*)(void), CAST_DOWN(sig_t, catcher));

		if (copyout(&uctx, p_uctx, sizeof(struct user_ucontext64)))
			goto bad;
		if (copyout(&sinfo, p_sinfo, sizeof(user_siginfo_t)))
			goto bad;
	} else {