使用printk打印变量等方法,是调试内核的有效方法之一,但是这种方法必须重新构建并用新内核启动,调试效率比较低。以内核模块的方式使用kprobes、jprobes,就可以在任意地址插入侦测器,执行包括printk在内的各种调试工作,而无须重新构建内核,也无须重启。

一、首先内核必须支持kprobes、jprobes:

#make menuconfig

General setup  --->

[*] Kprobes

使内核支持kprobes。

二、kprobes的使用方法:
1、分配一个kprobe结构体供kprobes运行时使用。
2、在kprobe结构体的addr成员中设置要插入侦测器的函数地址,可以通过查看system.map查找,或者通过proc文件系统查找

# cat /proc/kallsyms | grep "do_execve"

c00bbfb8 T do_execve
3、如果不想设置addr成员,可以设置symbol_name成员为"do_execve"(想要侦测的函数),需要内核版本在2.6.19以上才支持。

4、在kprob结构的pre_handler成员设置侦测函数exec_pre_handler。

5、调用register_kprobe函数注册侦测器函数。

以下是一个用kprobes监测do_execve()函数的例子,在每次调用do_execve()函数之前,就会打印当前的进程pid、jiffies值等全局变量信息。#include <linux/module.h>

  1. #include <linux/kprobes.h>
  2. #include <linux/kallsyms.h>
  3. struct kprobe exec_kp;
  4. static int exec_pre_handler(struct kprobe *p, struct pt_regs *regs)
  5. {
  6. printk("Enter into %s\n", __func__);
  7. printk("pt_regs:%p, pid:%d, jiffies:%ld\n", regs, current->tgid, jiffies);
  8. return 0;
  9. }
  10. static __init int kprobes_exec_init(void)
  11. {
  12. /*设置要检测的函数do_execve()的地址*/
  13. //exec_kp.addr = (kprobe_opcode_t *)0xc00bbfb8;
  14. /*如果不想直接给addr成员设置地址,也可以使用符号名*/
  15. exec_kp.symbol_name = "do_execve";
  16. exec_kp.pre_handler = exec_pre_handler;
  17. /*注册kprobes*/
  18. register_kprobe(&exec_kp);
  19. return 0;
  20. }
  21. static __exit void kprobes_exec_cleanup(void)
  22. {
  23. /*撤销kprobes注册*/
  24. unregister_kprobe(&exec_kp);
  25. }
  26. module_init(kprobes_exec_init);
  27. module_exit(kprobes_exec_cleanup);
  28. MODULE_LICENSE("GPL");

编译并insmod上述ko,那么在do_execve()函数执行之前就会先执行kprobes的pre_handler所指向的exec_pre_handler,打印内核的当前进程pid、jiffies等全局变量的值。由于do_exec函数用于生成进程,因此每次执行ls等命令都会显示一次:

pt_regs:c52ebf08, pid:110, jiffies:155286

pt_regs:c5313f08, pid:113, jiffies:159137

pt_regs:c52ebf08, pid:112, jiffies:159137

利用kprobes也可以查看内核函数内部任意位置的信息,此时需要把内核函数反汇编,确定想要查看位置相对于函数起始地址的偏移量,在初始化kprobes时,设置kprobe结构体的offset成员,就可以查看内核内部函数任意位置的信息。

三、jprobes的使用方法

用kprobes可以方便的查看内核内部任意位置的信息,相反,jprobes则是特别为函数开头的侦测准备的,通过jprobes,可以更容易的获取传递给函数的参数。使用jprobes与使用kprobes大体上一样,主要有以下区别:

1、分配给jprobes的结构体是jprobe结构体,并将指针传递给register_jprobe。jprobe结构的成员如下所示,只包括kprobe和entry两者。

  1. struct jprobe {
  2. struct kprobe kp;
  3. void *entry;    /* probe handling code to jump to */
  4. };

struct kprobe kp成员设置的是要侦测函数的符号或地址,entry中为通过JPROBE_ENTRY()宏处理过的侦测器处理程序。

2、侦测器处理程序的参数应当与需要侦测的函数的参数相同,这样可以方便的打印被侦测函数的形参。使用kprobes时,必须通过寄存器或者栈才能计算出参数的值。而计算方法还依赖于cpu架构,如果使用jprobes,则无须了解架构的详细知识,也能查看参数的值。
3、侦测器处理函数的尾部必须加上jprobe_return();

以下是使用jprobes打印do_execve函数的参数的例子,每次调用do_execve之前,都会打印相应的参数:

  1. #include <linux/module.h>
  2. #include <linux/kprobes.h>
  3. #include <linux/kallsyms.h>
  4. struct jprobe exec_jp;
  5. int jp_do_execve(const char * filename,
  6. const char __user *const __user *argv,
  7. const char __user *const __user *envp,
  8. struct pt_regs * regs)
  9. {
  10. int cnt = 0;
  11. printk("filename = %s\n", filename);
  12. for(; *argv != NULL;argv++,cnt++)
  13. printk("argv[%d] = %s\n", cnt, *argv);
  14. jprobe_return();
  15. return 0;
  16. }
  17. static __init int jprobes_exec_init(void)
  18. {
  19. exec_jp.kp.symbol_name = "do_execve";
  20. exec_jp.entry = JPROBE_ENTRY(jp_do_execve);
  21. /*注册jprobes*/
  22. register_jprobe(&exec_jp);
  23. return 0;
  24. }
  25. static __exit void jprobes_exec_cleanup(void)
  26. {
  27. /*撤销jprobes注册*/
  28. unregister_jprobe(&exec_jp);
  29. }
  30. module_init(jprobes_exec_init);
  31. module_exit(jprobes_exec_cleanup);
  32. MODULE_LICENSE("GPL");

