GDB调试技巧:gdb at pid无法调试的问题

简介: 作者:gfree.wind@gmail.com 博客:blog.focus-linux.net   linuxfocus.blog.chinaunix.net    本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。
作者:gfree.wind@gmail.com
博客:blog.focus-linux.net   linuxfocus.blog.chinaunix.net
 
 
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
======================================================================================================
今天这个主题有点意思,各位同学听我慢慢道来。

当我们使用GDB调试一个daemon的时候,一般有两种方式:
1. 直接在shell命令行键入gdb attach pid (要调试daemon的进程ID)。一般情况下,我都习惯于缩写gdb at pid;
2. 在shell中键入gdb,进入gdb,然后attach pid(同样是要调试daemon的进程ID)。我不常用这种方式,因为这种方式需要2个步骤——尽管键入的字母是一样的。

下面来说说今天遇到的问题。公司的一个实习生来问我问题。他目前正在做一个工作,大致的功能是得到某个daemon的某一时刻的调用栈——就像gdb一样。但是他发现当daemon处于系统调用状态时,从EBP得到的返回地址不正确。然后我让他直接使用gdb查看是否可以看到完整的调用栈,如果GDB可以,那么就没有问题,可以去看GDB如何实现的。如果不能,再想为什么。——这里先插一句,当时我去查看了他的EBP的值,根据其值获得的返回地址确实不正确。今晚查了查,知道在某些函数调用时,为了速度,EBP有可能并没有被压栈。但是这个不是今天的主题,让我们再转回来。他很快的试了试,告诉我gdb虽然可以使用bt(backtrace)得到函数栈,但是显示出来的结果却不正确。

怎么回事呢?不可能啊。我在他那写了一个很简单的测试程序:
  1. #include <stdlib.h>
  2. #include <stdio.h>

  3. static void test(void)
  4. {
  5.     pause();
  6. }


  7. int main(void)
  8. {
  9.     test();

  10.     return 0;
  11. }
编译并运行:
  1. [xxx@xxx-vm-fc13 test]$ gcc -g test.c
  2. [xxx@xxx-vm-fc13 test]$ ./a.out
然后使用另外一个终端进行调试:
  1. [xxx@xxx-vm-fc13 test]$ ps auwx|grep a.out
  2. xxx 2412 0.0 0.0 1816 288 pts/4 S+ 11:19 0:00 ./a.out
  3. xxx 2415 0.0 0.0 4308 732 pts/5 S+ 11:20 0:00 grep a.out
  4. [xxx@xxx-vm-fc13 test]$ gdb at 2412
  5. GNU gdb (GDB) Fedora (7.1-18.fc13)
  6. Copyright (C) 2010 Free Software Foundation, Inc.
  7. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  8. This is free software: you are free to change and redistribute it.
  9. There is NO WARRANTY, to the extent permitted by law. Type "show copying"
  10. and "show warranty" for details.
  11. This GDB was configured as "i686-redhat-linux-gnu".
  12. For bug reporting instructions, please see:
  13. <http://www.gnu.org/software/gdb/bugs/>...
  14. Reading symbols from /usr/bin/at...(no debugging symbols found)...done.
  15. Attaching to program: /usr/bin/at, process 2412
  16. Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
  17. Loaded symbols for /lib/ld-linux.so.2
  18. 0x009f4424 in __kernel_vsyscall ()
  19. Missing separate debuginfos, use: debuginfo-install at-3.1.12-5.fc13.i686
  20. (gdb) bt
  21. #0 0x009f4424 in __kernel_vsyscall ()
  22. #1 0x0065dac6 in ?? ()
  23. #2 0x080483dc in ?? ()
  24. #3 0x005d6cc6 in ?? ()
  25. #4 0x08048331 in ?? ()
  26. (gdb)
看到这个结果,我还真有些意外。我使用gdb也有些年头了,从来都是这样调试daemon的啊。怎么会这样呢啊?看这个输出,很像没有调试信息啊。可是前面的编译有-g选项啊。

