4

我试图将 kprobe 转换为可加载的内核模块。

我能够运行samples/kprobes/内核树文件夹中可用的示例。

如果我们在 kernel( CONFIG_KPROBES) 中配置 kprobes,那么svc_entry宏将在__und_svc()处理程序中扩展为 64 字节。

参考: http://lxr.free-electrons.com/source/arch/arm/kernel/entry-armv.S?a= arm#L245

我的目标是不涉及内核方面,将 kprobe 作为内核模块。

所以内核在不启用 CONFIG_KPROBES 的情况下编译。所以 svc_entry 宏将在 __und_svc()中扩展为 0

我想摆脱这些疑虑。

  1. 如果 kprobe 处理了未定义的指令异常(只创建了 bcos kprobe),那么为什么__und_svc()会被调用。__und_svc()处理程序对于 kprobes的作用是什么?

  2. 如果 64 字节内存是强制性的,那么如何在不编译内核的情况下进行分配。即如何动态地做到这一点。??

请分享你的知识。

4

1 回答 1

5

您可能不会收到回复,因为您对事物的理解不是很好,并且linux-arm-kernel列表中的任何人都需要一些时间才能回复。阅读kprobes.txt并详细研究 ARM 架构。

如果 kprobe 处理了未定义的指令异常(只创建了 bcos kprobe),那么为什么__und_svc()会被调用。__und_svc()处理程序对于 kprobes的作用是什么?

在 ARM 上,mode0b11011未定义指令模式发生未定义指令时的流程是,

  1. lr_und = undef 指令的 pc + 4
  2. SPSR_und = 发生指令的模式的 CPSR。
  3. 在禁用中断的情况下将模式更改为 ARM。
  4. PC = 向量基数 + 4

第四步的主向量表位于__vectors_start并且这只是分支到 vector_und。该代码是一个名为 的宏vector_stub,它决定调用__und_svc__und_usr。堆栈是为每个进程保留的 4/8k 页。它是包含任务结构和内核堆栈的内核页面。

kprobe通过将未定义的指令放置在您希望探测的代码地址来工作。即,它涉及未定义的指令处理程序。这应该很明显。它调用两个例程,call_fpedo_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()是实际安装该功能的内容。

于 2013-12-13T18:27:42.493 回答