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 *anotherprobewashitwhilewithinthehandler. *Weheresavetheoriginalkprobesvariablesand *justsinglestepontheinstructionofthenewprobe *withoutcallinganyuserhandlers.
*/
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); return1;
} elseif (*(u32 *)addr != BREAKPOINT_INSTRUCTION) { /* The breakpoint instruction was removed by *anothercpurightafterwehit,nofurther *handlingofthisinterruptisappropriate
*/
ret = 1;
} goto no_kprobe;
}
p = get_kprobe(addr); if (!p) { if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) { /* *Thebreakpointinstructionwasremovedright *afterwehitit.Anothercpuhasremoved *eitheraprobepointoradebuggerbreakpoint *atthisaddress.Ineithercase,nofurther *handlingofthisinterruptisappropriate.
*/
ret = 1;
} /* Not one of ours: let kernel handle it */ goto no_kprobe;
}
/* If INSN is a relative control transfer instruction, *returnthecorrectedbranchdestinationvalue. * *regs->tpcandregs->tnpcstillholdthevaluesofthe *programcountersatthetimeoftrapduetotheexecution *oftheBREAKPOINT_INSTRUCTION_2atp->ainsn.insn[1] *
*/ staticunsignedlong __kprobes relbranch_fixup(u32 insn, struct kprobe *p, struct pt_regs *regs)
{ unsignedlong real_pc = (unsignedlong) p->addr;
/* Branch not taken, no mods necessary. */ if (regs->tnpc == regs->tpc + 0x4UL) return real_pc + 0x8UL;
/* The three cases are call, branch w/prediction, *andtraditionalbranch.
*/ if ((insn & 0xc0000000) == 0x40000000 ||
(insn & 0xc1c00000) == 0x00400000 ||
(insn & 0xc1c00000) == 0x00800000) { unsignedlong ainsn_addr;
ainsn_addr = (unsignedlong) &p->ainsn.insn[0];
/* The instruction did all the work for us *already,justapplytheoffsettothecorrect *instructionlocation.
*/ return (real_pc + (regs->tnpc - ainsn_addr));
}
/* It is jmpl or some other absolute PC modification instruction, *leaveNPCas-is.
*/ return regs->tnpc;
}
/* If INSN is an instruction which writes its PC location *intoadestinationregister,fixthatup.
*/ staticvoid __kprobes retpc_fixup(struct pt_regs *regs, u32 insn, unsignedlong real_pc)
{ unsignedlong *slot = NULL;
/* Simplest case is 'call', which always uses %o7 */ if ((insn & 0xc0000000) == 0x40000000) {
slot = ®s->u_regs[UREG_I7];
}
/* 'jmpl' encodes the register inside of the opcode */ if ((insn & 0xc1f80000) == 0x81c00000) { unsignedlong rd = ((insn >> 25) & 0x1f);
if (rd <= 15) {
slot = ®s->u_regs[rd];
} else { /* Hard case, it goes onto the stack. */
flushw_all();
/*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();
/* *Wrapperroutinetoforhandlingexceptions.
*/ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, unsignedlong val, void *data)
{ struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE;
if (args->regs && user_mode(args->regs)) return ret;
switch (val) { case DIE_DEBUG: if (kprobe_handler(args->regs))
ret = NOTIFY_STOP; break; case DIE_DEBUG_2: if (post_kprobe_handler(args->regs))
ret = NOTIFY_STOP; break; default: break;
} return ret;
}
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.