一次Android App NDK崩溃问题的分析及解决

文章目录

  • 小结
  • NDK崩溃的问题
    • 通过logcat查看崩溃日志
    • 提取`tombstone`的记录
  • 通过ndk-stack来输出日志
    • 取得的日志
  • 分析并解决
    • 分析
    • 使用add2line定位具体报错的行数
    • 解决
  • 参考

小结

最近碰一次Android App NDK崩溃的问题,这个NE(Native Exception)是从NDK层xxx.so库文件里抛出来的,进行了tombstone的日志分析,定位分析并解决了问题。

NDK崩溃的问题

相比于Java上层的崩溃问题的解决,NDK层xxx.so库文件里抛出异常比较难定位及解决。 最重要的步骤是提取崩溃日志。

通过logcat查看崩溃日志

手机连接电脑,可以在Android Studio里直接查看Logcat的日志:

...(省略)                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
2023-03-07 09:25:45.323 29167-29167 DEBUG                   pid-29167                            A  pid: 26758, tid: 26758, name: .aa.bb.cc.dd  >>> sg.aa.bb.cc.dd <<<
2023-03-07 09:25:45.329 29167-29167 DEBUG                   pid-29167                            A        #03 pc 00000000001199e0  /data/app/~~RW3C1fUQ0X24VpdWWeRdqg==/sg.aa.bb.cc.dd-4IaZ9lJY132Qxf-Jxajm3w==/base.apk!libJni.so (offset 0xa57000) (BuildId: 4cf43bec77672ebce12c16cca6693b03939d28da)
2023-03-07 09:25:45.329 29167-29167 DEBUG                   pid-29167                            A        #04 pc 00000000001197c8  /data/app/~~RW3C1fUQ0X24VpdWWeRdqg==/sg.aa.bb.cc.dd-4IaZ9lJY132Qxf-Jxajm3w==/base.apk!libJni.so (offset 0xa57000) (CSystem::aaaaa(char*, char*)+972) (BuildId: 4cf43bec77672ebce12c16cca6693b03939d28da)
2023-03-07 09:25:45.329 29167-29167 DEBUG                   pid-29167                            A        #05 pc 0000000000091b1c  /data/app/~~RW3C1fUQ0X24VpdWWeRdqg==/sg.aa.bb.cc.dd-4IaZ9lJY132Qxf-Jxajm3w==/base.apk!libJni.so (offset 0xa57000) (Java_aa.bb.cc.dd_jniqta_Process+2124) (BuildId: 4cf43bec77672ebce12c16cca6693b03939d28da)
2023-03-07 09:25:45.329 29167-29167 DEBUG                   pid-29167                            A        #06 pc 0000000000070b98  /data/app/~~RW3C1fUQ0X24VpdWWeRdqg==/sg.aa.bb.cc.dd-4IaZ9lJY132Qxf-Jxajm3w==/oat/arm64/base.odex (deleted)
			
...(省略)		

提取tombstone的记录

通过指令adb bugreport提取tombstone的日志。

C:\Users\John\AppData\Local\Android\Sdk\platform-tools>adb bugreport
/data/user_de/0/com.android.shell/files/bugreports/dumpstate-2023-03-10-00-09-22.zip: 1 file pulled, 0 skipped. 26.7 MB/s (10556968 bytes in 0.377s)
Bug report copied to C:\Users\John\AppData\Local\Android\Sdk\platform-tools\dumpstate-2023-03-10-00-09-22.zip

dumpstate-2023-03-10-00-09-22.zip\FS\data\tombstones这个目录下有10个tombstone日志,是在程序崩溃时生成的。

通过ndk-stack来输出日志

以下是通过logcat的输出,再通过ndk-stack来输出崩溃日志。

C:\Users\John\AppData\Local\Android\Sdk\platform-tools>adb shell logcat | C:\Users\John\AppData\Local\Android\Sdk\ndk\25.1.8937393\ndk-stack -sym C:\John_Development\library_jni\debug\jni\arm64-v8a\libJni.so

或者通过ndk-stack来分析tombstone的记录

=================
C:\Users\John\AppData\Local\Android\Sdk\platform-tools>C:\Users\John\AppData\Local\Android\Sdk\ndk\25.1.8937393\ndk-stack -sym C:\John_Development\library_jni\debug\jni\arm64-v8a\libJni.so -dump C:\John_Development\tombstone_00
********** Crash dump: **********
...(省略)

取得的日志

以下是取得的日志,但是不管是哪种办法取得的崩溃日志,都不能具体到程序的导致崩溃的那一行。

查看日志,SIGABRT (6) 是指通过c函数abort()发送,为assert()使用。日志中有一个关键字比较重要:
Abort message: 'FORTIFY: vsprintf: prevented 173-byte write into 30-byte buffer'

似乎是写入某一段内存里写入到边界外了,173个字节要写入一个30个字节的缓存区。

