GDB调试Android代码——环境搭建及调试过程

网上看了好多关于GDB调试android本地代码的,但是都是直接上手,对于一点都不懂的我,真是难办,所以本人根据个人经历,总结下怎么从小白一步一步进行调试。


先讲一下GDB调试android本地代码的情况。开始看了好多资料,天真的以为用GDB命令就能直接启动so库,实际情况是,先写好JNI的应用之后,肯定是java代码去调用本地代码的,所以需要设置按钮之类的,在调试过程中,需要通过按钮或其他方式,启动jni的本地代码。每次设置了断点之后,需要点击按钮启动代码,然后代码运行到断点出停止,然后通过GDB命令查看各种信息,或者继续运行。


好了下面开始介绍


调试环境:

调试平台:ubuntu14.04LTS

目标手机:Android6.0虚拟机 X86架构,我用的nexus5,烧的原生系统,ROOT,直接自带gdbserver

软件环境:android-ndk-r10b搭配adt-bundle,并且自己准备一个包含JNI调用的应用


然后准备gdb和gdbserver,远程调试需要在目标手机上有个类似调试客户端的东西来给gdb传送数据什么的,然后在linux上接受这些信息,进行调试,所以需要这两个东西,在网上看的资料各种在线下载或者交叉编译什么的才能得到这两个东西,其实不用那么麻烦,NDK里自带(Android源码里边也带,请自行查找):

1. gdb:$NDK_DIR/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb,中间的路径根据自己情况更改。

2. gdbserver:位置:$NDK_DIR/prebuilt/android-arm64/gdbserver

因为我的测试机自带gdbserver,所以我直接用NDK目录中的gdb配合使用,如果不用ndk的,用Android源码目录下的GDB话效果一样的。

需要注意的是gdbserver和gdb的版本要匹配,否则会出错。

查看gdbserver版本号:

