我正在寻找可以跟踪可执行文件中本地定义的函数的ltrace或strace之类的工具。ltrace仅跟踪动态库调用,而strace仅跟踪系统调用。例如,给定以下C程序:
#include <stdio.h> int triple ( int x ) { return 3 * x; } int main (void) { printf("%d\n", triple(10)); return 0; }
使用来运行程序ltrace将显示对的调用,printf因为这是标准库函数(在我的系统上是动态库),并且strace将显示启动代码,用于实现printf的系统调用以及关闭代码的所有系统调用。 ,但是我想要让我知道该函数triple已被调用的东西。假设优化编译器未内联局部函数,并且二进制文件未剥离(删除符号),是否有工具可以做到这一点?
ltrace
printf
strace
triple
编辑
一些澄清:
假设只希望收到有关特定功能的通知,可以这样进行:
使用调试信息进行编译(由于您已经具有符号信息,因此您可能还具有足够的调试功能)
给定
#include <iostream> int fac(int n) { if(n == 0) return 1; return n * fac(n-1); } int main() { for(int i=0;i<4;i++) std::cout << fac(i) << std::endl; }
使用gdb跟踪:
[js@HOST2 cpp]$ g++ -g3 test.cpp [js@HOST2 cpp]$ gdb ./a.out (gdb) b fac Breakpoint 1 at 0x804866a: file test.cpp, line 4. (gdb) commands 1 Type commands for when breakpoint 1 is hit, one per line. End with a line saying just "end". >silent >bt 1 >c >end (gdb) run Starting program: /home/js/cpp/a.out #0 fac (n=0) at test.cpp:4 1 #0 fac (n=1) at test.cpp:4 #0 fac (n=0) at test.cpp:4 1 #0 fac (n=2) at test.cpp:4 #0 fac (n=1) at test.cpp:4 #0 fac (n=0) at test.cpp:4 2 #0 fac (n=3) at test.cpp:4 #0 fac (n=2) at test.cpp:4 #0 fac (n=1) at test.cpp:4 #0 fac (n=0) at test.cpp:4 6 Program exited normally. (gdb)
这是我收集所有函数地址的方法:
tmp=$(mktemp) readelf -s ./a.out | gawk ' { if($4 == "FUNC" && $2 != 0) { print "# code for " $NF; print "b *0x" $2; print "commands"; print "silent"; print "bt 1"; print "c"; print "end"; print ""; } }' > $tmp; gdb --command=$tmp ./a.out; rm -f $tmp
请注意,除了打印当前frame(bt 1)之外,您还可以执行任何操作,打印某些全局值,执行一些shell命令,或者在命中该fatal_bomb_exploded函数时发送邮件:)不幸的是,gcc输出了一些“当前语言已更改”消息之间。但这很容易被窃听。没什么大不了的。
bt 1
fatal_bomb_exploded