core文件與gdb調試


本文簡單介紹core文件與gdb調試core文件的方法


概要:

    1. core 文件

    2. 配置core程序崩潰時產生文件

    3. 可修改core文件名

   4. 產生core文件的情形

    5. gdb調試core文件

        a) gdb -c <xxx.core> [可執行程序]

        b) gdb命令:backtrace / bt 

        c) gdb命令:up/down/frame

        d) gdb命令:info locals

        e) gdb命令:info args

        f) gdb命令:print <變量名> / print *<變量名>



1. core 文件


    linux/unix下,可執行程序崩潰時會產生core文件。core文件是內存映象,可用於調試程序找出程序崩潰的原因。


2. 配置core程序崩潰時產生文件


    linux/unix下,通過limit -a,可以查看系統是否對可程序的崩潰生成core文件。其中core file size 便是指產生core文件的大小。下面是freebsd系統中輸出limit -a 輸出的一行,unlimited表示不限制,如果 unlimited 爲 1024,則表示產生core文件最大爲 1024塊,每塊大小爲512字節。如果爲0,則表示不產生core文件。

core file size      (512-blocks, -c)  unlimited

core file size      (512-blocks, -c)  1024

core file size      (512-blocks, -c)  0


    通過limit命令,可以改變設置。如 ulimit -c unlimited 或 limit -c 1024等。


3. 可修改core文件名


    core文件產生於程序的工作目錄,不通系統命名不一樣 freebsd 下,默認命名爲 程序名.core ,這個名稱是可以修改的。freebsd下,通過 man core 可以知道,通過sysctl可以查看core文件名的規則和對其進行修改。下面是指core文件名組成是 程序名.core。


root@freebsd:/ # sysctl -a | grep corefile

kern.corefile: %N.core


    freebsd下查看 man core,可以知道core文件命名時可用的規則:


     The name of the file is controlled via the sysctl(8) variable

     kern.corefile.  The contents of this variable describes a filename to

     store the core image to.  This filename can be absolute, or relative

     (which will resolve to the current working directory of the program gen-

     erating it).


     The following format specifiers may be used in the kern.corefile sysctl

     to insert additional information into the resulting core file name:

          %H          Machine hostname.

          %I          An index starting at zero until the sysctl debug.ncores

                      is reached.  This can be useful for limiting the number

                      of corefiles generated by a particular process.

          %N          process name.

          %P          processes PID.

          %U          process UID.



4. 產生core文件的情形


    程序在運行時,發生致命錯誤導致程序崩潰,會產生core文件。當系統捕獲到一些信號如 SIGSEGV 等信號,就會生產core文件。


    通過man signal,可以查看到什麼信息會產生core:


     Num   Name         Default Action       Description

     1     SIGHUP       terminate process    terminal line hangup

     2     SIGINT       terminate process    interrupt program

     3     SIGQUIT      create core image    quit program

     4     SIGILL       create core image    illegal instruction

     5     SIGTRAP      create core image    trace trap

     6     SIGABRT      create core image    abort program (formerly SIGIOT)

     7     SIGEMT       create core image    emulate instruction executed

     8     SIGFPE       create core image    floating-point exception

     9     SIGKILL      terminate process    kill program

     10    SIGBUS       create core image    bus error

     11    SIGSEGV      create core image    segmentation violation

     12    SIGSYS       create core image    non-existent system call invoked


    最常見的程序崩潰的原因便是 SIGSEGV(非法訪問內存)。


5. gdb調試core文件


    1) 程序在編碼時,加上 -g 選項來增加調試信息。

    2) 用gdb對core文件進行調試,查看程序運行狀態。


下面列舉一些常用的命令:


a) gdb -c <xxx.core> [可執行程序]


    運行gdb,調度core文件。如下面是我的可執行程序所在的目錄:


root@freebsd:~/test/core_statck # ls

core_stack      core_stack.core core_stack.cpp


    core_stack.cpp    源文件

    core_stack          由源文件編譯出來的可執行程序

    core_stack.core   core_stack產生的core文件


    輸入命令後,gdb就會運行並輸出很多信息,這些信息基本上是加載庫的信息。最後還會輸出最後一個stack中的信息。此時gdb是處於第0棧狀態。


