core dump及應用
【1】core dump 概念
<a href="http://en.wikipedia.org.nyud.net:8080/wiki/Core_dump">http://en.wikipedia.org.nyud.net:8080/wiki/Core_dump</a>
A core dump is the recorded state of the working memory of a computer program at a specific time, generally when the program has terminated abnormally (crashed). In practice, other key pieces of program state are usually dumped at the same time, including the processor registers, which may include the program counter and stack pointer, memory management information, and other processor and operating system flags and information. The name comes from the once-standard memory technology core memory. Core dumps are often used to diagnose or debug errors in computer programs.
On many operating systems, a fatal error in a program automatically triggers a core dump, and by extension the phrase "to dump core" has come to mean, in many cases, any fatal error, regardless of whether a record of the program memory is created.
【2】示例:在Linux下産生并調試core檔案
先看看我用的是個什麼機器:
$ uname -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檔案了。
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max locked memory (kbytes, -l) 4
max memory size (kbytes, -m) unlimited
open files (-n) 2048
pipe size (512 bytes, -p) 8
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 7168
virtual memory (kbytes, -v) unlimited
寫個簡單的程式,看看core檔案是不是會被産生。建立foo.c,使内容如下。
$ more foo.c
#include <stdio.h>
static void sub(void);
int main(void)
{
sub();
return 0;
}
static void sub(void)
int *p = NULL;
/* derefernce a null pointer, expect core dump. */
printf("%d", *p);
$ gcc -Wall -g foo.c 【-Wall :[Warning all] 顯示所有常用的編譯警告資訊。 -g選項,将調試資訊加入到目标檔案或可執行檔案中。】
$ ./a.out
Segmentation fault 【所謂的Segmentation Fault(段錯誤)就是指通路的記憶體超出了系統所給這個程式的記憶體空間】
$ ls -l core*
ls: core*: No such file or directory
沒有找到core檔案,我們改改ulimit的設定,讓它産生,1024是随便取的,也可以使用ulimit -c unlimited不限制大小。
$ ulimit -c 1024
core file size (blocks, -c) 1024
Segmentation fault (core dumped)
-rw------- 1 uniware uniware 53248 Jun 30 17:10 core.9128 【此處也可能是名稱為core的檔案】
注意看上述的輸出資訊,多了個(core dumped)。确實産生了一個core檔案,9128是該程序的PID。我們用GDB來看看這個core。
$ gdb --core=core.9128
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 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 was configured as "i386-asianux-linux-gnu".
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x08048373 in ?? ()
(gdb) bt
#1 0xbfffd8f8 in ?? ()
#2 0x0804839e in ?? ()
#3 0xb74cc6b3 in ?? ()
#4 0x00000000 in ?? ()
此時用bt看不到backtrace,也就是調用堆棧,原來GDB還不知道符号資訊在哪裡。我們告訴它一下:
(gdb) file ./a.out
Reading symbols from ./a.out...done.
Using host libthread_db library "/lib/tls/libthread_db.so.1".
#0 0x08048373 in sub () at foo.c:17
#1 0x08048359 in main () at foo.c:8
此時backtrace出來了。
(gdb) l (此處是“L”的小寫,不是數字“1”)
8 sub();
9 return 0;
10 }
11
12 static void sub(void)
13 {
14 int *p = NULL;
15
16 /* derefernce a null pointer, expect core dump. */
17 printf("%d", *p);
(gdb)
【3】總結
在程式不尋常退出時,核心會在目前工作目錄下生成一個core檔案(是一個記憶體映像,同時加上調試資訊)。使用gdb來檢視core檔案,可以訓示出導緻程式出錯的代碼所在檔案和行數。
1.core檔案的生成開關和大小限制
1)使用ulimit -c指令可檢視core檔案的生成開關。若結果為0,則表示關閉了此功能,不會生成core檔案。
2)使用ulimit -c filesize指令,可以限制core檔案的大小(filesize的機關為kbyte)。如果生成的資訊超過此大小,将會被裁剪,最終生成一個不完整的core檔案。在調試此core檔案的時候,gdb會提示錯誤。若ulimit -c unlimited,則表示core檔案的大小不受限制。ulimit -c 0關閉該功能。
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
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的方式來規避這一點。