diff options
author | Dave Brolley <brolley@redhat.com> | 2010-01-07 14:00:49 -0500 |
---|---|---|
committer | Dave Brolley <brolley@redhat.com> | 2010-01-07 14:00:49 -0500 |
commit | af7b183c32c627b1934e9be2d028d7c4ff1a1d2e (patch) | |
tree | a1670ad0f02f3ebb47ef2aca648ff7d6afc4e5db /runtime/uprobes | |
parent | a0626e2e2ea13b6fc974157fb71fe6d48f4c7ec0 (diff) | |
parent | 4bd4d40e19f7ba203d5e380965210181648f560a (diff) | |
download | systemtap-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/uprobes')
-rw-r--r-- | runtime/uprobes/uprobes.c | 71 | ||||
-rw-r--r-- | runtime/uprobes/uprobes.h | 4 |
2 files changed, 44 insertions, 31 deletions
diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c index cdb98707..5ccc7102 100644 --- a/runtime/uprobes/uprobes.c +++ b/runtime/uprobes/uprobes.c @@ -2599,37 +2599,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/uprobes/uprobes.h b/runtime/uprobes/uprobes.h index e888f9e8..80725f23 100644 --- a/runtime/uprobes/uprobes.h +++ b/runtime/uprobes/uprobes.h @@ -99,7 +99,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); |