ntdll: Add special handling for int $0x2d exceptions.
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
c62fe153c6
commit
e65c89f1c5
|
@ -1553,6 +1553,31 @@ static inline DWORD is_privileged_instr( CONTEXT *context )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* handle_interrupt
|
||||||
|
*
|
||||||
|
* Handle an interrupt.
|
||||||
|
*/
|
||||||
|
static inline BOOL handle_interrupt( unsigned int interrupt, EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||||
|
{
|
||||||
|
switch(interrupt)
|
||||||
|
{
|
||||||
|
case 0x2d:
|
||||||
|
context->Eip += 3;
|
||||||
|
rec->ExceptionCode = EXCEPTION_BREAKPOINT;
|
||||||
|
rec->ExceptionAddress = (void *)context->Eip;
|
||||||
|
rec->NumberParameters = is_wow64 ? 1 : 3;
|
||||||
|
rec->ExceptionInformation[0] = context->Eax;
|
||||||
|
rec->ExceptionInformation[1] = context->Ecx;
|
||||||
|
rec->ExceptionInformation[2] = context->Edx;
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* check_invalid_gs
|
* check_invalid_gs
|
||||||
*
|
*
|
||||||
|
@ -2072,8 +2097,10 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
|
||||||
case TRAP_x86_PROTFLT: /* General protection fault */
|
case TRAP_x86_PROTFLT: /* General protection fault */
|
||||||
case TRAP_x86_UNKNOWN: /* Unknown fault code */
|
case TRAP_x86_UNKNOWN: /* Unknown fault code */
|
||||||
{
|
{
|
||||||
|
CONTEXT *win_context = get_exception_context( rec );
|
||||||
WORD err = get_error_code(context);
|
WORD err = get_error_code(context);
|
||||||
if (!err && (rec->ExceptionCode = is_privileged_instr( get_exception_context(rec) ))) break;
|
if (!err && (rec->ExceptionCode = is_privileged_instr( win_context ))) break;
|
||||||
|
if ((err & 7) == 2 && handle_interrupt( err >> 3, rec, win_context )) break;
|
||||||
rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
|
rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
|
||||||
rec->NumberParameters = 2;
|
rec->NumberParameters = 2;
|
||||||
rec->ExceptionInformation[0] = 0;
|
rec->ExceptionInformation[0] = 0;
|
||||||
|
|
|
@ -219,6 +219,11 @@ static const struct exception
|
||||||
|
|
||||||
{ { 0xf1, 0x90, 0xc3 }, /* icebp; nop; ret */
|
{ { 0xf1, 0x90, 0xc3 }, /* icebp; nop; ret */
|
||||||
1, 1, FALSE, STATUS_SINGLE_STEP, 0 },
|
1, 1, FALSE, STATUS_SINGLE_STEP, 0 },
|
||||||
|
{ { 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, /* mov $0xb8b8b8b8, %eax */
|
||||||
|
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, /* mov $0xb9b9b9b9, %ecx */
|
||||||
|
0xba, 0xba, 0xba, 0xba, 0xba, /* mov $0xbabababa, %edx */
|
||||||
|
0xcd, 0x2d, 0xc3 }, /* int $0x2d; ret */
|
||||||
|
17, 0, FALSE, STATUS_BREAKPOINT, 3, { 0xb8b8b8b8, 0xb9b9b9b9, 0xbabababa } },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int got_exception;
|
static int got_exception;
|
||||||
|
@ -473,7 +478,7 @@ static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *fram
|
||||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||||
{
|
{
|
||||||
const struct exception *except = *(const struct exception **)(frame + 1);
|
const struct exception *except = *(const struct exception **)(frame + 1);
|
||||||
unsigned int i, entry = except - exceptions;
|
unsigned int i, parameter_count, entry = except - exceptions;
|
||||||
|
|
||||||
got_exception++;
|
got_exception++;
|
||||||
trace( "exception %u: %x flags:%x addr:%p\n",
|
trace( "exception %u: %x flags:%x addr:%p\n",
|
||||||
|
@ -482,20 +487,23 @@ static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *fram
|
||||||
ok( rec->ExceptionCode == except->status ||
|
ok( rec->ExceptionCode == except->status ||
|
||||||
(except->alt_status != 0 && rec->ExceptionCode == except->alt_status),
|
(except->alt_status != 0 && rec->ExceptionCode == except->alt_status),
|
||||||
"%u: Wrong exception code %x/%x\n", entry, rec->ExceptionCode, except->status );
|
"%u: Wrong exception code %x/%x\n", entry, rec->ExceptionCode, except->status );
|
||||||
ok( rec->ExceptionAddress == (char*)code_mem + except->offset,
|
ok( context->Eip == (DWORD_PTR)code_mem + except->offset,
|
||||||
"%u: Wrong exception address %p/%p\n", entry,
|
"%u: Unexpected eip %#x/%#lx\n", entry,
|
||||||
rec->ExceptionAddress, (char*)code_mem + except->offset );
|
context->Eip, (DWORD_PTR)code_mem + except->offset );
|
||||||
|
ok( rec->ExceptionAddress == (char*)context->Eip ||
|
||||||
|
(rec->ExceptionCode == STATUS_BREAKPOINT && rec->ExceptionAddress == (char*)context->Eip + 1),
|
||||||
|
"%u: Unexpected exception address %p/%p\n", entry,
|
||||||
|
rec->ExceptionAddress, (char*)context->Eip );
|
||||||
|
|
||||||
if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
|
if (except->status == STATUS_BREAKPOINT && is_wow64)
|
||||||
{
|
parameter_count = 1;
|
||||||
ok( rec->NumberParameters == except->nb_params,
|
else if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
|
||||||
"%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
|
parameter_count = except->nb_params;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
parameter_count = except->alt_nb_params;
|
||||||
ok( rec->NumberParameters == except->alt_nb_params,
|
|
||||||
"%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
|
ok( rec->NumberParameters == parameter_count,
|
||||||
}
|
"%u: Unexpected parameter count %u/%u\n", entry, rec->NumberParameters, parameter_count );
|
||||||
|
|
||||||
/* Most CPUs (except Intel Core apparently) report a segment limit violation */
|
/* Most CPUs (except Intel Core apparently) report a segment limit violation */
|
||||||
/* instead of page faults for accesses beyond 0xffffffff */
|
/* instead of page faults for accesses beyond 0xffffffff */
|
||||||
|
@ -530,7 +538,7 @@ static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *fram
|
||||||
|
|
||||||
skip_params:
|
skip_params:
|
||||||
/* don't handle exception if it's not the address we expected */
|
/* don't handle exception if it's not the address we expected */
|
||||||
if (rec->ExceptionAddress != (char*)code_mem + except->offset) return ExceptionContinueSearch;
|
if (context->Eip != (DWORD_PTR)code_mem + except->offset) return ExceptionContinueSearch;
|
||||||
|
|
||||||
context->Eip += except->length;
|
context->Eip += except->length;
|
||||||
return ExceptionContinueExecution;
|
return ExceptionContinueExecution;
|
||||||
|
|
Loading…
Reference in New Issue