近期在做智能语音识别的项目,由于涉及到NDK的开发,而之前并没有没有NDK crash log的分析经验,这次积累了一些,分享给大家。
具体的环境搭建想必大家也都知道,详细的配置大家可以问下度娘,这里以我的开发环境来讲下,Eclipse+SDK+NDK(android-ndk-r9d)。
这里把NDK的编译配置也讲一下,以免有人走弯路。
1、打开配置面板。项目右键 -> Properties
2、新建编译器。Builders -> New… -> Program
Tab菜单 -> Main ->
Browse File System… 选择ndk目录下ndk-build.cmd文件
Browse Workspace… 选择需要编译的项目
Tab菜单 -> Refresh -> 勾选Refresh resources upon completion.
Tab菜单 -> Build Options ->
勾选During Auto builds
勾选Specify working set of relevant resources
点击Specify Resources… 选择需要编译的项目下的jni目录
到此,NDK编译配置就完成了,现在就可以编译你的NDK了。
在编译SO成功时,大家有没有注意到在项目根目录下,有个obj目录,这里存放的都是此次编译的中间文件,虽然不会编译进APK里,但调试时会用到。
一切都是准备工作,真正分析Crash log才刚刚开始,下边就以我在实际当中遇到的一个log为例。包名和SO名称以及经过处理,可以忽略。
pid: 22258, tid: 2156 >>> com.package <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000014
r0 68ef9718 r1 00000018 r2 00000014 r3 00000000
r4 00000200 r5 6d35b008 r6 00000019 r7 00000003
r8 7587dc78 r9 6ad3bf18 10 7a6fa568 fp 7587dc8c
ip 00000000 sp 7587db88 lr 6ad1241d pc 6ad1248c cpsr 20000030
#00 pc 0001248c /data/data/com.package/lib/libXXXSpeechSDK.so
#01 pc 000134ca /data/data/com.package/lib/libXXXSpeechSDK.so
#02 pc 00010e32 /data/data/com.package/lib/libXXXSpeechSDK.so
#03 pc 00012b5a /data/data/com.package/lib/libXXXSpeechSDK.so
#04 pc 00012c4e /data/data/com.package/lib/libXXXSpeechSDK.so
#05 pc 0001370e /data/data/com.package/lib/libXXXSpeechSDK.so
#06 pc 0001fb70 /system/lib/libdvm.so
#07 pc 0004e8ba /system/lib/libdvm.so
#08 pc 00029020 /system/lib/libdvm.so
#09 pc 0002d7e8 /system/lib/libdvm.so
#10 pc 0005ff32 /system/lib/libdvm.so
#11 pc 0005ff5a /system/lib/libdvm.so
#12 pc 0005535a /system/lib/libdvm.so
#13 pc 00012ff0 /system/lib/libc.so
#14 pc 00012748 /system/lib/libc.so
>>> [translate by crash parser] <<<
#00 pc 0001248c /data/data/com.package/lib/libXXXSpeechSDK.so
#01 pc 000134ca /data/data/com.package/lib/libXXXSpeechSDK.so
#02 pc 00010e32 /data/data/com.package/lib/libXXXSpeechSDK.so
#03 pc 00012b5a /data/data/com.package/lib/libXXXSpeechSDK.so
#04 pc 00012c4e /data/data/com.package/lib/libXXXSpeechSDK.so
#05 pc 0001370e /data/data/com.package/lib/libXXXSpeechSDK.so
#06 pc 0001fb70 /system/lib/libdvm.so
#07 pc 0004e8ba /system/lib/libdvm.so
#08 pc 00029020 /system/lib/libdvm.so
#09 pc 0002d7e8 /system/lib/libdvm.so
#10 pc 0005ff32 /system/lib/libdvm.so
#11 pc 0005ff5a /system/lib/libdvm.so
#12 pc 0005535a /system/lib/libdvm.so
#13 pc 00012ff0 /system/lib/libc.so
#14 pc 00012748 /system/lib/libc.so
>>> [Dalvik stack info] <<<
code around pc:
6ad1246c: 310150c2 3304692c 42a16ae8 f7ffddf8 .P.1,i.3.j.B....
6ad1247c: 696ffd59 e04f00f9 99026aeb 3a04185a Y.oi..O..j..Z..:
6ad1248c: 9a026811 589c1c08 2b006b2b f00cd00b .h.....X+k.+....
6ad1249c: 1c21eb4e 1c201c06 eb48f00c 1c301c01 N.!... ...H...0.
6ad124ac: ea22f00c f00ce010 1c21eb42 1c201c06 ..".....B.!... .
code around lr:
6ad123fc: eecef00b 1c049e08 68b01c0d eec8f00b ...........h....
6ad1240c: 1c0b1c02 1c291c20 ed46f00b ea16f00c .... .)...F.....
6ad1241c: b0252300 60b36070 46c0bdf0 00000000 .#%.p`.`...F....
6ad1242c: 3fe00000 b087b5f0 31049104 91011c15 ...?.......1....
6ad1243c: 23011c0a e0012100 3301c202 42a368ac ...#.!.....3.h.B
stack:
7587db48: f7a3667e 3f992155 60000000 c07249a2
7587db58: 68ef9b2c 00000800 00000080 00000000
7587db68: 00000080 000001ff 00000190 00000200
7587db78: 6d35b008 00000019 e3a070ad ef9000ad
7587db88: 65e677ed 691b8444 00000018 6ad11f2b #sp
7587db98: 691b8440 68d64898 00000190 6d35b008
7587dba8: 68d64898 00000019 740efb60 6ad134cf
7587dbb8: 00000001 691b8440 00000000 00000003
7587dbc8: 00000190 0000001a 00000016 721c9e78
7587dbd8: 00000001 7217f720 0000000e 686cf3c8
7587dbe8: 00003e80 6ad10e37 686cf3c8 77ab0308
7587dbf8: 6ad10e1f 68ce5d90 7587dc5c 6ad12b5d
7587dc08: 0000000e 68ce5d90 7587dc58 6ad12c53
7587dc18: 7587dc34 436e0550 00003e80 00003e7f
7587dc28: 77aae008 0000f9fc 6ad2a820 6ad12ba1
7587dc38: 6ad22e0d 00000000 00003e80 6ad13711
7587dc48: 7587dc58 00000000 41317578 436d8850
7587dc58: 00000000 00000000 436d8840 62cf59d0
7587dc68: 7a6fa558 00000004 6ad3bf20 41288b74
7587dc78: 6ad3bf14 00000001 42a2fd68 6aee02d1
7587dc88: 00000000 412b78bd 6ad3bf14 6aee02ce
7587dc98: 6ad136a9 7a6fa568 00000000 00000000
7587dca8: 00000001 401dca6c 42dc8c00 42dc8c00
7587dcb8: 00000001 42128018 43585e88 43585e88
7587dcc8: 7a6fa8c4 43585e88 00000003 7a6fa558
7587dcd8: 0000004c 43585e88 00000000 412be98d
7587dce8: 7587dd54 626cc9dc 00000001 4160c6c0
7587dcf8: 00000001 42128018 439d7af0 439d7af0
7587dd08: 42128018 00010fce 00000001 4022766b
7587dd18: 4008f008 413192c0 439d7af0 412d75b5
7587dd28: 413178e8 41317578 00010fce 00000000
7587dd38: 41317578 41295338 7587dd54 f79ebef4
7587dd48: 7587dd54 415a87d8 00010fbe 00000000
7587dd58: 401dca6c 412d0625 42a5d97c 6ad3beec
7587dd68: 1dcd64ff 412bc109 7a6fa558 f79ebef4
7587dd78: 00000001 6aede5b8 6ad3bf34 7a6fa558
7587dd88: 42d09e40 41288d00 00000000 6ad3bf00
7587dd98: 00000000 41292024 00000000 7a6fa558
7587dda8: 41311c5c 627d2628 00000000 7587ddd4
7587ddb8: 7587deb0 00000000 00000000 412967ec
7587ddc8: 00000000 00000000 00000000 00000000
7587ddd8: 6ad3bfe4 00000000 00000000 00000000
7587dde8: 00000000 00000000 00000000 00000000
7587ddf8: 00000000 00000000 00000000 44340000
7587de08: 44a00000 42400000 00000000 00000000
7587de18: 42400000 42400000 3f7ff797 3f000000
7587de28: 3f7ff797 e5caa992 fbfbfbfb fbfbfbfb
7587de38: 7a6fa558 627d2628 7587dea8 427c4008
7587de48: 6ad3bfec 642a5a18 7587deb0 412c8f35
7587de58: 7a6fa558 627d2628 427c4008 7587deb0
7587de68: 412f9b22 401dca6c 627d2628 41317874
7587de78: 00100000 7a6fa558 00000001 412c8f5f
7587de88: 7587deb0 7587dea8 7a6fa558 7587dea8
7587de98: 401dca6c 7a6fa558 412be35f 7587deb0
7587dea8: 71e89d98 00000000 00000000 00000000
7587deb8: 00000000 71e89db0 00000000 00000000
7587dec8: 00000000 71e89dad 71e89d98 f79ebef4
7587ded8: 7587df00 412be289 7a6fa558 00000078
7587dee8: 412be289 4019eff4 6efd71d0 7587df00
7587def8: bef75738 4019e74c 7587df00 6efd71d0
7587df08: 00000016 00000000 00000000 00000000
7587df18: 7a6fa558 00000000 00000000 00000000
7587df28: 00000000 6b93e260 687f6e20 00000000
7587df38: 00000000 00000000 00000000 00000000
7587df48: 00000000 00000000 00000000 00000000
7587df58: 00000000 00000000 00000000 00000000
7587df68: 00000000 00000000 00000000 00000000
7587df78: 00000000 00000000 00000000 00000000
7587df88: 00000000 00000000 00000000 00000000
7587df98: 00000000 00000000 00000000 00000000
7587dfa8: 00000000 00000000 00000000 00000000
7587dfb8: 00000000 00000000 00000000 00000000
7587dfc8: 00000000 00000000 00000000 00000000
7587dfd8: 00000000 00000000 00000000 00000000
7587dfe8: 00000000 00000000 00000000 00000000
print call stack finish!
获取log的方式不用计较,这是我们对系统log进行过特殊处理获取的。
开发中获取log可以使用
adb logcat -c && adb logcat > D://crash.log
如果想加过滤可以过滤器
Linux adb logcat -c && adb logcat | find "过滤词" > D://crash.log
Windows adb logcat -c && adb logcat | grep "过滤词" > D://crash.log
libdvm.so是Java层的堆栈关系,可以不用管,本文只分析此次NDK开发的log。
在上述log里,真实的Crash是在这里signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000014
寄存器的位置是00000014,这是个野指针,在log里有指明内存栈的调用,“sp 7587db88”是指从寄存器7587db88开始的,在之后的log里也有输出“7587db88: 65e677ed 691b8444 00000018 6ad11f2b #sp”
我们通过ndk-stack可以把这段log转化成NDK的调用堆栈,注意这里使用的是中间文件下的armeabi目录
D:\WorkStation\install\adt-bundle-windows-x86_64-20140702\android-ndk-r9d>ndk-st
ack -sym E:\WorkPlace\项目\obj\local\armeabi -dum
p 转换前日志文件 > 转换后的日志文件
这时候的日志就输出成堆栈的调用情况
********** Crash dump: **********
Build fingerprint: 'Xiaomi/aries/aries:4.1.1/JRO03L/JLB52.0:user/release-keys'
pid: 22258, tid: 2156 >>> com.package <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000014
Stack frame #00 pc 0001248c /data/data/com.package/lib/libxxxSpeechSDK.so: Routine Realft(float*) at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/signal_process.cpp:452
Stack frame #01 pc 000134ca /data/data/com.package/lib/libxxxSpeechSDK.so: Routine qn_sigmoid_vf_vf at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/QN_fltvec.h:179
Stack frame #02 pc 00010e32 /data/data/com.package/lib/libxxxSpeechSDK.so: Routine ~CMVNFeatureTranslator at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/feature_translate.cpp:243
Stack frame #03 pc 00012b5a /data/data/com.package/lib/libxxxSpeechSDK.so: Routine Vader::Init(char*, char*, char*) at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/vad.cpp:37
Stack frame #04 pc 00012c4e /data/data/com.package/lib/libxxxSpeechSDK.so: Routine ~Vader at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/vad.cpp:84
Stack frame #05 pc 0001370e /data/data/com.package/lib/libxxxSpeechSDK.so: Routine KillFE(FeOption*) at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/wav2feat.cpp:115
Stack frame #06 pc 0001fb70 /system/lib/libdvm.so
Stack frame #07 pc 0004e8ba /system/lib/libdvm.so
Stack frame #08 pc 00029020 /system/lib/libdvm.so
Stack frame #09 pc 0002d7e8 /system/lib/libdvm.so
Stack frame #10 pc 0005ff32 /system/lib/libdvm.so
Stack frame #11 pc 0005ff5a /system/lib/libdvm.so
Stack frame #12 pc 0005535a /system/lib/libdvm.so
Stack frame #13 pc 00012ff0 /system/lib/libc.so
Stack frame #14 pc 00012748 /system/lib/libc.so
这个时候就可以根据堆栈分析问题原因了,如果还不够详细,还可以使用arm-linux-androideabi-objdump反编译分析具体哪个指针有问题。
D:\WorkStation\install\adt-bundle-windows-x86_64-20140702\android-ndk-r9d\toolch
ains\arm-linux-androideabi-4.8\prebuilt\windows-x86_64\bin>arm-linux-androideabi
-objdump.exe -DSl E:\WorkPlace\xxxSpeech\xxxVoiceRecognition\obj\local\a
rmeabi\libxxxSpeechSDK.so > D://core.txt
就可以查看各个文件里每个方法的指针位置,再根据寄存器位置,找到具体有问题的指针。
E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/signal_process.cpp:442
s[i1] = xr1 + wrs * xr2 - wis * xi2;
12330: 00000014 andeq r0, r0, r4, lsl r0
12334: 14510001 ldrbne r0, [r1], #-1
12338: 30000000 andcc r0, r0, r0
1233c: 01000000 mrseq r0, (UNDEF: 0)
12340: 00305000 eorseq r5, r0, r0
12344: 01140000 tsteq r4, r0
12348: 00020000 andeq r0, r2, r0
1234c: 00006091 muleq r0, r1, r0
12350: 00000000 andeq r0, r0, r0
12354: 00020000 andeq r0, r2, r0
12358: 00180000 andseq r0, r8, r0
1235c: 00010000 andeq r0, r1, r0
12360: 00001852 andeq r1, r0, r2, asr r8
12364: 00009c00 andeq r9, r0, r0, lsl #24