Partial stub implementation of undocumented KERNEL routine PK16FNF,
[wine] / loader / signal.c
1 /*
2  * Wine signal handling
3  *
4  * Copyright 1995 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <signal.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <time.h>
15 #include <setjmp.h>
16
17 #include <sys/time.h>
18 #include <sys/timeb.h>
19 #include <sys/types.h>
20 #include <sys/wait.h>
21
22 #ifdef HAVE_SYS_PARAM_H
23 # include <sys/param.h>
24 #endif
25 #ifdef HAVE_SYSCALL_H
26 # include <syscall.h>
27 #else
28 # ifdef HAVE_SYS_SYSCALL_H
29 #  include <sys/syscall.h>
30 # endif
31 #endif
32
33 #include "winsock.h"
34 #include "global.h"
35 #include "options.h"
36 #include "debugger.h"
37 #include "miscemu.h"
38 #include "dosexe.h"
39 #include "thread.h"
40 #include "debug.h"
41
42 void (*fnWINE_Debugger)(int,SIGCONTEXT*) = NULL;
43 void (*ctx_debug_call)(int sig,CONTEXT*ctx)=NULL;
44 BOOL32 (*fnINSTR_EmulateInstruction)(SIGCONTEXT*ctx)=NULL;
45
46 #ifdef __i386__
47
48 /* i386 specific faults */
49 static const char * const SIGNAL_traps[] =
50 {
51     "Division by zero exception",      /* 0 */
52     "Debug exception",                 /* 1 */
53     "NMI interrupt",                   /* 2 */
54     "Breakpoint exception",            /* 3 */
55     "Overflow exception",              /* 4 */
56     "Bound range exception",           /* 5 */
57     "Invalid opcode exception",        /* 6 */
58     "Device not available exception",  /* 7 */
59     "Double fault exception",          /* 8 */
60     "Coprocessor segment overrun",     /* 9 */
61     "Invalid TSS exception",           /* 10 */
62     "Segment not present exception",   /* 11 */
63     "Stack fault",                     /* 12 */
64     "General protection fault",        /* 13 */
65     "Page fault",                      /* 14 */
66     "Unknown exception",               /* 15 */
67     "Floating point exception",        /* 16 */
68     "Alignment check exception",       /* 17 */
69     "Machine check exception"          /* 18 */
70 };
71 #define NB_TRAPS  (sizeof(SIGNAL_traps) / sizeof(SIGNAL_traps[0]))
72 #endif
73
74 /* Linux sigaction function */
75
76 #if defined(linux) && defined(__i386__)
77 /* This is the sigaction structure from the Linux 2.1.20 kernel.  */
78 #undef sa_handler
79 struct kernel_sigaction
80 {
81     void (*sa_handler)();
82     unsigned long sa_mask;
83     unsigned long sa_flags;
84     void (*sa_restorer)();
85 };
86
87 /* Similar to the sigaction function in libc, except it leaves alone the
88    restorer field, which is used to specify the signal stack address */
89 static __inline__ int wine_sigaction( int sig, struct kernel_sigaction *new,
90                                       struct kernel_sigaction *old )
91 {
92 #ifdef __PIC__
93     __asm__ __volatile__( "pushl %%ebx\n\t"
94                           "movl %2,%%ebx\n\t"
95                           "int $0x80\n\t"
96                           "popl %%ebx"
97                           : "=a" (sig)
98                           : "0" (SYS_sigaction),
99                             "g" (sig),
100                             "c" (new),
101                             "d" (old) );
102 #else
103     __asm__ __volatile__( "int $0x80"
104                           : "=a" (sig)
105                           : "0" (SYS_sigaction),
106                             "b" (sig),
107                             "c" (new),
108                             "d" (old) );
109 #endif  /* __PIC__ */
110     if (sig>=0)
111         return 0;
112     errno = -sig;
113     return -1;
114 }
115 #endif /* linux && __i386__ */
116
117 /* Signal stack */
118
119 static char SIGNAL_Stack[16384];
120 static sigset_t async_signal_set;
121
122 /**********************************************************************
123  *              SIGNAL_child
124  * 
125  * wait4 terminated child processes
126  */
127 static HANDLER_DEF(SIGNAL_child)
128 {
129     HANDLER_INIT();
130 #ifdef HAVE_WAIT4
131     wait4( 0, NULL, WNOHANG, NULL);
132 #elif defined (HAVE_WAITPID)
133     /* I am sort-of guessing that this is the same as the wait4 call.  */
134     waitpid (0, NULL, WNOHANG);
135 #else
136     wait(NULL);
137 #endif
138 }
139
140
141 /**********************************************************************
142  *              SIGNAL_SetHandler
143  */
144 void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
145 {
146     int ret;
147
148 #if defined(linux) && defined(__i386__)
149
150     struct kernel_sigaction sig_act;
151     sig_act.sa_handler = func;
152     sig_act.sa_flags   = SA_RESTART | (flags) ? SA_NOMASK : 0;
153     sig_act.sa_mask    = 0;
154     /* Point to the top of the stack, minus 4 just in case, and make
155        it aligned  */
156     sig_act.sa_restorer = 
157         (void (*)())((int)(SIGNAL_Stack + sizeof(SIGNAL_Stack) - 4) & ~3);
158     ret = wine_sigaction( sig, &sig_act, NULL );
159
160 #else  /* linux && __i386__ */
161
162     struct sigaction sig_act;
163     sig_act.sa_handler = func;
164     sigemptyset( &sig_act.sa_mask );
165
166 # if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
167     sig_act.sa_flags = SA_ONSTACK;
168 # elif defined (__svr4__) || defined(_SCO_DS)
169     sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
170 # elif defined(__EMX__)
171     sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */
172 # else
173     sig_act.sa_flags = 0;
174 # endif
175     ret = sigaction( sig, &sig_act, NULL );
176
177 #endif  /* linux && __i386__ */
178
179     if (ret < 0)
180     {
181         perror( "sigaction" );
182         exit(1);
183     }
184 }
185
186 extern void stop_wait(int a);
187 extern void WINSOCK_sigio(int a);
188 extern void ASYNC_sigio(int a);
189
190
191 /**********************************************************************
192  *              SIGNAL_MaskAsyncEvents
193  */
194 void SIGNAL_MaskAsyncEvents( BOOL32 flag )
195 {
196   sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &async_signal_set, NULL);
197 }
198
199 extern void SIGNAL_SetHandler( int sig, void (*func)(), int flags );
200
201 /**********************************************************************
202  *              SIGNAL_break
203  * 
204  * Handle Ctrl-C and such
205  */
206 static HANDLER_DEF(SIGNAL_break)
207 {
208     HANDLER_INIT();
209     if (Options.debug && fnWINE_Debugger)
210         fnWINE_Debugger( signal, HANDLER_CONTEXT );  /* Enter our debugger */
211     else exit(0);
212 }
213
214
215 /**********************************************************************
216  *              SIGNAL_trap
217  *
218  * SIGTRAP handler.
219  */
220 static HANDLER_DEF(SIGNAL_trap)
221 {
222     HANDLER_INIT();
223     if (fnWINE_Debugger)
224         fnWINE_Debugger( signal, HANDLER_CONTEXT );  /* Enter our debugger */
225 }
226
227
228 /**********************************************************************
229  *              SIGNAL_fault
230  *
231  * Segfault handler.
232  */
233 static HANDLER_DEF(SIGNAL_fault)
234 {
235     const char *fault = "Segmentation fault";
236     HANDLER_INIT();
237
238 #ifdef __i386__
239
240 #if defined(TRAP_sig) && defined(CR2_sig)
241     if (TRAP_sig(HANDLER_CONTEXT) == 0x0e
242         && VIRTUAL_HandleFault( (LPVOID)CR2_sig(HANDLER_CONTEXT) ))
243         return;
244 #endif
245
246     if (fnINSTR_EmulateInstruction && 
247         fnINSTR_EmulateInstruction( HANDLER_CONTEXT )
248     )
249         return;
250
251 #ifdef TRAP_sig
252     if (TRAP_sig( HANDLER_CONTEXT ) < NB_TRAPS)
253         fault = SIGNAL_traps[TRAP_sig( HANDLER_CONTEXT )];
254 #endif
255     if (IS_SELECTOR_SYSTEM(CS_sig(HANDLER_CONTEXT)))
256     {
257         MSG("%s in 32-bit code (0x%08lx).\n", fault, EIP_sig(HANDLER_CONTEXT));
258     }
259     else
260     {
261         MSG("%s in 16-bit code (%04x:%04lx).\n", fault,
262             (WORD)CS_sig(HANDLER_CONTEXT), EIP_sig(HANDLER_CONTEXT) );
263     }
264 #ifdef CR2_sig
265     MSG("Fault address is 0x%08lx\n",CR2_sig(HANDLER_CONTEXT));
266 #endif
267 #endif
268
269     if (fnWINE_Debugger)
270         fnWINE_Debugger( signal, HANDLER_CONTEXT );
271 }
272
273
274 /**********************************************************************
275  *              SIGNAL_InitHandlers
276  */
277 void SIGNAL_InitHandlers(void)
278 {
279     SIGNAL_SetHandler( SIGINT,  (void (*)())SIGNAL_break, 1);
280     SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1);
281     SIGNAL_SetHandler( SIGILL,  (void (*)())SIGNAL_fault, 1);
282     SIGNAL_SetHandler( SIGFPE,  (void (*)())SIGNAL_fault, 1);
283     SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap,  1); /* debugger */
284     SIGNAL_SetHandler( SIGHUP,  (void (*)())SIGNAL_trap,  1); /* forced break*/
285 #ifdef SIGBUS
286     SIGNAL_SetHandler( SIGBUS,  (void (*)())SIGNAL_fault, 1);
287 #endif
288     return;
289 }
290
291 /**********************************************************************
292  *              SIGNAL_Init
293  */
294 BOOL32 SIGNAL_Init(void)
295 {
296 #ifdef HAVE_WORKING_SIGALTSTACK
297     struct sigaltstack ss;
298     ss.ss_sp    = SIGNAL_Stack;
299     ss.ss_size  = sizeof(SIGNAL_Stack);
300     ss.ss_flags = 0;
301     if (sigaltstack(&ss, NULL) < 0)
302     {
303         perror("sigstack");
304         return FALSE;
305     }
306 #endif  /* HAVE_SIGALTSTACK */
307     
308     sigemptyset(&async_signal_set);
309
310     SIGNAL_SetHandler( SIGCHLD, (void (*)())SIGNAL_child, 1);
311 #ifdef CONFIG_IPC
312     sigaddset(&async_signal_set, SIGUSR2);
313     SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1);      /* For IPC */
314 #endif
315 #ifdef SIGIO
316     sigaddset(&async_signal_set, SIGIO);
317 /*    SIGNAL_SetHandler( SIGIO,   (void (*)())WINSOCK_sigio, 0);  */
318     SIGNAL_SetHandler( SIGIO,   (void (*)())ASYNC_sigio, 0); 
319 #endif
320     sigaddset(&async_signal_set, SIGALRM);
321
322     /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead  */
323     signal (SIGPIPE, SIG_IGN);
324     SIGNAL_InitHandlers();
325     return TRUE;
326 }