Add a configure check for struct request_sense. Use this in
[wine] / dlls / ntdll / signal_sparc.c
1 /*
2  * Sparc signal handling routines
3  *
4  * Copyright 1999 Ulrich Weigand
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #ifdef __sparc__
22
23 #include "config.h"
24
25 #include <signal.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <sys/ucontext.h>
33
34 #include "windef.h"
35 #include "winternl.h"
36 #include "winnt.h"
37
38 #include "wine/exception.h"
39 #include "ntdll_misc.h"
40
41 #include "wine/debug.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(seh);
44
45 #define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, ucontext_t *__context )
46 #define HANDLER_CONTEXT (__context)
47
48 typedef int (*wine_signal_handler)(unsigned int sig);
49
50 static wine_signal_handler handlers[256];
51
52 /***********************************************************************
53  *           dispatch_signal
54  */
55 inline static int dispatch_signal(unsigned int sig)
56 {
57     if (handlers[sig] == NULL) return 0;
58     return handlers[sig](sig);
59 }
60
61
62 /*
63  * FIXME:  All this works only on Solaris for now
64  */
65
66 /**********************************************************************
67  *              save_context
68  */
69 static void save_context( CONTEXT *context, ucontext_t *ucontext )
70 {
71     /* Special registers */
72     context->psr = ucontext->uc_mcontext.gregs[REG_PSR];
73     context->pc  = ucontext->uc_mcontext.gregs[REG_PC];
74     context->npc = ucontext->uc_mcontext.gregs[REG_nPC];
75     context->y   = ucontext->uc_mcontext.gregs[REG_Y];
76     context->wim = 0;  /* FIXME */
77     context->tbr = 0;  /* FIXME */
78
79     /* Global registers */
80     context->g0 = 0;  /* always */
81     context->g1 = ucontext->uc_mcontext.gregs[REG_G1];
82     context->g2 = ucontext->uc_mcontext.gregs[REG_G2];
83     context->g3 = ucontext->uc_mcontext.gregs[REG_G3];
84     context->g4 = ucontext->uc_mcontext.gregs[REG_G4];
85     context->g5 = ucontext->uc_mcontext.gregs[REG_G5];
86     context->g6 = ucontext->uc_mcontext.gregs[REG_G6];
87     context->g7 = ucontext->uc_mcontext.gregs[REG_G7];
88
89     /* Current 'out' registers */
90     context->o0 = ucontext->uc_mcontext.gregs[REG_O0];
91     context->o1 = ucontext->uc_mcontext.gregs[REG_O1];
92     context->o2 = ucontext->uc_mcontext.gregs[REG_O2];
93     context->o3 = ucontext->uc_mcontext.gregs[REG_O3];
94     context->o4 = ucontext->uc_mcontext.gregs[REG_O4];
95     context->o5 = ucontext->uc_mcontext.gregs[REG_O5];
96     context->o6 = ucontext->uc_mcontext.gregs[REG_O6];
97     context->o7 = ucontext->uc_mcontext.gregs[REG_O7];
98
99     /* FIXME: what if the current register window isn't saved? */
100     if ( ucontext->uc_mcontext.gwins && ucontext->uc_mcontext.gwins->wbcnt > 0 )
101     {
102         /* Current 'local' registers from first register window */
103         context->l0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[0];
104         context->l1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[1];
105         context->l2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[2];
106         context->l3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[3];
107         context->l4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[4];
108         context->l5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[5];
109         context->l6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[6];
110         context->l7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[7];
111
112         /* Current 'in' registers from first register window */
113         context->i0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[0];
114         context->i1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[1];
115         context->i2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[2];
116         context->i3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[3];
117         context->i4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[4];
118         context->i5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[5];
119         context->i6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[6];
120         context->i7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[7];
121     }
122 }
123
124 /**********************************************************************
125  *              restore_context
126  */
127 static void restore_context( CONTEXT *context, ucontext_t *ucontext )
128 {
129    /* FIXME */
130 }
131
132 /**********************************************************************
133  *              save_fpu
134  */
135 static void save_fpu( CONTEXT *context, ucontext_t *ucontext )
136 {
137    /* FIXME */
138 }
139
140 /**********************************************************************
141  *              restore_fpu
142  */
143 static void restore_fpu( CONTEXT *context, ucontext_t *ucontext )
144 {
145    /* FIXME */
146 }
147
148
149 /**********************************************************************
150  *              segv_handler
151  *
152  * Handler for SIGSEGV.
153  */
154 static void segv_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
155 {
156     EXCEPTION_RECORD rec;
157     CONTEXT context;
158
159     /* we want the page-fault case to be fast */
160     if ( info->si_code == SEGV_ACCERR )
161         if (VIRTUAL_HandleFault( (LPVOID)info->si_addr )) return;
162
163     save_context( &context, ucontext );
164     rec.ExceptionCode    = EXCEPTION_ACCESS_VIOLATION;
165     rec.ExceptionRecord  = NULL;
166     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
167     rec.ExceptionAddress = (LPVOID)context.pc;
168     rec.NumberParameters = 2;
169     rec.ExceptionInformation[0] = 0;  /* FIXME: read/write access ? */
170     rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
171
172     __regs_RtlRaiseException( &rec, &context );
173     restore_context( &context, ucontext );
174 }
175
176 /**********************************************************************
177  *              bus_handler
178  *
179  * Handler for SIGBUS.
180  */
181 static void bus_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
182 {
183     EXCEPTION_RECORD rec;
184     CONTEXT context;
185
186     save_context( &context, ucontext );
187     rec.ExceptionRecord  = NULL;
188     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
189     rec.ExceptionAddress = (LPVOID)context.pc;
190     rec.NumberParameters = 0;
191
192     if ( info->si_code == BUS_ADRALN )
193         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
194     else
195         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
196
197     __regs_RtlRaiseException( &rec, &context );
198     restore_context( &context, ucontext );
199 }
200
201 /**********************************************************************
202  *              ill_handler
203  *
204  * Handler for SIGILL.
205  */
206 static void ill_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
207 {
208     EXCEPTION_RECORD rec;
209     CONTEXT context;
210
211     switch ( info->si_code )
212     {
213     default:
214     case ILL_ILLOPC:
215     case ILL_ILLOPN:
216     case ILL_ILLADR:
217     case ILL_ILLTRP:
218         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
219         break;
220
221     case ILL_PRVOPC:
222     case ILL_PRVREG:
223         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
224         break;
225
226     case ILL_BADSTK:
227         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
228         break;
229     }
230
231     save_context( &context, ucontext );
232     rec.ExceptionRecord  = NULL;
233     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
234     rec.ExceptionAddress = (LPVOID)context.pc;
235     rec.NumberParameters = 0;
236     __regs_RtlRaiseException( &rec, &context );
237     restore_context( &context, ucontext );
238 }
239
240
241 /**********************************************************************
242  *              trap_handler
243  *
244  * Handler for SIGTRAP.
245  */
246 static void trap_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
247 {
248     EXCEPTION_RECORD rec;
249     CONTEXT context;
250
251     switch ( info->si_code )
252     {
253     case TRAP_TRACE:
254         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
255         break;
256     case TRAP_BRKPT:
257     default:
258         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
259         break;
260     }
261
262     save_context( &context, ucontext );
263     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
264     rec.ExceptionRecord  = NULL;
265     rec.ExceptionAddress = (LPVOID)context.pc;
266     rec.NumberParameters = 0;
267     __regs_RtlRaiseException( &rec, &context );
268     restore_context( &context, ucontext );
269 }
270
271
272 /**********************************************************************
273  *              fpe_handler
274  *
275  * Handler for SIGFPE.
276  */
277 static void fpe_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
278 {
279     EXCEPTION_RECORD rec;
280     CONTEXT context;
281
282     switch ( info->si_code )
283     {
284     case FPE_FLTSUB:
285         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
286         break;
287     case FPE_INTDIV:
288         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
289         break;
290     case FPE_INTOVF:
291         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
292         break;
293     case FPE_FLTDIV:
294         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
295         break;
296     case FPE_FLTOVF:
297         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
298         break;
299     case FPE_FLTUND:
300         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
301         break;
302     case FPE_FLTRES:
303         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
304         break;
305     case FPE_FLTINV:
306     default:
307         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
308         break;
309     }
310
311     save_context( &context, ucontext );
312     save_fpu( &context, ucontext );
313     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
314     rec.ExceptionRecord  = NULL;
315     rec.ExceptionAddress = (LPVOID)context.pc;
316     rec.NumberParameters = 0;
317     __regs_RtlRaiseException( &rec, &context );
318     restore_context( &context, ucontext );
319     restore_fpu( &context, ucontext );
320 }
321
322
323 /**********************************************************************
324  *              int_handler
325  *
326  * Handler for SIGINT.
327  */
328 static void int_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
329 {
330     if (!dispatch_signal(SIGINT))
331     {
332         EXCEPTION_RECORD rec;
333         CONTEXT context;
334
335         save_context( &context, ucontext );
336         rec.ExceptionCode    = CONTROL_C_EXIT;
337         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
338         rec.ExceptionRecord  = NULL;
339         rec.ExceptionAddress = (LPVOID)context.pc;
340         rec.NumberParameters = 0;
341         __regs_RtlRaiseException( &rec, &context );
342         restore_context( &context, ucontext );
343     }
344 }
345
346 /**********************************************************************
347  *              abrt_handler
348  *
349  * Handler for SIGABRT.
350  */
351 static HANDLER_DEF(abrt_handler)
352 {
353     EXCEPTION_RECORD rec;
354     CONTEXT context;
355
356     save_context( &context, HANDLER_CONTEXT );
357     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
358     rec.ExceptionFlags   = EH_NONCONTINUABLE;
359     rec.ExceptionRecord  = NULL;
360     rec.ExceptionAddress = (LPVOID)context.pc;
361     rec.NumberParameters = 0;
362     __regs_RtlRaiseException( &rec, &context ); /* Should never return.. */
363     restore_context( &context, HANDLER_CONTEXT );
364 }
365
366
367 /**********************************************************************
368  *              term_handler
369  *
370  * Handler for SIGTERM.
371  */
372 static HANDLER_DEF(term_handler)
373 {
374     server_abort_thread(0);
375 }
376
377
378 /**********************************************************************
379  *              usr1_handler
380  *
381  * Handler for SIGUSR1, used to signal a thread that it got suspended.
382  */
383 static HANDLER_DEF(usr1_handler)
384 {
385     LARGE_INTEGER timeout;
386
387     /* wait with 0 timeout, will only return once the thread is no longer suspended */
388     timeout.QuadPart = 0;
389     NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout );
390 }
391
392
393 /***********************************************************************
394  *           set_handler
395  *
396  * Set a signal handler
397  */
398 static int set_handler( int sig, void (*func)() )
399 {
400     struct sigaction sig_act;
401
402     sig_act.sa_handler = NULL;
403     sig_act.sa_sigaction = func;
404     sigemptyset( &sig_act.sa_mask );
405     sig_act.sa_flags = SA_SIGINFO;
406
407     return sigaction( sig, &sig_act, NULL );
408 }
409
410
411 /***********************************************************************
412  *           __wine_set_signal_handler   (NTDLL.@)
413  */
414 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
415 {
416     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
417     if (handlers[sig] != NULL) return -2;
418     handlers[sig] = wsh;
419     return 0;
420 }
421
422
423 /**********************************************************************
424  *              SIGNAL_Init
425  */
426 BOOL SIGNAL_Init(void)
427 {
428     if (set_handler( SIGINT,  (void (*)())int_handler  ) == -1) goto error;
429     if (set_handler( SIGFPE,  (void (*)())fpe_handler  ) == -1) goto error;
430     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
431     if (set_handler( SIGILL,  (void (*)())ill_handler  ) == -1) goto error;
432     if (set_handler( SIGBUS,  (void (*)())bus_handler  ) == -1) goto error;
433     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
434     if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
435     if (set_handler( SIGTERM, (void (*)())term_handler ) == -1) goto error;
436     if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
437     /* 'ta 6' tells the kernel to synthesize any unaligned accesses this 
438        process makes, instead of just signalling an error and terminating
439        the process.  wine-devel did not reach a conclusion on whether
440        this is correct, because that is what x86 does, or it is harmful 
441        because it could obscure problems in user code */
442     asm("ta 6"); /* 6 == ST_FIX_ALIGN defined in sys/trap.h */
443    return TRUE;
444
445  error:
446     perror("sigaction");
447     return FALSE;
448 }
449
450
451 /**********************************************************************
452  *              __wine_enter_vm86
453  */
454 void __wine_enter_vm86( CONTEXT *context )
455 {
456     MESSAGE("vm86 mode not supported on this platform\n");
457 }
458
459 /**********************************************************************
460  *              DbgBreakPoint   (NTDLL.@)
461  */
462 void WINAPI DbgBreakPoint(void)
463 {
464      kill(getpid(), SIGTRAP);
465 }
466
467 /**********************************************************************
468  *              DbgUserBreakPoint   (NTDLL.@)
469  */
470 void WINAPI DbgUserBreakPoint(void)
471 {
472      kill(getpid(), SIGTRAP);
473 }
474
475 #endif  /* __sparc__ */