android 调试 native 程序的方法

摘要:
二、方法首先,尝试搜索gdb-for-arm的工具,就是看有没有一个gdb可执行程序,是可以直接在androidarmdevices上运行的,如果有的话,就跟直接在linux环境里调试一样了,可惜,这么简单的需求,都搜索不到下面都是尝试用远程调试的方式第一种,客户端在win7.使用idapro6.6,它提供了一个android_server可以用来push到android系统里运行,然后在ida的界面里runremote可执行程序,这种方式可以跑起来,可以单步执行、可以下断点,但是无法加载正确的符号表。

一、背景

首先说需求,这个需求非常常见,就是android上需要的一个功能,linux已经有开源代码而且非常稳定,希望能直接porting过去使用,这个程序是pure c 的代码,也就是说,跟android framework, java 没关系,也跟jni没有关系,我们希望的就是能编译成一个可执行工具,push到android后能直接跑起来使用。

既然是native 代码,主要影响到的就是bionic libc, 因为android的这个基础库跟 linux 上常见的 gnu libc 有区别,主要是被精简了,至于更具体理解什么叫被精简,建议找个linux 开源工具代码在 android ndk 环境里编一下就知道了,其实,这里边还隐藏另外两层区别,一个是 android api level, 就是所谓的android 版本,比如 android 4.4.4 对应 android API 19, android 5 对应 android API 21 , 不同版本的 bionic libc 本身也是有区别的。 另一个是 abi , 就是体系架构的区别,比如 x86, x86_64, armeabi -v7a 等等,不同 abi 设置下 bionic libc 用到的接口也不一样。上面这两个影响会导致,你的代码可能在 API 21 编译通过了,但是在 API 19 失败,或者,在 armeabi-v7a 成功了,但是在 arm64-v8a 失败了。这两点的处理放在另外的文章说明,这篇文章不考虑。可以认为,我们暂时不考虑编译出来的工具的通用性,只在特定的目标,如 abi = armeabi-v7a, api = 21 的android devices 上运行。

好了,我们已经编成功了这个工具,push 到目标设备后(或模拟器)发现运行出现段错误,这是非常常见的,因为在移植过程中,我们把某些 glibc 的调用替换成了 bionic 的调用,接下去应该怎么调试呢?首先说这里的调试,当然是源码级别的单步调试,就是我们在 linux 上开发并调试程序一样。这个要求看似简单,但我搜索了一天的时间,尝试了多种方式,最后才找到一种简单可用且匹配需求的方式。

二、方法

首先,尝试搜索 gdb-for-arm 的工具,就是看有没有一个 gdb 可执行程序,是可以直接在 android arm devices 上运行的,如果有的话,就跟直接在 linux 环境里调试一样了,可惜,这么简单的需求,都搜索不到

下面都是尝试用远程调试的方式

第一种,客户端在win7. 使用 ida pro 6.6 , 它提供了一个 android_server 可以用来push到 android 系统里运行,然后在 ida 的界面里 run remote 可执行程序,这种方式可以跑起来,可以单步执行、可以下断点,但是无法加载正确的符号表。

第二种,客户端在win7,找了一个http://gnutoolchains.com/android/ 为android 编译好的 gnu tool chains 网站,下载 gdbserver 和 gdb.exe , gdbserver push到目标机器跑起来,本地用 gdb.exe 启动,使用gdb 远程调试那套步骤进行设置,发现也是能够跑起来,还是无法正确加载符号表。

第三种,客户在在win7,使用Cygwin 的方式跑gdb客户端,启动之后 cygwin 报了一个长度太长的问题,没有深入去解决

从这里开始,突然对在win7 下启动 gdb 客户端有些失望,随即改为在 ubuntu14.04 里启动 gdb 客户端, android 模拟器也在 ubuntu 里启动。这里的 ubuntu 跑在 win7 上的 vmware 里。具体如果在 ubutnu 里下载并配置 android sdk 开发环境,并创建 avd , 启动 avd, 可以从网上搜索,最终就是在 ubuntu 里正常启动一个 android emulator.

然后,就使用下面的方式,就是可以源代码单步调试了:

