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