最近工作涉及到分析core dump文件,發現這個好帖,就當仁不讓地轉到偶博客了O(∩_∩)O~
PS:
Where can you get dbx?
It is part of bos.adt.debug
# lslpp -w /usr/bin/dbx
File Fileset Type
-------------------------------------------
/usr/bin/dbx bos.adt.debug Symlink
以下轉自:http://www.aixchina.net/?6141/viewspace-18882
I core dump 分析入門
環境變量設置
可以通過 /etc/security/limits 文件對各用戶的基本配置參數包括 core 大小進行限制。或者通過 ulimit 更改當前環境下的 core 大小限制。
默認情況下,應用進程生成 core dump 時都使用文件名 core。為了避免同一工作目錄下的進程 core 相互覆蓋,可以定義環境變量 CORE_NAMING=true,然后啟動進程,這樣將生成名為 core.pid.ddhhmmss 的文件。可以使用 file core 命令查看 core 是哪個進程產生的。
默認情況下,應用進程 dump 時會包含所有的共享內存,如果 dump 時想排除共享內存內容,可以在啟動進程之前設置環境變量 CORE_NOSHM=true.
系統有一個參數 fullcore 用於控制是否在程序 coredump 時生成完整的 core。為避免信息丟失,建議打開 fullcore。可以使用 lsattr –El sys0 查詢是否將 fullcore 打開,使用 chdev -l sys0 -a fullcore=true 將 fullcore 狀態更改為打開。也可以在程序內部調用 sigaction 例程設置 fullcore,參考如下測試程序:
fullcore 設置示例
//test.C #include <iostream> #include <signal.h>
int main(int argc, char* argv[]) { char str[10]; struct sigaction s; s.sa_handler = SIG_DFL; s.sa_mask.losigs = 0; s.sa_mask.hisigs = 0; s.sa_flags = SA_FULLDUMP; sigaction(SIGSEGV,&s,(struct sigaction *) NULL);
std::cout << " input str!\n" << std::endl; std::cin >> str; return 0; }
|
尋找 core dump
應用進程的 core 產生在其當前工作目錄下,可以在應用程序內部使用 chdir 函數切換當前工作目錄。使用 procwdx 命令可以查看進程的當前工作目錄。系統的 core 生成在 lg_dumplv 下,並在重啟時轉移到 /var/adm/ras/ 目錄下(如果有足夠空間的話,否則繼續保留在 lg_dumplv,並隨時有可能被覆蓋)。
可以使用 errpt -a 查看標識 C0AA5338 SYSDUMP(系統 core)、B6048838 CORE_DUMP(進程 core)的詳細錯誤信息,獲取生成 core 的進程以及 core 文件位置。使用 snap –ac 收集系統的 dump 信息。
core dump 信息收集
如果可能 , 直接在發生 coredump 的機器上用 dbx 分析出結果 , 這樣是最方便的分析方法 . 這種情況下注意不要直接以 root 用戶登錄然后用 dbx 分析 , 而必須在應用程序所屬的用戶下進行此操作 , 因為 core 可能需要依賴應用程序運行時對應環境下的某些庫 , 這樣就要借助應用程序的環境變量 .
如果需取回生產機上的 core 信息在實驗室分析 , 則需要搜集一些相關信息 . 進程 core 分析一般至少需要依賴應用可執行程序,有時還需要包括一些運行時動態庫信息。如果需要收集 core 相關的完整信息,可運行 snapcore <core 路徑以及名稱 > < 可執行文件以及名稱 >,例如 snapcore ./core ./a.out,然后在 /tmp/snapcore 下取下相應的 .pax.Z 文件。
正常的收集過程應該如下 :
snap core 收集過程
# snapcore ./core ./a.out Core file "./core" created by "a.out"
pass1() in progress ....
Calculating space required .
Total space required is 14130 kbytes ..
Checking for available space ...
Available space is 807572 kbytes
pass1 complete.
pass2() in progress ....
Collecting fileset information .
Collecting error report of CORE_DUMP errors ..
Creating readme file ..
Creating archive file ...
Compressing archive file ....
pass2 completed.
Snapcore completed successfully. Archive created in /tmp/snapcore.
# cd /tmp/snapcore # ls snapcore_352276.pax.Z # uncompress snapcore_352276.pax.Z # ls snapcore_352276.pax # pax -r -f snapcore_352276.pax # ls 注意需要保證有類似如下文件 ( 可執行文件,/core/errpt/lslpp/usr 目錄等 ): README errpt.out usr a.out lslpp.out core snapcore_352276.pax #
|
II 使用 dbx 分析 core dump 的例子
dbx 是 AIX 下基於命令行界面的源碼級調試工具。本文檔只提供一些基本的 dbx 分析指令,詳細內容請參考“General Programming Concepts: Writing and Debugging Programs”關於 dbx 的描述。
初步分析
示例:
# dbx ./test core Type 'help' for help. warning: The core file is not a fullcore. Some info may not be available. [using memory image in core] reading symbolic information ...warning: no source compiled with -g
Segmentation fault in raise at 0xd022e1e4 0xd022e1e4 (raise+0x40) 80410014 lwz r2,0x14(r1)
|
顯示出 core 發生時,當前進程執行到的位置(-g 編譯的情況下能夠看到具體的行):
(dbx) where raise(??) at 0xd022e1e4 main(0x1, 0x2ff22d48) at 0x100019c4
|
注意:
如果分析的是異地 core 文件,需要采用 snapcore 收集相關 core 信息。對於依賴鏈接庫的情況,注意需要增加 -p ldpath=newpath:...
重新設置鏈接庫路徑(只有所有依賴的庫都已經被鏈接,才能完整的復現 core dump 故障現場),參考 dbx 的幫助文檔獲取更多信息。
# cd /tmp/snapcore # dbx –p /=./ a.out core Type 'help' for help. [using memory image in core] reading symbolic information ...warning: no source compiled with -g
IOT/Abort trap in raise at 0xd01f4f60 0xd01f4f60 (raise+0x40) 80410014 lwz r2,0x14(r1)
|
列舉源碼信息
列舉程序源碼(list,需要在運行 dbx 命令時使用 -I 指明源碼搜索路徑,並使用 -g 編譯)或者匯編碼(listi):
(dbx) listi main 0x10001924 (main) 7c0802a6 mflr r0 0x10001928 (main+0x4) bfa1fff4 stmw r29,-12(r1) 0x1000192c (main+0x8) 90010008 stw r0,0x8(r1) 0x10001930 (main+0xc) 9421ffa0 stwu r1,-96(r1) 0x10001934 (main+0x10) 83e20064 lwz r31,0x64(r2) 0x10001938 (main+0x14) 90610078 stw r3,0x78(r1) 0x1000193c (main+0x18) 9081007c stw r4,0x7c(r1) 0x10001940 (main+0x1c) 83a20068 lwz r29,0x68(r2)
|
列舉變量內容
示例代碼:
#include <iostream> #include <signal.h> int g_test =0;
int testfunc(int ¶) { para++; return 0; }
int main(int argc, char* argv[]) { struct sigaction s; s.sa_handler = SIG_DFL; s.sa_mask.losigs = 0; s.sa_mask.hisigs = 0; s.sa_flags = SA_FULLDUMP; sigaction(SIGSEGV,&s,(struct sigaction *) NULL);
char str[10]; g_test =0;
testfunc(g_test); abort(); } # xlC test.C -g
|
以全局變量 g_test 舉例:
#print g_test 顯示 g_test 的取值
#print sizeof(g_test) 顯示 g_test 的大小
#whatis g_test 顯示 g_test 的類型
#print &g_test 顯示 g_test 的地址
#&g_test/16x 顯示從 g_test 的地址開始處,連續 16 個 WORD(?byte)的取值
如果沒有使用 -g 編譯,則不能動態獲取 g_test 的類型、大小等信息,但能夠得到 g_test 的地址,並查詢該地址所在區域存儲空間的值。
例如:
# ./a.out IOT/Abort trap(coredump) # dbx ./a.out core Type 'help' for help. [using memory image in core] reading symbolic information ...
IOT/Abort trap in raise at 0xd03365bc 0xd03365bc (raise+0x40) 80410014 lwz r2,0x14(r1) (dbx) print g_test 1 (dbx) whatis g_test int g_test; (dbx) print sizeof(g_test) 4 (dbx) print &g_test 0x20000428 (dbx) &g_test/16x 0x20000428: 0000 0001 0000 0000 0000 0000 0000 0000 0x20000438: 0000 0000 0000 0000 0000 0000 0000 0000
|
列舉寄存器內容
列舉寄存器內容:
(dbx) registers
如下模擬一個簡單的 core dump,對 0 地址賦值引發 core dump 的問題:
# dbx ./a.out core Type 'help' for help. warning: The core file is not a fullcore. Some info may not be available. [using memory image in core] reading symbolic information ...warning: no source compiled with -g
Segmentation fault in main at 0x10000348 0x10000348 (main+0x18) 90640000 stw r3,0x0(r4) (dbx) where main(0x1, 0x2ff22ccc) at 0x10000348 (dbx) registers $r0:0x00000000 $stkp:0x2ff22bf0 $toc:0x20000414 $r3:0x00000012 $r4:0x00000000 $r5:0x2ff22cd4 $r6:0xdeadbeef $r7:0x2ff22ff8 $r8:0x00000000 $r9:0x04030000 $r10:0xf0577538 $r11:0xdeadbeef $r12:0xdeadbeef $r13:0xdeadbeef $r14:0x00000001 $r15:0x2ff22ccc $r16:0x2ff22cd4 $r17:0x00000000 $r18:0xdeadbeef $r19:0xdeadbeef $r20:0xdeadbeef $r21:0xdeadbeef $r22:0xdeadbeef $r23:0xdeadbeef $r24:0xdeadbeef $r25:0xdeadbeef $r26:0xdeadbeef $r27:0xdeadbeef $r28:0xdeadbeef $r29:0xdeadbeef $r30:0xdeadbeef $r31:0xdeadbeef $iar:0x10000348 $msr:0x0000d0b2 $cr:0x22282489 $link:0x100001b4 $ctr:0xdeadbeef $xer:0x20000020 Condition status = 0:e 1:e 2:e 3:l 4:e 5:g 6:l 7:lo [unset $noflregs to view floating point registers] [unset $novregs to view vector registers] in main at 0x10000348 0x10000348 (main+0x18) 90640000 stw r3,0x0(r4) (dbx) print $r3 0x00000012 (dbx) print $r4 (nil)
|
這個例子比較簡單,從最后匯編指令“stw r3,0x0(r4)”就可以簡單的看到程序 core dump 是因為向 0 地址(0+r4)存入 18(r3 寄存器值)造成。
查看多線程相關信息
如果以下環境變量采用默認的 OFF 值,則系統會完全禁止適當的調試列表,這意味着 dbx 命令將顯示不出任何對象:
AIXTHREAD_MUTEX_DEBUG
AIXTHREAD_COND_DEBUG
AIXTHREAD_RWLOCK_DEBUG
可以使用
export AIXTHREAD_MUTEX_DEBUG=ON
打開 AIXTHREAD_MUTEX_DEBUG。
- 查看線程信息
(dbx) print $t1 // 打印 t1 線程的基本信息
(dbx) attribute
(dbx) condition
(dbx) mutex
(dbx) rwlock
(dbx) thread
例如:
(thread_id = 1, state_u = 4, priority = 60, policy = other, attributes = 0x20001078)
- 切換當前線程(默認當前線程為收到 core 觸發信號所在線程)
(dbx) thread current [tid]
例如(> 表明 core dump 時的當前線程):
(dbx)thread thread state-k wchan state-u k-tid mode held scope function $t1 wait 0x31bbb558 running 10321 k no pro _ptrgl $t2 wait 0x311fb958 running 6275 k no pro _ptrgl >$t3 run running 6985 k no pro _p_nsleep $t4 wait 0x31bbbb18 running 6571 k no pro _ptrgl $t5 wait 0x311fb9d8 running 7999 k no pro _ptrgl $t6 wait 0x31bf8f98 running 8257 k no pro _ptrgl $t7 wait 0x311fba18 running 8515 k no pro _ptrgl $t8 wait 0x311fb7d8 running 8773 k no pro _ptrgl $t9 wait 0x311fbb18 running 9031 k no pro _ptrgl $t10 wait 0x311fb898 running 9547 k no pro _ptrgl $t11 wait 0x311fb818 running 9805 k no pro _ptrgl $t12 wait 0x311fba58 running 10063 k no pro _ptrgl $t13 wait 0x311fb8d8 running 10579 k no pro _ptrgl (dbx) thread current 3 (dbx) where _p_nsleep(??, ??) at 0xd005f740 raise.nsleep(??, ??) at 0xd022de3c sleep(??) at 0xd0260344 helper(??) at 0x100005ac (dbx) thread current 4 warning: Thread is in kernel mode, not all registers can be accessed. (dbx) where ptrgl._ptrgl() at 0xd020e470 raise.nsleep(??, ??) at 0xd022de3c raise.nsleep(??, ??) at 0xd022de3c sleep(??) at 0xd0260344 helper(??) at 0x100005ac (dbx)
|
core dump 分析的局限性
不要期待能依賴 core dump 分析解決所有的問題,下面是一個簡單的模擬緩沖區溢出的例子,在這個例子中由於緩沖區溢出覆蓋了調用棧信息,從而完全丟失了定位依據:
root@/tmp#>xlC test.C -g -o test2 root@/tmp#> root@/tmp#>./test input str!
012345678901234567890123456789 Segmentation fault(coredump) root@/tmp#>dbx ./test2 core Type 'help' for help. [using memory image in core] reading symbolic information ...
Segmentation fault in test2. at 0x34353634 0x34353634 (???) warning: Unable to access address 0x34353634 from core (dbx) where warning: Unable to access address 0x34353634 from core warning: Unable to access address 0x34353634 from core warning: Unable to access address 0x34353630 from core warning: Unable to access address 0x34353630 from core warning: Unable to access address 0x34353634 from core warning: Unable to access address 0x34353634 from core warning: Unable to access address 0x34353630 from core warning: Unable to access address 0x34353630 from core warning: Unable to access address 0x34353634 from core warning: Unable to access address 0x36373841 from core test2.() at 0x34353634 warning: Unable to access address 0x36373839 from core warning: Unable to access address 0x36373839 from core (dbx)
|

 |

