int __kprobes arch_prepare_kprobe(struct kprobe *p)
{ if ((unsignedlong)p->addr & 3UL) return -EINVAL;
p->ainsn.insn = get_insn_slot(); if (!p->ainsn.insn) return -ENOMEM;
/* * Set up new instructions. Second break instruction will * trigger call of parisc_kprobe_ss_handler().
*/
p->opcode = *p->addr;
p->ainsn.insn[0] = p->opcode;
p->ainsn.insn[1] = PARISC_KPROBES_BREAK_INSN2;
flush_insn_slot(p); return 0;
}
void __kprobes arch_remove_kprobe(struct kprobe *p)
{ if (!p->ainsn.insn) return;
kcb = get_kprobe_ctlblk();
p = get_kprobe((unsignedlong *)regs->iaoq[0]);
if (!p) {
preempt_enable_no_resched(); return 0;
}
if (kprobe_running()) { /* * We have reentered the kprobe_handler, since another kprobe * was hit while within the handler, we save the original * kprobes and single step on the instruction of the new probe * without calling any user handlers to avoid recursive * kprobes.
*/
save_previous_kprobe(kcb);
set_current_kprobe(p);
kprobes_inc_nmissed_count(p);
setup_singlestep(p, kcb, regs);
kcb->kprobe_status = KPROBE_REENTER; return 1;
}
/* 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 - which means user handler setup registers to exit * to another instruction, we must skip the single stepping.
*/
if (regs->iaoq[0] != (unsignedlong)p->ainsn.insn+4) return 0;
/* restore back original saved kprobe variables and continue */ if (kcb->kprobe_status == KPROBE_REENTER) {
restore_previous_kprobe(kcb); return 1;
}
/* for absolute branch instructions we can copy iaoq_b. for relative * branch instructions we need to calculate the new address based on the * difference between iaoq_f and iaoq_b. We cannot use iaoq_b without * modifications because it's based on our ainsn.insn address.
*/
if (p->post_handler)
p->post_handler(p, regs, 0);
switch (regs->iir >> 26) { case 0x38: /* BE */ case 0x39: /* BE,L */ case 0x3a: /* BV */ case 0x3b: /* BVE */ /* for absolute branches, regs->iaoq[1] has already the right * address
*/
regs->iaoq[0] = kcb->iaoq[1]; break; default:
regs->iaoq[0] = kcb->iaoq[1];
regs->iaoq[1] = regs->iaoq[0] + 4; break;
}
kcb->kprobe_status = KPROBE_HIT_SSDONE;
reset_current_kprobe(); return 1;
}
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.