!analyze 擴展

本文轉自:http://hi.baidu.com/litomboy/item/1332cb96a8ac67f128164727

 

調試一個當機的目標計算機或應用程序,第一步是使用 !analyze 擴展命令。

該擴展執行大量的自動分析。分析結果在調試器命令窗口中顯示。

若要數據的全冗長模式顯示,你應該使用 -v 選項。關於其他選項更多細節,詳見 !analyze 參考頁。

這個主題包含:

用戶模式 !analyze -v 示例 

內核模式 !analyze -v 示例 

Followup字段和triage.ini文件 

輔助的 !analyze 技術 






用戶模式 !analyze -v 示例
本例中,調試器被附加到一個已遭遇異常的用戶模式應用程序。

0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

Debugger SolutionDb Connection::Open failed 80004005

如果計算機有連接英特網,調試器嘗試訪問一個由微軟維護的當機解決方案數據庫。這裏它顯示了一個錯誤信息,指出或是你的機器不能夠訪問英特網或是網站關閉。

FAULTING_IP: 
ntdll!PropertyLengthAsVariant+73
77f97704 cc               int     3

FAULTING_IP字段表示出現故障時的指令指針。

EXCEPTION_RECORD:  ffffffff -- (.exr ffffffffffffffff)
ExceptionAddress: 77f97704 (ntdll!PropertyLengthAsVariant+0x00000073)
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 3
   Parameter[0]: 00000000
   Parameter[1]: 00010101
   Parameter[2]: ffffffff

EXCEPTION_RECORD字段表示這次當機的異常記錄。也可以使用 .exr (顯示異常記錄) 命令查看該信息。

BUGCHECK_STR:  80000003

BUGCHECK_STR字段表示異常代碼。這個名稱使用不當 - 隱錯檢查bug check這個術語實際上表示是一個內核模式當機。在用戶模式調試中將顯示異常代碼 - 這裏是0x80000003。

DEFAULT_BUCKET_ID:  APPLICATION_FAULT

DEFAULT_BUCKET_ID字段表示故障所屬類別,這裏顯示是一般的故障。

PROCESS_NAME:  MyApp.exe

PROCESS_NAME字段說明引發異常的進程名字。

LAST_CONTROL_TRANSFER:  from 01050963 to 77f97704

LAST_CONTROL_TRANSFER字段表示在棧中最後的調用。這裏,在地址0x01050963處的代碼調用在0x77F97704處的一個函數。你可以使用ln (列出最近的符號)命令確定這些地址在什麼模塊和函數中。

STACK_TEXT:  
0006b9dc 01050963 00000000 0006ba04 000603fd ntdll!PropertyLengthAsVariant+0x73
0006b9f0 010509af 00000002 0006ba04 77e1a449 MyApp!FatalErrorBox+0x55 [D:\source_files\MyApp\util.c @ 541]
0006da04 01029f4e 01069850 0000034f 01069828 MyApp!ShowAssert+0x47 [D:\source_files\MyApp\util.c @ 579]
0006db6c 010590c3 000e01ea 0006fee4 0006feec MyApp!SelectColor+0x103 [D:\source_files\MyApp\colors.c @ 849]
0006fe04 77e11d0a 000e01ea 00000111 0000413c MyApp!MainWndProc+0x1322 [D:\source_files\MyApp\MyApp.c @ 1031]
0006fe24 77e11bc8 01057da1 000e01ea 00000111 USER32!UserCallWinProc+0x18
0006feb0 77e172b4 0006fee4 00000001 010518bf USER32!DispatchMessageWorker+0x2d0
0006febc 010518bf 0006fee4 00000000 01057c5d USER32!DispatchMessageA+0xb
0006fec8 01057c5d 0006fee4 77f82b95 77f83920 MyApp!ProcessQCQPMessage+0x3b [D:\source_files\MyApp\util.c @ 2212]
0006ff70 01062cbf 00000001 00683ed8 00682b88 MyApp!main+0x1e6 [D:\source_files\MyApp\MyApp.c @ 263]
0006ffc0 77e9ca90 77f82b95 77f83920 7ffdf000 MyApp!mainCRTStartup+0xff [D:\source_files\MyApp\crtexe.c @ 338]
0006fff0 00000000 01062bc0 00000000 000000c8 KERNEL32!BaseProcessStart+0x3d

