10 #if defined(__NetBSD__) || defined(__FreeBSD__)
11 #include <sys/syscall.h>
12 #include <sys/param.h>
20 #include "prototypes.h"
24 #if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
27 struct sigaction segv_act
;
30 extern void ___sig_restore();
31 extern void ___masksig_restore();
33 /* Similar to the sigaction function in libc, except it leaves alone the
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
));
48 int do_int(int intnum
, struct sigcontext_struct
*scp
)
52 case 0x10: return do_int10(scp
);
55 scp
->sc_eax
= (scp
->sc_eax
& 0xffff0000L
) | DOS_GetEquipment();
59 scp
->sc_eax
= (scp
->sc_eax
& 0xffff0000L
) | 640L;
60 return 1; /* get base mem size */
62 case 0x13: return do_int13(scp
);
63 case 0x15: return do_int15(scp
);
64 case 0x16: return do_int16(scp
);
65 case 0x1a: return do_int1a(scp
);
66 case 0x21: return do_int21(scp
);
75 case 0x25: return do_int25(scp
);
76 case 0x26: return do_int26(scp
);
77 case 0x2a: return do_int2a(scp
);
78 case 0x2f: return do_int2f(scp
);
79 case 0x31: return do_int31(scp
);
85 static void win_fault(int signal
, struct sigcontext_struct context
)
87 struct sigcontext_struct
*scp
= &context
;
89 static void win_fault(int signal
, int code
, struct sigcontext
*scp
)
92 unsigned char * instr
;
93 #if !(defined (linux) || defined (__NetBSD__))
97 /* First take care of a few preliminaries */
104 && signal
!= SIGTRAP
)
109 /* And back up over the int3 instruction. */
110 if(signal
== SIGTRAP
) {
115 if((scp
->sc_cs
& 7) != 7)
118 #if defined(__NetBSD__) || defined(__FreeBSD__)
119 /* set_es(0x27); set_ds(0x27); */
120 if(signal
!= SIGBUS
&& signal
!= SIGSEGV
&& signal
!= SIGTRAP
)
122 if(scp
->sc_cs
== 0x1f)
126 "Segmentation fault in Wine program (%x:%lx)."
128 scp
->sc_cs
, scp
->sc_eip
);
132 /* Now take a look at the actual instruction where the program
134 instr
= (unsigned char *) SAFEMAKEPTR(scp
->sc_cs
, scp
->sc_eip
);
138 case 0xcd: /* int <XX> */
140 if (!do_int(*instr
, scp
)) {
141 fprintf(stderr
,"Unexpected Windows interrupt %x\n", *instr
);
144 scp
->sc_eip
+= 2; /* Bypass the int instruction */
147 case 0xe4: /* inb al,XX */
152 case 0xe5: /* in ax,XX */
157 case 0xe6: /* outb XX,al */
162 case 0xe7: /* out XX,ax */
167 case 0xec: /* inb al,dx */
172 case 0xed: /* in ax,dx */
177 case 0xee: /* outb dx,al */
182 case 0xef: /* out dx,ax */
187 case 0xfa: /* cli, ignored */
191 case 0xfb: /* sti, ignored */
196 fprintf(stderr
, "Unexpected Windows program segfault"
197 " - opcode = %x\n", *instr
);
201 /* OK, done handling the interrupt */
206 XUngrabPointer(display
, CurrentTime
);
207 XUngrabServer(display
);
209 fprintf(stderr
,"In win_fault %x:%lx\n", scp
->sc_cs
, scp
->sc_eip
);
210 #if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__)
211 wine_debug(signal
, (int *)scp
); /* Enter our debugger */
213 fprintf(stderr
,"Stack: %x:%x\n", scp
->sc_ss
, scp
->sc_esp
);
217 fprintf(stderr
," %8.8x", *dump
++);
219 fprintf(stderr
,"\n");
221 fprintf(stderr
,"\n");
226 void init_wine_signals(void)
229 segv_act
.sa_handler
= (__sighandler_t
) win_fault
;
230 /* Point to the top of the stack, minus 4 just in case, and make
232 segv_act
.sa_restorer
=
233 (void (*)()) (((unsigned int)(cstack
) + sizeof(cstack
) - 4) & ~3);
234 wine_sigaction(SIGSEGV
, &segv_act
, NULL
);
235 wine_sigaction(SIGILL
, &segv_act
, NULL
);
237 wine_sigaction(SIGBUS
, &segv_act
, NULL
);
239 wine_sigaction(SIGTRAP
, &segv_act
, NULL
); /* For breakpoints */
241 #if defined(__NetBSD__) || defined(__FreeBSD__)
243 #if defined(BSD4_4) && !defined (__FreeBSD__)
244 struct sigaltstack ss
;
246 if ((ss
.ss_base
= malloc(MINSIGSTKSZ
)) == NULL
) {
247 fprintf(stderr
, "Unable to allocate signal stack (%d bytes)\n",
251 ss
.ss_size
= MINSIGSTKSZ
;
253 if (sigaltstack(&ss
, NULL
) < 0) {
260 ss
.ss_sp
= (char *) (((unsigned int)(cstack
) + sizeof(cstack
) - 4) & ~3);
262 if (sigstack(&ss
, NULL
) < 0) {
267 sigemptyset(&sig_mask
);
268 segv_act
.sa_handler
= (void (*)) win_fault
;
269 segv_act
.sa_flags
= SA_ONSTACK
;
270 segv_act
.sa_mask
= sig_mask
;
271 if (sigaction(SIGBUS
, &segv_act
, NULL
) < 0) {
272 perror("sigaction: SIGBUS");
275 segv_act
.sa_handler
= (void (*)) win_fault
;
276 segv_act
.sa_flags
= SA_ONSTACK
;
277 segv_act
.sa_mask
= sig_mask
;
278 if (sigaction(SIGSEGV
, &segv_act
, NULL
) < 0) {
279 perror("sigaction: SIGSEGV");
282 segv_act
.sa_handler
= (void (*)) win_fault
; /* For breakpoints */
283 segv_act
.sa_flags
= SA_ONSTACK
;
284 segv_act
.sa_mask
= sig_mask
;
285 if (sigaction(SIGTRAP
, &segv_act
, NULL
) < 0) {
286 perror("sigaction: SIGTRAP");
292 static sigjmp_buf segv_jmpbuf
;
297 siglongjmp(segv_jmpbuf
, 1);
301 test_memory( char *p
, int write
)
304 struct sigaction new_act
;
305 struct sigaction old_act
;
307 memset(&new_act
, 0, sizeof new_act
);
308 new_act
.sa_handler
= segv_handler
;
309 if (sigsetjmp( segv_jmpbuf
, 1 ) == 0) {
311 if (sigaction(SIGSEGV
, &new_act
, &old_act
) < 0)
319 wine_sigaction(SIGSEGV
, &old_act
, NULL
);
321 sigaction(SIGSEGV
, &old_act
, NULL
);
326 #endif /* ifndef WINELIB */