Как декодировать /proc/pid/pagemap записи в Linux?

132
9

Я пытаюсь расшифровать использование /proc/pid/pagemap, чтобы получить физический адрес заданного набора страниц. Предположим, что на картах/proc/pid/я получаю виртуальный адрес afa2d000-afa42000, который соответствует куче. Мой вопрос заключается в том, как использовать эту информацию для перемещения файла pagemap и найти, что физические кадры страниц соответствуют адресу afa2d000-afa42000.


Запись/proc/pid/pagemap находится в двоичном формате. Есть ли какие-либо инструменты для синтаксического анализа этого файла?

спросил(а) 2021-01-25T17:27:58+03:00 4 месяца, 4 недели назад
1
Решение
89

Надеюсь, эта ссылка поможет. Это очень простой инструмент, и определить адрес, который вам нужен для доступа, очень просто:
http://fivelinesofcode.blogspot.com/2014/03/how-to-translate-virtual-to-physical.html

ответил(а) 2021-01-25T17:27:58+03:00 4 месяца, 4 недели назад
77

Попробуйте это
http://www.eqware.net/Articles/CapturingProcessMemoryUsageUnderLinux/
Он может анализировать карту pagemap для вас, например, если виртуальный адрес
вас интересует куча, которая равна 0x055468:
= 0004c000-0005a000 rw-p 00000000 00:00 0 [куча]
: 86000000000FD6D6
: 0600000000000000

: 0600000000000000

: 86000000000FE921

: 86000000000FE922

: 0600000000000000

: 86000000000FD5AD

: 86000000000FD6D4

: 86000000000FD5F8

: 86000000000FD5FA = > 9th

Предположим, что размер страницы равен 4 КБ и
(0x055468 - 0x4c000) mod 4K = 9,
Таким образом, номер страницы страницы вашей страницы - это 9-я страница
 == > : 86000000000FD5FA
Таким образом, физический pfn равен 0xFD5FA000 (возьмите последние 55 бит и раз размер страницы)
плюс смещение: (0x055468 - 0x4c000 - 9 * 4K) = 0x468
== > физический addr равен 0xFD5FA000 + 0x468 = 0xFD5FA468

ответил(а) 2021-01-25T17:27:58+03:00 4 месяца, 4 недели назад
63

Документация ядра Linux


Документация ядра Linux, описывающая формат: https://github.com/torvalds/linux/blob/v4.9/Documentation/vm/pagemap.txt


* Bits 0-54  page frame number (PFN) if present
* Bits 0-4 swap type if swapped
* Bits 5-54 swap offset if swapped
* Bit 55 pte is soft-dirty (see Documentation/vm/soft-dirty.txt)
* Bit 56 page exclusively mapped (since 4.2)
* Bits 57-60 zero
* Bit 61 page is file-page or shared-anon (since 3.5)
* Bit 62 page swapped
* Bit 63 page present

Функция парсера C


GitHub вверх по течению.


#define _XOPEN_SOURCE 700
#include <fcntl.h> /* open */
#include <stdint.h> /* uint64_t */
#include <stdlib.h> /* size_t */
#include <unistd.h> /* pread, sysconf */

typedef struct {
uint64_t pfn : 54;
unsigned int soft_dirty : 1;
unsigned int file_page : 1;
unsigned int swapped : 1;
unsigned int present : 1;
} PagemapEntry;

/* Parse the pagemap entry for the given virtual address.
*
* @param[out] entry the parsed entry
* @param[in] pagemap_fd file descriptor to an open /proc/pid/pagemap file
* @param[in] vaddr virtual address to get entry for
* @return 0 for success, 1 for failure
*/
int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr)
{
size_t nread;
ssize_t ret;
uint64_t data;

nread = 0;
while (nread < sizeof(data)) {
ret = pread(pagemap_fd, &data, sizeof(data),
(vaddr / sysconf(_SC_PAGE_SIZE)) * sizeof(data) + nread);
nread += ret;
if (ret <= 0) {
return 1;
}
}
entry->pfn = data & (((uint64_t)1 << 54) - 1);
entry->soft_dirty = (data >> 54) & 1;
entry->file_page = (data >> 61) & 1;
entry->swapped = (data >> 62) & 1;
entry->present = (data >> 63) & 1;
return 0;
}


Пример использования исполняемых программ:


ответил(а) 2021-01-25T17:27:58+03:00 4 месяца, 4 недели назад
45

В случае, если люди хотят сделать это из Rust, я добавил реализацию Rust, чтобы вы могли легко перемещаться по /proc/$pid/maps и /proc/$pid/pagemap: https://crates.io/crates/vm-info

ответил(а) 2021-01-25T17:27:58+03:00 4 месяца, 4 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема