常用的调试命令
https://blog.youkuaiyun.com/baidu_35679960/article/details/60140962gdb调试命令的使用及总结 这里比较全
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