每次执行ls时都会调用do_execve函数,具体的打印如下:

# ls

filename = /bin/ls

argv[0] = ls

 

[FW]使用kprobes查看内核内部信息的更多相关文章

  1. 使用kprobes查看内核内部信息

    前言:使用printk打印变量等方法,是调试内核的有效方法之一,但是这种方法必须重新构建并用新内核启动,调试效率比较低.以内核模块的方式使用kprobes.jprobes,就可以在任意地址插入侦测器, ...

  2. [linux系统]查看内核版本和系统版本方法

    查看内核版本信息的两个命令: uname -a cat /proc/version 查看系统版本的命令: lsb_release -a more /etc/issue cat /etc/redhat- ...

  3. linux查看内核版本、系统版本、系统位数(32or64)

     linux查看内核版本.系统版本.系统位数(32or64) 2011-05-01 22:05:12 标签:linux 内核版本 休闲 系统版本 系统位数 1. 查看内核版本命令: 1) [root@ ...

  4. 在linux下查看内核版本、gcc版本、操作系统多少位等参数

    1. 查看linux版本 cat /etc/issue Ubuntu 11.04 \n \l 2. 查看内核版本 1)cat /proc/version Linux version 2.6.38-13 ...

  5. Linux下查看内核、CPU、内存及各组件版本的命令和方法

    Linux下查看内核.CPU.内存及各组件版本的命令和方法 Linux查看内核版本: uname -a                        more /etc/*release       ...

  6. Ubuntu 中查看内核版本和系统版本的三个命令

    一.查看内核版本:cat /proc/version 二.查看内核版本:uname -a 三.查看系统版本:lsb_release -a 四.查看发行版类型:cat /etc/issue

  7. Linux查看内核和系统版本

    1. 查看内核版本命令: 1) [root@q1test01 ~]# cat /proc/version Linux version 2.6.9-22.ELsmp (bhcompile@crowe.d ...

  8. Linux查看内核信息或系统信息

    先说说为什么会写这个.这是我去面试的时候面试官问的一个问题,我感觉是一个普遍会被问到的问题.为了让我自己记住,也便于收集下Linux运维方向考官的题目. 第一,查看内核信息 cat /proc/ver ...

  9. Ubuntu 中查看内核版本和系统版本的四个命令

    一.查看内核版本:cat /proc/version 二.查看内核版本:uname -a 三.查看系统版本:lsb_release -a 四.查看发行版类型:cat /etc/issue

随机推荐

  1. JVM(17)之 准备-解析-初始化

    开发十年,就只剩下这套架构体系了! >>>   在类加载机制的五个阶段中,我们已经讲完了第一个阶段.剩下的四个阶段由于涉及到比较多的类文件相关的知识,现在讲了会看得很吃力,所以我们暂 ...

  2. JavaScript中正则使用

    字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在.比如判断一个字符串是否是合法的Email地址,虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样做不但麻烦, ...

  3. 2018-2-13-wpf-绑定-TextLength-

    title author date CreateTime categories wpf 绑定 TextLength lindexi 2018-2-13 17:23:3 +0800 2018-2-13 ...

  4. vue不是内部或外部命令的解决方法

    1.在nodejs的安装目录下,找到vue.cmd,将此路径加到环境变量中,我是通过nvm管理node版本的,路径是C:\Users\hy\AppData\Roaming\nvm\v6.10.0,关闭 ...

  5. ansible笔记(三)--模块讲解

    ansible 常用命令 ansible-doc ansible-playbook ansible-vault ansible-console ansible-galaxy ansible-pull ...

  6. MySQL MHA之 master_ip_failover.sh脚本

    master_ip_failover.sh脚本是用perl编写的,可以在mha-manager源码包中可以找到,下面给出的结合keepalived进行自动切换的脚本: [root@mha script ...

  7. $NOI2014$ 购票(斜率优化 点分治)

    \(NOI2014\)购票 哇终于可以碰电脑了赶快切些火题找找感觉. 拿到这道题的时候发现简单的斜率优化推一推可以秒掉平方做法,然后一条链也可以做. 然后呢... 卧槽这个在一棵树上怎么办啊. 大力\ ...

  8. VS2005下使用GSL-1.15小结

    最近在复习高等数学,有时为了验证顺便复习下C语言,看了看自己下载收集的软件,发现C语言有一个数学工具包,是GNU开发的,叫做GSL--GNU Scientific Library,中文:C++科学计算 ...

  9. ES5和ES6数组方法

    ES5 方法 indexOf和lastIndexOf 都接受两个参数:查找的值.查找起始位置不存在,返回 -1 :存在,返回位置.indexOf 是从前往后查找, lastIndexOf 是从后往前查 ...

  10. spring-boot整合Mybatis多数据源案例

    1.运行环境 开发工具:intellij idea JDK版本:1.8 项目管理工具:Maven 4.0.0 2.GITHUB地址 https://github.com/nbfujx/springBo ...