- made the MIDI sequencer error message much better for confused users
[wine] / dlls / ntdll / signal_sparc.c
1 /*
2  * Sparc signal handling routines
3  * 
4  * Copyright 1999 Ulrich Weigand
5  */
6
7 #ifdef __sparc__
8
9 #include "config.h"
10
11 #include <signal.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <stdio.h>
15
16 #include <sys/ucontext.h>
17
18 #include "wine/exception.h"
19 #include "winnt.h"
20 #include "winbase.h"
21 #include "global.h"
22 #include "stackframe.h"
23 #include "debugtools.h"
24
25 DEFAULT_DEBUG_CHANNEL(seh)
26
27
28 /*
29  * FIXME:  All this works only on Solaris for now
30  */
31
32 /**********************************************************************
33  *              save_context
34  */
35 static void save_context( CONTEXT *context, ucontext_t *ucontext )
36 {
37     /* Special registers */
38     context->psr = ucontext->uc_mcontext.gregs[REG_PSR];
39     context->pc  = ucontext->uc_mcontext.gregs[REG_PC];
40     context->npc = ucontext->uc_mcontext.gregs[REG_nPC];
41     context->y   = ucontext->uc_mcontext.gregs[REG_Y];
42     context->wim = 0;  /* FIXME */
43     context->tbr = 0;  /* FIXME */
44
45     /* Global registers */
46     context->g0 = 0;  /* always */
47     context->g1 = ucontext->uc_mcontext.gregs[REG_G1];
48     context->g2 = ucontext->uc_mcontext.gregs[REG_G2];
49     context->g3 = ucontext->uc_mcontext.gregs[REG_G3];
50     context->g4 = ucontext->uc_mcontext.gregs[REG_G4];
51     context->g5 = ucontext->uc_mcontext.gregs[REG_G5];
52     context->g6 = ucontext->uc_mcontext.gregs[REG_G6];
53     context->g7 = ucontext->uc_mcontext.gregs[REG_G7];
54
55     /* Current 'out' registers */
56     context->o0 = ucontext->uc_mcontext.gregs[REG_O0];
57     context->o1 = ucontext->uc_mcontext.gregs[REG_O1];
58     context->o2 = ucontext->uc_mcontext.gregs[REG_O2];
59     context->o3 = ucontext->uc_mcontext.gregs[REG_O3];
60     context->o4 = ucontext->uc_mcontext.gregs[REG_O4];
61     context->o5 = ucontext->uc_mcontext.gregs[REG_O5];
62     context->o6 = ucontext->uc_mcontext.gregs[REG_O6];
63     context->o7 = ucontext->uc_mcontext.gregs[REG_O7];
64
65     /* FIXME: what if the current register window isn't saved? */
66     if ( ucontext->uc_mcontext.gwins && ucontext->uc_mcontext.gwins->wbcnt > 0 )
67     {
68         /* Current 'local' registers from first register window */
69         context->l0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[0];
70         context->l1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[1];
71         context->l2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[2];
72         context->l3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[3];
73         context->l4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[4];
74         context->l5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[5];
75         context->l6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[6];
76         context->l7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[7];
77
78         /* Current 'in' registers from first register window */
79         context->i0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[0];
80         context->i1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[1];
81         context->i2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[2];
82         context->i3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[3];
83         context->i4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[4];
84         context->i5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[5];
85         context->i6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[6];
86         context->i7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[7];
87     }
88 }
89
90 /**********************************************************************
91  *              restore_context
92  */
93 static void restore_context( CONTEXT *context, ucontext_t *ucontext )
94 {
95    /* FIXME */
96 }
97
98 /**********************************************************************
99  *              save_fpu
100  */
101 static void save_fpu( CONTEXT *context, ucontext_t *ucontext )
102 {
103    /* FIXME */
104 }
105
106 /**********************************************************************
107  *              restore_fpu
108  */
109 static void restore_fpu( CONTEXT *context, ucontext_t *ucontext )
110 {
111    /* FIXME */
112 }
113
114
115 /**********************************************************************
116  *              segv_handler
117  *
118  * Handler for SIGSEGV.
119  */
120 static void segv_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
121 {
122     EXCEPTION_RECORD rec;
123     CONTEXT context;
124
125     /* we want the page-fault case to be fast */
126     if ( info->si_code == SEGV_ACCERR )
127         if (VIRTUAL_HandleFault( (LPVOID)info->si_addr )) return;
128
129     save_context( &context, ucontext );
130     rec.ExceptionCode    = EXCEPTION_ACCESS_VIOLATION;
131     rec.ExceptionRecord  = NULL;
132     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
133     rec.ExceptionAddress = (LPVOID)context.pc;
134     rec.NumberParameters = 2;
135     rec.ExceptionInformation[0] = 0;  /* FIXME: read/write access ? */
136     rec.ExceptionInformation[1] = (DWORD)info->si_addr;
137     
138     EXC_RtlRaiseException( &rec, &context );
139     restore_context( &context, ucontext );
140 }
141
142 /**********************************************************************
143  *              bus_handler
144  *
145  * Handler for SIGBUS.
146  */
147 static void bus_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
148 {
149     EXCEPTION_RECORD rec;
150     CONTEXT context;
151
152     save_context( &context, ucontext );
153     rec.ExceptionRecord  = NULL;
154     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
155     rec.ExceptionAddress = (LPVOID)context.pc;
156     rec.NumberParameters = 0;
157
158     if ( info->si_code == BUS_ADRALN )
159         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
160     else
161         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
162     
163     EXC_RtlRaiseException( &rec, &context );
164     restore_context( &context, ucontext );
165 }
166
167 /**********************************************************************
168  *              ill_handler
169  *
170  * Handler for SIGILL.
171  */
172 static void ill_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
173 {
174     EXCEPTION_RECORD rec;
175     CONTEXT context;
176
177     switch ( info->si_code )
178     {
179     default:
180     case ILL_ILLOPC:
181     case ILL_ILLOPN:
182     case ILL_ILLADR:
183     case ILL_ILLTRP:
184         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
185         break;
186
187     case ILL_PRVOPC:
188     case ILL_PRVREG:
189         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
190         break;
191
192     case ILL_BADSTK:
193         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
194         break;
195     }
196     
197     save_context( &context, ucontext );
198     rec.ExceptionRecord  = NULL;
199     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
200     rec.ExceptionAddress = (LPVOID)context.pc;
201     rec.NumberParameters = 0;
202     EXC_RtlRaiseException( &rec, &context );
203     restore_context( &context, ucontext );
204 }
205
206
207 /**********************************************************************
208  *              trap_handler
209  *
210  * Handler for SIGTRAP.
211  */
212 static void trap_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
213 {
214     EXCEPTION_RECORD rec;
215     CONTEXT context;
216
217     switch ( info->si_code )
218     {
219     case TRAP_TRACE:
220         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
221         break;
222     case TRAP_BRKPT:
223     default:
224         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
225         break;
226     }
227
228     save_context( &context, ucontext );
229     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
230     rec.ExceptionRecord  = NULL;
231     rec.ExceptionAddress = (LPVOID)context.pc;
232     rec.NumberParameters = 0;
233     EXC_RtlRaiseException( &rec, &context );
234     restore_context( &context, ucontext );
235 }
236
237
238 /**********************************************************************
239  *              fpe_handler
240  *
241  * Handler for SIGFPE.
242  */
243 static void fpe_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
244 {
245     EXCEPTION_RECORD rec;
246     CONTEXT context;
247
248     switch ( info->si_code )
249     {
250     case FPE_FLTSUB:
251         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
252         break;
253     case FPE_INTDIV:
254         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
255         break;
256     case FPE_INTOVF:
257         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
258         break;
259     case FPE_FLTDIV:
260         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
261         break;
262     case FPE_FLTOVF:
263         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
264         break;
265     case FPE_FLTUND:
266         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
267         break;
268     case FPE_FLTRES:
269         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
270         break;
271     case FPE_FLTINV:
272     default:
273         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
274         break;
275     }
276
277     save_context( &context, ucontext );
278     save_fpu( &context, ucontext );
279     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
280     rec.ExceptionRecord  = NULL;
281     rec.ExceptionAddress = (LPVOID)context.pc;
282     rec.NumberParameters = 0;
283     EXC_RtlRaiseException( &rec, &context );
284     restore_context( &context, ucontext );
285     restore_fpu( &context, ucontext );
286 }
287
288
289 /**********************************************************************
290  *              int_handler
291  *
292  * Handler for SIGINT.
293  */
294 static void int_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
295 {
296     EXCEPTION_RECORD rec;
297     CONTEXT context;
298
299     save_context( &context, ucontext );
300     rec.ExceptionCode    = CONTROL_C_EXIT;
301     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
302     rec.ExceptionRecord  = NULL;
303     rec.ExceptionAddress = (LPVOID)context.pc;
304     rec.NumberParameters = 0;
305     EXC_RtlRaiseException( &rec, &context );
306     restore_context( &context, ucontext );
307 }
308
309
310 /***********************************************************************
311  *           set_handler
312  *
313  * Set a signal handler
314  */
315 static int set_handler( int sig, void (*func)() )
316 {
317     struct sigaction sig_act;
318
319     sig_act.sa_handler = NULL;
320     sig_act.sa_sigaction = func;
321     sigemptyset( &sig_act.sa_mask );
322     sig_act.sa_flags = SA_SIGINFO;
323
324     return sigaction( sig, &sig_act, NULL );
325 }
326
327
328 /**********************************************************************
329  *              SIGNAL_Init
330  */
331 BOOL SIGNAL_Init(void)
332 {
333     /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead  */
334     signal( SIGPIPE, SIG_IGN );
335     /* automatic child reaping to avoid zombies */
336     signal( SIGCHLD, SIG_IGN );
337
338     if (set_handler( SIGINT,  (void (*)())int_handler  ) == -1) goto error;
339     if (set_handler( SIGFPE,  (void (*)())fpe_handler  ) == -1) goto error;
340     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
341     if (set_handler( SIGILL,  (void (*)())ill_handler  ) == -1) goto error;
342     if (set_handler( SIGBUS,  (void (*)())bus_handler  ) == -1) goto error;
343     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
344     return TRUE;
345
346  error:
347     perror("sigaction");
348     return FALSE;
349 }
350
351 /**********************************************************************
352  *              DbgBreakPoint   (NTDLL)
353  */
354 void WINAPI DbgBreakPoint(void)
355 {
356     /* FIXME */
357 }
358
359 /**********************************************************************
360  *              DbgUserBreakPoint   (NTDLL)
361  */
362 void WINAPI DbgUserBreakPoint(void)
363 {
364     /* FIXME */
365 }
366
367 #endif  /* __sparc__ */