[PATCH 4/4] ntdll: Allocate kernel stack below user stack.

Rémi Bernon rbernon at codeweavers.com
Tue Sep 28 04:22:28 CDT 2021


Gdb otherwise gets confused, as it considers the syscall frame to be
inner to the caller frame, stopping the stack unwinding early.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/ntdll/unix/thread.c  |  4 ++--
 dlls/ntdll/unix/virtual.c | 18 ++++++++++--------
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c
index e88a935ca31..9ccf03ceeb7 100644
--- a/dlls/ntdll/unix/thread.c
+++ b/dlls/ntdll/unix/thread.c
@@ -1180,7 +1180,7 @@ NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR zero_bits, SIZE_T reserve_size,
         teb->Tib.StackBase = teb->TlsSlots[WOW64_TLS_CPURESERVED] = cpu;
         teb->Tib.StackLimit = stack.StackLimit;
         teb->DeallocationStack = stack.DeallocationStack;
-        thread_data->kernel_stack = stack.StackBase;
+        thread_data->kernel_stack = (char *)stack.DeallocationStack - kernel_stack_size;
         return STATUS_SUCCESS;
 #else
         /* 64-bit stack */
@@ -1201,7 +1201,7 @@ NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR zero_bits, SIZE_T reserve_size,
     teb->Tib.StackBase = stack.StackBase;
     teb->Tib.StackLimit = stack.StackLimit;
     teb->DeallocationStack = stack.DeallocationStack;
-    thread_data->kernel_stack = stack.StackBase;
+    thread_data->kernel_stack = (char *)stack.DeallocationStack - kernel_stack_size;
     return STATUS_SUCCESS;
 }
 
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 984af2d4a21..eb878171093 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -3135,13 +3135,6 @@ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR zero_bits, SI
     VALGRIND_STACK_REGISTER( view->base, (char *)view->base + view->size );
 #endif
 
-    /* setup no access guard page */
-    set_page_vprot( view->base, page_size, VPROT_COMMITTED );
-    set_page_vprot( (char *)view->base + page_size, page_size,
-                    VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_GUARD );
-    mprotect_range( view->base, 2 * page_size, 0, 0 );
-    VIRTUAL_DEBUG_DUMP_VIEW( view );
-
     if (extra_size)
     {
         struct file_view *extra_view;
@@ -3149,16 +3142,25 @@ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR zero_bits, SI
         /* shrink the first view and create a second one for the extra size */
         /* this allows the app to free the stack without freeing the thread start portion */
         view->size -= extra_size;
-        status = create_view( &extra_view, (char *)view->base + view->size, extra_size,
+        view->base = (char *)view->base + extra_size;
+        status = create_view( &extra_view, (char *)view->base - extra_size, extra_size,
                               VPROT_READ | VPROT_WRITE | VPROT_COMMITTED );
         if (status != STATUS_SUCCESS)
         {
             view->size += extra_size;
+            view->base = (char *)view->base - extra_size;
             delete_view( view );
             goto done;
         }
     }
 
+    /* setup no access guard page */
+    set_page_vprot( view->base, page_size, VPROT_COMMITTED );
+    set_page_vprot( (char *)view->base + page_size, page_size,
+                    VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_GUARD );
+    mprotect_range( view->base, 2 * page_size, 0, 0 );
+    VIRTUAL_DEBUG_DUMP_VIEW( view );
+
     /* note: limit is lower than base since the stack grows down */
     stack->OldStackBase = 0;
     stack->OldStackLimit = 0;
-- 
2.33.0




More information about the wine-devel mailing list