I was trying to see memory map of a process on Linux x86-64 using pmap -x
command. I got confused looking at the output of the pmap. Particularly for the entries for mapping dynamic libraries. There are multiple entries for them (actually 4 for all most all of them, with some having 3 entries). Following is an example
Address Kbytes RSS Dirty Mode Mapping
00000036ca200000 88 64 0 r-x-- libpthread-2.5.so
00000036ca216000 2044 0 0 ----- libpthread-2.5.so
00000036ca415000 4 4 4 r---- libpthread-2.5.so
00000036ca416000 4 4 4 rw--- libpthread-2.5.so
The second row for each of the library always has size of 2MB while it has no page permission. Across all libraries it seems its RSS is ALWAYS zero. Last two rows also have same size (which is base page size) and same permissions (a handful libraries does not have rw mapping).
Does anybody has some explanation for this? I am kind of having a sense that possibly the mapping with the read-only protection is done by the loader to read the metadata of the library while the portion with the executable permission actually the code for the library. I may be wrong though.
But I have no clue about that middle row. No permission and no usages? Anyone has some words of wisdom here?
I also saw a few pages reported to be on the anonymous memory and not have any mode bit set. What do these represent?
These protected "----" pages are guard pages to prevent pointers from indexing between the code and data segments of the library. They only exist in the virtual space of the process and exist to cause a fault if a pointer walks past the end of the segment.
If these weren't addressed into a shared library file I would say they were serving as a buffer for expanding allocations into e.g. malloc or stack growth. For example glibc requests large chunks of address space from the kernel for thread-local allocation arenas then consumes them slowly for malloc'd allocations. In a much larger pmap from a JVM I'm looking at there are a few dozen of these, each following a RW page or filling in the space between two large RW allocations and the boundaries between them shift as the RW pages expand. On X86_64 guard pages like this can use the CPU's memory protection system to catch bad pointer dereferences.