On 10/13/2011 02:07 AM, Maneesh Soni wrote:
From: Maneesh Soni<manesoni@xxxxxxxxx> This patch provides support for kprobes on branch instructions. The branch instruction at the probed address is actually emulated and not executed out-of-line like other normal instructions. Instead the delay-slot instruction is copied and single stepped out of line. At the time of probe hit, the original branch instruction is evaluated and the target cp0_epc is computed similar to compute_retrun_epc(). It is also checked if the delay slot instruction can be skipped, which is true if there is a NOP in delay slot or branch is taken in case of branch likely instructions. Once the delay slot instruction is single stepped the normal execution resume with the cp0_epc updated the earlier computed cp0_epc as per the branch instructions.
I haven't tested it but...
Signed-off-by: Maneesh Soni<manesoni@xxxxxxxxx> --- arch/mips/include/asm/kprobes.h | 7 + arch/mips/kernel/kprobes.c | 341 +++++++++++++++++++++++++++++++++++---- 2 files changed, 320 insertions(+), 28 deletions(-)
[...]
+static int evaluate_branch_instruction(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { + union mips_instruction insn = p->opcode; + unsigned int dspcontrol; + long epc; + + epc = regs->cp0_epc; + if (epc& 3) + goto unaligned; + + if (p->ainsn.insn->word == 0) + kcb->flags |= SKIP_DELAYSLOT; + else + kcb->flags&= ~SKIP_DELAYSLOT; + + switch (insn.i_format.opcode) { + /* + * jr and jalr are in r_format format. + */ + case spec_op:
[...]
+ case bgtzl_op: + /* rt field assumed to be zero */ + if ((long)regs->regs[insn.i_format.rs]> 0) { + epc = epc + 4 + (insn.i_format.simmediate<< 2); + kcb->flags |= SKIP_DELAYSLOT; + } else + epc += 8; + regs->cp0_epc = epc; + break;
Where is the handling for: case cop1_op: #ifdef CONFIG_CPU_CAVIUM_OCTEON case lwc2_op: /* This is bbit0 on Octeon */ case ldc2_op: /* This is bbit032 on Octeon */ case swc2_op: /* This is bbit1 on Octeon */ case sdc2_op: /* This is bbit132 on Octeon */ #endif These are all defined in insn_has_delayslot() but not here.