+ switch (sig) {
+ case SIGILL:
+ switch (ut->uu_code) {
+ case EXC_I386_INVOP:
+ sinfo64.si_code = ILL_ILLOPC;
+ break;
+ default:
+ sinfo64.si_code = ILL_NOOP;
+ }
+ break;
+ case SIGFPE:
+#define FP_IE 0 /* Invalid operation */
+#define FP_DE 1 /* Denormalized operand */
+#define FP_ZE 2 /* Zero divide */
+#define FP_OE 3 /* overflow */
+#define FP_UE 4 /* underflow */
+#define FP_PE 5 /* precision */
+ if (ut->uu_code == EXC_I386_DIV) {
+ sinfo64.si_code = FPE_INTDIV;
+ }
+ else if (ut->uu_code == EXC_I386_INTO) {
+ sinfo64.si_code = FPE_INTOVF;
+ }
+ else if (ut->uu_subcode & (1 << FP_ZE)) {
+ sinfo64.si_code = FPE_FLTDIV;
+ } else if (ut->uu_subcode & (1 << FP_OE)) {
+ sinfo64.si_code = FPE_FLTOVF;
+ } else if (ut->uu_subcode & (1 << FP_UE)) {
+ sinfo64.si_code = FPE_FLTUND;
+ } else if (ut->uu_subcode & (1 << FP_PE)) {
+ sinfo64.si_code = FPE_FLTRES;
+ } else if (ut->uu_subcode & (1 << FP_IE)) {
+ sinfo64.si_code = FPE_FLTINV;
+ } else {
+ sinfo64.si_code = FPE_NOOP;
+ }
+ break;
+ case SIGBUS:
+ sinfo64.si_code = BUS_ADRERR;
+ sinfo64.si_addr = ua_cr2;
+ break;
+ case SIGTRAP:
+ sinfo64.si_code = TRAP_BRKPT;
+ break;
+ case SIGSEGV:
+ sinfo64.si_addr = ua_cr2;
+
+ switch (ut->uu_code) {
+ case EXC_I386_GPFLT:
+ /* CR2 is meaningless after GP fault */
+ /* XXX namespace clash! */
+ sinfo64.si_addr = 0ULL;
+ sinfo64.si_code = 0;
+ break;
+ case KERN_PROTECTION_FAILURE:
+ sinfo64.si_code = SEGV_ACCERR;
+ break;
+ case KERN_INVALID_ADDRESS:
+ sinfo64.si_code = SEGV_MAPERR;
+ break;
+ default:
+ sinfo64.si_code = FPE_NOOP;
+ }
+ 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);
+ sinfo64.si_pid = p->si_pid;
+ p->si_pid =0;
+ status_and_exitcode = p->si_status;
+ p->si_status = 0;
+ sinfo64.si_uid = p->si_uid;
+ p->si_uid =0;
+ sinfo64.si_code = p->si_code;
+ p->si_code = 0;
+ proc_unlock(p);
+ if (sinfo64.si_code == CLD_EXITED) {
+ if (WIFEXITED(status_and_exitcode))
+ sinfo64.si_code = CLD_EXITED;
+ else if (WIFSIGNALED(status_and_exitcode)) {
+ if (WCOREDUMP(status_and_exitcode)) {
+ sinfo64.si_code = CLD_DUMPED;
+ status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
+ } else {
+ sinfo64.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.
+ */
+ sinfo64.si_status = (WEXITSTATUS(status_and_exitcode) & 0x00FFFFFF) | (((uint32_t)(p->p_xhighbits) << 24) & 0xFF000000);
+ p->p_xhighbits = 0;
+ break;
+ }
+ }
+ if (proc_is64bit(p)) {
+ user64_siginfo_t sinfo64_user64;
+
+ bzero((caddr_t)&sinfo64_user64, sizeof(sinfo64_user64));
+
+ siginfo_user_to_user64_x86(&sinfo64,&sinfo64_user64);
+
+#if CONFIG_DTRACE
+ bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
+
+ ut->t_dtrace_siginfo.si_signo = sinfo64.si_signo;
+ ut->t_dtrace_siginfo.si_code = sinfo64.si_code;
+ ut->t_dtrace_siginfo.si_pid = sinfo64.si_pid;
+ ut->t_dtrace_siginfo.si_uid = sinfo64.si_uid;
+ ut->t_dtrace_siginfo.si_status = sinfo64.si_status;
+ /* XXX truncates faulting address to void * on K32 */
+ ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo64.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;
+ }