STACK_TEXT字段表示出錯組件的一個棧跟蹤(回溯)。

FOLLOWUP_IP: 
MyApp!FatalErrorBox+55
01050963 5e               pop     esi

FOLLOWUP_NAME:  dbg

SYMBOL_NAME:  MyApp!FatalErrorBox+55

MODULE_NAME:  MyApp

IMAGE_NAME:  MyApp.exe

DEBUG_FLR_IMAGE_TIMESTAMP:  383490a9

當 !analyze 確定某指令可能引起錯誤的時候,就在FOLLOWUP_IP字段中顯示它。 SYMBOL_NAME、MODULE_NAME、IMAGE_NAME和DBG_FLR_IMAGE_TIMESTAMP字段表示這個指令相應的符號、模塊、映像名字和映像時間戳。

STACK_COMMAND:  .ecxr ; kb

STACK_COMMAND字段表示用來獲取STACK_TEXT的命令。你可以使用這個指令重複顯示這個棧跟蹤,或者改變它以獲得有關的棧信息。

BUCKET_ID:  80000003_MyApp!FatalErrorBox+55

BUCKET_ID字段表示當前故障所屬的特定故障類別。這個類別幫助調試器確定在分析輸出中所顯示的其他信息。

Followup: dbg
---------

關於FOLLOWUP_NAME和Followup字段的信息,請看"Followup字段和triage.ini文件" The Followup Field and the triage.ini File。

還可能出現其他一些字段:

如果控制被轉移給一個無效地址,那麼FAULTING_IP字段將會包含有這個無效地址。不是FOLLOWUP_IP字段,而是FAILED_INSTRUCTION_ADDRESS字段將顯示該地址上的反彙編碼,雖然反彙編碼可能是無意義的。在這種情形下,SYMBOL_NAME、MODULE_NAME、IMAGE_NAME和DBG_FLR_IMAGE_TIMESTAMP字段將指出這條指令的調用者。 
如果處理器失敗,你可能會看到SINGLE_BIT_ERROR、TWO_BIT_ERROR或POSSIBLE_INVALID_CONTROL_TRANSFER字段。 
如果內存崩潰看起來已經發生,CHKIMG_EXTENSION字段將說明應該使用 !chkimg 擴展命令來調查。 

內核模式 !analyze -v 示例

本例調試器被附加到一臺剛剛當機的計算機。

kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pagable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.

首先顯示的是隱錯檢查代碼和這一類隱錯檢查的有關信息。上面顯示的文本有些可能不適用於這個特定實例。關於每個隱錯檢查的更多細節,請看"隱錯檢查代碼參考" Bug Check Code Reference部分。

Arguments:
Arg1: 00000004, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: f832035c, address which referenced memory

其次顯示隱錯檢查參數。在每個參數之後都有描述。例如,第三個參數是1,它後面的註釋解釋這是表示一個寫操作失敗。

Debugging Details:
------------------

WRITE_ADDRESS:  00000004 Nonpaged pool

CURRENT_IRQL:  2

下面幾個字段因當機類型而不同。這裏,我們看到WRITE_ADDRESS和CURRENT_IRQL字段。這些只是再次敘述在隱錯檢查參數中顯示的信息。通過比較這句“非頁池(Nonpaged pool)”和隱錯檢查文本“嘗試存取一個可分頁的(pagable) (或完全無效的)地址”,我們能夠看出該地址是無效的。在這裏,該無效地址是0x00000004。

FAULTING_IP: 
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204           mov     [edx+0x4],eax

FAULTING_IP字段表示出現故障時的指令指針。

DEFAULT_BUCKET_ID:  DRIVER_FAULT

DEFAULT_BUCKET_ID字段表示故障所屬類別,這裏顯示是一般的故障。

BUGCHECK_STR:  0xD1

BUGCHECK_STR字段表示隱錯檢查代碼,我們已經見到過。有些情況還附帶額外的優選(triage)信息。

