All pastes #350636 Raw Edit

kumbayo

public text v1 · immutable
·published 2007-02-11 16:24 UTC
rendered paste body
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index be82a84..05dd7cc 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -261,8 +261,8 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
         }
 
         /* Call handler */
-        TRACE( "calling handler at %p code=%x flags=%x\n",
-               frame->Handler, rec->ExceptionCode, rec->ExceptionFlags );
+        TRACE( "calling handler at %p code=%x flags=%x address=%p\n",
+               frame->Handler, rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
         res = EXC_CallHandler( rec, frame, context, &dispatch, frame->Handler, EXC_RaiseHandler );
         TRACE( "handler at %p returned %x\n", frame->Handler, res );
 
@@ -302,6 +302,10 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
 {
     NTSTATUS status;
 
+    if (rec->ExceptionCode == EXCEPTION_BREAKPOINT)
+//         GET_IP(context) = (char *)GET_IP(context) - 1;
+        context->Eip = (char *)context->Eip - 1;
+
     if (first_chance)
     {
         DWORD c;
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index d18f3d2..c7fd195 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -39,6 +39,9 @@
 static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
 static NTSTATUS  (WINAPI *pNtGetContextThread)(HANDLE,CONTEXT*);
 static NTSTATUS  (WINAPI *pNtSetContextThread)(HANDLE,CONTEXT*);
+static NTSTATUS  (WINAPI *pRtlRaiseException)(EXCEPTION_RECORD *rec);
+static NTSTATUS  (WINAPI *pNtRaiseException)(EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance);
+// static PVOID (WINAPI RtlAddVectoredExceptionHandler)(ULONG first, PVECTORED_EXCEPTION_HANDLER func);
 static void *code_mem;
 
 /* Test various instruction combinations that cause a protection fault on the i386,
@@ -162,6 +165,8 @@ static const struct exception
       0, 5, STATUS_ACCESS_VIOLATION, 2, { 1, 0xffffffff } },
 };
 
+static const BYTE int3_code[] = { 0xCC, 0xc3 };  /* int 3, ret */
+
 static int got_exception;
 
 static void run_exception_test(const void *handler, const void* context,
@@ -184,6 +189,120 @@ static void run_exception_test(const void *handler, const void* context,
     pNtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
 }
 
+static DWORD handler2( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
+                      CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
+{
+//     const struct exception *except = *(const struct exception **)(frame + 1);
+//     unsigned int i, entry = except - exceptions;
+    CONTEXT ctx;
+    NTSTATUS ret;
+
+    got_exception++;
+    trace( "exception2: %08x flags:%x addr:%p context: Eip:%x\n",
+           rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, context->Eip );
+
+    memset(&ctx, 0, sizeof(ctx));
+    ctx.ContextFlags = CONTEXT_CONTROL;//CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
+    ret = pNtGetContextThread(GetCurrentThread(), &ctx);/* not fully valid as we are currently running */
+    ok(!ret, "NtGetContextThread failed\n");
+    trace( "NtGetContextThread Eip:%p\n", ctx.Eip);
+
+//     trace( "\n", context->Eip);
+
+//     ok( rec->ExceptionCode == except->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 );
+
+//     ok( rec->NumberParameters == except->nb_params,
+//         "%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
+
+    /* Most CPUs (except Intel Core apparently) report a segment limit violation */
+    /* instead of page faults for accesses beyond 0xffffffff */
+//     if (except->nb_params == 2 && except->params[1] >= 0xfffffffd)
+//     {
+//         if (rec->ExceptionInformation[0] == 0 && rec->ExceptionInformation[1] == 0xffffffff)
+//             goto skip_params;
+//     }
+
+//     for (i = 0; i < rec->NumberParameters; i++)
+//         ok( rec->ExceptionInformation[i] == except->params[i],
+//             "%u: Wrong parameter %d: %lx/%x\n",
+//             entry, i, rec->ExceptionInformation[i], except->params[i] );
+
+// 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(got_exception == 2)
+    /* Eip in context is decreased by 1
+     * Increase it again, else execution will continue in the middle of a instruction */
+    if(rec->ExceptionCode == EXCEPTION_BREAKPOINT)
+        context->Eip += 1;
+    return ExceptionContinueExecution;
+}
+
+static void run_exception_test2(DWORD exception_code, const void* context//,
+                               /*const void *code, unsigned int code_size*/)
+{
+    struct {
+        EXCEPTION_REGISTRATION_RECORD frame;
+        const void *context;
+    } exc_frame;
+    EXCEPTION_RECORD record;
+
+    record.ExceptionCode = exception_code;
+    record.ExceptionFlags = 0;
+    record.ExceptionRecord = NULL;
+    record.ExceptionAddress = NULL;//&int3_code;
+    record.NumberParameters = 0;
+    trace("raising exception: %x setting record.ExceptionAddress to %x\n", exception_code, record.ExceptionAddress);
+
+    exc_frame.frame.Handler = handler2;
+    exc_frame.frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
+    exc_frame.context = context;
+
+    pNtCurrentTeb()->Tib.ExceptionList = &exc_frame.frame;
+    pRtlRaiseException(&record);
+    pNtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
+}
+
+static void run_exception_test3(DWORD exception_code, const void* context//,
+                               /*const void *code, unsigned int code_size*/)
+{
+    struct {
+        EXCEPTION_REGISTRATION_RECORD frame;
+        const void *context;
+    } exc_frame;
+
+    EXCEPTION_RECORD record;
+    CONTEXT ctx, ctx2;
+    NTSTATUS ret;
+
+    ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+    ret = pNtGetContextThread(GetCurrentThread(), &ctx);/* not fully valid as we are currently running */
+    ok(!ret, "NtGetContextThread failed\n");
+    memcpy(&ctx2, &ctx, sizeof(ctx));
+
+    record.ExceptionCode = exception_code;
+    record.ExceptionFlags = 0;
+    record.ExceptionRecord = NULL;
+    record.ExceptionAddress = NULL;//&int3_code;
+    record.NumberParameters = 0;
+    trace("setting record.ExceptionAddress to %x\n", record.ExceptionAddress);
+
+    exc_frame.frame.Handler = handler2;
+    exc_frame.frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
+    exc_frame.context = context;
+
+    pNtCurrentTeb()->Tib.ExceptionList = &exc_frame.frame;
+    pNtRaiseException(&record, &ctx, TRUE);
+    ok(memcmp(&ctx2, &ctx, sizeof(ctx)) == 0, "context should be the same after call\n");
+    pNtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
+}
+
+
 static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
                       CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
 {
@@ -373,15 +492,15 @@ static DWORD int3_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD
 {
     ok( rec->ExceptionAddress == code_mem, "exception address not at: %p, but at %p\n",
                                            code_mem,  rec->ExceptionAddress);
-    todo_wine {
+//     todo_wine {
         ok( context->Eip == (DWORD)code_mem, "eip not at: %p, but at %#x\n", code_mem, context->Eip);
-    }
+//     }
     if(context->Eip == (DWORD)code_mem) context->Eip++; /* skip breakpoint */
 
     return ExceptionContinueExecution;
 }
 
-static const BYTE int3_code[] = { 0xCC, 0xc3 };  /* int 3, ret */
+// static const BYTE int3_code[] = { 0xCC, 0xc3 };  /* int 3, ret */
 
 
 static void test_exceptions(void)
@@ -391,7 +510,11 @@ static void test_exceptions(void)
 
     pNtGetContextThread = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtGetContextThread" );
     pNtSetContextThread = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtSetContextThread" );
-    if (!pNtGetContextThread || !pNtSetContextThread)
+    pRtlRaiseException = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlRaiseException" );
+    pNtRaiseException = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtRaiseException" );
+//     pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlAddVectoredExceptionHandler" );
+
+    if (!pNtGetContextThread || !pNtSetContextThread || !pRtlRaiseException || !pNtRaiseException /*|| !pRtlAddVectoredExceptionHandler*/)
     {
         trace( "NtGetContextThread/NtSetContextThread not found, skipping tests\n" );
         return;
@@ -399,6 +522,11 @@ static void test_exceptions(void)
 
     /* test handling of debug registers */
     run_exception_test(dreg_handler, NULL, &segfault_code, sizeof(segfault_code));
+    run_exception_test2(0x12345, NULL);
+    run_exception_test2(EXCEPTION_BREAKPOINT, NULL);
+
+     run_exception_test3(0x12345, NULL);
+     run_exception_test3(EXCEPTION_BREAKPOINT, NULL);
 
     ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
     res = pNtGetContextThread(GetCurrentThread(), &ctx);