credui: Add the Romanian translation.
[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  *           copy_context
176  *
177  * Copy a register context according to the flags.
178  */
179 void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
180 {
181     flags &= ~CONTEXT_SPARC;  /* get rid of CPU id */
182     if (flags & CONTEXT_CONTROL)
183     {
184         to->psr = from->psr;
185         to->pc  = from->pc;
186         to->npc = from->npc;
187         to->y   = from->y;
188         to->wim = from->wim;
189         to->tbr = from->tbr;
190     }
191     if (flags & CONTEXT_INTEGER)
192     {
193         to->g0 = from->g0;
194         to->g1 = from->g1;
195         to->g2 = from->g2;
196         to->g3 = from->g3;
197         to->g4 = from->g4;
198         to->g5 = from->g5;
199         to->g6 = from->g6;
200         to->g7 = from->g7;
201         to->o0 = from->o0;
202         to->o1 = from->o1;
203         to->o2 = from->o2;
204         to->o3 = from->o3;
205         to->o4 = from->o4;
206         to->o5 = from->o5;
207         to->o6 = from->o6;
208         to->o7 = from->o7;
209         to->l0 = from->l0;
210         to->l1 = from->l1;
211         to->l2 = from->l2;
212         to->l3 = from->l3;
213         to->l4 = from->l4;
214         to->l5 = from->l5;
215         to->l6 = from->l6;
216         to->l7 = from->l7;
217         to->i0 = from->i0;
218         to->i1 = from->i1;
219         to->i2 = from->i2;
220         to->i3 = from->i3;
221         to->i4 = from->i4;
222         to->i5 = from->i5;
223         to->i6 = from->i6;
224         to->i7 = from->i7;
225     }
226     if (flags & CONTEXT_FLOATING_POINT)
227     {
228         /* FIXME */
229     }
230 }
231
232
233 /**********************************************************************
234  *              segv_handler
235  *
236  * Handler for SIGSEGV.
237  */
238 static void segv_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
239 {
240     EXCEPTION_RECORD rec;
241     CONTEXT context;
242
243     rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
244
245     /* we want the page-fault case to be fast */
246     if ( info->si_code == SEGV_ACCERR )
247         if (!(rec.ExceptionCode = virtual_handle_fault( info->si_addr, 0 ))) return;
248
249     save_context( &context, ucontext );
250     rec.ExceptionRecord  = NULL;
251     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
252     rec.ExceptionAddress = (LPVOID)context.pc;
253     rec.NumberParameters = 2;
254     rec.ExceptionInformation[0] = 0;  /* FIXME: read/write access ? */
255     rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
256
257     __regs_RtlRaiseException( &rec, &context );
258     restore_context( &context, ucontext );
259 }
260
261 /**********************************************************************
262  *              bus_handler
263  *
264  * Handler for SIGBUS.
265  */
266 static void bus_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
267 {
268     EXCEPTION_RECORD rec;
269     CONTEXT context;
270
271     save_context( &context, ucontext );
272     rec.ExceptionRecord  = NULL;
273     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
274     rec.ExceptionAddress = (LPVOID)context.pc;
275     rec.NumberParameters = 0;
276
277     if ( info->si_code == BUS_ADRALN )
278         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
279     else
280         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
281
282     __regs_RtlRaiseException( &rec, &context );
283     restore_context( &context, ucontext );
284 }
285
286 /**********************************************************************
287  *              ill_handler
288  *
289  * Handler for SIGILL.
290  */
291 static void ill_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
292 {
293     EXCEPTION_RECORD rec;
294     CONTEXT context;
295
296     switch ( info->si_code )
297     {
298     default:
299     case ILL_ILLOPC:
300     case ILL_ILLOPN:
301     case ILL_ILLADR:
302     case ILL_ILLTRP:
303         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
304         break;
305
306     case ILL_PRVOPC:
307     case ILL_PRVREG:
308         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
309         break;
310
311     case ILL_BADSTK:
312         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
313         break;
314     }
315
316     save_context( &context, ucontext );
317     rec.ExceptionRecord  = NULL;
318     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
319     rec.ExceptionAddress = (LPVOID)context.pc;
320     rec.NumberParameters = 0;
321     __regs_RtlRaiseException( &rec, &context );
322     restore_context( &context, ucontext );
323 }
324
325
326 /**********************************************************************
327  *              trap_handler
328  *
329  * Handler for SIGTRAP.
330  */
331 static void trap_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
332 {
333     EXCEPTION_RECORD rec;
334     CONTEXT context;
335
336     switch ( info->si_code )
337     {
338     case TRAP_TRACE:
339         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
340         break;
341     case TRAP_BRKPT:
342     default:
343         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
344         break;
345     }
346
347     save_context( &context, ucontext );
348     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
349     rec.ExceptionRecord  = NULL;
350     rec.ExceptionAddress = (LPVOID)context.pc;
351     rec.NumberParameters = 0;
352     __regs_RtlRaiseException( &rec, &context );
353     restore_context( &context, ucontext );
354 }
355
356
357 /**********************************************************************
358  *              fpe_handler
359  *
360  * Handler for SIGFPE.
361  */
362 static void fpe_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
363 {
364     EXCEPTION_RECORD rec;
365     CONTEXT context;
366
367     switch ( info->si_code )
368     {
369     case FPE_FLTSUB:
370         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
371         break;
372     case FPE_INTDIV:
373         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
374         break;
375     case FPE_INTOVF:
376         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
377         break;
378     case FPE_FLTDIV:
379         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
380         break;
381     case FPE_FLTOVF:
382         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
383         break;
384     case FPE_FLTUND:
385         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
386         break;
387     case FPE_FLTRES:
388         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
389         break;
390     case FPE_FLTINV:
391     default:
392         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
393         break;
394     }
395
396     save_context( &context, ucontext );
397     save_fpu( &context, ucontext );
398     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
399     rec.ExceptionRecord  = NULL;
400     rec.ExceptionAddress = (LPVOID)context.pc;
401     rec.NumberParameters = 0;
402     __regs_RtlRaiseException( &rec, &context );
403     restore_context( &context, ucontext );
404     restore_fpu( &context, ucontext );
405 }
406
407
408 /**********************************************************************
409  *              int_handler
410  *
411  * Handler for SIGINT.
412  */
413 static void int_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
414 {
415     if (!dispatch_signal(SIGINT))
416     {
417         EXCEPTION_RECORD rec;
418         CONTEXT context;
419
420         save_context( &context, ucontext );
421         rec.ExceptionCode    = CONTROL_C_EXIT;
422         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
423         rec.ExceptionRecord  = NULL;
424         rec.ExceptionAddress = (LPVOID)context.pc;
425         rec.NumberParameters = 0;
426         __regs_RtlRaiseException( &rec, &context );
427         restore_context( &context, ucontext );
428     }
429 }
430
431 /**********************************************************************
432  *              abrt_handler
433  *
434  * Handler for SIGABRT.
435  */
436 static HANDLER_DEF(abrt_handler)
437 {
438     EXCEPTION_RECORD rec;
439     CONTEXT context;
440
441     save_context( &context, HANDLER_CONTEXT );
442     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
443     rec.ExceptionFlags   = EH_NONCONTINUABLE;
444     rec.ExceptionRecord  = NULL;
445     rec.ExceptionAddress = (LPVOID)context.pc;
446     rec.NumberParameters = 0;
447     __regs_RtlRaiseException( &rec, &context ); /* Should never return.. */
448     restore_context( &context, HANDLER_CONTEXT );
449 }
450
451
452 /**********************************************************************
453  *              quit_handler
454  *
455  * Handler for SIGQUIT.
456  */
457 static HANDLER_DEF(quit_handler)
458 {
459     abort_thread(0);
460 }
461
462
463 /**********************************************************************
464  *              usr1_handler
465  *
466  * Handler for SIGUSR1, used to signal a thread that it got suspended.
467  */
468 static HANDLER_DEF(usr1_handler)
469 {
470     CONTEXT context;
471
472     save_context( &context, HANDLER_CONTEXT );
473     wait_suspend( &context );
474     restore_context( &context, HANDLER_CONTEXT );
475 }
476
477
478 /**********************************************************************
479  *              get_signal_stack_total_size
480  *
481  * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
482  * Must be a power of two.
483  */
484 size_t get_signal_stack_total_size(void)
485 {
486     assert( sizeof(TEB) <= getpagesize() );
487     return getpagesize();  /* this is just for the TEB, we don't need a signal stack */
488 }
489
490
491 /***********************************************************************
492  *           set_handler
493  *
494  * Set a signal handler
495  */
496 static int set_handler( int sig, void (*func)() )
497 {
498     struct sigaction sig_act;
499
500     sig_act.sa_sigaction = func;
501     sig_act.sa_mask = server_block_set;
502     sig_act.sa_flags = SA_SIGINFO;
503
504     return sigaction( sig, &sig_act, NULL );
505 }
506
507
508 /***********************************************************************
509  *           __wine_set_signal_handler   (NTDLL.@)
510  */
511 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
512 {
513     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
514     if (handlers[sig] != NULL) return -2;
515     handlers[sig] = wsh;
516     return 0;
517 }
518
519
520 /**********************************************************************
521  *              signal_init_thread
522  */
523 void signal_init_thread( TEB *teb )
524 {
525     static int init_done;
526
527     if (!init_done)
528     {
529         pthread_key_create( &teb_key, NULL );
530         init_done = 1;
531     }
532     pthread_setspecific( teb_key, teb );
533 }
534
535
536 /**********************************************************************
537  *              signal_init_process
538  */
539 void signal_init_process(void)
540 {
541     if (set_handler( SIGINT,  (void (*)())int_handler  ) == -1) goto error;
542     if (set_handler( SIGFPE,  (void (*)())fpe_handler  ) == -1) goto error;
543     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
544     if (set_handler( SIGILL,  (void (*)())ill_handler  ) == -1) goto error;
545     if (set_handler( SIGBUS,  (void (*)())bus_handler  ) == -1) goto error;
546     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
547     if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
548     if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
549     if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
550     /* 'ta 6' tells the kernel to synthesize any unaligned accesses this 
551        process makes, instead of just signalling an error and terminating
552        the process.  wine-devel did not reach a conclusion on whether
553        this is correct, because that is what x86 does, or it is harmful 
554        because it could obscure problems in user code */
555     asm("ta 6"); /* 6 == ST_FIX_ALIGN defined in sys/trap.h */
556     signal_init_thread();
557     return;
558
559  error:
560     perror("sigaction");
561     exit(1);
562 }
563
564
565 /**********************************************************************
566  *              __wine_enter_vm86
567  */
568 void __wine_enter_vm86( CONTEXT *context )
569 {
570     MESSAGE("vm86 mode not supported on this platform\n");
571 }
572
573 /**********************************************************************
574  *              DbgBreakPoint   (NTDLL.@)
575  */
576 void WINAPI DbgBreakPoint(void)
577 {
578      kill(getpid(), SIGTRAP);
579 }
580
581 /**********************************************************************
582  *              DbgUserBreakPoint   (NTDLL.@)
583  */
584 void WINAPI DbgUserBreakPoint(void)
585 {
586      kill(getpid(), SIGTRAP);
587 }
588
589 /**********************************************************************
590  *           NtCurrentTeb   (NTDLL.@)
591  */
592 TEB * WINAPI NtCurrentTeb(void)
593 {
594     return pthread_getspecific( teb_key );
595 }
596
597 #endif  /* __sparc__ */