使用GDB进行嵌入式远程调试


常用的调试命令
https://blog.csdn.net/baidu_35679960/article/details/60140962

gdb调试命令的使用及总结   这里比较全
https://www.cnblogs.com/lsgxeva/p/8024867.html

参考学习
https://www.cnblogs.com/lidabo/p/5645655.html


PC主机:Ubuntu 16.4 

目标板:海思3516DV300,Linux version 4.9.37

NOTE:为了使用gdb进行调试,强烈建议使用nfs服务,否则调试会非常麻烦。

1. 概述


所谓远程调试,就是开发板上建立一个gdb服务端,同时待调试的程序也位于开发板,
然后在PC机上使用gdb发起远程连接来进行调试。
也就是说,在PC端调试开发板上的程序。
请注意,在PC端需要包含被调试程序的符号调试信息(symbolic debug information),
因此强烈建议使用NFS,否则需要两份被调试的应用程序,一份供gdb使用,另一份供gdbserver使用。

2. 安装GDB服务

2.1 下载gdb安装包


下载gdb安装包,下载地址:

调试环境gdb-8.3.tar.gz
http://www.sourceware.org/pub/gdb/releases/

这里以7.4版本为例

解压安装包:

tar -xvf gdb-7.4/

pwd
/home/yj423/work_yj423/gdb-7.4

在开始编译之前,你必须知道你的交叉编译器的名字。
HI3516DV300 交叉编译器是arm-himix200-linux-gcc
HI3559AV100 交叉编译器是aarch64-himix100-linux-gcc
在下面将会用到该名字。

2.2 编译gdbserver

首先编译gdbserver,该程序运行在开发板上。

执行下列命令:
tar -xf gdb-8.3.tar.gz 
cd gdb-8.3/gdb/gdbserver/
./configure --host=arm-himix200-linux --target=arm-himix200-linux                             //HI3516DV300芯片:
./configure --host=aarch64-himix100-linux --target=aarch64-himix100-linux                 //HI3559AV100芯片

./configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf //arm32平台
make -j4

在make以后,会在当前目录下生成可执行文件gdbserver。
gdbserver路径是gdb-8.3/gdb/gdbserver/

2.3 编译gdb

 
接着编译gdb,该程序运行在PC机上。(gdb和gdbserver都在gdb-8.3.tar.gz包里,只不过路径不一样而已)

执行下列命令:

cd gdb-8.3
//可以在x86运行
sudo ./configure --targe=arm-himix200-linux                //HI3516DV300芯片:
sudo ./configure --targe=aarch64-himix100-linux         //HI3559AV100芯片


//生成HI3559AV100 板子下的 gdb 和gdbserver
./configure --host=aarch64-himix100-linux --target=aarch64-himix100-linux


make -j4

生成路径:
gdb-8.3\gdb\gdb
gdb-8.3\gdb\gdbserver\gdbserver

最终我们需要三个:
gdbserver:板子上可运行的
gdb: 板子上可运行的
gdb: x86上可运行的,可结合gdbserver远程调试

请注意执行命令时所在的目录。执行完以后会在gdb-7.4/gdb/下生成可执行文件gdb。
我将gdb改命为armgdb。

查看文件属性
file gdbserver
file armgdb



3 下面用准备好的gdbserver 和armgdb进行调试


把gdbserver和armgdb都拷贝到nfs挂载点的文件夹目录里
我这里的路径是:/home/tf/work/nfs


PC的IP:192.168.1.11
板子的IP:192.168.1.8
在板子的终端运行:./gdbserver 192.168.1.11:2001 test_main
                  Process /mnt/nfs/test_main created; pid = 238
                  Listening on port 2001

在PC端运行:./armgdb -q test_main
再运行:    target remote 192.168.1.8:2001
就可以连接上了
------------------------------------------------------------------------------
注:几个常用的调试命令

(1)l:列出所有源代码
(2)break main:在main处打断点               指定行号打断点    b 15
     break test_debug.c:11:在test_debug.c的11行打断点          b 11        
(3)c:运行到断点处                                            c
(4)step:单步执行                                             s
(5)next:单步执行,但是step会进入函数里面,但是next不会       n
(6)print a:打印a这个变量的值                                 p
(6)quit:退出,输入此命令则开发板上的gdbserver也退出          q

清屏命令: shell clear
查看代码运行在哪里: where

------------------------------------------------------------------------------
打断点的几种方式:

<1> 在函数名那里, 打断点
b func_name,  比如b main

<2> 在具体位置打断点
b /src/codefile.cc:81
b rtsp_demo.c:2013


