"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "dlls/ntdll/unix/signal_x86_64.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_x86_64.c  (wine-5.12.tar.xz):signal_x86_64.c  (wine-5.13.tar.xz)
skipping to change at line 228 skipping to change at line 228
TRAP_x86_SEGNPFLT = 11, /* Segment not present exception */ TRAP_x86_SEGNPFLT = 11, /* Segment not present exception */
TRAP_x86_STKFLT = 12, /* Stack fault */ TRAP_x86_STKFLT = 12, /* Stack fault */
TRAP_x86_PROTFLT = 13, /* General protection fault */ TRAP_x86_PROTFLT = 13, /* General protection fault */
TRAP_x86_PAGEFLT = 14, /* Page fault */ TRAP_x86_PAGEFLT = 14, /* Page fault */
TRAP_x86_ARITHTRAP = 16, /* Floating point exception */ TRAP_x86_ARITHTRAP = 16, /* Floating point exception */
TRAP_x86_ALIGNFLT = 17, /* Alignment check exception */ TRAP_x86_ALIGNFLT = 17, /* Alignment check exception */
TRAP_x86_MCHK = 18, /* Machine check exception */ TRAP_x86_MCHK = 18, /* Machine check exception */
TRAP_x86_CACHEFLT = 19 /* Cache flush exception */ TRAP_x86_CACHEFLT = 19 /* Cache flush exception */
}; };
static const size_t teb_size = 0x2000; /* we reserve two pages for the TEB */
typedef void (*raise_func)( EXCEPTION_RECORD *rec, CONTEXT *context );
/* stack layout when calling an exception raise function */ /* stack layout when calling an exception raise function */
struct stack_layout struct stack_layout
{ {
CONTEXT context; CONTEXT context;
ULONG64 unknown[4]; ULONG64 unknown[4];
EXCEPTION_RECORD rec; EXCEPTION_RECORD rec;
ULONG64 rsi; ULONG64 rsi;
ULONG64 rdi; ULONG64 rdi;
ULONG64 rbp; ULONG64 rbp;
ULONG64 rip; ULONG64 rip;
skipping to change at line 1377 skipping to change at line 1373
#endif #endif
#ifdef ES_sig #ifdef ES_sig
ES_sig(sigcontext) = context->SegEs; ES_sig(sigcontext) = context->SegEs;
#endif #endif
#ifdef SS_sig #ifdef SS_sig
SS_sig(sigcontext) = context->SegSs; SS_sig(sigcontext) = context->SegSs;
#endif #endif
} }
/*********************************************************************** /***********************************************************************
* get_signal_stack
*
* Get the base of the signal stack for the current thread.
*/
static inline void *get_signal_stack(void)
{
return (char *)NtCurrentTeb() + teb_size;
}
/***********************************************************************
* is_inside_signal_stack
*
* Check if pointer is inside the signal stack.
*/
static inline BOOL is_inside_signal_stack( void *ptr )
{
return ((char *)ptr >= (char *)get_signal_stack() &&
(char *)ptr < (char *)get_signal_stack() + signal_stack_size);
}
/***********************************************************************
* save_context * save_context
* *
* Set the register values from a sigcontext. * Set the register values from a sigcontext.
*/ */
static void save_context( CONTEXT *context, const ucontext_t *sigcontext ) static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
{ {
context->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_DEBUG_REGISTERS; context->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_DEBUG_REGISTERS;
context->Rax = RAX_sig(sigcontext); context->Rax = RAX_sig(sigcontext);
context->Rcx = RCX_sig(sigcontext); context->Rcx = RCX_sig(sigcontext);
context->Rdx = RDX_sig(sigcontext); context->Rdx = RDX_sig(sigcontext);
skipping to change at line 1832 skipping to change at line 1807
amd64_thread_data()->dr1 = context->Dr1; amd64_thread_data()->dr1 = context->Dr1;
amd64_thread_data()->dr2 = context->Dr2; amd64_thread_data()->dr2 = context->Dr2;
amd64_thread_data()->dr3 = context->Dr3; amd64_thread_data()->dr3 = context->Dr3;
amd64_thread_data()->dr6 = context->Dr6; amd64_thread_data()->dr6 = context->Dr6;
amd64_thread_data()->dr7 = context->Dr7; amd64_thread_data()->dr7 = context->Dr7;
} }
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
extern void CDECL raise_func_trampoline( raise_func func ); extern void CDECL raise_func_trampoline( void *dispatcher );
__ASM_GLOBAL_FUNC( raise_func_trampoline, __ASM_GLOBAL_FUNC( raise_func_trampoline,
"jmpq *%r8\n\t") "jmpq *%r8\n\t")
/*********************************************************************** /***********************************************************************
* setup_exception * setup_raise_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 ) static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec , CONTEXT *context )
{ {
void *stack_ptr = (void *)(RSP_sig(sigcontext) & ~15);
struct stack_layout *stack; struct stack_layout *stack;
DWORD exception_code = 0;
stack = (struct stack_layout *)(RSP_sig(sigcontext) & ~15);
/* stack sanity checks */
if (is_inside_signal_stack( stack ))
{
ERR( "nested exception on signal stack in thread %04x eip %016lx esp %01
6lx stack %p-%p\n",
GetCurrentThreadId(), (ULONG_PTR)RIP_sig(sigcontext), (ULONG_PTR)RS
P_sig(sigcontext),
NtCurrentTeb()->Tib.StackLimit, 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 %016lx esp %
016lx stack %p-%p\n",
GetCurrentThreadId(), (ULONG_PTR)RIP_sig(sigcontext), (ULONG_PTR)R
SP_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);
ERR( "stack overflow %u bytes in thread %04x eip %016lx esp %016lx stack
%p-%p-%p\n",
diff, GetCurrentThreadId(), (ULONG_PTR)RIP_sig(sigcontext),
(ULONG_PTR)RSP_sig(sigcontext), NtCurrentTeb()->DeallocationStack,
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);
ERR( "stack overflow %u bytes in thread %04x eip %016lx esp %016lx s
tack %p-%p-%p\n",
diff, GetCurrentThreadId(), (ULONG_PTR)RIP_sig(sigcontext),
(ULONG_PTR)RSP_sig(sigcontext), NtCurrentTeb()->DeallocationSta
ck,
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase )
;
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 = (void *)RIP_sig(sigcontext);
stack->rec.NumberParameters = 0;
save_context( &stack->context, sigcontext );
return stack;
}
static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
stack )
{
NTSTATUS status; NTSTATUS status;
if (stack->rec.ExceptionCode == EXCEPTION_SINGLE_STEP) if (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 */
} }
context->EFlags &= ~0x100; /* clear single-step flag */
stack->context.EFlags &= ~0x100; /* clear single-step flag */
} }
status = send_debug_event( &stack->rec, &stack->context, TRUE ); 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;
} }
/* now modify the sigcontext to return to the raise function */ /* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Rip--;
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
stack->rec = *rec;
stack->context = *context;
RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline;
R8_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher; R8_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher;
RSP_sig(sigcontext) = (ULONG_PTR)stack; RSP_sig(sigcontext) = (ULONG_PTR)stack;
/* 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);
} }
/***********************************************************************
* 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 void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
{
CONTEXT context;
rec->ExceptionAddress = (void *)RIP_sig(sigcontext);
save_context( &context, sigcontext );
setup_raise_exception( sigcontext, rec, &context );
}
extern void WINAPI user_exception_dispatcher_trampoline( struct stack_layout *st ack, extern void WINAPI user_exception_dispatcher_trampoline( struct stack_layout *st ack,
void *pKiUserExceptionDispatcher ); void *pKiUserExceptionDispatcher );
__ASM_GLOBAL_FUNC( user_exception_dispatcher_trampoline, __ASM_GLOBAL_FUNC( user_exception_dispatcher_trampoline,
"movq %rcx,%rsp\n\t" "movq %rcx,%rsp\n\t"
"movq 0x98(%rsp),%rcx\n\t" /* context->Rsp */ "movq 0x98(%rsp),%rcx\n\t" /* context->Rsp */
"movq 0xa0(%rsp),%rbp\n\t" "movq 0xa0(%rsp),%rbp\n\t"
"movq 0xa8(%rsp),%rsi\n\t" "movq 0xa8(%rsp),%rsi\n\t"
"movq 0xb0(%rsp),%rdi\n\t" "movq 0xb0(%rsp),%rdi\n\t"
"jmpq *%rdx") "jmpq *%rdx")
void WINAPI do_call_user_exception_dispatcher(EXCEPTION_RECORD *rec, CONTEXT *co void WINAPI do_call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *c
ntext, struct stack_layout *stack) ontext,
NTSTATUS (WINAPI *dispatcher)(EXC
EPTION_RECORD*,CONTEXT*),
struct stack_layout *stack )
{ {
memmove(&stack->context, context, sizeof(*context)); memmove(&stack->context, context, sizeof(*context));
memcpy(&stack->rec, rec, sizeof(*rec)); memcpy(&stack->rec, rec, sizeof(*rec));
user_exception_dispatcher_trampoline( stack, pKiUserExceptionDispatcher ); if (stack->rec.ExceptionCode == EXCEPTION_BREAKPOINT)
{
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
stack->context.Rip--;
}
user_exception_dispatcher_trampoline( stack, dispatcher );
} }
__ASM_GLOBAL_FUNC( call_user_exception_dispatcher, __ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
"movq 0x98(%rdx),%r8\n\t" /* context->Rsp */ "movq 0x98(%rdx),%r9\n\t" /* context->Rsp */
"andq $~0xf,%r8\n\t" "andq $~0xf,%r9\n\t"
"subq $0x630,%r8\n\t" /* sizeof(struct stack_layout) */ "subq $0x630,%r9\n\t" /* sizeof(struct stack_layout) */
"cmpq %r8,%rsp\n\t" "cmpq %rsp,%r9\n\t"
"cmovbq %r8,%rsp\n\t" "cmovbq %r9,%rsp\n\t"
"jmp " __ASM_NAME("do_call_user_exception_dispatcher") "\n\t" ) "jmp " __ASM_NAME("do_call_user_exception_dispatcher") "\n\t" )
/*********************************************************************** /***********************************************************************
* is_privileged_instr * is_privileged_instr
* *
* Check if the fault location is a privileged instruction. * Check if the fault location is a privileged instruction.
*/ */
static inline DWORD is_privileged_instr( CONTEXT *context ) static inline DWORD is_privileged_instr( CONTEXT *context )
{ {
BYTE instr[16]; BYTE instr[16];
skipping to change at line 2065 skipping to change at line 1995
return 0; return 0;
} }
return 0; return 0;
} }
/*********************************************************************** /***********************************************************************
* handle_interrupt * handle_interrupt
* *
* Handle an interrupt. * Handle an interrupt.
*/ */
static inline BOOL handle_interrupt( ucontext_t *sigcontext, struct stack_layout *stack ) static inline BOOL handle_interrupt( ucontext_t *sigcontext, EXCEPTION_RECORD *r ec, CONTEXT *context )
{ {
switch (ERROR_sig(sigcontext) >> 3) switch (ERROR_sig(sigcontext) >> 3)
{ {
case 0x2c: case 0x2c:
stack->rec.ExceptionCode = STATUS_ASSERTION_FAILURE; rec->ExceptionCode = STATUS_ASSERTION_FAILURE;
break; break;
case 0x2d: case 0x2d:
switch (stack->context.Rax) switch (context->Rax)
{ {
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) */
RIP_sig(sigcontext) += 3; RIP_sig(sigcontext) += 3;
return TRUE; return TRUE;
} }
stack->context.Rip += 3; context->Rip += 3;
stack->rec.ExceptionCode = EXCEPTION_BREAKPOINT; rec->ExceptionCode = EXCEPTION_BREAKPOINT;
stack->rec.ExceptionAddress = (void *)stack->context.Rip; rec->ExceptionAddress = (void *)context->Rip;
stack->rec.NumberParameters = 1; rec->NumberParameters = 1;
stack->rec.ExceptionInformation[0] = stack->context.Rax; rec->ExceptionInformation[0] = context->Rax;
break; break;
default: default:
return FALSE; return FALSE;
} }
setup_raise_exception( sigcontext, stack ); setup_raise_exception( sigcontext, rec, context );
return TRUE; return TRUE;
} }
/********************************************************************** /**********************************************************************
* 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 };
CONTEXT context;
ucontext_t *ucontext = sigcontext; ucontext_t *ucontext = sigcontext;
stack = (struct stack_layout *)(RSP_sig(ucontext) & ~15); rec.ExceptionAddress = (void *)RIP_sig(ucontext);
save_context( &context, sigcontext );
/* check for exceptions on the signal stack caused by write watches */
if (TRAP_sig(ucontext) == TRAP_x86_PAGEFLT && is_inside_signal_stack( stack
) &&
!virtual_handle_fault( siginfo->si_addr, (ERROR_sig(ucontext) >> 1) & 0x
09, TRUE ))
{
return;
}
/* check for page fault inside the thread stack */
if (TRAP_sig(ucontext) == TRAP_x86_PAGEFLT)
{
switch (virtual_handle_stack_fault( siginfo->si_addr ))
{
case 1: /* handled */
return;
case -1: /* overflow */
stack = setup_exception( sigcontext );
stack->rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
goto done;
}
}
stack = setup_exception( sigcontext );
if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch(TRAP_sig(ucontext)) 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(ucontext); 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( ucontext, stack )) return; if ((err & 7) == 2 && handle_interrupt( ucontext, &rec, &context ))
stack->rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION; return;
stack->rec.NumberParameters = 2; rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
stack->rec.ExceptionInformation[0] = 0; rec.NumberParameters = 2;
stack->rec.ExceptionInformation[1] = 0xffffffffffffffff; rec.ExceptionInformation[0] = 0;
rec.ExceptionInformation[1] = 0xffffffffffffffff;
} }
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(ucontext) >> 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;
if (!(stack->rec.ExceptionCode = virtual_handle_fault((void *)stack->rec rec.ExceptionCode = virtual_handle_fault( siginfo->si_addr, rec.Exceptio
.ExceptionInformation[1], nInformation[0],
stack->rec.Excepti (void *)RSP_sig(ucontext) );
onInformation[0], FALSE ))) if (!rec.ExceptionCode) return;
return;
break; break;
case TRAP_x86_ALIGNFLT: /* Alignment check exception */ case TRAP_x86_ALIGNFLT: /* Alignment check exception */
stack->rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
break; break;
default: default:
ERR( "Got unexpected trap %ld\n", (ULONG_PTR)TRAP_sig(ucontext) ); ERR( "Got unexpected trap %ld\n", (ULONG_PTR)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( sigcontext, &rec, &context );
setup_raise_exception( sigcontext, 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 )
{ {
struct stack_layout *stack = setup_exception( sigcontext ); EXCEPTION_RECORD rec = { 0 };
CONTEXT context;
ucontext_t *ucontext = sigcontext;
rec.ExceptionAddress = (void *)RIP_sig(ucontext);
save_context( &context, sigcontext );
switch (siginfo->si_code) switch (siginfo->si_code)
{ {
case TRAP_TRACE: /* Single-step exception */ case TRAP_TRACE: /* Single-step exception */
case 4 /* TRAP_HWBKPT */: /* Hardware breakpoint exception */ case 4 /* TRAP_HWBKPT */: /* Hardware breakpoint exception */
stack->rec.ExceptionCode = EXCEPTION_SINGLE_STEP; rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
break; break;
case TRAP_BRKPT: /* Breakpoint exception */ case TRAP_BRKPT: /* Breakpoint exception */
#ifdef SI_KERNEL #ifdef SI_KERNEL
case SI_KERNEL: case SI_KERNEL:
#endif #endif
/* Check if this is actually icebp instruction */ /* Check if this is actually icebp instruction */
if (((unsigned char *)stack->rec.ExceptionAddress)[-1] == 0xF1) if (((unsigned char *)RIP_sig(ucontext))[-1] == 0xF1)
{ {
stack->rec.ExceptionCode = EXCEPTION_SINGLE_STEP; rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
break; break;
} }
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 = 1; rec.NumberParameters = 1;
stack->rec.ExceptionInformation[0] = 0; rec.ExceptionInformation[0] = 0;
break; break;
} }
setup_raise_exception( sigcontext, &rec, &context );
setup_raise_exception( sigcontext, stack );
} }
/********************************************************************** /**********************************************************************
* 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 )
{ {
struct stack_layout *stack = setup_exception( sigcontext ); EXCEPTION_RECORD rec = { 0 };
switch (siginfo->si_code) switch (siginfo->si_code)
{ {
case FPE_FLTSUB: case FPE_FLTSUB:
stack->rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
break; break;
case FPE_INTDIV: case FPE_INTDIV:
stack->rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
break; break;
case FPE_INTOVF: case FPE_INTOVF:
stack->rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
break; break;
case FPE_FLTDIV: case FPE_FLTDIV:
stack->rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO; rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
break; break;
case FPE_FLTOVF: case FPE_FLTOVF:
stack->rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW; rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
break; break;
case FPE_FLTUND: case FPE_FLTUND:
stack->rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW; rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
break; break;
case FPE_FLTRES: case FPE_FLTRES:
stack->rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT; rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
break; break;
case FPE_FLTINV: case FPE_FLTINV:
default: default:
stack->rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
break; break;
} }
setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, 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 *ucontext ) static void quit_handler( int signal, siginfo_t *siginfo, void *ucontext )
{ {
abort_thread(0); abort_thread(0);
skipping to change at line 2409 skipping to change at line 2318
return NULL; return NULL;
} }
#endif #endif
/********************************************************************** /**********************************************************************
* 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;
stack_t ss;
#if defined __linux__ #if defined __linux__
arch_prctl( ARCH_SET_GS, teb ); arch_prctl( ARCH_SET_GS, teb );
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
amd64_set_gsbase( teb ); amd64_set_gsbase( teb );
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
sysarch( X86_64_SET_GSBASE, &teb ); sysarch( X86_64_SET_GSBASE, &teb );
#elif defined (__APPLE__) #elif defined (__APPLE__)
__asm__ volatile (".byte 0x65\n\tmovq %0,%c1" __asm__ volatile (".byte 0x65\n\tmovq %0,%c1"
: :
skipping to change at line 2433 skipping to change at line 2341
: "r" (teb->ThreadLocalStoragePointer), "n" (FIELD_OFFSET( TEB, ThreadLocalStoragePointer))); : "r" (teb->ThreadLocalStoragePointer), "n" (FIELD_OFFSET( TEB, ThreadLocalStoragePointer)));
/* alloc_tls_slot() needs to poke a value to an address relative to each /* alloc_tls_slot() needs to poke a value to an address relative to each
thread's gsbase. Have each thread record its gsbase pointer into its thread's gsbase. Have each thread record its gsbase pointer into its
TEB so alloc_tls_slot() can find it. */ TEB so alloc_tls_slot() can find it. */
teb->Reserved5[0] = mac_thread_gsbase(); teb->Reserved5[0] = mac_thread_gsbase();
#else #else
# error Please define setting %gs for your architecture # error Please define setting %gs for your architecture
#endif #endif
ss.ss_sp = (char *)teb + teb_size;
ss.ss_size = signal_stack_size;
ss.ss_flags = 0;
if (sigaltstack(&ss, NULL) == -1) perror( "sigaltstack" );
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ volatile ("fninit; fldcw %0" : : "m" (fpu_cw)); __asm__ volatile ("fninit; fldcw %0" : : "m" (fpu_cw));
#else #else
FIXME("FPU setup not implemented for this platform.\n"); FIXME("FPU setup not implemented for this platform.\n");
#endif #endif
} }
/********************************************************************** /**********************************************************************
* signal_init_process * signal_init_process
*/ */
 End of changes. 55 change blocks. 
227 lines changed or deleted 117 lines changed or added

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