ntdll: Build the exception record on the signal stack first.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-07-15 10:31:19 +02:00
parent ca45eda758
commit 485c8566f1
4 changed files with 90 additions and 111 deletions

View File

@ -524,19 +524,18 @@ __ASM_GLOBAL_FUNC( raise_func_trampoline_arm,
*
* Setup the exception record and context on the thread stack.
*/
static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func func )
static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func func, EXCEPTION_RECORD *rec )
{
struct stack_layout
{
CONTEXT context;
EXCEPTION_RECORD rec;
} *stack;
EXCEPTION_RECORD rec = { 0 };
void *stack_ptr = (void *)(SP_sig(sigcontext) & ~3);
rec.ExceptionAddress = (void *)PC_sig(sigcontext);
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), &rec );
stack->rec = rec;
rec->ExceptionAddress = (void *)PC_sig(sigcontext);
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
stack->rec = *rec;
save_context( &stack->context, sigcontext );
/* now modify the sigcontext to return to the raise function */
@ -574,47 +573,37 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context
*/
static void segv_handler( int signal, siginfo_t *info, void *ucontext )
{
EXCEPTION_RECORD *rec;
EXCEPTION_RECORD rec = { 0 };
ucontext_t *context = ucontext;
/* check for page fault inside the thread stack */
if (get_trap_code(signal, context) == TRAP_ARM_PAGEFLT)
{
DWORD err = (get_error_code(context) & 0x800) != 0;
NTSTATUS status = virtual_handle_fault( info->si_addr, err, (void *)SP_sig(context) );
if (!status) return;
rec = setup_exception( context, raise_segv_exception );
rec->ExceptionCode = status;
}
else rec = setup_exception( context, raise_segv_exception );
if (rec->ExceptionCode == EXCEPTION_STACK_OVERFLOW) return;
switch(get_trap_code(signal, context))
{
case TRAP_ARM_PRIVINFLT: /* Invalid opcode exception */
rec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
break;
case TRAP_ARM_PAGEFLT: /* Page fault */
rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
rec->NumberParameters = 2;
rec->ExceptionInformation[0] = (get_error_code(context) & 0x800) != 0;
rec->ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
rec.NumberParameters = 2;
rec.ExceptionInformation[0] = (get_error_code(context) & 0x800) != 0;
rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
rec.ExceptionCode = virtual_handle_fault( info->si_addr, rec.ExceptionInformation[0],
(void *)SP_sig(context) );
if (!rec.ExceptionCode) return;
break;
case TRAP_ARM_ALIGNFLT: /* Alignment check exception */
rec->ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
break;
case TRAP_ARM_UNKNOWN: /* Unknown fault code */
rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
rec->NumberParameters = 2;
rec->ExceptionInformation[0] = 0;
rec->ExceptionInformation[1] = 0xffffffff;
rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
rec.NumberParameters = 2;
rec.ExceptionInformation[0] = 0;
rec.ExceptionInformation[1] = 0xffffffff;
break;
default:
ERR("Got unexpected trap %d\n", get_trap_code(signal, context));
rec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
break;
}
setup_exception( context, raise_segv_exception, &rec );
}

View File

