對應符號 當 PEB 分頁時
若要載入符號,偵錯工具會查看作業系統所載入的模組清單。 使用者模式模組清單的指標是程式環境區塊中儲存的其中一個專案, (PEB) 。
若要回收記憶體,記憶體管理員可能會分頁出使用者模式資料,讓其他進程或核心模式元件有空間。 分頁出的使用者模式資料可能包含 PEB 資料結構。 如果沒有此資料結構,偵錯工具就無法判斷要載入符號的影像。
注意 這只會影響使用者模式模組的符號檔。 核心模式模組和符號不會受到影響,因為它們會在不同的清單中追蹤。
假設使用者模式模組已對應到目前的進程,而您想要修正它的符號。 在模組的虛擬位址範圍內尋找任何位址。 例如,假設模組對應到包含位址 7f78e9e000F 的虛擬位址範圍。 輸入下列命令。
3: kd> !vad 7f78e9e000F 1
命令輸出會顯示模組的虛擬位址描述元 (VAD) 的相關資訊。 命令輸出也包含重載命令字串,可用來載入模組的符號。 Reload 命令字串包含記事本模組 (000007f7'8e9e0000) 和大小 (32000) 。
VAD @ fffffa80056fb960
...
Reload command: .reload notepad.exe=000007f7`8e9e0000,32000
若要載入符號,請輸入重載命令字串中提供的命令。
.reload notepad.exe=000007f7`8e9e0000,32000
以下是另一個使用稍微不同技巧的範例。 此範例示範如何在分頁 PEB 時使用 !vad 延伸模組來對應符號。基本概念是尋找相關 DLL 的起始位址和大小,以便您接著使用 .reload 命令載入必要的符號。 假設目前進程的位址0xE0000126'01BA0AF0,而且您想要修正它的符號。 首先,使用 !process 命令來取得虛擬位址描述元, (VAD) 根位址:
kd> !process e000012601ba0af0 1
PROCESS e000012601ba0af0
SessionId: 2 Cid: 0b50 Peb: 6fbfffde000 ParentCid: 0efc
DirBase: 079e8461 ObjectTable: e000000600fbceb0 HandleCount: 360.
Image: explorer.exe
VadRoot e000012601a35e70 Vads 201 Clone 0 Private 917. Modified 2198. Locked 0.
...
然後使用 !vad 延伸模組來列出與進程相關聯的 VAD 樹狀結構。 標示為「EXECUTE_WRITECOPY」的 VAD 屬於程式碼模組。
kd> !vad e000012601a35e70
VAD level start end commit
...
e0000126019f9790 ( 6) 3fff0 3fff7 -1 Private READONLY
e000012601be1080 ( 7) 37d9bd30 37d9bd3e 2 Mapped Exe EXECUTE_WRITECOPY <-- these are DLLs
e000012600acd970 ( 5) 37d9bec0 37d9bece 2 Mapped Exe EXECUTE_WRITECOPY
e000012601a5cba0 ( 7) 37d9c910 37d9c924 2 Mapped Exe EXECUTE_WRITECOPY
...
然後再次使用 !vad 擴充功能來尋找分頁記憶體的起始位址和大小,其中包含感興趣的 DLL。 這會確認您已找到正確的 DLL:
kd> !vad e000012601be1080 1
VAD @ e000012601be1080
Start VPN: 37d9bd30 End VPN: 37d9bd3e Control Area: e00001260197b8d0
First ProtoPte: e0000006013e00a0 Last PTE fffffffffffffffc Commit Charge 2 (2.)
Secured.Flink 0 Blink 0 Banked/Extend: 0
File Offset 0
ImageMap ViewShare EXECUTE_WRITECOPY
...
File: \Windows\System32\ExplorerFrame.dll
[啟動 VPN] 欄位 - 在此案例中,0x37D9BD30 - 表示起始的虛擬頁碼。 這必須轉換成實際位址,方法是將它乘以頁面大小。 您可以使用 ? (Evaluate Expression) 命令,將此值乘以 0x2000,這是範例所來自 Itanium 電腦的頁面大小。
kd> ? 37d9bd3e*2000
Evaluate expression: 7676040298496 = 000006fb`37a7c000
然後,範圍的大小可以轉換成位元組:
kd> ? 37d9bd3e-37d9bd30+1 <-- computes the number of pages
Evaluate expression: 15 = 00000000`0000000f
kd> ? f*2000
Evaluate expression: 122880 = 00000000`0001e000
因此,ExplorerFrame.dll 從位址0x000006Fb'37A7C000 開始,且0x1E000位元組很大。 您可以使用:
kd> .reload /f ExplorerFrame.dll=6fb`37a7c000,1e000