...(省略)
2023-03-09 23:20:22.958  6426-6426  ScrollView              pid-6426                             D  initGoToTop
2023-03-09 23:20:22.987  6426-6426  libc                    pid-6426                             A  FORTIFY: vsprintf: prevented 173-byte write into 30-byte buffer
2023-03-09 23:20:22.988  6426-6426  libc                    pid-6426                             A  Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 6426 (.aa.bb.cc.dd), pid 6426 (.aa.bb.cc.dd)
2023-03-09 23:20:23.051  4172-4227  SensorManager           pid-4172                             D  TYPE_LIGHT (5): 9.000000
2023-03-09 23:20:23.061  7176-7176  crash_dump64            pid-7176                             I  obtaining output fd from tombstoned, type: kDebuggerdTombstone
2023-03-09 23:20:23.062  3708-3708  tombstoned              pid-3708                             I  received crash request for pid 6426
2023-03-09 23:20:23.064  7176-7176  crash_dump64            pid-7176                             I  performing dump of process 6426 (target tid = 6426)
2023-03-09 23:20:23.076  7176-7176  DEBUG                   pid-7176                             A  *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2023-03-09 23:20:23.076  7176-7176  DEBUG                   pid-7176                             A  Build fingerprint: 'samsung/aaa/aaa:11/RP1A.200720.012/aaa:user/release-keys'
2023-03-09 23:20:23.076  7176-7176  DEBUG                   pid-7176                             A  Revision: '2'
2023-03-09 23:20:23.076  7176-7176  DEBUG                   pid-7176                             A  ABI: 'arm64'
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A  Timestamp: 2023-03-09 23:20:23+0800
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A  pid: 6426, tid: 6426, name: .aa.bb.cc.dd  >>> sg.aa.bb.cc.dd <<<
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A  uid: 10270
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A  signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A  Abort message: 'FORTIFY: vsprintf: prevented 173-byte write into 30-byte buffer'
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A      x0  0000000000000000  x1  000000000000191a  x2  0000000000000006  x3  0000007fd3050530
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A      x4  0000000000000000  x5  0000000000000000  x6  0000000000000000  x7  0000000000000040
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A      x8  00000000000000f0  x9  6105dba6615d8073  x10 0000000000000000  x11 ffffffc0fffffbdf
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A      x12 0000000000000001  x13 000000006409f936  x14 003a9ebdec035bec  x15 00004092cc9cc37a
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A      x16 00000070e064e948  x17 00000070e062d2d0  x18 00000070e1fee000  x19 000000000000191a
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A      x20 000000000000191a  x21 00000000ffffffff  x22 00000070e1584000  x23 0000006fc04a3000
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A      x24 00000000a88031a0  x25 00000070e1584000  x26 0000000000000069  x27 0000000000000002
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A      x28 0000000000000000  x29 0000007fd30505b0
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A      lr  00000070e05e0ca4  sp  0000007fd3050510  pc  00000070e05e0cd0  pst 0000000000000000
2023-03-09 23:20:23.251  4172-4227  SensorManager           pid-4172                             D  TYPE_LIGHT (5): 10.000000
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A  backtrace:
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #00 pc 0000000000089cd0  /apex/com.android.runtime/lib64/bionic/libc.so (abort+164) (BuildId: 698b6aef520f034a9d40736d477f7a96)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #01 pc 00000000000b2360  /apex/com.android.runtime/lib64/bionic/libc.so (__fortify_fatal(char const*, ...)+124) (BuildId: 698b6aef520f034a9d40736d477f7a96)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #02 pc 00000000000b2f9c  /apex/com.android.runtime/lib64/bionic/libc.so (__vsprintf_chk+144) (BuildId: 698b6aef520f034a9d40736d477f7a96)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #03 pc 00000000001199e0  /data/app/~~l8Fk9UOg3WqEsbf_8ul2pg==/sg.aa.bb.cc.dd-c3ewrrLy2U1YDGg7VQZPnA==/base.apk!libJni.so (offset 0xa57000) (BuildId: 4cf43bec77672ebce12c16cca6693b03939d28da)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #04 pc 00000000001197c8  /data/app/~~l8Fk9UOg3WqEsbf_8ul2pg==/sg.aa.bb.cc.dd-c3ewrrLy2U1YDGg7VQZPnA==/base.apk!libJni.so (offset 0xa57000) (CSystem::aaaaa(char*, char*)+972) (BuildId: 4cf43bec77672ebce12c16cca6693b03939d28da)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #05 pc 0000000000091b1c  /data/app/~~l8Fk9UOg3WqEsbf_8ul2pg==/sg.aa.bb.cc.dd-c3ewrrLy2U1YDGg7VQZPnA==/base.apk!libJni.so (offset 0xa57000) (Java_aa.bb.cc.dd_jniqta_Process+2124) (BuildId: 4cf43bec77672ebce12c16cca6693b03939d28da)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #06 pc 000000000009cb98  /data/app/~~l8Fk9UOg3WqEsbf_8ul2pg==/sg.aa.bb.cc.dd-c3ewrrLy2U1YDGg7VQZPnA==/oat/arm64/base.odex (art_jni_trampoline+152)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #07 pc 0000000000134564  /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+548) (BuildId: 88f26013f87f4da3613557f39f57fd6a)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #08 pc 00000000001a9a78  /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+200) (BuildId: 88f26013f87f4da3613557f39f57fd6a)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #09 pc 000000000032129c  /apex/com.android.art/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+376) (BuildId: 88f26013f87f4da3613557f39f57fd6a)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #10 pc 00000000003175c8  /apex/com.android.art/lib64/libart.so (bool art::interpreter::DoCall(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+996) (BuildId: 88f26013f87f4da3613557f39f57fd6a)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #11 pc 000000000068cd1c  /apex/com.android.art/lib64/libart.so (MterpInvokeVirtualQuick+672) (BuildId: 88f26013f87f4da3613557f39f57fd6a)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #12 pc 0000000000132594  /apex/com.android.art/lib64/libart.so (mterp_op_invoke_virtual_quick+20) (BuildId: 88f26013f87f4da3613557f39f57fd6a)