TRAP_FRAME:  f8950dfc -- (.trap fffffffff8950dfc)
.trap fffffffff8950dfc
ErrCode = 00000002
eax=81cc86dc ebx=81cc80e0 ecx=81e55688 edx=00000000 esi=81cc8028 edi=8052cf3c
eip=f832035c esp=f8950e70 ebp=f8950e90 iopl=0         nv up ei pl nz ac po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010216
USBPORT!USBPORT_BadRequestFlush+7c:
f832035c 894204           mov     [edx+0x4],eax     ds:0023:00000004=????????
.trap
Resetting default context

TRAP_FRAME字段表示這次當機的陷阱框架。也可以使用 .trap (顯示陷阱框架)命令查看該信息。

LAST_CONTROL_TRANSFER:  from f83206e0 to f832035c

LAST_CONTROL_TRANSFER字段表示在棧中最後的調用。這裏,在地址0xF83206E0處的代碼調用在0xF832035C處的一個函數。你可以使用 ln (列出最近的符號)命令確定這些地址在什麼模塊和函數中。

STACK_TEXT:  
f8950e90 f83206e0 024c7262 00000000 f8950edc USBPORT!USBPORT_BadRequestFlush+0x7c
f8950eb0 804f5561 81cc8644 81cc8028 6d9a2f30 USBPORT!USBPORT_DM_TimerDpc+0x10c
f8950fb4 804f5644 6e4be98e 00000000 ffdff000 nt!KiTimerListExpire+0xf3
f8950fe0 8052c47c 8053cf20 00000000 00002e42 nt!KiTimerExpiration+0xb0
f8950ff4 8052c16a efdefd44 00000000 00000000 nt!KiRetireDpcList+0x31

STACK_TEXT字段表示出錯組件的一個棧跟蹤(回溯)。

FOLLOWUP_IP: 
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204           mov     [edx+0x4],eax

FOLLOWUP_IP字段表示可能引起錯誤的那條指令的反彙編。

FOLLOWUP_NAME:  usbtri

SYMBOL_NAME:  USBPORT!USBPORT_BadRequestFlush+7c

MODULE_NAME:  USBPORT

IMAGE_NAME:  USBPORT.SYS

DEBUG_FLR_IMAGE_TIMESTAMP:  3b7d868b

SYMBOL_NAME、MODULE_NAME、IMAGE_NAME和DBG_FLR_IMAGE_TIMESTAMP字段表示 (如果這條指令是有效的)與之相應的或者 (如果這條指令是無效的)與其調用者相應的符號、模塊、映像和映像時間戳。

STACK_COMMAND:  .trap fffffffff8950dfc ; kb

STACK_COMMAND字段表示用來獲取STACK_TEXT的命令。你可以使用這個命令重複顯示這個棧跟蹤裝置,或者改變它以獲得有關的棧信息。

BUCKET_ID:  0xD1_W_USBPORT!USBPORT_BadRequestFlush+7c

BUCKET_ID字段表示當前故障所屬的特定故障類別。這個類別幫助調試器確定在分析輸出中顯示的其他信息。

INTERNAL_SOLUTION_TEXT:  http://oca.microsoft.com/resredir.asp?sid=62&State=1

如果計算機有連接英特網,調試器嘗試訪問一個由微軟維護的當機解決方案數據庫。這個數據庫包含大量有關已知隱錯信息網頁的鏈接。如果找到一個與你的問題相匹配的,INTERNAL_SOLUTION_TEXT字段將顯示一個讓你可以獲取更多信息的網址。

Followup: usbtri
---------

      This problem has a known fix.
      Please connect to the following URL for details:
      ------------------------------------------------
      http://oca.microsoft.com/resredir.asp?sid=62&State=1

關於FOLLOWUP_NAME和Followup字段的信息,請看"Followup字段和triage.ini文件" The Followup Field and the triage.ini File:

還可能出現其他一些字段:

