在kretprobe的entry_handler中获取探测函数的参数

时间:2014-03-27 11:34:54

标签: c linux-kernel linux-device-driver

我试图使用kretprobe拦截kmalloc void *__kmalloc(size_t size, gfp_t flags); 我可以使用kretprobe结构的handler成员找出kmalloc的返回值。

static struct kretprobe kmalloc_probe = {
    .handler = kmalloc_ret_handler,
    .entry_handler = kmalloc_entry_handler,
    .data_size = sizeof(struct kmalloc_read_args),
    .maxactive = 20,
};

但是我需要一种方法来查找在entry_handler中调用函数的参数。 这是我的entry_handler函数:

static int kmalloc_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)

我尝试在regs struct参数的所有寄存器中搜索,但没有运气。我使用的架构是i686。 我知道jprobes可以更好地解决这类问题,但我需要使用kretprobes来解决它。 能否请你给我一些如何使用寄存器或堆栈来查找函数调用参数的提示?

pt_regs结构的链接:http://lxr.free-electrons.com/source/arch/x86/include/asm/ptrace.h#L11

1 个答案:

答案 0 :(得分:2)

{8}中的注释中描述了在x86上的内核中传递参数的约定。

在32位x86系统上,Linux内核中函数的第一个参数(系统调用和其他一些东西除外)通常按顺序在%eax,%edx,%ecx中传递。这是因为源代码是使用'-mregparm = 3'GCC选项编译的,默认设置。至少从内核2.6.32开始就是这种情况,或者甚至可能更早。

其余参数在堆栈上传递。

如果函数有一个可变参数列表(如sprintf()),那么就我所见,所有参数都在堆栈上传递。

因此,在您的情况下,size应该在%eax和flags - %edx中进入函数。如果这些寄存器没有被kretprobe以某种方式破坏,你应该能够在pt_regs中找到它们。

在64位x86系统上,约定更简单,更符合x86-64 ABI。内核函数的第一个参数(再次,除了系统调用和一些特殊函数)在%rdi,%rsi,%rdx,%rcx,%r8,%r9中按顺序传递,其余的都在堆栈上。< / p>