#include <linux/oom.h>
#include <linux/compat.h>
#include <linux/sdt.h>
+#include <linux/dtrace_os.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
/* execve succeeded */
#ifdef CONFIG_DTRACE
+ dtrace_task_cleanup(current); /* get rid of probes from old ... */
+ dtrace_task_init(current); /* ... be ready for probes from new */
current->dtrace_psinfo = dtrace_psinfo_alloc(current);
#endif
current->fs->in_exec = 0;
#define DTRACEIOC_REPLICATE _IOR(DTRACEIOC, 18, void *)
#define DTRACEHIOC 0xd8
-#define DTRACEHIOC_ADD _IOW(DTRACEHIOC, 1, int)
+#define DTRACEHIOC_ADD _IOW(DTRACEHIOC, 1, dof_hdr_t)
#define DTRACEHIOC_REMOVE _IOW(DTRACEHIOC, 2, int)
#define DTRACEHIOC_ADDDOF _IOW(DTRACEHIOC, 3, dof_helper_t)
-/* Copyright (C) 2011, 2012, 2013 Oracle Corporation */
+/* Copyright (C) 2011, 2012, 2013 Oracle, Inc. */
#ifndef _DTRACE_OS_H_
#define _DTRACE_OS_H_
extern void dtrace_stacktrace(stacktrace_state_t *);
+extern struct task_struct *register_pid_provider(pid_t);
+extern void unregister_pid_provider(pid_t);
+extern void dtrace_task_init(struct task_struct *tsk);
+extern void dtrace_task_cleanup(struct task_struct *tsk);
+
+extern void (*dtrace_helpers_cleanup)(struct task_struct *);
+extern void (*dtrace_fasttrap_probes_cleanup)(struct task_struct *);
+
#endif /* _DTRACE_OS_H_ */
--- /dev/null
+/* Copyright (C) 2011, 2012, 2013 Oracle, Inc. */
+
+#ifndef _FASTTRAP_H_
+#define _FASTTRAP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(CONFIG_DTRACE) || defined(CONFIG_DTRACE_MODULE)
+
+#define FASTTRAPIOC (('m' << 24) | ('r' << 16) | ('f' << 8))
+#define FASTTRAPIOC_MAKEPROBE (FASTTRAPIOC | 1)
+#define FASTTRAPIOC_GETINSTR (FASTTRAPIOC | 2)
+
+typedef enum fasttrap_probe_type {
+ DTFTP_NONE = 0,
+ DTFTP_ENTRY,
+ DTFTP_RETURN,
+ DTFTP_OFFSETS,
+ DTFTP_POST_OFFSETS,
+ DTFTP_IS_ENABLED
+} fasttrap_probe_type_t;
+
+typedef struct fasttrap_probe_spec {
+ pid_t ftps_pid;
+ fasttrap_probe_type_t ftps_type;
+ char ftps_func[DTRACE_FUNCNAMELEN];
+ char ftps_mod[DTRACE_MODNAMELEN];
+ uint64_t ftps_pc;
+ uint64_t ftps_size;
+ uint64_t ftps_noffs;
+ uint64_t ftps_offs[1];
+} fasttrap_probe_spec_t;
+
+typedef uint8_t fasttrap_instr_t;
+
+typedef struct fasttrap_instr_query {
+ uint64_t ftiq_pc;
+ pid_t ftiq_pid;
+ fasttrap_instr_t ftiq_instr;
+} fasttrap_instr_query_t;
+
+#endif /* CONFIG_DTRACE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FASTTRAP_H_ */
dtrace_psinfo_t *dtrace_psinfo;
void *dtrace_helpers;
+ uint32_t dtrace_probes;
#endif
#ifdef CONFIG_UPROBES
struct uprobe_task *utask;
return rc;
}
+
+/*---------------------------------------------------------------------------*\
+(* USER SPACE TRACING (FASTTRAP) SUPPORT *)
+\*---------------------------------------------------------------------------*/
+struct task_struct *register_pid_provider(pid_t pid)
+{
+ struct task_struct *p;
+
+ /*
+ * Make sure the process exists, (FIXME: isn't a child created as the
+ * result of a vfork(2)), and isn't a zombie (but may be in fork).
+ */
+ rcu_read_lock();
+ read_lock(&tasklist_lock);
+ if ((p = find_task_by_vpid(pid)) == NULL) {
+ read_unlock(&tasklist_lock);
+ rcu_read_unlock();
+ return NULL;
+ }
+
+ get_task_struct(p);
+ read_unlock(&tasklist_lock);
+ rcu_read_unlock();
+
+ if (p->state & TASK_DEAD ||
+ p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) {
+ put_task_struct(p);
+ return NULL;
+ }
+
+ /*
+ * Increment dtrace_probes so that the process knows to inform us
+ * when it exits or execs. fasttrap_provider_free() decrements this
+ * when we're done with this provider.
+ */
+ p->dtrace_probes++;
+ put_task_struct(p);
+
+ return p;
+}
+EXPORT_SYMBOL(register_pid_provider);
+
+void unregister_pid_provider(pid_t pid)
+{
+ struct task_struct *p;
+
+ /*
+ * Decrement dtrace_probes on the process whose provider we're
+ * freeing. We don't have to worry about clobbering somone else's
+ * modifications to it because we have locked the bucket that
+ * corresponds to this process's hash chain in the provider hash
+ * table. Don't sweat it if we can't find the process.
+ */
+ rcu_read_lock();
+ read_lock(&tasklist_lock);
+ if ((p = find_task_by_vpid(pid)) == NULL) {
+ read_unlock(&tasklist_lock);
+ rcu_read_unlock();
+ return;
+ }
+
+ get_task_struct(p);
+ read_unlock(&tasklist_lock);
+ rcu_read_unlock();
+
+ p->dtrace_probes--;
+ put_task_struct(p);
+}
+EXPORT_SYMBOL(unregister_pid_provider);
+
+void (*dtrace_helpers_cleanup)(struct task_struct *);
+EXPORT_SYMBOL(dtrace_helpers_cleanup);
+void (*dtrace_fasttrap_probes_cleanup)(struct task_struct *);
+EXPORT_SYMBOL(dtrace_fasttrap_probes_cleanup);
+
+void dtrace_task_init(struct task_struct *tsk)
+{
+ tsk->dtrace_helpers = NULL;
+ tsk->dtrace_probes = 0;
+}
+
+void dtrace_task_cleanup(struct task_struct *tsk)
+{
+ if (likely(dtrace_helpers_cleanup == NULL))
+ return;
+
+ if (tsk->dtrace_helpers != NULL)
+ (*dtrace_helpers_cleanup)(tsk);
+
+ if (tsk->dtrace_probes) {
+ if (dtrace_fasttrap_probes_cleanup == NULL)
+ pr_warn("Fasttrap probes, yet no cleanup routine\n");
+ else
+ (*dtrace_fasttrap_probes_cleanup)(tsk);
+ }
+}
#include <linux/writeback.h>
#include <linux/shm.h>
#include <linux/sdt.h>
+#include <linux/dtrace_os.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
DTRACE_PROC(lwp__exit);
DTRACE_PROC1(exit, int, code & 0x80 ? 3 : code & 0x7f ? 2 : 1);
+#ifdef CONFIG_DTRACE
+ dtrace_task_cleanup(tsk);
+#endif
+
exit_mm(tsk);
if (group_dead)
#include <linux/compiler.h>
#include <linux/sysctl.h>
#include <linux/sdt.h>
+#include <linux/dtrace_os.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#ifdef CONFIG_DTRACE
tsk->dtrace_psinfo = NULL;
+ dtrace_task_init(tsk);
#endif
return tsk;