在平时编码中有时候会遗漏对指针等内存操作的异常保护,而当设备访问异常内存空间时,操作系统会直接杀死改进程。当代码流程较多时,排查这类问题就比较痛苦,索性linux提供了coredump,改文件会保存进程被kill前调用的栈信息,根据这些信息我们可以快速的定位故障点。本文将介绍在openwrt中如果根据coredump来快速定位程序崩溃问题。
编写一个内存使用异常的程序:
编写一个helloworld程序,改程序直接访问空指针,改操作肯定会导致进程崩溃。
开启coredump功能:
openwrt中一般默认没有打开coredump功能,所以我们要先开启改功能,按照下面的配置开启之后,如果进程异常崩溃了,则会在/tmp目录下生成coredump文件。
ulimit -c unlimited
echo "/tmp/core-0.000000e+0--" > /proc/sys/kernel/core_pattern
执行helloworld程序:
从下图可以看出,我们已经生成了coredump文件。
分析coredump文件:
将coredump文件提取出来放到cross_gdb工具的目录(该工具一般都可以在网上下载到)。
因为我们没有使用到动态库,所以我们错误点肯定在helloworld下,所以我们只需要将编译目录中的helloword文件也拷贝到cross_gdb(注意不要直接从设备中导出该文件,因为设备中的app是去掉符号表的,你看不到什么有效的信息)。
打开mips-linux-gnu-gdb.exe,将app文件和core文件分别载入,然后输入bt命令就可以看到进程崩溃前的栈信息了。
导入app命令: file helloworld
导入core文件命令: core-file core-helloworld-2714-1558599983
当故障点在共享库时如何定位:
当故障app包含多个共享库时,我们无法确定到底是哪个共享库出问题,可以先只加载core文件,这时候bt时无法看到具体函数名,我们可以依据该地址去跟系统中该进程的map表进行对比,进而确认到底是哪个共享库出现异常。
如下图所示,红框内是进程号,我们的helloworld程序不会一直执行,所以没办法查看,这边随便找了个其他的程序作为例子。在map表中可以看到每个共享库都有其所在的内存地址范围,根据这个就可以确定是哪个库出现异常了,进而可以objdump该库查看具体的故障内容。