Alexandre Julliard : ntdll: Add a helper function to grow the stack on guard page faults.
Alexandre Julliard
julliard at winehq.org
Wed Jul 15 16:44:45 CDT 2020
Module: wine
Branch: master
Commit: f1e4c54104d92f57d0b3699a800c0f09ce4e8320
URL: https://source.winehq.org/git/wine.git/?a=commit;h=f1e4c54104d92f57d0b3699a800c0f09ce4e8320
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed Jul 15 10:28:57 2020 +0200
ntdll: Add a helper function to grow the stack on guard page faults.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/unix/virtual.c | 46 ++++++++++++++++++++++++++++------------------
1 file changed, 28 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index a155fc46f8..122f372978 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -2844,6 +2844,33 @@ void virtual_map_user_shared_data(void)
}
+/***********************************************************************
+ * grow_thread_stack
+ */
+static NTSTATUS grow_thread_stack( char *page )
+{
+ NTSTATUS ret = 0;
+ size_t guaranteed = max( NtCurrentTeb()->GuaranteedStackBytes, page_size * (is_win64 ? 2 : 1) );
+
+ set_page_vprot_bits( page, page_size, 0, VPROT_GUARD );
+ mprotect_range( page, page_size, 0, 0 );
+ if (page >= (char *)NtCurrentTeb()->DeallocationStack + page_size + guaranteed)
+ {
+ set_page_vprot_bits( page - page_size, page_size, VPROT_COMMITTED | VPROT_GUARD, 0 );
+ mprotect_range( page - page_size, page_size, 0, 0 );
+ }
+ else /* inside guaranteed space -> overflow exception */
+ {
+ page = (char *)NtCurrentTeb()->DeallocationStack + page_size;
+ set_page_vprot_bits( page, guaranteed, VPROT_COMMITTED, VPROT_GUARD );
+ mprotect_range( page, guaranteed, 0, 0 );
+ ret = STATUS_STACK_OVERFLOW;
+ }
+ NtCurrentTeb()->Tib.StackLimit = page;
+ return ret;
+}
+
+
/***********************************************************************
* virtual_handle_fault
*/
@@ -3045,24 +3072,7 @@ int virtual_handle_stack_fault( void *addr )
pthread_mutex_lock( &virtual_mutex ); /* no need for signal masking inside signal handler */
if (get_page_vprot( addr ) & VPROT_GUARD)
{
- size_t guaranteed = max( NtCurrentTeb()->GuaranteedStackBytes, page_size * (is_win64 ? 2 : 1) );
- char *page = ROUND_ADDR( addr, page_mask );
- set_page_vprot_bits( page, page_size, 0, VPROT_GUARD );
- mprotect_range( page, page_size, 0, 0 );
- if (page >= (char *)NtCurrentTeb()->DeallocationStack + page_size + guaranteed)
- {
- set_page_vprot_bits( page - page_size, page_size, VPROT_COMMITTED | VPROT_GUARD, 0 );
- mprotect_range( page - page_size, page_size, 0, 0 );
- ret = 1;
- }
- else /* inside guaranteed space -> overflow exception */
- {
- page = (char *)NtCurrentTeb()->DeallocationStack + page_size;
- set_page_vprot_bits( page, guaranteed, VPROT_COMMITTED, VPROT_GUARD );
- mprotect_range( page, guaranteed, 0, 0 );
- ret = -1;
- }
- NtCurrentTeb()->Tib.StackLimit = page;
+ ret = grow_thread_stack( ROUND_ADDR( addr, page_mask )) ? -1 : 1;
}
pthread_mutex_unlock( &virtual_mutex );
return ret;
More information about the wine-cvs
mailing list