Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
/*
 * Send an interrupt to process.
 *
 */
void
sendsig(
	struct proc * p,
	user_addr_t catcher,
	int sig,
	int mask,
	__unused uint32_t code
)
{
	union {
		struct ts32 {
			arm_thread_state_t ss;
		} ts32;
#if defined(__arm64__)
		struct ts64 {
			arm_thread_state64_t ss;
		} ts64;
#endif
	} ts;
	union { 
		struct user_sigframe32 uf32;
#if defined(__arm64__)
		struct user_sigframe64 uf64;
#endif
	} user_frame;

	user_siginfo_t sinfo;
	user_addr_t 	sp = 0, trampact;
	struct sigacts *ps = p->p_sigacts;
	int             oonstack, infostyle;
	thread_t        th_act;
	struct uthread *ut;
	user_size_t	stack_size = 0;
	user_addr_t     p_uctx, token_uctx;
	kern_return_t   kr;

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

	bzero(&ts, sizeof(ts));
	bzero(&user_frame, sizeof(user_frame));

	if (p->p_sigacts->ps_siginfo & sigmask(sig))
		infostyle = UC_FLAVOR;
	else
		infostyle = UC_TRAD;

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

	/*
	 * Get sundry thread state.
	 */
	if (proc_is64bit_data(p)) {
#ifdef __arm64__
		if (sendsig_get_state64(th_act, &ts.ts64.ss, &user_frame.uf64.mctx) != 0) {
			goto bad2;
		}
#else
	panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
	} else {
		if (sendsig_get_state32(th_act, &ts.ts32.ss, &user_frame.uf32.mctx) != 0) {
			goto bad2;
		}
	}

	/*
	 * Figure out where our new stack lives.
	 */
	if ((ps->ps_flags & SAS_ALTSTACK) && !oonstack &&
	    (ps->ps_sigonstack & sigmask(sig))) {
		sp = ps->ps_sigstk.ss_sp;
		sp += ps->ps_sigstk.ss_size;
		stack_size = ps->ps_sigstk.ss_size;
		ps->ps_sigstk.ss_flags |= SA_ONSTACK;
	} else {
		/*
		 * Get stack pointer, and allocate enough space
		 * for signal handler data.
		 */
		if (proc_is64bit_data(p)) {
#if defined(__arm64__)
			sp = CAST_USER_ADDR_T(ts.ts64.ss.sp);
			sp = (sp - sizeof(user_frame.uf64) - C_64_REDZONE_LEN) & ~0xf; /* Make sure to align to 16 bytes and respect red zone */
#else
			panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
		} else {
			sp = CAST_USER_ADDR_T(ts.ts32.ss.sp);
			sp -= sizeof(user_frame.uf32);
#if defined(__arm__) && (__BIGGEST_ALIGNMENT__ > 4)
			sp &= ~0xf; /* Make sure to align to 16 bytes for armv7k */
#endif
		}
	}

	proc_unlock(p);

	/*
	 * Fill in ucontext (points to mcontext, i.e. thread states).
	 */
	if (proc_is64bit_data(p)) {
#if defined(__arm64__)
		sendsig_fill_uctx64(&user_frame.uf64.uctx, oonstack, mask, sp, (user64_size_t)stack_size,
				(user64_addr_t)&((struct user_sigframe64*)sp)->mctx);
#else
		panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
	} else {
		sendsig_fill_uctx32(&user_frame.uf32.uctx, oonstack, mask, sp, (user32_size_t)stack_size, 
				(user32_addr_t)&((struct user_sigframe32*)sp)->mctx);
	}

	/*
	 * Setup siginfo.
	 */
	bzero((caddr_t) & sinfo, sizeof(sinfo));
	sinfo.si_signo = sig;

	if (proc_is64bit_data(p)) {
#if defined(__arm64__)
		sinfo.si_addr = ts.ts64.ss.pc;
		sinfo.pad[0] = ts.ts64.ss.sp;
#else
		panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
	} else {
		sinfo.si_addr = ts.ts32.ss.pc;
		sinfo.pad[0] = ts.ts32.ss.sp;
	}

	switch (sig) {
	case SIGILL:
#ifdef	BER_XXX
		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;
#else
		sinfo.si_code = ILL_ILLTRP;
#endif
		break;

	case SIGFPE:
		break;

	case SIGBUS:
		if (proc_is64bit_data(p)) {
#if defined(__arm64__)
			sinfo.si_addr = user_frame.uf64.mctx.es.far;
#else
			panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
		} else {
			sinfo.si_addr = user_frame.uf32.mctx.es.far;
		}

		sinfo.si_code = BUS_ADRALN;
		break;

	case SIGSEGV:
		if (proc_is64bit_data(p)) {
#if defined(__arm64__)
			sinfo.si_addr = user_frame.uf64.mctx.es.far;
#else
			panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
		} else {
			sinfo.si_addr = user_frame.uf32.mctx.es.far;
		}

#ifdef	BER_XXX
		/* 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;
#else
		sinfo.si_code = SEGV_ACCERR;
#endif
		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) & 0x00FFFFFF) | (((uint32_t)(p->p_xhighbits) << 24) & 0xFF000000);
		p->p_xhighbits = 0;
		break;
	}
	}

#if CONFIG_DTRACE	
	sendsig_do_dtrace(ut, &sinfo, sig, catcher);
#endif /* CONFIG_DTRACE */

	/* 
	 * Copy signal-handling frame out to user space, set thread state.
	 */
	if (proc_is64bit_data(p)) {
#if defined(__arm64__)
		user64_addr_t token;

		/*
		 * mctx filled in when we get state.  uctx filled in by 
		 * sendsig_fill_uctx64(). We fill in the sinfo now.
		 */
		siginfo_user_to_user64(&sinfo, &user_frame.uf64.sinfo);

		p_uctx = (user_addr_t)&((struct user_sigframe64*)sp)->uctx;
		/*
		 * Generate the validation token for sigreturn
		 */
		token_uctx = p_uctx;
		kr = machine_thread_siguctx_pointer_convert_to_user(th_act, &token_uctx);
		assert(kr == KERN_SUCCESS);
		token = (user64_addr_t)token_uctx ^ (user64_addr_t)ps->ps_sigreturn_token;

		if (copyout(&user_frame.uf64, sp, sizeof(user_frame.uf64)) != 0) {
			goto bad; 
		} 

		if (sendsig_set_thread_state64(&ts.ts64.ss,
			catcher, infostyle, sig, (user64_addr_t)&((struct user_sigframe64*)sp)->sinfo,
			(user64_addr_t)p_uctx, token, trampact, sp, th_act) != KERN_SUCCESS)
			goto bad;

#else
	panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
	} else {
		user32_addr_t token;

		/*
		 * mctx filled in when we get state.  uctx filled in by 
		 * sendsig_fill_uctx32(). We fill in the sinfo, *pointer*
		 * to uctx and token now.
		 */
		siginfo_user_to_user32(&sinfo, &user_frame.uf32.sinfo);

		p_uctx = (user_addr_t)&((struct user_sigframe32*)sp)->uctx;
		/*
		 * Generate the validation token for sigreturn
		 */
		token_uctx = (user_addr_t)p_uctx;
		kr = machine_thread_siguctx_pointer_convert_to_user(th_act, &token_uctx);
		assert(kr == KERN_SUCCESS);
		token = (user32_addr_t)token_uctx ^ (user32_addr_t)ps->ps_sigreturn_token;

		user_frame.uf32.puctx = (user32_addr_t)p_uctx;
		user_frame.uf32.token = token;

		if (copyout(&user_frame.uf32, sp, sizeof(user_frame.uf32)) != 0) {
			goto bad; 
		} 

		if (sendsig_set_thread_state32(&ts.ts32.ss,
			CAST_DOWN_EXPLICIT(user32_addr_t, catcher), infostyle, sig, (user32_addr_t)&((struct user_sigframe32*)sp)->sinfo,
			CAST_DOWN_EXPLICIT(user32_addr_t, trampact), CAST_DOWN_EXPLICIT(user32_addr_t, sp), th_act) != KERN_SUCCESS)
			goto bad;
	}

	proc_lock(p);
	return;

bad:
	proc_lock(p);
bad2:
	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);
}
Ejemplo n.º 3
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;
}