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

简介:
作者: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
目录
相关文章
|
3月前
|
NoSQL Linux C语言
Linux GDB 调试
Linux GDB 调试
62 10
|
3月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
|
3月前
|
NoSQL
技术分享:如何使用GDB调试不带调试信息的可执行程序
【8月更文挑战第27天】在软件开发和调试过程中,我们有时会遇到需要调试没有调试信息的可执行程序的情况。这可能是由于程序在编译时没有加入调试信息,或者调试信息被剥离了。然而,即使面对这样的挑战,GDB(GNU Debugger)仍然提供了一些方法和技术来帮助我们进行调试。以下将详细介绍如何使用GDB调试不带调试信息的可执行程序。
99 0
|
5月前
|
NoSQL Linux C语言
Linux gdb调试的时候没有对应的c调试信息库怎么办?
Linux gdb调试的时候没有对应的c调试信息库怎么办?
42 1
|
5月前
|
NoSQL Linux C语言
Linux gdb调试的时候没有对应的c调试信息库怎么办?
Linux gdb调试的时候没有对应的c调试信息库怎么办?
31 0
|
5月前
|
NoSQL Linux C++
Linux C/C++ gdb调试正在运行的程序
Linux C/C++ gdb调试正在运行的程序
|
5月前
|
NoSQL Linux C++
Linux C/C++ gdb调试core文件
Linux C/C++ gdb调试core文件
|
6月前
|
NoSQL 搜索推荐 openCL
【C/C++ 调试 GDB指南 】gdb调试基本操作
【C/C++ 调试 GDB指南 】gdb调试基本操作
378 2
|
6月前
|
NoSQL Linux 开发工具
【深入解析git和gdb:版本控制与调试利器的终极指南】(下)
【深入解析git和gdb:版本控制与调试利器的终极指南】
|
5月前
|
NoSQL Linux C++
Linux C/C++ gdb调试
Linux C/C++ gdb调试