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