gdb调试技巧gdb入门
Posted 奇妙之二进制
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gdb调试技巧gdb入门相关的知识,希望对你有一定的参考价值。
转自网友,我就不重复造轮子了,高阶部分我来补。
一、gdb简介
GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。
一般来说,GDB主要帮助你完成下面四个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。
对于一名Linux下工作的c/c++程序员,gdb是必不可少的工具。gdb不仅仅支持C/C++,还支持go、rust等多种热门语言。
二、gdb使用流程
这里用c程序做基本演示,c++程序也是一样的;
1、启动gdb
编译一个测试程序,-g表示可以调试,命令如下:
gcc -g test.c -o test
启动gdb,命令如下:
gdb test
或者
gdb -q test //表示不打印gdb版本信息,界面较为干净;
测试如下:
root@ubuntu:/home/eit/c_test# gdb test
GNU gdb (Ubuntu 7.7-0ubuntu3) 7.7
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 "x86_64-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) q
root@ubuntu:/home/eit/c_test# gdb -q test
Reading symbols from test...done.
(gdb)
到此gdb启动完成!
进入gdb调试界面的后续操作都是通过gdb命令来完成,接下来介绍几个常用的gdb命令。
2、查看源码
list(简写 l): 查看源程序代码,默认显示10行,按回车键会重复执行上一次的命令。
测试如下:
(gdb) list
9 #define MAX_SIZE
10
11 int main()
12
13 int i,fd,size1 ,size2 ,len;
14 char *buf = "helo!I'm liujiangyong ";
15 char buf_r[15];
16 len = strlen(buf);
17 fd = open("/home/hello.txt",O_CREAT | O_TRUNC | O_RDWR,0666);
18 if (fd<0)
(gdb)
19
20 perror("open :");
21 exit(1);
22
23 else
24
25 printf("open file:hello.txt %d\\n",fd);
26
27 size1 = write(fd,buf,len);
28 if (fd<0)
(gdb)
29
30 printf("writre erro;");
31
32
33 else
34
35 printf("写入的长度:%d\\n写入文本内容:%s\\n",size1,buf);
36
37
38 lseek(fd,0,SEEK_SET);
(gdb)
39 size2 = read(fd,buf_r,12);
40 if (size2 <0)
41
42 printf("read erro\\n");
43
44 else
45
46 printf("读取长度:%d\\n 文本内容是:%s\\n",size2,buf_r);
47
48 close(fd);
(gdb)
49
50
51
(gdb)
Line number 52 out of range; write.c has 51 lines.
(gdb)
3、运行程序
run(简写 r) :运行程序直到遇到 结束或者遇到断点等待下一个命令;
测试如下:
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/eit/c_test/test
open file:hello.txt 3
写入的长度:22
写入文本内容:helo!I'm liujiangyong
读取长度:12
文本内容是:helo!I'm liu
[Inferior 1 (process 19987) exited normally]
(gdb)
4、设置断点
break(简写 b) :格式 b 行号,在某行设置断点;
info breakpoints :显示断点信息
Num: 断点编号
Disp:断点执行一次之后是否有效 kep:有效 dis:无效
Enb: 当前断点是否有效 y:有效 n:无效
Address:内存地址
What:位置
(gdb) b 5
Breakpoint 3 at 0x400836: file write.c, line 5.
(gdb) b 26
Breakpoint 4 at 0x4008a6: file write.c, line 26.
(gdb) b 30
Breakpoint 5 at 0x4008c6: file write.c, line 30.
(gdb) info breakpoints
Num Type Disp Enb Address What
3 breakpoint keep y 0x0000000000400836 in main at write.c:5
4 breakpoint keep y 0x00000000004008a6 in main at write.c:26
5 breakpoint keep y 0x00000000004008c6 in main at write.c:30
(gdb)
有设置断点,自然有删除断点,方法是delete 断点编号
,简写d 断点编号
。
5、执行的几种方式
- continue 继续运行,直到遇到断点才会停止。
- step 陷入运行,想进到函数内部可以使用该命令
- next 就是单步运行,函数会作为整体一步运行。
测试如下:
(gdb) r
Starting program: /home/eit/c_test/test
Breakpoint 3, main () at write.c:12
12
(gdb) n
14 char *buf = "helo!I'm liujiangyong ";
(gdb)
16 len = strlen(buf);
(gdb)
17 fd = open("/home/hello.txt",O_CREAT | O_TRUNC | O_RDWR,0666);
(gdb) s
open64 () at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb)
main () at write.c:18
18 if (fd<0)
(gdb)
25 printf("open file:hello.txt %d\\n",fd);
(gdb)
__printf (format=0x400a26 "open file:hello.txt %d\\n") at printf.c:28
28 printf.c: No such file or directory.
(gdb) c
Continuing.
open file:hello.txt 3
Breakpoint 4, main () at write.c:27
27 size1 = write(fd,buf,len);
(gdb)
Continuing.
写入的长度:22
写入文本内容:helo!I'm liujiangyong
读取长度:12
文本内容是:helo!I'm liu
[Inferior 1 (process 20737) exited normally]
(gdb)
6、查看变量
使用print、whatis命令
测试如下:
main () at write.c:28
28 if (fd<0)
(gdb)
35 printf("写入的长度:%d\\n写入文本内容:%s\\n",size1,buf);
(gdb) print fd
$10 = 3
(gdb) whatis fd
type = int
(gdb)
7、退出gdb
用quit命令退出gdb:
(gdb) r
Starting program: /home/eit/c_test/test
open file:hello.txt 3
写入的长度:22
写入文本内容:helo!I'm liujiangyong
读取长度:12
文本内容是:helo!I'm liu
[Inferior 1 (process 20815) exited normally]
(gdb) q
root@ubuntu:/home/eit/c_test#
gdb很多命令都支持简写,记录如下:
continue(简写 c): 继续执行程序,直到下一个断点或者结束;
next(简写 n ):单步执行程序,但是遇到函数时会直接跳过函数,不进入函数;
step(简写 s) :单步执行程序,但是遇到函数会进入函数;
until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体;
until+行号: 运行至某行,不仅仅用来跳出循环;
finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息;
call 函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55);
quit:简记为 q ,退出gdb;
以上是关于gdb调试技巧gdb入门的主要内容,如果未能解决你的问题,请参考以下文章