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