Android系统对于Native(C/C++)应用程序的调试手段比单纯的linux系统coredump文件与gdb结合调试的手段.但是Android系统的天然不支持这种调试方式,其在内核中就没有启用coredump生成机制,那么Android系统下我们使用什么方式调试Native程序的崩溃问题呢?其实,Android系统将系统应用程序产生的崩溃日志都存储到了/data/tombstones目录下,其详细记录了Native应用程序崩溃时进程上下文,通过该文件我们可以知道进程崩溃的原因,崩溃的地点,崩溃线程的函数调用栈,通过这些信息就可轻松的定位到崩溃的具体位置.下面详细的介绍如何通过/data/tombstones目录下的崩溃日志定位到崩溃的位置和原因。
调试步骤
编写用于调试的程序
int main (void) { int *null = 0; *null = 0; return 0; }
编译并将其下载到Android系统
arm-linux-androideabi-gcc coredump.c -o coredump -pie -fPIE -g adb push coredump /data/coredump ./coredump
运行查看崩溃日志
ls /data/tombstones root@firefly:/data/tombstones # ls tombstone_00
上面的代码会触发崩溃,其会在/data/tombstones生成对应的崩溃日志,日志基本信息如下:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** **Build fingerprint: 'Android/rk3288_box/rk3288_box:5.1.1/LMY48W/firefly03111810:userdebug/test-keys' Revision: '0' ABI: 'arm' pid: 2992, tid: 2992, name: coredump >>> ./coredump <<< signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 r0 00000001 r1 bebcc894 r2 00000000 r3 00000000 r4 bebcc894 r5 bebcc89c r6 00000001 r7 b6f5730c r8 00000000 r9 00000000 sl 00000000 fp bebcc85c ip b6f3264c sp bebcc850 lr b6eed39f pc b6f57328 cpsr 60070010 d0 0000000000000000 d1 0000000000000000 d2 0000000000000fff d3 0000b30a0000b30a d4 000000000000b30a d5 0000000000000000 d6 0000000000000000 d7 0000000000000000 d8 0000000000000000 d9 0000000000000000 d10 0000000000000000 d11 0000000000000000 d12 0000000000000000 d13 0000000000000000 d14 0000000000000000 d15 0000000000000000 d16 0000000000000000 d17 0000000000000fff d18 0000000000000000 d19 0000000000000000 d20 0000000000000000 d21 0000000000000000 d22 0000000000000000 d23 0000000000000000 d24 0000000000000000 d25 0000000000000000 d26 0000000000000000 d27 0000000000000000 d28 0000000000000000 d29 0000000000000000 d30 0000000000000000 d31 0000000000000000 scr 00000000 backtrace: #00 pc 00000328 /data/coredump/coredump (main+28) #01 pc 0001239d /system/lib/libc.so (__libc_init+44)**
根据崩溃日志定位崩溃位置
崩溃日志中提供了程序崩溃时的函数调用栈,其详细记录了程序运行时PC(Programer Counter)地址,我么可以根据这些地址,定位程序的崩溃时程序的运行过程.调试崩溃位置,我们需要使用到addr2line函数,该函数将地址信息对应到程序的符号信息,根据符号信息就可以定位到程序代码的具体位置。
lhl@lhl-ubuntu:~/test$ arm-linux-androideabi-addr2line -a 00000328 -e coredump 0x00000328 /home/lhl/test/coredump.c:4
调试信息显示崩溃位置在coredump.c的第4行,对应一下代码,第4行为*null = 0; //访问非法地址0,触发段错误
总结
上面展示了一个完成的Native程序崩溃日志的调试步骤,其中有几点需要注意的地方
编译应用程序时需要制定-g选项,该选项会在应用程序中添加符号信息,而在使用addr2line时需要这些符号信息定位崩溃位置