C实战:强大的程序调试工具GDB

标签: 程序 调试工具 gdb | 发表时间:2015-06-13 05:21 | 作者:dc_726
出处:http://blog.csdn.net

C实战:强大的程序调试工具GDB

1.基本调试

这里只列举最最常用的GDB命令。

1.1 启动GDB

gdb program:准备调试程序。也可以直接进入gdb,再通过file命令加载。

1.2 添加断点

b function:为函数设置断点。b是break的缩写,除了函数名,还可以是地址、当前执行处的+/-偏移等。

1.3 运行程序

run args:开始运行程序,run后面可以加程序需要的参数,就像在命令行正常运行时那样。

1.4 单步调试

s/n/si/c/kill:s即step in,进入下一行代码执行;n即step next,执行下一行代码但不进入;si即step instruction,执行下一条汇编/CPU指令;c即continue,继续执行直到下一个断点处;kill终止调试;quit退出GDB。

1.5 打印调试信息

bt:bt是backtrace的缩写,打印当前所在函数的堆栈路径。
info frame id:打印选中的栈帧的信息。
info args:打印选中栈帧的参数。
print variable:打印指定变量的值。
list:列出相应的源代码。
info registers:查看所有寄存器的值。

还有个更灵活强大的是直接打印%esp开始的前N个元素,例如打印栈上前10个元素就是: x/10x $sp

2.GDB实战

下面是一个使用了上述命令的实战例子:

  [root@BC-VM-edce4ac67d304079868c0bb265337bd4 bufbomb]# gdb bufbomb 
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/Temp/bufbomb/bufbomb...done.
(gdb) b getbuf
Breakpoint 1 at 0x8048ad6
(gdb) run -t cdai
Starting program: /root/Temp/bufbomb/bufbomb -t cdai
Team: cdai
Cookie: 0x5e5ee04e

Breakpoint 1, 0x08048ad6 in getbuf ()
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6_6.4.i686

(gdb) bt
#0  0x08048ad6 in getbuf ()
#1  0x08048db2 in test ()
#2  0x08049085 in launch ()
#3  0x08049257 in main ()
(gdb) info frame 0
Stack frame at 0xffffb540:
 eip = 0x8048ad6 in getbuf; saved eip 0x8048db2
 called by frame at 0xffffb560
 Arglist at 0xffffb538, args: 
 Locals at 0xffffb538, Previous frame's sp is 0xffffb540
 Saved registers:
  ebp at 0xffffb538, eip at 0xffffb53c
