Alexandre Julliard : ntdll: Handle ATL thunk emulation in signal handler on i386.

Alexandre Julliard julliard at winehq.org
Thu Sep 12 16:28:57 CDT 2019


Module: wine
Branch: master
Commit: 5501055ed585a9f0045d387a69ab5049af5797d6
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=5501055ed585a9f0045d387a69ab5049af5797d6

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Sep 12 20:50:16 2019 +0200

ntdll: Handle ATL thunk emulation in signal handler on i386.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/signal_i386.c | 109 +++++++++++++++++++----------------------------
 1 file changed, 43 insertions(+), 66 deletions(-)

diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 587940c032..11ef7c393a 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -1682,9 +1682,9 @@ union atl_thunk
  *
  * Check if code destination is an ATL thunk, and emulate it if so.
  */
-static BOOL check_atl_thunk( EXCEPTION_RECORD *rec, CONTEXT *context )
+static BOOL check_atl_thunk( ucontext_t *sigcontext, struct stack_layout *stack )
 {
-    const union atl_thunk *thunk = (const union atl_thunk *)rec->ExceptionInformation[1];
+    const union atl_thunk *thunk = (const union atl_thunk *)stack->rec.ExceptionInformation[1];
     union atl_thunk thunk_copy;
     SIZE_T thunk_len;
 
@@ -1694,62 +1694,61 @@ static BOOL check_atl_thunk( EXCEPTION_RECORD *rec, CONTEXT *context )
     if (thunk_len >= sizeof(thunk_copy.t1) && thunk_copy.t1.movl == 0x042444c7 &&
                                               thunk_copy.t1.jmp == 0xe9)
     {
-        if (!virtual_uninterrupted_write_memory( (DWORD *)context->Esp + 1,
+        if (!virtual_uninterrupted_write_memory( (DWORD *)stack->context.Esp + 1,
                                                  &thunk_copy.t1.this, sizeof(DWORD) ))
         {
-            context->Eip = (DWORD_PTR)(&thunk->t1.func + 1) + thunk_copy.t1.func;
+            EIP_sig(sigcontext) = (DWORD_PTR)(&thunk->t1.func + 1) + thunk_copy.t1.func;
             TRACE( "emulating ATL thunk type 1 at %p, func=%08x arg=%08x\n",
-                   thunk, context->Eip, thunk_copy.t1.this );
+                   thunk, EIP_sig(sigcontext), thunk_copy.t1.this );
             return TRUE;
         }
     }
     else if (thunk_len >= sizeof(thunk_copy.t2) && thunk_copy.t2.movl == 0xb9 &&
                                                    thunk_copy.t2.jmp == 0xe9)
     {
-        context->Ecx = thunk_copy.t2.this;
-        context->Eip = (DWORD_PTR)(&thunk->t2.func + 1) + thunk_copy.t2.func;
+        ECX_sig(sigcontext) = thunk_copy.t2.this;
+        EIP_sig(sigcontext) = (DWORD_PTR)(&thunk->t2.func + 1) + thunk_copy.t2.func;
         TRACE( "emulating ATL thunk type 2 at %p, func=%08x ecx=%08x\n",
-               thunk, context->Eip, context->Ecx );
+               thunk, EIP_sig(sigcontext), ECX_sig(sigcontext) );
         return TRUE;
     }
     else if (thunk_len >= sizeof(thunk_copy.t3) && thunk_copy.t3.movl1 == 0xba &&
                                                    thunk_copy.t3.movl2 == 0xb9 &&
                                                    thunk_copy.t3.jmp == 0xe1ff)
     {
-        context->Edx = thunk_copy.t3.this;
-        context->Ecx = thunk_copy.t3.func;
-        context->Eip = thunk_copy.t3.func;
+        EDX_sig(sigcontext) = thunk_copy.t3.this;
+        ECX_sig(sigcontext) = thunk_copy.t3.func;
+        EIP_sig(sigcontext) = thunk_copy.t3.func;
         TRACE( "emulating ATL thunk type 3 at %p, func=%08x ecx=%08x edx=%08x\n",
-               thunk, context->Eip, context->Ecx, context->Edx );
+               thunk, EIP_sig(sigcontext), ECX_sig(sigcontext), EDX_sig(sigcontext) );
         return TRUE;
     }
     else if (thunk_len >= sizeof(thunk_copy.t4) && thunk_copy.t4.movl1 == 0xb9 &&
                                                    thunk_copy.t4.movl2 == 0xb8 &&
                                                    thunk_copy.t4.jmp == 0xe0ff)
     {
-        context->Ecx = thunk_copy.t4.this;
-        context->Eax = thunk_copy.t4.func;
-        context->Eip = thunk_copy.t4.func;
+        ECX_sig(sigcontext) = thunk_copy.t4.this;
+        EAX_sig(sigcontext) = thunk_copy.t4.func;
+        EIP_sig(sigcontext) = thunk_copy.t4.func;
         TRACE( "emulating ATL thunk type 4 at %p, func=%08x eax=%08x ecx=%08x\n",
-               thunk, context->Eip, context->Eax, context->Ecx );
+               thunk, EIP_sig(sigcontext), EAX_sig(sigcontext), ECX_sig(sigcontext) );
         return TRUE;
     }
     else if (thunk_len >= sizeof(thunk_copy.t5) && thunk_copy.t5.inst1 == 0xff515859 &&
                                                    thunk_copy.t5.inst2 == 0x0460)
     {
-        DWORD func, stack[2];
-        if (virtual_uninterrupted_read_memory( (DWORD *)context->Esp,
-            stack, sizeof(stack) ) == sizeof(stack) &&
-            virtual_uninterrupted_read_memory( (DWORD *)stack[1] + 1,
-            &func, sizeof(DWORD) ) == sizeof(DWORD) &&
-            !virtual_uninterrupted_write_memory( (DWORD *)context->Esp + 1, &stack[0], sizeof(stack[0]) ))
+        DWORD func, sp[2];
+        if (virtual_uninterrupted_read_memory( (DWORD *)stack->context.Esp, sp, sizeof(sp) ) == sizeof(sp) &&
+            virtual_uninterrupted_read_memory( (DWORD *)sp[1] + 1, &func, sizeof(DWORD) ) == sizeof(DWORD) &&
+            !virtual_uninterrupted_write_memory( (DWORD *)stack->context.Esp + 1, &sp[0], sizeof(sp[0]) ))
         {
-            context->Ecx = stack[0];
-            context->Eax = stack[1];
-            context->Esp = context->Esp + sizeof(DWORD);
-            context->Eip = func;
+            ECX_sig(sigcontext) = sp[0];
+            EAX_sig(sigcontext) = sp[1];
+            ESP_sig(sigcontext) += sizeof(DWORD);
+            EIP_sig(sigcontext) = func;
             TRACE( "emulating ATL thunk type 5 at %p, func=%08x eax=%08x ecx=%08x esp=%08x\n",
-                   thunk, context->Eip, context->Eax, context->Ecx, context->Esp );
+                   thunk, EIP_sig(sigcontext), EAX_sig(sigcontext),
+                   ECX_sig(sigcontext), ESP_sig(sigcontext) );
             return TRUE;
         }
     }
