Dec 27, 2009

linux's core dump

core dump 的目地是當你的程式跑到一半當掉(異常中止跳出或freeze)時,我們可從 core 中得到最後掛在那裡,在加上 backtrace 就能快速的找出那裡有 bug :).

先認定 core file size: ulimit -a
如果是 0 的話,我們需要先做一些動作,才有辨法開啟 core dump 的功能.
1. sudo vi /etc/security/limits.conf, 加入這行
* soft core unlimited
2. 開一個新的 terminal,輸入 ulimit -c,此時因該還是0, 利用 ulimit -c unlimited,更改成 unlimited。

設定完 core file size 之後,我使用下面程式來測試 debgu 的效果

/*
* file name: wrong.c
* gcc -g wrong.c -o wrong
*/

#include
#include

void func3()
{
//go to dia;
char *x = 0x0;
*x = 1;
printf("%s", x);
strcpy(x, "This is wrong");
}

void func2(void)
{
func3();
}

void func1(void)
{
func2();
}


int main(void)
{
func1();
return 0;
}

執行結果為:
程式記憶體區段錯誤 (core dumped)
如沒有意外的話,因該可以看到多出了一個 core 的檔案
$file core
core: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './wrong'
有了 core file 之後,我們就可以利用 gdb 來做 backtrace
$ gdb wrong core
Core was generated by `./wrong'.
Program terminated with signal 11, Segmentation fault.
#0 0x08048264 in func3 () at wrong.c:8

warning: Source file is more recent than executable.
8
我們大概可以知道是停在 func3 裡,透過 print 可知道,發生了什麼事
(gdb) p x
$1 = 0x0
(gdb) p *x
Cannot access memory at address 0x0
另外,最好用的當然是 backtrace
(gdb) where
#0 0x08048264 in func3 () at wrong.c:8
#1 0x080482a4 in func2 () at wrong.c:15
#2 0x080482b1 in func1 () at wrong.c:20
#3 0x080482be in main () at wrong.c:26
(gdb) help where
Print backtrace of all stack frames, or innermost COUNT frames.
With a negative argument, print outermost -COUNT frames.
Use of the 'full' qualifier also prints the values of the local variables.
where 指令,我們能很清楚的知道是從
main -> func1 -> func2 -> func3
另外還有一種情況是,程式掉進 trap,而不會觸發 SIGEGV signal,此時可以利用 xiaosuo 寫的 dumper 讓你所想要的程式觸發 signal 產生 core file。

將 wrong.c 中的 func3 改成

void func3()
{
//go into loop;
while(1){
sleep(1);
}
}

compiler完之後,讓 wrong_loop 於背景執行
./wrong_loop &
[1] 31908
當然,我們都知道,它是不會中止的,此時可以利用 dumper 來中止 wrong_loop 且產生 core file
$ ./dumper 31908 -k
Start injecting(31908)...OK
[1]+ 不合法的命令 (core dumped) ./wrong_loop
$
$ file core
core: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './wrong_loop'
產生了 core 我們就可利用 GDB 來debug
$ gdb wrong_loop core
.....
Program terminated with signal 4, Illegal instruction.
#0 0xbfe0f4dc in ?? ()
(gdb) where
#0 0xbfe0f4dc in ?? ()
#1 0x08048266 in func3 () at wrong_loop.c:8
#2 0x08048273 in func2 () at wrong_loop.c:14
#3 0x08048280 in func1 () at wrong_loop.c:19
#4 0x0804828d in main () at wrong_loop.c:25
(gdb)

Reference:

No comments: