首先可以看下探测点检测到非法指令时候,产生中断的dump_stack:
symbol<c0011df0>] (dump_backtrace+0x0/0x10c) from [<c0630370>] (dump_stack+0x18/0x1c)
symbol<c0630358>] (dump_stack+0x0/0x1c) from [<bf00c208>] (handler_pre+0x144/0x19c [kk])
symbol<bf00c0c4>] (handler_pre+0x0/0x19c [kk]) from [<c063d174>] (kprobe_handler+0x194/0x234)
symbol<c063cfe0>] (kprobe_handler+0x0/0x234) from [<c063d23c>] (kprobe_trap_handler+0x28/0x54)
symbol<c063d214>] (kprobe_trap_handler+0x0/0x54) from [<c00082ac>] (do_undefinstr+0x118/0x1b0)
symbol<c0008194>] (do_undefinstr+0x0/0x1b0) from [<c063ca68>] (__und_svc+0x48/0x60)
symbol<c00523e0>] (do_fork+0x0/0x464) from [<c0011aec>] (sys_clone+0x34/0x3c)
symbol<c0011ab8>] (sys_clone+0x0/0x3c) from [<c000df20>] (ret_fast_syscall+0x0/0x30)
// 向中断列表注册一个中断回调函数
static struct undef_hook kprobes_arm_break_hook = {
.instr_mask = 0x0fffffff,
.instr_val = KPROBE_ARM_BREAKPOINT_INSTRUCTION,
.cpsr_mask = MODE_MASK,
.cpsr_val = SVC_MODE,
.fn = kprobe_trap_handler,
};
// 目前只有 kgdb , ptrace , kprobe 注册过
// 初始化
int __init arch_init_kprobes()
{
arm_kprobe_decode_init();
register_undef_hook(&kprobes_arm_break_hook);
return 0;
}
// 注册函数很简单,只是往list添加一个节点而已
void register_undef_hook(struct undef_hook *hook)
{
unsigned long flags;
raw_spin_lock_irqsave(&undef_lock, flags);
list_add(&hook->node, &undef_hook);
raw_spin_unlock_irqrestore(&undef_lock, flags);
}
// 当然你也可以注销
void unregister_undef_hook(struct undef_hook *hook)
{
unsigned long flags;
raw_spin_lock_irqsave(&undef_lock, flags);
list_del(&hook->node);
raw_spin_unlock_irqrestore(&undef_lock, flags);
}
//当CPU检测到没有定义的指令时候,ISR中会调用do_undefinstr:
asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
{
unsigned int instr;
void __user *pc;
//获取导致trap的指令
regs->ARM_pc -= correction;
pc = (void __user *)instruction_pointer(regs);
instr = *(u32 *) pc;
//回调
if (call_undef_hook(regs, instr) == 0)
goto do_undefinstr_exit;
}
// 查找列表,对已经注册的函数,进行回调
static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
{
struct undef_hook *hook;
unsigned long flags;
int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL;
// 遍历list,查看哪个注册的指令值与当前的一致
list_for_each_entry(hook, &undef_hook, node)
// instr 与注册的要一致的
// kgdb , ptrace , kprobe 的都不一致
if ((instr & hook->instr_mask) == hook->instr_val &&
(regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)
//回调函数
fn = hook->fn;
return fn ? fn(regs, instr) : 1;
}