一、简介
OpenHarmony系统层代码大部分是C++ 实现的,运用了C++ 继承多态等特性,使得代码框架灵活,但是对于开发者代码走读,整理实现逻辑不太友好。利用GDB调试导出调用栈、查看中间变量状态,则能帮助开发者快速清晰化实现逻辑链,不仅提升代码走读效率,而且提高Issue定位效率。
二、实践过程
本文从以下几方面介绍使用GDB调试OpenHarmony源码的过程与案例:
- 如何制作OpenHarmony之GDB。
- 如何准备可调试动态库。
- 如何使用GDB调试动态库。
- 案例展示。
1、制作OpenHarmony之GDB
如果已经有配套版本的GDB程序了,可以跳过这节直接进入下一步:2.3.1 上传GDB,将GDB工具上传到目标开发板。另外,为了方便,以下所有命令都在ubuntu编译机的root用户下进行。
(1)准备arm-Linux交叉编译环境
新建目录:
新建目录,路径如下:
/usr/local/ARM-toolchain/
获取工具包:
使用如下命令或者从浏览器手工下载arm-Linux交叉编译工具包:
wget https://releases.linaro.org/components/toolchain/binaries/latest-5/arm-linux-gnueabi/gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi.tar.xz
解压工具包:
将arm-Linux交叉编译工具包放在/usr/local/ARM-toolchain/目录下,使用以下命令解压:
tar xvf gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi.tar.xz
将该版本gcc的bin路径配置到系统环境变量PATH中,以便后续脚本执行能找到bin下的工具程序。
export PATH=$PATH:/usr/local/ARM-toolchain/gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi/bin/
(2)下载、编译GDB源码包
示例使用的版本是gdb-8.2.1.tar.gz,在以下路径获取。
https://mirrors.ustc.edu.cn/gnu/gdb/
在ubuntu编译机上任意建一个目录存放该包。如:
/home/kaihong/zzcgdb/gdb
解压:
tar zxvf gdb-8.2.1.tar.gz
进入解压后的文件目录:
cd gdb-8.2.1
在该目录下新建build目录,用于生成Makefile文件。
mkdir build
进入build目录:
cd build/
使用…/configure生成gcc编译的Makefile文件,命令如下:
CC="/usr/local/ARM-toolchain/gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc" CXX="/usr/local/ARM-toolchain/gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-g++" ../configure LDFLAGS=-static --prefix=$HOME/glibc32-2.6 -target=arm-linux-gnueabi --host=arm-linux-gnueabi
说明:
- 这里我用CC=和CXX=强行指定了arm编译器路径,因环境上/usr/bin/目录下有x86的gcc和g++,它们在PATH中可能会被优先找到,这样编出来就不是arm版的GDB程序了。
- 必须要指定LDFLAGS=-static (静态链接),这样编译时会把需要的库都一起编译进来,编译的结果会稍大一些,但能保证包含了所有需要的库。如果不指定这个参数,默认为动态链接方式,编译的GDB文件放到目标板上运行时可能会因找不到所需的依赖库而无法启动。
- 这一步执行完成后,builld目录下就成功生成了MakeFile文件。
开始编译:
make -j32
make install
两步都成功后,在build/gdb/目录下就生成了目标文件GDB。
可通过file命令检查编处的是否确实是arm版的GDB。
2、准备可调试动态库
开发板中将待调试的libnapitest.z.so动态库替换为携带调试信息的动态库。
- 源码当中找到携带调试信息的动态库,命令如下:
harmony@Ubuntu-64:~/OpenHarmony/out$ find ./ -name "*libnapites*" | xargs ls -lh
-rwxrwxr-x 1 harmony harmony 47K 8月 5 09:29 ./rk3568-khdvk/innerkits/ohos-arm/napitest_interface/napitest/libnapitest.z.so
-rwxrwxr-x 1 harmony harmony 766K 8月 5 09:28 ./rk3568-khdvk/lib.unstripped/napitest/napitest_interface/libnapitest.z.so
-rwxrwxr-x 1 harmony harmony 47K 8月 5 09:28 ./rk3568-khdvk/napitest/napitest_interface/libnapitest.z.so
-rw-rw-r-- 1 harmony harmony 10K 7月 29 18:07 ./rk3568-khdvk/packages/phone/NOTICE_FILES/system/lib/module/libnapitest.z.so.txt
-rwxrwxr-x 1 harmony harmony 47K 8月 5 09:35 ./rk3568-khdvk/packages/phone/system/lib/module/libnapitest.z.so
其中./rk3568-khdvk/lib.unstripped/napitest/napitest_interface/目录下的动态库(文件大小比其他文件大)为携带符号信息动态库,将该动态库下载到本地。
将携带符号信息的libnapitest.z.so动态库替换开发板中/system/lib/module目录下的libnapitest.z.so动态库。
由于/system/lib/module目录下只有读写权限,无法直接将镜像上传到/system/lib/module目录下。因此可将镜像上传到data目录下,修改文件权限后,再将/system/lib/module目录下的libnapitest.z.so镜像替换为携带符号信息的镜像。具体操作命令如下:
PS E:hdc> .hdc_std.exe file send .libnapitest.z.so /data FileTransfer finish, Size:784348 time:134ms rate:5853.34kB/s PS
E:hdc> .hdc_std.exe shell
# mount -o remount,rw /
# cp /data/libnapitest.z.so /system/lib/module/
3、使用GDB调试动态库
(1)上传GDB
有了编译好的arm版GDB,把它上传到目标开发板。
这里我们以hdc_std工具上传为例,如果你有其他的文件传输方式也可以。
准备GDB和hdc_std工具:
在window主机上建一个目录,将ubuntu虚拟机上编译好的GDB拷贝过来,并拷贝一个hdc_std工具到该目录。
将开发板与window主机连接,确保hdc_std工具能够连接访问。
在windows目录中开启第一个cmd命令行窗口,执行hdc_std shell 连接开发板。
上传GDB:
程序在windows目录下再开启第二个cmd命令行窗口,执行如下命令将GDB文件上传到开发版/data目录下(可以是任意目录,gdb大小约70M)。
hdc_std file send gdb /data
发送成功后,可以回到第一个cmd窗口中看到/data目录下的GDB程序
备注:
有的开发板在上传时可能会报没有写权限,如果遇到,可在hdc_std shell中执行如下命令打开读写权限:
mount -o remount,rw /
(2)调试GDB
进入/data目录,先给gdb程序加上可执行权限:
chmod +x /data/gdb
然后运行/data/gdb,出现如下信息说明GDB已经可以正常使用了。
如果不想每次执行都带完整路径, 可以在系统默认运行路径 (/bin) 下给/data/gdb做一个软链接:
ln -s /data/gdb /bin/gdb
4、案例展示
Issue:zzcnative2的应用调用NAPI接口add(8,3),接口返回值预期是11,实际结果为5
以上述Issue为例,展示一下GDB调试的过程。
在开发板上加载运行zzcnative2应用,该应用包含部分c++的native代码,可以使用GDB对其进行调式。
找到需要跟踪的进程号。
OpenHarmony的应用进程都是由应用孵化器(appspawn)创建的,可以先执行如下命令找到孵化器的进程号(92)。
ps -ef | grep appspawn
然后再找所有父进程为孵化器(92)的进程
ps -ef | grep 92
找到要调试的程序进程号(1167)后,执行如下命令运行GDB并挂到目标进程中
gdb attach 1167
在需要的地方打上断点,然后让程序继续运行。
在App上进行相关操作,触发断点所在的业务代码流程。
然后就可以开始各种调试手段了,如查看调用栈,打印变量,设置观测点等等,具体请参考GDB使用手册。
定位问题设置断点位置为Add入口,查看运行时入参value0、value1以及运行结果ret的值,发现逻辑与预期不一致,进一步使用list查看代码,发现“double ret = value0 – value1”符号错误,问题快速成功定位。
另外使用bt命令可打印调用栈信息,其他命令大家可以自己试一下。
三、总结
对于开发者来说,高效的调试手段至关重要,熟练使用GDB,可以帮忙大家提高代码走读、Issue定位效率,希望本次分享给大家一些启发,共同参与到OpenHarmony开发效率提升建设中。
文章版权声明
1 原创文章作者:8423,如若转载,请注明出处: https://www.52hwl.com/107006.html
2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈
3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)
4 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别