最近我的安卓项目中,native模块都是在linux环境下编译成so后再放到android studio工程中使用的,网上常见的gdb/ndk-gdb教程并不完全适用于我们项目,所以我总结了一份文档,供大家参考使用。
主机环境:ubuntu 18.04 in virtualBox
安卓平台:android 7.0 手机
android NDK: r14b
注意 android手机要有完全的root权限,ubuntu中也需提前配置好adb环境
将手机usb透传进虚拟机:
virtualBox菜单栏 ->设备 -> USB -> 选择对应的手机usb端口
下文中,PHONE:#
表示手机端(android)shell的命令,PC:$
表示主机端(ubuntu)shell的命令。
先确认手机cpu的类型
PHONE:# getprop ro.product.cpu.abi
我这台手机返回 armeabi-v7a
,对应的32位gdbserver,路径在NDK文件中:
~/android/android-ndk-r14b/prebuilt/android-arm/gdbserver/gdbserver
如果返回的是armeabi-v8a
,对应的是64位的gdbserver,路径在:
~/android/android-ndk-r14b/prebuilt/android-arm64/gdbserver/gdbserver
将gdbserver文件PUSH进手机并修改权限
PC:$ adb remount
PC:$ adb push gdbserver /system/bin
PC:$ adb shell chmod 755 /system/bin
android 4.4以上的机器,请关闭selinux,否则gdbserver可能无法attach到应用的进程上
PHONE:# echo 0 > /sys/fs/selinux/enforce
最后可以检查一下gdbserver的版本号来确认其有没安装好
PHONE:# gdbserver --version
GNU gdbserver (GDB) 7.11
so lib库需要增加一些debug的编译参数,修改Application.mk增加:
PROJECT/jni/Application.mk
APP_OPTIM := debug
APP_CFLAG:=-O0 -ggdb3 -fno-inline -g
然后编译出来带符号表的so文件在:
PROJECT/obj/local/armeabi-v7a/
这里比较简单的办法是直接在工程中使用上面生成的so文件,即直接覆盖android工程中的原来文件,后面就不需要再手动指定符号表的so文件了
先在手机上查询你应用的进程号
PHONE:# ps | grep "YOUR_PROJECT_NAME " | awk ‘{print $2}’
11856
把gdbserver attach上去,指定某端口(这里以6000为例)
PHONE:# gdbserver remote:6000 --attach 11856
Attached; pid = 11856
Listening on port 6000
上面没有报错说明attach成功了,新开一个shell窗口,将手机上的6000端口转发到pc的6000端口
PC:$ adb forward tcp:6000 tcp:6000
再去找ndk自带的gdb,在如下路径
~/android/android-ndk-r14b/prebuilt/linux-x86_64/bin/gdb
ndk路径下还有一个ndk-gdb,实质上ndk-gdb只是个py脚本,最终还是调用上面的gdb
运行上面的gdb,注意不要和ubuntu系统安装的gdb弄混了,这里 gdb版本应该是和上面的gdbserver对应的
PC:$ ./gdb
GNU gdb (GDB) 7.11
如果上面第3步没有把带符号表的so覆盖到android工程里面,这里需要手动指定这些so的路径(做了上面第3步请无视下面命令)
(gdb) set solib-search-path ~/SOURCE/PROJECT/obj/local/armeabi-v7a/
把gdb和远程的gdbserver连接起来
(gdb) target remote :6000
此时,gdb会将手机所有的lib都加载(包括我们应用中带符号表的so),期间你的应用可能会显示"停止响应",按继续等待就好了
加载完成后,终于可以用gdb进行愉悦的调试了_
~ EOF ~