PEB がページアウトされている場合のシンボルの照合
シンボルを読み込むために、デバッガーは、オペレーティング システムによって読み込まれたモジュールの一覧を確認します。 ユーザー モード モジュール リストへのポインターは、プロセス環境ブロック (PEB) に格納されている項目の 1 つです。
メモリを再利用するために、メモリ マネージャはユーザー モード データをページアウトして、他のプロセスまたはカーネル モード コンポーネント用のスペースを確保することがあります。 ページングされるユーザー モード データには、PEB データ構造が含まれる場合があります。 このデータ構造がないと、デバッガーはシンボルを読み込むイメージを特定できません。
注: これは、ユーザー モード モジュールのシンボル ファイルにのみ影響します。 カーネルモードのモジュールとシンボルは、別のリストで追跡されるため、影響を受けません。
ユーザー モード モジュールが現在のプロセスにマップされていて、そのシンボルを修正するとします。 モジュールの仮想アドレスの範囲内にある任意のアドレスを検索します。 たとえば、モジュールが、アドレス 7f78e9e000F を含む仮想アドレス範囲にマップされるとします。 次のコマンドを入力します。
3: kd> !vad 7f78e9e000F 1
コマンド出力には、モジュールの仮想アドレス記述子 (VAD) に関する情報が表示されます。 コマンド出力には、モジュールのシンボルの読み込みに使用できる Reload コマンド文字列も含まれています。 Reload コマンド文字列には、メモ帳モジュールの開始アドレス (000007f7'8e9e0000) とサイズ (32000) が含まれます。
VAD @ fffffa80056fb960
...
Reload command: .reload notepad.exe=000007f7`8e9e0000,32000
シンボルを読み込むには、Reload コマンド文字列に指定されたコマンドを入力します。
.reload notepad.exe=000007f7`8e9e0000,32000
少し異なる手法を使用する別の例を次に示します。 この例では、PEB のページング時に !vad 拡張機能を使用してシンボルをマップする方法を示します。基本的な考え方は、 .reload コマンドを使用して必要なシンボルを読み込むことができるように、関連する DLL の開始アドレスとサイズを見つけることです。 現在のプロセスのアドレスが 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) は、開始仮想ページ番号を示します。 これは、ページ サイズを乗算して、実際のアドレスに変換する必要があります。 ?(式の評価) コマンドを使用して、この値に 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
そのため、エクスプローラー Frame.dllアドレス 0x000006Fb'37A7C000 から始まり、0x1E000 バイトの大きさになります。 シンボルは次の方法で読み込むことができます。
kd> .reload /f ExplorerFrame.dll=6fb`37a7c000,1e000