参考:

http://dustymabe.com/2012/10/14/trace-function-calls-using-gdb/

可以使用下面的脚本来把 gdb 作为一个函数跟踪器。

#!/bin/sh


# Make a function call trace using GDB. This is stupid, but it should work


if [ "$*" = "" ]; then
echo “usage: $0 [args]”
exit
fi


_CMDFILE=/tmp/`basename $0`.$$
_PROG=$1
shift


echo "Writing GDB commands file"
# Write the temporary GDB commands file
echo "set args $*" > $_CMDFILE
for i in $(nm -f posix $_PROG | awk '$2 == "T" {print $1}'); do
(echo break $i
echo command
echo silent
echo backtrace 1
echo continue
echo end
echo
) >> $_CMDFILE
done


echo run >> $_CMDFILE
echo q >> $_CMDFILE


# Now do the run
echo Starting GDB
gdb -quiet -command=$_CMDFILE $_PROG


# and clean up
echo GDB run finished
rm -f $_CMDFILE



代码的简单说明:

使用 nm 获取对应程序的函数信息保存到一个临时文件里。

该临时文件会对每一个函数设置断点,并在执行到该断点时打印一下对应的 backtrace ,因为设置成1,所以就打印当前的函数位置信息。


示例如下:

$ sh gdb-trace.sh /tmp/foo
Writing GDB commands file
 Starting GDB
 Reading symbols from /tmp/foo...done.
 Breakpoint 1 at 0x400560
 Breakpoint 2 at 0x4004d0
 Breakpoint 3 at 0x4005a8
 Breakpoint 4 at 0x400390
 Breakpoint 5 at 0x4003d0
 Breakpoint 6 at 0x4004b8: file foo.c, line 5.
 Breakpoint 7 at 0x4004c3: file foo.c, line 10.
 #0 _init (argc=1, argv=0x7fffffffde48, envp=0x7fffffffde58) at ../sysdeps/unix/sysv/linux/x86_64/../init-first.c:53
 #0 0x00000000004003d0 in _start ()
 #0 0x00000000004004d0 in __libc_csu_init ()
 #0 0x0000000000400390 in _init ()
 #0 main () at foo.c:10
 #0 foo () at foo.c:5
 #0 0x00000000004005a8 in _fini ()
 [Inferior 1 (process 31474) exited normally]
 GDB run finished