+ switch (sig) {
+ case SIGILL:
+ switch (ut->uu_code) {
+ case EXC_I386_INVOP:
+ sinfo64.si_code = ILL_ILLOPC;
+ break;
+ default:
+ printf("unknown SIGILL code %ld\n", (long) ut->uu_code);
+ 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_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 {
+ printf("unknown SIGFPE code %ld, subcode %lx\n",
+ (long) ut->uu_code, (long) ut->uu_subcode);
+ 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:
+ printf("unknown SIGSEGV code %ld\n", (long) ut->uu_code);
+ 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);
+ break;
+ }
+ }
+ if (proc_is64bit(p)) {
+
+ /* XXX truncates catcher address to uintptr_t */
+ DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo64,
+ void (*)(void), CAST_DOWN(sig_t, ua_catcher));
+
+ if (copyout((caddr_t)&sinfo64, ua_sip, sizeof (sinfo64)))
+ goto bad;
+
+ flavor = x86_THREAD_STATE64;
+ state_count = x86_THREAD_STATE64_COUNT;
+ state = (void *)&mctx.mctx64.ss;
+ } else {
+ x86_thread_state32_t *tstate32;
+ siginfo_t sinfo32;
+
+ bzero((caddr_t)&sinfo32, sizeof(siginfo_t));
+
+ sinfo32.si_signo = sinfo64.si_signo;
+ sinfo32.si_code = sinfo64.si_code;
+ sinfo32.si_pid = sinfo64.si_pid;
+ sinfo32.si_uid = sinfo64.si_uid;
+ sinfo32.si_status = sinfo64.si_status;
+ sinfo32.si_addr = CAST_DOWN(void *, sinfo64.si_addr);
+ sinfo32.__pad[0] = sinfo64.pad[0];
+
+ DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo32,
+ void (*)(void), CAST_DOWN(sig_t, ua_catcher));