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; }
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; }
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 {