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)
*/
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;
}
* 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 */
};