- adb push gdbserver /system/bin/
"gdbserver"位于host的android-ndk-r9d\prebuilt\android-arm\gdbserver\gdbserver
- adb push E:\github\hello-jni\libs\armeabi /data/local/armeabi
armeabi目录下包括二进制程序及依赖的动态库,如main,libhello-jni.so
- adb forward tcp:7777 tcp:7777
- adb shell
- cd /data/local/armeabi
- chmod 777 ./main
- export LD_LIBRARY_PATH=./
- gdbserver :7777 ./main
root@msm8974:/data/local/armeabi # gdbserver :7777 main
gdbserver :7777 main
Process main created; pid = 2291
Listening on port 7777
- cd D:\Installer\android-ndk-r9d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin
toolchains版本默认为“arm-linux-androideabi-4.6”
-
arm-linux-androideabi-gdb.exe -q E:\github\hello-jni\obj\local\armeabi\main (指定的本地可执行文件与target上一致;且必须位于obj目录下,带调试信息)
- (gdb) target remote :7777
- (gdb) b main
- (gdb) continue (不可以用 run 或者start。main程序已经执行,只不过处于挂起状态)
- (gdb) i sharedlibrary
From To Syms Read Shared Object Library No /system/bin/linker No libc.so No libstdc++.so No libm.so No liblog.so No libcutils.so No libNimsWrap.so No libhello-jni.so- (gdb) set solib-search-path E:\github\hello-jni\obj\local\armeabi
- (gdb) i sharedlibrary
From To Syms Read Shared Object Library 0xb6f84a60 0xb6f8fac0 Yes (*) E:/github/hello-jni/obj/local/armeabi/linker 0xb6f2e180 0xb6f5ecec Yes (*) E:/github/hello-jni/obj/local/armeabi/libc.so No libstdc++.so No libm.so No liblog.so No libcutils.so No libNimsWrap.so 0xb6eecbec 0xb6eee0a0 Yes E:/github/hello-jni/obj/local/armeabi/libhello-jni.so- (gdb) next\step\break xxx......
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
printf("111111111111111\n");
printf("222222222222222222\n");
dynamicFunc();
return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");
}
void dynamicFunc()
{
printf("This called from dynamicFunc\n");
char *p=NULL;
*p = "123"; // signal SIGSEGV
}
比如点击按钮运行“stringFromJNI”,在调用到dynamicFunc()中存在错误的内存使用,产生段错误。
-
点击应用,运行apk服务
-
adb shell
- ps |grep "com.example.hellojni"
root@msm8974:/data/local/armeabi # ps|grep "com.example.hellojni" u0_a208 25704 277 1013352 27136 ffffffff 4010b8e8 S com.example.hellojni- gdbserver :7777 --attach 25704
root@msm8974:/data/local/armeabi # gdbserver :7777 --attach 25704 gdbserver :7777 --attach 25704 Attached; pid = 25704 Listening on port 7777
-
arm-linux-androideabi-gdb.exe -q
- (gdb) target remote :7777
- (gdb) set solib-search-path E:\github\hello-jni\obj\local\armeabi
- (gdb) c
- 点击按钮,触发crash
(gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x7c3f2c30 in dynamicFunc () at E:/github/hello-jni//jni/hello-jni.c:75 75 *p = "123";- (gdb) bt // 查看堆栈信息
(gdb) bt #0 0x7c3f2c30 in dynamicFunc () at E:/github/hello-jni//jni/hello-jni.c:75 #1 0x7c3f2c5c in Java_com_example_hellojni_HelloJni_stringFromJNI (env=0x41b91fc8, thiz=<optimized out>) at E:/github/hello-jni//jni/hello-jni.c:64 #2 0x41667768 in ?? () #3 0x4160a0d4 in ?? () #4 0x4160a0d4 in ?? () Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) next
Program received signal SIGILL, Illegal instruction.
0x7c3f1ba8 in ?? () from E:/github/hello-jni/obj/local/armeabi/libhello-jni.so
-
程序在指定的断点停下后,单步执行,会报如上错误。
-
原因:
It seems that the root cause is an address offset calculation are done twice in different places. I checked the rowboat kernel code in rowboat/rowboat-am335x-kernel-3.2 branch, the code isn't fixed yet.
- 安全红线问题
-
解决方法:
- 添加多个断点,使用continue操作。使用该方法代替单步。
Afaict openssl probes the capabilities of the user's CPU by trying to do things and trapping the illegal instruction errors. So a couple of sigills during startup is normal. When using a debugger in order to find the real failure in your application you must continue past the startup sigills. 14. Use GDB commands to debug
ndk-gdb --start --verbose --force --nowait
- 这个辅助脚本集成gdbserver、gdbclient等一系列操作,这是调试apk应用的最佳方式。
(gdb) bt
#0 0x400f08e8 in ?? ()
#1 0x4016a642 in ?? ()
#2 0x4016a642 in ?? ()
(gdb) i threads
Id Target Id Frame
11 Thread 10442 0x400f0ab0 in ?? ()
10 Thread 10432 0x400ef734 in ?? ()
9 Thread 10431 0x400ef734 in ?? ()
8 Thread 10429 0x400f0ab0 in ?? ()
7 Thread 10428 0x400f0ab0 in ?? ()
6 Thread 10427 0x400f0ab0 in ?? ()
5 Thread 10426 0x400f0ab0 in ?? ()
4 Thread 10425 0x400f0584 in ?? ()
3 Thread 10424 0x400f031c in ?? ()
2 Thread 10423 0x400f0ab0 in ?? ()
* 1 Thread 10419 0x400f08e8 in ?? ()
- adb pull /system/lib/libc.so E:\github\hello-jni\obj\local\armeabi
- (gdb) set solib-search-path E:\github\hello-jni\obj\local\armeabi
- i sharedlibrary
(gdb) i threads
Id Target Id Frame
11 Thread 10442 0x400f0ab0 in __futex_syscall3 () from E:/github/hello-jni/obj/local/armeabi/libc.so
10 Thread 10432 0x400ef734 in __ioctl () from E:/github/hello-jni/obj/local/armeabi/libc.so
9 Thread 10431 0x400ef734 in __ioctl () from E:/github/hello-jni/obj/local/armeabi/libc.so
8 Thread 10429 0x400f0ab0 in __futex_syscall3 () from E:/github/hello-jni/obj/local/armeabi/libc.so
7 Thread 10428 0x400f0ab0 in __futex_syscall3 () from E:/github/hello-jni/obj/local/armeabi/libc.so
6 Thread 10427 0x400f0ab0 in __futex_syscall3 () from E:/github/hello-jni/obj/local/armeabi/libc.so
5 Thread 10426 0x400f0ab0 in __futex_syscall3 () from E:/github/hello-jni/obj/local/armeabi/libc.so
4 Thread 10425 0x400f0584 in recvmsg () from E:/github/hello-jni/obj/local/armeabi/libc.so
3 Thread 10424 0x400f031c in __rt_sigtimedwait () from E:/github/hello-jni/obj/local/armeabi/libc.so
2 Thread 10423 0x400f0ab0 in __futex_syscall3 () from E:/github/hello-jni/obj/local/armeabi/libc.so
* 1 Thread 10419 0x400f08e8 in epoll_wait () from E:/github/hello-jni/obj/local/armeabi/libc.so
(gdb) bt
#0 0x400f08e8 in epoll_wait () from E:/github/hello-jni/obj/local/armeabi/libc.so
#1 0x4016a642 in ?? ()
#2 0x4016a642 in ?? ()
- 相关动态库的信息就打印出来了。原因就在于host上不存在target上的动态库或者版本不一致。需要将target上实际使用的动态库同步到本地
- 在host上,创建本地目录,专门存放该型号手机下的系统lib
mkdir ~/HUAWEI_P10
mkidr ~/HUAWEI_P10/system_lib
mkidr ~/HUAWEI_P10/vendor_lib
- 同步target的多个目录、文件至host
cd ~/Android/system_lib/
adb pull /system/lib
cd ~/Android/vendor_lib/
adb pull /vendor/lib
cd ~/Android
# 在64位系统 /system/bin/app_process32 和 /system/bin/app_process64
adb pull /system/bin/app_process
cd ~/Android
# 在64位系统 /system/bin/linker 和 /system/bin/linker64
adb pull /system/bin/linker
set solib-search-path J:\git\SDK-Project\TF-SDK\src\main\obj\local\armeabi;H:\Users\liuwb\HUAWEI_P10;H:\Users\liuwb\HUAWEI_P10\system_lib;H:\Users\liuwb\HUAWEI_P10\vendor_lib
其中:
- 多路径之间必须用
";"分割!!(windows环境下) - 原因:
Multiple directories can be specified but must be separated with either:
a colon (Unix)
a semi-colon (Windows).
- 也可参考host本身的
PATH,同样使用;分割
(gdb) PATH
Executable and object file path: D:\Android\android-ndk-r9d\prebuilt\windows\bin;H:\WINDOWS\system32;H:\WINDOWS;H:\WINDOWS\System32\Wbem;H:\WINDOWS\System32\WindowsPowerShell\v1.0\;H:\Program Files (x86)\Java\jdk1.7.0_55\bin;
NDK在非root手机上调试APP的原理:gdbserver通过run-as获得与目标进程相同的UID,然后就可以ptrace到目标进程去调试了。
- APP开启debuggable:"android:debuggable="true""
- 推送cmd:gdbserver至手机中某目录下
adb push D:\Android\android-ndk-r9d\prebuilt\android-arm\gdbserver\gdbserver /sdcard/
- 进入APP沙盒内(本质使得接下来的操作获得与目标APP同样的UID。原因:由于gdbserver使用ptrace注入目标进程,权限检查包括gdbserver和目标进程的uid、gid一致,而run-as可以修改gdbserver进程的uid)
adb shell
run-as km.ssl
- 获得gdbserver命令行,拷贝至APP目录下
HWVKY:/data/data/km.ssl $ pwd
/data/data/km.ssl
cp /sdcard/gdbserver ./
chmod 777 ./gdbserver
- 运行APP,获得APP进程号,attach后进行调试。(与上相同)
HWVKY:/sdcard $ ps|grep km.ssl
ps|grep km.ssl
u0_a343 16940 516 1592224 109824 0 0000000000 S km.ssl
HWVKY:/data/data/km.ssl $ ./gdbserver :7777 --attach 16940
./gdbserver :7777 --attach 16940
Attached; pid = 16940
Listening on port 7777
- gdbserver 使用socket启动失败,报错:
130|a6pltechn:/data/data/com.ximalaya.mediaprocessor $ ./gdbserver :7777 --attach 26229
Can't open socket: Permission denied.
Exiting
- gdbserver 使用管道代替,启动成功:
1|a6pltechn:/data/data/com.ximalaya.mediaprocessor $ ./gdbserver +debug-pipe --attach 26229
Attached; pid = 26229
Listening on Unix socket debug-pipe
- 此时,host下的设置需要做相应调整,表示已经建立本地10000端口到server端pipe的映射:
adb forward --remove-all
adb forward tcp:10000 local:/data/data/com.ximalaya.mediaprocessor/debug-pipe
adb forward --list
8a329736 tcp:10000 local:/data/data/com.ximalaya.mediaprocessor/debug-piped
- 此时,gdbclient无法连接到remote上,调试中断
(gdb) target remote :10000
Remote debugging using :10000
Remote communication error. Target disconnected.: Connection reset by peer.
arm-linux-androideabi-gdb在新版本ndk中已经废除,需要从老版本r10e中找。