|
系統 dump 分析
環境變量設置
可以通過“sysdumpdev –l”查看系統當前的 dump 配置信息:
root@/#>sysdumpdev -l primary /dev/hd6 secondary /dev/sysdumpnull copy directory /var/adm/ras forced copy flag TRUE always allow dump FALSE dump compression ON
|
注意舊版本的 AIX “always allow dump”可能默認為關閉;為方便系統 crash 時問題定位,建議打開,可使用命令 sysdumpdev –K 或者使用 smitty -> System Environments-> Change / Show Characteristics of System Dump 菜單設置。
sysdumpdev –L 獲得最近系統產生的 dump 的相關統計信息:
#>sysdumpdev -L 0453-039 Device name: /dev/hd6 Major device number: 10 Minor device number: 2 Size: 18885120 bytes Uncompressed Size: 113724523 bytes Date/Time: Sat Jul 21 14:20:22 BEIST 2007 Dump status: 0 dump completed successfully Dump copy filename: /var/adm/ras/vmcore.2.Z
|
為保證系統出現 crash 時,dump device 能夠保存下 dump 信息,需要合理的配置 dump device 的大小,可以使用 sysdumpdev –e 估計系統 dump 需要的空間。一般推薦的 dump device 值大小為 sysdumpdev –e 估計值的 1.5 倍。
環境變量設置
本文檔只提供一些基本的 dump 分析指令,詳細內容請參考“KDB kernel debugger and kdb command ”。
初步分析
kdb 對 dump 文件分析需要借助於產生 dump 的內核文件 /unix,一般 snap –ac 會對此文件進行收集。初步命令如下:
#kdb ./dump ./unix
示例:
#kdb ./dump ./unix The specified kernel file is a 64-bit kernel ./dump mapped from @ 700000000000000 to @ 70000007da53bd5 Preserving 1317350 bytes of symbol table First symbol __mulh Component Names: 1) minidump [2 entries] 2) dmp_minimal [9 entries] 3) proc [481 entries] 4) thrd [1539 entries] 5) rasct [1 entries] 6) ldr [2 entries] 7) errlg [3 entries] 8) mtrc [26 entries] 9) lfs [1 entries] 10) bos [2 entries] 11) ipc [7 entries] 12) vmm [13 entries] 13) alloc_kheap [256 entries] 14) alloc_other [26 entries] 15) rtastrc [8 entries] 16) efcdd [20 entries] 17) eidedd [1 entries] 18) sisraid [2 entries] 19) aixpcm [5 entries] 20) scdisk [11 entries] 21) lvm [2 entries] 22) jfs2 [1 entries] 23) tty [4 entries] 24) netstat [10 entries] 25) goent_dd [7 entries] 26) scsidisk [11 entries] 27) efscsi [5 entries] 28) dump_statistics [1 entries] Component Dump Table has 2456 entries START END <name> 0000000000001000 0000000003BBA050 start+000FD8 F00000002FF47600 F00000002FFDC920 __ublock+000000 000000002FF22FF4 000000002FF22FF8 environ+000000 000000002FF22FF8 000000002FF22FFC errno+000000 F100070F00000000 F100070F10000000 pvproc+000000 F100070F10000000 F100070F18000000 pvthread+000000 PFT: PVT: id....................0002 raddr.....0000000000686000 eaddr.....F200800030000000 size..............00040000 align.............00001000 valid..1 ros....0 fixlmb.1 seg....0 wimg...2 Dump analysis on CHRP_SMP_PCI POWER_PC POWER_5 machine with 8 available CPU(s) (64-bit registers) Processing symbol table... .......................done
|
分析命令示例
status 查看各個 CPU 在 dump 時正在運行的進程,如:
0)> status CPU TID TSLOT PID PSLOT PROC_NAME 0 2580F5 600 14C0F6 332 cron 1 12025 18 D01A 13 wait 2 1020BB 258 1580C6 344 expr 3 1502B 21 F01E 15 wait
|
cpu <id> 命令切換當前 CPU,默認的當前 CPU 為 cpu0:
(0)> cpu 1
(1)>
打印系統的基本狀態和相關信息:
(0)> stat
打印系統 dump 時內核棧的情況:
(0)> f
lke 用來列出內核代碼對應的相關系統文件信息:
(0)> lke 003DE9CC
顯示系統 dump 時最后所在的指令:
(0)> dr iar
顯示虛擬存儲管理的日志信息;其中 Exception value 若為 0000001C 則表示 pagingspace 耗盡:
(0)> vmlog
顯示進程表的信息:
(0)> proc
顯示線程表的信息:
(0)> th
顯示系統的 errpt 信息:
(0)> errpt
ERRORS NOT READ BY ERRDEMON (ORDERED CHRONOLOGICALLY):
Error Record:
erec_flags .............. 1
erec_len ................ 54
erec_timestamp .......... 46DCDD9D
erec_rec_len ............ 34
erec_dupcount ........... 0
erec_duptime1 ........... 0
erec_duptime2 ........... 0
erec_rec.error_id ....... DD11B4AF
erec_rec.resource_name .. SYSPROC
00007FFF FFFFD000 00000000 003DE9CC .............=..
00000000 00020000 80000000 000290B2 ................