Release 960516
[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 #include <sys/time.h>
11 #include <sys/timeb.h>
12
13 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__svr4__) || defined(_SCO_DS)
14 #ifndef _SCO_DS
15 #include <sys/syscall.h>
16 #endif
17 #include <sys/param.h>
18 #else
19 #include <syscall.h>
20 #endif
21
22 #include "debugger.h"
23 #include "miscemu.h"
24 #include "registers.h"
25 #include "win.h"
26
27 #if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
28 char * cstack[4096];
29 #endif
30
31 #ifdef linux
32 extern void ___sig_restore();
33 extern void ___masksig_restore();
34
35 /* Similar to the sigaction function in libc, except it leaves alone the
36    restorer field */
37
38 static int
39 wine_sigaction(int sig,struct sigaction * new, struct sigaction * old)
40 {
41         __asm__("int $0x80":"=a" (sig)
42                 :"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old));
43         if (sig>=0)
44                 return 0;
45         errno = -sig;
46         return -1;
47 }
48 #endif
49
50
51 /**********************************************************************
52  *              wine_timer
53  *
54  * SIGALRM handler.
55  */
56 #ifdef linux
57 static void wine_timer(int signal, struct sigcontext_struct context_struct)
58 {
59 #elif defined(__svr4__)
60 static void wine_timer(int signal, void *siginfo, ucontext_t *context)
61 {
62 #else
63 static void wine_timer(int signal, int code, struct sigcontext *context)
64 {
65 #endif
66     /* Should do real-time timers here */
67
68     DOSMEM_Tick();
69 }
70
71
72 /**********************************************************************
73  *              win_fault
74  *
75  * Segfault handler.
76  */
77 #ifdef linux
78 static void win_fault(int signal, struct sigcontext_struct context_struct)
79 {
80     struct sigcontext_struct *context = &context_struct;
81 #elif defined(__svr4__) || defined(_SCO_DS)
82 static void win_fault(int signal, void *siginfo, ucontext_t *context)
83 {
84 #else
85 static void win_fault(int signal, int code, struct sigcontext *context)
86 {
87 #endif
88     if (signal == SIGTRAP)
89     {
90         /* If SIGTRAP not caused by breakpoint or single step 
91            don't jump into the debugger */
92         if (!(EFL_reg(context) & STEP_FLAG))
93         {
94             DBG_ADDR addr;
95             addr.seg = CS_reg(context);
96             addr.off = EIP_reg(context) - 1;
97             if (DEBUG_FindBreakpoint(&addr) == -1) return;
98         }
99     }
100     else if (signal != SIGHUP)
101     {
102         if (CS_reg(context) == WINE_CODE_SELECTOR)
103         {
104             fprintf(stderr, "Segmentation fault in Wine program (%x:%lx)."
105                             "  Please debug.\n",
106                             CS_reg(context), EIP_reg(context) );
107         }
108         else
109         {
110             if (INSTR_EmulateInstruction( context )) return;
111             fprintf( stderr, "Segmentation fault in Windows program %x:%lx.\n",
112                      CS_reg(context), EIP_reg(context) );
113         }
114     }
115
116     wine_debug( signal, context );  /* Enter our debugger */
117 }
118
119
120 /**********************************************************************
121  *              SIGNAL_SetHandler
122  */
123 static void SIGNAL_SetHandler( int sig, void (*func)() )
124 {
125     int ret;
126     struct sigaction sig_act;
127
128 #ifdef linux
129     sig_act.sa_handler = func;
130     sig_act.sa_flags = SA_RESTART | SA_NOMASK;
131     /* Point to the top of the stack, minus 4 just in case, and make
132        it aligned  */
133     sig_act.sa_restorer = 
134         (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
135     ret = wine_sigaction( sig, &sig_act, NULL );
136 #endif  /* linux */
137
138 #if defined(__NetBSD__) || defined(__FreeBSD__)
139     sigset_t sig_mask;
140     sigemptyset(&sig_mask);
141     sig_act.sa_handler = func;
142     sig_act.sa_flags = SA_ONSTACK;
143     sig_act.sa_mask = sig_mask;
144     ret = sigaction( sig, &sig_act, NULL );
145 #endif  /* __FreeBSD__ || __NetBSD__ */
146
147 #if defined (__svr4__) || defined(_SCO_DS)
148     sigset_t sig_mask;
149     sigemptyset(&sig_mask);
150     sig_act.sa_handler = func;
151     sig_act.sa_flags = SA_ONSTACK | SA_SIGINFO;
152     sig_act.sa_mask = sig_mask;
153     ret = sigaction( sig, &sig_act, NULL );
154 #endif  /* __svr4__ || _SCO_DS */
155
156     if (ret < 0)
157     {
158         perror( "sigaction" );
159         exit(1);
160     }
161 }
162
163 extern void stop_wait(int a);
164
165
166 /**********************************************************************
167  *              init_wine_signals
168  */
169 void init_wine_signals(void)
170 {
171 #if defined(__NetBSD__) || defined(__FreeBSD__)
172     struct sigaltstack ss;
173         
174     if ((ss.ss_sp = malloc(MINSIGSTKSZ)) == NULL) {
175         fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
176                 MINSIGSTKSZ);
177         exit(1);
178     }
179     ss.ss_size = MINSIGSTKSZ;
180     ss.ss_flags = 0;
181     if (sigaltstack(&ss, NULL) < 0) {
182         perror("sigstack");
183         exit(1);
184     }
185 #endif  /* __FreeBSD__ || __NetBSD__ */
186
187 #if defined (__svr4__) || defined(_SCO_DS)
188     struct sigaltstack ss;
189         
190     if ((ss.ss_sp = malloc(SIGSTKSZ) ) == NULL) {
191         fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
192                 SIGSTKSZ);
193         exit(1);
194     }
195     ss.ss_size = SIGSTKSZ;
196     ss.ss_flags = 0;
197     if (sigaltstack(&ss, NULL) < 0) {
198         perror("sigstack");
199         exit(1);
200     }
201 #endif  /* __svr4__ || _SCO_DS */
202     
203     SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer );
204     SIGNAL_SetHandler( SIGSEGV, (void (*)())win_fault );
205     SIGNAL_SetHandler( SIGILL,  (void (*)())win_fault );
206     SIGNAL_SetHandler( SIGFPE,  (void (*)())win_fault );
207     SIGNAL_SetHandler( SIGTRAP, (void (*)())win_fault ); /* For debugger */
208     SIGNAL_SetHandler( SIGHUP,  (void (*)())win_fault ); /* For forced break */
209 #ifdef SIGBUS
210     SIGNAL_SetHandler( SIGBUS,  (void (*)())win_fault );
211 #endif
212 #ifdef CONFIG_IPC
213     SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait ); /* For IPC */
214 #endif
215 }
216
217
218 /**********************************************************************
219  *              SIGNAL_StartBIOSTimer
220  *
221  * Start the BIOS tick timer.
222  */
223 void SIGNAL_StartBIOSTimer(void)
224 {
225     struct itimerval vt_timer;
226     static int timer_started = 0;
227
228     if (timer_started) return;
229     timer_started = 1;
230     vt_timer.it_interval.tv_sec = 0;
231     vt_timer.it_interval.tv_usec = 54929;
232     vt_timer.it_value = vt_timer.it_interval;
233
234     setitimer(ITIMER_REAL, &vt_timer, NULL);
235 }
236
237 #endif /* ifndef WINELIB */