利用core文件调试

首先用-g选项编译程序,然后用
ulimit -c unlimited
打开core文件限制
to make the changes permanent, add the following line to /etc/sysctl.conf:
kernel.core_pattern = core.%e.%p
sysctl is a similar tool to ulimit: It allows to configure kernel
parameters at runtime. If you wish to keep settings persistent across
reboots you should edit /etc/sysctl.conf - be aware that wrong settings
may break things in unforeseen ways.

用/proc/sys/kernel/core_pattern控制core文件产生的地方
在测试站上
root: cat /proc/sys/kernel/corepattern
/tmp/core.%p
%e
也就是说,所有core文件都在/tmp文件夹,文件名是
core.pid_execFileName
这时,启动任何程序,只要是非正常退出,都会产生一个core文件

echo "/tmp/core-%e-%p-%t" > core_pattern
将会控制所产生的core文件会存放到/tmp目录下,产生的文件名为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 添加命令名

然后用
gdb -f execfile -c corefile打开core文件,比如

gdb -c /tmp/core.24281_fweb -f /home/bbs/bbshome/httpd/fweb
GNU gdb 5.3-debian
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-linux"…
Core was generated by `/home/bbs/bbshome/httpd/fweb’.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/local/lib/libglib-2.0.so.0…done.
Loaded symbols for /usr/local/lib/libglib-2.0.so.0
Reading symbols from /usr/local/lib/libfcgi.so.0…done.
Loaded symbols for /usr/local/lib/libfcgi.so.0
Reading symbols from /lib/libdl.so.2…done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/libc.so.6…done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libnsl.so.1…done.
Loaded symbols for /lib/libnsl.so.1
Reading symbols from /lib/ld-linux.so.2…done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /home/bbs/bbshome/httpd/pages/bbsqry.so…done.
Loaded symbols for /home/bbs/bbshome/httpd/pages/bbsqry.so
Reading symbols from /home/bbs/bbshome/httpd/pages/bbsgetmsg.so…done.
Loaded symbols for /home/bbs/bbshome/httpd/pages/bbsgetmsg.so
Reading symbols from /home/bbs/bbshome/httpd/pages/bbslogin.so…done.
Loaded symbols for /home/bbs/bbshome/httpd/pages/bbslogin.so
#0 FCGI_fprintf (fp=0x0, format=0x40e9929e "%d") at fcgi_stdio.c:602
/root/fcgi-2.4.0/libfcgi/fcgi_stdio.c:602:15672:beg:0x400a1850

这个时候,你可以看是哪一步让进程死掉,比如先用
(gdb) backtrace
#0 FCGI_fprintf (fp=0x0, format=0x40e9929e "%d") at fcgi_stdio.c:602
#1 0x40e990ad in check_login_limit (x=0x805d5a0) at bbslogin.c:303
#2 0x40e988d5 in bbslogin_main () at bbslogin.c:127
#3 0x0804ca1c in do_invoke (p=0x8087408) at module.c:162
#4 0x0804ca80 in invoke_module (name=0x8083d59 "bbslogin") at module.c:192
#5 0x0804cb70 in process_request () at dispatcher.c:44
#6 0x0804cbf5 in cgiMain () at dispatcher.c:82
#7 0x0804cfb5 in serv_request () at cgic.c:322
#8 0x08050ae3 in main () at main.c:44
打印frames,然后用
(gdb) frame 1
#1 0x40e990ad in check_login_limit (x=0x805d5a0) at bbslogin.c:303
/home/jawahh/bbs/fweb/pages/bbslogin.c:303:6735:beg:0x40e990ad
选择你要看的frame,现在选择了#1 frame,然后就可以用如
(gdb) info locals
fp = (FCGI_FILE ) 0x0
filename = "home/C/clickbeetle/logincheck05b診001塞"
num = 0
察看本地变量
(gdb) list
298 sethomefile(filename, x->userid, "logincheck");
299 if (!file_exist(filename)
300 || abs(file_time(filename) - time(0)) > 86400)
301 {
302 fp = fopen(filename, "w");
303 fprintf(fp, "%d", x->numlogins);
304 fclose(fp);
305 return;
306 }
307 fp = fopen(filename, "r");
察看程序代码
(gdb) p fp
$5 = (FCGI_FILE
) 0x0
察看变量

等等等等很多方法,这样调试会简单多