(gdb) info registers
eax            0xc      12
ecx            0xffffb548       -19128
edx            0xc8c340 13157184
ebx            0x0      0
esp            0xffffb510       0xffffb510
ebp            0xffffb538       0xffffb538
esi            0x804b018        134524952
edi            0xffffffff       -1
eip            0x8048ad6        0x8048ad6 <getbuf+6>
eflags         0x282    [ SF IF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0      0
gs             0x63     99
(gdb) x/10x $sp
0xffffb510:     0xf7ffc6b0      0x00000001      0x00000001      0xffffb564
0xffffb520:     0x08048448      0x0804a12c      0xffffb548      0x00c8aff4
0xffffb530:     0x0804b018      0xffffffff

(gdb) si
0x08048ad9 in getbuf ()
(gdb) si
0x08048adc in getbuf ()
(gdb) si
0x080489c0 in Gets ()
(gdb) n
Single stepping until exit from function Gets,
which has no line number information.
Type string:123
0x08048ae1 in getbuf ()
(gdb) si
0x08048ae2 in getbuf ()
(gdb) c
Continuing.
Dud: getbuf returned 0x1
Better luck next time

Program exited normally.
(gdb) quit

3.逆向调试

GDB 7.0后加入了Reversal Debugging功能。具体来说,比如我在getbuf()和main()上设置了断点,当启动程序时会停在main()函数的断点上。此时敲入record后continue到下一断点getbuf(),GDB就会记录从main()到getbuf()的运行时信息。现在用rn就可以逆向地从getbuf()调试到main()。就像《X战警:逆转未来》里一样,挺神奇吧!

这种方式适合从bug处反向去找引起bug的代码,实用性因情况而异。当然,它也是有局限性的。像程序假如有I/O输出等外部条件改变时,GDB是没法“逆转”的。

  [root@vm bufbomb]# gdb bufbomb 
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/Temp/bufbomb/bufbomb...done.

(gdb) b getbuf
Breakpoint 1 at 0x8048ad6
(gdb) b main
Breakpoint 2 at 0x80490c6

(gdb) run -t cdai
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /root/Temp/bufbomb/bufbomb -t cdai

Breakpoint 2, 0x080490c6 in main ()
(gdb) record
(gdb) c
Continuing.
Team: cdai
Cookie: 0x5e5ee04e

Breakpoint 1, 0x08048ad6 in getbuf ()

(gdb) rn
Single stepping until exit from function getbuf,
which has no line number information.
0x08048dad in test ()
(gdb) rn
Single stepping until exit from function test,
which has no line number information.
0x08049080 in launch ()
(gdb) rn
Single stepping until exit from function launch,
which has no line number information.
0x08049252 in main ()
作者:dc_726 发表于2015/6/12 21:21:02 原文链接
阅读:0 评论:0 查看评论

相关 [程序 调试工具 gdb] 推荐:

gdb调试工具

- - CSDN博客系统运维推荐文章
查看帮助一是man 命令,二是进入 www.gnu.org,找到gdb的帮助文档(更详细). gcc -Wall -g main.c -o main,只有这样才能产生调试信息,包括core的调试信息.     run(r)  运行,执行到断点,重新用r,表示重新开始执行.     list(l)  列出源代码,l 2,l main,l 2,16(数字表示行数).

C实战:强大的程序调试工具GDB

- - CSDN博客综合推荐文章
C实战:强大的程序调试工具GDB. 这里只列举最最常用的GDB命令. gdb program:准备调试程序. 也可以直接进入gdb,再通过file命令加载. b function:为函数设置断点. b是break的缩写,除了函数名,还可以是地址、当前执行处的+/-偏移等. run args:开始运行程序,run后面可以加程序需要的参数,就像在命令行正常运行时那样.

Linux下gdb调试工具的使用

- - CSDN博客综合推荐文章
gdb是GNU开源组织发布的一个强大的Linux下的程序调试工具. gdb主要完成四个方面的功能:(1)、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序;(2)、可让被调试的程序在你所指定的调试的断点处停住(断点可以是条件表达式);(3)、当程序被停住时,可以检查此时你的程序中所发生的事;(4)、动态的改变你程序的执行环境.

用gdb+nm调试php c extension程序

- ndv - 淘宝核心系统团队博客
最近在写Beanstalkd的php c extension客户端程序,写程序离不开调试,下面把调试中碰到的问题和解决方法和大家分享一下. .so写好了是给php脚本调用的,如果php脚本执行崩掉了,.so也只能在进程中饮恨而终,这时候php脚本调试经常用的echo, print_r, var_dump都派不上用场了.

使用gdb调试运行时的程序小技巧

- - 淘宝核心系统团队博客
转载请注明:转载自淘宝核心系统团队博客,谢谢. 原文链接地址: 使用gdb调试运行时的程序小技巧. 下面介绍我调试时经常遇到的三种问题,如果大家也有类似的问题交流一下解决方法:. 情景1:在不中止程序服务的情况下,怎么调试正在运行时的程序. 情景2:需要同时看几个变量的值或者批量查看多个core文件的堆栈信息怎么办.

与符号表分离程序或动态库, 如何用GDB调试

- - 搜索技术博客-淘宝
GDB支持用户将程序调试信息放在一个独立的文件里,而不是和可执行程序在一个文件中,GDB可以某种方式来查找和自动加载调试信息. 由于调试信息可能非常大,有时可能比可执行代码自身还要大,某些系统将其可执行程序的调试信息以单独的文件发布,在需要调试问题的时候,用户可以再安装这些文件. GDB支持两种设置单独调试信息文件的方式:.

Linux下gdb调试

- - CSDN博客移动开发推荐文章
关于gdb的其他客套话不多说,直接进入正题. 列出产生执行文件源代码的一部分. 执行一行源代码但不进入函数内部. 执行一行源代码而且进入函数内部. 监视一个变量的值,一旦值有变化程序停住. 1.新建一个源文件vi yrp.cc,源代码如下:. 2.生成可执行文件 g++ -g -o yrp yrp.cc  注意必须使用-g参数,编译会加入调试信息,否则无法调试执行文件..

[转]GDB调试多线程

- - 小彰
GDB 多线程调试基本命令 实现简介 以及一个问题的解决. 一直对GDB多线程调试接触不多,最近因为工作有了一些接触,简单作点记录吧. 先介绍一下GDB多线程调试的基本命令. 显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID. 切换当前调试的线程为指定ID的线程.

Linux下进行GDB调试

- - CSDN博客推荐文章
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具. 一般来说,GDB主要帮助自己完成下面四个方面的功能;. 1:启动你的程序,可以按照你的自定义的要求随心所欲的运行程序. 2:可以让被调试的程序在你所指定的调制的断点处停住(断点可以是条件表达式). 3:当程序被停住时,可以检查你的程序中发生的事.

GDB学习之道:GDB调试精粹及使用实例

- - CSDN博客系统运维推荐文章
要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、. 如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的. 利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表.