X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fvma-iter.c;h=1de69d803ebd90f1718beb22a70d63ac21e3ae18;hb=f9e83fd48cb5c5a0b5a65751710138d42c814402;hp=251ef755404397aea4f872d99834311257105d0b;hpb=fe810bf8507a92354b4750e6dd1b3bd974ab7fc5;p=gnulib.git diff --git a/lib/vma-iter.c b/lib/vma-iter.c index 251ef7554..1de69d803 100644 --- a/lib/vma-iter.c +++ b/lib/vma-iter.c @@ -40,10 +40,15 @@ # include #endif -#if defined __BEOS__ /* BeOS */ +#if defined __BEOS__ || defined __HAIKU__ /* BeOS, Haiku */ # include #endif +#if HAVE_MQUERY /* OpenBSD */ +# include +# include /* mquery */ +#endif + /* Support for reading text files in the /proc file system. */ @@ -331,10 +336,12 @@ vma_iterate (vma_iterate_callback_fn callback, void *data) { /* Consider [start,end-1] \ [auxmap_start,auxmap_end-1] = [start,auxmap_start-1] u [auxmap_end,end-1]. */ - if (callback (data, start, auxmap_start, flags)) - break; - if (callback (data, auxmap_end, end, flags)) - break; + if (start < auxmap_start) + if (callback (data, start, auxmap_start, flags)) + break; + if (auxmap_end - 1 < end - 1) + if (callback (data, auxmap_end, end, flags)) + break; } else { @@ -464,7 +471,7 @@ vma_iterate (vma_iterate_callback_fn callback, void *data) address = (unsigned long)info.BaseAddress + info.RegionSize; } -#elif defined __BEOS__ +#elif defined __BEOS__ || defined __HAIKU__ /* Use the BeOS specific API. */ area_info info; @@ -488,6 +495,99 @@ vma_iterate (vma_iterate_callback_fn callback, void *data) break; } +#elif HAVE_MQUERY /* OpenBSD */ + + uintptr_t pagesize; + uintptr_t address; + int /*bool*/ address_known_mapped; + + pagesize = getpagesize (); + /* Avoid calling mquery with a NULL first argument, because this argument + value has a specific meaning. We know the NULL page is unmapped. */ + address = pagesize; + address_known_mapped = 0; + for (;;) + { + /* Test whether the page at address is mapped. */ + if (address_known_mapped + || mquery ((void *) address, pagesize, 0, MAP_FIXED, -1, 0) + == (void *) -1) + { + /* The page at address is mapped. + This is the start of an interval. */ + uintptr_t start = address; + uintptr_t end; + + /* Find the end of the interval. */ + end = (uintptr_t) mquery ((void *) address, pagesize, 0, 0, -1, 0); + if (end == (uintptr_t) (void *) -1) + end = 0; /* wrap around */ + address = end; + + /* It's too complicated to find out about the flags. Just pass 0. */ + if (callback (data, start, end, 0)) + break; + + if (address < pagesize) /* wrap around? */ + break; + } + /* Here we know that the page at address is unmapped. */ + { + uintptr_t query_size = pagesize; + + address += pagesize; + + /* Query larger and larger blocks, to get through the unmapped address + range with few mquery() calls. */ + for (;;) + { + if (2 * query_size > query_size) + query_size = 2 * query_size; + if (address + query_size - 1 < query_size) /* wrap around? */ + { + address_known_mapped = 0; + break; + } + if (mquery ((void *) address, query_size, 0, MAP_FIXED, -1, 0) + == (void *) -1) + { + /* Not all the interval [address .. address + query_size - 1] + is unmapped. */ + address_known_mapped = (query_size == pagesize); + break; + } + /* The interval [address .. address + query_size - 1] is + unmapped. */ + address += query_size; + } + /* Reduce the query size again, to determine the precise size of the + unmapped interval that starts at address. */ + while (query_size > pagesize) + { + query_size = query_size / 2; + if (address + query_size - 1 >= query_size) + { + if (mquery ((void *) address, query_size, 0, MAP_FIXED, -1, 0) + != (void *) -1) + { + /* The interval [address .. address + query_size - 1] is + unmapped. */ + address += query_size; + address_known_mapped = 0; + } + else + address_known_mapped = (query_size == pagesize); + } + } + /* Here again query_size = pagesize, and + either address + pagesize - 1 < pagesize, or + mquery ((void *) address, pagesize, 0, MAP_FIXED, -1, 0) fails. + So, the unmapped area ends at address. */ + } + if (address + pagesize - 1 < pagesize) /* wrap around? */ + break; + } + #endif }