[FIX] Preload: thumb -> arm mode switch 24/43624/3
authorVasiliy Ulyanov <v.ulyanov@samsung.com>
Sun, 12 Jul 2015 13:35:52 +0000 (16:35 +0300)
committerDmitry Kovalenko <d.kovalenko@samsung.com>
Sun, 12 Jul 2015 17:44:05 +0000 (10:44 -0700)
We need to switch to arm if a probe is hit in thumb mode.
Currently all the preloaded userspace handlers are arm-only.

Change-Id: Ic7d3fc0d2b72b783d0f69efebd4fe8b9a0f8e712
Signed-off-by: Vasiliy Ulyanov <v.ulyanov@samsung.com>
preload/preload_module.c
uprobe/arch/arm/swap-asm/swap_uprobes.c
uprobe/swap_uprobes.c
uprobe/swap_uprobes.h

index b915b8d..ddd9cfa 100644 (file)
@@ -158,6 +158,13 @@ static inline void __prepare_ujump(struct uretprobe_instance *ri,
                                   unsigned long vaddr)
 {
        ri->rp->up.kp.ss_addr[smp_processor_id()] = (kprobe_opcode_t *)vaddr;
+
+#ifdef CONFIG_ARM
+       if (thumb_mode(regs)) {
+               regs->ARM_cpsr &= ~PSR_T_BIT;
+               ri->preload_thumb = 1;
+       }
+#endif /* CONFIG_ARM */
 }
 
 static inline int __push(struct pt_regs *regs, void *buf, size_t len)
index df572e2..c6921e2 100644 (file)
@@ -685,11 +685,15 @@ int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
        /* Set flag of current mode */
        ri->sp = (kprobe_opcode_t *)((long)ri->sp | !!thumb_mode(regs));
 
-       if (thumb_mode(regs))
+       if (ri->preload_thumb) {
                regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b;
-       else
-               regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn +
-                                              UPROBES_TRAMP_RET_BREAK_IDX);
+       } else {
+               if (thumb_mode(regs))
+                       regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b;
+               else
+                       regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn +
+                                                      UPROBES_TRAMP_RET_BREAK_IDX);
+       }
 
        return 0;
 }
index 45523d0..f9ad605 100644 (file)
@@ -772,6 +772,9 @@ static int pre_handler_uretprobe(struct kprobe *p, struct pt_regs *regs)
 
                ri->rp = rp;
                ri->task = current;
+#ifdef CONFIG_ARM
+               ri->preload_thumb = 0;
+#endif
 
                if (rp->entry_handler)
                        rp->entry_handler(ri, regs);
index 89ce372..1e3a9fd 100644 (file)
@@ -116,6 +116,14 @@ struct uretprobe_instance {
        kprobe_opcode_t *ret_addr;          /**< Return address */
        kprobe_opcode_t *sp;                /**< Pointer to stack */
        struct task_struct *task;           /**< Pointer to the task struct */
+#ifdef CONFIG_ARM
+       /* FIXME Preload: if this flag is set then ignore the thumb_mode(regs)
+        * check in arch_prepare_uretprobe and use thumb trampoline. For the
+        * moment we have to explicitly force arm mode when jumping to preload
+        * handlers but we need the correct (i.e. original) retprobe tramp set
+        * anyway. */
+       int preload_thumb;
+#endif
        char data[0];                       /**< Custom data */
 };