#include <sys/wait.h>
#include <mach/thread_act.h> /* for thread_abort_safely */
#include <mach/thread_status.h>
-#include <i386/machine_routines.h>
#include <i386/eflags.h>
#include <i386/psl.h>
+#include <i386/machine_routines.h>
#include <i386/seg.h>
#include <sys/kdebug.h>
#include <sys/sdt.h>
+
+
/* Forward: */
extern boolean_t machine_exception(int, mach_exception_code_t,
mach_exception_subcode_t, int *, mach_exception_subcode_t *);
* to the user specified pc, psl.
*/
struct sigframe32 {
- int retaddr;
- sig_t catcher;
- int sigstyle;
- int sig;
- siginfo_t * sinfo;
- struct ucontext * uctx;
+ int retaddr;
+ user32_addr_t catcher; /* sig_t */
+ int sigstyle;
+ int sig;
+ user32_addr_t sinfo; /* siginfo32_t* */
+ user32_addr_t uctx; /* struct ucontext32 */
};
+/*
+ * NOTE: Source and target may *NOT* overlap!
+ */
+static void
+siginfo_user_to_user32(user_siginfo_t *in, user32_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_EXPLICIT(user32_addr_t,in->si_addr);
+ /* following cast works for sival_int because of padding */
+ out->si_value.sival_ptr = CAST_DOWN_EXPLICIT(user32_addr_t,in->si_value.sival_ptr);
+ out->si_band = in->si_band; /* range reduction */
+ out->__pad[0] = in->pad[0]; /* mcontext.ss.r1 */
+}
+static void
+siginfo_user_to_user64(user_siginfo_t *in, user64_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 = in->si_addr;
+ out->si_value.sival_ptr = in->si_value.sival_ptr;
+ out->si_band = in->si_band; /* range reduction */
+ out->__pad[0] = in->pad[0]; /* mcontext.ss.r1 */
+}
void
-sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_long code)
+sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused uint32_t code)
{
union {
struct mcontext32 mctx32;
struct sigacts *ps = p->p_sigacts;
int oonstack, flavor;
+ user_addr_t trampact;
+ int sigonstack;
void * state;
mach_msg_type_number_t state_count;
infostyle = UC_FLAVOR;
oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;
+ trampact = ps->ps_trampact[sig];
+ sigonstack = (ps->ps_sigonstack & sigmask(sig));
/*
* init siginfo
*/
proc_unlock(p);
- bzero((caddr_t)&sinfo64, sizeof(user_siginfo_t));
+ bzero((caddr_t)&sinfo64, sizeof(sinfo64));
sinfo64.si_signo = sig;
/* figure out where our new stack lives */
if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
- (ps->ps_sigonstack & sigmask(sig))) {
+ (sigonstack)) {
ua_sp = ut->uu_sigstk.ss_sp;
stack_size = ut->uu_sigstk.ss_size;
ua_sp += stack_size;
ua_sp -= sizeof (struct user_ucontext64);
ua_uctxp = ua_sp; // someone tramples the first word!
- ua_sp -= sizeof (user_siginfo_t);
+ ua_sp -= sizeof (user64_siginfo_t);
ua_sip = ua_sp;
ua_sp -= sizeof (struct mcontext64);
sinfo64.pad[0] = tstate64->rsp;
sinfo64.si_addr = tstate64->rip;
- tstate64->rip = ps->ps_trampact[sig];
+ tstate64->rip = trampact;
tstate64->rsp = ua_fp;
tstate64->rflags = get_eflags_exportmask();
/*
} else {
x86_thread_state32_t *tstate32;
- struct ucontext uctx32;
+ struct user_ucontext32 uctx32;
struct sigframe32 frame32;
flavor = x86_THREAD_STATE32;
/* figure out where our new stack lives */
if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
- (ps->ps_sigonstack & sigmask(sig))) {
+ (sigonstack)) {
ua_sp = ut->uu_sigstk.ss_sp;
stack_size = ut->uu_sigstk.ss_size;
ua_sp += stack_size;
}
ua_cr2 = mctx.mctx32.es.faultvaddr;
- ua_sp -= sizeof (struct ucontext);
+ ua_sp -= sizeof (struct user_ucontext32);
ua_uctxp = ua_sp; // someone tramples the first word!
- ua_sp -= sizeof (siginfo_t);
+ ua_sp -= sizeof (user32_siginfo_t);
ua_sip = ua_sp;
ua_sp -= sizeof (struct mcontext32);
frame32.retaddr = -1;
frame32.sigstyle = infostyle;
frame32.sig = sig;
- frame32.catcher = CAST_DOWN(sig_t, ua_catcher);
- frame32.sinfo = CAST_DOWN(siginfo_t *, ua_sip);
- frame32.uctx = CAST_DOWN(struct ucontext *, ua_uctxp);
+ frame32.catcher = CAST_DOWN_EXPLICIT(user32_addr_t, ua_catcher);
+ frame32.sinfo = CAST_DOWN_EXPLICIT(user32_addr_t, ua_sip);
+ frame32.uctx = CAST_DOWN_EXPLICIT(user32_addr_t, ua_uctxp);
if (copyout((caddr_t)&frame32, ua_fp, sizeof (frame32)))
goto bad;
uctx32.uc_onstack = oonstack;
uctx32.uc_sigmask = mask;
- uctx32.uc_stack.ss_sp = CAST_DOWN(char *, ua_fp);
+ uctx32.uc_stack.ss_sp = CAST_DOWN_EXPLICIT(user32_addr_t, ua_fp);
uctx32.uc_stack.ss_size = stack_size;
if (oonstack)
uctx32.uc_mcsize = sizeof(struct mcontext32);
- uctx32.uc_mcontext = CAST_DOWN(_STRUCT_MCONTEXT32 *, ua_mctxp);
+ uctx32.uc_mcontext = CAST_DOWN_EXPLICIT(user32_addr_t, ua_mctxp);
if (copyout((caddr_t)&uctx32, ua_uctxp, sizeof (uctx32)))
goto bad;
sinfo64.si_code = ILL_ILLOPC;
break;
default:
- printf("unknown SIGILL code %ld\n", (long) ut->uu_code);
sinfo64.si_code = ILL_NOOP;
}
break;
#define FP_OE 3 /* overflow */
#define FP_UE 4 /* underflow */
#define FP_PE 5 /* precision */
- if (ut->uu_subcode & (1 << FP_ZE)) {
+ 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_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;
sinfo64.si_code = SEGV_MAPERR;
break;
default:
- printf("unknown SIGSEGV code %ld\n", (long) ut->uu_code);
sinfo64.si_code = FPE_NOOP;
}
break;
}
}
if (proc_is64bit(p)) {
+ user64_siginfo_t sinfo64_user64;
+
+ bzero((caddr_t)&sinfo64_user64, sizeof(sinfo64_user64));
+
+ siginfo_user_to_user64(&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;
+ }
/* XXX truncates catcher address to uintptr_t */
- DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo64,
+ DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
void (*)(void), CAST_DOWN(sig_t, ua_catcher));
+#endif /* CONFIG_DTRACE */
- if (copyout((caddr_t)&sinfo64, ua_sip, sizeof (sinfo64)))
- goto bad;
+ if (copyout((caddr_t)&sinfo64_user64, ua_sip, sizeof (sinfo64_user64)))
+ 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;
+ x86_thread_state32_t *tstate32;
+ user32_siginfo_t sinfo32;
+
+ bzero((caddr_t)&sinfo32, sizeof(sinfo32));
- bzero((caddr_t)&sinfo32, sizeof(siginfo_t));
+ siginfo_user_to_user32(&sinfo64,&sinfo32);
- 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];
+#if CONFIG_DTRACE
+ bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
- DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo32,
+ ut->t_dtrace_siginfo.si_signo = sinfo32.si_signo;
+ ut->t_dtrace_siginfo.si_code = sinfo32.si_code;
+ ut->t_dtrace_siginfo.si_pid = sinfo32.si_pid;
+ ut->t_dtrace_siginfo.si_uid = sinfo32.si_uid;
+ ut->t_dtrace_siginfo.si_status = sinfo32.si_status;
+ ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo32.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;
+ }
+
+ DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
void (*)(void), CAST_DOWN(sig_t, ua_catcher));
+#endif /* CONFIG_DTRACE */
- if (copyout((caddr_t)&sinfo32, ua_sip, sizeof (sinfo32)))
- goto bad;
+ if (copyout((caddr_t)&sinfo32, ua_sip, sizeof (sinfo32)))
+ goto bad;
tstate32 = &mctx.mctx32.ss;
- tstate32->eip = CAST_DOWN(unsigned int, ps->ps_trampact[sig]);
- tstate32->esp = CAST_DOWN(unsigned int, ua_fp);
-
+
+ tstate32->eip = CAST_DOWN_EXPLICIT(user32_addr_t, trampact);
+ tstate32->esp = CAST_DOWN_EXPLICIT(user32_addr_t, ua_fp);
+
tstate32->eflags = get_eflags_exportmask();
tstate32->cs = USER_CS;
goto bad;
ml_fp_setvalid(FALSE);
+
proc_lock(p);
return;
fs = (void *)&mctx.mctx64.fs;
} else {
- struct ucontext uctx32;
+ struct user_ucontext32 uctx32;
if ((error = copyin(uap->uctx, (void *)&uctx32, sizeof (uctx32))))
return(error);