Linux下gdb的安装及使用入门

一、安装gdb。

在root用户权限下:html

root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get update
......
......
......
root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get install gdb 
......
......
......
Do you want to continue? [Y/n] y
......
......
......
root@iZ2zeeailqvwws5dcuivdbZ:~# 

安装好gdb了。linux

二、gdb的简单使用。

用root权限的Terminal(或通常权限的Terminal)的vi编辑器编写一个C程序a.c:redis

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5   int a = 1;
 6   int b = a;
 7 
 8   printf("a = %d, b =%d\n", a, b);
 9 
10   return 0;
11 }

(1) 在可执行文件中加入源码信息

这个过程经过gcc来完成:ubuntu

gcc –o a a.c -g sass

-o选项的做用是:对命令输出结果进行导入操做,这里是把gcc –o a a.c -g的操做结果输出到文件a(文件名能够自定义)中进行保存。session

-g选项的做用是:在可执行文件中加入源码信息,好比:可执行文件中第几条机器指令对应源代码的第几行,但并非把整个源文件都嵌入到可执行文件中,而是在调试时必须保证gdb能找到源文件。编辑器

(2) 进入gdb

root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gcc -o a a.c -g
root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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 a...done.
(gdb) 

以下图所示:函数

gdb提供一个相似Shell的命令行环境,上面的(gdb)就是提示符,在提示符后面输入gdb的相应命令就能够实现其对应的功能。ui

(3) gdb调试经常使用命令

  [1] start

  用start命令开始执行程序:spa

(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) 

  gdb提示准备执行a.c程序的第六行代码。而后继续用(gdb)提示须要输入的命令。

  [2] 单步执行(n)

(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) n 6           int b = a;
(gdb) n 8           printf("a = %d, b = %d\n", a, b);
(gdb) n
a = 1, b = 1
9           return 0;
(gdb) quit
A debugging session is active.

        Inferior 1 [process 22935] will be killed.

Quit anyway? (y or n) y
root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# 

  在start命令后,每输入一个n就可以单步执行一条语句(输入一个命令后,直接回车表示最近输入命令的含义)。当程序执行完时,能够输入quit命令来退出gdb模式。

  [3] gdb断点调试

  [ breakpoint,continue和display ]

(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) b 8
Breakpoint 2 at 0x40053b: file a.c, line 8.
(gdb) c
Continuing.

Breakpoint 2, main () at a.c:8
8           printf("a = %d, b = %d\n", a, b);
(gdb) display b 1: b = 1
(gdb) n
a = 1, b = 1
9           return 0;
1: b = 1
(gdb) 
10      }
1: b = 1
(gdb) quit
root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# 

  gdb  a会进入a可执行程序的gdb模式,start命令就使程序准备运行程序中的第一条语句。b 8是breakpoint  8的简写(breakpoint的参数也能够以是某个函数名,表示在此函数处设置一个断点),表示在程序第八行设置一个断点。c是continue的缩写,表示继续运行程序,程序会在设置断点处停下来。displayb表示将b的值显示出来(undisplay取消对变量的跟踪),而后再输入单步调试命令n(next)就可使程序继续运行。

  可见断点有助于快速跳过没有问题的代码,而后在有问题的代码上慢慢走慢慢分析,“断点加单步”是使用调试器的基本方法。至于应该在哪里设置断点,怎么知道哪些代码能够跳过,而哪些代码要慢慢走,也要经过对错误现象的分析和假设来肯定,之前咱们用printf打印中间结果时,也要分析应该在哪里插入printf,打印哪些中间结果,调试的基本思路是同样的。

  [4]info

  一次调试能够设置多个断点,用info命令能够查看已经设置的断点:

root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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 a...done.
(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) b 7
Breakpoint 2 at 0x40053b: file a.c, line 7.
(gdb) b 8
Note: breakpoint 2 also set at pc 0x40053b.
Breakpoint 3 at 0x40053b: file a.c, line 8.
(gdb) i breakpoints 
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040053b in main at a.c:7
3       breakpoint     keep y   0x000000000040053b in main at a.c:8
(gdb) 

  [5]delete

  每一个断点都有一个编号(有的断点行数不同,但地址却同样,有的地方不可以设置断点或者说与上一个设置的断点等效),能够用编号指定删除某个断点。

