/* *insn_has_ll_or_scfunctioncheckswhetherinstructionisllorsc *one;puttingbreakpointontopofatomicll/scpairisbadidea; *soweneedtopreventitandrefusekprobesinsertionforsuch *instructions;cannotdomuchaboutbreakpointinthemiddleof *ll/scpair;itisuptousertoavoidthoseplaces
*/ staticint insn_has_ll_or_sc(union mips_instruction insn)
{ int ret = 0;
switch (insn.i_format.opcode) { case ll_op: case lld_op: case sc_op: case scd_op:
ret = 1; break; default: break;
} return ret;
}
NOKPROBE_SYMBOL(insn_has_ll_or_sc);
int arch_prepare_kprobe(struct kprobe *p)
{ union mips_instruction insn; union mips_instruction prev_insn; int ret = 0;
insn = p->addr[0];
if (insn_has_ll_or_sc(insn)) {
pr_notice("Kprobes for ll and sc instructions are not supported\n");
ret = -EINVAL; goto out;
}
if (copy_from_kernel_nofault(&prev_insn, p->addr - 1, sizeof(mips_instruction)) == 0 &&
insn_has_delayslot(prev_insn)) {
pr_notice("Kprobes for branch delayslot are not supported\n");
ret = -EINVAL; goto out;
}
if (__insn_is_compact_branch(insn)) {
pr_notice("Kprobes for compact branches are not supported\n");
ret = -EINVAL; goto out;
}
/* insn: must be on special executable page on mips. */
p->ainsn.insn = get_insn_slot(); if (!p->ainsn.insn) {
ret = -ENOMEM; goto out;
}
ret = __compute_return_epc_for_insn(regs, insn); if (ret < 0) return ret;
if (ret == BRANCH_LIKELY_TAKEN)
kcb->flags |= SKIP_DELAYSLOT;
kcb->target_epc = regs->cp0_epc;
return0;
unaligned:
pr_notice("Failed to emulate branch instruction because of unaligned epc - sending SIGBUS to %s.\n", current->comm);
force_sig(SIGBUS); return -EFAULT;
}
staticvoid prepare_singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{ int ret = 0;
regs->cp0_status &= ~ST0_IE;
/* single step inline if the instruction is a break */ if (p->opcode.word == breakpoint_insn.word ||
p->opcode.word == breakpoint2_insn.word)
regs->cp0_epc = (unsignedlong)p->addr; elseif (insn_has_delayslot(p->opcode)) {
ret = evaluate_branch_instruction(p, regs, kcb); if (ret < 0) return;
}
regs->cp0_epc = (unsignedlong)&p->ainsn.insn[0];
}
p = get_kprobe(addr); if (!p) { if (addr->word != breakpoint_insn.word) { /* *Thebreakpointinstructionwasremovedright *afterwehitit.Anothercpuhasremoved *eitheraprobepointoradebuggerbreakpoint *atthisaddress.Ineithercase,nofurther *handlingofthisinterruptisappropriate.
*/
ret = 1;
} /* Not one of ours: let kernel handle it */ goto no_kprobe;
}
if (p->pre_handler && p->pre_handler(p, regs)) { /* handler has already set things up, so skip ss setup */
reset_current_kprobe();
preempt_enable_no_resched(); return1;
}
/* Restore back the original saved kprobes variables and continue. */ if (kcb->kprobe_status == KPROBE_REENTER) {
restore_previous_kprobe(kcb); goto out;
}
reset_current_kprobe();
out:
preempt_enable_no_resched();
return1;
}
int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{ struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE;
switch (val) { case DIE_BREAK: if (kprobe_handler(args->regs))
ret = NOTIFY_STOP; break; case DIE_SSTEPBP: if (post_kprobe_handler(args->regs))
ret = NOTIFY_STOP; break;
case DIE_PAGE_FAULT: /* kprobe_running() needs smp_processor_id() */
preempt_disable();
if (kprobe_running()
&& kprobe_fault_handler(args->regs, args->trapnr))
ret = NOTIFY_STOP;
preempt_enable(); break; default: break;
} return ret;
}
NOKPROBE_SYMBOL(kprobe_exceptions_notify);
/* *Functionreturnprobetrampoline: *-init_kprobes()establishesaprobepointhere *-Whentheprobedfunctionreturns,thisprobecausesthe *handlerstofire
*/ staticvoid __used kretprobe_trampoline_holder(void)
{ asmvolatile( ".set push\n\t" /* Keep the assembler from reordering and placing JR here. */ ".set noreorder\n\t" "nop\n\t" ".global __kretprobe_trampoline\n" "__kretprobe_trampoline:\n\t" "nop\n\t" ".set pop"
: : : "memory");
}
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.