深入探索Linux coredump調試技巧

1.       coredump 產生的原理和侷限

 

1.1.  如何產生 core 文件

       要素一,必須有信號產生:

       從上面的信號定義和說明可以看出,進程中止前肯定會產生信號,然後內核根據信號的類型來決定是否要產生 core 文件。

要素二,編譯器支持:

       要產生 core 文件,編譯器必須支持把當前進程的鏡像以某種格式 dump 到一個文件中,常見的比如 gcc/g++ -g 選項。

要素三,環境參數支持:

通過 ulimit –a 查看 core file size 是否爲 0 ,如果爲 0 則不能產生 core 文件。

通過 ulimit –c unlimited 可以系統能支持的產生足夠大的 core 文件,也可以設置爲具體值。

特別說明:

core 文件的產生不是 POSIX.1 所屬部分,而是很多 UNIX/Linux 版本的實現特徵。

 

1.2.  Unix/Linux 對信號的處理方式

 

UNIX System signals

Name

Description

ISO C

SUS

FreeBSD 5.2.1

Linux 2.4.22

Mac OS X 10.3

Solaris 9

Default action

SIGABRT

abnormal termination (abort )

terminate+core

SIGALRM

timer expired (alarm )

 

terminate

SIGBUS

hardware fault

 

terminate+core

SIGCANCEL

threads library internal use

 

 

 

 

 

ignore

SIGCHLD

change in status of child

 

ignore

SIGCONT

Continue stopped process

 

continue/ignore

SIGEMT

hardware fault

 

 

terminate+core

SIGFPE

arithmetic exception

terminate+core

SIGFREEZE

checkpoint freeze

 

 

 

 

 

ignore

SIGHUP

hangup

 

terminate

SIGILL

illegal instruction

terminate+core

SIGINFO

status request from keyboard

 

 

 

 

ignore

SIGINT

terminal interrupt character

terminate

SIGIO

asynchronous I/O

 

 

terminate/ignore

SIGIOT

hardware fault

 

 

terminate+core

SIGKILL

termination

 

terminate

SIGLWP

threads library internal use

 

 

 

 

 

ignore

SIGPIPE

write to pipe with no readers

 

terminate

SIGPOLL

pollable event (poll )

 

XSI

 

 

terminate

SIGPROF

profiling time alarm (setitimer )

 

XSI

terminate

SIGPWR

power fail/restart

 

 

 

 

terminate/ignore

SIGQUIT

terminal quit character

 

terminate+core

SIGSEGV

invalid memory reference

terminate+core

SIGSTKFLT

coprocessor stack fault

 

 

 

 

 

terminate

SIGSTOP

stop

 

stop process

SIGSYS

invalid system call

 

XSI

terminate+core

SIGTERM

termination

terminate

SIGTHAW

checkpoint thaw

 

 

 

 

 

ignore

SIGTRAP

hardware fault

 

XSI

terminate+core

SIGTSTP

terminal stop character

 

stop process

SIGTTIN

background read from control tty

 

stop process

SIGTTOU

background write to control tty

 

stop process

SIGURG

urgent condition (sockets)

 

ignore

SIGUSR1

user-defined signal

 

terminate

SIGUSR2

user-defined signal

 

terminate

SIGVTALRM

virtual time alarm (setitimer )

 

XSI

terminate

SIGWAITING

threads library internal use

 

 

 

 

 

ignore

SIGWINCH

terminal window size change

 

 

ignore

SIGXCPU

CPU limit exceeded (setrlimit )

 

XSI

terminate+core/ignore

SIGXFSZ

file size limit exceeded (setrlimit )

 

XSI

terminate+core/ignore

SIGXRES

resource control exceeded

 

 

 

 

 

ignore

 

2.       core 文件的使用

 

3.       core 文件的侷限

core 文件提供了當前進程的所有線程的堆棧信息,但是也有他的侷限性。

由於 core 是對當前進程地址空間的鏡像,所以 core 文件一般比較巨大,特別是針對服務器程序。

這樣如果服務器程序自動重啓幾次,可能就會導致磁盤空間佔滿。

另外,由於 core 文件巨大,不刪除的話佔用大量磁盤空間,下載下來又比較費時。

對於緩衝區溢出導致的 coredump ,進程的調用堆棧已經被覆蓋破壞了, core 文件顯示的堆棧信息往往錯誤。

一些信號導致進程崩潰,但是不產生 core 文件,比如 SIGPIPE

只能在進程中止時纔可以產生 core, 不能實時產生。

4.       堆棧打印

4.1.  如何打印堆棧

1 、通過backtracebacktrace_symbolsbacktrace_symbols_fd 實現當前線程的堆棧打印。

