驗證符號

符號問題可能會以各種方式顯示。 或許堆疊追蹤會顯示不正確的資訊,或無法識別堆疊中函式的名稱。 或者,偵錯工具命令可能無法瞭解模組、函式、變數、結構或資料類型的名稱。

如果您懷疑偵錯工具未正確載入符號,您可以採取數個步驟來調查此問題。

首先,使用 lm (List Loaded Modules) 命令,以符號資訊顯示載入的模組清單。 此命令最實用的形式如下:

0:000> lml 

如果您使用 WinDbg,偵錯 |模組 功能表命令也可讓您查看這項資訊。

請特別注意您可能會在這些顯示中看到的任何附注或縮寫。 如需這些的解譯,請參閱 符號狀態縮寫

如果您沒有看到適當的符號檔,第一件事就是檢查符號路徑:

0:000> .sympath
Current Symbol Path is: d:\MyInstallation\i386\symbols\retail

如果您的符號路徑錯誤,請加以修正。 如果您使用核心偵錯工具,請確定您的本機 %WINDIR% 不在符號路徑上。

然後使用 .reload (重載模組) 命令重載符號:

0:000> .reload ModuleName 

如果您的符號路徑正確,您應該啟用 雜訊模式 ,以便查看正在載入的符號檔 dbghelp 。 然後重載模組。 如需如何啟用雜訊模式的詳細資訊,請參閱 設定符號選項

以下是 Microsoft Windows 符號的「雜訊」重載範例:

kd> !sym noisy
kd> .reload nt
 1: Kernel Version 2081 MP Checked
 2: Kernel base = 0x80400000 PsLoadedModuleList = 0x80506fa0
 3: DBGHELP: FindExecutableImageEx-> Looking for D:\MyInstallation\i386\ntkrnlmp.exe...mismatched timestamp
 4: DBGHELP: No image file available for ntkrnlmp.exe
 5: DBGHELP: FindDebugInfoFileEx-> Looking for
 6: d:\MyInstallation\i386\symbols\retail\symbols\exe\ntkrnlmp.dbg... no file
 7: DBGHELP: FindDebugInfoFileEx-> Looking for
 8: d:\MyInstallation\i386\symbols\retail\symbols\exe\ntkrnlmp.pdb... no file
 9: DBGHELP: FindDebugInfoFileEx-> Looking for d:\MyInstallation\i386\symbols\retail\exe\ntkrnlmp.dbg... OK
10: DBGHELP: LocatePDB-> Looking for d:\MyInstallation\i386\symbols\retail\exe\ntkrnlmp.pdb... OK
11: *** WARNING: symbols checksum and timestamp is wrong 0x0036a4ea 0x00361a83 for ntkrnlmp.exe

符號處理常式會先尋找符合其嘗試 (載入第三行和第四行) 之模組的影像。 影像本身不一定必要,但如果存在不正確的影像,符號處理常式通常會失敗。 這幾行顯示偵錯工具在 D:\MyInstallation\i386\ntkrnlmp.exe找到影像,但時間戳記不符合。 因為時間戳記不符合,所以搜尋會繼續。 接下來,偵錯工具會尋找符合已載入映射的 .dbg 檔案和 .pdb 檔案。 這些位於第 6 到 10 行。 第 11 行表示即使已載入符號,影像的時間戳記與 (不符,也就是說,符號) 錯誤。

如果符號搜尋發生重大失敗,您會看到表單的訊息:

ImgHlpFindDebugInfo(00000000, module.dll, c:\MyDir;c:\SomeDir, 0823345, 0) failed

這可能是由檔案系統失敗、網路錯誤和損毀 .dbg 檔案等專案所造成。

診斷符號載入錯誤

在雜訊模式中時,偵錯工具可能會在無法載入符號檔時列印出錯誤碼。 .dbg 檔案的錯誤碼會列在 winerror.h 中。 .pdb 錯誤碼來自另一個來源,最常見的錯誤會以純英文文字列印。

來自 winerror.h 之 .dbg 檔案的一些常見錯誤碼如下:

0xB
ERROR_BAD_FORMAT

0x3
ERROR_PATH_NOT_FOUND

0x35
ERROR_BAD_NETPATH

