Date: Sat, 10 Jun 2006 18:22:46 +0200 From: Bruno Haible <bruno@clisp.org> To: hackers@freebsd.org Cc: Vasil Dimov <vd@freebsd.org> Subject: valid VMA ranges and mincore() Message-ID: <200606101822.46437.bruno@clisp.org>
next in thread | raw e-mail | index | archive | help
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 purpose =========== 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. The problem =========== On NetBSD, Linux, Solaris, mincore() applied to a range of addresses that is partially not mapped, returns -1 with errno set to ENOMEM. See NetBSD: http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/sys/mincore.2?rev=1.19&content-type=text/plain Linux: http://linux.about.com/library/cmd/blcmdl2_mincore.htm Solaris: http://docs.sun.com/app/docs/doc/816-5167/6mbb2jaib?a=view 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 to distinguish a page which is valid address range but currently swapped out from a page which is unmapped. As a consequence, mincore() does not help for the aforementioned purpose. Proposals ========= Alternatively: Proposal 1: Change mincore() to behave like the one on NetBSD, Linux, Solaris. 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 platforms. 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)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606101822.46437.bruno>