@@ -1901,41 +1900,6 @@ static inline DWORD get_fpu_code( const CONTEXT *context )
 }
 
 
-/**********************************************************************
- *		raise_segv_exception
- */
-static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
-{
-    NTSTATUS status;
-
-    switch(rec->ExceptionCode)
-    {
-    case EXCEPTION_ACCESS_VIOLATION:
-        if (rec->NumberParameters == 2)
-        {
-            if (rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
-            {
-                ULONG flags;
-                NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags,
-                                           &flags, sizeof(flags), NULL );
-
-                if (!(flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION) && check_atl_thunk( rec, context ))
-                    goto done;
-
-                /* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
-                if (!(flags & MEM_EXECUTE_OPTION_DISABLE))
-                    rec->ExceptionInformation[0] = EXCEPTION_READ_FAULT;
-            }
-        }
-        break;
-    }
-    status = NtRaiseException( rec, context, TRUE );
-    raise_status( status, rec );
-done:
-    set_cpu_context( context );
-}
-
-
 /**********************************************************************
  *		raise_generic_exception
  *
@@ -2065,9 +2029,22 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
         stack->rec.NumberParameters = 2;
         stack->rec.ExceptionInformation[0] = (get_error_code(context) >> 1) & 0x09;
         stack->rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr;
-        if (!(stack->rec.ExceptionCode = virtual_handle_fault( (void *)stack->rec.ExceptionInformation[1],
-                                                               stack->rec.ExceptionInformation[0], FALSE )))
-            return;
+        stack->rec.ExceptionCode = virtual_handle_fault( (void *)stack->rec.ExceptionInformation[1],
+                                                         stack->rec.ExceptionInformation[0], FALSE );
+        if (!stack->rec.ExceptionCode) return;
+        if (stack->rec.ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
+            stack->rec.ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
+        {
+            ULONG flags;
+            NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags,
+                                       &flags, sizeof(flags), NULL );
+            if (!(flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION) && check_atl_thunk( context, stack ))
+                return;
+
+            /* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
+            if (!(flags & MEM_EXECUTE_OPTION_DISABLE))
+                stack->rec.ExceptionInformation[0] = EXCEPTION_READ_FAULT;
+        }
         break;
     case TRAP_x86_ALIGNFLT:  /* Alignment check exception */
         /* FIXME: pass through exception handler first? */
@@ -2091,7 +2068,7 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
         break;
     }
 done:
-    setup_raise_exception( context, stack, raise_segv_exception );
+    setup_raise_exception( context, stack, raise_generic_exception );
 }
 
 




More information about the wine-cvs mailing list