voID foobar(int arg,int arg2,int arg3,int arg4,int arg5,int arg6,int arg7,int arg8){ printk("foobar called\n");}
@H_419_1@把kprobe放在上面并调用函数:@H_419_1@...kp.addr = (kprobe_opcode_t *) foobar;register_kprobe(&kp);foobar(0xdead1,0xdead2,0xdead3,0xdead4,0xdead5,0xdead6,0xdead7,0xdead8);
@H_419_1@最后预处理功能(取自here):@H_419_1@static int inst_generic_make_request(struct kprobe *p,struct pt_regs *regs){ printk(KERN_INFO "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",regs->ax,regs->bx,regs->cx,regs->dx); printk(KERN_INFO "esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",regs->si,regs->di,regs->bp,regs->sp); regs++; //...}
@H_419_1@预处理程序函数的输出看起来像这样(我将regs指针增加3次)@H_419_1@May 10 22:58:07 kernel: [ 402.640994] eax: 000dead1 ebx: f7d80086 ecx: 000dead3 edx: 000dead2May 10 22:58:07 kernel: [ 402.640996] esi: 00000000 edi: b77c8040 ebp: 00000000 esp: f7d8006cMay 10 22:58:07 kernel: [ 402.641006] eax: f7d8032c ebx: 000dead5 ecx: 000dead6 edx: 000dead7May 10 22:58:07 kernel: [ 402.641007] esi: 000dead8 edi: f7d800e0 ebp: f7d80330 esp: 08049674May 10 22:58:07 kernel: [ 402.641014] eax: 00000080 ebx: 0992b018 ecx: 0000108e edx: 0992b008May 10 22:58:07 kernel: [ 402.641015] esi: 08049674 edi: b77c8040 ebp: bfe23fb8 esp: bfe23f50
@H_419_1@现在我可以在各种寄存器中看到foobar函数的参数(但是在哪里是0xdead4?),它们不应该在堆栈中吗?如何从预处理程序功能访问堆栈?或者如何在不知道其类型和数量的情况下获取任何函数的参数?我知道这可能不是一件容易的事(甚至不可能获得所有值),但只有大约值才足够.我正在计算两个函数的参数之间的相关性,我真的不需要精确的值.如果我有调用函数的汇编代码,其中参数被压入堆栈,它会有帮助吗?最佳答案至少有两种方法.@H_419_1@方法1:Jprobes@H_419_1@可能是最简单的一个:如果Jprobes适合你的任务,你可以尝试一下.他们是kprobes的近亲(参见他们的详细描述和kernel docs中的例子的链接).@H_419_1@Jprobes允许在进入后者时使用与探测到的功能相同的签名来调用您的函数.您可以通过这种方式自动获取所有参数.@H_419_1@方法2:寄存器和堆栈@H_419_1@另一种方法可能是扩展你已经做过的事情,并从寄存器和堆栈中检索参数.从您的问题中的输出日志,我假设您正在使用32位x86系统.@H_419_1@x86,32位@H_419_1@据我所知,在x86上的linux内核中有两个最常见的参数传递约定(详情见manual by Agner Fog).请注意,系统调用遵循其他约定(有关详细信息,请参阅manual),但我假设您有兴趣分析“普通”函数而不是系统调用.@H_419_1@公约1@H_419_1@对于标有asmlinkage的函数以及带有变量参数列表的函数,所有参数都在堆栈上传递.函数的返回地址应该在函数入口处的堆栈顶部,第一个参数位于它的正下方.第二个参数低于第一个参数,依此类推.@H_419_1@由于您拥有esp的保存值,您可以找到它指向的内容. *(esp 4)应该是第一个参数,*(esp 8) – 第二个,等等,如果使用此约定.@H_419_1@公约2@H_419_1@它似乎用于大多数内核函数,包括您在问题中提到的函数.@H_419_1@内核使用-mregparm = 3进行编译,因此前三个参数按顺序在eax,edx和ecx中传递,其余参数在堆栈上进行. *(特别是4)应该是第四个参数,*(特别是8) – 第五个,依此类推.@H_419_1@x86,64位@H_419_1@似乎x86-64上的事情有点简单.大多数内核函数(包括那些带有变量参数列表的函数)按顺序获取rdi,rsi,rdx,rcx,r8,r9中的前6个参数,其余函数继续堆栈. *(特别是8)应该是第7个参数,*(特别是16) – 第8个,依此类推.@H_419_1@编辑:@H_419_1@请注意,在x86-32上,对于内核模式陷阱(包括kprobes所依赖的软件断点),esp的值不会保存在pt_regs中. 提供了kernel_stack_pointer()函数来检索esp的正确值,它在x86-32和x86-64上都有效.有关详细信息,请参阅该头文件中的kernel_stack_pointer()的说明.@H_419_1@此外,regs_get_kernel_stack_nth()(也在该标头中定义)提供了一种在处理程序中获取堆栈内容的便捷方法. 总结 以上是内存溢出为你收集整理的linux – 使用kprobes获取函数参数全部内容,希望文章能够帮你解决linux – 使用kprobes获取函数参数所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)