次の方法で共有


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