[IMPROVE] remove atomic dependence from uprobe handlers 86/55186/4
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Mon, 21 Dec 2015 18:30:46 +0000 (21:30 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Tue, 22 Dec 2015 11:52:35 +0000 (14:52 +0300)
Remove field ss_addr from uprobe struct. To exit from handler
to specifyed address, change PC/IP (ARM/x86) register to one and
handler return value to 1.

Change-Id: If5c70942e8614d374d4d52b9e80d75d202b24ea0
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
preload/preload_handlers.c
preload/preload_module.c
uprobe/arch/arm/swap-asm/swap_uprobes.c
uprobe/arch/x86/swap-asm/swap_uprobes.c
uprobe/swap_uprobes.c
uprobe/swap_uprobes.h

index fa4573c..578cebf 100644 (file)
@@ -171,6 +171,7 @@ static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
        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;
@@ -199,7 +200,8 @@ static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
 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)
index 7a408e5..e155149 100644 (file)
@@ -113,7 +113,7 @@ static inline void __prepare_ujump(struct uretprobe_instance *ri,
                                   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)) {
index d36f537..861aabd 100644 (file)
@@ -797,16 +797,8 @@ check_lr: /* check lr anyway */
 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);
@@ -929,18 +921,11 @@ static int urp_handler(struct pt_regs *regs, pid_t tgid)
  */
 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;
        }
 }
 
index f914aba..499f04d 100644 (file)
@@ -148,8 +148,6 @@ int arch_prepare_uprobe(struct uprobe *p)
 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];
 
@@ -166,10 +164,6 @@ int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs)
                       "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
@@ -450,18 +444,9 @@ no_change:
        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)
@@ -496,15 +481,12 @@ static int uprobe_handler(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);
                }
        }
 
index 6df1884..877dafe 100644 (file)
@@ -763,6 +763,7 @@ static int pre_handler_uretprobe(struct uprobe *p, struct pt_regs *regs)
 #endif
        struct uretprobe_instance *ri;
        unsigned long flags;
+       int ret = 0;
 
 #ifdef CONFIG_ARM
        if (noret)
@@ -776,7 +777,7 @@ static int pre_handler_uretprobe(struct uprobe *p, struct pt_regs *regs)
        /* 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;
@@ -785,11 +786,11 @@ static int pre_handler_uretprobe(struct uprobe *p, struct pt_regs *regs)
 #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;
                }
@@ -799,7 +800,7 @@ static int pre_handler_uretprobe(struct uprobe *p, struct pt_regs *regs)
 
        spin_unlock_irqrestore(&uretprobe_lock, flags);
 
-       return 0;
+       return ret;
 }
 
 /**
index e644524..d33b9e7 100644 (file)
@@ -84,13 +84,6 @@ struct uprobe {
        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;