Partilhar via


Convertendo endereços virtuais em endereços físicos

A maioria dos comandos do depurador usa endereços virtuais, não endereços físicos, como entrada e saída. No entanto, há momentos em que ter o endereço físico pode ser útil.

Há duas maneiras de converter um endereço virtual em um endereço físico: usando a extensão !vtop e usando a extensão !pte .

Para obter uma visão geral do endereço virtual no Windows, consulte Espaços de endereço virtuais.

Conversão de endereço usando !vtop

Suponha que você esteja depurando um computador de destino no qual o processo de MyApp.exe está em execução e queira investigar o endereço virtual 0x0012F980. Este é o procedimento que você usaria com a extensão !vtop para determinar o endereço físico correspondente.

Convertendo um endereço virtual em um endereço físico usando !vtop

  1. Verifique se você está trabalhando em hexadecimal. Se necessário, defina a base atual com o comando N 16 .

  2. Determine o índice de bytes do endereço. Esse número é igual aos 12 bits mais baixos do endereço virtual. Portanto, o endereço virtual 0x0012F980 tem um índice de bytes de 0x980.

  3. Determine a base de diretório do endereço usando a extensão !process :

    kd> !process 0 0
    **** NT ACTIVE PROCESS DUMP ****
    ....
    PROCESS ff779190  SessionId: 0  Cid: 04fc    Peb: 7ffdf000  ParentCid: 0394
     DirBase: 098fd000  ObjectTable: e1646b30  TableSize:   8.
        Image: MyApp.exe
    
  4. Determine o número do quadro de página da base do diretório. Essa é simplesmente a base de diretório sem os três zeros hexadecimais à direita. Neste exemplo, a base de diretório é 0x098FD000, portanto, o número do quadro de página é 0x098FD.

  5. Use a extensão !vtop . O primeiro parâmetro dessa extensão deve ser o número do quadro de página. O segundo parâmetro de !vtop deve ser o endereço virtual em questão:

    kd> !vtop 98fd 12f980
    Pdi 0 Pti 12f
    0012f980 09de9000 pfn(09de9)
    

    O segundo número mostrado na linha final é o endereço físico do início da página física.

  6. Adicione o índice de bytes ao endereço do início da página: 0x09DE9000 + 0x980 = 0x09DE9980. Esse é o endereço físico desejado.

Você pode verificar se essa computação foi feita corretamente exibindo a memória em cada endereço. A extensão !d\* exibe memória em um endereço físico especificado:

kd> !dc 9de9980
# 9de9980 6d206e49 726f6d65 00120079 0012f9f4 In memory.......
# 9de9990 0012f9f8 77e57119 77e8e618 ffffffff .....q.w...w....
# 9de99a0 77e727e0 77f6f13e 77f747e0 ffffffff .'.w>..w.G.w....
# 9de99b0 .....

O comando d* (Exibir Memória) usa um endereço virtual como argumento:

kd> dc 12f980
0012f980  6d206e49 726f6d65 00120079 0012f9f4  In memory.......
0012f990  0012f9f8 77e57119 77e8e618 ffffffff  .....q.w...w....
0012f9a0  77e727e0 77f6f13e 77f747e0 ffffffff  .'.w>..w.G.w....
0012f9b0  .....

Como os resultados são os mesmos, isso indica que o endereço físico 0x09DE9980 realmente corresponde ao endereço virtual 0x0012F980.

Conversão de endereço usando !pte

Novamente, suponha que você esteja investigando o endereço virtual 0x0012F980 pertencente ao processo de MyApp.exe. Este é o procedimento que você usaria com a extensão !pte para determinar o endereço físico correspondente:

Convertendo um endereço virtual em um endereço físico usando !pte

  1. Verifique se você está trabalhando em hexadecimal. Se necessário, defina a base atual com o comando N 16 .

  2. Determine o índice de bytes do endereço. Esse número é igual aos 12 bits mais baixos do endereço virtual. Portanto, o endereço virtual 0x0012F980 tem um índice de bytes de 0x980.

  3. Defina o contexto do processo para o processo desejado:

    kd> !process 0 0
    **** NT ACTIVE PROCESS DUMP ****
    ....
    PROCESS ff779190  SessionId: 0  Cid: 04fc    Peb: 7ffdf000  ParentCid: 0394
        DirBase: 098fd000  ObjectTable: e1646b30  TableSize:   8.
        Image: MyApp.exe
    
    kd> .process /p ff779190
    Implicit process is now ff779190
    .cache forcedecodeuser done
    
  4. Use a extensão !pte com o endereço virtual como seu argumento. Isso exibe informações em duas colunas. A coluna à esquerda descreve a PDE (entrada de diretório de página) para esse endereço; a coluna à direita descreve sua PTE (entrada de tabela de página):

    kd> !pte 12f980
                   VA 0012f980
    PDE at   C0300000        PTE at C00004BC
    contains 0BA58067      contains 09DE9067
    pfn ba58 ---DA--UWV    pfn 9de9 ---DA--UWV
    
  5. Examine a última linha da coluna à direita. A notação "pfn 9de9" é exibida. O número 0x9DE9 é o PFN ( número de quadro de página ) desse PTE. Multiplique o número do quadro de página por 0x1000 (por exemplo, desloque-o para a esquerda 12 bits). O resultado, 0x09DE9000, é o endereço físico do início da página.

  6. Adicione o índice de bytes ao endereço do início da página: 0x09DE9000 + 0x980 = 0x09DE9980. Esse é o endereço físico desejado.

Esse é o mesmo resultado obtido pelo método anterior.

Convertendo endereços manualmente

Embora as extensões !ptov e pte forneçam a maneira mais rápida de converter endereços virtuais em endereços físicos, essa conversão também pode ser feita manualmente. Uma descrição desse processo lançará luz sobre alguns dos detalhes da arquitetura de memória virtual.

As estruturas de memória variam de tamanho, dependendo do processador e da configuração de hardware. Este exemplo é obtido de um sistema x86 que não tem a PAE (Extensão de Endereço Físico) habilitada.

Usando 0x0012F980 novamente como o endereço virtual, primeiro você precisa convertê-lo em binário, manualmente ou usando o comando .formats (Mostrar Formatos de Número ):

kd> .formats 12f980
Evaluate expression:
  Hex:     0012f980
  Decimal: 1243520
  Octal:   00004574600
  Binary:  00000000 00010010 11111001 10000000
  Chars:   ....
  Time:    Thu Jan 15 01:25:20 1970
  Float:   low 1.74254e-039 high 0
  Double:  6.14381e-318

Esse endereço virtual é uma combinação de três campos. Os bits de 0 a 11 são o índice de bytes. Os bits 12 a 21 são o índice da tabela de páginas. Os bits de 22 a 31 são o índice de diretório de página. Separando os campos, você tem:

0x0012F980  =  0y  00000000 00   010010 1111   1001 10000000

Isso expõe as três partes do endereço virtual:

  • Índice de diretório de página = 0y0000000000 = 0x0

  • Índice da tabela de página = 0y0100101111 = 0x12F

  • Índice de bytes = 0y100110000000 = 0x980

Em seguida, você precisa de três informações adicionais para seu sistema.

  • O tamanho de cada PTE. São 4 bytes em sistemas não PAE x86.

  • O tamanho de uma página. Isso é 0x1000 bytes.

  • O PTE_BASE endereço virtual. Em um sistema não PAE, isso é 0xC0000000.

Usando esses dados, você pode calcular o endereço do próprio PTE:

PTE address   =   PTE_BASE  
                + (page directory index) * PAGE_SIZE
                + (page table index) * sizeof(MMPTE)
              =   0xc0000000
                + 0x0   * 0x1000
                + 0x12F * 4
              =   0xC00004BC

Esse é o endereço da PTE. O PTE é um DWORD de 32 bits. Examine seu conteúdo:

kd> dd 0xc00004bc L1
c00004bc  09de9067

Essa PTE tem valor 0x09DE9067. Ele é feito de dois campos:

  • Os 12 bits baixos do PTE são os sinalizadores status. Nesse caso, esses sinalizadores são iguais 0x067 ou, em binário, 0y000001100111. Para obter uma explicação dos sinalizadores de status, consulte a página de referência !pte.

  • Os 20 bits altos do PTE são iguais ao PFN ( número de quadro de página ) do PTE. Nesse caso, o PFN é 0x09DE9.

O primeiro endereço físico na página física é o PFN multiplicado por 0x1000 (deslocado para a esquerda 12 bits). O índice de bytes é o deslocamento nesta página. Portanto, o endereço físico que você está procurando é 0x09DE9000 + 0x980 = 0x09DE9980. Esse é o mesmo resultado obtido pelos métodos anteriores.