dtrace_modload = dtrace_module_loaded;
dtrace_modunload = dtrace_module_unloaded;
dtrace_helpers_cleanup = dtrace_helpers_destroy;
+ dtrace_helpers_fork = dtrace_helpers_duplicate;
#ifdef FIXME
dtrace_cpu_init = dtrace_cpu_setup_initial;
dtrace_cpustart_init = dtrace_suspend;
void dtrace_dev_exit(void)
{
+ mutex_lock(&cpu_lock);
+ mutex_lock(&dtrace_provider_lock);
+ mutex_lock(&dtrace_lock);
+
+ dtrace_unregister((dtrace_provider_id_t)dtrace_provider);
+ dtrace_provider = NULL;
+
+ dtrace_probe_exit();
+
+ dtrace_modload = NULL;
+ dtrace_modunload = NULL;
+ dtrace_helpers_cleanup = NULL;
+ dtrace_helpers_fork = NULL;
+#ifdef FIXME
+ dtrace_cpu_init = NULL;
+ dtrace_cpustart_init = NULL;
+ dtrace_cpustart_fini = NULL;
+ dtrace_debugger_init = NULL;
+ dtrace_debugger_fini = NULL;
+
+ unregister_cpu_setup_func((cpu_setup_func_t *)dtrace_cpu_setup, NULL);
+#endif
+
+ mutex_unlock(&cpu_lock);
+
+ dtrace_hash_destroy(dtrace_bymod);
+ dtrace_hash_destroy(dtrace_byfunc);
+ dtrace_hash_destroy(dtrace_byname);
+ dtrace_bymod = NULL;
+ dtrace_byfunc = NULL;
+ dtrace_byname = NULL;
+
kmem_cache_destroy(dtrace_state_cache);
misc_deregister(&helper_dev);
misc_deregister(&dtrace_dev);
- dtrace_probe_exit();
+ mutex_unlock(&dtrace_lock);
+ mutex_unlock(&dtrace_provider_lock);
}
dtrace_difo_hold(dp);
}
+dtrace_difo_t * dtrace_difo_duplicate(dtrace_difo_t *dp,
+ dtrace_vstate_t *vstate)
+{
+ dtrace_difo_t *new;
+ size_t sz;
+
+ ASSERT(dp->dtdo_buf != NULL);
+ ASSERT(dp->dtdo_refcnt != 0);
+
+ new = vzalloc(sizeof(dtrace_difo_t));
+
+ ASSERT(dp->dtdo_buf != NULL);
+ sz = dp->dtdo_len * sizeof(dif_instr_t);
+ new->dtdo_buf = vmalloc(sz);
+ memcpy(new->dtdo_buf, dp->dtdo_buf, sz);
+ new->dtdo_len = dp->dtdo_len;
+
+ if (dp->dtdo_strtab != NULL) {
+ ASSERT(dp->dtdo_strlen != 0);
+ new->dtdo_strtab = vmalloc(dp->dtdo_strlen);
+ memcpy(new->dtdo_strtab, dp->dtdo_strtab, dp->dtdo_strlen);
+ new->dtdo_strlen = dp->dtdo_strlen;
+ }
+
+ if (dp->dtdo_inttab != NULL) {
+ ASSERT(dp->dtdo_intlen != 0);
+ sz = dp->dtdo_intlen * sizeof(uint64_t);
+ new->dtdo_inttab = vmalloc(sz);
+ memcpy(new->dtdo_inttab, dp->dtdo_inttab, sz);
+ new->dtdo_intlen = dp->dtdo_intlen;
+ }
+
+ if (dp->dtdo_vartab != NULL) {
+ ASSERT(dp->dtdo_varlen != 0);
+ sz = dp->dtdo_varlen * sizeof(dtrace_difv_t);
+ new->dtdo_vartab = vmalloc(sz);
+ memcpy(new->dtdo_vartab, dp->dtdo_vartab, sz);
+ new->dtdo_varlen = dp->dtdo_varlen;
+ }
+
+ dtrace_difo_init(new, vstate);
+
+ return new;
+}
+
void dtrace_difo_destroy(dtrace_difo_t *dp, dtrace_vstate_t *vstate)
{
int i;
}
}
-#define DTRACE_V4MAPPED_OFFSET (sizeof (uint32_t) * 3)
+#define DTRACE_V4MAPPED_OFFSET (sizeof(uint32_t) * 3)
/*
* Emulate the execution of DTrace ID subroutines invoked by the call opcode.
dtrace_enabling_matchall();
}
-static void dtrace_helper_provider_register(struct task_struct *curr,
+static void dtrace_helper_provider_register(struct task_struct *tsk,
dtrace_helpers_t *dth,
dof_helper_t *dofhp)
{
if (dth->dthps_next == NULL && dth->dthps_prev == NULL &&
dtrace_deferred_pid != dth) {
dth->dthps_deferred = 1;
- dth->dthps_pid = current->pid;
+ dth->dthps_pid = tsk->pid;
dth->dthps_next = dtrace_deferred_pid;
dth->dthps_prev = NULL;
if (dtrace_deferred_pid != NULL)
*/
mutex_unlock(&dtrace_lock);
- dtrace_helper_provide(dofhp, current->pid);
+ dtrace_helper_provide(dofhp, tsk->pid);
} else {
/*
* Otherwise, just pass all the helper provider descriptions
for (i = 0; i < dth->dthps_nprovs; i++) {
dtrace_helper_provide(&dth->dthps_provs[i]->dthp_prov,
- current->pid);
+ tsk->pid);
}
}
mutex_unlock(&dtrace_lock);
}
+void dtrace_helpers_duplicate(struct task_struct *from, struct task_struct *to)
+{
+ dtrace_helpers_t *help, *newhelp;
+ dtrace_helper_action_t *helper, *new, *last;
+ dtrace_difo_t *dp;
+ dtrace_vstate_t *vstate;
+ int i, j, sz, hasprovs = 0;
+
+ mutex_lock(&dtrace_lock);
+
+ ASSERT(from->dtrace_helpers != NULL);
+ ASSERT(dtrace_helpers > 0);
+
+ help = from->dtrace_helpers;
+ newhelp = dtrace_helpers_create(to);
+
+ ASSERT(to->dtrace_helpers != NULL);
+
+ newhelp->dthps_generation = help->dthps_generation;
+ vstate = &newhelp->dthps_vstate;
+
+ /*
+ * Duplicate the helper actions.
+ */
+ for (i = 0; i < DTRACE_NHELPER_ACTIONS; i++) {
+ if ((helper = help->dthps_actions[i]) == NULL)
+ continue;
+
+ for (last = NULL; helper != NULL; helper = helper->dtha_next) {
+ new = vzalloc(sizeof(dtrace_helper_action_t));
+ new->dtha_generation = helper->dtha_generation;
+
+ if ((dp = helper->dtha_predicate) != NULL) {
+ dp = dtrace_difo_duplicate(dp, vstate);
+ new->dtha_predicate = dp;
+ }
+
+ new->dtha_nactions = helper->dtha_nactions;
+ sz = sizeof(dtrace_difo_t *) * new->dtha_nactions;
+ new->dtha_actions = vmalloc(sz);
+
+ for (j = 0; j < new->dtha_nactions; j++) {
+ dtrace_difo_t *dp = helper->dtha_actions[j];
+
+ ASSERT(dp != NULL);
+
+ dp = dtrace_difo_duplicate(dp, vstate);
+ new->dtha_actions[j] = dp;
+ }
+
+ if (last != NULL)
+ last->dtha_next = new;
+ else
+ newhelp->dthps_actions[i] = new;
+
+ last = new;
+ }
+ }
+
+ /*
+ * Duplicate the helper providers and register them with the
+ * DTrace framework.
+ */
+ if (help->dthps_nprovs > 0) {
+ newhelp->dthps_nprovs = help->dthps_nprovs;
+ newhelp->dthps_maxprovs = help->dthps_nprovs;
+ newhelp->dthps_provs = vmalloc(
+ newhelp->dthps_nprovs *
+ sizeof(dtrace_helper_provider_t *));
+
+ for (i = 0; i < newhelp->dthps_nprovs; i++) {
+ newhelp->dthps_provs[i] = help->dthps_provs[i];
+ newhelp->dthps_provs[i]->dthp_ref++;
+ }
+
+ hasprovs = 1;
+ }
+
+ mutex_unlock(&dtrace_lock);
+
+ if (hasprovs)
+ dtrace_helper_provider_register(to, newhelp, NULL);
+}
+
int dtrace_helper_destroygen(int gen)
{
struct task_struct *p = current;
return hash;
}
+void dtrace_hash_destroy(dtrace_hash_t *hash)
+{
+#ifdef DEBUG
+ int i;
+
+ for (i = 0; i < hash->dth_size; i++)
+ ASSERT(hash->dth_tab[i] == NULL);
+#endif
+
+ vfree(hash->dth_tab);
+ vfree(hash);
+}
+
static int dtrace_hash_resize(dtrace_hash_t *hash)
{
int size = hash->dth_size, i, ndx;
asm volatile("movq %%rbp,%0" : "=m"(bp));
+#if 0
+for (i = 0, st = (uint64_t *)bp; i < 180; i++) pr_info("stack[%3d] %p = %llx\n", i, &st[i], st[i]);
+#endif
+#if 0
+for (i = 0, st = (uint64_t *)bp; i < 16; i++) { pr_info("BP at frame %d: %p -> (%llx, %llx)\n", i, st, st[0], st[1]); if (st[0] == 0) break; st = (uint64_t *)st[0]; }
+#endif
for (i = 0; i < aframes; i++)
bp = *((unsigned long *)bp);
while (i < argc)
argv[i++] = 0;
+for (i = 0; i < argc; i++) pr_info("%s: argv[%2d] = %lx\n", __FUNCTION__, i, argv[i]);
}
static int fasttrap_pid_probe(fasttrap_machtp_t *mtp, struct pt_regs *regs) {
fasttrap_id_t *id;
int is_enabled = 0;
+ /*
+ * Verify that this probe event is actually related to the current
+ * task. If not, ignore it.
+ *
+ * TODO: The underlying probe mechanism should register a single
+ * handler for the (inode, offset) combination. When the handler
+ * is called, it should run through a list of fasttrap
+ * tracepoints associated with the OS-level probe, looking for
+ * one that is related to the current task.
+ */
+ if (tp->ftt_pid != current->pid)
+ return 0;
+
if (atomic64_read(&tp->ftt_proc->ftpc_acount) == 0)
return 0;
fasttrap_bucket_t *bucket;
char provname[DTRACE_PROVNAMELEN];
struct task_struct *p;
- const cred_t *cred;
+ const cred_t *cred = NULL;
ASSERT(strlen(name) < sizeof (fp->ftp_name));
ASSERT(pa != NULL);
return new_fp;
fail:
- put_cred(cred);
-
if (proc)
fasttrap_proc_release(proc);
+ if (cred)
+ put_cred(cred);
if (p)
unregister_pid_provider(pid);
}
#ifdef FIXME
- dtrace_fasttrap_fork_ptr = &fasttrap_fork;
dtrace_fasttrap_exit_ptr = &fasttrap_exec_exit;
dtrace_fasttrap_exec_ptr = &fasttrap_exec_exit;
#endif
vfree(fasttrap_procs.fth_table);
fasttrap_procs.fth_nent = 0;
- /*
- * We know there are no tracepoints in any process anywhere in
- * the system so there is no process which has its p_dtrace_count
- * greater than zero, therefore we know that no thread can actively
- * be executing code in fasttrap_fork(). Similarly for p_dtrace_probes
- * and fasttrap_exec() and fasttrap_exit().
- */
#ifdef FIXME
- ASSERT(dtrace_fasttrap_fork_ptr == &fasttrap_fork);
- dtrace_fasttrap_fork_ptr = NULL;
-
ASSERT(dtrace_fasttrap_exec_ptr == &fasttrap_exec_exit);
dtrace_fasttrap_exec_ptr = NULL;
*/
extern dtrace_hash_t *dtrace_hash_create(uintptr_t, uintptr_t, uintptr_t);
+extern void dtrace_hash_destroy(dtrace_hash_t *);
extern int dtrace_hash_add(dtrace_hash_t *, dtrace_probe_t *);
extern dtrace_probe_t *dtrace_hash_lookup(dtrace_hash_t *, dtrace_probe_t *);
extern int dtrace_hash_collisions(dtrace_hash_t *, dtrace_probe_t *);
extern int dtrace_difo_cacheable(dtrace_difo_t *);
extern void dtrace_difo_hold(dtrace_difo_t *);
extern void dtrace_difo_init(dtrace_difo_t *, dtrace_vstate_t *);
+extern dtrace_difo_t * dtrace_difo_duplicate(dtrace_difo_t *,
+ dtrace_vstate_t *);
extern void dtrace_difo_release(dtrace_difo_t *, dtrace_vstate_t *);
extern uint64_t dtrace_dif_emulate(dtrace_difo_t *, dtrace_mstate_t *,
* DTrace Helper Functions
*/
extern void dtrace_helpers_destroy(struct task_struct *);
+extern void dtrace_helpers_duplicate(struct task_struct *,
+ struct task_struct *);
extern uint64_t dtrace_helper(int, dtrace_mstate_t *, dtrace_state_t *,
uint64_t, uint64_t);