{
struct pd_t *pd = __get_process_data(ri->rp);
struct hd_t *hd;
+ unsigned long old_pc = swap_get_instr_ptr(regs);
unsigned long flags = get_preload_flags(current);
struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
unsigned long vaddr = 0;
out_set_orig:
preload_set_priv_origin(ri, vaddr);
- return 0;
+ /* PC change check */
+ return old_pc != swap_get_instr_ptr(regs);
}
static void __do_preload_ret(struct uretprobe_instance *ri, struct hd_t *hd)
struct pt_regs *regs,
unsigned long vaddr)
{
- ri->rp->up.ss_addr[smp_processor_id()] = (kprobe_opcode_t *)vaddr;
+ swap_set_instr_ptr(regs, vaddr);
#ifdef CONFIG_ARM
if (thumb_mode(regs)) {
int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs)
{
struct ujprobe *jp = container_of(p, struct ujprobe, up);
-
- uprobe_pre_entry_handler_t pre_entry =
- (uprobe_pre_entry_handler_t)jp->pre_entry;
entry_point_t entry = (entry_point_t)jp->entry;
- if (pre_entry) {
- p->ss_addr[smp_processor_id()] = (uprobe_opcode_t *)
- pre_entry(jp->priv_arg, regs);
- }
-
if (entry) {
entry(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2,
regs->ARM_r3, regs->ARM_r4, regs->ARM_r5);
*/
static void arch_prepare_singlestep(struct uprobe *p, struct pt_regs *regs)
{
- int cpu = smp_processor_id();
-
- if (p->ss_addr[cpu]) {
- regs->ARM_pc = (unsigned long)p->ss_addr[cpu];
- p->ss_addr[cpu] = NULL;
+ if (p->ainsn.handler) {
+ regs->ARM_pc += 4;
+ p->ainsn.handler(p->opcode, &p->ainsn, regs);
} else {
- if (p->ainsn.handler) {
- regs->ARM_pc += 4;
- p->ainsn.handler(p->opcode, &p->ainsn, regs);
- } else {
- regs->ARM_pc = (unsigned long)p->ainsn.insn;
- }
+ regs->ARM_pc = (unsigned long)p->ainsn.insn;
}
}
int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs)
{
struct ujprobe *jp = container_of(p, struct ujprobe, up);
- uprobe_pre_entry_handler_t pre_entry =
- (uprobe_pre_entry_handler_t)jp->pre_entry;
entry_point_t entry = (entry_point_t)jp->entry;
unsigned long args[6];
"failed to read user space func arguments %lx!\n",
regs->sp + 4);
- if (pre_entry)
- p->ss_addr[smp_processor_id()] = (uprobe_opcode_t *)
- pre_entry(jp->priv_arg, regs);
-
if (entry)
entry(args[0], args[1], args[2], args[3], args[4], args[5]);
else
return;
}
-static bool prepare_ss_addr(struct uprobe *p, struct pt_regs *regs)
+static void prepare_tramp(struct uprobe *p, struct pt_regs *regs)
{
- unsigned long *ss_addr = (long *)&p->ss_addr[smp_processor_id()];
-
- if (*ss_addr) {
- regs->ip = *ss_addr;
- *ss_addr = 0;
- return true;
- } else {
- regs->ip = (unsigned long)p->ainsn.insn;
- return false;
- }
+ regs->ip = (unsigned long)p->ainsn.insn;
}
static void prepare_ss(struct pt_regs *regs)
return 1;
} else {
if (!p->pre_handler || !p->pre_handler(p, regs)) {
- if (p->ainsn.boostable == 1 && !p->post_handler) {
- prepare_ss_addr(p, regs);
+ prepare_tramp(p, regs);
+ if (p->ainsn.boostable == 1 && !p->post_handler)
return 1;
- }
- if (prepare_ss_addr(p, regs) == false) {
- set_current_probe(p);
- prepare_ss(regs);
- }
+ set_current_probe(p);
+ prepare_ss(regs);
}
}
#endif
struct uretprobe_instance *ri;
unsigned long flags;
+ int ret = 0;
#ifdef CONFIG_ARM
if (noret)
/* TODO: test - remove retprobe after func entry but before its exit */
ri = get_free_urp_inst(rp);
if (ri != NULL) {
- int ret;
+ int err;
ri->rp = rp;
ri->task = current;
#endif
if (rp->entry_handler)
- rp->entry_handler(ri, regs);
+ ret = rp->entry_handler(ri, regs);
- ret = arch_prepare_uretprobe(ri, regs);
+ err = arch_prepare_uretprobe(ri, regs);
add_urp_inst(ri);
- if (ret) {
+ if (err) {
recycle_urp_inst(ri);
++rp->nmissed;
}
spin_unlock_irqrestore(&uretprobe_lock, flags);
- return 0;
+ return ret;
}
/**
uprobe_break_handler_t break_handler;
/** Saved opcode (which has been replaced with breakpoint).*/
uprobe_opcode_t opcode;
- /** Override single-step target address, may be used to redirect
- * control-flow to arbitrary address after probe point without
- * invocation of original instruction; useful for functions
- * replacement. If jprobe.entry should return address of function or
- * NULL if original function should be called.
- * Not supported for X86, not tested for MIPS. */
- uprobe_opcode_t *ss_addr[NR_CPUS];
#ifdef CONFIG_ARM
/** Safe/unsafe to use probe on ARM.*/
unsigned safe_arm:1;