Linux小知识---GDB使用范例

背景介绍

最近总有人问,你常用的调试方式都有什么啊,我说:我最擅长的就是打印,log记录。结果人家都嫌弃我的方法低级。
那就来个常听说但是不常用的方法。
在这里插入图片描述

GDB

GDB是GNU开源组织发布的一个强大的UNIX下调试程序工具,GDB主要帮助你完成下面四个方面的功能:

  • 启动你的程序,可以按照你自定义的要求随心所欲的运行程序。
  • 可以让调试程序在你所指定的位置的断点处停止。
  • 当程序停止时,可以检查此时你的程序中所发生的事情。
  • 动态的改变你程序的执行环境。

GDB的使用通常有三种场合,本地调试,远程调试和事后分析。
在这里插入图片描述

本地GDB范例

代码准备

首先创建了两个文件
在这里插入图片描述
然后放上简单的代码 ;
gdb_study.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

extern int divide();
 
int main()
{
	divide();
}

utils.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int divide()
{
	int x=5, y=0 ,c=0;

	c=x/y;
	
	return c;
}

这是一段包含bug的代码,一会会用到

在这里插入图片描述

编译

如果需要调试的话,编译参数需要带-g

gcc -o gdb_study -g gdb_study.c untils.c 

然后就得到了可执行文件。
在这里插入图片描述

开始调试

开始调试,直接执行 gdb 可行程序

