C语言之gdb的使用详解

一、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 gdbapt-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.xztar -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 xxxgdb -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)

通过continuestepnext指令实现单步执行。

(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、查看变量的值

通过printwhatis指令查看变量的值和类型

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 aprint ++aprint 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) _
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容