GDB
是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。。
下面举一个调试例子对其用法加以说明:
源程序:a.c
1 #include<stdio.h>
2 #include<string.h>
3 int main(int argc,char* argv[])
4 {
5 unsigned short s;
6 int i;
7 char buf[10];
8
9 if(argc < 3)
10 {
11 printf("Usage:%s <length><string>\n",argv[0]);
12 return -1;
13 }
14
15 i=atoi(argv[1]);
16 s=i;
17
18 if(s>=10)
19 {
20 printf("string too long!\n");
21 return -1;
22 }
23
24 memcpy(buf,argv[2],i);
25 buf[i]='\0';
26 printf("%s\n",buf);
27 return 0;
28 }
操作步骤:
1. gcc -g a.c -o a.out
<-
编译时-g 打开调试选项;
2. gdb a.out
<-
注意gdb后面跟的是可执行程序;
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(gdb)l
<-
l
是list的缩写,是查看源程序内容的命令;
1 #include<stdio.h>
2 #include<string.h>
3 int main(int argc,char* argv[])
4 {
5 unsigned short s;
6 int i;
7 char buf[10];
8
9 if(argc < 3)
10 {
(gdb)<enter>
<-
直接回车时重复执行上次的命令;
11 printf("Usage:%s <length><string>\n",argv[0]);
12 return -1;
13 }
14
15 i=atoi(argv[1]);
16 s=i;
17
18 if(s>=10)
19 {
20 printf("string too long!\n");
(gdb)b 15
<-
b +
数字 是在某一行设置一个断点,可以同时设置多个断点;
Breakpoint 1 at 0x80483c4: file overflow.c, line 15.
ç
显示出断点的信息;
(gdb)r 5 hello
<-
运行程序,在设置的断点处停止。注意程序的运行规则,如加参数等;
Starting program: /root/test/day7/a.out 5 hello
Breakpoint 1, main (argc=3, argv=0xbfffdea4) at overflow.c:15
ç
停止在断点处;
15 i=atoi(argv[1]);
(gdb)p i
<-
查看一下此时变量i的值;
$1 = -1073747112
<-
由于i此时还未有值,出现一个随机的值;
(gdb)n
<-
单步执行程序后半部分;
16 s=i;
<-
显示执行的是哪一行;
(gdb)p i
<-
查看执行上一步语句之后变量i的值;
$2 = 5
(gdb)info break
<-
查看整个程序断点信息,如断点的个数及其位置;
Num Type Disp Enb Address What
1 breakpoint keep y 0x080483c4 in main at overflow.c:15
breakpoint already hit 1 time
(gdb)info all
<-
显示整个程序运行到此时,各个寄存器中的值;
eax 0x5 5
ecx 0x0 0
edx 0x5 5
ebx 0x42130a14 1108544020
esp 0xbfffeb20 0xbfffeb20
ebp 0xbfffeb58 0xbfffeb58
esi 0x40015360 1073828704
edi 0x8048474 134513780
eip 0x80483da 0x80483da
eflags 0x10382 66434
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x33 51
st0 0 (raw 0x00000000000000000000)
st1 0 (raw 0x00000000000000000000)
st2 0 (raw 0x00000000000000000000)
st3 0 (raw 0x00000000000000000000)
st4 0 (raw 0x00000000000000000000)
st5 0 (raw 0x00000000000000000000)
st6 0 (raw 0x00000000000000000000)
st7 0 (raw 0x00000000000000000000)
fctrl 0x37f 895
fstat 0x0 0
ftag 0xffff 65535
fiseg 0x0 0
fioff 0x0 0
foseg 0x0 0
fooff 0x0 0
fop 0x0 0
xmm0 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}
xmm1 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}
xmm2 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}
xmm3 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}
xmm4 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}
xmm5 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}
xmm6 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}
xmm7 {v4_float = {0x0, 0x0, 0x0, 0x0}, v2_double = {0x0, 0x0}, v16_int8 = {0x0 <repeats 16 times>}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x00000000000000000000000000000000}
mxcsr 0x1f80 8064
mm0 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0, 0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm1 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0, 0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm2 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0, 0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm3 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0, 0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm4 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0, 0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm5 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0, 0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
---Type <return> to continue, or q <return> to quit---
mm6 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0, 0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
mm7 {uint64 = 0x0, v2_int32 = {0x0, 0x0}, v4_int16 = {0x0, 0x0, 0x0, 0x0}, v8_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}
(gdb)file b.out
<-
继续调试另外一个程序;
一般来说,GDB主要用到以下几个功能:
1
、可以设置断点(断点可以是条件表达式),然后按照你的设置单步运行程序。
2
、当程序被停住时,可以检查此时你的程序中所发生的事,比如某一个标志性的变量的值的变化是否按照程序的目标运行。
3
、在单步运行过程中,随时查看变量的变化,如果出现异常可立即发现错误语句的位置,然后排错。
4
、动态的查看程序运行中各个寄存器中的值。