在上一篇中介绍的2种方法都是在代码的某个特定的地方查看函数的调用关系,接下来介绍的2个工具可以追踪程序从main函数开始全部执行过的函数。
1.uftrace
1.1安装
工具在github上下载,地址如下:
https://github.com/namhyung/uftrace
readme里提供了一些简单的示例来说明uftrace的使用,这里主要针对稍复杂点的工程,演示程序以sqlite3为例,程序见:
http://blog.youkuaiyun.com/pfysw/article/details/78629167
注意要加上-finstrument-functions对整个工程重新编译一遍,这个是用来导出函数符号表的,配置如下图
在编译安装uftrace 之前要先安装elfutils,先下载elfutils-0.161,地址如下:
https://sourceware.org/elfutils/ftp/
解压后编译安装:
./configure --prefix=/usr --program-prefix="eu-" &&
make
make install
然后再安装uftrace,也是安装3部曲:
./configure make make install
安装过程可能有很多坑,我来说下我碰到的:
如果gcc版本是4.4.7,编译能通过,但是使用时会出现:“mcount: /home/qxqb/work/uftrace-master/libmcount/plthook.c:798:plthook_entry
ERROR: invalid function idx found! (idx: 952/202, module:”的错误
gcc版本切换到4.6.3编译后没有问题。
另外我还把gcc升级到4.8.5,这时eclipse自动编译的程序debug时会出现No source available for "main() at 0x80488e9"的错误,需要手动在编译选项设置里添加-gstabs+才不会报错,而4.6.3和4.4.7没有这个问题。
1.2使用
uftrace支持的子命令有:
* `record` : runs a program and saves the trace data
* `replay` : shows program execution in the trace data
* `report` : shows performance statistics in the trace data
* `live` : does record and replay in a row (default)
* `info` : shows system and program info in the trace data
* `dump` : shows low-level trace data
* `recv` : saves the trace data from network
* `graph` : shows function call graph in the trace data
* `script` : runs a script for recorded trace data
可以通过uftrace --help命令来查看操作选项,如:
--auto-args :显示函数参数和返回值
-F:仅追踪某个函数
-t:过滤掉执行函数小于某个值的函数
-k:显示内核函数
……
接下来开始演示怎么使用,新建一个文件夹mytest,并把要追踪的程序tclsqlite放到该文件夹下,新建一个文件tclscript:
sqlite3 db file:example1.db?mode=memory&cache=shared
db eval {CREATE TABLE t1(a TEXT, b INTEGER)}
db eval {
INSERT INTO t1 VALUES('one',1);
INSERT INTO t1 VALUES('two',2);
INSERT INTO t1 VALUES(NULL,3);
}
db eval {SELECT * FROM t1} {
puts "a=$a b=$b"
}
cd进入该文件夹并生成跟踪记录:
cd ./mytest
uftrace --auto-args record tclsqlite tclscript
然后把跟踪记录导出到文件,这里有2种方式,一种是replay:
uftrace replay>trace_replay
另外一种是dump模式
uftrace dump>trace_dump
我在使用-k时出现了以下错误:
uftrace -k record tclsqlite tclscript
WARN: kernel tracing disabled due to an error
does CONFIG_FTRACE enable in kernel?
暂时不知道什么原因,有2种思路解决,一种是去/sys/kernel/debug/tracing目录下找到相关文件配置一下,试了一下把tracing_enabled和tracing_on都打开:
echo 1 > tracing_enabled
echo 1 > tracing_on
好像也没什么效果,可能还有哪些配置要改,这个就需要进一步了解linux内核的调试工具ftrace。
另外一种思路就是调试uftrace源码了,看看到底在哪里出错了,以后有时间再来解决这个问题吧。
2.ftrace
2.1示例
这里的ftrace并不是指内核的ftrace,而是github上有人写的一个追踪函数执行过程的工具,地址如下:
https://github.com/finaldie/ftracer
当然github上ftrace工具还有很多,大家可以都尝试一下,这个我用了还不错,所以在这里介绍一下。
解压后,cd进入./example/c文件夹,首先看一个例子
make
./run.sh
这时候会生成追踪记录保存在/tmp/trace.txt,我们需要把记录导出来:
cd 进入tools文件夹,执行:
./gen_report.sh -e ../example/c/test -f /tmp/trace.txt
然后就生成了report文件,总共有3个线程,每个线程都生成一个报告
thread(3067386688) report generate complete at /tmp/trace_report.3067386688
thread(3075779392) report generate complete at /tmp/trace_report.3075779392
thread(3075782336) report generate complete at /tmp/trace_report.3075782336
cat /tmp/trace_report.3067386688
1x work(/home/qxqb/work/ftracer-master/example/c/test.c:50) - (called from ??:0)
.. 3x a(/home/qxqb/work/ftracer-master/example/c/test.c:43) - (called from test.c:51)
.... 1x b(/home/qxqb/work/ftracer-master/example/c/test.c:27) - (called from test.c:46)
...... 1x c(/home/qxqb/work/ftracer-master/example/c/test.c:22) - (called from test.c:32)
...... 1x f(/home/qxqb/work/ftracer-master/example/c/test.c:7) - (called from test.c:32)
.... 1x b(/home/qxqb/work/ftracer-master/example/c/test.c:27) - (called from test.c:46)
...... 2x d(/home/qxqb/work/ftracer-master/example/c/test.c:17) - (called from test.c:34)
...... 1x e(/home/qxqb/work/ftracer-master/example/c/test.c:12) - (called from test.c:38)
如果要以网页的形式生成报告,打开gen_report.sh,找到output_format=,改为output_format=html,网页的优势是支持折叠和展开,看起来比较方便。
2.2使用
仍然以tclsqlite这个程序为例,在example目录里新建一个文件夹mytest,把上面说到的tclsqlite 和tclscript文件放到该目录下,新建run.sh文件:
#!/bin/sh
export LD_PRELOAD=../../src/ftracer.so
./tclsqlite tclscript
然后运行./run.sh生成记录。
在tools目录下生成报告:
./gen_report.sh -e ../example/mytest/tclsqlite -f /tmp/trace.txt
这时发现生成的报告竟然还是上一次的test程序的记录,因为ftrace并不会清理上一次生成的记录,需要手动清理,解决的办法是进入/tmp/文件夹,把以下选中的文件删掉:
把/tmp/html文件夹也删掉,如果没权限,进入sudo nautilus模式就有权限了。
再重复开始的步骤就得到追踪的报告的html文件:
trace_report.3073885888.html
有了这个之后我们就可以很方便地查找某段代码的上下文了。
3.结束
这是以上例子中生成的针对sqlite3的函数追踪报告的下载:
http://download.youkuaiyun.com/download/pfysw/10254999
里面有trace_replay、uftrace_dump、trace_report.3073885888.html
除了这里介绍的2个工具,还有一些别的工具如rr、valgrind等应该也还是不错的,功能更强大,有时间的朋友也可以研究一下。