淺談core dump

core文件描述

 

參考:man手冊

 

1.什麼是core dump

許多程序和操作系統崩潰或者出錯時,一般會自動生成一個叫core 的文件(二進制文件)。因爲某些信號的默認動作是導致進程終止併產生一個core dump文件(signal(7)),core文件記錄的是程序崩潰時的內存映像,包含寄存器的狀態,堆棧指針,內存管理信息還有各種函數調用堆棧信息等,並且加入了調試信息(例如,gdb(1)),core文件生成的過程叫core dump

通過工具分析這個文件(如 GNU Binutils Binary File Descriptor library (BFD),GNU Debugger (gdb),mdb等),我們可以定位到程序異常退出時對應的堆棧

調用等各種狀態信息,並找出問題所在並及時進行解決。

2.core一般性原因(其實就是一些常見的調試錯誤)

1.內存訪問越界

a)下表使用錯誤,導致數組訪問越界

b)搜索字符竄時,沒有正確使用結束符

c)沒有使用安全的讀寫複製函數

2.多線程程序使用了線程不安全的函數(博主對線程不安全函知之甚少,就偷懶了)

應該使用下面這些可衝入的函數,他們很容易被用錯:

asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n)ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c)getlogin_r(3c)getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c)fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c)getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3)getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n)nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3)getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c)getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c)getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)

3.多線程讀寫的數據未加鎖進行保護

4.非法指針

a)空指針

b)將某種非指針類型或結構的內存轉換成指針來使用

5.堆棧溢出

3.core文件的存儲位置以及設置生成core文件

1.core文件默認的存儲位置與對應的可執行程序在同一目錄,文件名是core.(注:但是可以通過chdir()函數指定core文件創建的路徑)

	cat /proc/sys/kernel/core_patterncat /proc/sys/kernel/core_pattern

2.設置生成core文件

ulimit  -c                   //查看core-dump的狀態,若返回0。則表示不會產生對應的core-dump

ulimit  -c[size]          //指定對應的字符大小,例如:ulimit  -c 1024,數字最好大於3

ulimit  -c  unlimited   //表示產生的core-dump大小不受限制(加入文件 /etc/profile)
3.gdb利用core文件進行調試

gdb[exec file]   [core file]                //查看core文件的內容

bt                                                    //用來進入gdb後,來定位core-dump的文件->行

4.不產生core文件的幾種情況

*進程沒有寫入core dump文件的權限。(默認情況下,core file稱爲core,並在當前工作目錄中創建。)如果core文件它的目錄被創建,並且是nonwritable的,core文件就會創建失敗,或者如果一個具有相同名稱的文件已存在,不可寫或是不正規的文件(例如,它是一個目錄或符號鏈接)都會失敗。

*將用於core dump,但是相同的文件名稱已經存在,並且有多個硬鏈接文件。

*文件系統的core dump被創建爲已滿;或已用完默認的字節數;或是設爲只讀;或用戶已達到文件系統的配額數量等。

*要創建core dump的目錄不存在。

* RLIMIT_CORE(core文件大小)或 RLIMIT_FSIZE(文件大小)的進程的資源限制設置爲零;看getrlimit(2)與查看shell文件的ulimit下顯示的文件((limit in csh(1))。

*進程所執行的二進制文件沒有啓用讀權限。

*進程正在執行由用戶(組)所擁有的set-user-ID (set-group-ID)程序,而不是該進程的真實用戶(組)ID。(不過,可以查看 prctl(2) PR_SET_DUMPABLE的操作,和文件過程描述在 /proc/sys/fs/suid_dumpable file in proc(5)中.)

*(自從Linux 3.7內核配置)沒有CONFIG_COREDUMP選項。

 

此外,一個core dump文件可以排除該進程的地址空間的一部分,如果 madvise(2) MADV_DONTDUMP標誌存在的
 

5.core_pattern的格式(/proc/sys/kernel/core_pattern)

可以在core_pattern模板下使用的變量還有:

%%單個%字符

%p被dump的進程的進程ID

%u(數字)被dump的進程的實際用戶ID

% g(數字)被dump的進程的實際組ID

%s導致本次dump的信號

%t dump的時間,秒錶示由於時代,1970-01-0 00:00:00 + 0000(UTC)

% h主機名(same as nodename returned by uname(2)))

%e可執行文件名(無路徑前綴)

%E生成可執行的路徑,以斜槓(/)取代標記('!')。

%C core文件資源大小限制崩潰的進程(自Linux 2.6.24)

6.編寫一個利用管道指定core_pattern_pipe_test(在文件 /proc/)

      $ cc -o core_pattern_pipe_test core_pattern_pipe_test.c
         $ su
         Password:
         # echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \
              /proc/sys/kernel/core_pattern
         # exit
         $ sleep 100
         ^\                     # type control-backslash
         Quit (core dumped)
         $ cat core.info
         argc=5
         argc[0]=</home/mtk/core_pattern_pipe_test>
         argc[1]=<20575>
         argc[2]=<UID=1000>
         argc[3]=<GID=100>
         argc[4]=<sig=3>
         Total bytes in core dump: 282624$ cc -o core_pattern_pipe_test core_pattern_pipe_test.c
         $ su
         Password:
         # echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \
              /proc/sys/kernel/core_pattern
         # exit
         $ sleep 100
         ^\                     # type control-backslash
         Quit (core dumped)
         $ cat core.info
         argc=5
         argc[0]=</home/mtk/core_pattern_pipe_test>
         argc[1]=<20575>
         argc[2]=<UID=1000>
         argc[3]=<GID=100>
         argc[4]=<sig=3>
         Total bytes in core dump: 282624

Program source

/* core_pattern_pipe_test.c */
       #define _GNU_SOURCE
       #include <sys/stat.h>
       #include <fcntl.h>
       #include <limits.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #define BUF_SIZE 1024
       int main(int argc, char *argv[])
       {
           int tot, j;
           ssize_t nread;
           char buf[BUF_SIZE];
           FILE *fp;
           char cwd[PATH_MAX];
           /* Change our current working directory to that of the
              crashing process */
           snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]);
           chdir(cwd);

           /* Write output to file "core.info" in that directory */

           fp = fopen("core.info", "w+");
           if (fp == NULL)
               exit(EXIT_FAILURE);

           /* Display command-line arguments given to core_pattern
              pipe program */
 	   fprintf(fp, "argc=%d\n", argc);
           for (j = 0; j < argc; j++)
               fprintf(fp, "argc[%d]=<%s>\n", j, argv[j]);
           /* Count bytes in standard input (the core dump) */

           tot = 0;
           while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
               tot += nread;
           fprintf(fp, "Total bytes in core dump: %d\n", tot);

           exit(EXIT_SUCCESS);
       }	   fprintf(fp, "argc=%d\n", argc);
           for (j = 0; j < argc; j++)
               fprintf(fp, "argc[%d]=<%s>\n", j, argv[j]);
           /* Count bytes in standard input (the core dump) */

           tot = 0;
           while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
               tot += nread;
           fprintf(fp, "Total bytes in core dump: %d\n", tot);

           exit(EXIT_SUCCESS);
       }

7.結言

以上如果有什麼不正確的地方,望衆博友一起討論,一起進步。

終於開始使用手冊進行參考了,嘻嘻,當然剛開始還是有點不習慣的,但是查函數原型真的比百度強太多了,還有描述,真的毫不廢話,都是很精煉的。

 

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