我正在试图破译如何使用/ proc / pid / pagemap来获取给定页面的物理地址。 假设从/ proc / pid / maps中,我得到对应于堆的虚拟地址afa2d000-afa42000。 我的问题是如何使用这个信息来遍历页面地图文件,并find物理页面框架对应的地址afa2d000-afa42000。
/ proc / pid / pagemap条目是二进制格式。 有没有什么工具来帮助parsing这个文件?
试试这个http://www.eqware.net/Articles/CapturingProcessMemoryUsageUnderLinux/它可以解析你的页面地图,例如,如果你感兴趣的虚拟地址是堆0x055468:= 0004c000-0005a000 rw-p 00000000 00:00 0 [堆]:86000000000FD6D6:0600000000000000
:0600000000000000
:86000000000FE921
:86000000000FE922
:0600000000000000
:86000000000FD5AD
:86000000000FD6D4
:86000000000FD5F8
:86000000000FD5FA => 9
假设页面大小为4KB,并且(0x055468 – 0x4c000)mod 4K = 9,那么你的页面的页帧号是第9页的帧==>:86000000000FD5FA所以物理pfn是0xFD5FA000(取最后的55位和时间(0x055468 – 0x4c000 – 9 * 4K)= 0x468 ==>物理地址0xFD5FA000 + 0x468 =
我希望这个链接将有所帮助。 这是一个非常简单的工具,并确定您需要访问的地址是非常简单的: http : //fivelinesofcode.blogspot.com/2014/03/how-to-translate-virtual-to-physical.html
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; }
使用它的示例可运行程序: