Alexandre Julliard : ntdll: Unwind the stack before calling exit/ abort_thread on i386 the same way we do on x86_64.

Alexandre Julliard julliard at winehq.org
Wed Oct 19 14:05:25 CDT 2011


Module: wine
Branch: master
Commit: 62b7069fa941c6ac1c923f0a7986261e290862c0
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=62b7069fa941c6ac1c923f0a7986261e290862c0

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Oct 19 12:59:58 2011 +0200

ntdll: Unwind the stack before calling exit/abort_thread on i386 the same way we do on x86_64.

---

 dlls/ntdll/ntdll_misc.h  |    4 +++
 dlls/ntdll/signal_i386.c |   49 +++++++++++++++++++++++++++++++++++++++------
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 4956537..20f1c45 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -224,6 +224,10 @@ struct ntdll_thread_data
     int                wait_fd[2];    /* 1ec/300 fd for sleeping server requests */
     BOOL               wow64_redir;   /* 1f4/308 Wow64 filesystem redirection flag */
     pthread_t          pthread_id;    /* 1f8/310 pthread thread id */
+#ifdef __i386__
+    WINE_VM86_TEB_INFO vm86;          /* 1fc vm86 private data */
+    void              *exit_frame;    /* 204 exit frame pointer */
+#endif
 };
 
 static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 6c8e8e2..e839994 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -2473,9 +2473,41 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
 }
 
 
+extern void DECLSPEC_NORETURN call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg );
+__ASM_GLOBAL_FUNC( call_thread_entry_point,
+                   "pushl %ebp\n\t"
+                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
+                   __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
+                   "movl %esp,%ebp\n\t"
+                   __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
+                   "pushl %ebx\n\t"
+                   __ASM_CFI(".cfi_rel_offset %ebx,-4\n\t")
+                   "pushl %esi\n\t"
+                   __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
+                   "pushl %edi\n\t"
+                   __ASM_CFI(".cfi_rel_offset %edi,-12\n\t")
+                   "pushl %ebp\n\t"
+                   "pushl 12(%ebp)\n\t"
+                   "pushl 8(%ebp)\n\t"
+                   "call " __ASM_NAME("call_thread_func") );
+
+extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), void *frame );
+__ASM_GLOBAL_FUNC( call_thread_exit_func,
+                   "movl 4(%esp),%eax\n\t"
+                   "movl 8(%esp),%ecx\n\t"
+                   "movl 12(%esp),%ebp\n\t"
+                   __ASM_CFI(".cfi_def_cfa %ebp,4\n\t")
+                   __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
+                   __ASM_CFI(".cfi_rel_offset %ebx,-4\n\t")
+                   __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
+                   __ASM_CFI(".cfi_rel_offset %edi,-12\n\t")
+                   "leal -20(%ebp),%esp\n\t"
+                   "pushl %eax\n\t"
+                   "call *%ecx" );
+
 /* wrapper for apps that don't declare the thread function correctly */
-extern void DECLSPEC_NORETURN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg );
-__ASM_GLOBAL_FUNC(call_thread_func,
+extern void DECLSPEC_NORETURN call_thread_func_wrapper( LPTHREAD_START_ROUTINE entry, void *arg );
+__ASM_GLOBAL_FUNC(call_thread_func_wrapper,
                   "pushl %ebp\n\t"
                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
                   __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
@@ -2490,13 +2522,14 @@ __ASM_GLOBAL_FUNC(call_thread_func,
                   "int $3" )
 
 /***********************************************************************
- *           call_thread_entry_point
+ *           call_thread_func
  */
-void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg )
+void call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg, void *frame )
 {
+    ntdll_get_thread_data()->exit_frame = frame;
     __TRY
     {
-        call_thread_func( entry, arg );
+        call_thread_func_wrapper( entry, arg );
     }
     __EXCEPT(unhandled_exception_filter)
     {
@@ -2511,7 +2544,8 @@ void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg )
  */
 void WINAPI RtlExitUserThread( ULONG status )
 {
-    exit_thread( status );
+    if (!ntdll_get_thread_data()->exit_frame) exit_thread( status );
+    call_thread_exit_func( status, exit_thread, ntdll_get_thread_data()->exit_frame );
 }
 
 /***********************************************************************
@@ -2519,7 +2553,8 @@ void WINAPI RtlExitUserThread( ULONG status )
  */
 void abort_thread( int status )
 {
-    terminate_thread( status );
+    if (!ntdll_get_thread_data()->exit_frame) terminate_thread( status );
+    call_thread_exit_func( status, terminate_thread, ntdll_get_thread_data()->exit_frame );
 }
 
 /**********************************************************************




More information about the wine-cvs mailing list