valid VMA ranges and mincore()
bruno at clisp.org
Sat Jun 10 18:38:20 UTC 2006
Hi memory management hackers,
The mincore(2) system call is, on FreeBSD, not usable for some purposes
for which it can be used on other platforms. Let me explain the purpose,
the problem and two proposed solutions.
The task at hand is to enumerate the VMAs of the current process.
In other words, determine which address ranges are mapped and which aren't.
If the /proc filesystem is available, the /proc/curproc/map file
can be opened and parsed; it contains the necessary information.
But I'm being told that /proc is not mounted by default, and as an
application developer I have no control over that. So, I must look for
a solution that works also when /proc is not mounted.
The purpose of this task can be
a) To detect whether a SIGSEGV is actually a stack overflow, a
write access to a read-only memory page, or simply a bug in
the program. If the fault address is near to the stack segment,
it's likely a stack overflow; if it's nearer to a data segment,
it's more likely a bug.
b) To choose optimal addresses for mmap with MAP_FIXED that obey
some constraints about lengths and bit patterns.
Ideally the OS would have a system call that allows to iterate over
the VMAs of the current process (corresponding to the lines of
/proc/curproc/map), or to retrieve the list of VMAs as a big array.
Lacking such a system call, on platforms other than FreeBSD, for example
NetBSD, I can use mincore() instead.
On NetBSD, Linux, Solaris, mincore() applied to a range of addresses that
is partially not mapped, returns -1 with errno set to ENOMEM. See
This is consistent with mprotect(), which also fails with errno = ENOMEM
if the address range is not fully mapped.
FreeBSD doesn't work this way: it fills 0 values into the array passed
as argument instead, a 0 for each unmapped page. This makes it impossible
a page which is valid address range but currently swapped out
a page which is unmapped.
As a consequence, mincore() does not help for the aforementioned purpose.
Proposal 1: Change mincore() to behave like the one on NetBSD, Linux,
Proposal 2: Define a new constant MINCORE_MAPPED != 0, and change mincore()
to set the per-page value to
- MINCORE_MAPPED for a page that is mapped but swapped out,
- 0 for a page which is unmapped address range.
Proposal 1 would have the advantage to lead to the same code across
Proposal 2 would have the advantage to be backward compatible.
Can you do something about this?
Bruno (an application programmer, not a FreeBSD kernel hacker)
More information about the freebsd-hackers