#include <mach/mach_types.h>
#include <mach/exception_types.h>
#include <sys/param.h>
#include <sys/proc_internal.h>
#include <sys/user.h>
#include <sys/ucontext.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
#include <sys/ux_exception.h>
#include <ppc/signal.h>
#include <sys/signalvar.h>
#include <sys/kdebug.h>
#include <sys/wait.h>
#include <kern/thread.h>
#include <mach/ppc/thread_status.h>
#include <ppc/proc_reg.h>
#include <sys/sdt.h>
extern kern_return_t thread_getstatus(register thread_t act, int flavor,
thread_state_t tstate, mach_msg_type_number_t *count);
extern unsigned int get_msr_exportmask(void);
extern kern_return_t thread_setstatus(thread_t thread, int flavor,
thread_state_t tstate, mach_msg_type_number_t count);
extern void ppc_checkthreadstate(void *, int);
extern struct savearea_vec *find_user_vec_curr(void);
extern int thread_enable_fpe(thread_t act, int onoff);
#define C_32_REDZONE_LEN 224
#define C_32_STK_ALIGN 16
#define C_32_PARAMSAVE_LEN 64
#define C_32_LINKAGE_LEN 48
#define C_64_REDZONE_LEN 320
#define C_64_STK_ALIGN 32
#define C_64_PARAMSAVE_LEN 64
#define C_64_LINKAGE_LEN 48
#define TRUNC_DOWN32(a,b,c) ((((uint32_t)a)-(b)) & ((uint32_t)(-(c))))
#define TRUNC_DOWN64(a,b,c) ((((uint64_t)a)-(b)) & ((uint64_t)(-(c))))
#define UC_TRAD 1
#define UC_TRAD_VEC 6
#define UC_TRAD64 20
#define UC_TRAD64_VEC 25
#define UC_FLAVOR 30
#define UC_FLAVOR_VEC 35
#define UC_FLAVOR64 40
#define UC_FLAVOR64_VEC 45
#define UC_DUAL 50
#define UC_DUAL_VEC 55
#define UC_SET_ALT_STACK 0x40000000
#define UC_RESET_ALT_STACK 0x80000000
#define UC_FLAVOR_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
#define UC_FLAVOR_VEC_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
#define UC_FLAVOR64_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
#define UC_FLAVOR64_VEC_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
static void
ucontext_32to64(struct ucontext64 *in, struct user_ucontext64 *out)
{
out->uc_onstack = in->uc_onstack;
out->uc_sigmask = in->uc_sigmask;
out->uc_stack.ss_sp = CAST_USER_ADDR_T(in->uc_stack.ss_sp);
out->uc_stack.ss_size = in->uc_stack.ss_size;
out->uc_stack.ss_flags = in->uc_stack.ss_flags;
out->uc_link = CAST_USER_ADDR_T(in->uc_link);
out->uc_mcsize = in->uc_mcsize;
out->uc_mcontext64 = CAST_USER_ADDR_T(in->uc_mcontext64);
}
static void
ucontext_64to32(struct user_ucontext64 *in, struct ucontext64 *out)
{
out->uc_onstack = in->uc_onstack;
out->uc_sigmask = in->uc_sigmask;
out->uc_stack.ss_sp = CAST_DOWN(void *,in->uc_stack.ss_sp);
out->uc_stack.ss_size = in->uc_stack.ss_size;
out->uc_stack.ss_flags = in->uc_stack.ss_flags;
out->uc_link = CAST_DOWN(void *,in->uc_link);
out->uc_mcsize = in->uc_mcsize;
out->uc_mcontext64 = CAST_DOWN(void *,in->uc_mcontext64);
}
static void
siginfo_64to32(user_siginfo_t *in, 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 = CAST_DOWN(void *,in->si_addr);
out->si_value.sival_ptr = CAST_DOWN(void *,in->si_value.sival_ptr);
out->si_band = in->si_band;
out->__pad[0] = in->pad[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;
struct mcontext64 mctx64;
user_addr_t p_mctx64 = USER_ADDR_NULL;
struct user_ucontext64 uctx;
user_addr_t p_uctx;
user_siginfo_t sinfo;
user_addr_t p_sinfo;
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);
if (p->p_sigacts->ps_siginfo & sigmask(sig)) {
if (is_64signalregset()) {
if (IS_64BIT_PROCESS(p) ||
(p->p_sigacts->ps_64regset & sigmask(sig))) {
ctx32 = 0;
infostyle = UC_FLAVOR64;
} else {
dualcontext = 1;
infostyle = UC_DUAL;
}
} else {
infostyle = UC_FLAVOR;
}
} else {
if (is_64signalregset() || IS_64BIT_PROCESS(p)) {
ctx32 = 0;
infostyle = UC_TRAD64;
}
}
proc_unlock(p);
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;
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);
}
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);
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)) {
sp -= sizeof(struct user_ucontext64);
p_uctx = sp;
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 {
sp -= sizeof(struct ucontext64);
p_uctx = sp;
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;
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(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(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);
}
sinfo.si_code = BUS_ADRALN;
break;
case SIGSEGV:
if (ctx32 == 0) {
sinfo.si_addr = mctx64.es.dar;
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);
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;
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);
}
}
}
sinfo.si_status = WEXITSTATUS(status_and_exitcode);
break;
}
}
if (IS_64BIT_PROCESS(p)) {
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 {
struct ucontext64 uctx32;
siginfo_t sinfo32;
ucontext_64to32(&uctx, &uctx32);
siginfo_64to32(&sinfo,&sinfo32);
DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo32,
void (*)(void), CAST_DOWN(sig_t, catcher));
if (copyout(&uctx32, p_uctx, sizeof(struct ucontext64)))
goto bad;
if (copyout(&sinfo32, p_sinfo, sizeof(siginfo_t)))
goto bad;
}
if ((ctx32 == 0) || dualcontext) {
if (copyout(&mctx64, p_mctx64, (vec_used? UC_FLAVOR64_VEC_SIZE: UC_FLAVOR64_SIZE)))
goto bad;
}
if ((ctx32 == 1) || dualcontext) {
if (copyout(&mctx, p_mctx, uctx.uc_mcsize))
goto bad;
}
if(IS_64BIT_PROCESS(p)) {
mctx64.ss.r3 = catcher;
mctx64.ss.r4 = CAST_USER_ADDR_T(infostyle);
mctx64.ss.r5 = CAST_USER_ADDR_T(sig);
mctx64.ss.r6 = p_sinfo;
mctx64.ss.r7 = p_uctx;
mctx64.ss.srr0 = trampact;
mctx64.ss.srr1 = CAST_USER_ADDR_T(get_msr_exportmask());
mctx64.ss.r1 = sp;
state_count = PPC_THREAD_STATE64_COUNT;
if ((kretn = thread_setstatus(th_act, PPC_THREAD_STATE64, (void *)&mctx64.ss, state_count)) != KERN_SUCCESS) {
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.srr0 = CAST_DOWN(unsigned long,trampact);
mctx.ss.srr1 = get_msr_exportmask();
mctx.ss.r1 = CAST_DOWN(unsigned long,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);
}
}
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;
proc_unlock(p);
psignal_locked(p, SIGILL);
proc_lock(p);
return;
}
int
sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
{
struct user_ucontext64 uctx;
char mactx[sizeof(struct mcontext64)];
struct mcontext *p_mctx;
struct mcontext64 *p_64mctx;
int error;
thread_t th_act;
struct sigacts *ps = p->p_sigacts;
sigset_t mask;
user_addr_t action;
unsigned long state_count;
unsigned int state_flavor;
struct uthread * ut;
int vec_used = 0;
void *tsptr, *fptr, *vptr;
int infostyle = uap->infostyle;
th_act = current_thread();
ut = (struct uthread *)get_bsdthread_info(th_act);
if (infostyle == UC_SET_ALT_STACK) {
ut->uu_sigstk.ss_flags |= SA_ONSTACK;
return (0);
} else if ((unsigned int)infostyle == UC_RESET_ALT_STACK) {
ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
return (0);
}
if (IS_64BIT_PROCESS(p)) {
error = copyin(uap->uctx, &uctx, sizeof(struct user_ucontext64));
if (error)
return(error);
} else {
struct ucontext64 uctx32;
error = copyin(uap->uctx, &uctx32, sizeof(struct ucontext));
if (error)
return(error);
ucontext_32to64(&uctx32, &uctx);
}
switch (uctx.uc_mcsize) {
case UC_FLAVOR64_VEC_SIZE:
case UC_FLAVOR64_SIZE:
case UC_FLAVOR_VEC_SIZE:
case UC_FLAVOR_SIZE:
break;
default:
return(EINVAL);
}
error = copyin(uctx.uc_mcontext64, mactx, uctx.uc_mcsize);
if (error)
return(error);
if ((uctx.uc_onstack & 01))
ut->uu_sigstk.ss_flags |= SA_ONSTACK;
else
ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
ut->uu_sigmask = uctx.uc_sigmask & ~sigcantmask;
if (ut->uu_siglist & ~ut->uu_sigmask)
signal_setast(current_thread());
vec_used = 0;
switch (infostyle) {
case UC_FLAVOR64_VEC:
case UC_TRAD64_VEC:
vec_used = 1;
case UC_TRAD64:
case UC_FLAVOR64: {
p_64mctx = (struct mcontext64 *)mactx;
tsptr = (void *)&p_64mctx->ss;
fptr = (void *)&p_64mctx->fs;
vptr = (void *)&p_64mctx->vs;
state_flavor = PPC_THREAD_STATE64;
state_count = PPC_THREAD_STATE64_COUNT;
}
break;
case UC_FLAVOR_VEC :
case UC_TRAD_VEC :
vec_used = 1;
case UC_FLAVOR :
case UC_TRAD :
default: {
p_mctx = (struct mcontext *)mactx;
tsptr = (void *)&p_mctx->ss;
fptr = (void *)&p_mctx->fs;
vptr = (void *)&p_mctx->vs;
state_flavor = PPC_THREAD_STATE;
state_count = PPC_THREAD_STATE_COUNT;
}
break;
}
(void)ppc_checkthreadstate(tsptr, state_flavor);
if (thread_setstatus(th_act, state_flavor, tsptr, state_count) != KERN_SUCCESS) {
return(EINVAL);
}
state_count = PPC_FLOAT_STATE_COUNT;
if (thread_setstatus(th_act, PPC_FLOAT_STATE, fptr, state_count) != KERN_SUCCESS) {
return(EINVAL);
}
mask = sigmask(SIGFPE);
if (((ut->uu_sigmask & mask) == 0) && (p->p_sigcatch & mask) && ((p->p_sigignore & mask) == 0)) {
action = ps->ps_sigact[SIGFPE];
if((action != SIG_DFL) && (action != SIG_IGN)) {
thread_enable_fpe(th_act, 1);
}
}
if (vec_used) {
state_count = PPC_VECTOR_STATE_COUNT;
if (thread_setstatus(th_act, PPC_VECTOR_STATE, vptr, state_count) != KERN_SUCCESS) {
return(EINVAL);
}
}
return (EJUSTRETURN);
}
boolean_t
machine_exception(
int exception,
mach_exception_code_t code,
__unused mach_exception_subcode_t subcode,
int *unix_signal,
mach_exception_code_t *unix_code)
{
switch(exception) {
case EXC_BAD_INSTRUCTION:
*unix_signal = SIGILL;
*unix_code = code;
break;
case EXC_ARITHMETIC:
*unix_signal = SIGFPE;
*unix_code = code;
break;
case EXC_SOFTWARE:
if (code == EXC_PPC_TRAP) {
*unix_signal = SIGTRAP;
*unix_code = code;
break;
} else
return(FALSE);
default:
return(FALSE);
}
return(TRUE);
}