您可能不会收到回复,因为您对事物的理解不是很好,并且linux-arm-kernel列表中的任何人都需要一些时间才能回复。阅读kprobes.txt并详细研究 ARM 架构。
如果 kprobe 处理了未定义的指令异常(只创建了 bcos kprobe),那么为什么__und_svc()
会被调用。__und_svc()
处理程序对于 kprobes的作用是什么?
在 ARM 上,mode0b11011
是未定义指令模式。发生未定义指令时的流程是,
- lr_und = undef 指令的 pc + 4
- SPSR_und = 发生指令的模式的 CPSR。
- 在禁用中断的情况下将模式更改为 ARM。
- PC = 向量基数 + 4
第四步的主向量表位于__vectors_start
并且这只是分支到
vector_und
。该代码是一个名为 的宏vector_stub
,它决定调用__und_svc
或__und_usr
。堆栈是为每个进程保留的 4/8k 页。它是包含任务结构和内核堆栈的内核页面。
kprobe通过将未定义的指令放置在您希望探测的代码地址来工作。即,它涉及未定义的指令处理程序。这应该很明显。它调用两个例程,call_fpe
或do_undefinstr()
. 您对获取操作码和调用的第二种情况感兴趣call_undef_hook()
。添加一个带有register_undef_hook()的钩子;你可以看到arch_init_kprobes()
。主回调kprobe_handler
是用 调用的struct pt_regs *regs
,这恰好是在 中保留的额外内存__und_svc
。例如,请注意kretprobe_trampoline()
,它正在与当前正在执行的堆栈玩技巧。
如果 64 字节内存是强制性的,那么如何在不编译内核的情况下进行分配。即如何动态地做到这一点。?
不它不是。您可以使用不同的机制,但您可能必须修改kprobes代码。很可能您将不得不限制功能。也可以完全重写堆栈帧并在事后保留额外的 64 字节。它不是中的分配kmalloc()
。它只是从主管堆栈指针中添加/减去一个数字。我猜想代码会重写未定义处理程序的返回地址,以在kprobed地址的上下文(ISR、下半/线程 IRQ、work_queue、内核任务)中执行。但是您可能还没有遇到其他问题。如果arch_init_kprobes()
从未被调用,那么您可以随时进行预订__und_svc
; 它只吃 64 字节的堆栈,这将使内核堆栈更有可能溢出。即,改变,
__und_svc:
@ Always reserve 64 bytes, even if kprobe is not active.
svc_entry 64
arch_init_kprobes()
是实际安装该功能的内容。