Release 950727
[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__)
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 struct sigaction segv_act;
26 struct sigaction usr2_act;
27
28 #ifdef linux
29 extern void ___sig_restore();
30 extern void ___masksig_restore();
31
32 /* Similar to the sigaction function in libc, except it leaves alone the
33    restorer field */
34
35 static int
36 wine_sigaction(int sig,struct sigaction * new, struct sigaction * old)
37 {
38         __asm__("int $0x80":"=a" (sig)
39                 :"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old));
40         if (sig>=0)
41                 return 0;
42         errno = -sig;
43         return -1;
44 }
45 #endif
46
47
48 #ifdef linux
49 static void win_fault(int signal, struct sigcontext_struct context_struct)
50 {
51     struct sigcontext_struct *context = &context_struct;
52 #else
53 static void win_fault(int signal, int code, struct sigcontext *context)
54 {
55 #endif
56     if (signal != SIGTRAP)
57     {
58         if (CS == WINE_CODE_SELECTOR)
59         {
60             fprintf(stderr, "Segmentation fault in Wine program (%x:%lx)."
61                             "  Please debug\n", CS, EIP );
62         }
63         else if (INSTR_EmulateInstruction( context )) return;
64         fprintf(stderr,"In win_fault %x:%lx\n", CS, EIP );
65     }
66     XUngrabPointer(display, CurrentTime);
67     XUngrabServer(display);
68     XFlush(display);
69     wine_debug( signal, context );  /* Enter our debugger */
70 }
71
72 void init_wine_signals(void)
73 {
74         extern void stop_wait(int a);
75 #ifdef linux
76         segv_act.sa_handler = (__sighandler_t) win_fault;
77         /* Point to the top of the stack, minus 4 just in case, and make
78            it aligned  */
79         segv_act.sa_restorer = 
80             (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
81         usr2_act.sa_restorer= segv_act.sa_restorer;
82         usr2_act.sa_handler = (__sighandler_t) stop_wait;
83         /* Point to the top of the stack, minus 4 just in case, and make
84            it aligned  */
85         wine_sigaction(SIGSEGV, &segv_act, NULL);
86         wine_sigaction(SIGILL, &segv_act, NULL);
87         wine_sigaction(SIGFPE, &segv_act, NULL);
88         wine_sigaction(SIGUSR2, &usr2_act, NULL);
89 #ifdef SIGBUS
90         wine_sigaction(SIGBUS, &segv_act, NULL);
91 #endif
92         wine_sigaction(SIGTRAP, &segv_act, NULL); /* For breakpoints */
93 #endif
94 #if defined(__NetBSD__) || defined(__FreeBSD__)
95         sigset_t sig_mask;
96         struct sigaltstack ss;
97         
98 #if !defined (__FreeBSD__)
99         if ((ss.ss_base = malloc(MINSIGSTKSZ)) == NULL) {
100 #else
101         if ((ss.ss_sp = malloc(MINSIGSTKSZ)) == NULL) {
102 #endif
103                 fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
104                         MINSIGSTKSZ);
105                 exit(1);
106         }
107         ss.ss_size = MINSIGSTKSZ;
108         ss.ss_flags = 0;
109         if (sigaltstack(&ss, NULL) < 0) {
110                 perror("sigstack");
111                 exit(1);
112         }
113         sigemptyset(&sig_mask);
114         segv_act.sa_handler = (void (*)) win_fault;
115         segv_act.sa_flags = SA_ONSTACK;
116         segv_act.sa_mask = sig_mask;
117         if (sigaction(SIGBUS, &segv_act, NULL) < 0) {
118                 perror("sigaction: SIGBUS");
119                 exit(1);
120         }
121         segv_act.sa_handler = (void (*)) win_fault;
122         segv_act.sa_flags = SA_ONSTACK;
123         segv_act.sa_mask = sig_mask;
124         if (sigaction(SIGSEGV, &segv_act, NULL) < 0) {
125                 perror("sigaction: SIGSEGV");
126                 exit(1);
127         }
128         segv_act.sa_handler = (void (*)) win_fault; /* For breakpoints */
129         segv_act.sa_flags = SA_ONSTACK;
130         segv_act.sa_mask = sig_mask;
131         if (sigaction(SIGTRAP, &segv_act, NULL) < 0) {
132                 perror("sigaction: SIGTRAP");
133                 exit(1);
134         }
135         usr2_act.sa_handler = (void (*)) stop_wait; /* For breakpoints */
136         usr2_act.sa_flags = SA_ONSTACK;
137         usr2_act.sa_mask = sig_mask;
138         if (sigaction(SIGUSR2, &usr2_act, NULL) < 0) {
139                 perror("sigaction: SIGUSR2");
140                 exit(1);
141         }
142 #endif
143 }
144
145 #endif /* ifndef WINELIB */