Linux下调试core dump文件的方法

来源:互联网 发布:端口号 53 编辑:程序博客网 时间:2024/05/21 03:17

在开发和使用Linux程序时,引擎有时会莫名其妙的core掉,在网上查了一下,整理了一个简单的调试core文件的方法
1、什么是core dump?
Core,即core memory, 指由一系列小当纳圈形的磁性材料组成的存储器,这里不过是沿用了这一称呼,而dump就是堆放的意思。core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.
2、如何打开core dump支持?
有的操作系统并没有默认打开core dump支持,需要用ulimit -c unlimited语句进行设置,core文件生成的位置一般在程序运行的当前目录下,文件名为core.进程号(当然不同的系统也许有所不同,可以查看相手册对路径和文件名进行设置).
3、Core dump的使用方法
首先应该在用gcc进行编译时选择-g选项,以便起动debug支持,生成可执行文件时ex,./ex运行可执行文件,如果程序当掉,则会生成一个core文件,假设为core.1568,则gdb ex core.1568进入gdb,然后再用where命令进行查看即可。
先看看我用的是个什么机器:

1uname -a

Linux dev 2.4.21-9.30AXsmp #1 SMP Wed May 26 23:37:09 EDT 2004 i686 i686 i386 GNU/Linux

再看看默认的一些参数,注意core file size是个0,程序出错时不会产生core文件了。

1ulimit -a
2core file size (blocks, -c) 0
3data seg size (kbytes, -d) unlimited
4file size (blocks, -f) unlimited
5max locked memory (kbytes, -l) 4
6max memory size (kbytes, -m) unlimited
7open files (-n) 2048
8pipe size (512 bytes, -p) 8
9stack size (kbytes, -s) 10240
10cpu time (seconds, -t) unlimited
11max user processes (-u) 7168
12virtual memory (kbytes, -v) unlimited

写个简单的程序,看看core文件是不是会被产生。

1#include <stdio.h>
2 
3static void sub(void);
4 
5int main(void)
6{
7    sub();
8    return 0;
9}
10 
11static void sub(void)
12{
13    int *p = NULL;
14 
15    /* derefernce a null pointer, expect core dump. */
16    printf("%d", *p);
17}
18 
19$ gcc -Wall -g foo.c
20$ ./a.out
21Segmentation fault
22 
23ls -l core.*
24ls: core.*: No such file or directory

没有找到core文件,我们改改ulimit的设置,让它产生。1024是随便取的,要是core文件大于1024个块,就产生不出来了。

1ulimit -c 1024
2 
3ulimit -a
4core file size (blocks, -c) 1024
5data seg size (kbytes, -d) unlimited
6file size (blocks, -f) unlimited
7max locked memory (kbytes, -l) 4
8max memory size (kbytes, -m) unlimited
9open files (-n) 2048
10pipe size (512 bytes, -p) 8
11stack size (kbytes, -s) 10240
12cpu time (seconds, -t) unlimited
13max user processes (-u) 7168
14virtual memory (kbytes, -v) unlimited
15 
16$ ./a.out
17Segmentation fault (core dumped)
18ls -l core.*
19-rw------- 1 uniware uniware 53248 Jun 30 17:10 core.9128

注意看上述的输出信息,多了个(core dumped)。确实产生了一个core文件,9128是该进程的PID。我们用GDB来看看这个core。

