Code Debug and Inject

来源:互联网 发布:java 子类的构造器 编辑:程序博客网 时间:2024/05/20 08:27

分类: LINUX

欢迎转载,转载请保留文档完整性!

From:http://blog.chinaunix.net/uid-20662820-id-3799149.html

 

Code Debug and Inject

Author: Tony tingw.liu@gmail.com

Date:2013711日星期四

 

1.   Debug

Linux下较新的内核调试是Kprobe,应用层框架是PtraceUtracegdb正是基于ptrace实现。

由于应用层程序可能不在内存中,而且可能存在一个程序多次执行的情况,所有内核层的调试不能直接调试应用层程序。

2.   Kprobe

2.1.    About kprobe

Kprobe机制是内核提供的一种调试机制,它提供了一种方法,能够在不修改现有代码的基础上,灵活的跟踪内核函数的执行。kprobe已经被Linus纳入主树,只需要内核选项“CONFIG_KPROBES=y”就可以开启kprobe功能。

Kprobe提供了三种形式的探测点,一种是最基本的kprobe,能够在指定代码执行前、执行后进行探测,但此时不能访问被探测函数内的相关变量信息;一种是jprobe,用于探测某一函数的入口,并且能够访问对应的函数参数;一种是kretprobe,用于完成指定函数返回值的探测功能。其中最基本的就是kprobe机制,jprobe以及kretprobe的实现都依赖于kprobe

2.2.    How kprobe works?

对于kprobe功能的实现主要利用了两个功能特性:trapx86/x64下是int 3),单步执行(EFLAGS中的TF标志)。

kprobe功能初始化时会注册到die_notifier通知链,该通知链在trapdebug异常的时候被调用,从而使得kprobe可以感知trapdebug异常。

通过kprobe查看探测点的大概的流程:

 1)注册探测点

kprobe会对被探测地址的指令码进行替换,替换为int 3trap)的指令码,并将原有地址和指令码保存。同时会保存用户希望在探测点执行的代码pre_handler(指令码)。

 2)内核执行到探测点

由于探测点的指令码被修改为trap,触发trap异常。通过do_int3-->notify_die调用到kprobe的回调函数。

 3)在kprobe回调函数中处理trap异常

kprobe根据寄存器中RIP(x64),计算出触发异常的RIP(寄存器RIP中存放着触发异常的下一条指令的地址)。

kprobe根据计算出的RIP与第一步中保存的地址相比较,判断是否是探测点。

执行第一步中保存的pre_handler

 4)执行原有的指令

通过设置EFLAGS中的TF标志位,进入单步调试模式,并且把异常返回的地址修改为第一步中保存的原指令码;

 5)回复执行流程

因为进入单步调试模式,原有指令码执行完成后,会触发DEBUG。通过do_debug-->notify_die调用到kprobe的回调函数。

 6)在kprobe中恢复原有执行流程

kprobe修改RIP中保存的异常返回的指令地址为第一步中保存的指令地址的下一条地址。DEBUG异常返回后,调整到RIP中执行,原有流程恢复。

2.3.    How kretprobe works?

kretprobe利用kprobe实现,可以在函数返回之前添加要执行的代码。kretprobe的大概流程:

         1)在调用函数的call指令后添加kprobe

         2kprobe的回调函数会记录下call指令保存的函数返回的return地址,并将该地址替换为一个特殊的“trampoline”。

         3kprobetrampoline地址上注册kprobe,该kprobe会调用用户定义的代码。

         4)当函数返回时,会执行“trampoline”,从而运行之前注册的用户定义代码。

3.   Utrace

3.1.    About Utrace

UtraceRed HatRoland McGrath编写,是 Linux内核中最新的 trace debug基础构架。正如其名称所暗示,utrace为运行在用户态的进程提供 trace debug支持。

Utrace2007年第一次提交到内核邮件列表,但是由于Linus的强烈反对(http://yarchive.net/comp/linux/utrace.html),目前Utrace仍然只在-mm分支,并不在Mainline。用户要想适应utrace,需要自己给内核打patch

关于Utrace的介绍可以参考http://www.ibm.com/developerworks/cn/linux/l-cn-utrace/

4.   Systemtap

4.1.    About Systemtap

SystemTapprovides free software (GPL) infrastructure to simplify the gathering ofinformation about the running Linux system. This assists diagnosis of aperformance or functional problem. SystemTap eliminates the need for thedeveloper to go through the tedious and disruptive instrument, recompile,install, and reboot sequence that may be otherwise required to collect data.

SystemTapprovides a simple command line interface and scripting language for writinginstrumentation for a live running kernel plus user-spaceapplications. We are publishing samples, as well as enlarging the internal"tapset" script library to aid reuse and abstraction.

Amongother tracing/probing tools, SystemTap is the tool of choice for complex tasksthat may require live analysis, programmable on-line response, and whole-systemsymbolic access. SystemTap can also handle simple tracing jobs.

Currentproject members include Red Hat, IBM, Hitachi, and Oracle.( http://sourceware.org/systemtap/)

4.2.    How Systemtap works?

KprobeUtrace提供了内核态和用户态探测函数的接口,用户可以直接编写内核模块来实现debug/inject。鉴于内核模块的编写需要较高的门槛,Systemtap通过提供一个框架,只需要用户编写脚本就可以实现debug/inject

用户需要编写systemtap脚本,然后systemtap框架将脚本转换成内核C代码,编译成内核模块,实现代码的debug/inject

5.   DemoSLES11SP2

5.1.    Prepare

5.1.1.     Kernel Utrace

SLES11SP2已经应用了utrace patch,但是默认内核没有开启。修改开启UTRACE选项,重新编译内核

5.1.2.     Systemtap

zypperinstall systemtap

5.1.3.     Glibc debuginfo

如果需要debug/inject glibc库,需要安装对于的debuginfo安装包。

zypperca

zypper mr-e SLE11-SP2-Debuginfo-Core

zyppermr -e SLE11-SP2-Debuginfo-Updates

rpm -qiglibc

zypperinstall glibc-debuginfo-2.11.3-17.31.1(这里需要确保安装的debuginfo的版本与系统glibc版本完全一致)

5.2.    Coding program which will be injectd


5.3.    Systemtap scripts


5.4.    Run program


5.5.    Inject program


6.   What we can do with it?

PerformanceTuning

Debugkernel

Debugapplication

Injectrunning program

Injectlibray

……

7.   Appendix

7.1.    Per event performance

0 0