@ -539,15 +539,14 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
*
* Setup the exception record and context on the thread stack.
*/
static struct stack_layout *setup_exception( ucontext_t *sigcontext )
static struct stack_layout *setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
{
EXCEPTION_RECORD rec = { 0 };
void *stack_ptr = (void *)(SP_sig(sigcontext) & ~15);
struct stack_layout *stack;
rec.ExceptionAddress = (void *)PC_sig(sigcontext);
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), &rec );
stack->rec = rec;
rec->ExceptionAddress = (void *)PC_sig(sigcontext);
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
stack->rec = *rec;
save_context( &stack->context, sigcontext );
save_fpu( &stack->context, sigcontext );
return stack;
@ -609,41 +608,32 @@ void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *cont
*/
static void segv_handler( int signal, siginfo_t *info, void *ucontext )
{
EXCEPTION_RECORD rec = { 0 };
struct stack_layout *stack;
ucontext_t *context = ucontext;
/* check for page fault inside the thread stack */
if (signal == SIGSEGV)
{
DWORD err = (get_fault_esr( context ) & 0x40) != 0;
NTSTATUS status = virtual_handle_fault( info->si_addr, err, (void *)SP_sig(context) );
if (!status) return;
stack = setup_exception( context );
stack->rec.ExceptionCode = status;
}
else stack = setup_exception( context );
if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch(signal)
{
case SIGILL: /* Invalid opcode exception */
stack->rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
break;
case SIGSEGV: /* Segmentation fault */
stack->rec.NumberParameters = 2;
stack->rec.ExceptionInformation[0] = (get_fault_esr( context ) & 0x40) != 0;
stack->rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
rec.NumberParameters = 2;
rec.ExceptionInformation[0] = (get_fault_esr( context ) & 0x40) != 0;
rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
rec.ExceptionCode = virtual_handle_fault( info->si_addr, rec.ExceptionInformation[0],
(void *)SP_sig(context) );
if (!rec.ExceptionCode) return;
break;
case SIGBUS: /* Alignment check exception */
stack->rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
break;
default:
ERR("Got unexpected signal %i\n", signal);
stack->rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
break;
}
done:
stack = setup_exception( context, &rec );
setup_raise_exception( context, stack );
}
@ -655,20 +645,22 @@ done:
*/
static void trap_handler( int signal, siginfo_t *info, void *ucontext )
{
EXCEPTION_RECORD rec = { 0 };
ucontext_t *context = ucontext;
struct stack_layout *stack = setup_exception( context );
struct stack_layout *stack;
switch (info->si_code)
{
case TRAP_TRACE:
stack->rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
break;
case TRAP_BRKPT:
default:
stack->rec.ExceptionCode = EXCEPTION_BREAKPOINT;
stack->context.Pc += 4;
rec.ExceptionCode = EXCEPTION_BREAKPOINT;
PC_sig(context) += 4;
break;
}
stack = setup_exception( context, &rec );
setup_raise_exception( context, stack );
}
@ -680,52 +672,54 @@ static void trap_handler( int signal, siginfo_t *info, void *ucontext )
*/
static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
struct stack_layout *stack = setup_exception( sigcontext );
EXCEPTION_RECORD rec = { 0 };
struct stack_layout *stack;
switch (siginfo->si_code & 0xffff )
{
#ifdef FPE_FLTSUB
case FPE_FLTSUB:
stack->rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
break;
#endif
#ifdef FPE_INTDIV
case FPE_INTDIV:
stack->rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
break;
#endif
#ifdef FPE_INTOVF
case FPE_INTOVF:
stack->rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
break;
#endif
#ifdef FPE_FLTDIV
case FPE_FLTDIV:
stack->rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
break;
#endif
#ifdef FPE_FLTOVF
case FPE_FLTOVF:
stack->rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
break;
#endif
#ifdef FPE_FLTUND
case FPE_FLTUND:
stack->rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
break;
#endif
#ifdef FPE_FLTRES
case FPE_FLTRES:
stack->rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
break;
#endif
#ifdef FPE_FLTINV
case FPE_FLTINV:
#endif
default:
stack->rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
break;
}
stack = setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, stack );
}
@ -737,9 +731,8 @@ static void fpe_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 );
stack->rec.ExceptionCode = CONTROL_C_EXIT;
EXCEPTION_RECORD rec = { CONTROL_C_EXIT };
struct stack_layout *stack = setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, stack );
}
@ -751,10 +744,8 @@ static void int_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 );
stack->rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
stack->rec.ExceptionFlags = EH_NONCONTINUABLE;
EXCEPTION_RECORD rec = { EXCEPTION_WINE_ASSERTION, EH_NONCONTINUABLE };
struct stack_layout *stack = setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, stack );
}

View File

