首页 > 代码库 > gdb基础知识一
gdb基础知识一
gdb是Linux下c/c++必不可少的调试工具,其强大相较于其他IDE完全有过之而无不及。本文主要介绍gdb的一些基础使用,启动调试器,设置断点,显示变量值,单步执行等。
以下面一段小代码test.c为例,执行环境ubuntu14.04, 32位:
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int sum; 5 6 void swap(int *m, int *n) 7 { 8 int tmp; 9 10 tmp = *m; 11 *m = *n; 12 *n = tmp; 13 } 14 15 int diff_fun(int x, int y) 16 { 17 int tmp_sum; 18 19 if (x > y) { 20 swap(&x, &y); 21 } 22 23 tmp_sum = y - x; 24 25 return tmp_sum; 26 } 27 28 int main() 29 { 30 int a, b; 31 32 a = 10; 33 b = 5; 34 sum = diff_fun(a, b); 35 36 return sum; 37 }
1、准备
要使用GDB进行调试,须在gcc编译时使用-g选项,如:
gcc -g -Wall test.c -o test
2、启动调试器
#gdb ./test ----->执行gdb
root@zhuzhu:test_work# gdb ./test
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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 "i686-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./test...done.
(gdb)
(gdb) start ----->开始调试
Temporary breakpoint 1 at 0x8048421: file gdb.c, line 32.
Starting program: /root/work/test_work/test
Temporary breakpoint 1, main () at gdb.c:32
32a = 10;
(gdb)
3、设置断点
gdb设置断点可以有很多的方式,可以根据函数、行号、当前位置偏移、地址等来下断点。break写的时候也可以简写为b,如:
break 行号 break 函数名 break +偏移量 b -偏移量 b *地址
如执行:
(gdb) list ----->列出附近行的代码
27
28int main()
29{
30int a, b;
31
32a = 10;
33b = 5;
34sum = diff_fun(a, b);
35
36return sum;
(gdb) b diff_fun ----->对diff_fun打断点
Breakpoint 2 at 0x80483eb: file gdb.c, line 19.
(gdb) b 23 ----->在23行处打断点
Breakpoint 3 at 0x8048407: file gdb.c, line 23.
(gdb) b +1 ----->暂停位置向下偏移一行处打断点
Breakpoint 4 at 0x8048428: file gdb.c, line 33.
(gdb) disas diff_fun ----->反汇编指定函数代码,若不跟函数名,默认反汇编当前函数
Dump of assembler code for function diff_fun:
0x080483e5 <+0>:push %ebp
0x080483e6 <+1>:mov %esp,%ebp
0x080483e8 <+3>:sub $0x18,%esp
0x080483eb <+6>:mov 0x8(%ebp),%edx
0x080483ee <+9>:mov 0xc(%ebp),%eax
0x080483f1 <+12>:cmp %eax,%edx
0x080483f3 <+14>:jle 0x8048407 <diff_fun+34>
0x080483f5 <+16>:lea 0xc(%ebp),%eax
0x080483f8 <+19>:mov %eax,0x4(%esp)
0x080483fc <+23>:lea 0x8(%ebp),%eax
0x080483ff <+26>:mov %eax,(%esp)
0x08048402 <+29>:call 0x80483c3 <swap>
0x08048407 <+34>:mov 0xc(%ebp),%edx
0x0804840a <+37>:mov 0x8(%ebp),%eax
0x0804840d <+40>:mov %edx,%ecx
0x0804840f <+42>:sub %eax,%ecx
0x08048411 <+44>:mov %ecx,%eax
0x08048413 <+46>:mov %eax,-0x4(%ebp)
0x08048416 <+49>:mov -0x4(%ebp),%eax
0x08048419 <+52>:leave
0x0804841a <+53>:ret
End of assembler dump.
(gdb)b *0x080483e8 ----->在指定的地点打上断点
Breakpoint 5 at 0x80483e8: file gdb.c, line 16.
(gdb) i b ----->查看所设断点
Num Type Disp Enb Address What
2 breakpoint keep y 0x080483eb in diff_fun at gdb.c:19
3 breakpoint keep y 0x08048407 in diff_fun at gdb.c:23
4 breakpoint keep y 0x08048428 in main at gdb.c:33
5 breakpoint keep y 0x080483e8 in diff_fun at gdb.c:16
4、显示变量、寄存器、地址的值和单步执行
print用来显示变量的值,简写为p
info可以用来显示寄存器的值,简写为i
x命令用来显示内存的内容
(gdb)run ---->继续执行直到遇到第一个断点
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/work/test_work/test
Breakpoint 4, main () at gdb.c:33
33 b = 5;
(gdb) layout split ---->在不同窗口下查看源代码和汇编代码,及当前暂停的位置
(gdb) p a ----->打印变量a
$2 = 10
(gdb)
同样p也可以给变量赋值,如:
(gdb) p a=9 ----->修改变量a的值
$3 = 9
(gdb) p a
$4 = 9
(gdb)
(gdb) info reg ----->显示多有寄存器的值
eax 0x1 1
ecx 0xaace997e -1429300866
edx 0xbffff614 -1073744364
ebx 0xb7fbe000 -1208229888
esp 0xbffff5d0 0xbffff5d0 --->可能会经常用到
ebp 0xbffff5e8 0xbffff5e8
esi 0x0 0
edi 0x0 0
eip 0x8048428 0x8048428 <main+13> --->可能会经常用到
eflags 0x282 [ SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)
其中指向栈顶的sp和程序计数器ip可能会经常用到,也可以单独显示某个寄存器,如,
(gdb) p $eip ----->打印某个寄存器
$5 = (void (*)()) 0x8048428 <main+13>
(gdb)
print还支持多种打印格式,如:
x 显示为十六进制
d 显示为十进制
o 显示为八进制
a 显示地址
c 显示字符类型
f 显示浮点小数类型
s 显示为字符串
i 显示为机器语言(x命令可用)
(gdb) p/c a ---->字符形式显示变量a的值
$6 = 9 ‘\t‘
(gdb)
(gdb) x &a ----->显示变量a所在地址的值
0xbffff5e4: 9 ‘\t‘
(gdb) x/i a
0x9: Cannot access memory at address 0x9
(gdb) x/i &a ----->显示变量a地址的汇编指令
0xbffff5e4: or %eax,(%eax)
(gdb)
(gdb) c ----->continue继续执行,简写为c,暂停在下一个断点处
Continuing.
Breakpoint 2, diff_fun (x=9, y=5) at gdb.c:19
19 if (x > y) {
(gdb) l
14
15 int diff_fun(int x, int y)
16 {
17 int tmp_sum;
18
19 if (x > y) {
20 swap(&x, &y);
21 }
22
23 tmp_sum = y - x;
(gdb)
(gdb) bt ------>backtrace显示所有栈帧
#0 diff_fun (x=9, y=5) at gdb.c:19
#1 0x08048441 in main () at gdb.c:34
(gdb
(gdb) frame 1 ----->进入栈帧1
#1 0x08048441 in main () at gdb.c:34
34 sum = diff_fun(a, b);
(gdb) i locals
a = 9
b = 5
(gdb) frame 0 ------>进入栈帧0
#0 diff_fun (x=9, y=5) at gdb.c:19
19 if (x > y) {
(gdb) bt
#0 diff_fun (x=9, y=5) at gdb.c:19
#1 0x08048441 in main () at gdb.c:34
(gdb)
(gdb) bt full ----->显示每个栈帧更全面的信息
#0 diff_fun (x=9, y=5) at gdb.c:19
tmp_sum = 134513408
#1 0x08048441 in main () at gdb.c:34
a = 9
b = 5
(gdb)
单步执行有next和step其中后者会进入函数,前者不会,加上i的话nexti、stepi,单步汇编指令,这在大型程序中较少用到。
删除断点的话,使用d 编号
(gdb) i b
Num Type Disp Enb Address What
2 breakpoint keep y 0x080483eb in diff_fun at gdb.c:19
breakpoint already hit 1 time
3 breakpoint keep y 0x08048407 in diff_fun at gdb.c:23
4 breakpoint keep y 0x08048428 in main at gdb.c:33
breakpoint already hit 1 time
5 breakpoint keep y 0x080483eb in diff_fun at gdb.c:16
breakpoint already hit 1 time
(gdb) d 2 ----->delete 编号2断点
(gdb) i b
Num Type Disp Enb Address What
3 breakpoint keep y 0x08048407 in diff_fun at gdb.c:23
4 breakpoint keep y 0x08048428 in main at gdb.c:33
breakpoint already hit 1 time
5 breakpoint keep y 0x080483eb in diff_fun at gdb.c:16
breakpoint already hit 1 time
(gdb)
以上是gdb的一些基本命令,接下来会介绍一些常见的应用场景。
参考资料:
gdb 调试入门,大牛写的高质量指南
debug hacks
man page
本文出自 “12128867” 博客,请务必保留此出处http://12138867.blog.51cto.com/12128867/1910950
gdb基础知识一