core dump and gdb

core dump功能

core dump 文件是在程序因严重错误(如段错误)而崩溃时由操作系统生成的一个内存映像文件(支持自定义设置设备文件名格式)。这个文件包含了程序崩溃时刻的内存状态,包括寄存器的状态、栈、全局变量等数据。这对于调试程序(gdb)非常有用,因为它可以帮助开发者理解程序在崩溃前的状态,从而定位和解决问题。

linux系统默认关闭core dump文件的生成,原因是:需要占用一部分系统开销。

  • 查看core dump是否开启

可以通过命令查看是否启动core dump功能:ulimit -c,若打印结果为:0,说明没有启动core dump功能。

可以通过该命令查看详细信息:ulimit -a

  • 开启core dump功能

在当前的shell窗口启用core dump功能,执行:ulimit -c unlimited ,即生成的core文件大小不受限制。如果想限制core文件的大小,可以执行:ulimit -c 1024,即生成的core文件最大限制为1024KB。如果想关闭core dump功能,执行:ulimit -c 0 即可。

注意:shell窗口关闭后,core dump功能失效

  • core dump文件名格式
1
2
3
# 查看core dump文件名格式。%p表示程序ID,%e表示程序文件名
$ cat /proc/sys/kernel/core_pattern
/data/core-%p-%e
  • core dump文件的生成

在使用gcc编译目标程序时,添加参数 -g ,执行目标程序,复现Segment Fault错误,此时在生成了core dump文件 core-2585-g_main_loop_run

gdb调试功能

将core dump文件拷贝至宿主机,用交叉编译链gdb去分析core dump文件。但是执行:./arm-linux-gnueabihf-gdb --help ,报错并提示缺少动态库文件。

查看一下gdb依赖的动态库文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cj@5aee87bd72ed:/workspace/xxx/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin$ ldd ./arm-linux-gnueabihf-gdb
linux-vdso.so.1 (0x00007ffea9745000)
libtinfo.so.5 => not found
libncursesw.so.5 => not found
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x0000719329bca000)
libpython2.7.so.1.0 => not found
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000719329837000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x0000719329832000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007193296e1000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007193296b3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007193294c1000)
/lib64/ld-linux-x86-64.so.2 (0x0000719329c41000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x0000719329491000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x0000719329475000)

分别有三个动态库文件找不到:libtinfo.so.5、libncursesw.so.5、libpython2.7.so.1.0

1
2
3
4
5
6
7
8
9
10
# 安装libncurses5 可以解决libtinfo.so.5缺失的问题
sudo apt install libncurses5

# 安装libpython2.7 可以解决libpython2.7.so.1.0缺失问题
sudo apt install libpython2.7

# 安装libncursesw5-dev后,并创建动态库的软链接
# 安装时,可以显示已经安装了,没有最新安装。而且安装的动态库是libncursesw.so.6.2
sudo apt install libncursesw5-dev
sudo ln -s /usr/lib/x86_64-linux-gnu/libncursesw.so.6.2 /usr/lib/x86_64-linux-gnu/libncursesw.so.5

至此,gdb可以正常运行。

调试目标程序和其对应的core dump文件,执行:`./arm-linux-gnueabihf-gdb ./target_program ./core-2585-g_main_loop_run

注意:这里将目标程序和对应的core dump文件拷贝到了和gdb同一文件夹

以下是执行的结果:

1
2
3
4
5
6
7
8
9
10
11
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
Core was generated by `./bt-ctl/bt-ctl'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00000000 in ?? ()
[Current thread is 1 (LWP 2588)]
(gdb) bt
#0 0x00000000 in ?? ()
#1 0xa6def8b0 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)

可以看到程序是由于SIGSEGV导致异常终止,通过 bt 打印堆栈,却看不到详细信息。由于我的目标程序无法移植到宿主机运行,故无法查看具体是由于哪一行代码导致的报错。

但是可以修改代码,在程序中捕捉SIGSEGV信号,并打印出堆栈信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 需要的头文件
#include <execinfo.h>

void printStackTrace(void)
{
void *callStack[1280] = {0};
char **messages = NULL;
int numFrames = 0;

// 获取调用栈信息
numFrames = backtrace(callStack, 1280);
messages = backtrace_symbols(callStack, numFrames);

printf("Obtained %zd frames.\n", numFrames);

for (int i = 0; i < numFrames; ++i)
{
printf(" %2d %s\n", i, messages[i]);
}

free(messages); // 释放内存
}

参考

1、怎么办,板子里的程序崩了

2、ubuntu 缺少 libtinfo.so.5 问题