如何在Linux中解码/proc/pid/pagemap条目?

olqngx59  于 2023-03-17  发布在  Linux
关注(0)|答案(4)|浏览(176)

我正在尝试破解如何使用/proc/pid/pagemap来获取一组给定页面的物理地址。假设从/proc/pid/maps中,我得到了对应于堆的虚拟地址afa 2d 000-afa 42000。我的问题是如何使用此信息遍历pagemap文件并找到对应于地址afa 2d 000-afa 42000的物理页帧。
/proc/pid/pagemap条目是二进制格式的。有什么工具可以帮助解析这个文件吗?

lqfhib0f

lqfhib0f1#

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

在较新的Linux中,文档文件移至:https://github.com/torvalds/linux/blob/v6.2/Documentation/admin-guide/mm/pagemap.rst(感谢评论中的matvore)。

C解析器函数

GitHub upstream .

#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, ((uint8_t*)&data) + nread, sizeof(data) - nread,
                (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;
}

使用它的可运行程序示例:

  • 将一个虚拟地址转换为物理地址:Linux中是否有API可以从虚拟地址中确定物理地址?
  • 转储有关进程所有页面的信息:/proc/[pid]/页面Map和/proc/[pid]/Map|Linux操作系统
b4qexyjb

b4qexyjb2#

我希望这个链接会有所帮助。这是一个非常简单的工具,确定您需要访问的地址也非常简单:http://fivelinesofcode.blogspot.com/2014/03/how-to-translate-virtual-to-physical.html

kqhtkvqz

kqhtkvqz3#

尝试http://www.eqware.net/Articles/CapturingProcessMemoryUsageUnderLinux/它可以为您解析页面图,例如,如果您感兴趣的虚拟地址位于堆中,即0x 055468:= 0004 c 000 - 0005 a000读取-写入0000000 00:00 0 [堆]:8600000000FD6D6:0600000000000000
:06亿美元
:8600000000FE921
:8600000000FE922
:06亿美元
:86亿美元
:86亿美元
:86000000000FD5F8
:8600000000 FD 5 FA =〉第9位
假设页面大小为4KB,且(0x 055468 - 0x 4c 000)mod 4K = 9,则您的页面的页框号为第9页框==〉:8600000000 FD 5 FA因此,物理pfn为0xFD 5 FA 000(取最后55位乘以页面大小)加上偏移量:(0x 055468 - 0x 4c 000 - 9*4K)= 0x 468 ==〉物理地址为0xFD 5 FA 000 + 0x 468 = 0xFD 5 FA 468

xwbd5t1u

xwbd5t1u4#

如果有人想在Rust中执行此操作,我添加了一个Rust实现,以便您可以轻松地导航/proc/$pid/maps/proc/$pid/pagemaphttps://crates.io/crates/vm-info

相关问题