gdb常用调试命令

1. 前言

GNU调试器(英语:GNU Debugger,缩写:GDB),是GNU软件系统中的标准调试器,此外GDB也是个具有移携性的调试器,经过移携需求的调修与重新编译,如今许多的类UNIX操作系统上都可以使用GDB,而现有GDB所能支持调试的编程语言有C、C++、Pascal以及FORTRAN。在Linux下开发C语言,经常用到gdb进行调试,下面总结一下gdb调试过程中常用的命令。

2. 应用场景

一般来说,GDB主要帮忙你完成下面四个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、动态的改变你程序的执行环境。

3. 调试程序

要使用gdb进行调试,必须在编译的时候加上-g参数,不然是无法使用gdb进行调试的。

$ cc -g lkm.c -o lkm

编译完成后,使用gdb 可执行文件,启动gdb调试。

szp@szp-pc:~/code/mynode$ gdb lkm
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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 lkm...
(gdb) 

使用l 行数可以列出源代码,然后直接按回车会重复执行l命令,会继续列出后面的代码。

(gdb) l 1
1    //
2    // Created by szp on 2020/10/10.
3    //
4    #include <stdio.h>
5    #include <fcntl.h>
6    #include <unistd.h>
7    #include <string.h>
8    void show_opt () {
9        printf("1. process name \n"
10               "2. group id \n"
(gdb) l
11               "3. parent process \n"
12               "4. process group leader \n"
13               "5. child processes created \n"
14               "6. process memory segments \n"
15               "7 . virtual memory mapping \n"
16               "8. process priority \n"
17               "9. process state \n"
18               "10. cpu used by process \n"
19               "11. total fault count of process  \n"
20               "12. process start time \n"
(gdb) 
21               "13. process link count \n"
22               "0. quit \n");
23        printf ("\nEnter Option : ");
24    }
25    
26    
27    int main () {
28                char buf [700],opt[50];
29                int rt;
30                // open device node of LKM
(gdb)

按照行数设置断点,通过break 行数

(gdb) break 9
Breakpoint 1 at 0x1271: file lkm.c, line 9.

按照函数名设置断点,break 函数名

(gdb) break show_opt
Breakpoint 2 at 0x1269: file lkm.c, line 8.

查看断点信息info break

(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000001271 in show_opt at lkm.c:9
2       breakpoint     keep y   0x0000000000001269 in show_opt at lkm.c:8
(gdb)

运行程序 r,run命令简写。在设置的断点处停下。

(gdb) r
Starting program: /home/szp/code/mynode/lkm 
Enter Process PID:1

Breakpoint 2, show_opt () at lkm.c:8
8    void show_opt () {
(gdb) 

单条语句执行,next命令简写n。

(gdb) n

Breakpoint 1, show_opt () at lkm.c:9
9        printf("1. process name \n"

打印变量的值p 变量,print的缩写。

(gdb) p buf
$1 = 0x0

GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。

(gdb) p/c buf
$3 = 0 '\000'
(gdb)

产看函数堆栈 bt

(gdb) bt
#0  show_opt () at lkm.c:23
#1  0x0000555555555301 in main () at lkm.c:37

退出当前函数 finish

(gdb) finish
Run till exit from #0  show_opt () at lkm.c:23

main () at lkm.c:38
38                scanf("%s",opt);
(gdb) 

继续执行c,continue缩写。

(gdb) c
Continuing.

要退出gdb时,只用发quit或命令简称q就行了。

gdb的命令很多,gdb把之分成许多个种类。help命令只是例出gdb的命令种类,如果要看种类中的命令,可以使用help 命令,如:help breakpoints,查看设置断点的所有命令。也可以直接help 来查看命令的帮助。
(gdb) help
List of classes of commands:

aliases – Aliases of other commands.
breakpoints – Making program stop at certain points.
data – Examining data.
files – Specifying and examining files.
internals – Maintenance commands.
obscure – Obscure features.
running – Running the program.
stack – Examining the stack.
status – Status inquiries.
support – Support facilities.
tracepoints – Tracing of program execution without stopping the program.
user-defined – User-defined commands.

Type “help” followed by a class name for a list of commands in that class.
Type “help all” for the list of all commands.
Type “help” followed by command name for full documentation.
Type “apropos word” to search for commands related to “word”.
Type “apropos -v word” for full documentation of commands related to “word”.
Command name abbreviations are allowed if unambiguous.
(gdb)

gdb中,输入命令时,可以不用将命令敲完整,只用打命令的前几个字符就可以了,当然,命令的前几个字符应该要标志着一个唯一的命令,在Linux下,你可以敲击两次TAB键来补齐命令的全称,如果有重复的,那么gdb会把其例出来。

在gdb中,我们可以有以下几种暂停方式:断点(BreakPoint)、观察点(WatchPoint)、捕捉点(CatchPoint)、信号(Signals)、线程停止(Thread Stops)。如果要恢复程序运行,可以使用c或是continue命令。详细内容不介绍了。

info line命令查看源代码在内存中的地址。info line后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”,这个命令会打印出所指定的源码在运行时的内存地址,如:

(gdb) info line show_opt
Line 8 of "lkm.c" starts at address 0x555555555269 <show_opt>
   and ends at 0x555555555271 <show_opt+8>.

disassemble可以查看源程序的当前执行时的汇编代码,这个命令会把目前内存中的指令dump出来。

(gdb) disassemble show_opt
Dump of assembler code for function show_opt:
=> 0x0000555555555269 <+0>:    endbr64 
   0x000055555555526d <+4>:    push   %rbp
   0x000055555555526e <+5>:    mov    %rsp,%rbp
   0x0000555555555271 <+8>:    lea    0xd90(%rip),%rdi        # 0x555555556008
   0x0000555555555278 <+15>:    callq  0x5555555550e0 <puts@plt>
   0x000055555555527d <+20>:    lea    0xebe(%rip),%rdi        # 0x555555556142
   0x0000555555555284 <+27>:    mov    $0x0,%eax
   0x0000555555555289 <+32>:    callq  0x555555555110 <printf@plt>
   0x000055555555528e <+37>:    nop
   0x000055555555528f <+38>:    pop    %rbp
   0x0000555555555290 <+39>:    retq   
End of assembler dump.

查看寄存器的值info registers

(gdb) info registers
rax            0x0                 0
rbx            0x555555555430      93824992236592
rcx            0x0                 0
rdx            0x0                 0
rsi            0xa                 10
rdi            0x7fffffffd750      140737488344912
rbp            0x7fffffffdc80      0x7fffffffdc80
rsp            0x7fffffffdc80      0x7fffffffdc80
r8             0xa                 10
r9             0x12                18
r10            0x555555556172      93824992239986
r11            0x246               582
r12            0x555555555180      93824992235904
r13            0x7fffffffe0a0      140737488347296
r14            0x0                 0
r15            0x0                 0
rip            0x555555555271      0x555555555271 <show_opt+8>
eflags         0x206               [ PF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
--Type <RET> for more, q to quit, c to continue without paging--

修改变量的值
修改被调试程序运行时的变量值,在GDB中很容易实现,使用GDB的print命令即可完成。如:
(gdb) print x=4

4. 总结

以上总结的都是gdb最基础的调试命令,满足简单使用,gdb还有很多高级命令,后续进行补充,此外,善用help命令可以发现更多gdb好用的命令。

------ 本文结束------
  • 文章标题: gdb常用调试命令
  • 本文作者: 你是我的阳光
  • 发布时间: 2020年10月19日 - 13:32:08
  • 最后更新: 2021年08月03日 - 16:23:53
  • 本文链接: https://szp2016.github.io/c/gdb常用调试命令/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
0%