2016/12/11

如何開啟 Microsoft Windows 的 crashdump


1. 事前準備


1-1 Enable Windows Error Reporting Service

    1.  執行 "services.msc".
    2.  找到 "Windows Error Reporting Service"
    3.  啟動(Enable it).


1-2- Configure Registry

    1. 執行 "regedit.exe"
    2. 在以下路徑新增名為 "LocalDumps" 的 key:
 "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting".
    3. 在上述新增的鍵(Key) ("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps") ,新增三個鍵值 :
         (1)
           Type: REG_EXPAND_SZ
           Name: DumpFolder
           Data: c:\coredump   <<<< 自行決定要存在哪
         (2)
           Type: DWORD
           Name: DumpCount
           Data: 0xa                <<<< 自行決定最多產生幾個檔案(此例為10, 產生第11個檔案時,最舊的就會被刪掉)
         (3)
           Type: DWORD
           Name: DumpType
           Data: 0x2

1-3 安裝 WinDbg (Debugging Tools for Windows)

  1. 到微軟的官網下載 debugging tool,
https://developer.microsoft.com/en-us/windows/hardware/windows-driver-kit
  2. 參考 "Get debugging tools" 節,安裝 WinDbg。

1-4 造出 pdb file

  1. 在編譯執行檔時,必須在 Makefile 加上 "-g" option.
  2. 執行以下指令:
    # cv2pdb.exe -C /path/to/exe/file/helloworld.exe
  pbd file: helloworld.pdb 在產生在 /path/to/exe/file 這個路徑。
 
  注意 e:
    You should make a pdb file from executing binary.
    If you make pdb file from another binary, it can't use to debug even if it compiled from same code.
    exe file have unique hash value. WinDbg checks this ID to identify pbd file.

2. 分析 Dump 出來的資料

2-1. Launch WinDbg(x64).
2-2. Press "File > Symbol File Path..." in menu bar.
2-3. Input follows to "Symbol path:" text box.
   SRV*c:\symbols*http://msdl.microsoft.com/download/symbols

2-4. 若有 pdb file, 把它加進來,例:
   SRV*c:\symbols*http://msdl.microsoft.com/download/symbols;path/to/pbd/file
2-5. Open crash dump file.
   (Press "File > Open Crash Dump" in menu bar and select crash dump file)

2-6. 執行以下指令:
   > !analyze -v   (Exception Analysis will be started)

6. 將會顯示分析的結果。

3. 如何看懂分析的結果

3-1 Stack analysis (Call trace analysis)

 我們會需要 symbol table,即 pdb file 以解析函數名稱,記憶體位址等等資訊。(見 2-4 把 pdb 加進來)

若沒有 pdb ,則要花比較大的功夫來看懂 output 的內容; We need to make a object dump and search function address from dump file.

3-2. Check STACK_TEST section,

--- Example ---

STACK_TEXT: 
00000000`02dbda10 00000000`63ddd2a4 : 00000000`0023ae88 00007ffa`e1271fd2 00000000`63e00225 00000000`00000132 : msvcrt!abort+0x45
00000000`02dbdaa0 00000000`63ddd556 : 00000000`02dbe0e0 000001d2`36f33051 00000000`003fb347 00000000`0000cd50 : libmongoc_1_0_0!mongoc_server_description_new_copy+0xa20
00000000`02dbe000 00000000`63de05aa : 00000000`00000009 00000000`00000009 00000000`016cad20 00007ffa`d1971cbc : libmongoc_1_0_0!mongoc_socket_errno+0x1E
00000000`02dbe030 00000000`63ddec5b : 00000000`00000000 00000000`00000011 00000000`00000000 00000000`00840000 : libmongoc_1_0_0!mongoc_stream_gridfs_new+0x55a
....

--- End ---
沒有 pdb, WinDbg 只能猜測函數名稱可能為何,但通常是猜錯的。
因此,我們就得核對 stacked address 並從 dump file 中找出正確的 function name.


見第一行:
00000000`02dbda10 00000000`63ddd2a4 : 00000000`0023ae88 00007ffa`e1271fd2 00000000`63e00225 00000000`00000132 : msvcrt!abort+0x45
00000000`63ddd2a4 」 就是出現的點(位址) !!!
以此例,這個位址是屬於 libmongoc_1_0_0.dll 的範圍,因此接著要 dump libmongoc_1_0_0.dll 繼續追蹤。

3-3. Dump program


使用「objdump」指令 ( msys 裡應該有此指令)

# objdump -d /path/to/dump_file

3-4. Check address

以 3-2 看到的位址,查 function name.

--- part of libmongoc_1_0_0.dll dump file ---
0000000063ddd260 <mongoc_socket_errno.part.2>:  <- this is function name
    63ddd260:    48 83 ec 38              sub    $0x38,%rsp
    63ddd264:    ff 15 86 46 03 00        callq  *0x34686(%rip)        # 63e118f0 <__imp___iob_func>
    63ddd26a:    41 b9 32 01 00 00        mov    $0x132,%r9d
    63ddd270:    48 8d 48 60              lea    0x60(%rax),%rcx
    63ddd274:    48 8d 05 c5 2f 02 00     lea    0x22fc5(%rip),%rax        # 63e00240 <.rdata+0x60>
    63ddd27b:    4c 8d 05 a3 2f 02 00     lea    0x22fa3(%rip),%r8        # 63e00225 <.rdata+0x45>
    63ddd282:    48 89 44 24 28           mov    %rax,0x28(%rsp)
    63ddd287:    48 8d 05 e2 31 02 00     lea    0x231e2(%rip),%rax        # 63e00470 <__FUNCTION__.95423>
    63ddd28e:    48 8d 15 6b 2f 02 00     lea    0x22f6b(%rip),%rdx        # 63e00200 <.rdata+0x20>
    63ddd295:    48 89 44 24 20           mov    %rax,0x20(%rsp)
    63ddd29a:    e8 91 ff ff ff           callq  63ddd230 <fprintf.constprop.4>
    63ddd29f:    e8 44 ae 01 00           callq  63df80e8 <abort>
    63ddd2a4:    90                       nop
#   ^^^^^^^^ <- recorded address
    63ddd2a5:    66 66 2e 0f 1f 84 00     data16 nopw %cs:0x0(%rax,%rax,1)
    63ddd2ac:    00 00 00 00
--- End ---

提醒事項:
1. 若你找不到 symbol name, 你須要加上 "-g" 重新 compile 這個程式。記得不要有 "strip symbol" (通常是 "-s" 這個 option) 這個動作!

3-5. Repeat step 3-2 to step 3-4


(本文完)

沒有留言:

張貼留言