交叉编译GDB+GDB-Server远程调试开发板

前言

本期主要讲解如何移植,使用gdb调试程序,及如何使用gdbserver远程调试开发板

正文

话不多少进入正文,gdb基础调试的文章网上有很多了,大家可以多参考几篇博客。

移植gdbserver

开发板上面空间不足以运行gdb,所以要移植gdbserver进行远程调试。

  1. 移植gmp
    GDB是依赖于GMP的,所以要先交叉编译GMP。这一点是网上很多水博客的人没有提到的。不然会报错:

configure: error: GMP is missing or unusable

官网:[https://gmplib.org/](https://gmplib.org/),截至2023年8月最新版本为6.3.0

下载,解压,配置,编译,安装。
tar -xf gmp.tar.xz
cd gmp
./configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --prefix=$PWD/__install
make
make install
# 此时记下目录,后面配置会用到,我的是:
# /home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/lib
# /home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/include
# # 为了方便使用,也可以将__install目录下的文件复制到交叉编译工具链下对应的include和lib目录下,后续将不用增加额外配置项
  1. 编译gdb

    官网:https://sourceware.org/gdb/,最新版本为12.2

    下载,解压,配置,编译gdb,编译gdbserver,将要用到的产出物推到板子上。

tar -xf gdb.tar.xz
cd gdb
# 记下的目录在这里用到
./configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --prefix=$PWD/__install  CFLAGS="-I/home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/include -L/home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/lib" CXXFLAGS="-I/home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/include -L/home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/lib"
make -j $nproc

正常用apt安装的交叉编译工具链到这里可以编译成功的,由于我用了自己厂商给的工具链,中间会遇到一些小问题,无非是缺少宏定义或者头文件没有引入,直接修改对应文件代码即可,比如:

  • 缺少一些宏定义
./fibheap.c:38:24: error: 'long_min' undeclared (first use in this function)  #define fibheapkey_min long_min

解决:
将以下代码复制到报错文件

#ifndef ULONG_MAX
#define	ULONG_MAX	((unsigned long)(~0L))		/* 0xFFFFFFFF */
#endif

#ifndef LONG_MAX
#define	LONG_MAX	((long)(ULONG_MAX >> 1))	/* 0x7FFFFFFF */
#endif

#ifndef LONG_MIN
#define	LONG_MIN	((long)(~LONG_MAX))		/* 0x80000000 */
#endif

  • 缺少宏定义

解决:查看宏定义属于头文件fcntl.h,则引入头文件#include <fcntl.h>

  1. 编译gdbserver
    正常编译gdb会顺便将gdbserver编译出来的,在gdbserver目录下,如果需要单独编译的话,直接运行以下命令即可(前提是要先编译过gdb,不然可能会报错)。
make install # 安装到目录下的__isntall
cd gdbserver
./configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf 
make # 同目录下生成gdbserver文件,推到板子上就可以用啦

运行如下命令验证是否成功:

root@sun8i:/mnt/UDISK# ./gdbserver --version
GNU gdbserver (GDB) 13.2
Copyright (C) 2023 Free Software Foundation, Inc.
gdbserver is free software, covered by the GNU General Public License.
This gdbserver was configured as "arm-openwrt-linux"

如图:
在这里插入图片描述

gdb 调试

私以为当从以下几个方面掌握:

  • 断点和单步执行:学习如何在程序中设置断点,以便在特定位置暂停程序的执行。

  • 变量查看和修改:学习如何在调试过程中查看和修改变量的值。

  • 栈和调用链:了解函数调用的栈帧结构,学习如何查看当前的函数调用链,以便在调试过程中理解函数的嵌套关系。

  • 内存和指针:学习如何查看和跟踪内存中的数据,包括指针和动态内存分配。这对于定位内存泄漏和野指针等问题非常重要。

  • 多线程调试:学习如何在多线程程序中进行调试,理解线程的状态和相互作用,以及如何避免竞态条件等并发问题。

  • 异常处理和信号:了解如何调试程序中的异常情况和信号处理程序。通过对程序中的异常情况进行调试,可以更好地理解代码的异常处理机制。

  • 调试优化:学习如何使用 GDB 的各种功能和选项来加速调试过程,并提高调试效率。

主要调试命令有以下几类:

信息展示:

命令作用
info sources查看所有相关源文件
info source查看当前运行的源文件
list查看当前运行位置代码,简写l
info break查看当前断点
x/<n><fmt> <address>以fmt格式打印address地址的n个,fmt可选以下内容:b:以字节为单位显示。h:以半个字(2 字节)为单位显示。w:以字(4 字节)为单位显示。g:以双字(8 字节)为单位显示。x/d/s:以十六进制/十进制/空字符为终止标志打印字符串。i:显示机器指令。a:以内存地址和符号名称的形式显示。
backtrace简写bt 查看调用栈信息,也可加参数 bt full/ bt 数字
display i每次都展示变量i
info threads打印线程信息

断点相关:

命令作用
break main.c:10 if i=10在第十行设置条件断点,只有i=10的才停
break add在add函数设置断点
break *address在address地址上设置断点
break main.c:add在main.c文件的add函数设置断点
info breakpoints展示所有断点,这里有断点的编号
delete/disable/enable 断点编号删除,屏蔽,使能编号

流程相关

命令作用
run开始运行
continue继续运行
next运行下一行
step进入函数
finish运行到当前函数结束,并给出返回值
call add(a,b)强制调用add函数,入参是a,b
call malloc_stats()统计内存使用

变量相关

命令作用
set var i=10将变量i设置成10
print i=10将i赋值为10

进程相关

  • info threads:显示当前所有线程的信息,包括线程编号(Id)、线程状态(State)和当前所在位置等。
  • thread <thread_id>:切换到指定线程。例如,thread 2 将切换到线程编号为 2 的线程。

信号相关

  • 异常处理:
  • catch : 设置一个断点来捕获指定的异常。例子:catch throw 捕获所有 throw 语句引发的异常。
  • handle [command]: 对指定信号进行处理。您可以指定一个命令来在捕获该信号时执行。例子:handle SIGSEGV nostop 可以在捕获到 SIGSEGV(段错误)信号时继续执行程序而不暂停。
  • 信号处理:
  • info signals: 显示所有信号的信息,包括信号名称和描述。
  • handle [options]: 设置对指定信号的处理方式。例如,handle SIGINT nostop 可以在捕获到 SIGINT(中断)信号时继续执行程序而不暂停。
  • signal : 发送一个指定的信号给正在运行的程序。例子:signal SIGTERM 发送 SIGTERM 给程序,以请求其优雅地终止。

贴一些记录:

(gdb) l
11	        printf("i=%d\n",i);
12	    }
13	
14	    char *str = "Hello World!";
15	
16	    for(i=0;i<15;i++){
17	        printf("%d \t: %c\n",i,str[i]);
18	    }
19	
20	
(gdb) print str
$1 = 0x555555556004 "Hello World!"
(gdb) x/s  0x555555556004
0x555555556004:	"Hello World!"
(gdb) x/w  0x555555556004
0x555555556004:	U"\x6c6c6548\x6f57206f\x21646c72\x253d6900\x25000a64\x3a092064\xa632520\x253d6900\x6a202c64\xa64253d\x6c654800\x57206f6c\x646c726f\x646e4520!\x3b031b01\064\005\xffffefe0h\xfffff010\220\xfffff020¨\xfffff040P\xfffff129À"
(gdb) x/s  0x555555556004
0x555555556004:	"Hello World!"
(gdb) x/xb  0x555555556004
0x555555556004:	0x48
(gdb) x/5xb  0x555555556004
0x555555556004:	0x48	0x65	0x6c	0x6c	0x6f
(gdb) x/5xh
0x555555556009:	0x5720	0x726f	0x646c	0x0021	0x3d69
(gdb) x/a  0x555555556004
0x555555556004:	0x6f57206f6c6c6548
(gdb) x/xb &i
0x7fffffffde70:	0x04

