# Linux Kernel Module Cheat

###### 17.12.2.1.3. pagemap_dump.out

Dump the physical address of all pages mapped to a given process using `/proc/<pid>/maps` and `/proc/<pid>/pagemap`.

First launch `linux/virt_to_phys_user.out` as described at Userland physical address experiments. Suppose that the output was:

    # ./posix/virt_to_phys_test.out &
    vaddr 0x601048
    pid 63
    # ./linux/virt_to_phys_user.out 63 0x601048
    0x1a61048

Now obtain the page map for the process:

    ./linux/pagemap_dump.out 63

Sample output excerpt:

    vaddr pfn soft-dirty file/shared swapped present library
    400000 1ede 0 1 0 1 ./posix/virt_to_phys_test.out
    600000 1a6f 0 0 0 1 ./posix/virt_to_phys_test.out
    601000 1a61 0 0 0 1 ./posix/virt_to_phys_test.out
    602000 2208 0 0 0 1 [heap]
    603000 220b 0 0 0 1 [heap]
    7ffff78ec000 1fd4 0 1 0 1 /lib/libuClibc-1.0.30.so

Source:

- userland/linux/pagemap_dump.c

- lkmc/pagemap.h

Adapted from: https://github.com/dwks/pagemap/blob/8a25747bc79d6080c8b94eac80807a4dceeda57a/pagemap2.c

Meaning of the flags:

- `vaddr`: first virtual address of a page the belongs to the process. Notably:

      ./run-toolchain readelf -- -l "$(./getvar userland_build_dir)/posix/virt_to_phys_test.out"

  contains:

        Type           Offset             VirtAddr           PhysAddr
                       FileSiz            MemSiz              Flags  Align
      ...
        LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                       0x000000000000075c 0x000000000000075c  R E    0x200000
        LOAD           0x0000000000000e98 0x0000000000600e98 0x0000000000600e98
                       0x00000000000001b4 0x0000000000000218  RW     0x200000

       Section to Segment mapping:
        Segment Sections...
      ...
         02     .interp .hash .dynsym .dynstr .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
         03     .ctors .dtors .jcr .dynamic .got.plt .data .bss

  from which we deduce that:

  - `400000` is the text segment

  - `600000` is the data segment

- `pfn`: add three zeroes to it, and you have the physical address.

  Three zeroes is 12 bits which is 4kB, which is the size of a page.

  For example, the virtual address `0x601000` has `pfn` of `0x1a61`, which means that its physical address is `0x1a61000`

  This is consistent with what `linux/virt_to_phys_user.out` told us: the virtual address `0x601048` has physical address `0x1a61048`.

  `048` corresponds to the three last zeroes, and is the offset within the page.

  Also, this value falls inside `0x601000`, which as previously analyzed is the data section, which is the normal location for global variables such as ours.

- `soft-dirty`: TODO

- `file/shared`: TODO. `1` seems to indicate that the page can be shared across processes, possibly for read-only pages? E.g. the text segment has `1`, but the data has `0`.

- `swapped`: TODO swapped to disk?

- `present`: TODO vs swapped?

- `library`: which executable owns that page

This program works in two steps:

- parse the human readable lines lines from `/proc/<pid>/maps`. This files contains lines of form:

      7ffff7b6d000-7ffff7bdd000 r-xp 00000000 fe:00 658                        /lib/libuClibc-1.0.22.so

  which tells us that:

  - `7f8af99f8000-7f8af99ff000` is a virtual address range that belong to the process, possibly containing multiple pages.

  - `/lib/libuClibc-1.0.22.so` is the name of the library that owns that memory

- loop over each page of each address range, and ask `/proc/<pid>/pagemap` for more information about that page, including the physical address