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