root@freebsd:~/test/core_statck # gdb -c core_stack.core core_stack

GNU gdb 6.1.1 [FreeBSD]

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 GDB was configured as "i386-marcel-freebsd"...

Core was generated by `core_stack'.

Program terminated with signal 6, Aborted.

Reading symbols from /usr/lib/libc++.so.1...done.

Loaded symbols for /usr/lib/libc++.so.1

Reading symbols from /lib/libcxxrt.so.1...done.

Loaded symbols for /lib/libcxxrt.so.1

Reading symbols from /lib/libm.so.5...done.

Loaded symbols for /lib/libm.so.5

Reading symbols from /lib/libgcc_s.so.1...done.

Loaded symbols for /lib/libgcc_s.so.1

Reading symbols from /lib/libc.so.7...done.

Loaded symbols for /lib/libc.so.7

Reading symbols from /libexec/ld-elf.so.1...done.

Loaded symbols for /libexec/ld-elf.so.1

#0  0x2829a467 in kill () from /lib/libc.so.7

(gdb) 


b) gdb命令:backtrace / bt 


    gdb命令 bt 可以輸出程序崩潰前棧上的信息,主要是程序的調用棧。


(gdb) bt

#0  0x2829a467 in kill () from /lib/libc.so.7

#1  0x2829a3f7 in raise () from /lib/libc.so.7

#2  0x28298b06 in abort () from /lib/libc.so.7

#3  0x282797f8 in __assert () from /lib/libc.so.7

#4  0x08049de0 in MyDump::print (this=0xbfbfecd8, x=4, core=false) at core_stack.cpp:13

#5  0x080491bd in MyDump::detaildump (this=0xbfbfecd8, a=111, b=222) at core_stack.cpp:35

#6  0x08049166 in MyDump::dump (this=0xbfbfecd8, level=0, a=111, b=222) at core_stack.cpp:30

#7  0x08049140 in MyDump::dump (this=0xbfbfecd8, level=1, a=111, b=222) at core_stack.cpp:28

#8  0x08049140 in MyDump::dump (this=0xbfbfecd8, level=2, a=111, b=222) at core_stack.cpp:28

#9  0x08049140 in MyDump::dump (this=0xbfbfecd8, level=3, a=111, b=222) at core_stack.cpp:28

#10 0x0804928f in main () at core_stack.cpp:46


    由上面輸出可以看出,程序的調用情況,同時還會輸出源文件中對應的行號。


c) gdb命令:up/down/frame


up: 進行上一棧

down: 進入下一棧

frame N: 進行第N棧


這三個命令主要是用戶切換gdb當前所處於的棧。gdb處理某一棧的狀態時,便可以通過info,print等命令來查看棧中的信息。


d) gdb命令:info locals


查看局部變量,一個很有用的命令。下面可以看到,函數內有一個局部變量lev,值爲2


(gdb) info locals

lev = 2


e) gdb命令:info args


    查看函數參數,一個很有用的命令。下面可以看到函數的入參有 this, level, a, b 以及它們的值。


(gdb) info args

this = (MyDump *) 0xbfbfecd8

level = 2

a = 111

b = 222


f) gdb命令:print <變量名> / print *<變量名>


    查看變量值和指針所指變量的值,一個很有用的命令。print 可以打印當前棧可見的變量,包括局部變量、函數入參、全局變量等。下面是輸出this指針的對象,this所指對象有一個成員變量m_n,值爲4


(gdb) print *this

$6 = {m_n = 4}


    info locals, info args, print 三個命令配合起來,基本上很容易瞭解到程序core時的當前狀態,定位core的原因。


    上面的命令,大部分情況都可以定位出程序core的問題了。但是對於複雜的棧情況或是棧中有數據被破壞,這是比較能發查出的。更多的命令和用法,需要查看man gdb 和 gdb 命令 help 來了解。


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