http://lists.transgaming.org/pipermail/winex-cvs-logs/2007-March/002780.html

[winex-cvs-logs] CVS: winex/dlls/ntdll Makefile.in, 1.4, 1.5
signal_i386.c, 1.39, 1.40
daniel at transgaming.org daniel at transgaming.org
Thu Mar 29 09:09:49 EST 2007

    * Previous message: [winex-cvs-logs] CVS: winex/dlls/kernel
kernel32.spec,1.25,1.26
    * Next message: [winex-cvs-logs] CVS: winex/server debugger.c,1.12,1.13
    * Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

Subject: winex/dlls/ntdll Makefile.in,1.4,1.5
signal_i386.c,1.39,1.40Update of /var/lib/cvsd/cvsroot/winex/dlls/ntdll
In directory agravaine:/tmp/cvs-serv19896/dlls/ntdll

Modified Files:
        Makefile.in signal_i386.c
Log Message:
- add Mach exception handler infrastructure
- use it for breakpoint exceptions, as SIGTRAP isn't working reliably on
  MacOSX
- modify debugger_attach()/debugger_detach() to work on MacOS X
- fix off-by-one in EIP for debug breakpoints on MacOSX, which gets debug
  exceptions working
- add wrapper functions to convert structures between mach exception info
  and bsd exception info, allowing us to use the same SIGTRAP handler as
other platforms


Index: Makefile.in
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/ntdll/Makefile.in,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Makefile.in 14 Mar 2005 17:14:05 -0000      1.4
+++ Makefile.in 29 Mar 2007 14:09:47 -0000      1.5
@@ -32,6 +32,8 @@
        time.c \
        wcstring.c

+ at [EMAIL PROTECTED] += exc_server.defs.c
+
 GEN_ASM_SRCS = \
        relay32.s

@@ -69,4 +71,10 @@
 relay32.s: $(WINEBUILD)
        $(LDPATH) $(WINEBUILD) @DLLFLAGS@ -o $@ -relay32

+ at [EMAIL PROTECTED] : exc_server.defs.h
+
+exc_server.defs.c exc_server.defs.h: /usr/include/mach/exc.defs
+       mig -server exc_server.defs.c -sheader exc_server.defs.h \
+               -user /dev/null -header /dev/null $<
+
 ### Dependencies:

Index: signal_i386.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/ntdll/signal_i386.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- signal_i386.c       29 Mar 2007 14:06:10 -0000      1.39
+++ signal_i386.c       29 Mar 2007 14:09:47 -0000      1.40
@@ -254,15 +254,20 @@
 #endif  /* __EMX__ */

 #ifdef __APPLE__
-# include <sys/ucontext.h>
 # include <sys/types.h>
+# include <sys/ucontext.h>
 # include <signal.h>
+# include <mach/mach.h>
 # include <mach/mach_init.h>
 # include <mach/i386/thread_act.h>
 # include <mach/i386/thread_status.h>
+# include "exc_server.defs.h"

 typedef ucontext_t SIGCONTEXT;

+/* NOTE - if you add or change any of these, check
build_fake_signal_context()
+   and friend to make sure it's implemented in our mach exceptions */
+
 #define EAX_sig(context)     ((context)->uc_mcontext->ss.eax)
 #define EBX_sig(context)     ((context)->uc_mcontext->ss.ebx)
 #define ECX_sig(context)     ((context)->uc_mcontext->ss.ecx)
@@ -290,7 +295,7 @@
 #define HANDLER_DEF(name) void __dynamicstackalign name( int __signal,
siginfo_t *__siginfo, SIGCONTEXT *__context )
 #define HANDLER_CONTEXT (__context)

-#define FAULT_ADDRESS        (__siginfo->si_addr)
+static mach_port_t gExceptionPort;

 #endif /* __APPLE__ */

@@ -782,7 +787,6 @@
 #  define raise_signal_if_unexpected_thread(a,b) do {} while(0)
 #endif /* USE_PTHREADS */

-
 /**********************************************************************
  *              store_debug_regs
  *
@@ -1050,6 +1054,9 @@
        /* breakpoint due to int3 (0xCC) instruction */
        /* back up over the int3 instruction */
         rec->ExceptionAddress = (char *)rec->ExceptionAddress - 1;
+#ifdef __APPLE__
+        context->Eip = context->Eip - 1;
+#endif
        /* FIXME: I forgot to check whether or not context->Eip is
         * modified as well. */
      }
