当前位置: 首页 > 科技观察

OpenHarmony标准系统实践中GDB调试

时间:2023-03-14 21:28:55 科技观察

了解更多开源请访问:开源基础软件社区https://ost.51cto.com1.OpenHarmony系统简介大部分层代码用C++实现,它利用C++的继承、多态等特性使代码框架灵活,但对开发者阅读代码和组织实现逻辑不是很友好。使用GDB调试导出调用栈,查看中间变量状态,可以帮助开发者快速清晰的实现逻辑链条,不仅提高了代码走读的效率,也提高了issue定位的效率。2.实践过程本文从以下几个方面介绍了使用GDB调试OpenHarmony源码的过程和案例:如何制作OpenHarmony的GDB。如何编写可调试的动态库。如何使用GDB调试动态库。案例介绍。1.制作OpenHarmony的GDB如果您已经有配套版本的GDB程序,可以跳过本节直接进入下一步:2.3.1上传GDB,将GDB工具上传到目标开发板。另外,为了方便起见,以下所有命令均在ubuntu编译器的root用户下执行。(1)准备arm-Linux交叉编译环境Createanewdirectory:新建目录,路径如下:/usr/local/ARM-toolchain/获取工具包:使用以下命令或手动下载arm-来自浏览器的Linux交叉编译工具包:wgethttps://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/目录下,使用以下命令解压:tarxvfgcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi.tar.xz在系统环境变量PATH中配置gcc的bin路径,以便后续脚本执行可以找到bin下的工具程序。exportPATH=$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解压:tarzxvfgdb-8.2.1.tar.gz进入解压后的文件目录:cdgdb-8.2.1在此目录下新建build目录,用于生成Makefile文件。mkdirbuild进入build目录:cdbuild/Use.../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++”。./configureLDFLAGS=-static--prefix=$HOME/glibc32-2.6-target=arm-linux-gnueabi--host=arm-linux-gnueabi说明:这里我使用CC=和CXX=强制指定arm编译器path,因为在环境的/usr/bin/目录下有x86的gcc和g++,可能在PATH中最先找到,所以编译出来的程序不是arm版的gdb程序。LDFLAGS=-static(静态链接)必须指定,这样在编译的时候会把所有需要的库一起编译,编译出来的结果会稍微大一些,但是可以保证把需要的库都包含进来。如果不指定该参数,则默认为动态链接方式。编译好的GDB文件放到目标板上运行时,可能会因为找不到需要的依赖库而启动失败。这一步完成后,在build目录下就成功生成了MakeFile文件。开始编译:make-j32makeinstall两步都成功后,在build/gdb/目录下生成了目标文件GDB。可以使用file命令查看修改后的版本是否确实是GDB的arm版本。2.准备可调试动态库在开发板中,将需要调试的libnapitest.z.so动态库替换为携带调试信息的动态库。在源码中找到带有调试信息的动态库,命令如下:harmony@Ubuntu-64:~/OpenHarmony/out$find./-name"*libnapites*"|xargsls-lh-rwxrwxr-x1harmonyharmony47KAugust509:29./rk3568-khdvk/innerkits/ohos-arm/napitest_interface/napitest/libnapitest.z.so-rwxrwxr-x1harmonyharmony766KAug509:28./rk3568-khdvk/lib.unstripped/napitest/napitest_interface/libnapitest.z.so-rwxrwxr-x1harmonyharmony47KAug509:28./rk3568-khdvk/napitest/napitest_interface/libnapitest.z.so-rw-rw-r--1harmonyharmony10K7Aug.2918:07./rk3568-khdvk/packages/phone/NOTICE_FILES/system/lib/module/libnapitest.z.so.txt-rwxrwxr-x1harmony和声47KAug.509:35./rk3568-khdvk/packages/phone/system/lib/module/libnapitest.z.so其中./rk3568-khdvk/lib.unstripped/napitest/napitest_interface/目录下的动态库(文件比其他文件大)是一个携带符号信息的动态库,下载动态库到本地。将开发板/system/lib/module目录下的libnapitest.z.so动态库替换为带有符号信息的libnapitest.z.so动态库。由于/system/lib/module目录只有读写权限,无法直接将镜像上传到/system/lib/module目录。因此,可以将镜像上传到data目录,修改文件权限,然后将/system/lib/module目录下的libnapitest.z.so镜像替换为带有符号信息的镜像。具体操作命令如下:PSE:\hdc>.\hdc_std.exefilesend.\libnapitest.z.so/dataFileTransferfinish,Size:784348time:134msrate:5853.34kB/sPSE:\hdc>.\hdc_std.exeshell#mount-oremount,rw/#cp/data/libnapitest.z.so/system/lib/module/3.使用GDB调试动态库(1)用编译好的arm版GDB上传GDB,上传到目标板。这里我们以hdc_std工具上传为例,如果你有其他文件传输方式也可以。准备GDB和hdc_std工具:在window主机上创建一个目录,将编译好的GDB复制到ubuntu虚拟机上,复制一个hdc_std工具到该目录下。将开发板连接到window主机,确保hdc_std工具可以连接访问。在windows目录下打开第一个cmd命令行窗口,执行hdc_stdshell连接开发板。上传GDB:程序在windows目录下打开第二个cmd命令行窗口,执行如下命令将GDB文件上传到开发版/data目录下(可以是任意目录,gdb大小70M左右)。hdc_stdfilesendgdb/data发送成功后,可以回到第一个cmd窗口,可以看到/data目录下的GDB程序注意:部分开发板上传时可能会报没有写权限。在hdc_stdshell中执行以下命令开启读写权限:mount-oremount,rw/(2)调试GDB并进入/data目录,首先给gdb程序添加可执行权限:chmod+x/data/gdb然后运行/data/gdb,出现如下信息,说明gdb可以正常使用了。如果不想每次执行都带全路径,可以在系统默认运行路径(/bin)下做一个软链接到/data/gdb:ln-s/data/gdb/bin/gdb4、案例展示Issue:应用zzcnative2调用NAPI接口add(8,3),接口返回值期望为11,实际结果为5。以上述Issue为例展示GDB调试过程。在开发板上加载并运行zzcnative2应用程序。该应用程序包含部分C++的本机代码,可以使用GDB对其进行调试。找到需要跟踪的进程号。OpenHarmony的应用进程是由应用孵化器(appspawn)创建的,可以先执行以下命令找到孵化器的进程号(92)。ps-ef|grepappspawn然后查找父进程为孵化器的所有进程(92)ps-ef|grep92找到要调试程序的进程号(1167)后,执行如下命令运行GDB挂到目标进程中gdbattach1167在需要的地方打断点,然后让程序继续运行。对App进行相关操作,触发断点所在的业务代码流程。然后就可以开始各种调试方式了,比如查看调用栈,打印变量,设置观察点等等,具体可以参考GDB手册。定位问题设置断点位置为Add入口,查看运行时入参value0、value1和运行结果ret的值,发现逻辑与预期不符,进一步使用list查看代码,发现那个符号“doubleret=value0–value1”是错误的,问题快速定位成功。另外,使用bt命令打印调用栈信息,其他命令大家可以自行尝试。3.总结对于开发者来说,高效的调试方法非常重要。熟练使用GDB可以帮助你提高代码阅读和issue定位的效率。希望本次分享能给大家一些启发,共同参与OpenHarmony开发效率提升的建设。.了解更多开源知识,请访问:开源基础软件社区https://ost.51cto.com。