Chinaunix首页 | 论坛 | 博客
  • 博客访问: 116602
  • 博文数量: 22
  • 博客积分: 835
  • 博客等级: 准尉
  • 技术积分: 260
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-25 21:23
文章分类

全部博文(22)

文章存档

2011年(1)

2009年(21)

我的朋友

分类: LINUX

2009-12-04 15:52:25

1、GDB对于基于GNU系统开发的程序员来说是最基本的东西,必须的。所以这篇学习总结中,不打算包括GDB的一般使用方法。因为这些东西必须是随手拈来的。所以也就不花时间来整理,我只把一些比较高级的应用在这里作一个整理。
 
2、在编译链接程序时需要使用"-ggdb"选项来生成可供GDB调试用的信息,否则GDB将失去作用,因此GDB和GCC联系的非常紧密。并且当-g和-O开关同时打开时,调试和优化可能会产生冲突,经常会发现所见和事实不合的情况,所以要选择性地开启优化开关。
 
3、GDB的一些使用技巧:
 1)设置断点的方法包括:函数,行号,if条件断点express,这些前面都可以跟上文件名。另外还可以设置地址断点:b *0x8048424.
 2)GDB用来分析core文件,启动格式:gdb debugme core.xyz
 3)开启core文件生成的方法是: ulimit -c unlimited
 4)在不同函数的调用栈上切换及查看当前信息:bt/frame XX/up/down/info frame/args/locals
 5)调试一正运行的进程:gdb debugme pid或者gdb debugme + attach pid + detach,类似的应用还有:strace/ltrace/truss
 6)如果某个线程/进程处于死锁状态,还可以通过gcore pid来手动生成core文件来分析当前线程/进程的状态,然后利用GDB来分析, gcore使用方法:gcore pid,注意被调试的进程会临时性停止去生成core文件
 7)查看函数的反汇编指令:disassemble fun_name
 8)汇编指令级别的单步执行:ni/si,显示当前执行的汇编指令: x/i $pc
 9)查看寄存器的内容:info registers/all-registers
 10)查看某地址开始的内容:x/num 0xYYYYYYY 查看从0xYYYYYYY开始的num个单元内容;p 输出数组内容
 11)在函数调试中途强制返回:return  ;
 12)向被调试程序发送指定信号:在任意一点ctrl+C进入gdb调试命令行,然后:signal 1-15
 
4、用GDB来调试多线程程序: 
 1)显示当前可调试的所有线程:info threads,GDB按照线程启动顺序重新安排了一个线程ID,这个ID是供GDB使用的
 2)在调试多线程的程序时,默认调试的是主线程,其他线程也同时处于暂停状态,如果想切换调试其他的线程,则只需要:thread id
 3)在对某一线程进行next/step执行的时候,其他线程也同时在执行,如果要限制其他线程执行,则可以使用:set scheduler-locking on
 4)对指定线程或者所有线程执行同样的操作,比如查看调用栈信息:thread apply ID1 ID2/all bt
 5)另外你也可以利用strace -p pid来显示某个线程当前的系统调用情况。或者利用gdb debugme pid来调试某个线程,但注意该方法会暂停整个进程的执行。对于多线程的程序gdb ./debugme相当于默认调试主线程,而gdb ./debugme pid则相当于默认调试pid线程。
 
5、用GDB来调试多进程程序:
 1)当fork子进程后,继续调试父进程或者调试刚产生的子进程:set follow-fork-mode parent/child,注意调试的时候其他的进程仍然在运行。
 2)如果父进程fork了多个子进程,上面的这种方法也只能跟踪调试到第一个子进程,并且不影响其他子进程的运行。
 3)如果想在调试一个进程的时候,其他进程处于暂停状态,则可以利用:set detach-on-fork off来做到
 4)利用attach来调试子进程。因为父进程fork子进程后,子进程会马上得到执行,如果恰好执行过了你要调试的地方,则来不及查询pid并且attach,所以为了支持直接attach调试,一般会在子进程的代码开始处加上一个sleep,以使得你有时间来查询pid,然后attach进入来调试。
   attach pid + stop + break XXX + continue + n + n ...+ s + s + ....
 5)利用gdb ./debugme pid都可以用来调试进程和线程,但不同的是GDB控制的范围不一样,前者不影响其他的并行单元(进程),而后则会使真个进程暂停。 
 
6、调试动态链接库函数:
 我们可能要调试动态库的函数,或者通过调试来学习动态库函数的实现。这个时候,则需要GDB包括该动态库的debug版本,否则在GDB下面只会打印:0xXXXXXX: ??
 比如包括:glibc debug version,如下是一些glibc的debug版本的下载地址:
 
 
注:GDB的远端调试功能,暂时还没有接触过,现不做学习和总结.
 GDB对于多线程,多进程的调试支持并不强大,但可以利用其他专用调试器,比如TotalView:
 参考地址:
         
    
   
7、一些辅助的诊断及调试工具:
 1)strace:跟踪系统调用情况
 2)ltrace:跟踪动态库的调用情况
 3)mtrace,pmalloc:跟踪内存使用情况,需要嵌入代码,打印内存使用记录。 
 4)Binuitls:Toolchain的工具,参考我的上一篇总结。
 5)Valgrind:非常好的内存泄露检测工具,限于i386
 6)oprofile, NPTL Trace Tool等
 7)ald:汇编语言调试器
 8)Dude:另一个运行linux上的调试器,未使用ptrace实现
 9)Linice()是SoftIce在Linux中的模拟软件,用于调试没有源代码的二进制文件的内核级调试器。
 10)其他 
关于调试及诊断工具包括许多,估计可以写一系列的文章来说明。

其他参考资料:
0)GDB官方网站:
1)快速参考GDB支持的所有调试命令:《GDB QUICK REFERENCE》
2)GDB的使用手册:《Debugging with gdb--The gnu Source-Level Debugger》
3)《Embedded linux prime》的第13/14/15章可以作为参考。
 
阅读(1309) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~