[FIX] Preload: implement automatic ARM <-> THUMB mode switch 37/63537/1
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 24 Mar 2016 10:41:58 +0000 (13:41 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 24 Mar 2016 10:41:58 +0000 (13:41 +0300)
Previously it was implemented only for THUMB -> ARM case.
Now proper mode is determined automaticaly.

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

index 0071a7b..622621c 100644 (file)
@@ -113,12 +113,12 @@ static inline void __prepare_ujump(struct uretprobe_instance *ri,
                                   struct pt_regs *regs,
                                   unsigned long vaddr)
 {
-       swap_set_instr_ptr(regs, vaddr);
-
 #ifdef CONFIG_ARM
-       if (thumb_mode(regs))
-               ri->preload_thumb = 1;
+       ri->preload.use = true;
+       ri->preload.thumb = !!thumb_mode(regs);
 #endif /* CONFIG_ARM */
+
+       swap_set_instr_ptr(regs, vaddr);
 }
 
 static inline int __push(struct pt_regs *regs, void *buf, size_t len)
index 3809a4e..e99bc9b 100644 (file)
@@ -670,22 +670,23 @@ void arch_opcode_analysis_uretprobe(struct uretprobe *rp)
  */
 int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
+       unsigned long thumb, bp_offset;
+
+       thumb = ri->preload.use ? ri->preload.thumb : thumb_mode(regs);
+       bp_offset = thumb ? 0x1b : sizeof(long) * UPROBES_TRAMP_RET_BREAK_IDX;
+
+       /* save original return address */
        ri->ret_addr = (uprobe_opcode_t *)regs->ARM_lr;
+
+       /* replace return address with break point adddress */
+       regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + bp_offset;
+
+       /* save stack pointer address */
        ri->sp = (uprobe_opcode_t *)regs->ARM_sp;
 
        /* Set flag of current mode */
        ri->sp = (uprobe_opcode_t *)((long)ri->sp | !!thumb_mode(regs));
 
-       if (ri->preload_thumb) {
-               regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b;
-       } else {
-               if (thumb_mode(regs))
-                       regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b;
-               else
-                       regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn +
-                                                      UPROBES_TRAMP_RET_BREAK_IDX);
-       }
-
        return 0;
 }
 
index 6320e58..64cb4cd 100644 (file)
@@ -812,7 +812,7 @@ static int pre_handler_uretprobe(struct uprobe *p, struct pt_regs *regs)
                ri->rp = rp;
                ri->task = current;
 #ifdef CONFIG_ARM
-               ri->preload_thumb = 0;
+               ri->preload.use = false;
 #endif
 
                if (rp->entry_handler)
index 22ec4d2..ea43fe6 100644 (file)
@@ -195,7 +195,10 @@ struct uretprobe_instance {
         * 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;
+       struct {
+               unsigned use:1;
+               unsigned thumb:1;
+       } preload;
 #endif
        char data[0];                       /**< Custom data */
 };