......
(gdb) b 7 Breakpoint 2 at 0x40053b: file a.c, line 7. (gdb) b 8 Note: breakpoint 2 also set at pc 0x40053b. Breakpoint 3 at 0x40053b: file a.c, line 8. (gdb) i breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x000000000040053b in main at a.c:7 3 breakpoint keep y 0x000000000040053b in main at a.c:8 (gdb) delete 3 (gdb) i breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x000000000040053b in main at a.c:7 (gdb)

  有时候一个断点暂时不用能够禁用掉而没必要删除,这样之后想用的时候能够直接启用,而没必要从新从代码里找应该在哪一行设断点,这个过程用 disable 和 enable 来完成。

  [6]条件断点 (break 和run

  gdb的断点功能很是灵活,还能够设置断点在知足某个条件时才激活,例如:

......
//先把其他的断点删掉。
(gdb) b 9 if a == 2 Breakpoint 5 at 0x400552: file a.c, line 9. (gdb) i breakpoints Num Type Disp Enb Address What 5 breakpoint keep y 0x0000000000400552 in main at a.c:9 stop only if a == 2 (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/2/02/a a = 1, b = 1 [Inferior 1 (process 22968) exited normally] (gdb)

  r表示从头开始运行程序,在a==2的条件下中断才有效。a不等于2,因此中断无效。  

  [7] gdb的观察点(watch 和c

  断点是当程序执行到某一代码行时中断,而观察点是当程序访问某个存储单元时中断,若是咱们不知道某个存储单元是在哪里被改动的,这时候观察点尤为有用。

root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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 a...done.
(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) watch b
Hardware watchpoint 2: b
(gdb) c
Continuing.

Hardware watchpoint 2: b

Old value = 0
New value = 1
main () at a.c:8
8           printf("a = %d, b = %d\n", a, b);
(gdb) 

  程序执行到b存储单元,将此执行单元执行先后的值都显示出来。

  [8] 段错误

  若是程序运行时出现段错误,用gdb能够很容易定位到到底是哪一行引起的段错误。在gdb中运行,遇到段错误会自动停下来,这时能够用命令查看当前执行到哪一行代码了。

  gdb显示段错误出如今 _IO_vfscanf 函数中,用bt命令能够看到是哪个函数调用了它。

  [9] gdb基本命令

  gdb有许多有用的命令如list(显示源代码),这样就能够结合源码与调试信息更好的进行调试。将gdb经常使用命令摘抄以下表:

命令

描述

backtrace(bt)

查看各级函数调用及参数

finish

连续运行到当前函数返回为止,而后停下来等待命令

frame(f)  帧编号

选择栈帧

info(i)  locals

查看当前栈帧局部变量的值

list(l)

列出源代码,接着上次的位置往下列,每次列十行

list  行号

列出第几行开始的源代码

list  函数名

列出某个函数的源代码

next(n)

执行下一行语句

print(p)

打印表达式的值,经过表达式的值能够修改变量的值或者调用函数

quit(q)

退出gdb调试环境

set  var

修改变量的值

start

开始执行程序,停在main函数第一行语句前面等待命令

step(s)

执行下一行语句,若是有函数则进入到函数中

break(b)  行号

在某一行设置断点

break  函数名

在某个函数开头设置断点

break(b)… if…

设置条件断点

continue(c)

从当前位置开始连续运行程序

delete breakpoints 断点号

删掉此号的断点

display  变量名

跟踪查看某个变量,每次停下来都显示它的值

disable  breakpoints 断点号

禁用此断点

enable  断点号

启用此断点

info(i)  breakpoints

查看当前设置了哪些断点

run(r)

从头开始连续运行程序

undisplay  跟踪显示行号

取消跟踪显示

watch

设置观察点

info(i)   watchpoints

查看当前设置了哪些观察点

x

从某个位置开始打印存储单元的内容,所有当成字节来看,而不区分哪一个字节属于哪一个变量

 

disassemble

反汇编当前函数或者指定的函数,单独用disassemble命令是反汇编当前函数,若是disassemble命令后面跟函数名或地址则反汇编指定的函数。

si

能够一条指令一条指令地单步调试。

info  registers

能够显示全部寄存器的当前值。在gdb中表示寄存器名时前面要加个$,例如p $esp能够打印esp寄存器的值。

set follow-fork-mode child/parent 设置gdb在fork以后跟踪子进程/父进程
set  args  'command-line' 给执行的程序传命令行参数
s(stepin) 进入子函数
相关文章
相关标签/搜索