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