X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d1ecb069dfe24481e4a83f44cb5217a2b06746d7..8a3053a07cee346dca737a5670e546fd26a7c9d6:/bsd/dev/dtrace/systrace.c diff --git a/bsd/dev/dtrace/systrace.c b/bsd/dev/dtrace/systrace.c index 74ab8a105..cdd5a3040 100644 --- a/bsd/dev/dtrace/systrace.c +++ b/bsd/dev/dtrace/systrace.c @@ -19,7 +19,7 @@ * 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. */ @@ -43,17 +43,15 @@ #endif #endif -#define MACH__POSIX_C_SOURCE_PRIVATE 1 /* pulls in suitable savearea from mach/ppc/thread_status.h */ #include #include + /* XXX All of these should really be derived from syscall_sw.h */ -#if defined(__i386__) || defined (__x86_64__) +#if defined (__x86_64__) #define SYSCALL_CLASS_SHIFT 24 #define SYSCALL_CLASS_MASK (0xFF << SYSCALL_CLASS_SHIFT) #define SYSCALL_NUMBER_MASK (~SYSCALL_CLASS_MASK) #define I386_SYSCALL_NUMBER_MASK (0xFFFF) - -typedef x86_saved_state_t savearea_t; #endif #include @@ -73,10 +71,9 @@ typedef x86_saved_state_t savearea_t; #include #include -#if defined (__ppc__) || defined (__ppc64__) -#define SYSTRACE_ARTIFICIAL_FRAMES 3 -#define MACHTRACE_ARTIFICIAL_FRAMES 4 -#elif defined(__i386__) || defined (__x86_64__) +#include + +#if defined (__x86_64__) #define SYSTRACE_ARTIFICIAL_FRAMES 2 #define MACHTRACE_ARTIFICIAL_FRAMES 3 #else @@ -96,23 +93,26 @@ extern const char *syscallnames[]; #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, 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, - uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7) + uint64_t arg2, uint64_t arg3, uint64_t arg4) { -#pragma unused(id,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7) +#pragma unused(id,arg0,arg1,arg2,arg3,arg4) } - int32_t dtrace_systrace_syscall(struct proc *pp, void *uap, int *rv) { - boolean_t flavor; - unsigned short code; + unsigned short code; /* The system call number */ systrace_sysent_t *sy; dtrace_id_t id; @@ -122,24 +122,9 @@ dtrace_systrace_syscall(struct proc *pp, void *uap, int *rv) #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; - - /* - * FIXME: unix_syscall screens for "unsafe calls" and instead calls nosys(), *not* sysent[code] ! - */ - } -#elif defined(__i386__) || defined (__x86_64__) -#pragma unused(flavor) +#if defined (__x86_64__) { + 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)) { @@ -169,10 +154,17 @@ dtrace_systrace_syscall(struct proc *pp, void *uap, int *rv) sy = (code >= NUM_SYSENT) ? &systrace_sysent[63] : &systrace_sysent[code]; 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), *(ip+5), *(ip+6), *(ip+7)); + (*systrace_probe)(id, *ip, *(ip+1), *(ip+2), *(ip+3), *(ip+4)); else - (*systrace_probe)(id, 0, 0, 0, 0, 0, 0, 0, 0); + (*systrace_probe)(id, 0, 0, 0, 0, 0); + + if (uthread) + uthread->t_dtrace_syscall_args = (void *)0; } #if 0 /* XXX */ @@ -260,7 +252,7 @@ dtrace_systrace_syscall(struct proc *pp, void *uap, int *rv) * * 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, 0, 0, 0); + (*systrace_probe)(id, munged_rv0, munged_rv0, munged_rv1, (uint64_t)rval, 0); } return (rval); @@ -328,7 +320,7 @@ dtrace_systrace_syscall_return(unsigned short code, int rval, int *rv) munged_rv1 = 0LL; } - (*systrace_probe)(id, munged_rv0, munged_rv0, munged_rv1, (uint64_t)rval, 0, 0, 0, 0); + (*systrace_probe)(id, munged_rv0, munged_rv0, munged_rv1, (uint64_t)rval, 0); } } #endif /* __APPLE__ */ @@ -409,6 +401,7 @@ systrace_init(struct sysent *actual, systrace_sysent_t **interposed) 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__ */ @@ -482,7 +475,7 @@ systrace_destroy(void *arg, dtrace_id_t id, void *parg) } /*ARGSUSED*/ -static void +static int systrace_enable(void *arg, dtrace_id_t id, void *parg) { #pragma unused(arg) /* __APPLE__ */ @@ -505,17 +498,21 @@ systrace_enable(void *arg, dtrace_id_t id, void *parg) 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*/ @@ -529,9 +526,10 @@ systrace_disable(void *arg, dtrace_id_t id, void *parg) 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, @@ -569,7 +567,7 @@ static dtrace_pops_t systrace_pops = { NULL, NULL, NULL, - NULL, + systrace_getarg, NULL, systrace_destroy }; @@ -738,22 +736,18 @@ typedef kern_return_t (*mach_call_t)(void *); 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 defined(__x86_64__) + mach_munge_t *mach_trap_arg_munge32; /* system call arguments for 32-bit */ #endif -#if !MACH_ASSERT - int mach_trap_unused; -#else - const char* mach_trap_name; -#endif /* !MACH_ASSERT */ + int mach_trap_u32_words; +#if MACH_ASSERT + const char* mach_trap_name; +#endif /* MACH_ASSERT */ } mach_trap_t; -extern mach_trap_t mach_trap_table[]; +extern const mach_trap_t mach_trap_table[]; /* syscall_sw.h now declares this as const */ extern int mach_trap_count; extern const char *mach_syscall_name_table[]; @@ -778,21 +772,27 @@ 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; static kern_return_t dtrace_machtrace_syscall(struct mach_call_args *args) { - boolean_t flavor; - unsigned short code; + int code; /* The mach call number */ machtrace_sysent_t *sy; dtrace_id_t id; @@ -803,20 +803,9 @@ dtrace_machtrace_syscall(struct mach_call_args *args) 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__) -#pragma unused(flavor) +#if defined (__x86_64__) { + 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)) { @@ -831,8 +820,17 @@ dtrace_machtrace_syscall(struct mach_call_args *args) 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 */ /* @@ -858,7 +856,7 @@ dtrace_machtrace_syscall(struct mach_call_args *args) } static void -machtrace_init(mach_trap_t *actual, machtrace_sysent_t **interposed) +machtrace_init(const mach_trap_t *actual, machtrace_sysent_t **interposed) { machtrace_sysent_t *msysent = *interposed; int i; @@ -869,16 +867,16 @@ machtrace_init(mach_trap_t *actual, machtrace_sysent_t **interposed) } for (i = 0; i < NSYSCALL; i++) { - mach_trap_t *a = &actual[i]; + const mach_trap_t *a = &actual[i]; machtrace_sysent_t *s = &msysent[i]; 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 = (sy_call_t *)a->mach_trap_function; + s->stsy_underlying = a->mach_trap_function; } } @@ -937,7 +935,7 @@ machtrace_destroy(void *arg, dtrace_id_t id, void *parg) } /*ARGSUSED*/ -static void +static int machtrace_enable(void *arg, dtrace_id_t id, void *parg) { #pragma unused(arg) /* __APPLE__ */ @@ -953,13 +951,20 @@ machtrace_enable(void *arg, dtrace_id_t id, void *parg) } if (enabled) { - ASSERT(sysent[sysnum].sy_callc == (void *)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*/ @@ -973,10 +978,13 @@ machtrace_disable(void *arg, dtrace_id_t id, void *parg) 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)) { @@ -1002,7 +1010,7 @@ static dtrace_pops_t machtrace_pops = { NULL, NULL, NULL, - NULL, + machtrace_getarg, NULL, machtrace_destroy }; @@ -1104,3 +1112,49 @@ void systrace_init( void ) } #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); +} +