Release 960324
[wine] / loader / signal.c
1 #ifndef WINELIB
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <signal.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <time.h>
8 #include <setjmp.h>
9
10 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__svr4__)
11 #include <sys/syscall.h>
12 #include <sys/param.h>
13 #else
14 #include <syscall.h>
15 #endif
16
17 #include "debugger.h"
18 #include "miscemu.h"
19 #include "registers.h"
20 #include "win.h"
21
22 #if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
23 char * cstack[4096];
24 #endif
25
26 #ifdef linux
27 extern void ___sig_restore();
28 extern void ___masksig_restore();
29
30 /* Similar to the sigaction function in libc, except it leaves alone the
31    restorer field */
32
33 static int
34 wine_sigaction(int sig,struct sigaction * new, struct sigaction * old)
35 {
36         __asm__("int $0x80":"=a" (sig)
37                 :"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old));
38         if (sig>=0)
39                 return 0;
40         errno = -sig;
41         return -1;
42 }
43 #endif
44
45
46 #if defined(linux) 
47 static void win_fault(int signal, struct sigcontext_struct context_struct)
48 {
49     struct sigcontext_struct *context = &context_struct;
50 #elif defined(__svr4__)
51 static void win_fault(int signal, void *siginfo, ucontext_t *context)
52 {
53 #else
54 static void win_fault(int signal, int code, struct sigcontext *context)
55 {
56 #endif
57     if (signal == SIGTRAP)
58     {
59         /* If SIGTRAP not caused by breakpoint or single step 
60            don't jump into the debugger */
61         if (!(EFL_reg(context) & STEP_FLAG))
62         {
63             DBG_ADDR addr;
64             addr.seg = CS_reg(context);
65             addr.off = EIP_reg(context) - 1;
66             if (DEBUG_FindBreakpoint(&addr) == -1) return;
67         }
68     }
69     else if (signal != SIGHUP)
70     {
71         if (CS_reg(context) == WINE_CODE_SELECTOR)
72         {
73             fprintf(stderr, "Segmentation fault in Wine program (%x:%lx)."
74                             "  Please debug.\n",
75                             CS_reg(context), EIP_reg(context) );
76         }
77         else
78         {
79             if (INSTR_EmulateInstruction( context )) return;
80             fprintf( stderr, "Segmentation fault in Windows program %x:%lx.\n",
81                      CS_reg(context), EIP_reg(context) );
82         }
83     }
84
85     XUngrabPointer(display, CurrentTime);
86     XUngrabServer(display);
87     XFlush(display);
88     wine_debug( signal, context );  /* Enter our debugger */
89 }
90
91
92 /**********************************************************************
93  *              SIGNAL_SetHandler
94  */
95 static void SIGNAL_SetHandler( int sig, void (*func)() )
96 {
97     int ret;
98     struct sigaction sig_act;
99
100 #ifdef linux
101     sig_act.sa_handler = func;
102     /* Point to the top of the stack, minus 4 just in case, and make
103        it aligned  */
104     sig_act.sa_restorer = 
105         (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
106     ret = wine_sigaction( sig, &sig_act, NULL );
107 #endif  /* linux */
108
109 #if defined(__NetBSD__) || defined(__FreeBSD__)
110     sigset_t sig_mask;
111     sigemptyset(&sig_mask);
112     sig_act.sa_handler = func;
113     sig_act.sa_flags = SA_ONSTACK;
114     sig_act.sa_mask = sig_mask;
115     ret = sigaction( sig, &sig_act, NULL );
116 #endif  /* __FreeBSD__ || __NetBSD__ */
117
118 #if defined (__svr4__)
119     sigset_t sig_mask;
120     sigemptyset(&sig_mask);
121     sig_act.sa_handler = func;
122     sig_act.sa_flags = SA_ONSTACK | SA_SIGINFO;
123     sig_act.sa_mask = sig_mask;
124     ret = sigaction( sig, &sig_act, NULL );
125 #endif  /* __svr4__ */
126
127     if (ret < 0)
128     {
129         perror( "sigaction" );
130         exit(1);
131     }
132 }
133
134
135 /**********************************************************************
136  *              init_wine_signals
137  */
138 void init_wine_signals(void)
139 {
140     extern void stop_wait(int a);
141
142 #if defined(__NetBSD__) || defined(__FreeBSD__)
143     struct sigaltstack ss;
144         
145 #if !defined (__FreeBSD__) 
146     if ((ss.ss_base = malloc(MINSIGSTKSZ)) == NULL) {
147 #else
148     if ((ss.ss_sp = malloc(MINSIGSTKSZ)) == NULL) {
149 #endif
150         fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
151                 MINSIGSTKSZ);
152         exit(1);
153     }
154     ss.ss_size = MINSIGSTKSZ;
155     ss.ss_flags = 0;
156     if (sigaltstack(&ss, NULL) < 0) {
157         perror("sigstack");
158         exit(1);
159     }
160 #endif  /* __FreeBSD__ || __NetBSD__ */
161
162 #if defined (__svr4__)
163     struct sigaltstack ss;
164         
165     if ((ss.ss_sp = malloc(SIGSTKSZ) ) == NULL) {
166         fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
167                 SIGSTKSZ);
168         exit(1);
169     }
170     ss.ss_size = SIGSTKSZ;
171     ss.ss_flags = 0;
172     if (sigaltstack(&ss, NULL) < 0) {
173         perror("sigstack");
174         exit(1);
175     }
176 #endif  /* __svr4__ */
177
178     SIGNAL_SetHandler( SIGSEGV, (void (*)())win_fault );
179     SIGNAL_SetHandler( SIGILL,  (void (*)())win_fault );
180     SIGNAL_SetHandler( SIGFPE,  (void (*)())win_fault );
181     SIGNAL_SetHandler( SIGTRAP, (void (*)())win_fault ); /* For debugger */
182     SIGNAL_SetHandler( SIGHUP,  (void (*)())win_fault ); /* For forced break */
183 #ifdef SIGBUS
184     SIGNAL_SetHandler( SIGBUS,  (void (*)())win_fault );
185 #endif
186 #ifdef CONFIG_IPC
187     SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait ); /* For IPC */
188 #endif
189 }
190
191 #endif /* ifndef WINELIB */