如何对仅在指定调用路径下的函数断下断点
举个例子,有示例代码如下:
[root@lenky test]# cat t.c #include <stdio.h> void foo() { printf("foo\n"); } void bar() { foo(); } void baz() { foo(); } int main() { bar(); baz(); bar(); baz(); return 0; }
对于函数foo()而言,有两条调用路径分别为:
1,main() -> bar() -> foo()
2,main() -> baz() -> foo()
那么如何仅在通过第2条路径执行到foo()函数时才断下来呢?办法是有的,演示如下:
[root@lenky test]# gcc -g t.c -o t [root@lenky test]# gdb t -q (gdb) source gdb_script Breakpoint 1 at 0x80483ab: file t.c, line 15. Breakpoint 2 at 0x804838a: file t.c, line 5. (gdb) r Starting program: /home/gqk/test/t foo Breakpoint 2, foo () at t.c:5 5 printf("foo\n"); (gdb) bt #0 foo () at t.c:5 #1 0x080483b0 in baz () at t.c:15 #2 0x080483cd in main () at t.c:21 (gdb) c Continuing. foo foo Breakpoint 2, foo () at t.c:5 5 printf("foo\n"); (gdb) bt #0 foo () at t.c:5 #1 0x080483b0 in baz () at t.c:15 #2 0x080483d7 in main () at t.c:24 (gdb) c Continuing. foo Program exited normally. (gdb) q [root@lenky test]#
命令“source gdb_script”用于加载我的一个gdb脚本,根据显示来看,我在脚本里下了两个断点,其中Breakpoint 1在函数baz()处,而Breakpoint 2在函数foo()处。接着在通过命令r实际执行时,虽然函数foo()被调用了4次,但仅断下了2次,并且都是通过函数baz()调下来的路径被断了下来,达到了最初的设定目标。
下面再来解释我们是如何做的,很明显,这其中最重要的就是文件gdb_script:
[root@lenky test]# cat gdb_script set breakpoint pending on set $baz_enter = 0 b baz commands silent set $baz_enter = 1 c end b foo if $baz_enter == 1 commands set $baz_enter = 0 end
思路很简单,在执行到函数baz()时,设置变量$baz_enter为1,然后再执行到函数foo()时根据变量$baz_enter做条件断点。另外一些细节的处理无需多说。
可以将文件gdb_script改名为.gdbinit,这样gdb在启动时将自动读取和处理。
[root@lenky test]# mv gdb_script .gdbinit [root@lenky test]# gdb t -q Breakpoint 1 at 0x80483ab: file t.c, line 15. Breakpoint 2 at 0x804838a: file t.c, line 5. (gdb) q
本文介绍内容有什么实用场景?举个例子,比如内核代码中申请内存页面的逻辑有很多,但最终都会调入到__alloc_pages_nodemask()函数(以kernel 3.4.4为例),如果我只想断下从某条指定路径下来的情况,那么这里介绍的内容就有用了。
其它相关:
设置自动延后识别(避免提示“Make breakpoint pending on future shared library load?”):
set breakpoint pending on
也可以用
start
代替,即这样:
start # runs to main, so shared libraries are loaded
# after you reach main, GDB should have libc symbols, “puts” among them
break puts
…
设置屏幕大小(避免提示“gdb disable type return to continue or q return to quit”):
set width 0
set height 0
set verbose off
设置日志输出(转存调试日志):
set logging on #启用日志
set logging file /tmp/log.log #设置日志文件路径
参考资料:
http://sourceware.org/gdb/onlinedocs/gdb/Set-Breaks.html
http://sourceware.org/gdb/onlinedocs/gdb/Conditions.html#Conditions
http://sourceware.org/gdb/onlinedocs/gdb/Expressions.html#Expressions
http://sourceware.org/gdb/onlinedocs/gdb/Python.html#Python
http://stackoverflow.com/questions/10748501/automating-gdb-sessions
转载请保留地址:http://lenky.info/archives/2013/03/16/2244 或 http://lenky.info/?p=2244
备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。
法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以或书面等方式告知,本站将及时删除相关内容或链接。