* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-/* #pragma ident "@(#)systrace.c 1.5 06/03/24 SMI" */
+/* #pragma ident "@(#)systrace.c 1.6 06/09/19 SMI" */
#if !defined(__APPLE__)
#include <sys/dtrace.h>
#include <sys/conf.h>
#include <sys/user.h>
-#if defined (__ppc__) || defined (__ppc64__)
-#define SYSTRACE_ARTIFICIAL_FRAMES 3
-#define MACHTRACE_ARTIFICIAL_FRAMES 4
-#elif defined(__i386__) || defined (__x86_64__)
+#include <machine/pal_routines.h>
+
+#if defined(__i386__) || defined (__x86_64__)
#define SYSTRACE_ARTIFICIAL_FRAMES 2
#define MACHTRACE_ARTIFICIAL_FRAMES 3
#else
#define LOADABLE_SYSCALL(a) 0 /* Not pertinent to Darwin. */
#define LOADED_SYSCALL(a) 1 /* Not pertinent to Darwin. */
+extern lck_attr_t* dtrace_lck_attr;
+extern lck_grp_t* dtrace_lck_grp;
+static lck_mtx_t dtrace_systrace_lock; /* probe state lock */
+
systrace_sysent_t *systrace_sysent = NULL;
-void (*systrace_probe)(dtrace_id_t, uint64_t, uint64_t,
- uint64_t, uint64_t, uint64_t);
+void (*systrace_probe)(dtrace_id_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
+
+static uint64_t systrace_getarg(void *, dtrace_id_t, void *, int, int);
void
systrace_stub(dtrace_id_t id, uint64_t arg0, uint64_t arg1,
#endif
syscall_arg_t *ip = (syscall_arg_t *)uap;
-#if defined (__ppc__) || defined (__ppc64__)
- {
- savearea_t *regs = (savearea_t *)find_user_regs(current_thread());
-
- flavor = (((unsigned int)regs->save_r0) == 0)? 1: 0;
-
- if (flavor)
- code = regs->save_r3;
- else
- code = regs->save_r0;
- }
-#elif defined(__i386__) || defined (__x86_64__)
+#if defined(__i386__) || defined (__x86_64__)
#pragma unused(flavor)
{
+ pal_register_cache_state(current_thread(), VALID);
x86_saved_state_t *tagged_regs = (x86_saved_state_t *)find_user_regs(current_thread());
if (is_saved_state64(tagged_regs)) {
}
} else {
code = saved_state32(tagged_regs)->eax & I386_SYSCALL_NUMBER_MASK;
- /*
- * TODO: handle indirect system calls
- */
+
+ if (code == 0) {
+ vm_offset_t params = (vm_offset_t) (saved_state32(tagged_regs)->uesp + sizeof (int));
+ code = fuword(params);
+ }
}
}
#else
// Bounds "check" the value of code a la unix_syscall
sy = (code >= NUM_SYSENT) ? &systrace_sysent[63] : &systrace_sysent[code];
- if ((id = sy->stsy_entry) != DTRACE_IDNONE)
- (*systrace_probe)(id, *ip, *(ip+1), *(ip+2), *(ip+3), *(ip+4));
+ if ((id = sy->stsy_entry) != DTRACE_IDNONE) {
+ uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());
+ if (uthread)
+ uthread->t_dtrace_syscall_args = (void *)ip;
+
+ if (ip)
+ (*systrace_probe)(id, *ip, *(ip+1), *(ip+2), *(ip+3), *(ip+4));
+ else
+ (*systrace_probe)(id, 0, 0, 0, 0, 0);
+
+ if (uthread)
+ uthread->t_dtrace_syscall_args = (void *)0;
+ }
#if 0 /* XXX */
/*
rval = (*sy->stsy_underlying)(pp, uap, rv);
if ((id = sy->stsy_return) != DTRACE_IDNONE) {
- uint64_t munged_rv;
+ uint64_t munged_rv0, munged_rv1;
uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());
if (uthread)
* "Decode" rv for use in the call to dtrace_probe()
*/
if (rval == ERESTART) {
- munged_rv = -1LL; /* System call will be reissued in user mode. Make DTrace report a -1 return. */
+ munged_rv0 = -1LL; /* System call will be reissued in user mode. Make DTrace report a -1 return. */
+ munged_rv1 = -1LL;
} else if (rval != EJUSTRETURN) {
if (rval) {
- munged_rv = -1LL; /* Mimic what libc will do. */
+ munged_rv0 = -1LL; /* Mimic what libc will do. */
+ munged_rv1 = -1LL;
} else {
switch (sy->stsy_return_type) {
case _SYSCALL_RET_INT_T:
- munged_rv = rv[0];
+ munged_rv0 = rv[0];
+ munged_rv1 = rv[1];
break;
case _SYSCALL_RET_UINT_T:
- munged_rv = ((u_int)rv[0]);
+ munged_rv0 = ((u_int)rv[0]);
+ munged_rv1 = ((u_int)rv[1]);
break;
case _SYSCALL_RET_OFF_T:
- munged_rv = *(u_int64_t *)rv;
+ case _SYSCALL_RET_UINT64_T:
+ munged_rv0 = *(u_int64_t *)rv;
+ munged_rv1 = 0LL;
break;
case _SYSCALL_RET_ADDR_T:
case _SYSCALL_RET_SIZE_T:
case _SYSCALL_RET_SSIZE_T:
- munged_rv = *(user_addr_t *)rv;
+ munged_rv0 = *(user_addr_t *)rv;
+ munged_rv1 = 0LL;
break;
case _SYSCALL_RET_NONE:
- munged_rv = 0LL;
+ munged_rv0 = 0LL;
+ munged_rv1 = 0LL;
break;
default:
- munged_rv = 0LL;
+ munged_rv0 = 0LL;
+ munged_rv1 = 0LL;
break;
}
}
- } else
- munged_rv = 0LL;
+ } else {
+ munged_rv0 = 0LL;
+ munged_rv1 = 0LL;
+ }
- (*systrace_probe)(id, munged_rv, munged_rv, (uint64_t)rval, 0, 0);
+ /*
+ * <http://mail.opensolaris.org/pipermail/dtrace-discuss/2007-January/003276.html> says:
+ *
+ * "This is a bit of an historical artifact. At first, the syscall provider just
+ * had its return value in arg0, and the fbt and pid providers had their return
+ * values in arg1 (so that we could use arg0 for the offset of the return site).
+ *
+ * We inevitably started writing scripts where we wanted to see the return
+ * values from probes in all three providers, and we made this script easier
+ * to write by replicating the syscall return values in arg1 to match fbt and
+ * pid. We debated briefly about removing the return value from arg0, but
+ * decided that it would be less confusing to have the same data in two places
+ * than to have some non-helpful, non-intuitive value in arg0.
+ *
+ * This change was made 4/23/2003 according to the DTrace project's putback log."
+ */
+ (*systrace_probe)(id, munged_rv0, munged_rv0, munged_rv1, (uint64_t)rval, 0);
}
return (rval);
sy = (code >= NUM_SYSENT) ? &systrace_sysent[63] : &systrace_sysent[code];
if ((id = sy->stsy_return) != DTRACE_IDNONE) {
- uint64_t munged_rv;
+ uint64_t munged_rv0, munged_rv1;
uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());
if (uthread)
* "Decode" rv for use in the call to dtrace_probe()
*/
if (rval == ERESTART) {
- munged_rv = -1LL; /* System call will be reissued in user mode. Make DTrace report a -1 return. */
+ munged_rv0 = -1LL; /* System call will be reissued in user mode. Make DTrace report a -1 return. */
+ munged_rv1 = -1LL;
} else if (rval != EJUSTRETURN) {
if (rval) {
- munged_rv = -1LL; /* Mimic what libc will do. */
+ munged_rv0 = -1LL; /* Mimic what libc will do. */
+ munged_rv1 = -1LL;
} else {
switch (sy->stsy_return_type) {
case _SYSCALL_RET_INT_T:
- munged_rv = rv[0];
+ munged_rv0 = rv[0];
+ munged_rv1 = rv[1];
break;
case _SYSCALL_RET_UINT_T:
- munged_rv = ((u_int)rv[0]);
+ munged_rv0 = ((u_int)rv[0]);
+ munged_rv1 = ((u_int)rv[1]);
break;
case _SYSCALL_RET_OFF_T:
- munged_rv = *(u_int64_t *)rv;
+ case _SYSCALL_RET_UINT64_T:
+ munged_rv0 = *(u_int64_t *)rv;
+ munged_rv1 = 0LL;
break;
case _SYSCALL_RET_ADDR_T:
case _SYSCALL_RET_SIZE_T:
case _SYSCALL_RET_SSIZE_T:
- munged_rv = *(user_addr_t *)rv;
+ munged_rv0 = *(user_addr_t *)rv;
+ munged_rv1 = 0LL;
break;
case _SYSCALL_RET_NONE:
- munged_rv = 0LL;
+ munged_rv0 = 0LL;
+ munged_rv1 = 0LL;
break;
default:
- munged_rv = 0LL;
+ munged_rv0 = 0LL;
+ munged_rv1 = 0LL;
break;
}
}
- } else
- munged_rv = 0LL;
+ } else {
+ munged_rv0 = 0LL;
+ munged_rv1 = 0LL;
+ }
- (*systrace_probe)(id, munged_rv, munged_rv, (uint64_t)rval, 0, 0);
+ (*systrace_probe)(id, munged_rv0, munged_rv0, munged_rv1, (uint64_t)rval, 0);
}
}
#endif /* __APPLE__ */
static dev_info_t *systrace_devi;
static dtrace_provider_id_t systrace_id;
-#if defined(__APPLE__)
-#define systrace_init _systrace_init /* Avoid name clash with Darwin automagic conf symbol */
-#endif
+#if !defined (__APPLE__)
static void
systrace_init(struct sysent *actual, systrace_sysent_t **interposed)
{
#endif
s->stsy_underlying = a->sy_callc;
-#if defined(__APPLE__)
- s->stsy_return_type = a->sy_return_type;
+ }
+}
+#else
+#define systrace_init _systrace_init /* Avoid name clash with Darwin automagic conf symbol */
+static void
+systrace_init(struct sysent *actual, systrace_sysent_t **interposed)
+{
+
+ systrace_sysent_t *ssysent = *interposed; /* Avoid sysent shadow warning
+ from bsd/sys/sysent.h */
+ int i;
+
+ if (ssysent == NULL) {
+ *interposed = ssysent = kmem_zalloc(sizeof (systrace_sysent_t) *
+ NSYSCALL, KM_SLEEP);
+ }
+
+ for (i = 0; i < NSYSCALL; i++) {
+ struct sysent *a = &actual[i];
+ systrace_sysent_t *s = &ssysent[i];
+
+ if (LOADABLE_SYSCALL(a) && !LOADED_SYSCALL(a))
+ continue;
+
+ if (a->sy_callc == dtrace_systrace_syscall)
+ continue;
+
+#ifdef _SYSCALL32_IMPL
+ if (a->sy_callc == dtrace_systrace_syscall32)
+ continue;
#endif
+
+ s->stsy_underlying = a->sy_callc;
+ s->stsy_return_type = a->sy_return_type;
}
+ lck_mtx_init(&dtrace_systrace_lock, dtrace_lck_grp, dtrace_lck_attr);
}
+#endif /* __APPLE__ */
+
/*ARGSUSED*/
static void
systrace_provide(void *arg, const dtrace_probedesc_t *desc)
{
+#pragma unused(arg) /* __APPLE__ */
int i;
if (desc != NULL)
static void
systrace_destroy(void *arg, dtrace_id_t id, void *parg)
{
+#pragma unused(arg,id) /* __APPLE__ */
+
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
+#pragma unused(sysnum) /* __APPLE__ */
/*
* There's nothing to do here but assert that we have actually been
* disabled.
}
/*ARGSUSED*/
-static void
+static int
systrace_enable(void *arg, dtrace_id_t id, void *parg)
{
+#pragma unused(arg) /* __APPLE__ */
+
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
int enabled = (systrace_sysent[sysnum].stsy_entry != DTRACE_IDNONE ||
systrace_sysent[sysnum].stsy_return != DTRACE_IDNONE);
if (enabled) {
ASSERT(sysent[sysnum].sy_callc == dtrace_systrace_syscall);
- return;
+ return(0);
}
-
- (void) casptr(&sysent[sysnum].sy_callc,
- (void *)systrace_sysent[sysnum].stsy_underlying,
- (void *)dtrace_systrace_syscall);
#ifdef _SYSCALL32_IMPL
(void) casptr(&sysent32[sysnum].sy_callc,
(void *)systrace_sysent32[sysnum].stsy_underlying,
(void *)dtrace_systrace_syscall32);
#endif
+
+ lck_mtx_lock(&dtrace_systrace_lock);
+ if (sysent[sysnum].sy_callc == systrace_sysent[sysnum].stsy_underlying) {
+ vm_offset_t dss = (vm_offset_t)&dtrace_systrace_syscall;
+ ml_nofault_copy((vm_offset_t)&dss, (vm_offset_t)&sysent[sysnum].sy_callc, sizeof(vm_offset_t));
+ }
+ lck_mtx_unlock(&dtrace_systrace_lock);
+ return (0);
}
/*ARGSUSED*/
static void
systrace_disable(void *arg, dtrace_id_t id, void *parg)
{
+#pragma unused(arg,id) /* __APPLE__ */
+
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
int disable = (systrace_sysent[sysnum].stsy_entry == DTRACE_IDNONE ||
systrace_sysent[sysnum].stsy_return == DTRACE_IDNONE);
if (disable) {
- (void) casptr(&sysent[sysnum].sy_callc,
- (void *)dtrace_systrace_syscall,
- (void *)systrace_sysent[sysnum].stsy_underlying);
+ lck_mtx_lock(&dtrace_systrace_lock);
+ if (sysent[sysnum].sy_callc == dtrace_systrace_syscall)
+ ml_nofault_copy((vm_offset_t)&systrace_sysent[sysnum].stsy_underlying, (vm_offset_t)&sysent[sysnum].sy_callc, sizeof(systrace_sysent[sysnum].stsy_underlying));
+ lck_mtx_unlock(&dtrace_systrace_lock);
#ifdef _SYSCALL32_IMPL
(void) casptr(&sysent32[sysnum].sy_callc,
NULL,
NULL,
NULL,
- NULL,
+ systrace_getarg,
NULL,
systrace_destroy
};
return (DDI_FAILURE);
}
- systrace_probe = dtrace_probe;
+#if !defined(__APPLE__)
+ systrace_probe = (void (*)())dtrace_probe;
membar_enter();
if (ddi_create_minor_node(devi, "systrace", S_IFCHR, 0,
ddi_remove_minor_node(devi, NULL);
return (DDI_FAILURE);
}
+#else
+ systrace_probe = (void(*))&dtrace_probe;
+ membar_enter();
+
+ if (ddi_create_minor_node(devi, "systrace", S_IFCHR, 0,
+ DDI_PSEUDO, 0) == DDI_FAILURE ||
+ dtrace_register("syscall", &systrace_attr, DTRACE_PRIV_USER, NULL,
+ &systrace_pops, NULL, &systrace_id) != 0) {
+ systrace_probe = systrace_stub;
+ ddi_remove_minor_node(devi, NULL);
+ return (DDI_FAILURE);
+ }
+#endif /* __APPLE__ */
ddi_report_dev(devi);
systrace_devi = devi;
typedef void mach_munge_t(const void *, void *);
typedef struct {
- int mach_trap_arg_count;
- int (*mach_trap_function)(void);
-#if defined(__i386__)
- boolean_t mach_trap_stack;
-#else
- mach_munge_t *mach_trap_arg_munge32; /* system call arguments for 32-bit */
- mach_munge_t *mach_trap_arg_munge64; /* system call arguments for 64-bit */
+ int mach_trap_arg_count;
+ kern_return_t (*mach_trap_function)(void *);
+#if 0 /* no active architectures use mungers for mach traps */
+ mach_munge_t *mach_trap_arg_munge32; /* system call arguments for 32-bit */
+ mach_munge_t *mach_trap_arg_munge64; /* system call arguments for 64-bit */
#endif
-#if !MACH_ASSERT
- int mach_trap_unused;
-#else
- const char* mach_trap_name;
-#endif /* !MACH_ASSERT */
+#if MACH_ASSERT
+ const char* mach_trap_name;
+#endif /* MACH_ASSERT */
} mach_trap_t;
-#define MACH_TRAP_TABLE_COUNT 128
-
extern mach_trap_t mach_trap_table[];
extern int mach_trap_count;
-#define MACH_TRAP(name, foo, bar, baz) #name
-
-/* XXX From osfmk/kern/syscall_sw.c */
-static const char * mach_name_table[MACH_TRAP_TABLE_COUNT] = {
-/* 0 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 1 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 2 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 3 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 4 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 5 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 6 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 7 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 8 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 9 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 10 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 11 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 12 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 13 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 14 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 15 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 16 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 17 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 18 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 19 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 20 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 21 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 22 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 23 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 24 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 25 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 26 */ MACH_TRAP(mach_reply_port, 0, NULL, NULL),
-/* 27 */ MACH_TRAP(thread_self_trap, 0, NULL, NULL),
-/* 28 */ MACH_TRAP(task_self_trap, 0, NULL, NULL),
-/* 29 */ MACH_TRAP(host_self_trap, 0, NULL, NULL),
-/* 30 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 31 */ MACH_TRAP(mach_msg_trap, 7, munge_wwwwwww, munge_ddddddd),
-/* 32 */ MACH_TRAP(mach_msg_overwrite_trap, 8, munge_wwwwwwww, munge_dddddddd),
-/* 33 */ MACH_TRAP(semaphore_signal_trap, 1, munge_w, munge_d),
-/* 34 */ MACH_TRAP(semaphore_signal_all_trap, 1, munge_w, munge_d),
-/* 35 */ MACH_TRAP(semaphore_signal_thread_trap, 2, munge_ww, munge_dd),
-/* 36 */ MACH_TRAP(semaphore_wait_trap, 1, munge_w, munge_d),
-/* 37 */ MACH_TRAP(semaphore_wait_signal_trap, 2, munge_ww, munge_dd),
-/* 38 */ MACH_TRAP(semaphore_timedwait_trap, 3, munge_www, munge_ddd),
-/* 39 */ MACH_TRAP(semaphore_timedwait_signal_trap, 4, munge_wwww, munge_dddd),
-/* 40 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 41 */ MACH_TRAP(init_process, 0, NULL, NULL),
-/* 42 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 43 */ MACH_TRAP(map_fd, 5, munge_wwwww, munge_ddddd),
-/* 44 */ MACH_TRAP(task_name_for_pid, 3, munge_www, munge_ddd),
-/* 45 */ MACH_TRAP(task_for_pid, 3, munge_www, munge_ddd),
-/* 46 */ MACH_TRAP(pid_for_task, 2, munge_ww,munge_dd),
-/* 47 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 48 */ MACH_TRAP(macx_swapon, 4, munge_wwww, munge_dddd),
-/* 49 */ MACH_TRAP(macx_swapoff, 2, munge_ww, munge_dd),
-/* 50 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 51 */ MACH_TRAP(macx_triggers, 4, munge_wwww, munge_dddd),
-/* 52 */ MACH_TRAP(macx_backing_store_suspend, 1, munge_w, munge_d),
-/* 53 */ MACH_TRAP(macx_backing_store_recovery, 1, munge_w, munge_d),
-/* 54 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 55 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 56 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 57 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 58 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 59 */ MACH_TRAP(swtch_pri, 0, NULL, NULL),
-/* 60 */ MACH_TRAP(swtch, 0, NULL, NULL),
-/* 61 */ MACH_TRAP(thread_switch, 3, munge_www, munge_ddd),
-/* 62 */ MACH_TRAP(clock_sleep_trap, 5, munge_wwwww, munge_ddddd),
-/* 63 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* traps 64 - 95 reserved (debo) */
-/* 64 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 65 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 66 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 67 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 68 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 69 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 70 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 71 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 72 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 73 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 74 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 75 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 76 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 77 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 78 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 79 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 80 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 81 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 82 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 83 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 84 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 85 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 86 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 87 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 88 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 89 */ MACH_TRAP(mach_timebase_info_trap, 1, munge_w, munge_d),
-/* 90 */ MACH_TRAP(mach_wait_until_trap, 2, munge_l, munge_d),
-/* 91 */ MACH_TRAP(mk_timer_create_trap, 0, NULL, NULL),
-/* 92 */ MACH_TRAP(mk_timer_destroy_trap, 1, munge_w, munge_d),
-/* 93 */ MACH_TRAP(mk_timer_arm_trap, 3, munge_wl, munge_dd),
-/* 94 */ MACH_TRAP(mk_timer_cancel_trap, 2, munge_ww, munge_dd),
-/* 95 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* traps 64 - 95 reserved (debo) */
-/* 96 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 97 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 98 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 99 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* traps 100-107 reserved for iokit (esb) */
-/* 100 */ MACH_TRAP(iokit_user_client_trap, 8, munge_wwwwwwww, munge_dddddddd),
-/* 101 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 102 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 103 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 104 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 105 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 106 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 107 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* traps 108-127 unused */
-/* 108 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 109 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 110 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 111 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 112 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 113 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 114 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 115 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 116 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 117 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 118 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 119 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 120 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 121 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 122 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 123 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 124 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 125 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 126 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-/* 127 */ MACH_TRAP(kern_invalid, 0, NULL, NULL),
-};
+extern const char *mach_syscall_name_table[];
/* XXX From osfmk/i386/bsd_i386.c */
struct mach_call_args {
#error 1 << SYSTRACE_SHIFT must exceed number of Mach traps
#endif
-typedef systrace_sysent_t machtrace_sysent_t;
+typedef struct machtrace_sysent {
+ dtrace_id_t stsy_entry;
+ dtrace_id_t stsy_return;
+ kern_return_t (*stsy_underlying)(void *);
+ int32_t stsy_return_type;
+} machtrace_sysent_t;
static machtrace_sysent_t *machtrace_sysent = NULL;
void (*machtrace_probe)(dtrace_id_t, uint64_t, uint64_t,
uint64_t, uint64_t, uint64_t);
+static uint64_t machtrace_getarg(void *, dtrace_id_t, void *, int, int);
+
static dev_info_t *machtrace_devi;
static dtrace_provider_id_t machtrace_id;
syscall_arg_t *ip = (syscall_arg_t *)args;
mach_call_t mach_call;
-#if defined (__ppc__) || defined (__ppc64__)
- {
- savearea_t *regs = (savearea_t *)find_user_regs(current_thread());
-
- flavor = (((unsigned int)regs->save_r0) == 0)? 1: 0;
-
- if (flavor)
- code = -regs->save_r3;
- else
- code = -regs->save_r0;
- }
-#elif defined(__i386__) || defined (__x86_64__)
+#if defined(__i386__) || defined (__x86_64__)
#pragma unused(flavor)
{
+ pal_register_cache_state(current_thread(), VALID);
x86_saved_state_t *tagged_regs = (x86_saved_state_t *)find_user_regs(current_thread());
if (is_saved_state64(tagged_regs)) {
- code = -saved_state64(tagged_regs)->rax & SYSCALL_NUMBER_MASK;
+ code = saved_state64(tagged_regs)->rax & SYSCALL_NUMBER_MASK;
} else {
code = -saved_state32(tagged_regs)->eax;
}
sy = &machtrace_sysent[code];
- if ((id = sy->stsy_entry) != DTRACE_IDNONE)
+ if ((id = sy->stsy_entry) != DTRACE_IDNONE) {
+ uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());
+
+ if (uthread)
+ uthread->t_dtrace_syscall_args = (void *)ip;
+
(*machtrace_probe)(id, *ip, *(ip+1), *(ip+2), *(ip+3), *(ip+4));
+
+ if (uthread)
+ uthread->t_dtrace_syscall_args = (void *)0;
+ }
#if 0 /* XXX */
/*
if (LOADABLE_SYSCALL(a) && !LOADED_SYSCALL(a))
continue;
- if ((mach_call_t)(a->mach_trap_function) == (mach_call_t)(dtrace_machtrace_syscall))
+ if (a->mach_trap_function == (mach_call_t)(dtrace_machtrace_syscall))
continue;
s->stsy_underlying = a->mach_trap_function;
static void
machtrace_provide(void *arg, const dtrace_probedesc_t *desc)
{
+#pragma unused(arg) /* __APPLE__ */
+
int i;
if (desc != NULL)
continue;
if (dtrace_probe_lookup(machtrace_id, NULL,
- mach_name_table[i], "entry") != 0)
+ mach_syscall_name_table[i], "entry") != 0)
continue;
- (void) dtrace_probe_create(machtrace_id, NULL, mach_name_table[i],
+ (void) dtrace_probe_create(machtrace_id, NULL, mach_syscall_name_table[i],
"entry", MACHTRACE_ARTIFICIAL_FRAMES,
(void *)((uintptr_t)SYSTRACE_ENTRY(i)));
- (void) dtrace_probe_create(machtrace_id, NULL, mach_name_table[i],
+ (void) dtrace_probe_create(machtrace_id, NULL, mach_syscall_name_table[i],
"return", MACHTRACE_ARTIFICIAL_FRAMES,
(void *)((uintptr_t)SYSTRACE_RETURN(i)));
static void
machtrace_destroy(void *arg, dtrace_id_t id, void *parg)
{
+#pragma unused(arg,id) /* __APPLE__ */
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
+
+#pragma unused(sysnum) /* __APPLE__ */
/*
* There's nothing to do here but assert that we have actually been
}
/*ARGSUSED*/
-static void
+static int
machtrace_enable(void *arg, dtrace_id_t id, void *parg)
{
+#pragma unused(arg) /* __APPLE__ */
+
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
int enabled = (machtrace_sysent[sysnum].stsy_entry != DTRACE_IDNONE ||
machtrace_sysent[sysnum].stsy_return != DTRACE_IDNONE);
}
if (enabled) {
- ASSERT(sysent[sysnum].sy_callc == dtrace_machtrace_syscall);
- return;
+ ASSERT(mach_trap_table[sysnum].mach_trap_function == (void *)dtrace_machtrace_syscall);
+ return(0);
+ }
+
+ lck_mtx_lock(&dtrace_systrace_lock);
+
+ if (mach_trap_table[sysnum].mach_trap_function == machtrace_sysent[sysnum].stsy_underlying) {
+ vm_offset_t dss = (vm_offset_t)&dtrace_machtrace_syscall;
+ ml_nofault_copy((vm_offset_t)&dss, (vm_offset_t)&mach_trap_table[sysnum].mach_trap_function, sizeof(vm_offset_t));
}
- (void) casptr(&mach_trap_table[sysnum].mach_trap_function,
- (void *)machtrace_sysent[sysnum].stsy_underlying,
- (void *)dtrace_machtrace_syscall);
+ lck_mtx_unlock(&dtrace_systrace_lock);
+
+ return(0);
}
/*ARGSUSED*/
static void
machtrace_disable(void *arg, dtrace_id_t id, void *parg)
{
+#pragma unused(arg,id) /* __APPLE__ */
+
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
int disable = (machtrace_sysent[sysnum].stsy_entry == DTRACE_IDNONE ||
machtrace_sysent[sysnum].stsy_return == DTRACE_IDNONE);
if (disable) {
- (void) casptr(&mach_trap_table[sysnum].mach_trap_function,
- (void *)dtrace_machtrace_syscall,
- (void *)machtrace_sysent[sysnum].stsy_underlying);
+ lck_mtx_lock(&dtrace_systrace_lock);
+
+ if (mach_trap_table[sysnum].mach_trap_function == (mach_call_t)dtrace_machtrace_syscall) {
+ ml_nofault_copy((vm_offset_t)&machtrace_sysent[sysnum].stsy_underlying, (vm_offset_t)&mach_trap_table[sysnum].mach_trap_function, sizeof(vm_offset_t));
+ }
+ lck_mtx_unlock(&dtrace_systrace_lock);
}
if (SYSTRACE_ISENTRY((uintptr_t)parg)) {
NULL,
NULL,
NULL,
- NULL,
+ machtrace_getarg,
NULL,
machtrace_destroy
};
return (DDI_FAILURE);
}
- machtrace_probe = dtrace_probe;
+#if !defined(__APPLE__)
+ machtrace_probe = (void (*)())dtrace_probe;
membar_enter();
if (ddi_create_minor_node(devi, "machtrace", S_IFCHR, 0,
dtrace_register("mach_trap", &machtrace_attr, DTRACE_PRIV_USER, NULL,
&machtrace_pops, NULL, &machtrace_id) != 0) {
machtrace_probe = systrace_stub;
+#else
+ machtrace_probe = dtrace_probe;
+ membar_enter();
+
+ if (ddi_create_minor_node(devi, "machtrace", S_IFCHR, 0,
+ DDI_PSEUDO, 0) == DDI_FAILURE ||
+ dtrace_register("mach_trap", &machtrace_attr, DTRACE_PRIV_USER, NULL,
+ &machtrace_pops, NULL, &machtrace_id) != 0) {
+ machtrace_probe = (void (*))&systrace_stub;
+#endif /* __APPLE__ */
ddi_remove_minor_node(devi, NULL);
return (DDI_FAILURE);
}
return;
}
- systrace_attach( (dev_info_t *)majdevno, DDI_ATTACH );
- machtrace_attach( (dev_info_t *)majdevno, DDI_ATTACH );
+ systrace_attach( (dev_info_t *)(uintptr_t)majdevno, DDI_ATTACH );
+ machtrace_attach( (dev_info_t *)(uintptr_t)majdevno, DDI_ATTACH );
gSysTraceInited = 1;
} else
}
#undef SYSTRACE_MAJOR
#endif /* __APPLE__ */
+
+static uint64_t
+systrace_getarg(void *arg, dtrace_id_t id, void *parg, int argno, int aframes)
+{
+#pragma unused(arg,id,parg,aframes) /* __APPLE__ */
+ uint64_t val = 0;
+ syscall_arg_t *stack = (syscall_arg_t *)NULL;
+
+ uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());
+
+ if (uthread)
+ stack = (syscall_arg_t *)uthread->t_dtrace_syscall_args;
+
+ if (!stack)
+ return(0);
+
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+ /* dtrace_probe arguments arg0 .. arg4 are 64bits wide */
+ val = (uint64_t)*(stack+argno);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+ return (val);
+}
+
+
+static uint64_t
+machtrace_getarg(void *arg, dtrace_id_t id, void *parg, int argno, int aframes)
+{
+#pragma unused(arg,id,parg,aframes) /* __APPLE__ */
+ uint64_t val = 0;
+ syscall_arg_t *stack = (syscall_arg_t *)NULL;
+
+ uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());
+
+ if (uthread)
+ stack = (syscall_arg_t *)uthread->t_dtrace_syscall_args;
+
+ if (!stack)
+ return(0);
+
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+ /* dtrace_probe arguments arg0 .. arg4 are 64bits wide */
+ val = (uint64_t)*(stack+argno);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+ return (val);
+}
+