ARM - PC 通过网络进行arm的gdb调试
碎念,gdb调试arm花去了断断续续几天的时间,网上虽然有很多文章,但都是基于一个英文文章翻译的,我按那篇文章操作,一直不成功,索性自己一点点试,终于试出点眉目
提示几个问题点
- 配置PC端的gdb的几个环境变量,这些环境变量的路径是PC的路径,我们要准备rootfs在PC上。这问问题很多文章里写了,但是没有强调,搞的人不知道环境变量路径是对应的PC的路径还是ARM的路径。
- 配置环境变量了,但是又配置的不够充分,有些库找不到。
- 找到了库,在调试过程中还会有调试到库的时候,没有debug信息,库没有debug信息会打印问号,这时我们是否需要进行处理。
前提假设
- PC系统是ubuntu,ip是192.168.2.202
- ARM系统是linux,ip是192.168.2.200
- ARM上安装了在PC上交叉编译的gdbserver,PC上安装了gdb-multiarch命令
- PC上保存有和ARM上同样的rootfs,PC上rootfs保存在本机 /home/tronlong目录下,名字为/home/tronlong/rootfs
- 待调试的程序名为kzx-xdl是在PC上交叉编译后的程序,gcc / g++ 编译时使用了-g选项
arm上执行
gdbserver 192.168.2.202:1234 ./kzx-xdl
ubuntu上执行
gdb-multiarch ./kzx-xdl (可用sudo 也 可不用sudo)
(gdb) set architecture arm
(gdb) set sysroot /home/tronlong/rootfs
(gdb) set solib-search-path /home/tronlong/ti-processor-sdk-linux-rt-am57xx-evm-04.03.00.05/linux-devkit/sysroots/x86_64-arago-linux/usr/lib:/home/tronlong/rootfs/lib
去除交叉编译工具链的库路径,改为:
(gdb) set solib-search-path /home/tronlong/rootfs/lib:/home/tronlong/rootfs/usr/lib
(gdb) set solib-absolute-prefix /home/tronlong/rootfs
(gdb) target remote 192.168.2.200:1234
在配置正常时,PC通过网络连上ARM之后,在ubuntu上执行continue.
(gdb) continue
Continuing.
程序中printf的输出从gdbserver那边输出
解释
/home/tronlong/ti-processor-sdk-linux-rt-am57xx-evm-04.03.00.05/linux-devkit/sysroots/x86_64-arago-linux/usr/lib 为PC上ARM交叉编译工具链的的库路径,网上有人把这个路径也加到 solib-search-path 内了,加不加主要看你的程序里会不会引用对应的库。
我遇到问题的过程先表述一下
假设当前PC端未设置gdb环境变量,gdb会出现找不到库的情况
PC端gdb-multiarch调试时显示:
(gdb)
...... 省略
warning: Could not load shared library symbols for /usr/lib/libts-1.0.so.0.
Do you need "set solib-search-path" or "set sysroot"?
...... 省略
0xb6fd79c0 in ?? ()
...... 省略
ARM上搜libts-1.0.so.0
root@AM57xx-Tronlong:/mnt/nfs# ls -al /usr/lib |grep libts-1.0.so.0
lrwxrwxrwx 1 root root 18 Oct 14 20:26 libts-1.0.so.0 -> libts-1.0.so.0.0.0
-rwxr-xr-x 1 root root 7112 Oct 14 20:26 libts-1.0.so.0.0.0
然后添加环境变量,再重新走一遍流程,还是上面的问题,搞了很久才明白,是未添加环境变量的原因,那么就在gdb调试时添加
(gdb)
set solib-search-path /home/tronlong/rootfs/lib:/home/tronlong/rootfs/usr/lib
结果还是不行
PC上搜libts-1.0.so.0
tronlong@tronlong-virtual-machine:~/rootfs/usr/lib$ ls -al |grep libts-1.0.so.0
tronlong@tronlong-virtual-machine:~/rootfs/usr/lib$
PC的/home/tronlong/rootfs底下缺东西,说明PC上的rootfs与设备端的rootfs不一致(实际情况是,的确是不一致)
做驱动的同事给了我新的rootfs(他说这个rootfs和设备的一样),我把它依然放在了ubuntu的/home/tronlong/rootfs目录下(替换之前的rootfs),然后就可以了。
(gdb) target remote 192.168.2.200:1234
Remote debugging using 192.168.2.200:1234
warning: limiting remote suggested packet size (18431 bytes) to 16384
Reading symbols from /home/tronlong/rootfs/lib/ld-linux-armhf.so.3...(no debugging symbols found)...done.
Loaded symbols for /home/tronlong/rootfs/lib/ld-linux-armhf.so.3
Cannot access memory at address 0x0
0xb6fd79c0 in ?? () from /home/tronlong/rootfs/lib/ld-linux-armhf.so.3
但看PC端gdb-multiarch的输出,还是有问号的问题,这时不时找不到库了,而是库没有debug的符号表。
网友回答:
仔细看no debugging symbols found是在哪里的。是载入系统lib库的时候没有调试符号,这当然是没有的。
那么我不用理他,继续运行其他命令,调用list命令,bingo,终于看到代码了。
(gdb) list
9 Txdl myxdl;
10 effectivevaluethread rms;
11 algorithmthread algorithm;
12 comtradethread comtrade;
13 CANrec direc;
14
15 int main(int argc, char *argv[])
16 {
17 //调用虚拟键盘
18 qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
coredump处理
在发生coredump时,把coredump文件从arm拷到ubuntu。
ubuntu# gdb-multiarch ./kzx-xdl ./core.QThread.998.1603867475
(无需arm端执行,gdbserver)
(gdb) bt
在arm上执行kzx-xdl时不保存coredump文件时如何配置的问题。
arm 的/etc/sysctl.conf文件后面添加一行
kernel.core_pattern=/corefile/core.%e.%p.%t
其中/corefile目录可以根据情况自行更改,没有/corefile这个路径时需要先创建此目录。
例子:解决一个coredump问题,原因是kzx-xdl程序的comtrade进程内访问的文件不存在,所以逻辑出现了错误,引发的coredump
tronlong@zhangjyvm:~/nfs_share/work$ sudo gdb-multiarch ./kzx-xdl ./core.comtrade.1171.6
...... 省略了很多上面配置路径的语句和打印的语句
(gdb) bt
#0 0xb5e18ab6 in ?? () from /home/tronlong/rootfs/lib/libc.so.6
#1 0xb5e264f0 in raise () from /home/tronlong/rootfs/lib/libc.so.6
#2 0xb5e271ea in abort () from /home/tronlong/rootfs/lib/libc.so.6
#3 0xb61bdfa0 in QMessageLogger::fatal(char const*, ...) const () from /home/tronlong/rootfs/usr/lib/libQt5Core.so.5
#4 0xb61b94f8 in qt_assert_x(char const*, char const*, char const*, int) () from /home/tronlong/rootfs/usr/lib/libQt5Core.so.5
#5 0x000e81f0 in QList<QString>::operator[] (this=0xb01fece8, i=1)
at ../../ti-processor-sdk-linux-rt-am57xx-evm-04.03.00.05/linux-devkit/sysroots/armv7ahf-neon-linux-gnueabi/usr/include/qt5/QtCore/qlist.h:545
#6 0x000eee50 in comtradethread::xdl_initComtradeCfg (this=0x10a384f8 <comtrade>) at ../kzx-xdl/extensivecalc.cpp:620
#7 0x000eebb0 in comtradethread::StartWaveRecord (this=0x10a384f8 <comtrade>) at ../kzx-xdl/extensivecalc.cpp:597
#8 0x000eeb58 in comtradethread::run (this=0x10a384f8 <comtrade>) at ../kzx-xdl/extensivecalc.cpp:588
#9 0xb61d7734 in ?? () from /home/tronlong/rootfs/usr/lib/libQt5Core.so.5
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)
coredump产生后,进程内所有的线程都退出了,这点需要注意,架构设计时要考虑这个问题。
bt命令后的 #0 - #9行是这样的:
线程comtrade的coredump产生时,此线程的栈从#0 - #9层层保存,
- libc.so.6内的??(未知函数)-> libc.so.6内的函数raise()-> libc.so.6内的函数abort()->
- libQt5Core.so.5内的函数QMessageLogger::fatal(char const*, …) const ->
- libQt5Core.so.5内的函数qt_assert_x(char const*, char const*, char const*, int) ()->
- extensivecalc.cpp:620行,函数comtradethread::xdl_initComtradeCfg->
- extensivecalc.cpp:597行,函数comtradethread::StartWaveRecord->
- extensivecalc.cpp:588行,函数comtradethread::run 退出到这里已经到了线程超级循环函数了。