@@ -1100,7 +1107,6 @@
     restore_context_fast( HANDLER_CONTEXT, fs );
 }

-
 /**********************************************************************
  *             fpe_raiser
  */
@@ -1583,6 +1589,158 @@
 #endif
 }

+
+#ifdef __APPLE__
+
+static void build_fake_signal_context (x86_thread_state32_t *thread_state,
+                                       struct ucontext *context)
+{
+    context->uc_mcontext->ss.eax = thread_state->eax;
+    context->uc_mcontext->ss.ebx = thread_state->ebx;
+    context->uc_mcontext->ss.ecx = thread_state->ecx;
+    context->uc_mcontext->ss.edx = thread_state->edx;
+    context->uc_mcontext->ss.edi = thread_state->edi;
+    context->uc_mcontext->ss.esi = thread_state->esi;
+    context->uc_mcontext->ss.ebp = thread_state->ebp;
+    context->uc_mcontext->ss.esp = thread_state->esp;
+    context->uc_mcontext->ss.ss = thread_state->ss;
+    context->uc_mcontext->ss.eflags = thread_state->eflags;
+    context->uc_mcontext->ss.eip = thread_state->eip;
+    context->uc_mcontext->ss.cs = thread_state->cs;
+    context->uc_mcontext->ss.ds = thread_state->ds;
+    context->uc_mcontext->ss.es = thread_state->es;
+    context->uc_mcontext->ss.fs = thread_state->fs;
+    context->uc_mcontext->ss.gs = thread_state->gs;
+}
+
+
+static void restore_from_signal_context(x86_thread_state32_t *thread_state,
+                                        struct ucontext *context)
+{
+    thread_state->eax = context->uc_mcontext->ss.eax;
+    thread_state->ebx = context->uc_mcontext->ss.ebx;
+    thread_state->ecx = context->uc_mcontext->ss.ecx;
+    thread_state->edx = context->uc_mcontext->ss.edx;
+    thread_state->edi = context->uc_mcontext->ss.edi;
+    thread_state->esi = context->uc_mcontext->ss.esi;
+    thread_state->ebp = context->uc_mcontext->ss.ebp;
+    thread_state->esp = context->uc_mcontext->ss.esp;
+    thread_state->ss = context->uc_mcontext->ss.ss;
+    thread_state->eflags = context->uc_mcontext->ss.eflags;
+    thread_state->eip = context->uc_mcontext->ss.eip;
+    thread_state->cs = context->uc_mcontext->ss.cs;
+    thread_state->ds = context->uc_mcontext->ss.ds;
+    thread_state->es = context->uc_mcontext->ss.es;
+    thread_state->fs = context->uc_mcontext->ss.fs;
+    thread_state->gs = context->uc_mcontext->ss.gs;
+}
+
+
+kern_return_t catch_exception_raise (mach_port_t ExceptionPort,
+                                     mach_port_t ExceptionThread,
+                                     mach_port_t ExceptionTask,
+                                     exception_type_t Exception,
+                                     exception_data_t Data,
+                                     mach_msg_type_number_t DataCount)
+{
+   return KERN_NOT_SUPPORTED;
+}
+
+
+kern_return_t catch_exception_raise_state (mach_port_t ExceptionPort,
+                                           exception_type_t Exception,
+                                           exception_data_t Data,
+                                           mach_msg_type_number_t
DataCount,
+                                           int *Flavour,
+                                           thread_state_t OldState,
+                                           mach_msg_type_number_t
OldStateCount,
+                                           thread_state_t NewState,
+                                           mach_msg_type_number_t
*NewStateCount)
+{
+   return KERN_NOT_SUPPORTED;
+}
+
+
+kern_return_t
+catch_exception_raise_state_identity (mach_port_t ExceptionPort,
+                                      mach_port_t ExceptionThread,
+                                      mach_port_t ExceptionTask,
+                                      exception_type_t Exception,
+                                      exception_data_t Data,
+                                      mach_msg_type_number_t DataCount,
+                                      int *Flavour,
+                                      thread_state_t OldState,
+                                      mach_msg_type_number_t OldStateCount,
+                                      thread_state_t NewState,
+                                      mach_msg_type_number_t
*NewStateCount)
+{
+   mach_msg_type_number_t sc = x86_EXCEPTION_STATE32_COUNT;
+   kern_return_t res;
+   struct ucontext ucontext;
+   struct mcontext uc_mcontext;
+   x86_thread_state32_t x86State;
+
+   if ((OldStateCount * sizeof (natural_t)) < sizeof
(x86_thread_state32_t))
+   {
+      fprintf (stderr, "Old state size too small!\n");
+      return KERN_INVALID_ARGUMENT;
+   }
+
+   if (((*NewStateCount) * sizeof (natural_t)) < sizeof
(x86_thread_state32_t))
+   {
+      fprintf (stderr, "New state size too small!\n");
+      return KERN_INVALID_ARGUMENT;
+   }
+
+   x86State = *(x86_thread_state32_t *)OldState;
+   memset (&uc_mcontext, 0, sizeof (uc_mcontext));
+   memset (&ucontext, 0, sizeof (ucontext));
+   ucontext.uc_mcontext = &uc_mcontext;
+
+   build_fake_signal_context (&x86State, &ucontext);
+
+   res = thread_get_state (ExceptionThread, x86_EXCEPTION_STATE32,
+                           (thread_state_t)&uc_mcontext.es, &sc);
+   if (res)
+      fprintf (stderr,
+               "thread_get_state x86_EXCEPTION_STATE32 failed! res:
0x%x\n",
+               res);
+
+   switch (Exception)
+   {
+      case EXC_BREAKPOINT:
+         trap_handler (SIGTRAP, NULL, &ucontext);
+         break;
+
+      default:
+         return KERN_NOT_SUPPORTED;
+   }
+
+   restore_from_signal_context (&x86State, &ucontext);
+
+   *(x86_thread_state32_t *)NewState = x86State;
+   *NewStateCount = sizeof (x86_thread_state32_t) / sizeof (natural_t);
+   return KERN_SUCCESS;
+}
+
+
+void *MachExceptionThread (void *Data)
+{
+   sigset_t SigSet;
+
+   /* Block all signals so that they go to the Windows threads */
+   sigfillset (&SigSet);
+   if (pthread_sigmask (SIG_BLOCK, &SigSet, NULL))
+      fprintf (stderr,
+               "WARNING: MachExceptionThread isn't blocking all
signals!\n");
+
+   mach_msg_server (exc_server, 2048, gExceptionPort, 0);
+   return NULL;
+}
+
+
+#endif
+
 /**********************************************************************
  *             SIGNAL_Init
  */
@@ -1590,6 +1748,49 @@
 {
     int have_sigaltstack = SIGNAL_SetupSignalStack();

+#ifdef __APPLE__
+    kern_return_t res;
+
+    if (!gExceptionPort)
+    {
+       pthread_t thread;
+
+       res = mach_port_allocate (mach_task_self (),
MACH_PORT_RIGHT_RECEIVE,
+                                 &gExceptionPort);
+       if (res != KERN_SUCCESS)
+       {
+          fprintf (stderr, "mach_port_allocate failed: 0x%x\n", res);
+          return FALSE;
+       }
+
+       res = mach_port_insert_right (mach_task_self (), gExceptionPort,
+                                     gExceptionPort,
MACH_MSG_TYPE_MAKE_SEND);
+       if (res != KERN_SUCCESS)
+       {
+          fprintf (stderr, "mach_port_insert_right failed: 0x%x\n", res);
+          return FALSE;
+       }
+
+       if (pthread_create (&thread, NULL, MachExceptionThread, NULL))
+       {
+          fprintf (stderr, "pthread_create failed: 0x%x\n", errno);
+          return FALSE;
+       }
+    }
+
+    res = thread_set_exception_ports (mach_thread_self (),
+                                      EXC_MASK_BREAKPOINT,
+                                      gExceptionPort,
+                                      EXCEPTION_STATE_IDENTITY,
+                                      x86_THREAD_STATE32);
+    if (res != KERN_SUCCESS)
+    {
+       fprintf (stderr, "thread_set_exception_ports failed: 0x%x\n", res);
+       return FALSE;
+    }
+
+#endif
+
     sigfillset( &all_sigs );

     /* automatic child reaping to avoid zombies */
@@ -1603,7 +1804,7 @@
 #ifdef SIGBUS
     if (set_handler( SIGBUS,  have_sigaltstack, (void
(*)())segv_handler ) == -1) goto error;
 #endif
-#ifdef SIGTRAP
+#if defined(SIGTRAP) && !defined(__APPLE__)
     if (set_handler( SIGTRAP, have_sigaltstack, (void
(*)())trap_handler ) == -1) goto error;
 #endif


Reply via email to