"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "dlls/ntdll/unix/signal_i386.c" between
wine-5.12.tar.xz and wine-5.13.tar.xz

About: Wine is an Open Source implementation of the MS Windows API on top of X, OpenGL, and Unix. Think of Wine as a compatibility layer for running Windows programs. Development release.

signal_i386.c  (wine-5.12.tar.xz):signal_i386.c  (wine-5.13.tar.xz)
skipping to change at line 428 skipping to change at line 428
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO]) #define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR]) #define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#define FPU_sig(context) ((FLOATING_SAVE_AREA *)&(context)->uc_mcontext.fpre gs.fp_reg_set.fpchip_state) #define FPU_sig(context) ((FLOATING_SAVE_AREA *)&(context)->uc_mcontext.fpre gs.fp_reg_set.fpchip_state)
#define FPUX_sig(context) NULL #define FPUX_sig(context) NULL
#else #else
#error You must define the signal context functions for your platform #error You must define the signal context functions for your platform
#endif /* linux */ #endif /* linux */
/* stack layout when calling an exception raise function */
struct stack_layout
{
void *ret_addr; /* return address from raise_generic_except
ion */
EXCEPTION_RECORD *rec_ptr; /* first arg for raise_generic_exception */
CONTEXT *context_ptr; /* second arg for raise_generic_exception *
/
CONTEXT context;
EXCEPTION_RECORD rec;
DWORD ebp;
DWORD eip;
};
static const size_t teb_size = 4096; /* we reserve one page for the TEB */
static ULONG first_ldt_entry = 32; static ULONG first_ldt_entry = 32;
enum i386_trap_code enum i386_trap_code
{ {
#if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) #if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
TRAP_x86_DIVIDE = T_DIVIDE, /* Division by zero exception */ TRAP_x86_DIVIDE = T_DIVIDE, /* Division by zero exception */
TRAP_x86_TRCTRAP = T_TRCTRAP, /* Single-step exception */ TRAP_x86_TRCTRAP = T_TRCTRAP, /* Single-step exception */
TRAP_x86_NMI = T_NMI, /* NMI interrupt */ TRAP_x86_NMI = T_NMI, /* NMI interrupt */
TRAP_x86_BPTFLT = T_BPTFLT, /* Breakpoint exception */ TRAP_x86_BPTFLT = T_BPTFLT, /* Breakpoint exception */
TRAP_x86_OFLOW = T_OFLOW, /* Overflow exception */ TRAP_x86_OFLOW = T_OFLOW, /* Overflow exception */
skipping to change at line 543 skipping to change at line 530
/*********************************************************************** /***********************************************************************
* ldt_is_system * ldt_is_system
*/ */
static inline int ldt_is_system( WORD sel ) static inline int ldt_is_system( WORD sel )
{ {
return is_gdt_sel( sel ) || ((sel >> 3) < first_ldt_entry); return is_gdt_sel( sel ) || ((sel >> 3) < first_ldt_entry);
} }
/*********************************************************************** /***********************************************************************
* get_signal_stack
*
* Get the base of the signal stack for the current thread.
*/
static inline void *get_signal_stack(void)
{
return (char *)NtCurrentTeb() + 4096;
}
/***********************************************************************
* get_current_teb * get_current_teb
* *
* Get the current teb based on the stack pointer. * Get the current teb based on the stack pointer.
*/ */
static inline TEB *get_current_teb(void) static inline TEB *get_current_teb(void)
{ {
unsigned long esp; unsigned long esp;
__asm__("movl %%esp,%0" : "=g" (esp) ); __asm__("movl %%esp,%0" : "=g" (esp) );
return (TEB *)(esp & ~signal_stack_mask); return (TEB *)(esp & ~signal_stack_mask);
} }
skipping to change at line 1371 skipping to change at line 1348
WORD inst2; WORD inst2;
} t5; } t5;
}; };
#include "poppack.h" #include "poppack.h"
/********************************************************************** /**********************************************************************
* check_atl_thunk * check_atl_thunk
* *
* Check if code destination is an ATL thunk, and emulate it if so. * Check if code destination is an ATL thunk, and emulate it if so.
*/ */
static BOOL check_atl_thunk( ucontext_t *sigcontext, struct stack_layout *stack ) static BOOL check_atl_thunk( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, CONT EXT *context )
{ {
const union atl_thunk *thunk = (const union atl_thunk *)stack->rec.Exception Information[1]; const union atl_thunk *thunk = (const union atl_thunk *)rec->ExceptionInform ation[1];
union atl_thunk thunk_copy; union atl_thunk thunk_copy;
SIZE_T thunk_len; SIZE_T thunk_len;
thunk_len = virtual_uninterrupted_read_memory( thunk, &thunk_copy, sizeof(*t hunk) ); thunk_len = virtual_uninterrupted_read_memory( thunk, &thunk_copy, sizeof(*t hunk) );
if (!thunk_len) return FALSE; if (!thunk_len) return FALSE;
if (thunk_len >= sizeof(thunk_copy.t1) && thunk_copy.t1.movl == 0x042444c7 & & if (thunk_len >= sizeof(thunk_copy.t1) && thunk_copy.t1.movl == 0x042444c7 & &
thunk_copy.t1.jmp == 0xe9) thunk_copy.t1.jmp == 0xe9)
{ {
if (!virtual_uninterrupted_write_memory( (DWORD *)stack->context.Esp + 1 , if (!virtual_uninterrupted_write_memory( (DWORD *)context->Esp + 1,
&thunk_copy.t1.this, sizeof(DWO RD) )) &thunk_copy.t1.this, sizeof(DWO RD) ))
{ {
EIP_sig(sigcontext) = (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", TRACE( "emulating ATL thunk type 1 at %p, func=%08x arg=%08x\n",
thunk, EIP_sig(sigcontext), thunk_copy.t1.this ); thunk, EIP_sig(sigcontext), thunk_copy.t1.this );
return TRUE; return TRUE;
} }
} }
else if (thunk_len >= sizeof(thunk_copy.t2) && thunk_copy.t2.movl == 0xb9 && else if (thunk_len >= sizeof(thunk_copy.t2) && thunk_copy.t2.movl == 0xb9 &&
thunk_copy.t2.jmp == 0xe9) thunk_copy.t2.jmp == 0xe9)
skipping to change at line 1427 skipping to change at line 1404
EAX_sig(sigcontext) = thunk_copy.t4.func; EAX_sig(sigcontext) = thunk_copy.t4.func;
EIP_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" , TRACE( "emulating ATL thunk type 4 at %p, func=%08x eax=%08x ecx=%08x\n" ,
thunk, EIP_sig(sigcontext), EAX_sig(sigcontext), ECX_sig(sigconte xt) ); thunk, EIP_sig(sigcontext), EAX_sig(sigcontext), ECX_sig(sigconte xt) );
return TRUE; return TRUE;
} }
else if (thunk_len >= sizeof(thunk_copy.t5) && thunk_copy.t5.inst1 == 0xff51 5859 && else if (thunk_len >= sizeof(thunk_copy.t5) && thunk_copy.t5.inst1 == 0xff51 5859 &&
thunk_copy.t5.inst2 == 0x0460 ) thunk_copy.t5.inst2 == 0x0460 )
{ {
DWORD func, sp[2]; DWORD func, sp[2];
if (virtual_uninterrupted_read_memory( (DWORD *)stack->context.Esp, sp, sizeof(sp) ) == sizeof(sp) && if (virtual_uninterrupted_read_memory( (DWORD *)context->Esp, sp, sizeof (sp) ) == sizeof(sp) &&
virtual_uninterrupted_read_memory( (DWORD *)sp[1] + 1, &func, sizeof (DWORD) ) == sizeof(DWORD) && 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]) )) !virtual_uninterrupted_write_memory( (DWORD *)context->Esp + 1, &sp[ 0], sizeof(sp[0]) ))
{ {
ECX_sig(sigcontext) = sp[0]; ECX_sig(sigcontext) = sp[0];
EAX_sig(sigcontext) = sp[1]; EAX_sig(sigcontext) = sp[1];
ESP_sig(sigcontext) += sizeof(DWORD); ESP_sig(sigcontext) += sizeof(DWORD);
EIP_sig(sigcontext) = func; EIP_sig(sigcontext) = func;
TRACE( "emulating ATL thunk type 5 at %p, func=%08x eax=%08x ecx=%08 x esp=%08x\n", TRACE( "emulating ATL thunk type 5 at %p, func=%08x eax=%08x ecx=%08 x esp=%08x\n",
thunk, EIP_sig(sigcontext), EAX_sig(sigcontext), thunk, EIP_sig(sigcontext), EAX_sig(sigcontext),
ECX_sig(sigcontext), ESP_sig(sigcontext) ); ECX_sig(sigcontext), ESP_sig(sigcontext) );
return TRUE; return TRUE;
} }
} }
return FALSE; return FALSE;
} }
/*********************************************************************** /***********************************************************************
* setup_exception_record * setup_exception_record
* *
* Setup the exception record and context on the thread stack. * Setup the exception record and context on the thread stack.
*/ */
static struct stack_layout *setup_exception_record( ucontext_t *sigcontext, void static void *setup_exception_record( ucontext_t *sigcontext, EXCEPTION_RECORD *r
*stack_ptr ) ec, CONTEXT *context )
{
struct stack_layout *stack = stack_ptr;
DWORD exception_code = 0;
/* stack sanity checks */
if ((char *)stack >= (char *)get_signal_stack() &&
(char *)stack < (char *)get_signal_stack() + signal_stack_size)
{
WINE_ERR( "nested exception on signal stack in thread %04x eip %08x esp
%08x stack %p-%p\n",
GetCurrentThreadId(), (unsigned int) EIP_sig(sigcontext),
(unsigned int) ESP_sig(sigcontext), NtCurrentTeb()->Tib.StackL
imit,
NtCurrentTeb()->Tib.StackBase );
abort_thread(1);
}
if (stack - 1 > stack || /* check for overflow in subtraction */
(char *)stack <= (char *)NtCurrentTeb()->DeallocationStack ||
(char *)stack > (char *)NtCurrentTeb()->Tib.StackBase)
{
WARN( "exception outside of stack limits in thread %04x eip %08x esp %08
x stack %p-%p\n",
GetCurrentThreadId(), (unsigned int) EIP_sig(sigcontext),
(unsigned int) ESP_sig(sigcontext), NtCurrentTeb()->Tib.StackLimit
,
NtCurrentTeb()->Tib.StackBase );
}
else if ((char *)(stack - 1) < (char *)NtCurrentTeb()->DeallocationStack + 4
096)
{
/* stack overflow on last page, unrecoverable */
UINT diff = (char *)NtCurrentTeb()->DeallocationStack + 4096 - (char *)(
stack - 1);
WINE_ERR( "stack overflow %u bytes in thread %04x eip %08x esp %08x stac
k %p-%p-%p\n",
diff, GetCurrentThreadId(), (unsigned int) EIP_sig(sigcontext)
,
(unsigned int) ESP_sig(sigcontext), NtCurrentTeb()->Deallocati
onStack,
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase
);
abort_thread(1);
}
else if ((char *)(stack - 1) < (char *)NtCurrentTeb()->Tib.StackLimit)
{
/* stack access below stack limit, may be recoverable */
switch (virtual_handle_stack_fault( stack - 1 ))
{
case 0: /* not handled */
{
UINT diff = (char *)NtCurrentTeb()->Tib.StackLimit - (char *)(stack
- 1);
WINE_ERR( "stack overflow %u bytes in thread %04x eip %08x esp %08x
stack %p-%p-%p\n",
diff, GetCurrentThreadId(), (unsigned int) EIP_sig(sigcont
ext),
(unsigned int) ESP_sig(sigcontext), NtCurrentTeb()->Deallo
cationStack,
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackB
ase );
abort_thread(1);
}
case -1: /* overflow */
exception_code = EXCEPTION_STACK_OVERFLOW;
break;
}
}
stack--; /* push the stack_layout structure */
#if defined(VALGRIND_MAKE_MEM_UNDEFINED)
VALGRIND_MAKE_MEM_UNDEFINED(stack, sizeof(*stack));
#elif defined(VALGRIND_MAKE_WRITABLE)
VALGRIND_MAKE_WRITABLE(stack, sizeof(*stack));
#endif
stack->rec.ExceptionRecord = NULL;
stack->rec.ExceptionCode = exception_code;
stack->rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
stack->rec.ExceptionAddress = (LPVOID)EIP_sig(sigcontext);
stack->rec.NumberParameters = 0;
save_context( &stack->context, sigcontext );
return stack;
}
/***********************************************************************
* setup_exception
*
* Setup a proper stack frame for the raise function, and modify the
* sigcontext so that the return from the signal handler will call
* the raise function.
*/
static struct stack_layout *setup_exception( ucontext_t *sigcontext )
{ {
void *stack = init_handler( sigcontext ); void *stack = init_handler( sigcontext );
return setup_exception_record( sigcontext, stack ); rec->ExceptionAddress = (void *)EIP_sig( sigcontext );
save_context( context, sigcontext );
return stack;
} }
/*********************************************************************** /***********************************************************************
* setup_raise_exception * setup_raise_exception
* *
* Change context to setup a call to a raise exception function. * Change context to setup a call to a raise exception function.
*/ */
static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * static void setup_raise_exception( ucontext_t *sigcontext, void *stack_ptr,
stack ) EXCEPTION_RECORD *rec, CONTEXT *context )
{ {
NTSTATUS status = send_debug_event( &stack->rec, &stack->context, TRUE ); struct
{
EXCEPTION_RECORD *rec_ptr; /* first arg for KiUserExceptionDispatc
her */
CONTEXT *context_ptr; /* second arg for KiUserExceptionDispat
cher */
CONTEXT context;
EXCEPTION_RECORD rec;
DWORD ebp;
DWORD eip;
} *stack;
NTSTATUS status = send_debug_event( rec, context, TRUE );
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
{ {
restore_context( &stack->context, sigcontext ); restore_context( context, sigcontext );
return; return;
} }
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Eip--;
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
stack->rec = *rec;
stack->context = *context;
stack->rec_ptr = &stack->rec;
stack->context_ptr = &stack->context;
ESP_sig(sigcontext) = (DWORD)stack; ESP_sig(sigcontext) = (DWORD)stack;
EIP_sig(sigcontext) = (DWORD)pKiUserExceptionDispatcher; EIP_sig(sigcontext) = (DWORD)pKiUserExceptionDispatcher;
/* clear single-step, direction, and align check flag */ /* clear single-step, direction, and align check flag */
EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000); EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000);
CS_sig(sigcontext) = get_cs(); CS_sig(sigcontext) = get_cs();
DS_sig(sigcontext) = get_ds(); DS_sig(sigcontext) = get_ds();
ES_sig(sigcontext) = get_ds(); ES_sig(sigcontext) = get_ds();
FS_sig(sigcontext) = get_fs(); FS_sig(sigcontext) = get_fs();
GS_sig(sigcontext) = get_gs(); GS_sig(sigcontext) = get_gs();
SS_sig(sigcontext) = get_ds(); SS_sig(sigcontext) = get_ds();
stack->ret_addr = (void *)0xdeadbabe; /* KiUserExceptionDispatcher must
not return */
stack->rec_ptr = &stack->rec; /* arguments for KiUserExceptionD
ispatcher */
stack->context_ptr = &stack->context;
} }
void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *cont /***********************************************************************
ext ) * setup_exception
*
* Do the full setup to raise an exception from an exception record.
*/
static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
{ {
pKiUserExceptionDispatcher( rec, context ); CONTEXT context;
void *stack = setup_exception_record( sigcontext, rec, &context );
setup_raise_exception( sigcontext, stack, rec, &context );
} }
__ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
"add $4,%esp\n\t"
"movl (%esp),%eax\n\t" /* rec */
"cmpl $0x80000003,(%eax)\n\t" /* ExceptionCode */
"jne 1f\n\t"
"movl 4(%esp),%eax\n\t" /* context */
"decl 0xb8(%eax)\n\t" /* Eip */
"1:\tjmp *8(%esp)")
/********************************************************************** /**********************************************************************
* get_fpu_code * get_fpu_code
* *
* Get the FPU exception code from the FPU status. * Get the FPU exception code from the FPU status.
*/ */
static inline DWORD get_fpu_code( const CONTEXT *context ) static inline DWORD get_fpu_code( const CONTEXT *context )
{ {
DWORD status = context->FloatSave.StatusWord & ~(context->FloatSave.ControlW ord & 0x3f); DWORD status = context->FloatSave.StatusWord & ~(context->FloatSave.ControlW ord & 0x3f);
if (status & 0x01) /* IE */ if (status & 0x01) /* IE */
skipping to change at line 1599 skipping to change at line 1532
if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW; /* UE flag */ if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW; /* UE flag */
if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT; /* PE flag */ if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT; /* PE flag */
return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */ return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */
} }
/*********************************************************************** /***********************************************************************
* handle_interrupt * handle_interrupt
* *
* Handle an interrupt. * Handle an interrupt.
*/ */
static BOOL handle_interrupt( unsigned int interrupt, ucontext_t *sigcontext, st static BOOL handle_interrupt( unsigned int interrupt, ucontext_t *sigcontext, vo
ruct stack_layout *stack ) id *stack,
EXCEPTION_RECORD *rec, CONTEXT *context )
{ {
switch(interrupt) switch(interrupt)
{ {
case 0x2d: case 0x2d:
if (!is_wow64) if (!is_wow64)
{ {
/* On Wow64, the upper DWORD of Rax contains garbage, and the debug /* On Wow64, the upper DWORD of Rax contains garbage, and the debug
* service is usually not recognized when called from usermode. */ * service is usually not recognized when called from usermode. */
switch (stack->context.Eax) switch (context->Eax)
{ {
case 1: /* BREAKPOINT_PRINT */ case 1: /* BREAKPOINT_PRINT */
case 3: /* BREAKPOINT_LOAD_SYMBOLS */ case 3: /* BREAKPOINT_LOAD_SYMBOLS */
case 4: /* BREAKPOINT_UNLOAD_SYMBOLS */ case 4: /* BREAKPOINT_UNLOAD_SYMBOLS */
case 5: /* BREAKPOINT_COMMAND_STRING (>= Win2003) */ case 5: /* BREAKPOINT_COMMAND_STRING (>= Win2003) */
EIP_sig(sigcontext) += 3; EIP_sig(sigcontext) += 3;
return TRUE; return TRUE;
} }
} }
stack->context.Eip += 3; context->Eip += 3;
stack->rec.ExceptionCode = EXCEPTION_BREAKPOINT; rec->ExceptionCode = EXCEPTION_BREAKPOINT;
stack->rec.ExceptionAddress = (void *)stack->context.Eip; rec->ExceptionAddress = (void *)context->Eip;
stack->rec.NumberParameters = is_wow64 ? 1 : 3; rec->NumberParameters = is_wow64 ? 1 : 3;
stack->rec.ExceptionInformation[0] = stack->context.Eax; rec->ExceptionInformation[0] = context->Eax;
stack->rec.ExceptionInformation[1] = stack->context.Ecx; rec->ExceptionInformation[1] = context->Ecx;
stack->rec.ExceptionInformation[2] = stack->context.Edx; rec->ExceptionInformation[2] = context->Edx;
setup_raise_exception( sigcontext, stack ); setup_raise_exception( sigcontext, stack, rec, context );
return TRUE; return TRUE;
default: default:
return FALSE; return FALSE;
} }
} }
/********************************************************************** /**********************************************************************
* segv_handler * segv_handler
* *
* Handler for SIGSEGV and related errors. * Handler for SIGSEGV and related errors.
*/ */
static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{ {
struct stack_layout *stack; EXCEPTION_RECORD rec = { 0 };
ucontext_t *context = sigcontext; CONTEXT context;
void *stack_ptr = init_handler( sigcontext ); ucontext_t *ucontext = sigcontext;
void *stack = setup_exception_record( sigcontext, &rec, &context );
/* check for exceptions on the signal stack caused by write watches */
if (TRAP_sig(context) == TRAP_x86_PAGEFLT &&
(char *)stack_ptr >= (char *)get_signal_stack() &&
(char *)stack_ptr < (char *)get_signal_stack() + signal_stack_size &&
!virtual_handle_fault( siginfo->si_addr, (ERROR_sig(context) >> 1) & 0x0
9, TRUE ))
{
return;
}
/* check for page fault inside the thread stack */
if (TRAP_sig(context) == TRAP_x86_PAGEFLT)
{
switch (virtual_handle_stack_fault( siginfo->si_addr ))
{
case 1: /* handled */
return;
case -1: /* overflow */
stack = setup_exception_record( context, stack_ptr );
stack->rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
goto done;
}
}
stack = setup_exception_record( context, stack_ptr );
if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch (TRAP_sig(context)) switch (TRAP_sig(ucontext))
{ {
case TRAP_x86_OFLOW: /* Overflow exception */ case TRAP_x86_OFLOW: /* Overflow exception */
stack->rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
break; break;
case TRAP_x86_BOUND: /* Bound range exception */ case TRAP_x86_BOUND: /* Bound range exception */
stack->rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
break; break;
case TRAP_x86_PRIVINFLT: /* Invalid opcode exception */ case TRAP_x86_PRIVINFLT: /* Invalid opcode exception */
stack->rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
break; break;
case TRAP_x86_STKFLT: /* Stack fault */ case TRAP_x86_STKFLT: /* Stack fault */
stack->rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
break; break;
case TRAP_x86_SEGNPFLT: /* Segment not present exception */ case TRAP_x86_SEGNPFLT: /* Segment not present exception */
case TRAP_x86_PROTFLT: /* General protection fault */ case TRAP_x86_PROTFLT: /* General protection fault */
{ {
WORD err = ERROR_sig(context); WORD err = ERROR_sig(ucontext);
if (!err && (stack->rec.ExceptionCode = is_privileged_instr( &stack- if (!err && (rec.ExceptionCode = is_privileged_instr( &context ))) b
>context ))) break; reak;
if ((err & 7) == 2 && handle_interrupt( err >> 3, context, stack )) if ((err & 7) == 2 && handle_interrupt( err >> 3, ucontext, stack, &
return; rec, &context )) return;
stack->rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION; rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
stack->rec.NumberParameters = 2; rec.NumberParameters = 2;
stack->rec.ExceptionInformation[0] = 0; rec.ExceptionInformation[0] = 0;
/* if error contains a LDT selector, use that as fault address */ /* if error contains a LDT selector, use that as fault address */
if ((err & 7) == 4 && !ldt_is_system( err | 7 )) if ((err & 7) == 4 && !ldt_is_system( err | 7 )) rec.ExceptionInform
stack->rec.ExceptionInformation[1] = err & ~7; ation[1] = err & ~7;
else else
{ {
stack->rec.ExceptionInformation[1] = 0xffffffff; rec.ExceptionInformation[1] = 0xffffffff;
if (check_invalid_gs( context, &stack->context )) return; if (check_invalid_gs( ucontext, &context )) return;
} }
} }
break; break;
case TRAP_x86_PAGEFLT: /* Page fault */ case TRAP_x86_PAGEFLT: /* Page fault */
stack->rec.NumberParameters = 2; rec.NumberParameters = 2;
stack->rec.ExceptionInformation[0] = (ERROR_sig(context) >> 1) & 0x09; rec.ExceptionInformation[0] = (ERROR_sig(ucontext) >> 1) & 0x09;
stack->rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr;
stack->rec.ExceptionCode = virtual_handle_fault( (void *)stack->rec.Exce rec.ExceptionCode = virtual_handle_fault( siginfo->si_addr, rec.Exceptio
ptionInformation[1], nInformation[0], stack );
stack->rec.ExceptionInf if (!rec.ExceptionCode) return;
ormation[0], FALSE ); if (rec.ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
if (!stack->rec.ExceptionCode) return; rec.ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
if (stack->rec.ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
stack->rec.ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
{ {
ULONG flags; ULONG flags;
NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags,
&flags, sizeof(flags), NULL ); &flags, sizeof(flags), NULL );
if (!(flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION) && check_a if (!(flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION) &&
tl_thunk( context, stack )) check_atl_thunk( ucontext, &rec, &context ))
return; return;
/* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */ /* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
if (!(flags & MEM_EXECUTE_OPTION_DISABLE)) if (!(flags & MEM_EXECUTE_OPTION_DISABLE)) rec.ExceptionInformation[
stack->rec.ExceptionInformation[0] = EXCEPTION_READ_FAULT; 0] = EXCEPTION_READ_FAULT;
} }
break; break;
case TRAP_x86_ALIGNFLT: /* Alignment check exception */ case TRAP_x86_ALIGNFLT: /* Alignment check exception */
/* FIXME: pass through exception handler first? */ /* FIXME: pass through exception handler first? */
if (stack->context.EFlags & 0x00040000) if (context.EFlags & 0x00040000)
{ {
EFL_sig(context) &= ~0x00040000; /* disable AC flag */ EFL_sig(ucontext) &= ~0x00040000; /* disable AC flag */
return; return;
} }
stack->rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
break; break;
default: default:
WINE_ERR( "Got unexpected trap %d\n", TRAP_sig(context) ); WINE_ERR( "Got unexpected trap %d\n", TRAP_sig(ucontext) );
/* fall through */ /* fall through */
case TRAP_x86_NMI: /* NMI interrupt */ case TRAP_x86_NMI: /* NMI interrupt */
case TRAP_x86_DNA: /* Device not available exception */ case TRAP_x86_DNA: /* Device not available exception */
case TRAP_x86_DOUBLEFLT: /* Double fault exception */ case TRAP_x86_DOUBLEFLT: /* Double fault exception */
case TRAP_x86_TSSFLT: /* Invalid TSS exception */ case TRAP_x86_TSSFLT: /* Invalid TSS exception */
case TRAP_x86_MCHK: /* Machine check exception */ case TRAP_x86_MCHK: /* Machine check exception */
case TRAP_x86_CACHEFLT: /* Cache flush exception */ case TRAP_x86_CACHEFLT: /* Cache flush exception */
stack->rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
break; break;
} }
done: setup_raise_exception( ucontext, stack, &rec, &context );
setup_raise_exception( context, stack );
} }
/********************************************************************** /**********************************************************************
* trap_handler * trap_handler
* *
* Handler for SIGTRAP. * Handler for SIGTRAP.
*/ */
static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext ) static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{ {
ucontext_t *context = sigcontext; EXCEPTION_RECORD rec = { 0 };
struct stack_layout *stack = setup_exception( context ); CONTEXT context;
ucontext_t *ucontext = sigcontext;
void *stack = setup_exception_record( sigcontext, &rec, &context );
switch (TRAP_sig(context)) switch (TRAP_sig(ucontext))
{ {
case TRAP_x86_TRCTRAP: /* Single-step exception */ case TRAP_x86_TRCTRAP: /* Single-step exception */
stack->rec.ExceptionCode = EXCEPTION_SINGLE_STEP; rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
/* when single stepping can't tell whether this is a hw bp or a /* when single stepping can't tell whether this is a hw bp or a
* single step interrupt. try to avoid as much overhead as possible * single step interrupt. try to avoid as much overhead as possible
* and only do a server call if there is any hw bp enabled. */ * and only do a server call if there is any hw bp enabled. */
if (!(stack->context.EFlags & 0x100) || (stack->context.Dr7 & 0xff)) if (!(context.EFlags & 0x100) || (context.Dr7 & 0xff))
{ {
/* (possible) hardware breakpoint, fetch the debug registers */ /* (possible) hardware breakpoint, fetch the debug registers */
DWORD saved_flags = stack->context.ContextFlags; DWORD saved_flags = context.ContextFlags;
stack->context.ContextFlags = CONTEXT_DEBUG_REGISTERS; context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
NtGetContextThread( GetCurrentThread(), &stack->context ); NtGetContextThread( GetCurrentThread(), &context );
stack->context.ContextFlags |= saved_flags; /* restore flags */ context.ContextFlags |= saved_flags; /* restore flags */
} }
stack->context.EFlags &= ~0x100; /* clear single-step flag */ context.EFlags &= ~0x100; /* clear single-step flag */
break; break;
case TRAP_x86_BPTFLT: /* Breakpoint exception */ case TRAP_x86_BPTFLT: /* Breakpoint exception */
stack->rec.ExceptionAddress = (char *)stack->rec.ExceptionAddress - 1; /* back up over the int3 instruction */ rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1; /* back up ove r the int3 instruction */
/* fall through */ /* fall through */
default: default:
stack->rec.ExceptionCode = EXCEPTION_BREAKPOINT; rec.ExceptionCode = EXCEPTION_BREAKPOINT;
stack->rec.NumberParameters = is_wow64 ? 1 : 3; rec.NumberParameters = is_wow64 ? 1 : 3;
stack->rec.ExceptionInformation[0] = 0; rec.ExceptionInformation[0] = 0;
stack->rec.ExceptionInformation[1] = 0; /* FIXME */ rec.ExceptionInformation[1] = 0; /* FIXME */
stack->rec.ExceptionInformation[2] = 0; /* FIXME */ rec.ExceptionInformation[2] = 0; /* FIXME */
break; break;
} }
setup_raise_exception( context, stack ); setup_raise_exception( sigcontext, stack, &rec, &context );
} }
/********************************************************************** /**********************************************************************
* fpe_handler * fpe_handler
* *
* Handler for SIGFPE. * Handler for SIGFPE.
*/ */
static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext ) static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{ {
ucontext_t *context = sigcontext; EXCEPTION_RECORD rec = { 0 };
struct stack_layout *stack = setup_exception( context ); CONTEXT context;
ucontext_t *ucontext = sigcontext;
void *stack = setup_exception_record( sigcontext, &rec, &context );
switch (TRAP_sig(context)) switch (TRAP_sig(ucontext))
{ {
case TRAP_x86_DIVIDE: /* Division by zero exception */ case TRAP_x86_DIVIDE: /* Division by zero exception */
stack->rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
break; break;
case TRAP_x86_FPOPFLT: /* Coprocessor segment overrun */ case TRAP_x86_FPOPFLT: /* Coprocessor segment overrun */
stack->rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
break; break;
case TRAP_x86_ARITHTRAP: /* Floating point exception */ case TRAP_x86_ARITHTRAP: /* Floating point exception */
stack->rec.ExceptionCode = get_fpu_code( &stack->context ); rec.ExceptionCode = get_fpu_code( &context );
stack->rec.ExceptionAddress = (LPVOID)stack->context.FloatSave.ErrorOffs rec.ExceptionAddress = (void *)context.FloatSave.ErrorOffset;
et;
break; break;
case TRAP_x86_CACHEFLT: /* SIMD exception */ case TRAP_x86_CACHEFLT: /* SIMD exception */
/* TODO: /* TODO:
* Behaviour only tested for divide-by-zero exceptions * Behaviour only tested for divide-by-zero exceptions
* Check for other SIMD exceptions as well */ * Check for other SIMD exceptions as well */
if(siginfo->si_code != FPE_FLTDIV && siginfo->si_code != FPE_FLTINV) if(siginfo->si_code != FPE_FLTDIV && siginfo->si_code != FPE_FLTINV)
FIXME("untested SIMD exception: %#x. Might not work correctly\n", FIXME("untested SIMD exception: %#x. Might not work correctly\n",
siginfo->si_code); siginfo->si_code);
stack->rec.ExceptionCode = STATUS_FLOAT_MULTIPLE_TRAPS; rec.ExceptionCode = STATUS_FLOAT_MULTIPLE_TRAPS;
stack->rec.NumberParameters = 1; rec.NumberParameters = 1;
/* no idea what meaning is actually behind this but that's what native d oes */ /* no idea what meaning is actually behind this but that's what native d oes */
stack->rec.ExceptionInformation[0] = 0; rec.ExceptionInformation[0] = 0;
break; break;
default: default:
WINE_ERR( "Got unexpected trap %d\n", TRAP_sig(context) ); WINE_ERR( "Got unexpected trap %d\n", TRAP_sig(ucontext) );
stack->rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
break; break;
} }
setup_raise_exception( sigcontext, stack, &rec, &context );
setup_raise_exception( context, stack );
} }
/********************************************************************** /**********************************************************************
* int_handler * int_handler
* *
* Handler for SIGINT. * Handler for SIGINT.
*/ */
static void int_handler( int signal, siginfo_t *siginfo, void *sigcontext ) static void int_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{ {
struct stack_layout *stack = setup_exception( sigcontext ); EXCEPTION_RECORD rec = { CONTROL_C_EXIT };
stack->rec.ExceptionCode = CONTROL_C_EXIT;
setup_raise_exception( sigcontext, stack ); setup_exception( sigcontext, &rec );
} }
/********************************************************************** /**********************************************************************
* abrt_handler * abrt_handler
* *
* Handler for SIGABRT. * Handler for SIGABRT.
*/ */
static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext ) static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{ {
struct stack_layout *stack = setup_exception( sigcontext ); EXCEPTION_RECORD rec = { EXCEPTION_WINE_ASSERTION, EH_NONCONTINUABLE };
stack->rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
stack->rec.ExceptionFlags = EH_NONCONTINUABLE; setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, stack );
} }
/********************************************************************** /**********************************************************************
* quit_handler * quit_handler
* *
* Handler for SIGQUIT. * Handler for SIGQUIT.
*/ */
static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext ) static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{ {
init_handler( sigcontext ); init_handler( sigcontext );
skipping to change at line 2160 skipping to change at line 2068
server_leave_uninterrupted_section( &ldt_mutex, &sigset ); server_leave_uninterrupted_section( &ldt_mutex, &sigset );
} }
/********************************************************************** /**********************************************************************
* signal_init_thread * signal_init_thread
*/ */
void signal_init_thread( TEB *teb ) void signal_init_thread( TEB *teb )
{ {
const WORD fpu_cw = 0x27f; const WORD fpu_cw = 0x27f;
struct x86_thread_data *thread_data = (struct x86_thread_data *)teb->SystemR eserved2; struct x86_thread_data *thread_data = (struct x86_thread_data *)teb->SystemR eserved2;
stack_t ss;
ss.ss_sp = (char *)teb + teb_size;
ss.ss_size = signal_stack_size;
ss.ss_flags = 0;
if (sigaltstack(&ss, NULL) == -1) perror( "sigaltstack" );
ldt_set_fs( thread_data->fs, teb ); ldt_set_fs( thread_data->fs, teb );
thread_data->gs = get_gs(); thread_data->gs = get_gs();
__asm__ volatile ("fninit; fldcw %0" : : "m" (fpu_cw)); __asm__ volatile ("fninit; fldcw %0" : : "m" (fpu_cw));
} }
/********************************************************************** /**********************************************************************
* signal_init_process * signal_init_process
*/ */
 End of changes. 59 change blocks. 
263 lines changed or deleted 144 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)