From 4b90d66bb9118ccc7de04a1041acaad85a142417 Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Thu, 27 Oct 2011 10:39:19 -0400 Subject: [PATCH] Implementation for tracing stub-based system calls. Due to the need for specialized code handling (mainly passing in a pt_regs structure as one of the arguments), some syscalls are called through a stub in assembly code. We duplicate the stub cdode in dtrace_stubs_x86_64.S, but instead of calling the actual syscall implementation code call our own syscall-specific handler, which ensures that entry and return probes are called as enabled, and then call the underlying implementation directly for handling the syscall. Also removed debugging output that is no longer relevant (code cleanup). Signed-off-by: Kris Van Hees --- dtrace/dtrace_dev.c | 21 ------------- dtrace/dtrace_ecb.c | 2 -- dtrace/dtrace_isa.c | 2 -- dtrace/dtrace_probe.c | 3 +- dtrace/dtrace_ptofapi.c | 5 --- dtrace/dtrace_spec.c | 3 -- dtrace/dtrace_state.c | 10 ------ dtrace/profile_dev.c | 68 ++++++++++++++++++++++++++++++++++++----- dtrace/systrace_dev.c | 61 ++++++++++++++++++------------------ 9 files changed, 92 insertions(+), 83 deletions(-) diff --git a/dtrace/dtrace_dev.c b/dtrace/dtrace_dev.c index e76497f6555c..821ef540b284 100644 --- a/dtrace/dtrace_dev.c +++ b/dtrace/dtrace_dev.c @@ -109,7 +109,6 @@ static long dtrace_ioctl(struct file *file, dtrace_providerdesc_t pvd; dtrace_provider_t *pvp; -printk(KERN_INFO "IOCTL provider\n"); if (copy_from_user(&pvd, argp, sizeof(pvd)) != 0) return -EFAULT; @@ -146,26 +145,21 @@ printk(KERN_INFO "IOCTL provider\n"); uint8_t *dest; int nrecs; -printk(KERN_INFO "IOCTL eprobe\n"); if (copy_from_user(&epdesc, argp, sizeof(epdesc)) != 0) return -EFAULT; mutex_lock(&dtrace_lock); -printk(KERN_INFO " Looking for ECB %ld\n", epdesc.dtepd_epid); if ((ecb = dtrace_epid2ecb(state, epdesc.dtepd_epid)) == NULL) { mutex_unlock(&dtrace_lock); -printk(KERN_INFO " ECB not found\n"); return -EINVAL; } if (ecb->dte_probe == NULL) { mutex_unlock(&dtrace_lock); -printk(KERN_INFO " ECB has no probe\n"); return -EINVAL; } -printk(KERN_INFO " ECB has probe %ld\n", ecb->dte_probe->dtpr_id); epdesc.dtepd_probeid = ecb->dte_probe->dtpr_id; epdesc.dtepd_uarg = ecb->dte_uarg; epdesc.dtepd_size = ecb->dte_size; @@ -228,7 +222,6 @@ printk(KERN_INFO " ECB has probe %ld\n", ecb->dte_probe->dtpr_id); size_t size; uint8_t *dest; -printk(KERN_INFO "IOCTL aggdesc\n"); if (copy_from_user(&aggdesc, argp, sizeof(aggdesc)) != 0) return -EFAULT; @@ -238,7 +231,6 @@ printk(KERN_INFO "IOCTL aggdesc\n"); mutex_unlock(&dtrace_lock); return -EINVAL; } -printk(KERN_INFO "IOCTL aggdesc: Found agg %lu, ECB %lu\n", agg->dtag_id, agg->dtag_ecb->dte_epid); aggdesc.dtagd_epid = agg->dtag_ecb->dte_epid; @@ -330,7 +322,6 @@ printk(KERN_INFO "IOCTL aggdesc: Found agg %lu, ECB %lu\n", agg->dtag_id, agg->d int err = 0; int rv; -printk(KERN_INFO "IOCTL enable\n"); rv = 0; /* @@ -391,7 +382,6 @@ printk(KERN_INFO "IOCTL enable\n"); dtrace_probedesc_t *create = &desc.dtrpd_create; int err; -printk(KERN_INFO "IOCTL replicate\n"); if (copy_from_user(&desc, argp, sizeof(desc)) != 0) return -EFAULT; @@ -420,7 +410,6 @@ printk(KERN_INFO "IOCTL replicate\n"); uint32_t priv; uid_t uid; -printk(KERN_INFO "IOCTL %s\n", cmd == DTRACEIOC_PROBEMATCH ? "probematch" : "probes"); if (copy_from_user(&desc, argp, sizeof(desc)) != 0) return -EFAULT; @@ -443,7 +432,6 @@ printk(KERN_INFO "IOCTL %s\n", cmd == DTRACEIOC_PROBEMATCH ? "probematch" : "pro dtrace_probekey(&desc, &pkey); pkey.dtpk_id = DTRACE_IDNONE; } -printk(KERN_INFO "IOCTL %s: id[%d] p[%s] m[%s] f[%s] n[%s]\n", cmd == DTRACEIOC_PROBEMATCH ? "probematch" : "probes", desc.dtpd_id, desc.dtpd_provider, desc.dtpd_mod, desc.dtpd_func, desc.dtpd_name); dtrace_cred2priv(file->f_cred, &priv, &uid); @@ -483,7 +471,6 @@ printk(KERN_INFO "IOCTL %s: id[%d] p[%s] m[%s] f[%s] n[%s]\n", cmd == DTRACEIOC_ dtrace_probe_description(probe, &desc); mutex_unlock(&dtrace_lock); -printk(KERN_INFO "Returning probe [%s]\n", desc.dtpd_name); if (copy_to_user(argp, &desc, sizeof(desc)) != 0) return -EFAULT; @@ -495,7 +482,6 @@ printk(KERN_INFO "Returning probe [%s]\n", desc.dtpd_name); dtrace_probe_t *probe; dtrace_provider_t *prov; -printk(KERN_INFO "IOCTL probearg\n"); if (copy_from_user(&desc, argp, sizeof(desc)) != 0) return -EFAULT; @@ -550,7 +536,6 @@ printk(KERN_INFO "IOCTL probearg\n"); case DTRACEIOC_GO: { processorid_t cpuid; -printk(KERN_INFO "IOCTL go\n"); rval = dtrace_state_go(state, &cpuid); if (rval != 0) @@ -565,7 +550,6 @@ printk(KERN_INFO "IOCTL go\n"); case DTRACEIOC_STOP: { processorid_t cpuid; -printk(KERN_INFO "IOCTL stop\n"); mutex_lock(&dtrace_lock); rval = dtrace_state_stop(state, &cpuid); mutex_unlock(&dtrace_lock); @@ -583,7 +567,6 @@ printk(KERN_INFO "IOCTL stop\n"); dof_hdr_t hdr, *dof; uint64_t len; -printk(KERN_INFO "IOCTL dofget\n"); if (copy_from_user(&hdr, argp, sizeof(hdr)) != 0) return -EFAULT; @@ -604,7 +587,6 @@ printk(KERN_INFO "IOCTL dofget\n"); caddr_t cached; dtrace_buffer_t *buf; -printk(KERN_INFO "IOCTL %s\n", cmd == DTRACEIOC_AGGSNAP ? "aggsnap" : "bufsnap"); if (copy_from_user(&desc, argp, sizeof(desc)) != 0) return -EFAULT; @@ -731,7 +713,6 @@ printk(KERN_INFO "IOCTL %s\n", cmd == DTRACEIOC_AGGSNAP ? "aggsnap" : "bufsnap") case DTRACEIOC_CONF: { dtrace_conf_t conf; -printk(KERN_INFO "IOCTL conf\n"); memset(&conf, 0, sizeof(conf)); conf.dtc_difversion = DIF_VERSION; conf.dtc_difintregs = DIF_DIR_NREGS; @@ -751,7 +732,6 @@ printk(KERN_INFO "IOCTL conf\n"); int i, j; uint64_t nerrs; -printk(KERN_INFO "IOCTL status\n"); /* * See the comment in dtrace_state_deadman() for the reason * for setting dts_laststatus to INT64_MAX before setting @@ -819,7 +799,6 @@ printk(KERN_INFO "IOCTL status\n"); char *str; int len; -printk(KERN_INFO "IOCTL format\n"); if (copy_from_user(&fmt, argp, sizeof (fmt)) != 0) return -EFAULT; diff --git a/dtrace/dtrace_ecb.c b/dtrace/dtrace_ecb.c index ed65ec025dc8..9541a0ec0872 100644 --- a/dtrace/dtrace_ecb.c +++ b/dtrace/dtrace_ecb.c @@ -148,7 +148,6 @@ again: } agg->dtag_id = aggid; -printk(KERN_INFO "New aggregation: %u (for ECB %u)\n", aggid, ecb->dte_epid); frec = &agg->dtag_first->dta_rec; if (frec->dtrd_alignment < sizeof(dtrace_aggid_t)) @@ -574,7 +573,6 @@ static dtrace_ecb_t *dtrace_ecb_add(dtrace_state_t *state, state->dts_ecbs[(ecb->dte_epid = epid) - 1] = ecb; -printk(KERN_INFO "ecb_add: ECB %u for probe ID %u\n", epid, probe ? probe->dtpr_id : 0xffff); return ecb; } diff --git a/dtrace/dtrace_isa.c b/dtrace/dtrace_isa.c index a767be6bf9f4..3628ad2098bb 100644 --- a/dtrace/dtrace_isa.c +++ b/dtrace/dtrace_isa.c @@ -148,7 +148,6 @@ uint64_t dtrace_getarg(int arg, int aframes) #endif int nreg = sizeof(regmap) / sizeof(regmap[0]) - 1; -printk(KERN_INFO "getarg(%d, %d) -> nreg = %d\n", arg, aframes, nreg); for (i = 1; i <= aframes; i++) { fp = fp->fr_savfp; @@ -173,7 +172,6 @@ printk(KERN_INFO "getarg(%d, %d) -> nreg = %d\n", arg, aframes, nreg); arg++; #ifndef __i386__ -printk(KERN_INFO "getarg(%d, %d) [!i386]-> nreg = %d\n", arg, aframes, nreg); if (arg <= nreg) { /* * This should not happen. If the argument was passed in a diff --git a/dtrace/dtrace_probe.c b/dtrace/dtrace_probe.c index 35e660671787..771b813c81e1 100644 --- a/dtrace/dtrace_probe.c +++ b/dtrace/dtrace_probe.c @@ -96,7 +96,6 @@ again: if (provider != dtrace_provider) mutex_unlock(&dtrace_lock); -printk(KERN_INFO "probe_create(%s, %s, %s, %s) -> %d\n", provider->dtpv_name, mod, func, name, id); return id; } EXPORT_SYMBOL(dtrace_probe_create); @@ -118,7 +117,7 @@ int dtrace_probe_enable(const dtrace_probedesc_t *desc, dtrace_enabling_t *enab) dtrace_probekey(desc, &pkey); dtrace_cred2priv(enab->dten_vstate->dtvs_state->dts_cred.dcr_cred, &priv, &uid); -printk(KERN_INFO "probe_enable(%d, %s, %s, %s, %s)\n", pkey.dtpk_id, pkey.dtpk_prov, pkey.dtpk_mod, pkey.dtpk_func, pkey.dtpk_name); + return dtrace_match(&pkey, priv, uid, dtrace_ecb_create_enable, enab); } diff --git a/dtrace/dtrace_ptofapi.c b/dtrace/dtrace_ptofapi.c index 920ddd7e1124..88df66704cd4 100644 --- a/dtrace/dtrace_ptofapi.c +++ b/dtrace/dtrace_ptofapi.c @@ -242,7 +242,6 @@ int dtrace_unregister(dtrace_provider_id_t id) NULL }; -printk(KERN_INFO "unregister(%p)\n", old); if (old->dtpv_pops.dtps_enable == (int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop) { /* @@ -273,7 +272,6 @@ printk(KERN_INFO "unregister(%p)\n", old); * are anonymous probes that are still enabled, we refuse to deregister * providers, unless the provider has been invalidated explicitly. */ -printk(KERN_INFO "unregister(%p) %d opens\n", old, dtrace_opens); if (!old->dtpv_defunct && (dtrace_opens || (dtrace_anon.dta_state != NULL && dtrace_anon.dta_state->dts_necbs > 0))) { @@ -293,7 +291,6 @@ printk(KERN_INFO "unregister(%p) %d opens\n", old, dtrace_opens); */ st.prov = old; err = dtrace_probe_for_each(dtrace_unregister_check, &st); -printk(KERN_INFO "unregister(%p) check -> %d\n", old, err); if (err < 0) { if (!self) { mutex_unlock(&dtrace_lock); @@ -310,7 +307,6 @@ printk(KERN_INFO "unregister(%p) check -> %d\n", old, err); * We chain all the probes together for further processing. */ dtrace_probe_for_each(dtrace_unregister_probe, &st); -printk(KERN_INFO "unregister(%p) unregister_probe done\n", old); /* * The probes associated with the provider have been removed. Ensure @@ -326,7 +322,6 @@ printk(KERN_INFO "unregister(%p) unregister_probe done\n", old); st.first = probe->dtpr_nextmod; -printk(KERN_INFO "unregister(%p) Destroying probe %d\n", old, probe_id); old->dtpv_pops.dtps_destroy(old->dtpv_arg, probe_id, probe->dtpr_arg); diff --git a/dtrace/dtrace_spec.c b/dtrace/dtrace_spec.c index f83870a27e33..d02224d3361e 100644 --- a/dtrace/dtrace_spec.c +++ b/dtrace/dtrace_spec.c @@ -94,7 +94,6 @@ void dtrace_speculation_commit(dtrace_state_t *state, processorid_t cpu, if (which == 0) return; -printk(KERN_INFO "spec-commit: CPU#%d, which %d\n", cpu, which); if (which > state->dts_nspeculations) { cpu_core[cpu].cpuc_dtrace_flags |= CPU_DTRACE_ILLOP; return; @@ -105,7 +104,6 @@ printk(KERN_INFO "spec-commit: CPU#%d, which %d\n", cpu, which); dest = &state->dts_buffer[cpu]; do { -printk(KERN_INFO "spec-commit: a) CPU#%d, which %d, spec-state %d\n", cpu, which, spec->dtsp_state); curr = spec->dtsp_state; if (curr == DTRACESPEC_COMMITTINGMANY) @@ -152,7 +150,6 @@ printk(KERN_INFO "spec-commit: a) CPU#%d, which %d, spec-state %d\n", cpu, which default: ASSERT(0); } -printk(KERN_INFO "spec-commit: a) CPU#%d, which %d, spec-state %d -> %d\n", cpu, which, curr, new); } while (cmpxchg((uint32_t *)&spec->dtsp_state, curr, new) != curr); diff --git a/dtrace/dtrace_state.c b/dtrace/dtrace_state.c index 2fdcd285d8ae..afbccb4ae7d7 100644 --- a/dtrace/dtrace_state.c +++ b/dtrace/dtrace_state.c @@ -481,7 +481,6 @@ static int dtrace_state_buffer(dtrace_state_t *state, dtrace_buffer_t *buf, ASSERT(state->dts_activity == DTRACE_ACTIVITY_INACTIVE || (state == dtrace_anon.dta_state && state->dts_activity == DTRACE_ACTIVITY_ACTIVE)); -printk(KERN_INFO "state_buffer(%p, %p, %d) opt[%d] = %lld\n", state, buf, which, which, opt[which]); if (opt[which] == DTRACEOPT_UNSET || opt[which] == 0) return 0; @@ -493,7 +492,6 @@ printk(KERN_INFO "state_buffer(%p, %p, %d) opt[%d] = %lld\n", state, buf, which, flags |= DTRACEBUF_NOSWITCH; if (which == DTRACEOPT_BUFSIZE) { -printk(KERN_INFO "state_buffer(%p, %p, %d) opt[CPU] = %lld, opt[BUFPOLICY] = %lld, sta_state = %p\n", state, buf, which, opt[DTRACEOPT_CPU], opt[DTRACEOPT_BUFPOLICY], dtrace_anon.dta_state); if (opt[DTRACEOPT_BUFPOLICY] == DTRACEOPT_BUFPOLICY_RING) flags |= DTRACEBUF_RING; @@ -503,7 +501,6 @@ printk(KERN_INFO "state_buffer(%p, %p, %d) opt[CPU] = %lld, opt[BUFPOLICY] = %ll if (state != dtrace_anon.dta_state || state->dts_activity != DTRACE_ACTIVITY_ACTIVE) flags |= DTRACEBUF_INACTIVE; -printk(KERN_INFO "state_buffer(%p, %p, %d) flags = %08x\n", state, buf, which, flags); } for (size = opt[which]; size >= sizeof (uint64_t); size >>= 1) { @@ -525,7 +522,6 @@ printk(KERN_INFO "state_buffer(%p, %p, %d) flags = %08x\n", state, buf, which, f } rval = dtrace_buffer_alloc(buf, size, flags, cpu); -printk(KERN_INFO "state_buffer: Alloc %d buffer: tomax %p xamot %p\n", which, buf->dtb_tomax, buf->dtb_xamot); if (rval != -ENOMEM) { opt[which] = size; @@ -600,7 +596,6 @@ int dtrace_state_go(dtrace_state_t *state, processorid_t *cpu) mutex_lock(&cpu_lock); mutex_lock(&dtrace_lock); -printk(KERN_INFO "state_go(1): dts_activity = %d (vs warmup %d or draining %d)\n", state->dts_activity, DTRACE_ACTIVITY_WARMUP, DTRACE_ACTIVITY_DRAINING); if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE) { rval = -EBUSY; goto out; @@ -633,7 +628,6 @@ printk(KERN_INFO "state_go(1): dts_activity = %d (vs warmup %d or draining %d)\n } spec = kzalloc(nspec * sizeof(dtrace_speculation_t), GFP_KERNEL); -printk(KERN_INFO "state_go: nspec = %d, spec = %p (%lld bytes)\n", (int)nspec, spec, nspec * sizeof(dtrace_speculation_t)); if (spec == NULL) { rval = -ENOMEM; goto out; @@ -648,7 +642,6 @@ printk(KERN_INFO "state_go: nspec = %d, spec = %p (%lld bytes)\n", (int)nspec, s goto err; } -printk(KERN_INFO "state_go: spec[%d].buf = %p (%d bytes)\n", i, buf, bufsize); spec[i].dtsp_buffer = buf; } @@ -790,7 +783,6 @@ printk(KERN_INFO "state_go: spec[%d].buf = %p (%d bytes)\n", i, buf, bufsize); state->dts_deadman = cyclic_add(&hdlr, &when); state->dts_activity = DTRACE_ACTIVITY_WARMUP; -printk(KERN_INFO "state_go(2): dts_activity = %d (vs warmup %d or draining %d)\n", state->dts_activity, DTRACE_ACTIVITY_WARMUP, DTRACE_ACTIVITY_DRAINING); /* * Now it's time to actually fire the BEGIN probe. We need to disable @@ -811,7 +803,6 @@ printk(KERN_INFO "state_go(2): dts_activity = %d (vs warmup %d or draining %d)\n * We may have had an exit action from a BEGIN probe; only change our * state to ACTIVE if we're still in WARMUP. */ -printk(KERN_INFO "state_go(3): dts_activity = %d (vs warmup %d or draining %d)\n", state->dts_activity, DTRACE_ACTIVITY_WARMUP, DTRACE_ACTIVITY_DRAINING); ASSERT(state->dts_activity == DTRACE_ACTIVITY_WARMUP || state->dts_activity == DTRACE_ACTIVITY_DRAINING); @@ -993,7 +984,6 @@ void dtrace_state_destroy(dtrace_state_t *state) * issue a sync to be sure that everyone is out of probe * context before we start blowing away ECBs. */ -printk(KERN_INFO "state_destroy: Setting dts_activity from %d to %d (KILLED)\n", state->dts_activity, DTRACE_ACTIVITY_KILLED); state->dts_activity = DTRACE_ACTIVITY_KILLED; dtrace_sync(); } diff --git a/dtrace/profile_dev.c b/dtrace/profile_dev.c index 584197c9afa4..e66a77f258cb 100644 --- a/dtrace/profile_dev.c +++ b/dtrace/profile_dev.c @@ -26,8 +26,11 @@ */ #include +#include #include #include +#include +#include #include "dtrace.h" #include "dtrace_dev.h" @@ -84,8 +87,64 @@ static atomic_t profile_total; /* current number of profile probes */ static void profile_tick(void *arg) { profile_probe_t *prof = arg; + struct pt_regs *regs = get_irq_regs(); + unsigned long pc = 0, upc = 0; - dtrace_probe(prof->prof_id, 0, 0, 0, 0, 0); /* FIXME */ + if (user_mode(regs)) + upc = GET_IP(regs); + else + pc = GET_IP(regs); + + dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0); +} + +static void profile_prof(void *arg) +{ + profile_probe_percpu_t *pcpu = arg; + profile_probe_t *prof = pcpu->profc_probe; + ktime_t late; + struct pt_regs *regs = get_irq_regs(); + unsigned long pc = 0, upc = 0; + + late = ktime_sub(dtrace_gethrtime(), pcpu->profc_expected); + pcpu->profc_expected = ktime_add(pcpu->profc_expected, + pcpu->profc_interval); + + if (user_mode(regs)) + upc = GET_IP(regs); + else + pc = GET_IP(regs); + + dtrace_probe(prof->prof_id, pc, upc, ktime_to_ns(late), 0, 0); +} + +static void profile_online(void *arg, processorid_t cpu, cyc_handler_t *hdlr, + cyc_time_t *when) +{ + profile_probe_t *prof = arg; + profile_probe_percpu_t *pcpu; + + pcpu = kzalloc(sizeof(profile_probe_percpu_t), GFP_KERNEL); + pcpu->profc_probe = prof; + + hdlr->cyh_func = profile_prof; + hdlr->cyh_arg = pcpu; + hdlr->cyh_level = CY_HIGH_LEVEL; + + when->cyt_interval = prof->prof_interval; + when->cyt_when = ktime_add(dtrace_gethrtime(), when->cyt_interval); + + pcpu->profc_expected = when->cyt_when; + pcpu->profc_interval = when->cyt_interval; +} + +static void profile_offline(void *arg, processorid_t cpu, void *oarg) +{ + profile_probe_percpu_t *pcpu = oarg; + + ASSERT(pcpu->profc_probe == arg); + + kfree(pcpu); } static void profile_create(ktime_t interval, const char *name, int kind) @@ -262,9 +321,7 @@ void profile_provide(void *arg, const dtrace_probedesc_t *desc) int profile_enable(void *arg, dtrace_id_t id, void *parg) { profile_probe_t *prof = parg; -#ifdef FIXME cyc_omni_handler_t omni; -#endif cyc_handler_t hdlr; cyc_time_t when; @@ -283,16 +340,11 @@ int profile_enable(void *arg, dtrace_id_t id, void *parg) } else { ASSERT(prof->prof_kind == PROF_PROFILE); -#ifdef FIXME omni.cyo_online = profile_online; omni.cyo_offline = profile_offline; omni.cyo_arg = prof; prof->prof_cyclic = cyclic_add_omni(&omni); -#else - prof->prof_cyclic = CYCLIC_NONE; - return -ENOTSUPP; -#endif } return 0; diff --git a/dtrace/systrace_dev.c b/dtrace/systrace_dev.c index 3dab2a42eed2..2af6ff08d1a3 100644 --- a/dtrace/systrace_dev.c +++ b/dtrace/systrace_dev.c @@ -69,13 +69,8 @@ void systrace_provide(void *arg, const dtrace_probedesc_t *desc) sz = strlen(nm); if (sz > 4 && memcmp(nm, "sys_", 4) == 0) nm += 4; -#if 0 else if (sz > 5 && memcmp(nm, "stub_", 5) == 0) nm += 5; -#else - else if (sz > 5 && memcmp(nm, "stub_", 5) == 0) - continue; -#endif if (dtrace_probe_lookup(syscall_id, NULL, nm, "entry") != 0) continue; @@ -92,59 +87,65 @@ void systrace_provide(void *arg, const dtrace_probedesc_t *desc) } } +static dt_sys_call_t get_intercept(int sysnum) +{ + switch (sysnum) { + default: + return systrace_info->syscall; + case __NR_clone: + return systrace_info->stubs[SCE_CLONE]; + case __NR_fork: + return systrace_info->stubs[SCE_FORK]; + case __NR_vfork: + return systrace_info->stubs[SCE_VFORK]; + case __NR_sigaltstack: + return systrace_info->stubs[SCE_SIGALTSTACK]; + case __NR_iopl: + return systrace_info->stubs[SCE_IOPL]; + case __NR_execve: + return systrace_info->stubs[SCE_EXECVE]; + case __NR_rt_sigreturn: + return systrace_info->stubs[SCE_RT_SIGRETURN]; + } +} + int systrace_enable(void *arg, dtrace_id_t id, void *parg) { - int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg); - int enabled = + int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg); + int enabled = systrace_info->sysent[sysnum].stsy_entry != DTRACE_IDNONE || systrace_info->sysent[sysnum].stsy_return != DTRACE_IDNONE; + dt_sys_call_t intercept = get_intercept(sysnum);; -#if 0 - if (SYSTRACE_ISENTRY((uintptr_t)parg)) - systrace_info->sysent[sysnum].stsy_entry = id; - else - systrace_info->sysent[sysnum].stsy_return = id; - - if (enabled) { - ASSERT((void *)*(systrace_info->sysent[sysnum].stsy_tblent) == - (void *)systrace_info->syscall); - - return 0; - } - - (void)cmpxchg(systrace_info->sysent[sysnum].stsy_tblent, - systrace_info->sysent[sysnum].stsy_underlying, - systrace_info->syscall); -#else if (!enabled) { if (cmpxchg(systrace_info->sysent[sysnum].stsy_tblent, systrace_info->sysent[sysnum].stsy_underlying, - systrace_info->syscall) != + intercept) != systrace_info->sysent[sysnum].stsy_underlying) return 0; } else ASSERT((void *)*(systrace_info->sysent[sysnum].stsy_tblent) == - (void *)systrace_info->syscall); + (void *)intercept); if (SYSTRACE_ISENTRY((uintptr_t)parg)) systrace_info->sysent[sysnum].stsy_entry = id; else systrace_info->sysent[sysnum].stsy_return = id; -#endif return 0; } void systrace_disable(void *arg, dtrace_id_t id, void *parg) { - int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg); - int enabled = + int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg); + int enabled = systrace_info->sysent[sysnum].stsy_entry != DTRACE_IDNONE || systrace_info->sysent[sysnum].stsy_return != DTRACE_IDNONE; + dt_sys_call_t intercept = get_intercept(sysnum);; if (enabled) (void)cmpxchg(systrace_info->sysent[sysnum].stsy_tblent, - systrace_info->syscall, + intercept, systrace_info->sysent[sysnum].stsy_underlying); if (SYSTRACE_ISENTRY((uintptr_t)parg)) -- 2.50.1