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>
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)
/* 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;
}
ri->rp = rp;
ri->task = current;
+#ifdef CONFIG_ARM
+ ri->preload_thumb = 0;
+#endif
if (rp->entry_handler)
rp->entry_handler(ri, regs);
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 */
};