符號檔可能因為網路錯誤而無法載入。 如果您看到ERROR_BAD_FORMAT或ERROR_BAD_NETPATH,而且正在從網路上的另一部電腦載入符號,請嘗試將符號檔複製到主機電腦,並將其路徑放在您的符號路徑中。 然後嘗試重載符號。

驗證您的搜尋路徑和符號

讓 「c:\MyDir;c:\SomeDir「 代表您的符號路徑。 您應該在哪裡尋找偵錯資訊?

如果二進位檔已移除偵錯資訊,例如 Windows 的免費組建,請先在下列位置尋找 .dbg 檔案:

c:\MyDir\symbols\exe\ntoskrnl.dbg
c:\SomeDir\symbols\exe\ntoskrnl.dbg
c:\MyDir\exe\ntoskrnl.dbg
c:\SomeDir\exe\ntoskrnl.dbg
c:\MyDir\ntoskrnl.dbg
c:\SomeDir\ntoskrnl.dbg
current-working-directory\ntoskrnl.dbg

接下來,在下列位置尋找 .pdb 檔案:

c:\MyDir\symbols\exe\ntoskrnl.pdb
c:\MyDir\exe\ntoskrnl.pdb
c:\MyDir\ntoskrnl.pdb
c:\SomeDir\symbols\exe\ntoskrnl.pdb
c:\SomeDir\exe\ntoskrnl.pdb
c:\SomeDir\ntoskrnl.pdb
current-working-directory\ntoskrnl.pdb

請注意,在搜尋 .dbg 檔案中,偵錯工具會交錯搜尋 MyDir 和 SomeDir 目錄,但在 .pdb 搜尋中則不會。

Windows XP 和更新版本的 Windows 不會使用任何 .dbg 符號檔。 如需詳細資訊 ,請參閱符號和符號檔

不相符的組建

在機器上偵錯失敗最常見的問題之一,通常是不同組建的符號不符。 此問題的三個常見原因是:指向錯誤組建的符號、使用私用建置的二進位檔而不使用對應的符號,以及使用單處理器硬體抽象層級, (HAL) 和多處理器電腦上的核心符號。 前兩個只是比對二進位檔和符號的問題;第三個可以藉由將 hal*.dbg 和 ntkrnlmp.dbg 重新命名為 hal.dbg 和 ntoskrnl.dbg 來更正。

若要找出目的電腦上安裝的 Windows 組建,請使用 vertarget (顯示目的電腦版本) 命令:

kd> vertarget 
Windows XP Kernel Version 2505 UP Free x86 compatible
Built by: 2505.main.010626-1514
Kernel base = 0x804d0000 PsLoadedModuleList = 0x80548748
Debug session time: Mon Jul 02 14:41:11 2001
System Uptime: 0 days 0:04:53 

測試符號

測試符號比較困難。 它牽涉到驗證偵錯工具上的堆疊追蹤,並查看偵錯輸出是否正確。 以下是一個嘗試的範例:

kd> u videoprt!videoportfindadapter2
Loading symbols for 0xf2860000     videoprt.sys ->   videoprt.sys

VIDEOPRT!VideoPortFindAdapter2:
f2856f42 55               push    ebp
f2856f43 8bec             mov     ebp,esp
f2856f45 81ecb8010000     sub     esp,0x1b8
f2856f4b 8b4518           mov     eax,[ebp+0x18]
f2856f4e 53               push    ebx
f2856f4f 8365f400         and     dword ptr [ebp-0xc],0x
f2856f53 8065ff00         and     byte ptr [ebp-0x1],0x0
f2856f57 56               push    esi

