【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指令

命令简写形式说明
backtracebt、where显示backtrace
breakb设置断点
continuec、cout继续执行
deleted删除断点
finish运行到函数结束
info breakpoints显示断点信息
nextn执行下一行
printp显示表达式
runr运行程序
steps一次执行一行
x显示内存内容
untilu执行到指定行
directorydir插入目录
disabledis禁用断点
downdo在当前调用的栈帧中选择要显示的栈帧
edite编辑文件或者函数
framef选择要显示的栈帧
forward-searchfo向前搜索
generate-core-filegcore生成内核转存储
helph显示帮助一览
infoi显示信息
listl显示函数或行
nextini执行下一行(以汇编代码为单位)
print-objectpo显示目标信息
sharelibraryshare加载共享符号
stepisi执行下一行

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值