一. 简述
之前有一篇文章讲诉了Android实际开发过程中一些崩溃的原因,以及对崩溃类型做了详细的介绍,简单回顾一下:Crash类型:Java和Native,JavaCrash中明显会打印出AndroidRuntime的log,而NativeCrash则Logcat 会在“debug”tag下输出dump信息,开发过程中javacrash较好分析,NativeCrash则相对较难,
二. NativeCrash
错误信号:11是信号量sigNum,SIGSEGV是信号的名字,SEGV_MAPERR是SIGSEGV下的一种类型。
寄存器快照:进程收到错误信号时保存下来的寄存器快照,其中PC寄存器存储的就是下个要运行的指令(出错的位置)。
调用栈:#00是栈顶,#02是栈底,#02调用#01调用#00方法,#00的方法时libspirit.so中的Spirit类下的testCrash方法,出错的地方是testCrash方法内汇编偏移17(不是行号哦!)
直接上一个问题。
问题描述:
使用CTS7.1.2R7包测试:run cts -m CtsSecurityTestCases -tandroid.security.cts.StagefrightTest#testStagefright_bug_35763994,
--------- beginning ofcrash
F libc : Fatal signal 8 (SIGFPE), code -6, faultaddr 0x3292 in tid 12963 (pool-1-thread-1)
I chatty : uid=0(root) /system/bin/debuggerd expire 16lines
F DEBUG : *** *** *** *** *** *** *** *** *** ****** *** *** *** *** ***
F DEBUG : Build fingerprint:'Turing/70821C/appassionato:7.1.2/N2G47H/v6H1N-0:user/release-keys'
F DEBUG : Revision: '0'
F DEBUG : ABI: 'arm'
F DEBUG : pid: 12946, tid: 12963, name:pool-1-thread-1 >>>android.security.cts <<<
F DEBUG : signal 8 (SIGFPE), code -6 (SI_TKILL),fault addr 0x3292
F DEBUG : r0 00000000 r1 000032a3 r2 00000008 r3 00000000
F DEBUG : r4 d37f6978 r5 00000008 r6 d37f6920 r7 0000010c
F DEBUG : r8 d37f3e20 r9 e5910c00 sl e5910c8c fp d37f3b6c
F DEBUG : ip 00000000 sp d37f3a68 lr ef34a537 pc ef34cdb8 cpsr 000d0010
I chatty : uid=1001(radio) com.android.phone expire 61lines
F DEBUG :
F DEBUG : backtrace:
F DEBUG : #00 pc 00049db8 /system/lib/libc.so (tgkill+12)
F DEBUG : #01 pc 00047533 /system/lib/libc.so (pthread_kill+34)
F DEBUG : #02 pc 0001d785 /system/lib/libc.so (raise+10)
F DEBUG : #03 pc 00012c08 /system/lib/libcutils.so (__aeabi_idiv0+8)
F DEBUG : #04 pc 000df1bb /system/lib/libstagefright.so(_ZNK7android16NuMediaExtractor17getCachedDurationEPxPb+214)
F DEBUG : #05 pc 00029bbf /system/lib/libmedia_jni.so
F DEBUG : #06 pc 01adf4e9 /system/framework/arm/boot-framework.oat (offset 0x164e000)(android.media.MediaExtractor.getCachedDuration+76)
F DEBUG : #07 pc 000a99c1 /system/lib/libart.so (art_quick_invoke_stub_internal+64)
F DEBUG : #08 pc 004052f1 /system/lib/libart.so (art_quick_invoke_stub+232)
F DEBUG : #09 pc 000b0c55 /system/lib/libart.so(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+136)
F DEBUG : #10 pc 001ed0d5 /system/lib/libart.so(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPKNS_7DexFile8CodeItemEPNS_11ShadowFrameEPNS_6JValueE+200)
…………………………………
I am_crash: [1433,0,android.security.cts,948485700,Nativecrash,Floating point exception,unknown,0]
咋一看,其实什么也发现不了,一大坨。其实这就是C里面的堆栈。要看这里的堆栈信息就要使用到源码环境里的addr2line这个工具
工具目录:prebuilts/tools/gcc-sdk,
使用实例:
addr2line -fe libstagefright “/out/target/product/appassionato/symbols/system/lib/libstagefright.so” 000df22b
当使用完上述命令,便会输出详细的代码出错位置:
_ZNK7android16NuMediaExtractor17getCachedDurationEPxPb
/proc/self/cwd/frameworks/av/media/libstagefright/NuMediaExtractor.cpp:650
输出信息指示我们出错位置在NuMediaExtractor.cpp:650,好找到相关代码:
oolNuMediaExtractor::getCachedDuration(
int64_t *durationUs, bool *eos) const {
Mutex::Autolock autoLock(mLock);
int64_t bitrate;
if (mIsWidevineExtractor) {
sp
static_cast
status_t finalStatus;
*durationUs =wvmExtractor->getCachedDurationUs(&finalStatus);
*eos = (finalStatus != OK);
return true;
} else if ((mDataSource->flags() &DataSource::kIsCachingDataSource)
&&getTotalBitrate(&bitrate)) {
sp
static_cast
status_t finalStatus;
size_t cachedDataRemaining =
cachedSource->approxDataRemaining(&finalStatus);
*durationUs = cachedDataRemaining * 8000000ll/ bitrate;
*eos = (finalStatus != OK);
return true;
}
return false;
}
找到出错位置,根据crashlog显示:
libc : Fatal signal 8 (SIGFPE), code -6, faultaddr 0x3292 in tid 12963 (pool-1-thread-1)
I am_crash: [1433,0,android.security.cts,948485700,Nativecrash,Floating point exception,unknown,0]
我们大致可定位问题在算数时bitrate为零,crash了。
因此修改如下:
diff --gita/media/libstagefright/NuMediaExtractor.cppb/media/libstagefright/NuMediaExtractor.cpp
index 4558b3c..8d80c4a100644
---a/media/libstagefright/NuMediaExtractor.cpp
+++b/media/libstagefright/NuMediaExtractor.cpp
@@ -612,7 +612,7 @@status_t NuMediaExtractor::getSampleMeta(sp
}
bool NuMediaExtractor::getTotalBitrate(int64_t*bitrate) const {
- if (mTotalBitrate >= 0) {
+ if (mTotalBitrate > 0) {
*bitrate = mTotalBitrate;
return true;
}
重新测试CTS,PASS