Android-jni(7)-反编译异常查看源代码位置

在我们平时出现ndk异常,光是看错误是看不懂的,比如以下错误:

A/libc: stack corruption detected (-fstack-protector)
A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 9466 (shixin.ndkdemo)
2018-12-02 22:27:41.096 2670-2990/com.google.android.gms I/Icing: Usage reports ok 0, Failed Usage reports 0, indexed 0, rejected 0, imm upload false
I/crash_dump32: obtaining output fd from tombstoned
I//system/bin/tombstoned: received crash request for pid 9466
I/crash_dump32: performing dump of process 9466 (target tid = 9466)
A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
A/DEBUG: Build fingerprint: 'google/sdk_gphone_x86/generic_x86:8.0.0/OSR1.170901.056/4497355:userdebug/dev-keys'
A/DEBUG: Revision: '0'
A/DEBUG: ABI: 'x86'
A/DEBUG: pid: 9466, tid: 9466, name: shixin.ndkdemo  >>> shixin.ndkdemo <<<
A/DEBUG: signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
A/DEBUG: Abort message: 'stack corruption detected (-fstack-protector)'
A/DEBUG:     eax 00000000  ebx 000024fa  ecx 000024fa  edx 00000006
A/DEBUG:     esi 000024fa  edi bfa41188
A/DEBUG:     xcs 00000073  xds 0000007b  xes 0000007b  xfs 0000003b  xss 0000007b
A/DEBUG:     eip affadac4  ebp bfa411a8  esp bfa4113c  flags 00000296
A/DEBUG: backtrace:
                //报错起始地址
A/DEBUG:     #00 pc 00000ac4  [vdso:affad000] (__kernel_vsyscall+16)
A/DEBUG:     #01 pc 00075b3c  /system/lib/libc.so (tgkill+28)
A/DEBUG:     #02 pc 0001f04e  /system/lib/libc.so (abort+110)
A/DEBUG:     #03 pc 0002720e  /system/lib/libc.so (__libc_fatal+46)
A/DEBUG:     #04 pc 00072f63  /system/lib/libc.so (__stack_chk_fail+35)
A/DEBUG:     #05 pc 00008ec2  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/lib/x86/libmy_native_lib.so (_Z12arrayPointerv+194)
A/DEBUG:     #06 pc 000090ce  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/lib/x86/libmy_native_lib.so (Java_shixin_ndkdemo_MainActivity_testCrash+46)
A/DEBUG:     #07 pc 000096f8  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/oat/x86/base.odex (offset 0x9000)
A/DEBUG:     #08 pc 00059fff  [anon:libc_malloc:afd00000]
A/DEBUG:     #09 pc 01244a67  /dev/ashmem/dalvik-main space (region space) (deleted)
A/DEBUG:     #10 pc 8bc3b28f  
A/DEBUG:     #11 pc 80c1c541  
A/DEBUG:     #12 pc 0d3fffff  /dev/ashmem/dalvik-main space (region space) (deleted)

咱们只能看到报错的起始地址:00000ac4,看不到具体对应的源代码路径,不能像java那样方便查看,很是头疼,其实也有方式看的,比如后面记录的两种。

在说这个之前,先简单说下符号表:

  • 符号表:

符号表是内存地址与函数名、文件名、行号的映射表,就像咱们java离的mapping文件类似的作用,可以定位出具体源代码。平时我们自己编写ndk的时候(这里指的cmake方式),/build/intermediates/cmake/路径下生成的so都是带符号表的,所以so会比较大。当打出apk的时候,就自动trip了,去符号表,so就比较小了。官网参数DCMAKE_BUILD_TYPE有说到。

接下来看下反编译的方式:

一. add2Line 工具

  • add2line工具路径:
ndk-bundle目录->toolchains->对应的abi(比如x86)->prebuild->目录->bin->文件后缀为-addr2line
  • 命令方式如下:
add2line -e 带符号表的so路径 错误栈地址

咱们利用add2line -e命令来输出错误栈对应源代码信息,从调用栈一个一个查找下来,下面为查找到#06步:

./i686-linux-android-addr2line -e /Users/MyDemo/NDKDemo/app/build/intermediates/cmake/debug/obj/x86/libmy_native_lib.so 000090ce

输出:

/MyDemo/NDKDemo/app/src/main/cpp/crash_test.cpp:99

惊喜,这样就输出错误的cpp文件与行数了。

利用该工具可以使用so与错误日志中的地址来显示出源文件中的位置。

二. ndk-stack 命令

上面用add2line工具虽然可以查看,但是一个一个的查下去,很慢,效率很低,所以一般都没用那种,常用ndk-stack命令,官方使用说明点这里.

  • ndk-stack路径
sdk/ndk-bundle/ndk-stack

命令方式:

  1. 以logcat作为输入,可即时显示出来
  • 命令:参数-sym
adb logcat | ndk-stack路径 -sym 工程下abi路径(比如build/intermediates/cmake/debug/obj/armeabi)
  • 使用
//这里是在ndk-stack路径下,后面是x86路径
adb logcat | ./ndk-stack -sym /Users/MyDemo/NDKDemo/app/build/intermediates/cmake/debug/obj/x86

只要一遇到错误就会输出(刚执行过缓存的错误,或者接下来复现的错误):

signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Stack frame #00 pc 00000ac4  [vdso:affad000] (__kernel_vsyscall+16)
Stack frame #01 pc 00075b3c  /system/lib/libc.so (tgkill+28)
Stack frame #02 pc 0001f04e  /system/lib/libc.so (abort+110)
Stack frame #03 pc 0002720e  /system/lib/libc.so (__libc_fatal+46)
Stack frame #04 pc 00072f63  /system/lib/libc.so (__stack_chk_fail+35)
Stack frame #05 pc 00008ec2  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/lib/x86/libmy_native_lib.so (_Z12arrayPointerv+194): Routine arrayPointer() at /Users/shixin/Documents/MyProject/MyDemo/NDKDemo/app/src/main/cpp/crash_test.cpp:?
Stack frame #06 pc 000090ce  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/lib/x86/libmy_native_lib.so (Java_shixin_ndkdemo_MainActivity_testCrash+46): Routine Java_shixin_ndkdemo_MainActivity_testCrash at
                            //这里输出了错误有关信息行数了
/Users/shixin/Documents/MyProject/MyDemo/NDKDemo/app/src/main/cpp/crash_test.cpp:99
Stack frame #07 pc 000096f8  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/oat/x86/base.odex (offset 0x9000)
Stack frame #08 pc 00059fff  [anon:libc_malloc:afd00000]
Stack frame #09 pc 0150a00f  /dev/ashmem/dalvik-main space (region space) (deleted)
Stack frame #10 pc 8bc3b28f  
Stack frame #11 pc 80c1c541  
Stack frame #12 pc 0d3fffff  /dev/ashmem/dalvik-main space (region space) (deleted)
  1. 使用带错误日志的文件:
  • 命令:参数-sym 基础上再加个-dump
ndk-stack路径 -sym 工程下abi路径(比如build/intermediates/cmake/debug/obj/armeabi) -dump 
日志文件路径
  • 使用
./ndk-stack -sym /MyDemo/NDKDemo/app/build/intermediates/cmake/debug/obj/x86 -dump /crash_test.txt

输出:

********** Crash dump: **********
Build fingerprint: 'google/sdk_gphone_x86/generic_x86:8.0.0/OSR1.170901.056/4497355:userdebug/dev-keys'
pid: 11596, tid: 11596, name: shixin.ndkdemo  >>> shixin.ndkdemo <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Stack frame #00 pc 00000ac4  [vdso:affad000] (__kernel_vsyscall+16)
Stack frame #01 pc 00075b3c  /system/lib/libc.so (tgkill+28)
Stack frame #02 pc 0001f04e  /system/lib/libc.so (abort+110)
Stack frame #03 pc 0002720e  /system/lib/libc.so (__libc_fatal+46)
Stack frame #04 pc 00072f63  /system/lib/libc.so (__stack_chk_fail+35)
Stack frame #05 pc 00008ec2  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/lib/x86/libmy_native_lib.so (_Z12arrayPointerv+194): Routine arrayPointer() at /Users/shixin/Documents/MyProject/MyDemo/NDKDemo/app/src/main/cpp/crash_test.cpp:?
Stack frame #06 pc 000090ce  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/lib/x86/libmy_native_lib.so (Java_shixin_ndkdemo_MainActivity_testCrash+46): Routine Java_shixin_ndkdemo_MainActivity_testCrash at /Users/shixin/Documents/MyProject/MyDemo/NDKDemo/app/src/main/cpp/crash_test.cpp:99
Stack frame #07 pc 000096f8  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/oat/x86/base.odex (offset 0x9000)
Stack frame #08 pc 00059fff  [anon:libc_malloc:afd00000]
Stack frame #09 pc 016cf007  /dev/ashmem/dalvik-main space (region space) (deleted)
Stack frame #10 pc 8bc3b28f  
Stack frame #11 pc 80c1c541  
Stack frame #12 pc 0d3fffff  /dev/ashmem/dalvik-main space (region space) (deleted)
Crash dump is completed

********** Crash dump: **********
Build fingerprint: 'google/sdk_gphone_x86/generic_x86:8.0.0/OSR1.170901.056/4497355:userdebug/dev-keys'
pid: 11627, tid: 11627, name: shixin.ndkdemo  >>> shixin.ndkdemo <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Stack frame #00 pc 00000ac4  [vdso:affad000] (__kernel_vsyscall+16)
Stack frame #01 pc 00075b3c  /system/lib/libc.so (tgkill+28)
Stack frame #02 pc 0001f04e  /system/lib/libc.so (abort+110)
Stack frame #03 pc 0002720e  /system/lib/libc.so (__libc_fatal+46)
Stack frame #04 pc 00072f63  /system/lib/libc.so (__stack_chk_fail+35)
Stack frame #05 pc 00008ec2  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/lib/x86/libmy_native_lib.so (_Z12arrayPointerv+194): Routine arrayPointer() at /Users/shixin/Documents/MyProject/MyDemo/NDKDemo/app/src/main/cpp/crash_test.cpp:?
Stack frame #06 pc 000090ce  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/lib/x86/libmy_native_lib.so (Java_shixin_ndkdemo_MainActivity_testCrash+46): Routine Java_shixin_ndkdemo_MainActivity_testCrash at
                        //错误信息对应源文件路径
/Users/shixin/Documents/MyProject/MyDemo/NDKDemo/app/src/main/cpp/crash_test.cpp:99
Stack frame #07 pc 000096f8  /data/app/shixin.ndkdemo-DtANX0oY1bKGylfJQXqMVg==/oat/x86/base.odex (offset 0x9000)
Stack frame #08 pc 00059fff  [anon:libc_malloc:afd00000]
Stack frame #09 pc 016d1dcf  /dev/ashmem/dalvik-main space (region space) (deleted)
Stack frame #10 pc 8bc3b28f  
Stack frame #11 pc 80c1c541  
Stack frame #12 pc 0d3fffff  /dev/ashmem/dalvik-main space (region space) (deleted)

看也有错误栈对应源文件路径了。

三. 总结

  1. add2line通过地址查看源文件错误位置
  2. ndk-stack命令使用更多,通过logcat日志,或日志方式查看错误信息位置

你可能感兴趣的:(Android-NDK)