[PATCH 6/7] ntdll: Add special handling for int $0x2d exceptions.
Henri Verbeet
hverbeet at codeweavers.com
Mon Feb 15 11:18:05 CST 2016
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
dlls/ntdll/signal_i386.c | 29 ++++++++++++++++++++++++++++-
dlls/ntdll/tests/exception.c | 38 +++++++++++++++++++++++---------------
2 files changed, 51 insertions(+), 16 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index a3abbff..10235fe 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -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
*
@@ -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_UNKNOWN: /* Unknown fault code */
{
+ CONTEXT *win_context = get_exception_context( rec );
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->NumberParameters = 2;
rec->ExceptionInformation[0] = 0;
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index c9e06ea..8ec7408 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -219,6 +219,11 @@ static const struct exception
{ { 0xf1, 0x90, 0xc3 }, /* icebp; nop; ret */
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;
@@ -473,7 +478,7 @@ static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *fram
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
{
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++;
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 ||
(except->alt_status != 0 && rec->ExceptionCode == except->alt_status),
"%u: Wrong exception code %x/%x\n", entry, rec->ExceptionCode, except->status );
- ok( rec->ExceptionAddress == (char*)code_mem + except->offset,
- "%u: Wrong exception address %p/%p\n", entry,
- rec->ExceptionAddress, (char*)code_mem + except->offset );
-
- if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
- {
- ok( rec->NumberParameters == except->nb_params,
- "%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
- }
+ ok( context->Eip == (DWORD_PTR)code_mem + except->offset,
+ "%u: Unexpected eip %#x/%#lx\n", entry,
+ 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->status == STATUS_BREAKPOINT && is_wow64)
+ parameter_count = 1;
+ else if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
+ parameter_count = except->nb_params;
else
- {
- ok( rec->NumberParameters == except->alt_nb_params,
- "%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
- }
+ parameter_count = except->alt_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 */
/* instead of page faults for accesses beyond 0xffffffff */
@@ -530,7 +538,7 @@ static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *fram
skip_params:
/* 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;
return ExceptionContinueExecution;
--
2.1.4
More information about the wine-patches
mailing list