u命令會將 videoportfindadapter 字串取消組譯為 videoprt.sys。 偵錯工具上的符號正確,因為 推送移動 等常見堆疊命令會顯示在堆疊上。 大部分函式都是使用基本指標 (ebp) 或 esp) 堆疊 (指標來開始新增、子或推送作業。

當符號無法正確運作時,通常很明顯。 Glintmp.sys 在此範例中沒有符號,因為 Glintmp旁未列出函式:

kd> kb
Loading symbols for 0xf28d0000     videoprt.sys ->   videoprt.sys
Loading symbols for 0xf9cdd000      glintmp.sys ->   glintmp.sys
*** ERROR: Symbols could not be loaded for glintmp.sys
ChildEBP RetAddr  Args to Child
f29bf1b0 8045b5fa 00000001 0000a100 00000030 ntoskrnl!RtlpBreakWithStatusInstruction
f29bf1b0 8044904e 00000001 0000a100 00000030 ntoskrnl!KeUpdateSystemTime+0x13e
f29bf234 f28d1955 f9b7d000 ffafb2dc f9b7d000 ntoskrnl!READ_REGISTER_ULONG+0x6
f29bf248 f9cde411 f9b7d000 f29bf2b0 f9ba0060 VIDEOPRT!VideoPortReadRegisterUlong+0x27
00000002 00000000 00000000 00000000 00000000 glintMP+0x1411 [No function listed.] 

已為此堆疊追蹤載入錯誤的組建符號。 請注意,前兩個呼叫中沒有列出的函式。 此堆疊追蹤看起來像 win32k.sys 繪圖矩形的問題:

1: kd> 
1: kd> kb                      [Local        9:50 AM]
Loading symbols for 0xf22b0000       agpcpq.sys ->   agpcpq.sys
*** WARNING: symbols checksum is wrong 0x0000735a 0x00000000 for agpcpq.sys
*** ERROR: Symbols could not be loaded for agpcpq.sys
Loading symbols for 0xa0000000       win32k.sys ->   win32k.sys
*** WARNING: symbols checksum is wrong 0x00191a41 0x001995a9 for win32k.sys
ChildEBP RetAddr  Args to Child
be682b18 f22b372b 82707128 f21c1ffc 826a70f8 agpCPQ+0x125b [No function listed.]
be682b4c a0140dd4 826a72f0 e11410a8 a0139605 agpCPQ+0x372b [No function listed.]
be682b80 a00f5646 e1145100 e1cee560 e1cee560 win32k!vPatCpyRect1_6x6+0x20b
00000001 00000000 00000000 00000000 00000000 win32k!RemoteRedrawRectangle+0x32 

以下是正確的堆疊追蹤。 問題真的是 AGP440.sys。 堆疊追蹤上出現的第一個專案通常是錯誤。 請注意,win32k.sys 矩形錯誤已消失:

1: kd> kb                      [Local        9:49 AM]
ChildEBP RetAddr  Args to Child
be682b18 f22b372b 82707128 f21c1ffc 826a70f8 agpCPQ!AgpReleaseMemory+0x88
be682b30 f20a385c 82703638 e183ec68 00000000 agpCPQ!AgpInterfaceReleaseMemory+0x8b
be682b4c a0140dd4 826a72f0 e11410a8 a0139605 VIDEOPRT!AgpReleasePhysical+0x44
be682b58 a0139605 e1cee560 e11410a8 a00e5f0a win32k!OsAGPFree+0x14
be682b64 a00e5f0a e1cee560 e11410a8 e1cee560 win32k!AGPFree+0xd
be682b80 a00f5646 e1145100 e1cee560 e1cee560 win32k!HeapVidMemFini+0x49
be682b9c a00f5c20 e1cee008 e1cee008 be682c0c win32k!vDdDisableDriver+0x3a
be682bac a00da510 e1cee008 00000000 be682c0c win32k!vDdDisableDirectDraw+0x2d
be682bc4 a00da787 00000000 e1843df8 e1843de8 win32k!PDEVOBJ__vDisableSurface+0x27
be682bec a00d59fb 00000000 e1843de8 00000000 win32k!PDEVOBJ__vUnreferencePdev+0x204
be682c04 a00d7421 e1cee008 82566a98 00000001 win32k!DrvDestroyMDEV+0x30
be682ce0 a00a9e7f e1843e10 e184a008 00000000 win32k!DrvChangeDisplaySettings+0x8b3
be682d20 a008b543 00000000 00000000 00000000 win32k!xxxUserChangeDisplaySettings+0x106
be682d48 8045d119 00000000 00000000 00000000 win32k!NtUserChangeDisplaySettings+0x48
be682d48 77e63660 00000000 00000000 00000000 ntkrnlmp!KiSystemService+0xc9 

有用的命令和延伸模組

下列命令和延伸模組在追蹤符號問題時可能很有用:

lm (列出載入的模組)
列出所有模組,並提供這些模組中所有符號的載入狀態。

!dh image-header-base
顯示從 image-header-base開始載入之影像的標頭資訊。

.reload /n
重載所有核心符號。

.reload [image-name]
(CDB 或 WinDbg 只會) 重載 映射名稱的符號。 如果未指定 任何影像名稱 ,則會重載所有影像的符號。 (變更符號路徑之後,必須重載符號。)

!sym noisy
開啟符號載入的詳細資訊模式。 這可用來取得模組載入的相關資訊。 如需詳細資訊,請參閱 設定符號選項

.sympath [new-symbol-path]
設定新的符號路徑,或顯示目前的符號路徑。 如需詳細資訊,請參閱 符號路徑

如果核心符號正確,但您未取得完整的堆疊,下列命令可能也很有用:

X*!
這會列出目前已載入符號的模組。 如果核心符號正確,這會很有用。

.reload /user
這會嘗試重載所有使用者模式符號。 如果在某個進程執行時載入符號,而稍後在另一個進程中發生中斷,則執行核心偵錯時需要此專案。 在此情況下,除非執行此命令,否則不會載入來自新進程的使用者模式符號。

X wdmaud!*start\*
這只會列出名稱包含 「start」 字串之 wdmaud 模組中的符號。 這有一個優點,它強制 在 wdmaud中重載所有符號,但只會在 wdmaud 中顯示具有「start」 的符號。 (這表示較短的清單,但因為其中一定有一些符號具有「開始」,所以會有一些驗證已執行負載。)

另一種驗證符號的實用技術是取消組譯程式碼。 大部分的函式都是使用 ebp) (的基底指標 (或 espsp) ,從新增、子或推送作業開始。 嘗試將 (U 函 式解除組譯) 堆疊上的某些函式, (從位移零) 來驗證符號。

網路和埠問題

符號檔和連接到偵錯工具時會發生問題。 如果您遇到問題,以下是要記住的一些事項:

  • 判斷偵錯纜線在測試系統上連接的 COM 埠。

  • 檢查測試系統的 boot.ini 設定。 尋找 /debug 參數,並檢查傳輸速率和 COM 埠設定。

  • 如果符號檔案是透過網路存取,網路問題可能會干擾偵錯。

  • .dll 和 .sys 具有相同名稱的檔案 (例如 - mga64.sys 和 mga64.dll) ,如果偵錯工具未分隔成符號樹狀目錄的適當目錄,則會混淆偵錯工具。

  • 核心偵錯工具不一定喜歡將組建符號檔取代為私人符號檔。 請仔細檢查符號路徑,並在符號上執行 .reloadFileName!dlls命令有時很有用。

問題和誤解

問: 我已成功載入符號,但堆疊似乎不正確。 偵錯工具是否中斷?

答: 不一定。 問題最可能的原因是您有不正確的符號。 請流覽本節所述的步驟,以判斷您是否已載入有效的符號。 請勿假設,因為某些專案有有效的符號。 例如,您非常順利地能夠執行 dd nt!ntbuildnumberu nt!具有不正確符號的 KeInitializeProcess 。 使用上述程式確認它們是否正確。

問: 偵錯工具是否會仍然使用不正確的符號?

答: 是和否。 通常,您可以使用不完全相符的符號來離開。 例如,來自先前 Windows 組建的符號通常會在特定案例中運作,但沒有規則可運作,以及何時無法運作。

問: 我在核心偵錯工具中停止,而我想要檢視使用者模式進程的符號。 我可以這麼做嗎?

答: 主要。 此案例的支援不佳,因為核心偵錯工具不會保留足夠的資訊來追蹤每個進程的模組負載,但有合理的因應措施。 若要載入使用者模式模組的符號,請執行 .reload -user 命令。 這會載入目前內容的使用者模式模組。

問: 下列訊息的意義為何?

*** WARNING: symbols checksum and timestamp is wrong 0x0036d6bf 0x0036ab55 for ntkrnlmp.exe

答: 這表示您的 ntkrnlmp.exe 符號錯誤。