一、gdb的简介
GDB是一个由GNU开源组织发布的,Unix/Linux操作系统下的,基于命令行的,功能强大的程序调试工具。
二、gdb源码安装方法
Linux系统及其衍生版本有的默认安装了gdb调试器,但有些默认不安装。
1、检查系统是否默认安装
执行
gdb -v
指令,如果提示gdb: command not found
则没有安装,否则表示安装。
root@openwifi-55:~# gdb -v
GNU gdb (Ubuntu 10.1-2ubuntu2) 10.1.90.20210411-git
Copyright (C) 2021 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.
2、使用自动工具安装
使用
yum -y install gdb
或apt-get -y install gdb
指令,使用包管理器进行自动安装。
[16:55@root ~]$yum install -y gdb
base-debuginfo | 2.5 kB 00:00:00
centos-sclo-rh-debuginfo | 3.0 kB 00:00:00
docker-ce-stable-debuginfo | 3.5 kB 00:00:00
epel-debuginfo/x86_64/metalink | 5.2 kB 00:00:00
epel-debuginfo | 3.0 kB 00:00:00
(1/2): epel-debuginfo/x86_64/primary_db | 896 kB 00:00:00
(2/2): base-debuginfo/x86_64/primary_db | 2.7 MB 00:01:08
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* centos-sclo-rh: mirrors.aliyun.com
* epel: hkg.mirror.rackspace.com
* epel-debuginfo: hkg.mirror.rackspace.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
Resolving Dependencies
--> Running transaction check
---> Package gdb.x86_64 0:7.6.1-120.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
========================================================================================
Package Arch Version Repository Size
========================================================================================
Installing:
gdb x86_64 7.6.1-120.el7 base 2.4 M
Transaction Summary
========================================================================================
Install 1 Package
Total size: 2.4 M
Installed size: 7.0 M
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : gdb-7.6.1-120.el7.x86_64 1/1
Verifying : gdb-7.6.1-120.el7.x86_64 1/1
Installed:
gdb.x86_64 0:7.6.1-120.el7
Complete!
[16:56@root ~]$gdb -v
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
3、使用源码安装
3.1 下载源码
GDB的源码下载网页:点击进入GDB源码下载页面
gdb-11.1版本下载链接: gdb-11.1.tar.xz 或 : gdb-11.1.tar.gz
3.2 上传源码
[17:00@root /usr/local/src]$rz
rz waiting to receive.
Starting zmodem transfer. Press Ctrl+C to cancel.
Transferring gdb-11.1.tar.gz...
100% 36967 KB 9241 KB/sec 00:00:04 0 Errors
Transferring gdb-11.1.tar.xz...
100% 21524 KB 10762 KB/sec 00:00:02 0 Errors
[17:00@root /usr/local/src]$ls
gdb-11.1.tar.gz gdb-11.1.tar.xz
3.3 解压源码包
(1)针对tar.gz文件,可以通过
tar -zxvf gdb-11.1.tar.gz
解压。
(2)针对tar.xz文件,可以通过xz -d gdb-11.1.tar.xz
和tar -xvf gdb-11.1.tar
解压。
3.4 准备依赖列表并开始编译
解压完成后,进入gdb-11.1目录,创建gdb_build-11.1目录并进入,然后执行
../configure
指令,等待执行完毕后,如果没报错,则编译成功。
[17:06@root /usr/local/src]$ls
gdb-11.1 gdb-11.1.tar gdb-11.1.tar.gz
[17:06@root /usr/local/src]$cd gdb-11.1/
[17:07@root /usr/local/src/gdb-11.1]$mkdir gdb_build-11.1
[17:07@root /usr/local/src/gdb-11.1]$cd gdb_build-11.1/
[17:07@root /usr/local/src/gdb-11.1/gdb_build-11.1]$../configure
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
(省略输出).....
checking where to find the target windres... host tool
checking where to find the target windmc... host tool
checking whether to enable maintainer-specific portions of Makefiles... no
configure: creating ./config.status
config.status: creating Makefile
[17:08@root /usr/local/src/gdb-11.1/gdb_build-11.1]$make
等待结果(时间较长)....
3.5 安装
执行
make install
指令安装,如果没报错,则重新连接后即可执行gdb -v
测试安装结果
[17:08@root /usr/local/src/gdb-11.1/gdb_build-11.1]$make install
(省略输出)....
[17:29@zhouchao ~]$gdb -v
GNU gdb (GDB) 11.1
Copyright (C) 2021 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.
三、gdb使用流程
1、编译源程序,增加-g
参数
通过
gcc -g xxx.c -o xxx
指令增加-g参数,指定生成的程序是可调试的。
gcc -g test.c -o test
2、启动gdb,准备调试
通过
gdb xxx
或gdb -q xxx
指令,加载执行程序。其中-q
表示不打印gdb版本信息,界面干净。
gdb test
gdb -q test //表示不打印gdb版本信息,界面较为干净
//执行结果如下:
[11:40@zhouchao ~/test]$gdb test
GNU gdb (Ubuntu 10.1-2ubuntu2) 10.1.90.20210411-git
Copyright (C) 2021 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:
<https://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...
(gdb)_
注意
如果程序已经运行,则可使用attach指令
- 通过ps(ps -ef | grep [进程名])或pidof(pidof [进程名])指令找到进程id
- 启动gdb后,执行attach [进程ID]指令
如果attach进程时报如下错误,可切换到root用户,修改
/etc/sysctl.d/10-ptrace.conf
配置文件中的kernel.yama.ptrace_scope = 0
,将其值改为0即可.
Could not attach to process. If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.
3、查看源码(list)
通过
list
指令查看源码(默认显示10行),通过回车键可翻页。
(gdb) list
1 #include <stdio.h>
2
3 void ShowRevertNum(int iNum)
4 {
5 while (iNum > 10)
6 {
7 printf("%d", iNum % 10);
8 iNum = iNum / 10;
9 }
10 printf("%d\n", iNum);
(gdb)
11 }
12
13 int main(void)
14 {
15 int iNum;
16 printf("Please input a number :");
17 scanf("%d", &iNum);
18 printf("After revert : ");
19 ShowRevertNum(iNum);
20 }
(gdb) _
4、设置断点(break)
通过
break [文件名]:[行号]/[函数名]
指令设置断点。通过info breakpoints
查看断点信息。
(gdb) break 15
Breakpoint 1 at 0x1231: file test.c, line 16.
(gdb) break ShowRevertNum
Breakpoint 2 at 0x1198: file test.c, line 5.
(gdb) break test.c:10
Breakpoint 3 at 0x11fd: file test.c, line 10.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000001231 in main at test.c:16
2 breakpoint keep y 0x0000000000001198 in ShowRevertNum at test.c:5
3 breakpoint keep y 0x00000000000011fd in ShowRevertNum at test.c:10
(gdb) _
5、运行程序(run)
通过
run
指令运行程序,直到结束或遇到断点等待下一个命令
(gdb) run
Starting program: /home/zhouchao/test/test
Breakpoint 1, main () at test.c:16
16 printf("Please input a number :");
(gdb) _
6、单步执行(c、s、n)
通过
continue
、step
、next
指令实现单步执行。
(gdb) continue
Continuing.
Please input a number :1234
Breakpoint 2, ShowRevertNum (iNum=1234) at test.c:5
5 while (iNum > 10)
(gdb) next
7 printf("%d", iNum % 10);
(gdb) next
8 iNum = iNum / 10;
(gdb) continue
Continuing.
Breakpoint 3, ShowRevertNum (iNum=1) at test.c:10
10 printf("%d\n", iNum);
(gdb) step
__printf (format=0x555555556007 "%d\n") at printf.c:28
28 printf.c: No such file or directory.
(gdb) continue
Continuing.
After revert : 4321
[Inferior 1 (process 1708210) exited normally]
(gdb) _
7、查看变量的值
通过
whatis
指令查看变量的值和类型
Breakpoint 2, ShowRevertNum (iNum=1234) at test.c:5
5 while (iNum > 10)
(gdb) print iNum
$1 = 1234
(gdb) whatis iNum
type = int
(gdb) _
8、退出gdb
通过
quit
命令退出gdb
(gdb) q
A debugging session is active.
Inferior 1 [process 1708219] will be killed.
Quit anyway? (y or n) y
四、gdb基本命令
命令/简写 | 格式 | 含义 | 备注 |
---|---|---|---|
==gdb== | gdb -q [exec-program] |
加载执行程序,启动gdb | 可不指定执行程序,直接启动gdb,后续通过file加载执行程序 |
file | file [exec-program] |
加载执行程序 | |
==list(l)== |
list list [line] list [func-name]
|
1、列出程序的源代码,默认每次显示10行 2、指定行号则显示当前文件行号的前后10行代码 3、指定函数名则显示该函数的源代码 |
不带参数则接着上一次list命令输出 |
==break(b)== |
break [func-name] break [line] break [file-name]:[line] break [file-name]:[func-name]
|
根据行号、函数名、指定源文件设置断点 | 上述断点可以增加条件来触发break xx if a > b
|
tbreak(tb) | tbreak [xxx] |
设置临时断点,只执行一次,配置方式与break一致 | |
rbreak(rb) | rbreak [file]:[regex] |
根据正则表达式匹配规则设置断点 | 如rbreak printNum* :所有调用该函数都设置断点rbreak . :当前文件所有函数都设置断点rbreak test.c:^print :所有test.c文件中print开头的函数设置断点 |
condition | condition [N] [条件] |
将断点N调整为条件断点 | 只有当条件满足时才会断点 |
ignore | ignore [N] [times] |
设置断点N跳过times次 | |
delete(d) |
delete [N] delete breakpoints
|
1、删除第N个断点 2、删除全部断点 |
|
clear | clear [line] |
清除指定行号的断点 | |
disable | disable [N] |
暂停第N个断点 | |
enable | enable [N] |
启用第N个断点 | |
==run(r)== | run [params] |
运行程序,直到结束或遇到断点停止运行等待命令 | |
==start== | start [params] |
运行程序到main函数入口处 | |
==continue(c)== | continue |
继续执行到下一个断点处或运行结束 | |
==next(n)== | next |
单步跟踪程序,遇函数不进入函数体 | |
==step(s)== | step |
单步调试,遇函数则进入函数体 | |
finish | finish |
运行程序,直到当前函数完成返回并打印函数返回时的堆栈信息和返回值、参数等信息 | |
==unitl== |
until until [line]
|
1、运行程序退出循环体 2、运行到指定的某一行 |
|
call | call [func] |
调用程序中可见的函数并传递参数 | 如call gdb_test(112)
|
==print(p)== |
print [var] print [exep] print [func] print {[var1],[var2],..}
|
打印变量、表达式、函数调用的值等,可以用分号包裹同时打印多个变量 | 如print a 、print ++a 、print gdb_test(12)
|
whatis | whatis [var] |
显示指定变量的类型,包括函数 | |
==display== |
display [exep] display {[exep1],[exep2],...}
|
设置表达式后每次单步进行指令后紧接着输出被设置表达式及其值,可用分号包裹同时显示多个值 | |
==watch== | watch [exep] |
设置监视点,一旦被监视的表达式值改变,gdb将强行终止正在被调试的程序 | 改变 |
rwatch | rwatch [exep] |
设置监视点,一旦被监视的表达式被访问,gdb将强行终止正在被调试的程序 | 访问 |
awatch | awatch [exep] |
设置监视点,一旦被监视的表达式被访问或被改变,gdb将强行终止正在被调试的程序 | 改变或访问 |
==info(i)== |
info breakpoints(break) info files info func info local info prog
|
1、显示当前的断点信息 2、显示当前调试文件的信息 3、显示所有函数名称 4、显示当前的函数的局部变量 5、显示被调试程序的执行状态 |
|
backtrace(bt)/where |
backtrace/bt/where bt full
|
显示的当前运行的堆栈列表(包括局部变量的值) | |
set variable | set variable [var]=[value] |
设置变量的值 | variable可省略 |
set args | set args [param1] [param2] .. |
设置程序运行参数 | 该参数也可通过run xxx时携带 |
show args | show args |
显示程序运行参数 | |
shell | shell [cmd] |
不退出gdb的情况下执行shell命令 | |
signal | signal [sig] |
产生指定的信号 | 如signal SIGINT
|
return(ret) | return [value] |
停止当前函数并返回value的值给调用者 | |
ptype | ptype |
显示结构定义 | |
==layout== |
layout layout src layout asm layout regs layout split
|
1、查看layout指令的帮助菜单 2、显示源代码窗口 3、显示反汇编窗口 4、显示CPU寄存器窗口和源代码或反汇编窗口 5、显示源代码和反汇编窗口 |
Ctrl+L刷新窗口 |
==quit(q)== | quit |
退出gdb | |
help | help [type] |
帮助手册,指定类型或命令可查看使用方法 |
1、示例操作
[15:18@zhouchao ~/test]$gdb test -q
Reading symbols from test...
(gdb) l
1 #include <stdio.h>
2
3 void ShowRevertNum(int iNum)
4 {
5 while (iNum > 10)
6 {
7 printf("%d", iNum % 10);
8 iNum = iNum / 10;
9 }
10 printf("%d\n", iNum);
(gdb) b 10
Breakpoint 1 at 0x11fd: file test.c, line 10.
(gdb) b ShowRevertNum
Breakpoint 2 at 0x1198: file test.c, line 5.
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000000011fd in ShowRevertNum at test.c:10
2 breakpoint keep y 0x0000000000001198 in ShowRevertNum at test.c:5
(gdb) r
Starting program: /home/zhouchao/test/test
Please input a number :1234
Breakpoint 2, ShowRevertNum (iNum=1234) at test.c:5
5 while (iNum > 10)
(gdb) watch iNum
Hardware watchpoint 3: iNum
(gdb) n
7 printf("%d", iNum % 10);
(gdb) n
8 iNum = iNum / 10;
(gdb) n
Hardware watchpoint 3: iNum
Old value = 1234
New value = 123
ShowRevertNum (iNum=123) at test.c:5
5 while (iNum > 10)
(gdb) c
Continuing.
Hardware watchpoint 3: iNum
Old value = 123
New value = 12
ShowRevertNum (iNum=12) at test.c:5
5 while (iNum > 10)
(gdb) until 10
Hardware watchpoint 3: iNum
Old value = 12
New value = 1
ShowRevertNum (iNum=1) at test.c:5
5 while (iNum > 10)
(gdb) ret 0
Make ShowRevertNum return now? (y or n) y
#0 0x0000555555555275 in main () at test.c:19
19 ShowRevertNum(iNum);
(gdb) c
Continuing.
Watchpoint 3 deleted because the program has left the block
in which its expression is valid.
After revert : 432[Inferior 1 (process 1716443) exited normally]
(gdb) _