...(省略)

分析并解决

分析

注意这三行:

...(省略)
2023-03-09 23:20:22.987  6426-6426  libc                    pid-6426                             A  FORTIFY: vsprintf: prevented 173-byte write into 30-byte buffer
2023-03-09 23:20:22.988  6426-6426  libc                    pid-6426                             A  Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 6426 (.aa.bb.cc.dd), pid 6426 (.aa.bb.cc.dd)
...(省略)
2023-03-09 23:20:23.077  7176-7176  DEBUG                   pid-7176                             A  Abort message: 'FORTIFY: vsprintf: prevented 173-byte write into 30-byte buffer'
...(省略)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #03 pc 00000000001199e0  /data/app/~~l8Fk9UOg3WqEsbf_8ul2pg==/sg.aa.bb.cc.dd-c3ewrrLy2U1YDGg7VQZPnA==/base.apk!libJni.so (offset 0xa57000) (BuildId: 4cf43bec77672ebce12c16cca6693b03939d28da)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #04 pc 00000000001197c8  /data/app/~~l8Fk9UOg3WqEsbf_8ul2pg==/sg.aa.bb.cc.dd-c3ewrrLy2U1YDGg7VQZPnA==/base.apk!libJni.so (offset 0xa57000) (CSystem::aaaaa(char*, char*)+972) (BuildId: 4cf43bec77672ebce12c16cca6693b03939d28da)
2023-03-09 23:20:23.348  7176-7176  DEBUG                   pid-7176                             A        #05 pc 0000000000091b1c  /data/app/~~l8Fk9UOg3WqEsbf_8ul2pg==/sg.aa.bb.cc.dd-c3ewrrLy2U1YDGg7VQZPnA==/base.apk!libJni.so (offset 0xa57000) (Java_aa.bb.cc.dd_jniqta_Process+2124) (BuildId: 4cf43bec77672ebce12c16cca6693b03939d28da)
...(省略)

以上有三个信息,

  • 173个字节要写入一个30个字节的缓存区,写入数据过界。
  • signal 6 (SIGABRT) 信号6发生产生崩溃。
  • 在libJni.so中发生问题,具体位置待定。

使用add2line定位具体报错的行数

以下是通过llvm-addr2line.exe来定位具体出错的是哪一行:

C:\Users\John\AppData\Local\Android\Sdk\platform-tools>C:\Users\John\AppData\Local\Android\Sdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-addr2line.exe -f -C -e C:\John_Development\libJni.so 00000000001199e0
sprintf(char*, char const* pass_object_size1, ...)
C:/Users/John/AppData/Local/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/include/bits/fortify/stdio.h:74

C:\Users\John\AppData\Local\Android\Sdk\platform-tools>C:\Users\John\AppData\Local\Android\Sdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-addr2line.exe -f -C -e C:\John_Development\libJni.so 00000000001197c8
CSystem::aaaaa(char*, char*)
D:/src/aaaaa.cpp:110

C:\Users\John\AppData\Local\Android\Sdk\platform-tools>C:\Users\John\AppData\Local\Android\Sdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-addr2line.exe -f -C -e C:\John_Development\libJni.so 0000000000091b1c
Java_aa.bb.cc.dd_jniqta_Process
D:/src/bbbbb.cpp:468

C:\Users\John\AppData\Local\Android\Sdk\platform-tools>

解决

具体出错的是sprintf(str, "%.2fMB(%.2f%%)", double_a, double_b);这一行,由于sprintf(…)不进行边界检查,写操作溢出边界,173个字节要写入一个30个字节的缓存区, 并导致程序崩溃。使用更为安全的snprintf(…)方法进行格式化,可以解决问题。

参考

CSDN: Android NDK Crash 定位分析
CSDN: Android NativeCrash 捕获与解析
CSDN: 使用 ndk-stack 寻找Android程序Crash的原因
Cnblogs: Android Tombstone 分析
CSDN:导出ANR、tombstones文件 - 无惧Permission denied  
CSDN: 使用addr2line 定位 FORTIFY: vsprintf: prevented write past end of buffer‘ 报错解决思路
CSDN: bug解决-内核C库写保护(FORTIFY: write: prevented read past end of buffer)
知乎: Android NDK Tombstone/Crash 分析
Native crash (Tombstone) in android AOSP

你可能感兴趣的:(Android,Java,android,android,studio,adb)