winejoystick.drv: Use CP_UNIXCP instead of CP_ACP when converting a string that comes...
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #ifdef __sparc__
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <assert.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <sys/ucontext.h>
35
36 #include "windef.h"
37 #include "winternl.h"
38 #include "winnt.h"
39
40 #include "wine/exception.h"
41 #include "ntdll_misc.h"
42
43 #include "wine/debug.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(seh);
46
47 static pthread_key_t teb_key;
48
49 #define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, ucontext_t *__context )
50 #define HANDLER_CONTEXT (__context)
51
52 typedef int (*wine_signal_handler)(unsigned int sig);
53
54 static wine_signal_handler handlers[256];
55
56 /***********************************************************************
57  *           dispatch_signal
58  */
59 static inline int dispatch_signal(unsigned int sig)
60 {
61     if (handlers[sig] == NULL) return 0;
62     return handlers[sig](sig);
63 }
64
65
66 /*
67  * FIXME:  All this works only on Solaris for now
68  */
69
70 /**********************************************************************
71  *              save_context
72  */
73 static void save_context( CONTEXT *context, ucontext_t *ucontext )
74 {
75     /* Special registers */
76     context->psr = ucontext->uc_mcontext.gregs[REG_PSR];
77     context->pc  = ucontext->uc_mcontext.gregs[REG_PC];
78     context->npc = ucontext->uc_mcontext.gregs[REG_nPC];
79     context->y   = ucontext->uc_mcontext.gregs[REG_Y];
80     context->wim = 0;  /* FIXME */
81     context->tbr = 0;  /* FIXME */
82
83     /* Global registers */
84     context->g0 = 0;  /* always */
85     context->g1 = ucontext->uc_mcontext.gregs[REG_G1];
86     context->g2 = ucontext->uc_mcontext.gregs[REG_G2];
87     context->g3 = ucontext->uc_mcontext.gregs[REG_G3];
88     context->g4 = ucontext->uc_mcontext.gregs[REG_G4];
89     context->g5 = ucontext->uc_mcontext.gregs[REG_G5];
90     context->g6 = ucontext->uc_mcontext.gregs[REG_G6];
91     context->g7 = ucontext->uc_mcontext.gregs[REG_G7];
92
93     /* Current 'out' registers */
94     context->o0 = ucontext->uc_mcontext.gregs[REG_O0];
95     context->o1 = ucontext->uc_mcontext.gregs[REG_O1];
96     context->o2 = ucontext->uc_mcontext.gregs[REG_O2];
97     context->o3 = ucontext->uc_mcontext.gregs[REG_O3];
98     context->o4 = ucontext->uc_mcontext.gregs[REG_O4];
99     context->o5 = ucontext->uc_mcontext.gregs[REG_O5];
100     context->o6 = ucontext->uc_mcontext.gregs[REG_O6];
101     context->o7 = ucontext->uc_mcontext.gregs[REG_O7];
102
103     /* FIXME: what if the current register window isn't saved? */
104     if ( ucontext->uc_mcontext.gwins && ucontext->uc_mcontext.gwins->wbcnt > 0 )
105     {
106         /* Current 'local' registers from first register window */
107         context->l0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[0];
108         context->l1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[1];
109         context->l2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[2];
110         context->l3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[3];
111         context->l4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[4];
112         context->l5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[5];
113         context->l6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[6];
114         context->l7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[7];
115
116         /* Current 'in' registers from first register window */
117         context->i0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[0];
118         context->i1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[1];
119         context->i2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[2];
120         context->i3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[3];
121         context->i4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[4];
122         context->i5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[5];
123         context->i6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[6];
124         context->i7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[7];
125     }
126 }
127
128 /**********************************************************************
129  *              restore_context
130  */
131 static void restore_context( CONTEXT *context, ucontext_t *ucontext )
132 {
133    /* FIXME */
134 }
135
136 /**********************************************************************
137  *              save_fpu
138  */
139 static void save_fpu( CONTEXT *context, ucontext_t *ucontext )
140 {
141    /* FIXME */
142 }
143
144 /**********************************************************************
145  *              restore_fpu
146  */
147 static void restore_fpu( CONTEXT *context, ucontext_t *ucontext )
148 {
149    /* FIXME */
150 }
151
152
153 /***********************************************************************
154  *              RtlCaptureContext (NTDLL.@)
155  */
156 void WINAPI RtlCaptureContext( CONTEXT *context )
157 {
158     FIXME("not implemented\n");
159     memset( context, 0, sizeof(*context) );
160 }
161
162
163 /***********************************************************************
164  *           set_cpu_context
165  *
166  * Set the new CPU context.
167  */
168 void set_cpu_context( const CONTEXT *context )
169 {
170     FIXME("not implemented\n");
171 }
172
173
174 /**********************************************************************
175  *              segv_handler
176  *
177  * Handler for SIGSEGV.
178  */
179 static void segv_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
180 {
181     EXCEPTION_RECORD rec;
182     CONTEXT context;
183
184     rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
185
186     /* we want the page-fault case to be fast */
187     if ( info->si_code == SEGV_ACCERR )
188         if (!(rec.ExceptionCode = virtual_handle_fault( info->si_addr, 0 ))) return;
189
190     save_context( &context, ucontext );
191     rec.ExceptionRecord  = NULL;
192     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
193     rec.ExceptionAddress = (LPVOID)context.pc;
194     rec.NumberParameters = 2;
195     rec.ExceptionInformation[0] = 0;  /* FIXME: read/write access ? */
196     rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
197
198     __regs_RtlRaiseException( &rec, &context );
199     restore_context( &context, ucontext );
200 }
201
202 /**********************************************************************
203  *              bus_handler
204  *
205  * Handler for SIGBUS.
206  */
207 static void bus_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
208 {
209     EXCEPTION_RECORD rec;
210     CONTEXT context;
211
212     save_context( &context, ucontext );
213     rec.ExceptionRecord  = NULL;
214     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
215     rec.ExceptionAddress = (LPVOID)context.pc;
216     rec.NumberParameters = 0;
217
218     if ( info->si_code == BUS_ADRALN )
219         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
220     else
221         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
222
223     __regs_RtlRaiseException( &rec, &context );
224     restore_context( &context, ucontext );
225 }
226
227 /**********************************************************************
228  *              ill_handler
229  *
230  * Handler for SIGILL.
231  */
232 static void ill_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
233 {
234     EXCEPTION_RECORD rec;
235     CONTEXT context;
236
237     switch ( info->si_code )
238     {
239     default:
240     case ILL_ILLOPC:
241     case ILL_ILLOPN:
242     case ILL_ILLADR:
243     case ILL_ILLTRP:
244         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
245         break;
246
247     case ILL_PRVOPC:
248     case ILL_PRVREG:
249         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
250         break;
251
252     case ILL_BADSTK:
253         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
254         break;
255     }
256
257     save_context( &context, ucontext );
258     rec.ExceptionRecord  = NULL;
259     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
260     rec.ExceptionAddress = (LPVOID)context.pc;
261     rec.NumberParameters = 0;
262     __regs_RtlRaiseException( &rec, &context );
263     restore_context( &context, ucontext );
264 }
265
266
267 /**********************************************************************
268  *              trap_handler
269  *
270  * Handler for SIGTRAP.
271  */
272 static void trap_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
273 {
274     EXCEPTION_RECORD rec;
275     CONTEXT context;
276
277     switch ( info->si_code )
278     {
279     case TRAP_TRACE:
280         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
281         break;
282     case TRAP_BRKPT:
283     default:
284         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
285         break;
286     }
287
288     save_context( &context, ucontext );
289     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
290     rec.ExceptionRecord  = NULL;
291     rec.ExceptionAddress = (LPVOID)context.pc;
292     rec.NumberParameters = 0;
293     __regs_RtlRaiseException( &rec, &context );
294     restore_context( &context, ucontext );
295 }
296
297
298 /**********************************************************************
299  *              fpe_handler
300  *
301  * Handler for SIGFPE.
302  */
303 static void fpe_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
304 {
305     EXCEPTION_RECORD rec;
306     CONTEXT context;
307
308     switch ( info->si_code )
309     {
310     case FPE_FLTSUB:
311         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
312         break;
313     case FPE_INTDIV:
314         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
315         break;
316     case FPE_INTOVF:
317         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
318         break;
319     case FPE_FLTDIV:
320         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
321         break;
322     case FPE_FLTOVF:
323         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
324         break;
325     case FPE_FLTUND:
326         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
327         break;
328     case FPE_FLTRES:
329         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
330         break;
331     case FPE_FLTINV:
332     default:
333         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
334         break;
335     }
336
337     save_context( &context, ucontext );
338     save_fpu( &context, ucontext );
339     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
340     rec.ExceptionRecord  = NULL;
341     rec.ExceptionAddress = (LPVOID)context.pc;
342     rec.NumberParameters = 0;
343     __regs_RtlRaiseException( &rec, &context );
344     restore_context( &context, ucontext );
345     restore_fpu( &context, ucontext );
346 }
347
348
349 /**********************************************************************
350  *              int_handler
351  *
352  * Handler for SIGINT.
353  */
354 static void int_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
355 {
356     if (!dispatch_signal(SIGINT))
357     {
358         EXCEPTION_RECORD rec;
359         CONTEXT context;
360
361         save_context( &context, ucontext );
362         rec.ExceptionCode    = CONTROL_C_EXIT;
363         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
364         rec.ExceptionRecord  = NULL;
365         rec.ExceptionAddress = (LPVOID)context.pc;
366         rec.NumberParameters = 0;
367         __regs_RtlRaiseException( &rec, &context );
368         restore_context( &context, ucontext );
369     }
370 }
371
372 /**********************************************************************
373  *              abrt_handler
374  *
375  * Handler for SIGABRT.
376  */
377 static HANDLER_DEF(abrt_handler)
378 {
379     EXCEPTION_RECORD rec;
380     CONTEXT context;
381
382     save_context( &context, HANDLER_CONTEXT );
383     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
384     rec.ExceptionFlags   = EH_NONCONTINUABLE;
385     rec.ExceptionRecord  = NULL;
386     rec.ExceptionAddress = (LPVOID)context.pc;
387     rec.NumberParameters = 0;
388     __regs_RtlRaiseException( &rec, &context ); /* Should never return.. */
389     restore_context( &context, HANDLER_CONTEXT );
390 }
391
392
393 /**********************************************************************
394  *              quit_handler
395  *
396  * Handler for SIGQUIT.
397  */
398 static HANDLER_DEF(quit_handler)
399 {
400     server_abort_thread(0);
401 }
402
403
404 /**********************************************************************
405  *              usr1_handler
406  *
407  * Handler for SIGUSR1, used to signal a thread that it got suspended.
408  */
409 static HANDLER_DEF(usr1_handler)
410 {
411     CONTEXT context;
412
413     save_context( &context, HANDLER_CONTEXT );
414     wait_suspend( &context );
415     restore_context( &context, HANDLER_CONTEXT );
416 }
417
418
419 /**********************************************************************
420  *              get_signal_stack_total_size
421  *
422  * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
423  * Must be a power of two.
424  */
425 size_t get_signal_stack_total_size(void)
426 {
427     assert( sizeof(TEB) <= getpagesize() );
428     return getpagesize();  /* this is just for the TEB, we don't need a signal stack */
429 }
430
431
432 /***********************************************************************
433  *           set_handler
434  *
435  * Set a signal handler
436  */
437 static int set_handler( int sig, void (*func)() )
438 {
439     struct sigaction sig_act;
440
441     sig_act.sa_sigaction = func;
442     sig_act.sa_mask = server_block_set;
443     sig_act.sa_flags = SA_SIGINFO;
444
445     return sigaction( sig, &sig_act, NULL );
446 }
447
448
449 /***********************************************************************
450  *           __wine_set_signal_handler   (NTDLL.@)
451  */
452 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
453 {
454     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
455     if (handlers[sig] != NULL) return -2;
456     handlers[sig] = wsh;
457     return 0;
458 }
459
460
461 /**********************************************************************
462  *              signal_init_thread
463  */
464 void signal_init_thread( TEB *teb )
465 {
466     static int init_done;
467
468     if (!init_done)
469     {
470         pthread_key_create( &teb_key, NULL );
471         init_done = 1;
472     }
473     pthread_setspecific( teb_key, teb );
474 }
475
476
477 /**********************************************************************
478  *              signal_init_process
479  */
480 void signal_init_process(void)
481 {
482     if (set_handler( SIGINT,  (void (*)())int_handler  ) == -1) goto error;
483     if (set_handler( SIGFPE,  (void (*)())fpe_handler  ) == -1) goto error;
484     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
485     if (set_handler( SIGILL,  (void (*)())ill_handler  ) == -1) goto error;
486     if (set_handler( SIGBUS,  (void (*)())bus_handler  ) == -1) goto error;
487     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
488     if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
489     if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
490     if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
491     /* 'ta 6' tells the kernel to synthesize any unaligned accesses this 
492        process makes, instead of just signalling an error and terminating
493        the process.  wine-devel did not reach a conclusion on whether
494        this is correct, because that is what x86 does, or it is harmful 
495        because it could obscure problems in user code */
496     asm("ta 6"); /* 6 == ST_FIX_ALIGN defined in sys/trap.h */
497     signal_init_thread();
498     return;
499
500  error:
501     perror("sigaction");
502     exit(1);
503 }
504
505
506 /**********************************************************************
507  *              __wine_enter_vm86
508  */
509 void __wine_enter_vm86( CONTEXT *context )
510 {
511     MESSAGE("vm86 mode not supported on this platform\n");
512 }
513
514 /**********************************************************************
515  *              DbgBreakPoint   (NTDLL.@)
516  */
517 void WINAPI DbgBreakPoint(void)
518 {
519      kill(getpid(), SIGTRAP);
520 }
521
522 /**********************************************************************
523  *              DbgUserBreakPoint   (NTDLL.@)
524  */
525 void WINAPI DbgUserBreakPoint(void)
526 {
527      kill(getpid(), SIGTRAP);
528 }
529
530 /**********************************************************************
531  *           NtCurrentTeb   (NTDLL.@)
532  */
533 TEB * WINAPI NtCurrentTeb(void)
534 {
535     return pthread_getspecific( teb_key );
536 }
537
538 #endif  /* __sparc__ */