您的位置:首页 > 其它

Suse 11 Code Debug and Inject

2015-07-08 17:26 351 查看
http://blog.chinaunix.net/uid-20662820-id-3799149.html

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

Code Debug and Inject

Author: Tony
tingw.liu@gmail.com
Date:2013年7月11日星期四

1.
Debug

Linux下较新的内核调试是Kprobe,应用层框架是Ptrace和Utrace。gdb正是基于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功能的实现主要利用了两个功能特性:trap(x86/x64下是int 3),单步执行(EFLAGS中的TF标志)。

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

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

1)注册探测点
kprobe会对被探测地址的指令码进行替换,替换为int 3(trap)的指令码,并将原有地址和指令码保存。同时会保存用户希望在探测点执行的代码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

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

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

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

3.
Utrace

3.1.
About Utrace

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

Utrace在2007年第一次提交到内核邮件列表,但是由于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

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

SystemTap provides a simple command line interface and scripting language for writing instrumentation for a live running kernel plus user-space applications. We are publishing samples, as well as enlarging the internal "tapset" script library to aid reuse
and abstraction.

Among other tracing/probing tools, SystemTap is the tool of choice for complex tasks that may require live analysis, programmable on-line response, and whole-system symbolic access. SystemTap can also handle simple tracing jobs.

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

4.2.
How Systemtap works?

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

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

5.
Demo(SLES11SP2)

5.1.
Prepare

5.1.1.
Kernel Utrace

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

5.1.2.
Systemtap

zypper install systemtap

5.1.3.
Glibc debuginfo

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

zypper ca

zypper mr -e SLE11-SP2-Debuginfo-Core

zypper mr -e SLE11-SP2-Debuginfo-Updates

rpm -qi glibc

zypper install 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?

Performance Tuning

Debug kernel

Debug application

Inject running program

Inject libray

……

7.
Appendix

7.1.
Per event performance

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: