static int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; void *addr = (void *)regs->pc; int ret = 0; pr_debug("kprobe_handler: kprobe_running=%p\n", kprobe_running()); /* * We don't want to be preempted for the entire * duration of kprobe processing */ preempt_disable(); /* Check that we're not recursing */ if (kprobe_running()) { p = get_kprobe(addr); if (p) { if (kprobe_status == KPROBE_HIT_SS) { printk("FIXME: kprobe hit while single-stepping!\n"); goto no_kprobe; } printk("FIXME: kprobe hit while handling another kprobe\n"); goto no_kprobe; } else { p = kprobe_running(); if (p->break_handler && p->break_handler(p, regs)) goto ss_probe; } /* If it's not ours, can't be delete race, (we hold lock). */ goto no_kprobe; } p = get_kprobe(addr); if (!p) goto no_kprobe; kprobe_status = KPROBE_HIT_ACTIVE; set_current_kprobe(p); if (p->pre_handler && p->pre_handler(p, regs)) /* handler has already set things up, so skip ss setup */ return 1; ss_probe: prepare_singlestep(p, regs); kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: preempt_enable_no_resched(); return ret; }
static int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; void *addr = (void *)regs->pc; int ret = 0; pr_debug("kprobe_handler: kprobe_running=%p\n", kprobe_running()); preempt_disable(); if (kprobe_running()) { p = get_kprobe(addr); if (p) { if (kprobe_status == KPROBE_HIT_SS) { printk("FIXME: kprobe hit while single-stepping!\n"); goto no_kprobe; } printk("FIXME: kprobe hit while handling another kprobe\n"); goto no_kprobe; } else { p = kprobe_running(); if (p->break_handler && p->break_handler(p, regs)) goto ss_probe; } goto no_kprobe; } p = get_kprobe(addr); if (!p) goto no_kprobe; kprobe_status = KPROBE_HIT_ACTIVE; set_current_kprobe(p); if (p->pre_handler && p->pre_handler(p, regs)) return 1; ss_probe: prepare_singlestep(p, regs); kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: preempt_enable_no_resched(); return ret; }
static int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; void *addr = (void *) regs->tpc; int ret = 0; struct kprobe_ctlblk *kcb; /* * We don't want to be preempted for the entire * duration of kprobe processing */ preempt_disable(); kcb = get_kprobe_ctlblk(); if (kprobe_running()) { p = get_kprobe(addr); if (p) { if (kcb->kprobe_status == KPROBE_HIT_SS) { regs->tstate = ((regs->tstate & ~TSTATE_PIL) | kcb->kprobe_orig_tstate_pil); goto no_kprobe; } /* We have reentered the kprobe_handler(), since * another probe was hit while within the handler. * We here save the original kprobes variables and * just single step on the instruction of the new probe * without calling any user handlers. */ save_previous_kprobe(kcb); set_current_kprobe(p, regs, kcb); kprobes_inc_nmissed_count(p); kcb->kprobe_status = KPROBE_REENTER; prepare_singlestep(p, regs, kcb); return 1; } else { if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) { /* The breakpoint instruction was removed by * another cpu right after we hit, no further * handling of this interrupt is appropriate */ ret = 1; goto no_kprobe; } p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) goto ss_probe; } goto no_kprobe; } p = get_kprobe(addr); if (!p) { if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) { /* * The breakpoint instruction was removed right * after we hit it. Another cpu has removed * either a probepoint or a debugger breakpoint * at this address. In either case, no further * handling of this interrupt is appropriate. */ ret = 1; } /* Not one of ours: let kernel handle it */ goto no_kprobe; } set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) return 1; ss_probe: prepare_singlestep(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: preempt_enable_no_resched(); return ret; }
static int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; void *addr = (void *) regs->tpc; int ret = 0; preempt_disable(); if (kprobe_running()) { /* We *are* holding lock here, so this is safe. * Disarm the probe we just hit, and ignore it. */ p = get_kprobe(addr); if (p) { if (kprobe_status == KPROBE_HIT_SS) { regs->tstate = ((regs->tstate & ~TSTATE_PIL) | current_kprobe_orig_tstate_pil); unlock_kprobes(); goto no_kprobe; } /* We have reentered the kprobe_handler(), since * another probe was hit while within the handler. * We here save the original kprobes variables and * just single step on the instruction of the new probe * without calling any user handlers. */ save_previous_kprobe(); set_current_kprobe(p, regs); p->nmissed++; kprobe_status = KPROBE_REENTER; prepare_singlestep(p, regs); return 1; } else { p = current_kprobe; if (p->break_handler && p->break_handler(p, regs)) goto ss_probe; } /* If it's not ours, can't be delete race, (we hold lock). */ goto no_kprobe; } lock_kprobes(); p = get_kprobe(addr); if (!p) { unlock_kprobes(); if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) { /* * The breakpoint instruction was removed right * after we hit it. Another cpu has removed * either a probepoint or a debugger breakpoint * at this address. In either case, no further * handling of this interrupt is appropriate. */ ret = 1; } /* Not one of ours: let kernel handle it */ goto no_kprobe; } set_current_kprobe(p, regs); kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) return 1; ss_probe: prepare_singlestep(p, regs); kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: preempt_enable_no_resched(); return ret; }
static inline int kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; unsigned int *addr = (unsigned int *)regs->nip; /* Check we're not actually recursing */ if (kprobe_running()) { /* We *are* holding lock here, so this is safe. Disarm the probe we just hit, and ignore it. */ p = get_kprobe(addr); if (p) { if (kprobe_status == KPROBE_HIT_SS) { regs->msr &= ~MSR_SE; regs->msr |= kprobe_saved_msr; unlock_kprobes(); goto no_kprobe; } disarm_kprobe(p, regs); ret = 1; } else { p = current_kprobe; if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } } /* If it's not ours, can't be delete race, (we hold lock). */ goto no_kprobe; } lock_kprobes(); p = get_kprobe(addr); if (!p) { unlock_kprobes(); if (*addr != BREAKPOINT_INSTRUCTION) { /* * PowerPC has multiple variants of the "trap" * instruction. If the current instruction is a * trap variant, it could belong to someone else */ kprobe_opcode_t cur_insn = *addr; if (IS_TW(cur_insn) || IS_TD(cur_insn) || IS_TWI(cur_insn) || IS_TDI(cur_insn)) goto no_kprobe; /* * The breakpoint instruction was removed right * after we hit it. Another cpu has removed * either a probepoint or a debugger breakpoint * at this address. In either case, no further * handling of this interrupt is appropriate. */ ret = 1; } /* Not one of ours: let kernel handle it */ goto no_kprobe; } kprobe_status = KPROBE_HIT_ACTIVE; current_kprobe = p; kprobe_saved_msr = regs->msr; if (p->pre_handler && p->pre_handler(p, regs)) /* handler has already set things up, so skip ss setup */ return 1; ss_probe: prepare_singlestep(p, regs); kprobe_status = KPROBE_HIT_SS; /* * This preempt_disable() matches the preempt_enable_no_resched() * in post_kprobe_handler(). */ preempt_disable(); return 1; no_kprobe: return ret; }