[1/4] ntdll: Correctly handle Thumb exceptions on ARM

André Hentschel nerv at dawncrow.de
Sun Apr 29 14:43:02 CDT 2012


---
 dlls/ntdll/signal_arm.c |   28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c
index 7514b4d..93a2ff5 100644
--- a/dlls/ntdll/signal_arm.c
+++ b/dlls/ntdll/signal_arm.c
@@ -356,20 +356,33 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
     return STATUS_SUCCESS;
 }
 
+extern void raise_func_trampoline_thumb( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func );
+__ASM_GLOBAL_FUNC( raise_func_trampoline_thumb,
+                   ".thumb\n\t"
+                   "blx r2\n\t"
+                   "bkpt")
+
+extern void raise_func_trampoline_arm( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func );
+__ASM_GLOBAL_FUNC( raise_func_trampoline_arm,
+                   ".arm\n\t"
+                   "blx r2\n\t"
+                   "bkpt")
+
 /***********************************************************************
  *           setup_exception_record
  *
  * Setup the exception record and context on the thread stack.
  */
-static EXCEPTION_RECORD *setup_exception_record( SIGCONTEXT *sigcontext, void *stack_ptr, raise_func func )
+static EXCEPTION_RECORD *setup_exception( SIGCONTEXT *sigcontext, raise_func func )
 {
     struct stack_layout
     {
         CONTEXT           context;
         EXCEPTION_RECORD  rec;
-    } *stack = stack_ptr;
+    } *stack;
     DWORD exception_code = 0;
 
+    stack = (struct stack_layout *)(SP_sig(sigcontext) & ~3);
     stack--;  /* push the stack_layout structure */
 
     stack->rec.ExceptionRecord  = NULL;
@@ -382,9 +395,13 @@ static EXCEPTION_RECORD *setup_exception_record( SIGCONTEXT *sigcontext, void *s
 
     /* now modify the sigcontext to return to the raise function */
     SP_sig(sigcontext) = (DWORD)stack;
-    PC_sig(sigcontext) = (DWORD)func;
+    if (CPSR_sig(sigcontext) & 0x20)
+        PC_sig(sigcontext) = (DWORD)raise_func_trampoline_thumb;
+    else
+        PC_sig(sigcontext) = (DWORD)raise_func_trampoline_arm;
     REGn_sig(0, sigcontext) = (DWORD)&stack->rec;  /* first arg for raise_func */
     REGn_sig(1, sigcontext) = (DWORD)&stack->context; /* second arg for raise_func */
+    REGn_sig(2, sigcontext) = (DWORD)func; /* the raise_func as third arg for the trampoline */
 
 
     return &stack->rec;
@@ -542,7 +559,6 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext )
 {
     EXCEPTION_RECORD *rec;
     SIGCONTEXT *context = ucontext;
-    void *stack = (void *) (SP_sig(context) & ~3);
 
     /* check for page fault inside the thread stack */
     if (TRAP_sig(context) == TRAP_ARM_PAGEFLT &&
@@ -553,13 +569,13 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext )
         /* check if this was the last guard page */
         if ((char *)info->si_addr < (char *)NtCurrentTeb()->DeallocationStack + 2*4096)
         {
-            rec = setup_exception_record( context, stack, raise_segv_exception );
+            rec = setup_exception( context, raise_segv_exception );
             rec->ExceptionCode = EXCEPTION_STACK_OVERFLOW;
         }
         return;
     }
 
-    rec = setup_exception_record( context, stack, raise_segv_exception );
+    rec = setup_exception( context, raise_segv_exception );
     if (rec->ExceptionCode == EXCEPTION_STACK_OVERFLOW) return;
 
     switch(TRAP_sig(context))
-- 

Best Regards, André Hentschel


More information about the wine-patches mailing list