【gdb】软件调试工具 - gdb命令及使用

检查安装gdb

打开终端输入

gdb -v

gdb已安装log:

zx@zx-PC:~/Desktop/codes$ gdb -v
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
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".

Ubuntu安装方法:

sudo apt install gdb

Arm平台交叉编译安装(环境限制,还未验证):

1.下载gdb安装包:

wget http://mirrors.ustc.edu.cn/gnu/gdb/gdb-7.9.1.tar.xz

2.解压

tar -xf gdb-7.9.1.tar.xz

3.安装

cd gdb-7.9.1
sudo apt install texinfo
./configure
make
sudo make install

GDB指令

命令 简写形式 说明
backtrace bt、where 显示backtrace
break b 设置断点
continue c、cout 继续执行
delete d 删除断点
finish 运行到函数结束
info breakpoints 显示断点信息
next n 执行下一行
print p 显示表达式
run r 运行程序
step s 一次执行一行
x 显示内存内容
until u 执行到指定行
directory dir 插入目录
disable dis 禁用断点
down do 在当前调用的栈帧中选择要显示的栈帧
edit e 编辑文件或者函数
frame f 选择要显示的栈帧
forward-search fo 向前搜索
generate-core-file gcore 生成内核转存储
help h 显示帮助一览
info i 显示信息
list l 显示函数或行
nexti ni 执行下一行(以汇编代码为单位)
print-object po 显示目标信息
sharelibrary share 加载共享符号
stepi si 执行下一行

GDB调试可执行文件

创建测试代码

vim main.c

测试代码:

#include<stdio.h>
#include<stdlib.h>

int main( int argc , char *argv[] )  
{
    int a = 1;
    int i = 0;
    int b[3] = {0,1,2};
    for(i = 0; i < 3;i++)
        b[i] = b[i] + 1;
    printf("%d\n",a);
    int *p;
    p = b;
    printf("%d\n",p[0]);
    return 0;
}

编译生成可以执行文件

gcc -g -o main main.c            # -g表示保留调试参数,否则无法生成调试文件

开始调试

gdb main       # gdb载入main可执行文件

查看源码和行号:

(gdb) l

image

断点:

  • 根据行号设置断点
1.(gdb) b 5
2.(gdb) b main.c:5
  • 根据函数设置断点
(gdb) b main
  • 根据条件设置断点
(gdb) b main.c:10 if a == 1
  • 根据偏移量设置断点
(gdb) b +3
  • 根据地址设置断点
(gdb) b *0x40059b
  • 设置临时断点(只生效一次)
(gdb) tbreak main.c:12   
  • 显示所有断点
(gdb) info break

image

  • 清除断点
(gdb) delete 2       # 清除第二个断点
(gdb) delete         # 清除所有断点

image

image

  • 清除当前行断点
(gdb) clear

运行:

运行:r
继续单步调试:n
继续执行到下一断点:c

image

打印变量的值:

  • 打印变量
(gdb) p a

image

  • 打印指针
(gdb) p p

image

  • 打印main函数中的变量a
(gdb) p 'main'::a

image

  • 打印指针指向的内容,@后面跟的是打印的长度
(gdb) p *p@2

image

  • 设置变量打印
(gdb) set $abc=0
(gdb) p p[$abc]

image

  • 设置打印格式
x 按十六进制格式显示变量
d 按十进制格式显示变量
u 按十六进制格式显示无符号整型
o 按八进制格式显示变量
t 按二进制格式显示变量
a 按十六进制格式显示变量
c 按字符格式显示变量
f 按浮点数格式显示变量
(gdb) p/x a(按十六进制格式显示变量)

image

退出GDB:

(gdb) q

image

gdb原理小结:

gdb调试原理本质是通过设置一个一个断点,可以通过打印输出在这个断点位置所关注变量的值,从而逐个断点调试每个位置的各变量值是否异常,来定位问题出现的位置。

gdb调试实例

1 #include <stdio.h>
2 #include <stdlib.h>    
3 
4 static char buff [256];
5 static char* string;
6 int main ()
7 {
8     printf ("Please input a string: ");
9     gets(string);
10    printf ("\nYour string is: %s\n", string);
11 }

这个程序是接收用户的输入,然后将用户的输入打印出来。该程序使用了一个未经过初始化的字符串地址string,因此编译运行之后会出现"Segment Fault"的错误。

调试步骤:

1.编译此程序生成可执行文件,然后运行"gdb a.out"加载可执行文件

wzx@wzx-PC:~/my/codes/gdb$ gdb main
GNU gdb (Deepin 10.1-1.7) 10.1.90.20210103-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 main...
(gdb)

2.运行程序

(gdb) run
Starting program: /home/wzx/my/codes/gdb/main
Please input a string: asdasd


Program received signal SIGSEGV, Segmentation fault.
_IO_gets (buf=0x0) at iogets.c:53
53      iogets.c: 没有那个文件或目录.

3.使用where查看程序出错的地方

(gdb) where
#0  _IO_gets (buf=0x0) at iogets.c:53
#1  0x0000000000401159 in main () at main.c:9

4.在第9行处打一个断点:break 9

(gdb) break 9
Breakpoint 1 at 0x7ffff7e49170: file iogets.c, line 32.

5.执行单步命令:next

(gdb) next


Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

程序出错,能够导致gets函数出错的因素就是变量string。

6.重新执行测试,,用print命令查看string的值

(gdb) run
Starting program: /home/wzx/my/codes/gdb/main


Breakpoint 1, _IO_gets (buf=0x0) at iogets.c:37
37      iogets.c: 没有那个文件或目录.
(gdb) print string
$1 = 0x0

问题在于string指向的是一个无效指针,修改程序,在8-9行间增加一条语句"string=buff",重新编译程序,然后继续运行,运行正常。










参考文章:
https://blog.csdn.net/lovely_dzh/article/details/109160337

posted @ 2022-11-15 21:54  Emma1111  阅读(781)  评论(0编辑  收藏  举报