4 PC Linux下的调试


在gdb中,运行程序使用r或是run命令。 程序的运行,你有可能需要设置下面四方面的事。 

1、程序运行参数。 
set args 可指定运行时参数。(如:set args 10 20 30 40 50) 
show args 命令可以查看设置好的运行参数。 

2、 运行环境。 
path <dir> 可设定程序的运行路径。 
show paths 查看程序的运行路径。 
set environment varname [=value] 设置环境变量。如:set env USER=hchen 
show environment [varname] 查看环境变量。 

3、工作目录。 
cd <dir> 相当于shell的cd命令。 
pwd 显示当前的所在目录。 

4、程序的输入输出。 
info terminal 显示你程序用到的终端的模式。 
使用重定向控制程序输出。如:run > outfile 
tty命令可以指写输入输出的终端设备。如:tty /dev/ttyb

具体来说就是

例如一个程序名为prog 参数为 -l a -C abc
则,运行gcc/g++ -g  prog.c/cpp -o prog
就可以用gdb调试程序prog
#gdb prog
进入gdb调试界面
输入参数命令set args 后面加上程序所要用的参数,注意,不再带有程序名,直接加参数,如:
set args -l a -C abc
回车后输入


5 Linux编程基础——GDB(设置断点)


启动GDB后,首先就是要设置断点,程序中断后才能调试。在gdb中,断点通常有三种形式:

5.1 断点(BreakPoint):

在代码的指定位置中断,这个是我们用得最多的一种。设置断点的命令是break,它通常有如下方式:

break <function>    在进入指定函数时停住
break <linenum>    在指定行号停住。
break +/-offset    在当前行号的前面或后面的offset行停住。offiset为自然数。
break filename:linenum    在源文件filename的linenum行处停住。
break ... if <condition>    ...可以是上述的参数,condition表示条件,在条件成立时停住。比如在循环境体中,可以设置break if i=100,表示当i为100时停住程序。
可以通过info breakpoints [n]命令查看当前断点信息。此外,还有如下几个配套的常用命令:

delete    删除所有断点
delete breakpoint [n]    删除某个断点
disable breakpoint [n]    禁用某个断点
enable breakpoint [n]    使能某个断点


5.2 观察点(WatchPoint):

在变量读、写或变化时中断,这类方式常用来定位bug。

watch <expr>    变量发生变化时中断
rwatch <expr>    变量被读时中断
awatch <expr>     变量值被读或被写时中断
可以通过info watchpoints [n]命令查看当前观察点信息

5.3 捕捉点(CatchPoint):

捕捉点用来补捉程序运行时的一些事件。如:载入共享库(动态链接库)、C++的异常等。通常也是用来定位bug。

捕捉点的命令格式是:catch <event>,event可以是下面的内容

throw     C++抛出的异常时中断
catch     C++捕捉到的异常时中断
exec    调用系统调用exec时(只在某些操作系统下有用)
fork    调用系统调用fork时(只在某些操作系统下有用)
vfork    调用系统调用vfork时(只在某些操作系统下有用)
load 或 load <libname>     载入共享库时(只在某些操作系统下有用)
unload 或 unload <libname>    卸载共享库时(只在某些操作系统下有用)
另外,还有一个tcatch <event>,功能类似,不过他只设置一次捕捉点,当程序停住以后,应点被自动删除。

捕捉点信息的查看方式和代码断点的命令是一样的,这里就不多介绍了。

在特定线程中中断

你可以定义你的断点是否在所有的线程上,或是在某个特定的线程。GDB很容易帮你完成这一工作。

break <linespec> thread <threadno>
break <linespec> thread <threadno> if ...
linespec指定了断点设置在的源程序的行号。threadno指定了线程的ID,注意,这个ID是GDB分配的,你可以通过"info threads"命令来查看正在运行程序中的线程信息。如果你不指定thread <threadno>则表示你的断点设在所有线程上面。你还可以为某线程指定断点条件。如:

     (gdb) break frik.c:13 thread 28 if bartab > lim

当你的程序被GDB停住时,所有的运行线程都会被停住。这方便你你查看运行程序的总体情况。而在你恢复程序运行时,所有的线程也会被恢复运行。那怕是主进程在被单步调试时。

恢复程序运行和单步调试

在gdb中,和调试步进相关的命令主要有如下几条:

