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