[FEAUTRE] ARM branches instrumentation
authorDmitry Kovalenko <d.kovalenko@samsung.com>
Tue, 25 Jun 2013 11:29:18 +0000 (15:29 +0400)
committerDmitry Kovalenko <d.kovalenko@samsung.com>
Tue, 25 Jun 2013 11:29:18 +0000 (15:29 +0400)
kprobe/arch/asm-arm/dbi_kprobes.c
kprobe/arch/asm-arm/dbi_kprobes.h
kprobe/arch/asm-arm/dbi_kprobes_arm.S
kprobe/arch/asm-arm/dbi_kprobes_arm.h

index 36b9e41..898dd1e 100644 (file)
@@ -439,10 +439,6 @@ static int arch_check_insn_arm (struct arch_specific_insn *ainsn)
                ARM_INSN_MATCH (AUNDEF, ainsn->insn_arm[0]) ||
                ARM_INSN_MATCH (SWI, ainsn->insn_arm[0]) ||
                ARM_INSN_MATCH (BREAK, ainsn->insn_arm[0]) ||
-               ARM_INSN_MATCH (BL, ainsn->insn_arm[0]) ||
-               ARM_INSN_MATCH (BLX1, ainsn->insn_arm[0]) ||
-               ARM_INSN_MATCH (BLX2, ainsn->insn_arm[0]) ||
-               ARM_INSN_MATCH (BX, ainsn->insn_arm[0]) ||
                ARM_INSN_MATCH (BXJ, ainsn->insn_arm[0]))
        {
                DBPRINTF ("Bad insn arch_check_insn_arm: %lx\n", ainsn->insn_arm[0]);
@@ -857,15 +853,36 @@ int arch_copy_trampoline_arm_uprobe (struct kprobe *p, struct task_struct *task,
        insns[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
        insns[7] = (kprobe_opcode_t) (p->addr + 1);
 
-       // B
-       if(ARM_INSN_MATCH (B, ainsn.insn_arm[0]))
-       {
-               memcpy (insns, pc_dep_insn_execbuf, sizeof (insns));
+       if (ARM_INSN_MATCH(B, ainsn.insn_arm[0]) &&    /* B */
+           !ARM_INSN_MATCH(BLX1, ainsn.insn_arm[0])) {
+               /* B check can be false positive on BLX1 instruction */
+               memcpy(insns, b_cond_insn_execbuf, sizeof (insns));
                insns[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
-               insns[6] = (kprobe_opcode_t) (p->addr + 2);
-               insns[7] = get_addr_b(p->opcode, p->addr);
+               insns[0] |= insn[0] & 0xf0000000;
+               insns[6] = get_addr_b(p->opcode, p->addr);
+               insns[7] = (kprobe_opcode_t) (p->addr + 1);
+       } else if (ARM_INSN_MATCH(BX, ainsn.insn_arm[0]) ||     // BX, BLX (Rm)
+                  ARM_INSN_MATCH(BLX2, ainsn.insn_arm[0])) {
+               memcpy(insns, b_r_insn_execbuf, sizeof (insns));
+               insns[0] = insn[0];
+               insns[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
+               insns[7] = (kprobe_opcode_t) (p->addr + 1);
+       } else if (ARM_INSN_MATCH(BLX1, ainsn.insn_arm[0])) {   // BL, BLX (Off)
+               memcpy(insns, blx_off_insn_execbuf, sizeof(insns));
+               insns[0] |= 0xe0000000;
+               insns[1] |= 0xe0000000;
+               insns[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
+               insns[6] = get_addr_b(p->opcode, p->addr) +
+                       2 * (p->opcode & 01000000) + 1; /* jump to thumb */
+               insns[7] = (kprobe_opcode_t) (p->addr + 1);
+       } else if (ARM_INSN_MATCH(BL, ainsn.insn_arm[0])){      // BL
+               memcpy(insns, blx_off_insn_execbuf, sizeof(insns));
+               insns[0] |= insn[0] & 0xf0000000;
+               insns[1] |= insn[0] & 0xf0000000;
+               insns[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
+               insns[6] = get_addr_b(p->opcode, p->addr);
+               insns[7] = (kprobe_opcode_t) (p->addr + 1);
        }
-
        DBPRINTF ("arch_prepare_uprobe: to %p - %lx %lx %lx %lx %lx %lx %lx %lx %lx",
                        p->ainsn.insn_arm, insns[0], insns[1], insns[2], insns[3], insns[4],
                        insns[5], insns[6], insns[7], insns[8]);
index 7f6f59e..1314df3 100644 (file)
@@ -162,8 +162,8 @@ static inline int dbi_fp_backtrace(struct task_struct *task, unsigned long *buf,
 # define PTRN_ARM_INSN_AUNDEF           0x07F000F0
 
 // branches
-# define MASK_ARM_INSN_B               0x0E000000              // xxxx111xxxxxxxxxxxxxxxxxxxxxxxxx
-# define PTRN_ARM_INSN_B               0x0A000000              // cccc101xxxxxxxxxxxxxxxxxxxxxxxxx
+# define MASK_ARM_INSN_B               0x0F000000              // xxxx1111xxxxxxxxxxxxxxxxxxxxxxxx
+# define PTRN_ARM_INSN_B               0x0A000000              // cccc1010xxxxxxxxxxxxxxxxxxxxxxxx
 
 # define MASK_THUMB_INSN_B1            0xF000                  // 1111xxxxxxxxxxxx
 # define PTRN_THUMB_INSN_B1            0xD000                  // 1101xxxxxxxxxxxx                                             // b<cond> label
@@ -180,7 +180,7 @@ static inline int dbi_fp_backtrace(struct task_struct *task, unsigned long *buf,
 # define MASK_THUMB2_INSN_B2           0xD000F800              // 11x1xxxxxxxxxxxx 11111xxxxxxxxxxx                            // swapped
 # define PTRN_THUMB2_INSN_B2           0x9000F000              // 10x1xxxxxxxxxxxx 11110xxxxxxxxxxx                            // swapped
 
-# define MASK_ARM_INSN_BL              0x0E000000              // xxxx111xxxxxxxxxxxxxxxxxxxxxxxxx
+# define MASK_ARM_INSN_BL              0x0F000000              // xxxx1111xxxxxxxxxxxxxxxxxxxxxxxx
 # define PTRN_ARM_INSN_BL              0x0B000000              // cccc1011xxxxxxxxxxxxxxxxxxxxxxxx
 
 //# define MASK_THUMB_INSN_BL          0xF800                  // 11111xxxxxxxxxxx
@@ -190,8 +190,8 @@ static inline int dbi_fp_backtrace(struct task_struct *task, unsigned long *buf,
 # define MASK_THUMB2_INSN_BL           0xD000F800              // 11x1xxxxxxxxxxxx 11111xxxxxxxxxxx                            // swapped
 # define PTRN_THUMB2_INSN_BL           0xD000F000              // 11x1xxxxxxxxxxxx 11110xxxxxxxxxxx                            // bl imm  swapped
 
-# define MASK_ARM_INSN_BLX1            0xFF000000              // 11111111xxxxxxxxxxxxxxxxxxxxxxxx
-# define PTRN_ARM_INSN_BLX1            0xFA000000              // 11111011xxxxxxxxxxxxxxxxxxxxxxxx
+# define MASK_ARM_INSN_BLX1            0xFE000000              // 1111111axxxxxxxxxxxxxxxxxxxxxxxx
+# define PTRN_ARM_INSN_BLX1            0xFA000000              // 1111101axxxxxxxxxxxxxxxxxxxxxxxx
 
 //# define MASK_THUMB_INSN_BLX1                0xF800                  // 11111xxxxxxxxxxx                                             / blx imm
 //# define PTRN_THUMB_INSN_BLX1                0xF000                  // 11101xxxxxxxxxxx
index 5b4c7bc..e483177 100644 (file)
@@ -29,6 +29,35 @@ pc_dep_insn_execbuf:
                nop                     // stored PC
                nop                     // stored PC-4 (next insn addr)
 
+       .global b_r_insn_execbuf
+b_r_insn_execbuf:
+               nop                     // bx, blx (Rm)
+               ldr     pc, np1
+               nop
+               nop
+               nop
+               nop                     // retbreak
+               nop
+np1:           nop                     // stored PC-4 (next insn addr)
 
-
-
+       .global b_cond_insn_execbuf
+b_cond_insn_execbuf:
+               beq     condway
+               ldr     pc, np2
+condway:       ldr     pc, bd2
+               nop
+               nop
+               nop                     // retbreak
+bd2:           nop                     // branch displacement
+np2:           nop                     // stored PC-4 (next insn addr)
+
+               .global blx_off_insn_execbuf
+blx_off_insn_execbuf:
+               ldreq   lr, bd3
+               blxeq   lr
+               ldr     pc, np3
+               nop
+               nop
+               nop                     // retbreak
+bd3:           nop                     // branch displacement
+np3:           nop                     // stored PC-4 (next insn addr)
index 914303a..b60ce7c 100644 (file)
@@ -1,2 +1,5 @@
 void gen_insn_execbuf(void);
 void pc_dep_insn_execbuf(void);
+void b_r_insn_execbuf(void);
+void b_cond_insn_execbuf(void);
+void blx_off_insn_execbuf(void);