King3399(ubuntu文件系统)GDB/GDBServer调试配置
0 引言
最近在用king3399进行驱动开发,即使是一些简单的外设也不免反复修改与烧录,若仅仅通过printk这种方法对程序进行打印调试,其过程也是相当复杂,因此想通过GDB/GDBServer的方式进行调试,本文主要是记录配置过程的要点,其中免不了抄/借鉴他人成果
1 虚拟机GDB配置
这部分操作都是在虚拟机中完成,虚拟机中ubuntu系统相关信息如下:
cat /proc/version
Linux version 5.4.0-150-generic (buildd@bos03-amd64-012) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #167~18.04.1-Ubuntu SMP Wed May 24 00:51:42 UTC 2023
安装 gdb-multiarch,该操作免于虚拟机上的GDB繁杂编译过程
sudo apt-get install gdb-multiarch
完成上述指令虚拟机端的配置就算做完了
2 板子GDBServer交叉编译
这部分操作都是在虚拟机中完成,这里的操作过程主要参考脚注【a】,若本文有描述不清楚的地方可查看参考文章
-
虚拟机中下载gdb源码,GDB官网,本人所下版本为
gdb-7.12.tar.gz
(文末仓库会给出本文所涉及的资料),这个需要注意一下,不同版本/编译环境,在编译过程中可能会遇到不同的问题,建议先尝试低版本gdb源码编译 -
将 gdb-7.12.tar.gz 解压到当前用户的某个目录下,解压后进入该文件下的gdbserver目录
tar zxvf gdb-7.12.tar.gz cd gdb-7.12/ cd gdb/gdbserver
-
交叉编译GDBerver配置,由于板子的架构为aarch64,因此需在当前目录下执行如下指令进行配置,参考脚注【b】
./configure --target=aarch64-linux-gnu --host=aarch64-linux-gnu
-
交叉编译GDBerver,这个过程可能会花费几分钟,并且在编译过程中可能会报错而中止编译过程
make
-
完成上述过程后会在当前目录下生成
gdbserver
可执行文件,将该文件传到板子上的用户目录下,并在板子上修改其权限为sudo chmod 777 gdbserver
-
编译GDBerver报错处理,本人在编译GDBerver时报错如下
location.c: In function ‘event_location* string_to_explicit_location(const char**, const language_defn*, int)’: location.c:527:19: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]|| *argp == '\0'^~~~
这个报错所涉及的文件在
.../gdb-7.12/gdb/location.c
,打开该文件,定位到527行,并做如下处理,修改后保存并再次make即可if (argp == NULL// || *argp == '\0'|| *argp == nullptr|| *argp[0] != '-'|| !isalpha ((*argp)[1])|| ((*argp)[0] == '-' && (*argp)[1] == 'p')) return NULL;
3 GDB调试文件准备
-
准备一个可以在板子上执行的调试文件,这里抄参考脚注【a】的例子
// file name : test.c#include <stdio.h>int main(void) {int i;for (i=0; i<5; i++) {printf("Hello World:%d\n", i);}printf("Good bye!\n");return 0; }
-
将其编译为可在板子上调试的文件,完成指令后会在当前目录下生成一个可执行的test文件,可通过
readelf -h test
查看该文件运行的系统架构Machine : AArch64
,这里需要注意一下,若没有aarch64-linux-gnu-gcc
编译器可自行安装,安装教程网上有很多,这里不赘述aarch64-linux-gnu-gcc -g test.c -o test
-
将上一步生成的可执行文件test传到板子的用户目录下,并在板子上修改其权限为
sudo chmod 777 test
4 GDB/GDBServer调试
-
完成上述所有操作后,配置环境及相关文件如下:
虚拟机:
- 安装了gdb-multiarch
- 可执行文件test
- ip:192.168.66.aaaa
板子:
- 可执行文件gdbserver
- 可执行文件test
- ip:192.168.66.bbbb
-
在板子上利用gdbserver执行test文件(此处将这两个文件放在同一文件夹内)
./gdbserver 192.168.66.aaaa:8888 test
成功执行后会打印如下内容
Process /test created; pio = 874 Listening on port 8888 Remote debugging from host 192.168.66.aaaa
-
在虚拟机上利用gdb-multiarch执行test文件
gdb-multiarch ./test
成功执行后打印如下内容
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1 ... Type "apropos word" to search for commands related to "word"... Reading symbols from ./test...done.
设置调试系统架构
(gdb) set architecture aarch64
成功执行后打印如下内容
The target architecture is assumed to be aarch64
连接板子
(gdb) target remote 192.168.66.bbbb:8888
成功执行后打印如下内容
Remote debugging using 192.168.66.bbbb:8888 Reading /lib/ld-linux-aarch64.so.1 from remote target... ... (no debugging symbols found)...done. 0x0000007ff7fcd100 in ?? () from target:/lib/ld-linux-aarch64.so.1
设置断点
(gdb) b main
执行下一步
(gdb) n
剩下的就是常规调试操作,网上有大量教程,这里不再赘述
5 其他
其实在写这篇博客前本人还尝试了其他方式配置板子的GDB,但都没有成功,一方面是板子对这部分的官方资料以及网上可参考的资料较少,另一方面是本人对配置GDB部分确实也不熟悉,以前使用时都是现成的,没有经验,这里将尝试的失败过程做一个总结,希望对其他人有帮助
首先还是官方参考资料,打开如下路径:...\02-软件文档\RK原厂文档\linux\cn\Common\DEBUG
,在该文件夹中可以看到不同的调试方法的参考手册,这里重点看《Rockchip_Developer_Guide_GDB_Over_ADB_CN.pdf》与《Rockchip_Developer_Guide_GNU_MCU_Eclipse_OpenOCD_CN.pdf》,由于板子不同?手册没更新?很多配置都对不上,网上这方面的配置也是不尽相同,可以参考着来
这里可能涉及到的目录及文件如下:
# 首先是 .../sdk/u-boot 目录下
make menuconfig# 目录层级
Command line interface > Debug conmmands
[*] kgdb - Allow debugging of U-Boot with gdb# 其次是 .../sdk/kernel 目录下
make menuconfig# 目录层级
Kernel hacking > Generic kernel Debugging Instruments
[*] KGDB: kernel debugger--- KGDB: kernel debugger [*] KGDB: use kprobe blocklist to prohibit unsafe breakpoints <*> KGDB: use kgdb over the serial console (NEW) [ ] KGDB: internal test suite (NEW) [*] KGDB: Allow debugging with traps in notifiers (NEW) [*] KGDB_KDB: include kdb frontend for kgdb (NEW)
[*] KGDB: use kprobe blocklist to prohibit unsafe breakpoints <*> KGDB: use kgdb over the serial console (NEW) [ ] KGDB: internal test suite (NEW) [*] KGDB: Allow debugging with traps in notifiers [*] KGDB_KDB: include kdb frontend for kgdb (0x1) KDB: Select kdb command functions to be enabled by defaul[ ] KGDB_KDB: keyboard as input device (NEW) (0) KDB: continue after catastrophic errors (NEW)# 另外就是设备树配置
# .../sdk/kernel/arch/arm64/boot/dts/rockchip/rk3399-linux.dtsi ,
# 这里会传入启动参数,当然也可以通过 parameter.txt 文件传入
# (这个文件在编译烧录镜像后会自动生成,遗憾的是没找到相关资料具体如何配置)
chosen {bootargs = "earlycon=uart8250,mmio32,0xff1a0000 console=ttyFIQ0 rw root=PARTUUID=614e0000-0000 rootfstype=ext4 rootwait coherent_pool=1m";# 在执行 make menuconfig 后(修改并保存),会生成新的.config文件,
# 通过镜像文件生成的日志(执行 ./build.sh u-boot 或 ./build.sh boot)
# 可推断这并不是生成镜像实际使用的 .config 文件,由于本人没能在镜像中
# 成功配置GDB,因此也不便在此瞎说,关于这部分的有效参考资料可参考
# 《【正点原子】ATK-DLRV1126 系统开发手册V1.6.pdf》与
# 《[野火]嵌入式Linux镜像构建与部署—基于LubanCat-RK系列板卡》,
# 这两个文件内有涉及到通过 make menuconfig 修改u-boot和kernel的部分,
# 但与GDB配置无关
6 总结
虽然最终实现了GDB调试但总感觉过程并不那么完美,如果能够通过SDK配置必然更加优雅,也希望这篇博客能够对各位有所帮助,若有通过SDK配置GDB的方法还望告知,万分感谢!
【a】 gdb+gdbserver远程调试技术(一)——调试环境搭建
【b】 rk系列在开发板上编译gdb
【c】 代码仓库(pwd : zh3j)