远程调试

远程调试只是换了一个启动方式,调试方法基本还是一致的。

  1. 在目标设备上启动gdbserver:在目标设备(被调试的设备)上运行gdbserver,并指定要调试的可执行文件。例如,可以通过以下命令启动gdbserver并监听特定端口:
gdbserver host:port <executable> # host:port替换为ip和端口号 <executable>  替换为被调试程序名

# 如下:
root@sun8i:/mnt/UDISK# ./gdbserver 10.192.136.217:8888 runner 
Process /mnt/UDISK/runner created; pid = 1732
Listening on port 8888
Remote debugging from host 10.192.136.238, port 58124



  1. 在本机启动gdb
gdb
target remote <target_ip>:<port>
#如下:
(gdb) target remote 10.192.136.217:8888
`target:/mnt/UDISK/runner' has disappeared; keeping its symbols.
Remote debugging using 10.192.136.217:8888

一些过程命令

在这里插入图片描述

./configure --host=arm-openwrt-linux --target=arm-openwrt-linux --prefix=$PWD/__install  CFLAGS="-I/home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/include -L/home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/lib -I/home/ql/Downloads/R16_Tina_compiler_glibc/staging_dir/target/usr/include -L/home/ql/Downloads/R16_Tina_compiler_glibc/staging_dir/target/usr/lib" CXXFLAGS="-I/home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/include -L/home/ql/Desktop/config/gdb-study/gmp-6.3.0/__install/lib -I/home/ql/Downloads/R16_Tina_compiler_glibc/staging_dir/target/usr/include -L/home/ql/Downloads/R16_Tina_compiler_glibc/staging_dir/target/usr/lib"

PATH=$PATH:/home/ql/Downloads/R16_Tina_compiler_glibc/toolchain-sunxi-glibc/toolchain/bin
STAGING_DIR=/home/ql/Downloads/R16_Tina_compiler_glibc/staging_dir
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值