使用第二种方法试试?
  1. [xxx@xxx-vm-fc13 test]$ gdb
  2. GNU gdb (GDB) Fedora (7.1-18.fc13)
  3. Copyright (C) 2010 Free Software Foundation, Inc.
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  5. This is free software: you are free to change and redistribute it.
  6. There is NO WARRANTY, to the extent permitted by law. Type "show copying"
  7. and "show warranty" for details.
  8. This GDB was configured as "i686-redhat-linux-gnu".
  9. For bug reporting instructions, please see:
  10. <http://www.gnu.org/software/gdb/bugs/>.
  11. (gdb) at 2412
  12. Attaching to process 2412
  13. Reading symbols from /home/fgao/works/test/a.out...done.
  14. Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
  15. Loaded symbols for /lib/libc.so.6
  16. Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
  17. Loaded symbols for /lib/ld-linux.so.2
  18. 0x009f4424 in __kernel_vsyscall ()
  19. Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.i686
  20. (gdb) bt
  21. #0 0x009f4424 in __kernel_vsyscall ()
  22. #1 0x0065dac6 in __pause_nocancel () from /lib/libc.so.6
  23. #2 0x080483cf in test () at test.c:6
  24. #3 0x080483dc in main () at test.c:12
  25. (gdb)
啊,这种方式就没有问题啊。怎么回事呢?难道是因为这两种方式的attach还有区别不成?于是我又查了gdb的说明,应该没有区别啊。

想了半天,又试了几次第一种方式,还是没有结果。当我感觉我以前的GDB的世界观都要崩溃的时候,对自己的GDB技能产生了极度的不自信的时候,再次退出gdb的时候,我发现了原因。该原因差点没把我郁闷死。。。

大家想一下哦。。。

  1. (gdb) q
  2. A debugging session is active.
  3. Inferior 1 [process 2412] will be detached.
  4. Quit anyway? (y or n) y
  5. Detaching from program: /usr/bin/at, process 2412
注意看这里的红色代码。进程号没有错,但是program却是/usr/bin/at。My god!原来我使用第一种方式的时候,一直在尝试调试at——这个linux命令。怪不得没有调试信息呢!在我以前的GDB应用中,因为系统中没有at这个命令,所以gdb at pid就等于gdb attach pid,是可以缩写的。但是在当前这个环境中,很并不幸的存在着at这个命令。结果GDB没有尝试去attach,而是直接去调试at命令。

不过这里,我觉得GDB可以做得更友好一些。虽然在这个情况下,GDB去调试at没有问题,但是后面的PID已经被我的测试程序占用了,它应该报个错误或者警告吧。

最后总结一下,GDB的缩写是好,但是小心过分的缩写会与已有命令冲突哦~~总之,缩写需谨慎。
相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
27天前
|
NoSQL 搜索推荐 openCL
【C/C++ 调试 GDB指南 】gdb调试基本操作
【C/C++ 调试 GDB指南 】gdb调试基本操作
48 2
|
3月前
|
NoSQL Linux C语言
调试器gdb
调试器gdb
47 0
|
NoSQL Linux 网络协议
GDB(十)--调试正在运行的进程
我编写了一个循环:     long i;    for (i = 0; i < 999999; i++) {        mt.a += 1;        sleep(1);    }把它编译成a.out,并在后台执行它:./a.out & [1] 2570 然后用命令gdb ./a.out 2570可以附加到这个进程上。
2101 0
|
NoSQL 开发工具 git
GDB 配置
调试器 GDB 的配置
5504 0
|
NoSQL Python
gdb kernel debug的进程断点
gdb调试kernel的时候, 如果设置通用函数断点, 比如vfs_read, 就会遇到一堆撞到断点的地方, 比如tty输入一个字符, 就是vfs_read, 没办法调试具体的某一个进程 一种办法就是条件断点, 其实不是很好用, 比如用pid, 但是有时候这个进程还没启动, 比如task的comm来判定, 但是kernel中是不支持strcmp来判断字符串是否相等, 因为需要跑函数 g
10901 0
|
Web App开发 NoSQL Linux
使用GDB命令行调试器调试C/C++程序【转】
转自:https://linux.cn/article-4302-1.html 编译自:http://xmodulo.com/gdb-command-line-debugger.html作者: Adrien Brochard原创:LCTT https://linux.
1346 0