堆棧打印的一個簡單示例:

     #include <execinfo.h>

     #include <stdio.h>

     #include <stdlib.h>

    

     /* Obtain a backtrace and print it to stdout. */

     void print_trace (void)

     {

       void *array[10];

       size_t size;

       size_t i;

    

       size = backtrace (array, 10);

       printf ("Obtained %zd stack frames./n", size);

    

       for (i = 0; i < size; i++)

          printf ("% /n",   array  [i]);

     }

    

     /* A dummy function to make the backtrace more interesting. */

     void dummy_function (void)

     {

       print_trace ();

     }

    

     int main (void)

     {

       dummy_function ();

       return 0;

     }

2 、編譯時必須加上 -rdynamic –ldl 選項。

3 、如果要打印崩潰線程的堆棧信息,則必須在信號處理函數中打印堆棧。注意要通過 setjmp/longjmp sigsetjmp/siglongjmp 來跳轉,否則會陷於死循環。因爲信號是軟件中斷,處理完後會返回到發生異常的地方繼續執行,這樣又會重新產生異常。

4 、我寫了一個 coredump 組件,支持打印崩潰線程的堆棧信息和寄存器變量,捕捉 SIGINT SIGTERM SIGFPE SIGABRT SIGSEGV 等信號引起的異常崩潰,打印信息輸出到一個文本文件。該組件將會放到 SGDP 中供項目組選用。具體使用方法請看 readme example

 

4.2.  打印堆棧的優缺點

優點: 1 、不依賴 core 文件。

         2 、可以打印當前崩潰線程的堆棧調用信息。

         3 、輸出到文件佔用的磁盤空間很小。

缺點:

1、  只能打印當前線程的堆棧信息。

2、  只能打印堆棧調用信息。

3、  不能打印當前線程的所有變量值。

4、  輸出函數名沒有 gdb core 文件可讀性好。

5、  對於 abort 異常定位,需要和 nm 等代碼分析工具配合使用。

6、   

5.       GCC/G++ 對內存錯誤的處理

GCC 對內存錯誤的檢查,在不同版本都有一定的體現。

GCC 對內存錯誤的檢查主要依靠 3 個選項: -fstack-check -fbounds-check -fstack-protector-all

其中 -fstack-check 的準確性較差,特別是在代碼執行了 O2 以上的優化後。

-fbounds-check 可以執行數組邊界錯誤,主要是檢查對數組賦值越界。

-fstack-protector-all 可以防止緩衝區溢出攻擊,也可以利用此選項來檢查代碼是否有緩衝區溢出的錯誤。

GCC 4.1 以前的版本支持 -fstack-check -fbounds-check GCC 4.1 以後版本支持 -fstack-check -fbounds-check -fstack-protector-all

GCC 4.1 以前的版本對於緩衝區溢出檢查沒有很好的解決方案,如果調用堆棧被破壞的不多還有可能定位出錯函數的位置,否則只是一個錯誤的堆棧信息甚至無信息。

-fstack-protector-all 選項加上後會在標準輸出上打印當前崩潰線程的堆棧調用信息,但是有時也不準確,同時產生 core 文件, core 文件中的出錯堆棧信息相對比較準確性。

 

6.       SGDP coredump 組件

我們自己開發了一個 Linux 版打印進程崩潰堆棧信息的 coredump 組件,放在 SGDP 的工具裏面。

coredump 組件支持打印崩潰線程的堆棧信息和寄存器變量,捕捉SIGINTSIGTERMSIGFPE SIGABRTSIGSEGV 等信號引起的異常崩潰,打印信息輸出到一個文本文件。

使用方法:1 、代碼中包含coredump.h

          2 、在main 函數開始的地方調用setup_sigcoredump()

如果大家需要的話,可以聯繫服務器引擎部,提供二進制版本的庫和示例代碼。

 

7.       Google coredumper

7.1.       項目介紹

在進程不中止的情況下可以產生 core 文件,該 core 文件可以使用 gdb 調試,對於多線程調試有重要意義。

在產生 core 文件時會掛起所有線程,所以是線程安全的。

版權聲明爲 BSD 授權。

當前最新版本爲 1.2.1

項目鏈接: http://code.google.com/p/google-coredumper/

7.2.       安裝方法

與標準的開源項目基本上差不多: ./configure make make install

需要注意的是編譯生成的庫在當前目錄和標準目錄中都沒有,具體需要查看 libcoredumper.la 描述信息,方法: vi libcoredumper.la

否則有可能找不到動態庫或靜態庫。

7.3.       使用方法

1、  包含 src 目錄下的 google/coredumper.h

2、  調用 GetCoreDump WriteCoreDump 等系列接口生成 core 文件。

3、  coredumper.h 中大部分函數都有 man 幫助。

4、  特別注意的是 WriteCoreDump 實際上是調用 GetCoreDump ,語義上好像是有點問題,看接口名稱是有點困惑,我是看代碼才發現的。

5、  可以指定預定義的壓縮器來生成壓縮的 core 文件,也可以自定義壓縮算法生成 core 文件。

6

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章