Alexandre Julliard : ntdll: Add some workarounds for Solaris signal handling breakages.

Alexandre Julliard julliard at winehq.org
Thu Jul 10 14:07:30 CDT 2008


Module: wine
Branch: master
Commit: e5566691e214527cb6f9f35b0efd38dc7357e17c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e5566691e214527cb6f9f35b0efd38dc7357e17c

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jul 10 18:18:16 2008 +0200

ntdll: Add some workarounds for Solaris signal handling breakages.

---

 dlls/ntdll/signal_i386.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 4e0c5fa..92e3819 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -575,6 +575,58 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec )
 #endif /* __HAVE_VM86 */
 
 
+#ifdef __sun
+
+/* We have to workaround two Solaris breakages:
+ * - Solaris doesn't restore %ds and %es before calling the signal handler so exceptions in 16-bit
+ *   code crash badly.
+ * - Solaris inserts a libc trampoline to call our handler, but the trampoline expects that registers
+ *   are setup correctly. So we need to insert our own trampoline below the libc trampoline to set %gs.
+ */
+
+extern int sigaction_syscall( int sig, const struct sigaction *new, struct sigaction *old );
+__ASM_GLOBAL_FUNC( sigaction_syscall,
+                  "call 1f\n"
+                  "1:\tpopl %edx\n\t"
+                  "movl $0x62,%eax\n\t"
+                  "add $[2f-1b],%edx\n\t"
+                  "movl %esp,%ecx\n\t"
+                  "sysenter\n"
+                  "2:\tret" )
+
+/* assume the same libc handler is used for all signals */
+static void (*libc_sigacthandler)( int signal, siginfo_t *siginfo, void *context );
+
+static void wine_sigacthandler( int signal, siginfo_t *siginfo, void *sigcontext )
+{
+    struct ntdll_thread_data *thread_data;
+
+    __asm__ __volatile__("mov %ss,%ax; mov %ax,%ds; mov %ax,%es");
+
+    thread_data = (struct ntdll_thread_data *)get_current_teb()->SystemReserved2;
+    wine_set_fs( thread_data->fs );
+    wine_set_gs( thread_data->gs );
+
+    libc_sigacthandler( signal, siginfo, sigcontext );
+}
+
+static int solaris_sigaction( int sig, const struct sigaction *new, struct sigaction *old )
+{
+    struct sigaction real_act;
+
+    if (sigaction( sig, new, old ) == -1) return -1;
+
+    /* retrieve the real handler and flags with a direct syscall */
+    sigaction_syscall( sig, NULL, &real_act );
+    libc_sigacthandler = real_act.sa_sigaction;
+    real_act.sa_sigaction = wine_sigacthandler;
+    sigaction_syscall( sig, &real_act, NULL );
+    return 0;
+}
+#define sigaction(sig,new,old) solaris_sigaction(sig,new,old)
+
+#endif
+
 typedef void (WINAPI *raise_func)( EXCEPTION_RECORD *rec, CONTEXT *context );
 
 
@@ -601,8 +653,10 @@ static inline void *init_handler( const SIGCONTEXT *sigcontext, WORD *fs, WORD *
     *gs = wine_get_gs();
 #endif
 
+#ifndef __sun  /* see above for Solaris handling */
     wine_set_fs( thread_data->fs );
     wine_set_gs( thread_data->gs );
+#endif
 
     if (!wine_ldt_is_system(CS_sig(sigcontext)) ||
         !wine_ldt_is_system(SS_sig(sigcontext)))  /* 16-bit mode */




More information about the wine-cvs mailing list