root@raspberrypi:/home/pgg/work/driver# gdb gdb_study
GNU gdb (Raspbian 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 "arm-linux-gnueabihf".
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 gdb_study...
(gdb) 

首先设置源码路径,注意,常用命令可用tab按键补齐。

(gdb) directory ./src/
Source directories searched: /home/pgg/work/driver/./src:$cdir:$cwd

查看源码

(gdb) list
1
2       #include <sys/types.h>
3       #include <sys/stat.h>
4       #include <fcntl.h>
5       #include <unistd.h>
6       #include <stdio.h>
7       #include <string.h>
8
9       extern int divide();
10       
(gdb) 

查看函数

(gdb) list main
7       #include <string.h>
8
9       extern int divide();
10       
11      int main()
12      {
13              divide();
14      }
15
16
(gdb) 

设置断点

(gdb) break 13
Breakpoint 2 at 0x1040c: file gdb_study.c, line 13.

开始执行

(gdb) run
Starting program: /home/pgg/work/driver/gdb_study 

Breakpoint 2, main () at gdb_study.c:13
13              divide();

步进调试

(gdb) step
divide () at untils.c:10
10              int x=5, y=0 ,c=0;
(gdb) step
12              c=x/y;

查看变量

(gdb) print x
$1 = 5
(gdb) print y
$2 = 0

这个程序有一个bug,继续执行,就会报错

(gdb) c
Continuing.

Program received signal SIGFPE, Arithmetic exception.
__GI_raise (sig=8) at ../sysdeps/unix/sysv/linux/raise.c:50
50      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.

查看堆栈

(gdb) bt
#0  __GI_raise (sig=8) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x000106b0 in __aeabi_ldiv0 ()
#2  0x0001044c in divide () at untils.c:12
#3  0x00010410 in main () at gdb_study.c:13
(gdb) 

一般到堆栈也就够用了。
在这里插入图片描述

远程GDB

如果是在交叉编译环境下,调试开发板的程序,那么就还有一种使用方法,远程gdb调试。
首先分清一下角色和其上要运行的程序。
开发板:gdbserver
宿主机:arm-linux-xxx-gdb或者gdb-multiarch

如果是交叉编译工具中带有gdb工具,那就不需要安装,我用的树莓派,没有arm-linux-gnueabihf-gdb。那么需要安装一个多平台的gdb工具

sudo apt-get install gdb-multiarch

代码准备

在宿主机上,准备代码和进行交叉编译

root@ubuntu:/home/pgg/shumeipai/app/gdb_study# arm-linux-gnueabihf-gcc -o gdb_study -g gdb_study.c untils.c 
root@ubuntu:/home/pgg/shumeipai/app/gdb_study# file gdb_study
gdb_study: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=9894a7805877c0be622eab86ae8858dd88542087, with debug_info, not stripped

得到可执行程序和环境,然后把可执行程序拷贝到开发板上
在这里插入图片描述

开发板

开发板侧执行如下程序

root@raspberrypi:/home/pgg/work/driver# gdbserver 192.168.0.116:1234 ./gdb_study 
Process ./gdb_study created; pid = 4141
Listening on port 1234
Remote debugging from host 192.168.0.135, port 35264
Remote side has terminated connection.  GDBserver will reopen the connection.
Listening on port 1234

开始监听调试

宿主机

首先执行gdb-multiarch

root@ubuntu:/home/pgg/shumeipai/app/gdb_study# gdb-multiarch 
GNU gdb (Ubuntu 10.2-0ubuntu1~18.04~2) 10.2
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".
(gdb) 

然后连接开发板

(gdb) target remote 192.168.0.116:1234
Remote debugging using 192.168.0.116:1234
Reading /home/pgg/work/driver/gdb_study from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /home/pgg/work/driver/gdb_study from remote target...
Reading symbols from target:/home/pgg/work/driver/gdb_study...
Reading /lib/ld-linux-armhf.so.3 from remote target...
Reading /lib/ld-linux-armhf.so.3 from remote target...
Reading symbols from target:/lib/ld-linux-armhf.so.3...
Reading /lib/955e226664c85da6b67816d9bba2900b612f9a.debug from remote target...
Reading /lib/.debug/955e226664c85da6b67816d9bba2900b612f9a.debug from remote target...
Reading /usr/lib/debug//lib/955e226664c85da6b67816d9bba2900b612f9a.debug from remote target...
Reading /usr/lib/debug/lib//955e226664c85da6b67816d9bba2900b612f9a.debug from remote target...
Reading target:/usr/lib/debug/lib//955e226664c85da6b67816d9bba2900b612f9a.debug from remote target...
(No debugging symbols found in target:/lib/ld-linux-armhf.so.3)
0x76fcca50 in ?? () from target:/lib/ld-linux-armhf.so.3

查看代码

(gdb) list main
7       #include <string.h>
8
9       extern int divide();
10       
11      int main()
12      {
13              divide();
14      }
15
16

调试过程,与前面本地gdb一样。
在这里插入图片描述

GDB解析core文件

        当程序运行过程中出现Segmentation fault (core dumped)错误时,程序停止运行,并产生core文件。core文件是程序运行状态的内存映象。使用gdb调试core文件,可以帮助我们快速定位程序出现段错误的位置。
        当程序访问的内存超出了系统给定的内存空间,就会产生Segmentation fault (core dumped),因此,段错误产生的情况主要有:(1)访问不存在的内存地址;(2)访问系统保护的内存地址;(3)数组访问越界等。
        core dumped又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dumped。

就是令人痛恨的Segmentation fault段错误。在解决这类问题的时候,我们经常会打开core文件,抓住出错时候的信息。
在这里插入图片描述

操作方法如下,首先关闭core文件限制

root@raspberrypi:/home/pgg/work/driver# ulimit -c unlimited

执行可执行文件,生成core文件

root@raspberrypi:/home/pgg/work/driver# ./gdb_study 
Floating point exception (core dumped)
root@raspberrypi:/home/pgg/work/driver# ls
core  gdb_study

分析命令

gdb --core core gdb_study

或者

gdb gdb_study core 

例如

root@raspberrypi:/home/pgg/work/driver# gdb gdb_study core        
GNU gdb (Raspbian 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 "arm-linux-gnueabihf".
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 gdb_study...
[New LWP 4210]
Core was generated by `./gdb_study'.
Program terminated with signal SIGFPE, Arithmetic exception.
#0  __GI_raise (sig=8) at ../sysdeps/unix/sysv/linux/raise.c:50
50      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=8) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x004e0802 in __aeabi_ldiv0 ()
#2  0x004e0538 in divide () at untils.c:12
#3  0x004e0518 in main () at gdb_study.c:13

可以看到崩溃时候的堆栈。

在这里插入图片描述

结束语

现在的蚊子真是厉害多了,公园待一会就满身包,昨天和孩子在公园玩了几分钟的秋千,突然想到为什么公园没有大人玩的游乐设施,比如秋千,滑梯什么的?大人玩这个不会快乐吗?还是大人不需要快乐?可能就是该死的面子吧.
在这里插入图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖哥王老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值