summaryrefslogtreecommitdiffstats
path: root/runtime/uprobes2
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2010-01-07 14:00:49 -0500
committerDave Brolley <brolley@redhat.com>2010-01-07 14:00:49 -0500
commitaf7b183c32c627b1934e9be2d028d7c4ff1a1d2e (patch)
treea1670ad0f02f3ebb47ef2aca648ff7d6afc4e5db /runtime/uprobes2
parenta0626e2e2ea13b6fc974157fb71fe6d48f4c7ec0 (diff)
parent4bd4d40e19f7ba203d5e380965210181648f560a (diff)
downloadsystemtap-steved-af7b183c32c627b1934e9be2d028d7c4ff1a1d2e.tar.gz
systemtap-steved-af7b183c32c627b1934e9be2d028d7c4ff1a1d2e.tar.xz
systemtap-steved-af7b183c32c627b1934e9be2d028d7c4ff1a1d2e.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
Diffstat (limited to 'runtime/uprobes2')
-rw-r--r--runtime/uprobes2/uprobes.c71
-rw-r--r--runtime/uprobes2/uprobes.h4
2 files changed, 44 insertions, 31 deletions
diff --git a/runtime/uprobes2/uprobes.c b/runtime/uprobes2/uprobes.c
index 02941e26..623855ff 100644
--- a/runtime/uprobes2/uprobes.c
+++ b/runtime/uprobes2/uprobes.c
@@ -2840,37 +2840,46 @@ static void uretprobe_set_trampoline(struct uprobe_process *uproc,
unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc,
unsigned long sp)
{
- struct uretprobe *rp;
- struct uprobe_kimg *uk;
- struct uprobe_process *uproc;
- unsigned long trampoline_addr;
- struct hlist_node *r;
- struct uretprobe_instance *ret_inst;
-
- if (!ri)
- return 0;
- rp = ri->rp;
- uk = (struct uprobe_kimg *)rp->u.kdata;
- if (!uk)
- return 0;
- uproc = uk->ppt->uproc;
- if (IS_ERR(uproc->uretprobe_trampoline_addr))
- return pc;
- trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr;
- if (pc != trampoline_addr)
- return pc;
- r = &ri->hlist;
- 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;
+ struct uretprobe *rp;
+ 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;
+ if (ri == GET_PC_URETPROBE_NONE) {
+ utask = uprobe_find_utask(current);
+ if (!utask)
+ return 0;
+ uproc = utask->uproc;
+ r = utask->uretprobe_instances.first;
+ } else {
+ rp = ri->rp;
+ uk = (struct uprobe_kimg *)rp->u.kdata;
+ if (!uk)
+ return 0;
+ 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;
}
EXPORT_SYMBOL_GPL(uprobe_get_pc);
diff --git a/runtime/uprobes2/uprobes.h b/runtime/uprobes2/uprobes.h
index 5d2a826e..c4e1f59c 100644
--- a/runtime/uprobes2/uprobes.h
+++ b/runtime/uprobes2/uprobes.h
@@ -92,7 +92,11 @@ extern void unmap_uretprobe(struct uretprobe *rp);
* Given a program counter, translate it back to the original address
* if it is the address of the trampoline. sp is the stack pointer for
* the frame that corresponds to the address.
+ *
+ * When not called from a uretprobe hander, pass GET_PC_URETPROBE_NONE
+ * instead of a uretprobe_instance.
*/
+#define GET_PC_URETPROBE_NONE ((struct uretprobe_instance *)-1L)
extern unsigned long uprobe_get_pc(struct uretprobe_instance *ri,
unsigned long pc,
unsigned long sp);