使用" __ kprobes"它是如何工作的?

时间:2014-06-21 03:41:31

标签: c linux-kernel

在提到Linux内核的内存模块时,有些功能对我来说并不清楚。其中一项功能如下所示:

static inline int __kprobes notify_page_fault(struct pt_regs *regs)
{
int ret = 0;

/* kprobe_running() needs smp_processor_id() */
if (kprobes_built_in() && !user_mode_vm(regs)) {
    preempt_disable();
    if (kprobe_running() && kprobe_fault_handler(regs, 14))
        ret = 1;
    preempt_enable();
}

return ret;
} 

我对返回类型和函数名称之间的“__kprobes”感到困惑。当我在compiler.h中查看“__kprobes”的初始化时,我发现如下:

/*Ignore/forbid kprobes attach on very low level functions marked by 
this attribute:*/
#ifdef CONFIG_KPROBES
# define __kprobes  __attribute__((__section__(".kprobes.text")))
#else
# define __kprobes
#endif

嗯,我知道在编译时__kprobe将被其定义的部分替换。

的问题:

1。)__attribute__((__section__(".kprobes.text")))有什么意义?

2.)在“function_name”之前使用它时,它在编译时和运行时做了什么?

我读到了kprobe并发现它必须对断点和反向跟踪做些什么。我对kprobe的理解是它将帮助调试器创建回溯跟踪和断点。有人可以用简单的语言向我解释它是如何运作的,如果我错了,请纠正我。

1 个答案:

答案 0 :(得分:3)

TL; DR

  1. __attribute__((__section__(".kprobes.text")))会将该函数放在kprobes无法找到的单独部分中,从而阻止无限断点。
  2. 您必须在“function_name”之前使用它将整个“function_name”符号放在单独的部分中。
  3. 真实答案

    kprobes(内核探测器)是用于动态跟踪的Linux内核机制。它允许您在几乎任何内核函数中插入断点,调用您的处理程序,然后继续执行。它通过运行时修补内核映像和所谓的内核探测器/ kprobe来工作 - 请参阅struct kprobe。此探针将允许您将控制权传递给您的处理程序,该处理程序通常会进行一些跟踪。

    那么,引起了什么:

    • 您可以通过定义要中断的地址和传递引用的处理程序来创建struct kprobe
    • 您使用register_kprobe
    • 注册了探针
    • 内核kprobe子系统从您的探测器中查找地址
    • 然后kprobe:
      • 在给定地址
      • 处插入断点CPU指令(x86的int 3
      • 添加了一些包装代码来保存上下文(寄存器等)
      • 添加了更多代码,以帮助您访问函数参数或返回值。
    • 现在,当内核执行命中探测到的地址时:
      • 它将落入CPU陷阱
      • 它将保存上下文
      • 它会通过notifier_call_chain
      • 将控制传递给您的处理程序
      • ...
      • 毕竟它将恢复上下文

    这就是它的工作原理。正如你所看到的那样,它是一个非常整洁和肮脏的黑客,但是一些内核功能非常低级,因此探测它们毫无意义。 notify_page_fault是其中一个函数 - 作为notifier_call_chain的一部分,它用于将控制权传递给您的处理程序。

    因此,如果您在notify_page_fault进行探测,您将获得无限循环的断点,这不是您想要的。你真正想要的是保护那种功能,而kprobes将它放在单独的.kprobes.text部分中。这将阻止探测该函数,因为kprobe不会在该部分中查找地址。这是__attribute__((__section__(".kprobes.text")))的工作。