continue    继续运行程序直到下一个断点(类似于VS里的F5)
next        逐过程步进,不会进入子函数(类似VS里的F10)
setp        逐语句步进,会进入子函数(类似VS里的F11)
until        运行至当前语句块结束
finish    运行至函数结束并跳出,并打印函数的返回值(类似VS的Shift+F11)
PS:这些命令大部分可以简写为第一个字母,在日常使用过程中,往往只会输入第一个字符即可执行该命令,我标红的即是通常的使用方式。这几条命令使用非常频繁,并且可以带一些附加参数以实现高级功能,需要熟练掌握。

=====================================================================
怎么删除断点
------------------------------------
断点的删除与断点的设置同样的重要。删除断点的命令有两个:
delete
用法:delete [breakpoints num] [range...]
delete可删除单个断点,也可删除一个断点的集合,这个集合用连续的断点号来描述。
例如:
delete 5
delete 1-10

clear
用法:clear 
    删除所在行的多有断点。
    clear location
clear 删除所选定的环境中所有的断点
clear location location描述具体的断点。
例如:
clear list_insert         //删除函数的所有断点
clear list.c:list_delet   //删除文件:函数的所有断点
clear 12                  //删除行号的所有断点
clear list.c:12           //删除文件:行号的所有断点

clear 删除断点是基于行的,不是把所有的断点都删除。

=====================================================================
显示断点:       info break
删除断点: delete 5  //5时info break显示出来的NUM号

利用gdb调试崩溃程序
 

将程序编译成debug模式
gdb 可执行程序
run            //让自己运行,直到崩掉
where          //当崩掉时输入where
p              //打印想要的变量,进行查看
quit           //退出


//如果生成了core文件,可以借助core来调试
gdb 可执行程序 core

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: gdbgdbserver远程调试技术的意义在于提供了一种方便有效的方式来调试运行在远程目标设备上的程序。这对于嵌入式系统或远程服务器等分布式系统的开发和调试非常有用。 首先,gdbgdbserver远程调试技术允许开发人员在不在本地环境下的目标设备上进行调试。这意味着开发人员可以通过网络连接到远程设备,并使用本地的gdb客户端来远程控制和调试目标设备上的程序。这样,不再需要将全部的代码和调试环境放在开发人员的本地机器上,大大节省了开发人员的时间和资源。 其次,远程调试技术提供了实时调试的能力。开发人员可以监控目标设备上的程序执行过程,并在运行时观察程序的状态和变量的值。这对于发现和解决运行时错误和异常非常重要。通过远程调试,开发人员可以更直接地了解程序在实际环境下的行为,从而更有效地修复问题。 此外,远程调试技术还提供了一个更加安全且可靠的调试方法。使用gdbgdbserver进行远程调试,可以避免将敏感的代码或数据复制到本地环境中,减少了潜在的安全风险。同时,由于远程调试是通过网络进行的,即使目标设备处于远程位置,也能够进行调试,减少了物理上接触设备的需求,提高了效率。 总而言之,gdbgdbserver远程调试技术的意义在于提供了一种方便、实时、安全的方法来远程控制和调试目标设备上的程序,使开发人员能够更有效地进行嵌入式系统和分布式系统的开发和调试工作。 ### 回答2: gdb gdbserver远程调试技术是一种用于在线调试嵌入式系统的工具。它的意义在于提供了一种便捷和高效的方式来调试远程嵌入式设备。 首先,gdb gdbserver远程调试技术可以节省时间和资源。在传统的调试方式中,如果想要调试远程嵌入式设备,通常需要将设备连接到开发服务器并使用串口进行调试。这种方式不仅繁琐,还占用了宝贵的硬件资源。而gdb gdbserver远程调试技术可以直接在目标设备上运行gdbserver,并通过网络连接到开发服务器上的gdb,使得调试变得更加方便快捷。 其次,gdb gdbserver远程调试技术可以提高团队协作效率。在实际的嵌入式系统项目中,通常会有多个开发人员同时开展工作。使用gdb gdbserver远程调试技术,不同的开发人员可以同时连接到同一个目标设备上进行调试,而不会相互干扰。这样可以提高团队成员之间的协作效率,加快问题解决和软件开发的速度。 此外,gdb gdbserver远程调试技术还提供了更灵活的调试方式。通过gdb gdbserver的支持,开发人员可以在目标设备上进行远程程序的调试,包括断点设置、变量查看、程序运行控制等。这种方式可以更加直观地观察到程序的实际执行情况,帮助开发人员更好地理解和解决问题。 总之,gdb gdbserver远程调试技术的意义在于提供了一种便捷、高效和灵活的嵌入式系统调试方式,节省了时间和资源,提高了团队协作效率,同时也方便开发人员更好地理解和解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值