How to decode /proc/pid/pagemap entries in Linux?

前端 未结 4 1748
名媛妹妹
名媛妹妹 2020-12-01 13:16

I am trying to decipher how to use /proc/pid/pagemap to get the physical address of a given set of pages. Suppose from the /proc/pid/maps, I get the virtual address afa2d000

相关标签:
4条回答
  • 2020-12-01 13:27

    Try this http://www.eqware.net/Articles/CapturingProcessMemoryUsageUnderLinux/ It can parse the pagemap for you, for example, if the virtual address you are interested is in the heap which is 0x055468 : = 0004c000-0005a000 rw-p 00000000 00:00 0 [heap] : 86000000000FD6D6 : 0600000000000000
    : 0600000000000000
    : 86000000000FE921
    : 86000000000FE922
    : 0600000000000000
    : 86000000000FD5AD
    : 86000000000FD6D4
    : 86000000000FD5F8
    : 86000000000FD5FA =>9th

    Suppose the page size as 4KB, and (0x055468 - 0x4c000) mod 4K = 9, So the page frame number of your page is the 9th page frames ==> : 86000000000FD5FA So the physical pfn is 0xFD5FA000 (take the last 55 bits and times page size) plus the offset: ( 0x055468 - 0x4c000 - 9*4K) = 0x468 ==> the physical addr is 0xFD5FA000 + 0x468 = 0xFD5FA468

    0 讨论(0)
  • 2020-12-01 13:33

    I hope this link will help. It's a very simple tool, and determining the address you need to access is very simple: http://fivelinesofcode.blogspot.com/2014/03/how-to-translate-virtual-to-physical.html

    0 讨论(0)
  • 2020-12-01 13:43

    Linux kernel documentation

    Linux kernel doc describing the format: 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 parser function

    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;
    }
    

    Example runnable programs using it:

    • convert one virtual address to physical: Is there any API for determining the physical address from virtual address in Linux?
    • dump information about all pages of a process: /proc/[pid]/pagemaps and /proc/[pid]/maps | linux
    0 讨论(0)
  • 2020-12-01 13:44

    In case folks want to do this from Rust, I've added a Rust implementation so you can easily navigate /proc/$pid/maps and /proc/$pid/pagemap: https://crates.io/crates/vm-info

    0 讨论(0)
提交回复
热议问题