Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Большинство команд отладчика используют виртуальные адреса, а не физические адреса в качестве входных и выходных данных. Однако есть времена, когда физический адрес может быть полезным.
Существует два способа преобразования виртуального адреса в физический адрес: с помощью расширения !vtop и с помощью расширения !pte .
Общие сведения о виртуальном адресе в Windows см. в разделе "Виртуальные адресные пространства".
Преобразование адресов с помощью !vtop
Предположим, что выполняется отладка целевого компьютера, на котором выполняется процесс MyApp.exe, и вы хотите изучить виртуальный адрес 0x0012F980. Ниже приведена процедура, используемая с расширением !vtop для определения соответствующего физического адреса.
Преобразование виртуального адреса в физический адрес с помощью !vtop
Убедитесь, что вы работаете в шестнадцатеричном формате. При необходимости задайте текущую базу с помощью команды N 16 .
Определите индекс байтов адреса. Это число равно наименьшей 12 бит виртуального адреса. Таким образом, виртуальный адрес 0x0012F980 имеет индекс байтов 0x980.
Определите базу каталогов адреса с помощью расширения !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
Определите номер кадра страницы базы каталога. Это просто база каталогов без трех конечных шестнадцатеричных нулей. В этом примере база каталогов 0x098FD000, поэтому номер кадра страницы 0x098FD.
Используйте расширение !vtop . Первым параметром этого расширения должен быть номер кадра страницы. Второй параметр !vtop должен быть виртуальным адресом, о котором идет речь.
kd> !vtop 98fd 12f980 Pdi 0 Pti 12f 0012f980 09de9000 pfn(09de9)
Второй номер, показанный в последней строке, — это физический адрес начала физической страницы.
Добавьте индекс байтов в адрес начала страницы: 0x09DE9000 + 0x980 = 0x09DE9980. Это нужный физический адрес.
Вы можете убедиться, что это вычисление было выполнено правильно, отображая память на каждом адресе. Расширение !d\* отображает память по указанному физическому адресу:
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 .....
Команда d* (Display Memory) использует виртуальный адрес в качестве аргумента:
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 .....
Так как результаты одинаковы, это означает, что физический адрес 0x09DE9980 действительно соответствует виртуальному адресу 0x0012F980.
Преобразование адресов с помощью !pte
Опять же, предположим, что вы изучаете виртуальный адрес 0x0012F980, принадлежащий процессу MyApp.exe. Ниже приведена процедура, используемая с расширением !pte для определения соответствующего физического адреса:
Преобразование виртуального адреса в физический адрес с помощью !pte
Убедитесь, что вы используете шестнадцатеричную систему. При необходимости задайте текущую базу с помощью команды N 16 .
Определите индекс байтов адреса. Это число равно наименьшей 12 бит виртуального адреса. Таким образом, виртуальный адрес 0x0012F980 имеет индекс байтов 0x980.
Задайте контекст процесса требуемому процессу:
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
Используйте расширение !pte с виртуальным адресом в качестве аргумента. Эта информация отображается в двух столбцах. В левом столбце описывается запись каталога страницы (PDE) для этого адреса; Правый столбец описывает запись таблицы страницы (PTE):
kd> !pte 12f980 VA 0012f980 PDE at C0300000 PTE at C00004BC contains 0BA58067 contains 09DE9067 pfn ba58 ---DA--UWV pfn 9de9 ---DA--UWV
Просмотрите последнюю строку правого столбца. Появится нотация "pfn 9de9". Номер 0x9DE9 — это номер кадра страницы (PFN) этого PTE. Умножьте номер кадра страницы на 0x1000 (например, сместите его влево 12 битов). Результатом 0x09DE9000 является физический адрес начала страницы.
Добавьте индекс байтов в адрес начала страницы: 0x09DE9000 + 0x980 = 0x09DE9980. Это требуемый физический адрес.
Это тот же результат, полученный ранее методом.
Преобразование адресов вручную
Хотя расширения !ptov и pte предоставляют самый быстрый способ преобразования виртуальных адресов в физические адреса, это преобразование также можно сделать вручную. Описание этого процесса будет пролить свет на некоторые детали архитектуры виртуальной памяти.
Структуры памяти различаются в зависимости от процессора и конфигурации оборудования. Этот пример взят из системы x86, которая не включает расширение физического адреса (PAE).
Используя 0x0012F980 снова в качестве виртуального адреса, сначала необходимо преобразовать его в двоичный вид, вручную либо с помощью команды .форматов (показать форматы чисел):
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
Этот виртуальный адрес представляет собой сочетание трех полей. Биты от 0 до 11 являются индексом байтов. Биты 12–21 — это индекс таблицы страницы. Биты 22–31 — это индекс каталога страницы. При разделении полей, у вас получится:
0x0012F980 = 0y 00000000 00 010010 1111 1001 10000000
Эта функция предоставляет три части виртуального адреса:
Индекс каталога страницы = 0y000000000 = 0x0
Индекс таблицы страницы = 0y0100101111 = 0x12F
Индекс байтов = 0y100110000000 = 0x980
Затем вам потребуется три дополнительных фрагмента информации для вашей системы.
Размер каждого PTE. Это 4 байта в системах x86, отличных от PAE.
Размер страницы. Это 0x1000 байт.
Виртуальный адрес PTE_BASE. В системе, отличной от PAE, это 0xC0000000.
С помощью этих данных можно вычислить адрес самого PTE:
PTE address = PTE_BASE
+ (page directory index) * PAGE_SIZE
+ (page table index) * sizeof(MMPTE)
= 0xc0000000
+ 0x0 * 0x1000
+ 0x12F * 4
= 0xC00004BC
Это адрес PTE. PTE — это 32-разрядный DWORD. Проверьте его содержимое:
kd> dd 0xc00004bc L1
c00004bc 09de9067
Этот PTE имеет значение 0x09DE9067. Он состоит из двух полей:
Низкие 12 битов PTE представляют собой флаги состояния. В этом случае эти флаги равны 0x067 - или в двоичном формате 0y00000110011. Для объяснения флагов состояния см. на справочной странице !pte.
Высокие 20 битов PTE соответствуют номеру кадра страницы (PFN) PTE. В этом случае PFN — 0x09DE9.
Первый физический адрес на физической странице — это PFN, умноженный на 0x1000 (смещенный влево 12 бит). Индекс байтов — это смещение на этой странице. Таким образом, физический адрес, который вы ищете, 0x09DE9000 + 0x980 = 0x09DE9980. Это тот же результат, полученный предыдущими методами.