Linux下gdb的安装及使⽤⼊门
1、安装gdb。
在root⽤户权限下:
root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get update
......
......
......
root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get install gdb
......
......
......
Do you want to continue? [Y/n] y
......
......
......
root@iZ2zeeailqvwws5dcuivdbZ:~#
安装好gdb了。
2、gdb的简单使⽤。
⽤root权限的Terminal(或⼀般权限的Terminal)的vi编辑器编写⼀个C程序a.c:
1 #include <stdio.h>
2
3int main()
4 {
5 int a = 1;
6 int b = a;
7
8 printf("a = %d, b =%d\n", a, b);
9
10 return0;
11 }
(1) 在可执⾏⽂件中加⼊源码信息
这个过程通过gcc来完成:
gcc –o a a.c -g
-
o选项的作⽤是:对命令输出结果进⾏导⼊操作,这⾥是把gcc –o a a.c -g的操作结果输出到⽂件a(⽂件名可以⾃定义)中进⾏保存。
-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 </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:
</software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
</software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols done.
(gdb)
如下图所⽰:
gdb提供⼀个类似Shell的命令⾏环境,上⾯的(gdb)就是提⽰符,在提⽰符后⾯输⼊gdb的相应命令就可以实现其对应的功能。
(3) gdb调试常⽤命令
[1] start
⽤start命令开始执⾏程序:
(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
5int 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
5int a = 1;
(gdb) n
6int b = a;
(gdb) n
8 printf("a = %d, b = %d\n", a, b);
(gdb) n
a = 1,
b = 1
9return0;
(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模式。
ubuntu使用入门教程 [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
5int 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
9return0;
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 </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:
</software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
</software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols 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
5int 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 0x0000000000400552in 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 </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:
</software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
</software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols 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
5int 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)查看各级函数调⽤及参数
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
可以显⽰所有寄存器的当前值。在gdb中表⽰寄存器名时前⾯要加个$,例如p $esp可以打印esp寄存器的值。
registers
set follow-fork-mode child/parent设置gdb在fork之后跟踪⼦进程/⽗进程
set args 'command-line'给执⾏的程序传命令⾏参数
s(stepin)进⼊⼦函数
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论