1. 在设备上部署gdbserver
所谓部署其实就是把android ndk下的gdbserver拷贝到设备上,可以通过如下命令
adb push $ANDROID_NDK_ROOT/prebuilt/android-arm/gdbserver/gdbserver /data
2. 在设备上部署你的Native程序
需要把你编译出的程序和相关so库部署到设备上,注意so库要放在/system/lib下,/system路径默认是只读的,可以通过adb remount来重置。
adb push ./myapp /data/data
adb push ./libmylib.so /system/lib
3. 把设备上的相关调试环境拷贝到本地
因为远程调试需要一些目标机的库,把如下文件拷贝到本地文件夹
adb pull /system/lib ./debugging/lib
adb pull /system/bin/linker ./debugging/lib
4. 在设备上通过gdbserver运行你的程序
adb shell gdbserver :12345 /data/data/myapp
5. 在本地把本地TCP端口forward到设备的TCP端口
adb forward tcp:12345 tcp:12345
6. 在本地运行Android ndk路径下的gdb程序
$ANDROID_NDK/toolchains/arm-linux-androideabi-4.4.3/prebuild/darwin-x86/bin/arm-linux-androideabi-gdb
这里注意如果你在Ubuntu下用的是Linux的NDK包,那路径会有点不同,darwin-x86的地方应该是linux-x86.最保险的还是自己在NDK下搜索。注意,必须是启动arm gdb, 如果是启动linux系统默认的 gdb (x86,x64 架构), 可能执行 “target remote :12345” 会报错 “Remote 'g' packet reply is too long:”
7. 启动gdb后在gdb下设置solib搜索路径
就是让gdb运行时能够找到调试相关的那些lib,也就是那些第三步中从设备上拉下来的文件。
(gdb) set solib-search-path ./debugging/lib
8. 在gdb下设置你希望调试的Native程序
(gdb) file ./myapp
9. 连接到设备的gdbserver
(gdb) target remote :12345
上面的6~9步也可以通过如下命令一步执行完
$ANDROID_NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb --eval-command="set solib-search-path ./debugging/lib"--eval-command="file./myapp"--eval-command="target remote :12345"
10. 开始调试
通过continue或c运行程序。注意不是用run,因为程序在目标机上其实已经启动了,只是break在程序入口。

免责声明:文章转载自《android 调试 native 程序的方法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇一文带你了解 HTTP 黑科技SpringCloud Alibaba实战(5:子模块基本业务开发)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C#中的release和debug模式

以下内容来源:https://www.cnblogs.com/rgjycs/p/9254332.html 在程序调试时的debug和release 网上有如下的描述:Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好...

linux运维、架构之路-K8s二进制版本升级

一、升级说明        Kubernetes集群小版本升级基本上是只需要更新二进制文件即可。如果大版本升级需要注意kubelet参数的变化,以及其他组件升级之后的变化。 由于Kubernetes版本更新过快许多依赖并没有解决完善,并不建议生产环境使用较新版本。 二、软件准备 1、下载地址 https://github.com/kubernetes/ku...

Deepin/UOS/debian/Ubuntu/Linux下搭建pyqt5开发环境—基于Pycharm

前言 由于Deepin/UOS/debian/Ubuntu自带python,所以不用管Python环境 默认你已经下好了并安装了pycharm 本教程实验环境 系统版本:deepin 社区版 20.2.4 python版本:python 3.7.3 pycharm版本:PyCharm 2021.2.1 (Community Edition) 一、安装 py...

Android学习笔记十:异步处理

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7520700.html 一:基础概念 UI线程:当Android程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件、屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。主线程通常又被称为...

Linux less grep

第一步,less查看文件 less 日志文件名 1,这时候,使用组合键 shift + g 可以定位到文件末尾。 在文件末尾,使用组合键(从末尾开始根据之后输入的字符串向上检索) shift + ? 然后输入查询条件,可以是时间串,也可以是关键字,比如日志有打印userid,则输入有问题的userid,检测所有有该userid出现过的日志。 使用...

操作笔记:linux下安装mysql

1,检查linux下是否安装了mysql shell指令如下: [root@iZ945sgm0ugZ ~]# rpm -qa|grep -i mysql 如果有的话:做出挨个删除(eg:rpm -ev mysql-connector-odbc-5.2.5-6.el7.x86_64) [root@iZ945sgm0ugZ ~]# rpm -qa|grep -...