/* Remove retprobe if first insn overwrites lr */
if (THUMB_INSN_MATCH(BLX2, p->kp.opcode) ||
THUMB2_INSN_MATCH(BL, p->kp.opcode) ||
- THUMB2_INSN_MATCH(BLX1, p->kp.opcode)){
- p->kp.pre_handler = NULL;
- }
+ THUMB2_INSN_MATCH(BLX1, p->kp.opcode))
+ p->thumb_noret = 0;
+ else
+ p->thumb_noret = 1;
+
+ if (ARM_INSN_MATCH(BLX1, p->kp.opcode) ||
+ ARM_INSN_MATCH(BLX2, p->kp.opcode) ||
+ ARM_INSN_MATCH(BL, p->kp.opcode))
+ p->arm_noret = 0;
+ else
+ p->arm_noret = 1;
return 0;
}
unsigned long flags = 0;
DBPRINTF ("START\n");
+ if (p && p->tgid) { /* Userspace */
+ if (unlikely(thumb_mode(regs))) {
+ if (!rp->thumb_noret)
+ return 0;
+ } else if (!rp->arm_noret)
+ return 0;
+ }
+
/*TODO: consider to only swap the RA after the last pre_handler fired */
spin_lock_irqsave (&kretprobe_lock, flags);
if (!rp->disarm)
int disarm;
struct hlist_head free_instances;
struct hlist_head used_instances;
+
+#ifdef CONFIG_ARM
+ // probe with noreturn (bl,blx)
+ unsigned arm_noret:1;
+ unsigned thumb_noret:1;
+#endif
+
};
struct kretprobe_instance