diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2006-07-13 08:34:54 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2006-07-13 08:34:54 +0000 |
commit | c7963ce29bf5a4c35c75ead5fef44c0c01d3fbfd (patch) | |
tree | c5a5794c13d6c6554b1db5550cb1481784f0f25c | |
parent | 202f17bca50a9f5dde2fad655a8ef838e89a1e4c (diff) | |
download | newlib-c7963ce29bf5a4c35c75ead5fef44c0c01d3fbfd.zip newlib-c7963ce29bf5a4c35c75ead5fef44c0c01d3fbfd.tar.gz newlib-c7963ce29bf5a4c35c75ead5fef44c0c01d3fbfd.tar.bz2 |
* Merge HEAD into cv-branch.
-rw-r--r-- | winsup/cygwin/ChangeLog | 16 | ||||
-rw-r--r-- | winsup/cygwin/exceptions.cc | 14 | ||||
-rw-r--r-- | winsup/cygwin/mmap.cc | 41 | ||||
-rw-r--r-- | winsup/cygwin/winsup.h | 2 |
4 files changed, 54 insertions, 19 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 30bfa92..f63f111 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,19 @@ +2006-07-13 Corinna Vinschen <corinna@vinschen.de> + + * exceptions.cc (_cygtls::handle_exceptions): Call new + mmap_is_attached_or_noreserve_page function in case of access violation + and allow application to retry access on noreserve pages. + * mmap.cc (mmap_is_attached_or_noreserve_page): Changed from + mmap_is_attached_page. Handle also noreserve pages now. Change + comment accordingly. + * winsup.h (mmap_is_attached_or_noreserve_page): Declare instead of + mmap_is_attached_page. + +2006-07-12 Corinna Vinschen <corinna@vinschen.de> + + * mmap.cc (mmap_record::alloc_page_map): Don't call VirtualProtect + on maps created with MAP_NORESERVE. + 2006-07-12 Corinna Vinschen <corinna@vinschen.de> * include/netdb.h: Declare rcmd, rcmd_af, rexec, rresvport, diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 4d078dd..12c6e06 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -526,17 +526,21 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT break; case STATUS_ACCESS_VIOLATION: - if (mmap_is_attached_page (e->ExceptionInformation[1])) - { + switch (mmap_is_attached_or_noreserve_page (e->ExceptionInformation[1])) + { + case 2: /* MAP_NORESERVE page, now commited. */ + return 0; + case 1: /* MAP_NORESERVE page, commit failed, or + access to mmap page beyond EOF. */ si.si_signo = SIGBUS; si.si_code = BUS_OBJERR; - } - else - { + break; + default: MEMORY_BASIC_INFORMATION m; VirtualQuery ((PVOID) e->ExceptionInformation[1], &m, sizeof m); si.si_signo = SIGSEGV; si.si_code = m.State == MEM_FREE ? SEGV_MAPERR : SEGV_ACCERR; + break; } break; diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index cee1a81..193ed7c 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -574,7 +574,7 @@ mmap_record::alloc_page_map () DWORD start_protect = gen_create_protect (); DWORD real_protect = gen_protect (); - if (real_protect != start_protect + if (real_protect != start_protect && !noreserve () && !VirtualProtect (get_address (), get_len (), real_protect, &start_protect)) system_printf ("Warning: VirtualProtect (addr: %p, len: 0x%x, " @@ -900,13 +900,25 @@ map::del_list (unsigned i) } /* This function is called from exception_handler when a segmentation - violation has happened. The function should return true, if the - faulting address (the parameter) is within attached pages. In this - case the exception_handler raises SIGBUS, as demanded by the memory - protection extension described in SUSv3 (see the mmap man page). - If false is returned, a normal SIGSEGV is raised. */ -bool -mmap_is_attached_page (ULONG_PTR addr) + violation has happened. We have two cases to check here. + + First, is it an address within "attached" mmap pages (indicated by + the __PROT_ATTACH protection, see there)? In this case the function + returns 1 and the exception_handler raises SIGBUS, as demanded by the + memory protection extension described in SUSv3 (see the mmap man + page). + + Second, check if the address is within "noreserve" mmap pages + (indicated by MAP_NORESERVE flag). If so, the function calls + VirtualAlloc to commit the page and returns 2. The exception handler + then just returns with 0 and the affected application retries the + failing memory access. If VirtualAlloc fails, the function returns + 1, so that the exception handler raises a SIGBUS, as described in the + MAP_NORESERVE man pages for Linux and Solaris. + + In any other case 0 is returned and a normal SIGSEGV is raised. */ +int +mmap_is_attached_or_noreserve_page (ULONG_PTR addr) { list *map_list; long record_idx; @@ -916,13 +928,16 @@ mmap_is_attached_page (ULONG_PTR addr) addr = rounddown (addr, pagesize); if (!(map_list = mmapped_areas.get_list_by_fd (-1))) - return false; + return 0; if ((record_idx = map_list->search_record ((caddr_t)addr, pagesize, u_addr, u_len, -1)) < 0) - return false; - if (!map_list->get_record (record_idx)->attached ()) - return false; - return true; + return 0; + if (map_list->get_record (record_idx)->attached ()) + return 1; + if (!map_list->get_record (record_idx)->noreserve ()) + return 0; + DWORD new_prot = map_list->get_record (record_idx)->gen_protect (); + return VirtualAlloc ((void *)addr, pagesize, MEM_COMMIT, new_prot) ? 2 : 1; } static caddr_t diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 9a1039d..7271514 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -299,7 +299,7 @@ size_t getsystempagesize (); /* mmap functions. */ void mmap_init (); -bool mmap_is_attached_page (ULONG_PTR); +int mmap_is_attached_or_noreserve_page (ULONG_PTR addr); int winprio_to_nice (DWORD) __attribute__ ((regparm (1))); DWORD nice_to_winprio (int &) __attribute__ ((regparm (1))); |