Coredump简介及使用... 1
目录... 2
一、什么是Coredump. 3
二、Coredump产生的原因... 3
三、如何控制产生Coredump. 4
四、使用Coredump的准备... 4
五、开始使用Coredump. 5
有些C/C++程序或者通过JNI调用了C/C++的APK程序可以通过编译, 但在运行时会出现错误,比如常见的signal 11 (SIGSEGV),这样的程序都是可以通过编译的,而且这样的错误一般情况下不会像编译错误一样告诉你具体在代码的那一行有问题,所以调试起来比较困难和麻烦。
因为上面的这种debug困难的情况,所以就产生了coredump这种机制(很多操作系统都支持这种机制,并不是Linux独有,也不是专门为Android而生),系统(或者标准库)在发现程序错误的异常退出时,就会把程序当时整个进程的状态dump 出来,生成一个coredump文件,通常情况下coredump包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息等,可以理解为把程序工作的当前状态存储成一个文件,很幸运,我们现在使用Android系统是基于Linux内核,Linux内核原生就支持这种机制。
造成程序coredump的原因很多,这里根据以往的经验总结一下:
1、 内存访问越界
a) 由于使用错误的下标,导致数组访问越界
b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符
c) 使用strcpy,strcat, sprintf, strcmp, strcasecmp等字符串操作函数,将目标字符串读/写爆。应该使用strncpy,strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。
2、 多线程程序使用了线程不安全的函数
第1类:不保护共享变量的函数
第2类:保持跨越多个调用的状态函数
第3类:返回指向静态变量指针的函数
第4类:调用线程不安全函数的函数
3、 多线程读写的数据未加锁保护
一个线程做完条件判断准备使用时发生了调度,另外一个线程将其释放并置空或者修改了内容,就会导致程序执行流错乱,要么指针异常,要么状态错乱发生另外的异常
4、 非法指针
a) 使用空指针
b) 随意使用指针转换。一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型 的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它 时就很容易因为bus error而core dump
c) 使用未初始化或者已经释放或者状态不明的野指针
5、 堆栈溢出
不要使用大的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误
直接修改init.rc(system/core/rootdir)文件,在setrlimit13 40 40后面添加:
setrlimit 4 -1 -1
mkdir /data/coredump 0777 system system
write /proc/sys/kernel/core_pattern/data/coredump/core.%e.%p
write /proc/sys/fs/suid_dumpable 1
这些命令的目的是将RLIMIT_CORE的大小修改为unlimited,具体参见:keywords.h中do_setrlimit函数。其中RLIMIT_CORE的定义在Resource.h中。在data目录下创建coredump文件夹,并给系统赋予可读可写权限。改写coredump文件的存储路径。使调用了seteuid()/setegid()的程序能够生成coredump,默认情况下系统不会为这些进程生成Coredump,需要设置suid_dumpable为1。
尽管是做了上面这些动作,但是仍然只能为native程序产生coredump,对于由zygotefork的apk进程则不会生成coredump,因为zygote在做初始化的时候会忽略Linux的配置,使用默认不生成coredump的配置,system server同样是由zygote fork的,所以也不会产生coredump,所以如果出现因为system server的thread crash引起的重启则会非常头疼,需要为system server配置生成coredump,如果其他apk进程需要产生coredump同样需要在开机初始化的时候为zygote做特殊的设置。
所谓的特殊设置就是将zygote的启动参数中应用rlimit的配置,system server也是同样。
通过设置在出问题时产生了coredump,接下来我们就要使用这个coredump为我们分析具体的问题。工欲善其事必先利其器,我们首先要准备好解析coredump的环境和工具。
1、GDB,由于我们是分析嵌入式Linux内核下的产生的coredump,所以我们需要专门的交叉编译工具链中的arm-linux-androideabi-gdb,大概位置:
prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb
2、有了GDB还不够,我们需要更加人性化、简单易操作的图形化工具—Eclipse+CDT来查看coredump
如何获得:
a、Eclipse C/C++ IDE for Luna SR2.click to download bundle package.
b、在ADT中更新你的CDT插件,help-》install newsoftware-》type url:http://download.eclipse.org/tools/cdt/releases/8.6
3、准备与coredump版本对应的源代码环境,最好与编译版本时的路径保持一致,以便定位具体的代码
4、准备与coredump版本对应的symbols