4 * Copyright 1995 Alexandre Julliard
19 #include <sys/timeb.h>
20 #include <sys/types.h>
23 #ifdef HAVE_SYS_PARAM_H
24 # include <sys/param.h>
29 # ifdef HAVE_SYS_SYSCALL_H
30 # include <sys/syscall.h>
43 void (*fnWINE_Debugger
)(int,SIGCONTEXT
*) = NULL
;
44 void (*ctx_debug_call
)(int sig
,CONTEXT
*ctx
)=NULL
;
45 BOOL (*fnINSTR_EmulateInstruction
)(SIGCONTEXT
*ctx
)=NULL
;
50 /* i386 specific faults */
51 static const char * const SIGNAL_traps
[] =
53 "Division by zero exception", /* 0 */
54 "Debug exception", /* 1 */
55 "NMI interrupt", /* 2 */
56 "Breakpoint exception", /* 3 */
57 "Overflow exception", /* 4 */
58 "Bound range exception", /* 5 */
59 "Invalid opcode exception", /* 6 */
60 "Device not available exception", /* 7 */
61 "Double fault exception", /* 8 */
62 "Coprocessor segment overrun", /* 9 */
63 "Invalid TSS exception", /* 10 */
64 "Segment not present exception", /* 11 */
65 "Stack fault", /* 12 */
66 "General protection fault", /* 13 */
67 "Page fault", /* 14 */
68 "Unknown exception", /* 15 */
69 "Floating point exception", /* 16 */
70 "Alignment check exception", /* 17 */
71 "Machine check exception" /* 18 */
73 #define NB_TRAPS (sizeof(SIGNAL_traps) / sizeof(SIGNAL_traps[0]))
76 /* Linux sigaction function */
78 #if defined(linux) && defined(__i386__)
79 /* This is the sigaction structure from the Linux 2.1.20 kernel. */
82 struct kernel_sigaction
85 unsigned long sa_mask
;
86 unsigned long sa_flags
;
87 void (*sa_restorer
)();
90 /* Similar to the sigaction function in libc, except it leaves alone the
91 restorer field, which is used to specify the signal stack address */
92 static __inline__
int wine_sigaction( int sig
, struct kernel_sigaction
*new,
93 struct kernel_sigaction
*old
)
96 __asm__
__volatile__( "pushl %%ebx\n\t"
101 : "0" (SYS_sigaction
),
106 __asm__
__volatile__( "int $0x80"
108 : "0" (SYS_sigaction
),
118 #endif /* linux && __i386__ */
122 static char SIGNAL_Stack
[16384];
123 static sigset_t async_signal_set
;
125 /**********************************************************************
128 * wait4 terminated child processes
130 static HANDLER_DEF(SIGNAL_child
)
134 wait4( 0, NULL
, WNOHANG
, NULL
);
135 #elif defined (HAVE_WAITPID)
136 /* I am sort-of guessing that this is the same as the wait4 call. */
137 waitpid (0, NULL
, WNOHANG
);
144 /**********************************************************************
147 void SIGNAL_SetHandler( int sig
, void (*func
)(), int flags
)
151 #if defined(linux) && defined(__i386__)
153 struct kernel_sigaction sig_act
;
154 sig_act
.sa_handler
= func
;
155 sig_act
.sa_flags
= SA_RESTART
| (flags
) ? SA_NOMASK
: 0;
157 /* Point to the top of the stack, minus 4 just in case, and make
159 sig_act
.sa_restorer
=
160 (void (*)())((int)(SIGNAL_Stack
+ sizeof(SIGNAL_Stack
) - 4) & ~3);
161 ret
= wine_sigaction( sig
, &sig_act
, NULL
);
163 #else /* linux && __i386__ */
165 struct sigaction sig_act
;
166 sig_act
.sa_handler
= func
;
167 sigemptyset( &sig_act
.sa_mask
);
169 # if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
170 sig_act
.sa_flags
= SA_ONSTACK
;
171 # elif defined (__svr4__) || defined(_SCO_DS)
172 sig_act
.sa_flags
= SA_SIGINFO
| SA_ONSTACK
| SA_RESTART
;
173 # elif defined(__EMX__)
174 sig_act
.sa_flags
= 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */
176 sig_act
.sa_flags
= 0;
178 ret
= sigaction( sig
, &sig_act
, NULL
);
180 #endif /* linux && __i386__ */
184 perror( "sigaction" );
189 extern void stop_wait(int a
);
190 extern void WINSOCK_sigio(int a
);
191 extern void ASYNC_sigio(int a
);
194 /**********************************************************************
195 * SIGNAL_MaskAsyncEvents
197 void SIGNAL_MaskAsyncEvents( BOOL flag
)
199 sigprocmask( (flag
) ? SIG_BLOCK
: SIG_UNBLOCK
, &async_signal_set
, NULL
);
202 extern void SIGNAL_SetHandler( int sig
, void (*func
)(), int flags
);
204 /**********************************************************************
207 * Handle Ctrl-C and such
209 static HANDLER_DEF(SIGNAL_break
)
212 if (Options
.debug
&& fnWINE_Debugger
)
213 fnWINE_Debugger( signal
, HANDLER_CONTEXT
); /* Enter our debugger */
218 /**********************************************************************
223 static HANDLER_DEF(SIGNAL_trap
)
227 fnWINE_Debugger( signal
, HANDLER_CONTEXT
); /* Enter our debugger */
231 /**********************************************************************
236 static HANDLER_DEF(SIGNAL_fault
)
238 const char *fault
= "Segmentation fault";
243 #if defined(TRAP_sig) && defined(CR2_sig)
244 if (TRAP_sig(HANDLER_CONTEXT
) == 0x0e
245 && VIRTUAL_HandleFault( (LPVOID
)CR2_sig(HANDLER_CONTEXT
) ))
248 #if defined(TRAP_sig)
249 /* We don't do alignment checks */
250 /* FIXME: if we get SEHs, pass the fault through them first? */
251 if (TRAP_sig(HANDLER_CONTEXT
) == 0x11) {
252 if (EFL_sig(HANDLER_CONTEXT
) & 0x00040000) {
253 /* Disable AC flag, return */
254 EFL_sig(HANDLER_CONTEXT
) &= ~0x00040000;
260 if (fnINSTR_EmulateInstruction
&&
261 fnINSTR_EmulateInstruction( HANDLER_CONTEXT
)
266 if (TRAP_sig( HANDLER_CONTEXT
) < NB_TRAPS
)
267 fault
= SIGNAL_traps
[TRAP_sig( HANDLER_CONTEXT
)];
269 if (IS_SELECTOR_SYSTEM(CS_sig(HANDLER_CONTEXT
)))
271 MSG("%s in 32-bit code (0x%08lx).\n", fault
, EIP_sig(HANDLER_CONTEXT
));
275 MSG("%s in 16-bit code (%04x:%04lx).\n", fault
,
276 (WORD
)CS_sig(HANDLER_CONTEXT
), EIP_sig(HANDLER_CONTEXT
) );
279 MSG("Fault address is 0x%08lx\n",CR2_sig(HANDLER_CONTEXT
));
284 fnWINE_Debugger( signal
, HANDLER_CONTEXT
);
288 /**********************************************************************
289 * SIGNAL_InitHandlers
291 void SIGNAL_InitHandlers(void)
293 SIGNAL_SetHandler( SIGINT
, (void (*)())SIGNAL_break
, 1);
294 SIGNAL_SetHandler( SIGSEGV
, (void (*)())SIGNAL_fault
, 1);
295 SIGNAL_SetHandler( SIGILL
, (void (*)())SIGNAL_fault
, 1);
296 SIGNAL_SetHandler( SIGFPE
, (void (*)())SIGNAL_fault
, 1);
297 SIGNAL_SetHandler( SIGTRAP
, (void (*)())SIGNAL_trap
, 1); /* debugger */
298 SIGNAL_SetHandler( SIGHUP
, (void (*)())SIGNAL_trap
, 1); /* forced break*/
300 SIGNAL_SetHandler( SIGBUS
, (void (*)())SIGNAL_fault
, 1);
305 /**********************************************************************
308 BOOL
SIGNAL_Init(void)
310 #ifdef HAVE_WORKING_SIGALTSTACK
311 struct sigaltstack ss
;
312 ss
.ss_sp
= SIGNAL_Stack
;
313 ss
.ss_size
= sizeof(SIGNAL_Stack
);
315 if (sigaltstack(&ss
, NULL
) < 0)
317 perror("sigaltstack");
320 #endif /* HAVE_SIGALTSTACK */
322 sigemptyset(&async_signal_set
);
324 SIGNAL_SetHandler( SIGCHLD
, (void (*)())SIGNAL_child
, 1);
326 sigaddset(&async_signal_set
, SIGUSR2
);
327 SIGNAL_SetHandler( SIGUSR2
, (void (*)())stop_wait
, 1); /* For IPC */
330 sigaddset(&async_signal_set
, SIGIO
);
331 /* SIGNAL_SetHandler( SIGIO, (void (*)())WINSOCK_sigio, 0); */
332 SIGNAL_SetHandler( SIGIO
, (void (*)())ASYNC_sigio
, 0);
334 sigaddset(&async_signal_set
, SIGALRM
);
336 /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead */
337 signal (SIGPIPE
, SIG_IGN
);
338 SIGNAL_InitHandlers();