在Android开发的过程中,有时候需要创建一个纯linux的应用程序,当这些程序crash时,如果找不到导致crash的直接原因,问题将很难被修复。本文将介绍一种分析crash问题的方法。
1)以下是crash时串口的打印信息:
pid: 96, tid: 798, name: Playback >>> /system/bin/dvb <<<
I/DEBUG ( 80): signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr 00000000
I/DEBUG ( 80): Abort message: 'heap corruption detected by dlfree'
W/NativeCrashListener( 428): Couldn't find ProcessRecord for pid 96
I/DEBUG ( 80): r0 00000000 r1 0000031e r2 00000006 r3 00000000
I/DEBUG ( 80): AM write failure (32 / Broken pipe)
I/DEBUG ( 80): r4 00000006 r5 00000016 r6 0000031e r7 0000010c
I/DEBUG ( 80): r8 000001b8 r9 00000000 sl 000001b8 fp 427dfcc8
I/DEBUG ( 80): ip 000000bd sp 4ad52c30 lr 41135075 pc 41144020 cpsr 080f0010
I/DEBUG ( 80): d0 6465746372666c64 d1 206e6f6974707572
I/DEBUG ( 80): d2 0000000000000000 d3 0000000000000000
I/DEBUG ( 80): d4 3fe0000000000000 d5 3fd19b5cefffd79a
I/DEBUG ( 80): d6 0000bb8031000000 d7 000000003f800000
I/DEBUG ( 80): d8 0000000000000000 d9 0000000000000000
I/DEBUG ( 80): d10 0000000000000000 d11 0000000000000000
I/DEBUG ( 80): d12 0000000000000000 d13 0000000000000000
I/DEBUG ( 80): d14 0000000000000000 d15 0000000000000000
I/DEBUG ( 80): d16 8000000000000000 d17 0000000000000000
I/DEBUG ( 80): d18 ffffffffffffffff d19 0000000000000000
I/DEBUG ( 80): d20 be926aa2f81b5123 d21 bf56882f94edacc2
I/DEBUG ( 80): d22 3e21e0e0299e8cc5 d23 3ff0000000000000
I/DEBUG ( 80): d24 3fe7325188001433 d25 3fd19b5cefffd79a
I/DEBUG ( 80): d26 0000000000000000 d27 3f895d470d6e9486
I/DEBUG ( 80): d28 3fe797c6a435ce85 d29 3e8f20d95f29baf8
I/DEBUG ( 80): d30 bef375cbdb605373 d31 3fe7bc89cf9e1300
I/DEBUG ( 80): scr 60000010
I/DEBUG ( 80):
I/DEBUG ( 80): backtrace:
I/DEBUG ( 80): #00 pc 00022020 /system/lib/libc.so (tgkill+12)
I/DEBUG ( 80): #01 pc 00013071 /system/lib/libc.so (pthread_kill+48)
I/DEBUG ( 80): #02 pc 00013285 /system/lib/libc.so (raise+10)
I/DEBUG ( 80): #03 pc 00011fbb /system/lib/libc.so
I/DEBUG ( 80): #04 pc 000218d4 /system/lib/libc.so (abort+4)
I/DEBUG ( 80): #05 pc 00012aa1 /system/lib/libc.so
I/DEBUG ( 80): #06 pc 0000f1ad /system/lib/libc.so
I/DEBUG ( 80): #07 pc 0001177b /system/lib/libc.so (dlfree+1222)
I/DEBUG ( 80): #08 pc 0000dcc3 /system/lib/libc.so (free+10)
I/DEBUG ( 80): #09 pc 0004a0e7 /system/lib/libmcp.so (mespSkip+172)
I/DEBUG ( 80): #10 pc 00026987 /system/lib/libmcp.so
I/DEBUG ( 80): #11 pc 000a58bd /system/lib/libmcp.so
I/DEBUG ( 80): #12 pc 0000d228 /system/lib/libc.so (__thread_entry+72)
I/DEBUG ( 80): #13 pc 0000d3c0 /system/lib/libc.so (pthread_create+240)
I/DEBUG ( 80):
I/DEBUG ( 80): stack:
I/DEBUG ( 80): 4ad52bf0 03df4597
I/DEBUG ( 80): 4ad52bf4 00000000
I/DEBUG ( 80): 4ad52bf8 00000000
I/DEBUG ( 80): 4ad52bfc 80000000
I/DEBUG ( 80): 4ad52c00 00000000
I/DEBUG ( 80): 4ad52c04 00000000
I/DEBUG ( 80): 4ad52c08 00000000
I/DEBUG ( 80): 4ad52c0c 00000000
I/DEBUG ( 80): 4ad52c10 00000000
I/DEBUG ( 80): 4ad52c14 00000000
I/DEBUG ( 80): 4ad52c18 03df44d7
I/DEBUG ( 80): 4ad52c1c 00000000
I/DEBUG ( 80): 4ad52c20 41341bad /system/lib/libmcp.so
I/DEBUG ( 80): 4ad52c24 00000000
I/DEBUG ( 80): 4ad52c28 42a99a20 [heap]
I/DEBUG ( 80): 4ad52c2c 42a9dadc [heap]
I/DEBUG ( 80): #00 4ad52c30 00000006
I/DEBUG ( 80): 4ad52c34 00000016
I/DEBUG ( 80): 4ad52c38 0000031e
I/DEBUG ( 80): 4ad52c3c 000000bd
I/DEBUG ( 80): 4ad52c40 000000bd
I/DEBUG ( 80): 4ad52c44 41135075 /system/lib/libc.so (pthread_kill+52)
I/DEBUG ( 80): #01 4ad52c48 00000006
I/DEBUG ( 80): 4ad52c4c 00000000
I/DEBUG ( 80): 4ad52c50 a35aaaaf
I/DEBUG ( 80): 4ad52c54 41135289 /system/lib/libc.so (raise+14)
I/DEBUG ( 80): #02 4ad52c58 4ad52c64
I/DEBUG ( 80): 4ad52c5c 41133fbf /system/lib/libc.so
I/DEBUG ( 80):
I/DEBUG ( 80): memory near fp:
I/DEBUG ( 80): 427dfca8 00000000 00000000 00000000 00000039
I/DEBUG ( 80): 427dfcb8 ffffffff 00000000 00000048 0000004b
I/DEBUG ( 80): 427dfcc8 495a6318 00000160 00000000 00000000
I/DEBUG ( 80): 427dfcd8 00000000 00000000 04b8b5d4 00000000
I/DEBUG ( 80): 427dfce8 00000000 00000000 00000000 00000000
I/DEBUG ( 80): 427dfcf8 00000000 00000039 ffffffff 42203a98
I/DEBUG ( 80): 427dfd08 00000048 0000015b 427dfd08 427dfd08
2) crash时,请注意 bracktrace 后面的打印信息就是crash时代码的位置,第29行 00022020就是最后一次crash的位置,可以使用objdump命令反编译出源代码以便查找导致crash的源代码位置,objdump命令取决于所使用的toolchain(下面是一种linux环境下反编译的命令情况)。
./prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-objdump -S out/dvb > dvb_map.txt
3)成功生成dvb_map.txt之后,打开该文件
if( dTempRet == SFS_FILE_TRUE )
{
//diag_printf("[Rd] copy file data to RAM\n");
dTempRet = SFS_ReadFileFull(dFile, pSect->sect_ram_anchor, pSect->sect_ram_size, &dErrNo);
if(dTempRet != SFS_FILE_SUCCESS)
2200e: b117 cbz r7, 22016 <NVM_Init_Section_DMem+0x66>
{
close(dFile);
22010: f7e7 ef18 blx 9e44 <close@plt>
22014: e00e b.n 22034 <NVM_Init_Section_DMem+0x84>
dRet = NVM_FAIL;
goto nvm_init_sect_dmem_fail;
}
close(dFile);
22016: f7e7 ef16 blx 9e44 <close@plt>
if(u8NvmCreateFile){//BRAD: to indicate that system setting file is created
2201a: 4912 ldr r1, [pc, #72] ; (22064 <NVM_Init_Section_DMem+0xb4>)
2201c: 4479 add r1, pc
2201e: 780c ldrb r4, [r1, #0]
22020: b194 cbz r4, 22048 <NVM_Init_Section_DMem+0x98>
dRet = NVM_WARN_FLASH_EMPTY;
u8NvmCreateFile = 0;
22022: 700f strb r7, [r1, #0]
}
close(dFile);
if(u8NvmCreateFile){//BRAD: to indicate that system setting file is created
dRet = NVM_WARN_FLASH_EMPTY;
22024: 2402 movs r4, #2
22026: e00f b.n 22048 <NVM_Init_Section_DMem+0x98>
pSect = (FLASH_SECTION_STRUCT *)get_sect_object(sect_id);
//Check Layout
对比源代码就可以找到原因(本例是因为操作了空指针所致)
4)某些情况下查看具体的crash时会比较困难,这个时候可以借用addr2line命令将crash源代码具体文件和行数印出来(同样,此命令不同的toolchain会有所差别)。
prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-addr2line -f -e out/dvb 22020
输入命令后会打印出类似下面的语句:
../libs/dvb_db/rw_nvmem.c:791