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]);
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]);
# 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
# 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
# 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