1$ gdb --core=core.9128
2GNU gdb Asianux (6.0post-0.20040223.17.1AX)
3Copyright 2004 Free Software Foundation, Inc.
4GDB is free software, covered by the GNU General Public License, and you are
5welcome to change it and/or distribute copies of it under certain conditions.
6Type "show copying" to see the conditions.
7There is absolutely no warranty for GDB. Type "show warranty" for details.
8This GDB was configured as "i386-asianux-linux-gnu".
9Core was generated by `./a.out'.
10Program terminated with signal 11, Segmentation fault.
11#0 0x08048373 in ?? ()
12(gdb) bt
13#0 0x08048373 in ?? ()
14#1 0xbfffd8f8 in ?? ()
15#2 0x0804839e in ?? ()
16#3 0xb74cc6b3 in ?? ()
17#4 0x00000000 in ?? ()
18 
19此时用bt看不到backtrace,也就是调用堆栈,原来GDB还不知道符号信息在哪里。我们告诉它一下:
20 
21(gdb) file ./a.out
22Reading symbols from ./a.out...done.
23Using host libthread_db library "/lib/tls/libthread_db.so.1".
24(gdb) bt
25#0 0x08048373 in sub () at foo.c:17
26#1 0x08048359 in main () at foo.c:8
27 
28此时backtrace出来了。
29 
30(gdb) l
318         sub();
329         return 0;
3310     }
3411
3512     static void sub(void)
3613     {
3714         int *p = NULL;
3815
3916         /* derefernce a null pointer, expect core dump. */
4017         printf("%d", *p);
41(gdb)

在程序不寻常退出时,内核会在当前工作目录下生成一个core文件(是一个内存映像,同时加上调试信息)。使用gdb来查看core文件,可以指示出导致程序出错的代码所在文件和行数。

1.core文件的生成开关和大小限制
———————————
1)使用ulimit -c命令可查看core文件的生成开关。若结果为0,则表示关闭了此功能,不会生成core文件。
2)使用ulimit -c filesize命令,可以限制core文件的大小(filesize的单位为kbyte)。若ulimit -c unlimited,则表示core文件的大小不受限制。如果生成的信息超过此大小,将会被裁剪,最终生成一个不完整的core文件。在调试此core文件的时候,gdb会提示错误。

2.core文件的名称和生成路径
—————————-
core文件生成路径:
输入可执行文件运行命令的同一路径下。
若系统生成的core文件不带其他任何扩展名称,则全部命名为core。新的core文件生成将覆盖原来的core文件。

1)/proc/sys/kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作为扩展。文件内容为1,表示添加pid作为扩展名,生成的core文件格式为core.xxxx;为0则表示生成的core文件同一命名为core。
可通过以下命令修改此文件:
echo “1″ > /proc/sys/kernel/core_uses_pid

2)proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式。
可通过以下命令修改此文件:
echo “/corefile/core-%e-%p-%t” > core_pattern,可以将core文件统一生成到/corefile目录下,产生的文件名为core-命令名-pid-时间戳
以下是参数列表:
%p – insert pid into filename 添加pid
%u – insert current uid into filename 添加当前uid
%g – insert current gid into filename 添加当前gid
%s – insert signal that caused the coredump into the filename 添加导致产生core的信号
%t – insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h – insert hostname where the coredump happened into filename 添加主机名
%e – insert coredumping executable name into filename 添加命令名

3.core文件的查看
—————–
core文件需要使用gdb来查看。
gdb ./a.out
core-file core.xxxx
使用bt命令即可看到程序出错的地方。
以下两种命令方式具有相同的效果,但是在有些环境下不生效,所以推荐使用上面的命令。
1)gdb -core=core.xxxx
file ./a.out
bt
2)gdb -c core.xxxx
file ./a.out
bt

4.开发板上使用core文件调试
—————————–
如果开发板的操作系统也是linux,core调试方法依然适用。如果开发板上不支持gdb,可将开发板的环境(依赖库)、可执行文件和core文件拷贝到PC的linux下。
在 PC上调试开发板上产生的core文件,需要使用交叉编译器自带的gdb,并且需要在gdb中指定solib-absolute-prefix和 solib-search-path两个变量以保证gdb能够找到可执行程序的依赖库路径。有一种建立配置文件的方法,不需要每次启动gdb都配置以上变量,即:在待运行gdb的路径下建立.gdbinit。
配置文件内容:
set solib-absolute-prefix YOUR_CROSS_COMPILE_PATH
set solib-search-path YOUR_CROSS_COMPILE_PATH
set solib-search-path YOUR_DEVELOPER_TOOLS_LIB_PATH
handle SIG32 nostop noprint pass

注意:待调试的可执行文件,在编译的时候需要加-g,core文件才能正常显示出错信息!有时候core信息很大,超出了开发板的空间限制,生成的core信息会残缺不全而无法使用,可以通过挂载到PC的方式来规避这一点。

0 0