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入门的主要内容,如果未能解决你的问题,请参考以下文章

GDB 多进程调试

gdb调试工具

gdb调试技巧 找到php执行进程当前执行的代码

gdb调试

gdb调试基本技巧

gdb调试基本技巧