@ -1458,14 +1458,14 @@ static BOOL check_atl_thunk( ucontext_t *sigcontext, struct stack_layout *stack
*
* Setup the exception record and context on the thread stack.
*/
static struct stack_layout *setup_exception_record( ucontext_t *sigcontext, void *stack_ptr )
static struct stack_layout *setup_exception_record( ucontext_t *sigcontext, void *stack_ptr,
EXCEPTION_RECORD *rec )
{
EXCEPTION_RECORD rec = { 0 };
struct stack_layout *stack;
rec.ExceptionAddress = (void *)EIP_sig(sigcontext);
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), &rec );
stack->rec = rec;
rec->ExceptionAddress = (void *)EIP_sig(sigcontext);
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
stack->rec = *rec;
save_context( &stack->context, sigcontext );
return stack;
}
@ -1478,11 +1478,11 @@ static struct stack_layout *setup_exception_record( ucontext_t *sigcontext, void
* sigcontext so that the return from the signal handler will call
* the raise function.
*/
static struct stack_layout *setup_exception( ucontext_t *sigcontext )
static struct stack_layout *setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
{
void *stack = init_handler( sigcontext );
return setup_exception_record( sigcontext, stack );
return setup_exception_record( sigcontext, stack, rec );
}
@ -1600,6 +1600,7 @@ static BOOL handle_interrupt( unsigned int interrupt, ucontext_t *sigcontext, st
*/
static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec = { 0 };
struct stack_layout *stack;
ucontext_t *context = sigcontext;
void *stack_ptr = init_handler( sigcontext );
@ -1608,13 +1609,11 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
if (TRAP_sig(context) == TRAP_x86_PAGEFLT)
{
DWORD err = (ERROR_sig(context) >> 1) & 0x09;
NTSTATUS status = virtual_handle_fault( siginfo->si_addr, err, stack_ptr );
if (!status) return;
stack = setup_exception_record( context, stack_ptr );
stack->rec.ExceptionCode = status;
rec.ExceptionCode = virtual_handle_fault( siginfo->si_addr, err, stack_ptr );
if (!rec.ExceptionCode) return;
}
else stack = setup_exception_record( context, stack_ptr );
stack = setup_exception_record( context, stack_ptr, &rec );
if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch (TRAP_sig(context))
@ -1701,8 +1700,9 @@ done:
*/
static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec = { 0 };
ucontext_t *context = sigcontext;
struct stack_layout *stack = setup_exception( context );
struct stack_layout *stack = setup_exception( context, &rec );
switch (TRAP_sig(context))
{
@ -1743,8 +1743,9 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
*/
static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec = { 0 };
ucontext_t *context = sigcontext;
struct stack_layout *stack = setup_exception( context );
struct stack_layout *stack = setup_exception( context, &rec );
switch (TRAP_sig(context))
{
@ -1788,8 +1789,8 @@ static void fpe_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 );
stack->rec.ExceptionCode = CONTROL_C_EXIT;
EXCEPTION_RECORD rec = { CONTROL_C_EXIT };
struct stack_layout *stack = setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, stack );
}
@ -1800,9 +1801,8 @@ static void int_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 );
stack->rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
stack->rec.ExceptionFlags = EH_NONCONTINUABLE;
EXCEPTION_RECORD rec = { EXCEPTION_WINE_ASSERTION, EH_NONCONTINUABLE };
struct stack_layout *stack = setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, stack );
}

View File

@ -1833,15 +1833,14 @@ __ASM_GLOBAL_FUNC( raise_func_trampoline,
* sigcontext so that the return from the signal handler will call
* the raise function.
*/
static struct stack_layout *setup_exception( ucontext_t *sigcontext )
static struct stack_layout *setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
{
EXCEPTION_RECORD rec = { 0 };
void *stack_ptr = (void *)(RSP_sig(sigcontext) & ~15);
struct stack_layout *stack;
rec.ExceptionAddress = (void *)RIP_sig(sigcontext);
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), &rec );
stack->rec = rec;
rec->ExceptionAddress = (void *)RIP_sig(sigcontext);
stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
stack->rec = *rec;
save_context( &stack->context, sigcontext );
return stack;
}
@ -2049,6 +2048,7 @@ static inline BOOL handle_interrupt( ucontext_t *sigcontext, struct stack_layout
*/
static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec = { 0 };
struct stack_layout *stack;
ucontext_t *ucontext = sigcontext;
@ -2058,13 +2058,11 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
if (TRAP_sig(ucontext) == TRAP_x86_PAGEFLT)
{
DWORD err = (ERROR_sig(ucontext) >> 1) & 0x09;
NTSTATUS status = virtual_handle_fault( siginfo->si_addr, err, stack );
if (!status) return;
stack = setup_exception( sigcontext );
stack->rec.ExceptionCode = status;
rec.ExceptionCode = virtual_handle_fault( siginfo->si_addr, err, stack );
if (!rec.ExceptionCode) return;
}
else stack = setup_exception( sigcontext );
stack = setup_exception( sigcontext, &rec );
if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch(TRAP_sig(ucontext))
@ -2125,7 +2123,8 @@ done:
*/
static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
struct stack_layout *stack = setup_exception( sigcontext );
EXCEPTION_RECORD rec = { 0 };
struct stack_layout *stack = setup_exception( sigcontext, &rec );
switch (siginfo->si_code)
{
@ -2163,7 +2162,8 @@ static void trap_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 };
struct stack_layout *stack = setup_exception( sigcontext, &rec );
switch (siginfo->si_code)
{
@ -2205,8 +2205,8 @@ static void fpe_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 );
stack->rec.ExceptionCode = CONTROL_C_EXIT;
EXCEPTION_RECORD rec = { CONTROL_C_EXIT };
struct stack_layout *stack = setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, stack );
}
@ -2218,9 +2218,8 @@ static void int_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 );
stack->rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
stack->rec.ExceptionFlags = EH_NONCONTINUABLE;
EXCEPTION_RECORD rec = { EXCEPTION_WINE_ASSERTION, EH_NONCONTINUABLE };
struct stack_layout *stack = setup_exception( sigcontext, &rec );
setup_raise_exception( sigcontext, stack );
}