如果控制被轉移給一個無效地址,那麼FAULTING_IP字段將會包含有這個無效地址。不是FOLLOWUP_IP字段,而是FAILED_INSTRUCTION_ADDRESS字段將顯示該地址上的反彙編碼,雖然反彙編碼可能是無意義的。在這種情形下,SYMBOL_NAME、MODULE_NAME、IMAGE_NAME和DBG_FLR_IMAGE_TIMESTAMP字段將指出這條指令的調用者。 
如果處理器失敗,你可能會看到SINGLE_BIT_ERROR、TWO_BIT_ERROR或POSSIBLE_INVALID_CONTROL_TRANSFER字段。 
如果內存崩潰看起來已經發生,CHKIMG_EXTENSION字段將說明應該使用 !chkimg 擴展命令來調查。 
如果在一個驅動程序的代碼裏面發生隱錯檢查,它的名字可能會在BUGCHECKING_DRIVER字段中顯示。 

Followup字段和triage.ini文件
在用戶模式和內核模式中,如果能夠確定,顯示的Followup字段都將表示當前棧框架屬主的有關信息。該信息是以下面方式確定:


當 !analyze 擴展被使用的時候,調試器從棧中最頂的框架開始,確定它是否對錯誤負責。如果不是,就分析下一個框架。這個過程繼續直到找出一個可能出錯的框架。 
調試器嘗試確定這個框架裏模塊及函數的屬主。如果屬主能夠被確定,就認爲這個框架有錯。 
如果屬主不能夠被確定,調試器轉到下一個棧框架,等等,直到屬主被確定 (或者棧全部檢查完)。搜索中第一個找到屬主的框架被認爲有錯。如果棧完了還沒有找到的任何信息,則不顯示Followup字段。 
故障框架的屬主在Followup字段中顯示。如果使用 !analyze -v,那麼FOLLOWUP_IP、SYMBOL_NAME、MODULE_NAME、IMAGE_NAME和DBG_FLR_IMAGE_TIMESTAMP字段將會指出這個框架。 

若要讓Followup字段顯示有用的信息,你必須先創建一個包含模塊和函數屬主名字的triage.ini文件。

triage.ini文件應該標識出所有可能出錯模塊的屬主。你可以使用一個信息字符串而不是使用實際的屬主,但是這個字符串不能夠包含空格。如果你確信一個模塊不會有故障,那麼可以省略這個模塊或指示應該略過它。給出一個較好的優選處理尺度,指定個別函數的屬主也是可能的。

關於triage.ini文件的語法,詳見"指明模塊和函數屬主"Specifying Module and Function Owners。

輔助的 !analyze 技術
如果認爲BUCKET_ID是不正確的,你可以使用帶 -D 參數 !analyze 重寫存儲桶選擇(bucket choice)。

如果沒有發生當機或異常,!analyze 將會顯示一個很簡短的文本給出目標的當前狀態。在某種情況下,你可能想強迫它象在發生當機的情況下一樣進行分析。使用 !analyze - f 完成這個任務。

在用戶模式中,如果一個異常已經發生,而你認爲問題潛在於一個掛起的線程,那麼把當前線程設置爲你要調查的線程,然後使用 !analyze -hang。這個擴展將會執行一個線程棧分析以確定是不是有哪些線程正在阻塞其他線程。

在內核模式中,如果一個隱錯檢查已經發生,而你認爲問題潛在於一個掛起的線程,那麼使用 !analyze -hang。這個擴展將會調查系統所持有的鎖,並且掃描 DPC 隊列鏈,然後將顯示任何掛起線程的指示。如果你認爲問題在於一個內核模式的資源死鎖,那麼與驅動程序驗證器(Driver Verifier)的死鎖檢測Deadlock Detection選項一起使用 !deadlock 擴展。

你也可以自動忽略已知的問題。若要這樣做,你必須先創建一個含有已知問題格式化列表的XML文件(可擴展標記語言)。使用 !analyze -c -load KnownIssuesFile 擴展裝載這個文件。然後在一個異常或中斷髮生的時候,使用 !analyze -c 擴展。如果該異常匹配某個已知問題,目標將會恢復運行。如果目標沒有恢復運行,那麼你就可以使用 !analyze - v 確定該問題的起因。XML文件樣例能夠在調試器安裝目錄的 sdk\samples\analyze_continue 子目錄中找到。 (你必須先執行Debugging Tools for Windows的完整安裝,纔會有這個文件。詳見"調試器安裝"Debugger Installation)。

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