Partilhar via


Mapeamento de Símbolos Quando o PEB é Descarregado da Memória

Para carregar símbolos, o depurador examina a lista de módulos carregados pelo sistema operacional. O ponteiro para a lista de módulos de modo de usuário é um dos itens armazenados no bloco de ambiente de processo (PEB).

Para recuperar memória, o Gerenciador de Memória pode paginar dados de modo de usuário para abrir espaço para outros componentes de processo ou modo kernel. Os dados de modo de usuário que são paginados podem incluir a estrutura de dados PEB. Sem essa estrutura de dados, o depurador não pode determinar para quais imagens carregar símbolos.

Observação Isso afeta os arquivos de símbolo apenas para os módulos de modo de usuário. Os módulos e símbolos do modo kernel não são afetados, pois são rastreados em uma lista diferente.

Suponha que um módulo em modo de utilizador esteja mapeado no processo atual e que deseje ajustar os símbolos para ele. Encontre qualquer endereço no intervalo de endereços virtuais do módulo. Por exemplo, suponha que um módulo é mapeado em um intervalo de endereços virtuais que contém o endereço 7f78e9e000F. Digite o seguinte comando.

3: kd> !vad 7f78e9e000F 1

A saída do comando exibe informações sobre o descritor de endereço virtual (VAD) para o módulo. A saída do comando também inclui uma cadeia de comando Reload que você pode usar para carregar os símbolos do módulo. A cadeia de comando Recarregar inclui o endereço inicial (000007f7'8e9e0000) e o tamanho (32000) do módulo do bloco de notas.

VAD @ fffffa80056fb960
...
Reload command: .reload notepad.exe=000007f7`8e9e0000,32000

Para carregar os símbolos, digite o comando que foi fornecido na cadeia de comandos 'Recarregar'.

.reload notepad.exe=000007f7`8e9e0000,32000

Aqui está outro exemplo que usa uma técnica ligeiramente diferente. O exemplo demonstra como usar a extensão !vad para mapear símbolos quando o PEB é paginado. A ideia básica é encontrar o endereço inicial e o tamanho da DLL relevante para que você possa usar o comando .reload para carregar os símbolos necessários. Suponha que o endereço do processo atual é 0xE0000126'01BA0AF0 e você deseja corrigir os símbolos para ele. Primeiro, use o comando !process para obter o endereço raiz do descritor de endereço virtual (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.
...

Em seguida, use a extensão !vad para listar a árvore VAD associada ao processo. Os VADs rotulados como "EXECUTE_WRITECOPY" pertencem a módulos de código.

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
...

Em seguida, use a extensão !vad novamente para encontrar o endereço inicial e o tamanho da memória paginada que contém a DLL de interesse. Isso confirma que você encontrou a DLL correta:

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

O campo "Iniciar VPN" - neste caso, 0x37D9BD30 - indica o número da página virtual inicial. Este deve ser convertido num endereço real, multiplicando-o pelo tamanho da página. Você pode usar o ? (Avaliar Expressão) para multiplicar esse valor por 0x2000, que é o tamanho da página da máquina baseada em Itanium da qual o exemplo vem.

kd> ? 37d9bd3e*2000 
Evaluate expression: 7676040298496 = 000006fb`37a7c000

Em seguida, o tamanho do intervalo pode ser convertido em bytes:

kd> ? 37d9bd3e-37d9bd30+1 <--   computes the number of pages
Evaluate expression: 15 = 00000000`0000000f
kd> ? f*2000
Evaluate expression: 122880 = 00000000`0001e000        

Assim, ExplorerFrame.dll começa no endereço 0x000006Fb'37A7C000 e tem 0x1E000 bytes de tamanho. Você pode carregar seus símbolos com:

kd> .reload /f ExplorerFrame.dll=6fb`37a7c000,1e000