summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorTim Moore <timoore@redhat.com>2010-01-13 19:37:51 +0100
committerTim Moore <timoore@redhat.com>2010-01-13 19:37:51 +0100
commit58b06a43d003a1e658b184d5ef577d44d824263e (patch)
tree513f1e61f0413a782747ccee02ee98ed7f6e8097 /runtime
parent275ea5e8ee085af6a7782fe3acbffe07645aa0a4 (diff)
downloadsystemtap-steved-58b06a43d003a1e658b184d5ef577d44d824263e.tar.gz
systemtap-steved-58b06a43d003a1e658b184d5ef577d44d824263e.tar.xz
systemtap-steved-58b06a43d003a1e658b184d5ef577d44d824263e.zip
map through uretprobe trampoline in an arbitrary task
* runtime/uprobes2/uprobes.c (uprobe_get_pc_task): new function (lookup_uretprobe): new helper function (uprobe_get_pc): use it * runtime/uprobes2/uprobes.h (uprobe_get_pc_task): declare * runtime/uprobes/uprobes.c : ditto * runtime/uprobes/uprobes.h : ditto
Diffstat (limited to 'runtime')
-rw-r--r--runtime/uprobes/uprobes.c68
-rw-r--r--runtime/uprobes/uprobes.h6
-rw-r--r--runtime/uprobes2/uprobes.c69
-rw-r--r--runtime/uprobes2/uprobes.h6
4 files changed, 114 insertions, 35 deletions
diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c
index 5ccc7102..61050121 100644
--- a/runtime/uprobes/uprobes.c
+++ b/runtime/uprobes/uprobes.c
@@ -2596,6 +2596,33 @@ static void uretprobe_set_trampoline(struct uprobe_process *uproc,
}
}
+static inline unsigned long lookup_uretprobe(struct hlist_node *r,
+ struct uprobe_process *uproc,
+ unsigned long pc,
+ unsigned long sp)
+{
+ struct uretprobe_instance *ret_inst;
+ unsigned long trampoline_addr;
+
+ if (IS_ERR(uproc->uretprobe_trampoline_addr))
+ return pc;
+ trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr;
+ if (pc != trampoline_addr)
+ return pc;
+ hlist_for_each_entry_from(ret_inst, r, hlist) {
+ if (ret_inst->ret_addr == trampoline_addr)
+ continue;
+ /* First handler with a stack pointer lower than the
+ address (or equal) must be the one. */
+ if (ret_inst->sp == sp || compare_stack_ptrs(ret_inst->sp, sp))
+ return ret_inst->ret_addr;
+ }
+ printk(KERN_ERR "Original return address for trampoline not found at "
+ "0x%lx pid/tgid=%d/%d\n", sp, current->pid, current->tgid);
+ return 0;
+
+}
+
unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc,
unsigned long sp)
{
@@ -2603,9 +2630,7 @@ unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc,
struct uprobe_kimg *uk;
struct uprobe_task *utask;
struct uprobe_process *uproc;
- unsigned long trampoline_addr;
struct hlist_node *r;
- struct uretprobe_instance *ret_inst;
if (!ri)
return 0;
@@ -2623,25 +2648,34 @@ unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc,
uproc = uk->ppt->uproc;
r = &ri->hlist;
}
- if (IS_ERR(uproc->uretprobe_trampoline_addr))
- return pc;
- trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr;
- if (pc != trampoline_addr)
+ return lookup_uretprobe(r, uproc, pc, sp);
+}
+
+EXPORT_SYMBOL_GPL(uprobe_get_pc);
+
+unsigned long uprobe_get_pc_task(struct task_struct *task, unsigned long pc,
+ unsigned long sp)
+{
+ struct uprobe_task *utask;
+ struct uprobe_process *uproc;
+ unsigned long result;
+
+ utask = uprobe_find_utask(task);
+ if (!utask) {
return pc;
- hlist_for_each_entry_from(ret_inst, r, hlist) {
- if (ret_inst->ret_addr == trampoline_addr)
- continue;
- /* First handler with a stack pointer lower than the
- address (or equal) must be the one. */
- if (ret_inst->sp == sp || compare_stack_ptrs(ret_inst->sp, sp))
- return ret_inst->ret_addr;
+ } else if (current == task && utask->active_probe) {
+ /* everything's locked. */
+ return uprobe_get_pc(GET_PC_URETPROBE_NONE, pc, sp);
}
- printk(KERN_ERR "Original return address for trampoline not found at "
- "0x%lx pid/tgid=%d/%d\n", sp, current->pid, current->tgid);
- return 0;
+ uproc = utask->uproc;
+ down_read(&uproc->rwsem);
+ result = lookup_uretprobe(utask->uretprobe_instances.first, uproc, pc,
+ sp);
+ up_read(&uproc->rwsem);
+ return result;
}
-EXPORT_SYMBOL_GPL(uprobe_get_pc);
+EXPORT_SYMBOL_GPL(uprobe_get_pc_task);
#else /* ! CONFIG_URETPROBES */
diff --git a/runtime/uprobes/uprobes.h b/runtime/uprobes/uprobes.h
index 80725f23..2096ff20 100644
--- a/runtime/uprobes/uprobes.h
+++ b/runtime/uprobes/uprobes.h
@@ -107,6 +107,12 @@ extern void unmap_uretprobe(struct uretprobe *rp);
extern unsigned long uprobe_get_pc(struct uretprobe_instance *ri,
unsigned long pc,
unsigned long sp);
+/*
+ * This version will do the mapping for an arbitrary task.
+ */
+extern unsigned long uprobe_get_pc_task(struct task_struct *task,
+ unsigned long pc,
+ unsigned long sp);
#ifdef UPROBES_IMPLEMENTATION
diff --git a/runtime/uprobes2/uprobes.c b/runtime/uprobes2/uprobes.c
index 623855ff..bf31b65d 100644
--- a/runtime/uprobes2/uprobes.c
+++ b/runtime/uprobes2/uprobes.c
@@ -2837,6 +2837,33 @@ static void uretprobe_set_trampoline(struct uprobe_process *uproc,
}
}
+static inline unsigned long lookup_uretprobe(struct hlist_node *r,
+ struct uprobe_process *uproc,
+ unsigned long pc,
+ unsigned long sp)
+{
+ struct uretprobe_instance *ret_inst;
+ unsigned long trampoline_addr;
+
+ if (IS_ERR(uproc->uretprobe_trampoline_addr))
+ return pc;
+ trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr;
+ if (pc != trampoline_addr)
+ return pc;
+ hlist_for_each_entry_from(ret_inst, r, hlist) {
+ if (ret_inst->ret_addr == trampoline_addr)
+ continue;
+ /* First handler with a stack pointer lower than the
+ address (or equal) must be the one. */
+ if (ret_inst->sp == sp || compare_stack_ptrs(ret_inst->sp, sp))
+ return ret_inst->ret_addr;
+ }
+ printk(KERN_ERR "Original return address for trampoline not found at "
+ "0x%lx pid/tgid=%d/%d\n", sp, current->pid, current->tgid);
+ return 0;
+
+}
+
unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc,
unsigned long sp)
{
@@ -2844,9 +2871,7 @@ unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc,
struct uprobe_kimg *uk;
struct uprobe_task *utask;
struct uprobe_process *uproc;
- unsigned long trampoline_addr;
struct hlist_node *r;
- struct uretprobe_instance *ret_inst;
if (!ri)
return 0;
@@ -2864,26 +2889,34 @@ unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc,
uproc = uk->ppt->uproc;
r = &ri->hlist;
}
- if (IS_ERR(uproc->uretprobe_trampoline_addr))
- return pc;
- trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr;
- if (pc != trampoline_addr)
- return pc;
- hlist_for_each_entry_from(ret_inst, r, hlist) {
- if (ret_inst->ret_addr == trampoline_addr)
- continue;
- /* First handler with a stack pointer lower than the
- address (or equal) must be the one. */
- if (ret_inst->sp == sp || compare_stack_ptrs(ret_inst->sp, sp))
- return ret_inst->ret_addr;
- }
- printk(KERN_ERR "Original return address for trampoline not found at "
- "0x%lx pid/tgid=%d/%d\n", sp, current->pid, current->tgid);
- return 0;
+ return lookup_uretprobe(r, uproc, pc, sp);
}
EXPORT_SYMBOL_GPL(uprobe_get_pc);
+unsigned long uprobe_get_pc_task(struct task_struct *task, unsigned long pc,
+ unsigned long sp)
+{
+ struct uprobe_task *utask;
+ struct uprobe_process *uproc;
+ unsigned long result;
+
+ utask = uprobe_find_utask(task);
+ if (!utask) {
+ return pc;
+ } else if (current == task && utask->active_probe) {
+ /* everything's locked. */
+ return uprobe_get_pc(GET_PC_URETPROBE_NONE, pc, sp);
+ }
+ uproc = utask->uproc;
+ down_read(&uproc->rwsem);
+ result = lookup_uretprobe(utask->uretprobe_instances.first, uproc, pc,
+ sp);
+ up_read(&uproc->rwsem);
+ return result;
+}
+
+EXPORT_SYMBOL_GPL(uprobe_get_pc_task);
#else /* ! CONFIG_URETPROBES */
static void uretprobe_handle_entry(struct uprobe *u, struct pt_regs *regs,
diff --git a/runtime/uprobes2/uprobes.h b/runtime/uprobes2/uprobes.h
index c4e1f59c..b48a9832 100644
--- a/runtime/uprobes2/uprobes.h
+++ b/runtime/uprobes2/uprobes.h
@@ -100,6 +100,12 @@ extern void unmap_uretprobe(struct uretprobe *rp);
extern unsigned long uprobe_get_pc(struct uretprobe_instance *ri,
unsigned long pc,
unsigned long sp);
+/*
+ * This version will do the mapping for an arbitrary task.
+ */
+extern unsigned long uprobe_get_pc_task(struct task_struct *task,
+ unsigned long pc,
+ unsigned long sp);
#ifdef UPROBES_IMPLEMENTATION