/* * Interrupts need to be disabled before single-step mode is set, and not * reenabled until after single-step mode ends. * Without disabling interrupt on local CPU, there is a chance of * interrupt occurrence in the period of exception return and start of * out-of-line single-step, that result in wrongly single stepping * into the interrupt handler.
*/ staticvoid __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb, struct pt_regs *regs)
{
kcb->saved_status = regs->status;
regs->status &= ~SR_SPIE;
}
/* restore back original saved kprobe variables and continue */ if (kcb->kprobe_status == KPROBE_REENTER) {
restore_previous_kprobe(kcb); return;
}
/* call post handler */
kcb->kprobe_status = KPROBE_HIT_SSDONE; if (cur->post_handler) { /* post_handler can hit breakpoint and single step * again, so we enable D-flag for recursive exception.
*/
cur->post_handler(cur, regs, 0);
}
switch (kcb->kprobe_status) { case KPROBE_HIT_SS: case KPROBE_REENTER: /* * We are here because the instruction being single * stepped caused a page fault. We reset the current * kprobe and the ip points back to the probe address * and allow the page fault handler to continue as a * normal page fault.
*/
regs->epc = (unsignedlong) cur->addr;
BUG_ON(!instruction_pointer(regs));
break; case KPROBE_HIT_ACTIVE: case KPROBE_HIT_SSDONE: /* * In case the user-specified fault handler returned * zero, try to fix up.
*/ if (fixup_exception(regs)) return 1;
} return 0;
}
if (p) { if (cur_kprobe) { if (reenter_kprobe(p, regs, kcb)) returntrue;
} else { /* Probe hit */
set_current_kprobe(p);
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
/* * If we have no pre-handler or it returned 0, we * continue with normal processing. If we have a * pre-handler and it returned non-zero, it will * modify the execution path and no need to single * stepping. Let's just reset current kprobe and exit. * * pre_handler can hit a breakpoint and can step thru * before return.
*/ if (!p->pre_handler || !p->pre_handler(p, regs))
setup_singlestep(p, regs, kcb, 0); else
reset_current_kprobe();
} returntrue;
}
/* * 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. * Return back to original instruction, and continue.
*/ returnfalse;
}
if (cur && (kcb->kprobe_status & (KPROBE_HIT_SS | KPROBE_REENTER)) &&
((unsignedlong)&cur->ainsn.api.insn[0] + GET_INSN_LENGTH(cur->opcode) == addr)) {
kprobes_restore_local_irqflag(kcb, regs);
post_kprobe_handler(cur, kcb, regs); returntrue;
} /* not ours, kprobes should ignore it */ returnfalse;
}
/* * Provide a blacklist of symbols identifying ranges which cannot be kprobed. * This blacklist is exposed to userspace via debugfs (kprobes/blacklist).
*/ int __init arch_populate_kprobe_blacklist(void)
{ int ret;
ret = kprobe_add_area_blacklist((unsignedlong)__irqentry_text_start,
(unsignedlong)__irqentry_text_end); return ret;
}
int __kprobes arch_trampoline_kprobe(struct kprobe *p)
{ return 0;
}
int __init arch_init_kprobes(void)
{ return 0;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.