conan@conan-HP-Pro-3380-MT:~$ adb shell
shell@hammerhead:/ $ gdbserver --version
GNU gdbserver (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
gdbserver is free software, covered by the GNU General Public License.
This gdbserver was configured as "arm-eabi-linux"

查看gdb版本号:

conan@conan-HP-Pro-3380-MT:~/java/adt-bundle-linux-x86_64-20140321/android-ndk-r10b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin$ ./arm-linux-androideabi-gdb --version
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
For bug reporting instructions, please see:
<http://source.android.com/source/report-bugs.html>.
conan@conan-HP-Pro-3380-MT:~/java/adt-bundle-linux-x86_64-20140321/android-ndk-r10b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin$ 



网上还有人说了了这个问题,好像确实有影响,所以也适当注意下,我是通过RE管理器直接修改的:

对了,还有一点需要注意的是,Android从4.4开始,强制打开了SELinux,其规则是不允许一个进程attach到一个非自己的子进程或兄弟进程上进行调试的,哪怕这个进程是以root用户启动的也不行。想要知道当前SELinux的工作模式,可以在adb shell下键入getenforce命令,例如:


这是在我运行Android 5.0系统的Google Nexus 5上运行的结果,可以看出,其已经默认打开了强制(Enforcing)模式。所以,要想调试成功,必须要关闭SELinux的强制模式,可以通过下面的命令来关闭:

        echo 0> /sys/fs/selinux/enforce

注意,这条命令必须用root用户来运行。下面看看运行后的结果:


可以看出,SELinux的模式已经从强制变成了允许(Permissive)。


准备妥当后就可以调试了,当然要写好自己的应用工程,包含jni代码的,我写的为JNI_test。

1 首先启动要调试的程序,ps 获取其进程号 (或者在eclipse的DDMS中直接查看)

conan@conan-HP-Pro-3380-MT:~$ adb shell
shell@hammerhead:/ $ ps | busybox grep jni      
u0_a78    23954 319   920924 49544 sys_epoll_ 00000000 S com.example.jni_test


2 启动gdbserver attach到目标进程  (在adb进入手机上操作,注意此时需要root权限)

shell@hammerhead:/ $ su
root@hammerhead:/ # gdbserver remote:1234 --attach 23954
Attached; pid = 23954
Listening on port 1234

其中 remote:1234 表示映射成tcp的1234端口,这个时候重新打开一个 adb shell 再ps yahfa发现

shell@hammerhead:/ $ ps | busybox grep yahfa
u0_a78    23954 319   930024 49648 ptrace_sto 00000000 t com.example.hook_yahfa
进程状态已经变成 t了,表示 attach已经成功了。


3 启动gdb 来进行调试 (pc环境中操作,我用的是ubuntu系统)

conan@conan-HP-Pro-3380-MT:~/Android/android-6.0.0_r1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin$ adb forward tcp:1234 tcp:1234

首先端口映射,映射成 1234 端口号


把/system/bin/app_process,/system/bin/linker,/system/lib/libc.so 从手机上拷贝出来(可以用adb pull 命令),其他so文件也拷贝出来也行,我们假定拷贝的目录为$lib

conan@conan-HP-Pro-3380-MT:~$ adb pull /system/bin/app_process /home/conan/java/tmp/GDB 
269 KB/s (22144 bytes in 0.080s)
conan@conan-HP-Pro-3380-MT:~$ adb pull /system/bin/linker /home/conan/java/tmp/GDB 
1351 KB/s (189636 bytes in 0.137s)
conan@conan-HP-Pro-3380-MT:~$ adb pull /system/lib/libc.so /home/conan/java/tmp/GDB 
2997 KB/s (676872 bytes in 0.220s)
conan@conan-HP-Pro-3380-MT:~$ 

运行arm-linux-androideabi-gdb ,输入以下命令序列 file $lib/app_process,   $lib目录中有从手机拷贝出来的app_process,linker和libc.so这些文件 ,如我放到了/home/conan/java/tmp/GDB目录下

conan@conan-HP-Pro-3380-MT:~/java/adt-bundle-linux-x86_64-20140321/android-ndk-r10b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin$ ./arm-linux-androideabi-gdb
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
For bug reporting instructions, please see:
<http://source.android.com/source/report-bugs.html>.
(gdb) file /home/conan/java/tmp/GDB/app_process
Reading symbols from /home/conan/java/tmp/GDB/app_process...(no debugging symbols found)...done.


set solib-absolute-prefix $nostriplib_dir, $nostriplib_dir是存放了没有strip的so的目录,因为我们有源代码,而本身android 源码ndk编译的时候默认是加 -g选项的,没有被 strip的so库在/home/conan/java/tmp/eclipse_android/JNI_test/obj/local/armeabi这个目录下,而在libs下的so是被 strip过的版本

gdb) set solib-absolute-prefix /home/conan/java/tmp/eclipse_android/JNI_test/obj/local/armeabi
(gdb) 

set solib-search-path $lib:$nostriplib_dir,

(gdb) set solib-search-path /home/conan/java/tmp/GDB:/home/conan/java/tmp/eclipse_android/JNI_test/obj/local/armeabi
(gdb) 

target remote :端口号 连上gdbserver

(gdb) <pre name="code" class="plain">(gdb) target remote :1234
Remote debugging using :1234
warning: Could not load shared library symbols for 118 libraries, e.g. /system/lib/libsigchain.so.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
Reading symbols from /home/conan/java/tmp/GDB/linker...(no debugging symbols found)...done.
Loaded symbols for /home/conan/java/tmp/GDB/linker
Reading symbols from /home/conan/java/tmp/GDB/libc.so...(no debugging symbols found)...done.
Loaded symbols for /home/conan/java/tmp/GDB/libc.so
Reading symbols from /home/conan/java/tmp/eclipse_android/JNI_test/obj/local/armeabi/libJNI_test.so...done.
Loaded symbols for /home/conan/java/tmp/eclipse_android/JNI_test/obj/local/armeabi/libJNI_test.so
0xb6d4a2e4 in __epoll_pwait () from /home/conan/java/tmp/GDB/libc.so

进入gdb,并监听1234端口,警告可以忽略,因为没从手机上pull出这些库,不影响的。

这个时候已经进入 gdb了

dir source 指定源码路径

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值