/* * Singlestep is implemented by disabling the current kprobe and setting one * on the next instruction, following branches. Two probes are set if the * branch is conditional. */ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t *addr = NULL; saved_current_opcode.addr = (kprobe_opcode_t *) (regs->pc); addr = saved_current_opcode.addr; if (p != NULL) { arch_disarm_kprobe(p); if (OPCODE_JSR(p->opcode) || OPCODE_JMP(p->opcode)) { unsigned int reg_nr = ((p->opcode >> 8) & 0x000F); saved_next_opcode.addr = (kprobe_opcode_t *) regs->regs[reg_nr]; } else if (OPCODE_BRA(p->opcode) || OPCODE_BSR(p->opcode)) {
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { __get_cpu_var(saved_current_opcode).addr = (kprobe_opcode_t *)regs->pc; if (p != NULL) { struct kprobe *op1, *op2; arch_disarm_kprobe(p); op1 = &__get_cpu_var(saved_next_opcode); op2 = &__get_cpu_var(saved_next_opcode2); if (OPCODE_JSR(p->opcode) || OPCODE_JMP(p->opcode)) { unsigned int reg_nr = ((p->opcode >> 8) & 0x000F); op1->addr = (kprobe_opcode_t *) regs->regs[reg_nr]; } else if (OPCODE_BRA(p->opcode) || OPCODE_BSR(p->opcode)) {
/* Analyzes the next instruction, to see where the program will go to when it runs. Returns the destination address. */ static long get_stepi_dest (void) { short op = *(short*)register_file.pc; long addr = register_file.pc + 2; /* BT, BT/S (untested!), BF and BF/S (untested!) TODO: test delay-slot branches */ if (((OPCODE_BT(op) || OPCODE_BTS(op)) && (register_file.sr & SR_T_BIT_MASK)) || ((OPCODE_BF(op) || OPCODE_BFS(op)) && !(register_file.sr & SR_T_BIT_MASK))) { /* we're taking the branch */ /* per 6.12 of the SH1/SH2 programming manual, PC+disp is address of the second instruction after the branch instruction, so we have to add 4 */ /* TODO: spend more time understanding this magic */ addr = register_file.pc + 4 + OPCODE_BTF_DISP(op); } /* BRA */ else if (OPCODE_BRA(op)) addr = register_file.pc + 4 + OPCODE_BRA_DISP(op); /* BRAF */ else if (OPCODE_BRAF(op)) addr = register_file.pc + 4 + register_file.r[OPCODE_BRAF_REG(op)]; /* BSR */ else if (OPCODE_BSR(op)) addr = register_file.pc + 4 + OPCODE_BSR_DISP(op); /* BSRF */ else if (OPCODE_BSRF(op)) addr = register_file.pc + 4 + register_file.r[OPCODE_BSRF_REG(op)]; /* JMP */ else if (OPCODE_JMP(op)) addr = register_file.r[OPCODE_JMP_REG(op)]; /* JSR */ else if (OPCODE_JSR(op)) addr = register_file.r[OPCODE_JSR_REG(op)]; /* RTS */ else if (OPCODE_RTS(op)) addr = register_file.pr; /* RTE */ else if (OPCODE_RTE(op)) addr = *(unsigned long*)(register_file.r[15]); /* TRAPA */ else if (OPCODE_TRAPA(op)) addr = register_file.vbr[OPCODE_TRAPA_DISP(op)]; return addr; }