After single-stepping an instruction that does not branch, execution resumes at the saved next PC, followed by the probed address plus 8. For an instruction in the delay slot of a taken branch the saved next PC is the branch target, so after the target execution goes back to the probed address plus 8 instead of continuing at the target plus 4.
Use the saved next PC plus 4, which equals the probed address plus 8 for any other instruction. Link: https://github.com/sparclinux/issues/issues/110 Signed-off-by: Stian Halseth <[email protected]> --- arch/sparc/kernel/kprobes.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/sparc/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c index 38e6d9b51a207..327d83188a978 100644 --- a/arch/sparc/kernel/kprobes.c +++ b/arch/sparc/kernel/kprobes.c @@ -211,13 +211,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * */ static unsigned long __kprobes relbranch_fixup(u32 insn, struct kprobe *p, - struct pt_regs *regs) + struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { unsigned long real_pc = (unsigned long) p->addr; /* Branch not taken, no mods necessary. */ if (regs->tnpc == regs->tpc + 0x4UL) - return real_pc + 0x8UL; + return kcb->kprobe_orig_tnpc + 0x4UL; /* The cases are call and the branches BPcc, Bicc, BPr, FBPfcc * and FBfcc. @@ -294,7 +295,7 @@ static void __kprobes resume_execution(struct kprobe *p, { u32 insn = p->ainsn.insn[0]; - regs->tnpc = relbranch_fixup(insn, p, regs); + regs->tnpc = relbranch_fixup(insn, p, regs, kcb); /* This assignment must occur after relbranch_fixup() */ regs->tpc = kcb->kprobe_orig_tnpc; -- 2.43.0
