imagehlp: Forward some more 64-bit functions to dbghelp.
[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 "ntstatus.h"
37 #define WIN32_NO_STATUS
38 #include "windef.h"
39 #include "winternl.h"
40 #include "winnt.h"
41
42 #include "wine/exception.h"
43 #include "ntdll_misc.h"
44
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(seh);
48
49 static pthread_key_t teb_key;
50
51 #define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, ucontext_t *__context )
52 #define HANDLER_CONTEXT (__context)
53
54 typedef int (*wine_signal_handler)(unsigned int sig);
55
56 static wine_signal_handler handlers[256];
57
58 /***********************************************************************
59  *           dispatch_signal
60  */
61 static inline int dispatch_signal(unsigned int sig)
62 {
63     if (handlers[sig] == NULL) return 0;
64     return handlers[sig](sig);
65 }
66
67
68 /*
69  * FIXME:  All this works only on Solaris for now
70  */
71
72 /**********************************************************************
73  *              save_context
74  */
75 static void save_context( CONTEXT *context, ucontext_t *ucontext )
76 {
77     /* Special registers */
78     context->psr = ucontext->uc_mcontext.gregs[REG_PSR];
79     context->pc  = ucontext->uc_mcontext.gregs[REG_PC];
80     context->npc = ucontext->uc_mcontext.gregs[REG_nPC];
81     context->y   = ucontext->uc_mcontext.gregs[REG_Y];
82     context->wim = 0;  /* FIXME */
83     context->tbr = 0;  /* FIXME */
84
85     /* Global registers */
86     context->g0 = 0;  /* always */
87     context->g1 = ucontext->uc_mcontext.gregs[REG_G1];
88     context->g2 = ucontext->uc_mcontext.gregs[REG_G2];
89     context->g3 = ucontext->uc_mcontext.gregs[REG_G3];
90     context->g4 = ucontext->uc_mcontext.gregs[REG_G4];
91     context->g5 = ucontext->uc_mcontext.gregs[REG_G5];
92     context->g6 = ucontext->uc_mcontext.gregs[REG_G6];
93     context->g7 = ucontext->uc_mcontext.gregs[REG_G7];
94
95     /* Current 'out' registers */
96     context->o0 = ucontext->uc_mcontext.gregs[REG_O0];
97     context->o1 = ucontext->uc_mcontext.gregs[REG_O1];
98     context->o2 = ucontext->uc_mcontext.gregs[REG_O2];
99     context->o3 = ucontext->uc_mcontext.gregs[REG_O3];
100     context->o4 = ucontext->uc_mcontext.gregs[REG_O4];
101     context->o5 = ucontext->uc_mcontext.gregs[REG_O5];
102     context->o6 = ucontext->uc_mcontext.gregs[REG_O6];
103     context->o7 = ucontext->uc_mcontext.gregs[REG_O7];
104
105     /* FIXME: what if the current register window isn't saved? */
106     if ( ucontext->uc_mcontext.gwins && ucontext->uc_mcontext.gwins->wbcnt > 0 )
107     {
108         /* Current 'local' registers from first register window */
109         context->l0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[0];
110         context->l1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[1];
111         context->l2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[2];
112         context->l3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[3];
113         context->l4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[4];
114         context->l5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[5];
115         context->l6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[6];
116         context->l7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[7];
117
118         /* Current 'in' registers from first register window */
119         context->i0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[0];
120         context->i1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[1];
121         context->i2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[2];
122         context->i3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[3];
123         context->i4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[4];
124         context->i5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[5];
125         context->i6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[6];
126         context->i7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[7];
127     }
128 }
129
130 /**********************************************************************
131  *              restore_context
132  */
133 static void restore_context( CONTEXT *context, ucontext_t *ucontext )
134 {
135    /* FIXME */
136 }
137
138 /**********************************************************************
139  *              save_fpu
140  */
141 static void save_fpu( CONTEXT *context, ucontext_t *ucontext )
142 {
143    /* FIXME */
144 }
145
146 /**********************************************************************
147  *              restore_fpu
148  */
149 static void restore_fpu( CONTEXT *context, ucontext_t *ucontext )
150 {
151    /* FIXME */
152 }
153
154
155 /***********************************************************************
156  *              RtlCaptureContext (NTDLL.@)
157  */
158 void WINAPI RtlCaptureContext( CONTEXT *context )
159 {
160     FIXME("not implemented\n");
161     memset( context, 0, sizeof(*context) );
162 }
163
164
165 /***********************************************************************
166  *           set_cpu_context
167  *
168  * Set the new CPU context.
169  */
170 void set_cpu_context( const CONTEXT *context )
171 {
172     FIXME("not implemented\n");
173 }
174
175
176 /***********************************************************************
177  *           copy_context
178  *
179  * Copy a register context according to the flags.
180  */
181 void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
182 {
183     flags &= ~CONTEXT_SPARC;  /* get rid of CPU id */
184     if (flags & CONTEXT_CONTROL)
185     {
186         to->psr = from->psr;
187         to->pc  = from->pc;
188         to->npc = from->npc;
189         to->y   = from->y;
190         to->wim = from->wim;
191         to->tbr = from->tbr;
192     }
193     if (flags & CONTEXT_INTEGER)
194     {
195         to->g0 = from->g0;
196         to->g1 = from->g1;
197         to->g2 = from->g2;
198         to->g3 = from->g3;
199         to->g4 = from->g4;
200         to->g5 = from->g5;
201         to->g6 = from->g6;
202         to->g7 = from->g7;
203         to->o0 = from->o0;
204         to->o1 = from->o1;
205         to->o2 = from->o2;
206         to->o3 = from->o3;
207         to->o4 = from->o4;
208         to->o5 = from->o5;
209         to->o6 = from->o6;
210         to->o7 = from->o7;
211         to->l0 = from->l0;
212         to->l1 = from->l1;
213         to->l2 = from->l2;
214         to->l3 = from->l3;
215         to->l4 = from->l4;
216         to->l5 = from->l5;
217         to->l6 = from->l6;
218         to->l7 = from->l7;
219         to->i0 = from->i0;
220         to->i1 = from->i1;
221         to->i2 = from->i2;
222         to->i3 = from->i3;
223         to->i4 = from->i4;
224         to->i5 = from->i5;
225         to->i6 = from->i6;
226         to->i7 = from->i7;
227     }
228     if (flags & CONTEXT_FLOATING_POINT)
229     {
230         /* FIXME */
231     }
232 }
233
234
235 /***********************************************************************
236  *           context_to_server
237  *
238  * Convert a register context to the server format.
239  */
240 NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
241 {
242     DWORD flags = from->ContextFlags & ~CONTEXT_SPARC;  /* get rid of CPU id */
243
244     memset( to, 0, sizeof(*to) );
245     to->cpu = CPU_SPARC;
246
247     if (flags & CONTEXT_CONTROL)
248     {
249         to->flags |= SERVER_CTX_CONTROL;
250         to->ctl.sparc_regs.psr = from->psr;
251         to->ctl.sparc_regs.pc  = from->pc;
252         to->ctl.sparc_regs.npc = from->npc;
253         to->ctl.sparc_regs.y   = from->y;
254         to->ctl.sparc_regs.wim = from->wim;
255         to->ctl.sparc_regs.tbr = from->tbr;
256     }
257     if (flags & CONTEXT_INTEGER)
258     {
259         to->flags |= SERVER_CTX_INTEGER;
260         to->integer.sparc_regs.g[0] = from->g0;
261         to->integer.sparc_regs.g[1] = from->g1;
262         to->integer.sparc_regs.g[2] = from->g2;
263         to->integer.sparc_regs.g[3] = from->g3;
264         to->integer.sparc_regs.g[4] = from->g4;
265         to->integer.sparc_regs.g[5] = from->g5;
266         to->integer.sparc_regs.g[6] = from->g6;
267         to->integer.sparc_regs.g[7] = from->g7;
268         to->integer.sparc_regs.o[0] = from->o0;
269         to->integer.sparc_regs.o[1] = from->o1;
270         to->integer.sparc_regs.o[2] = from->o2;
271         to->integer.sparc_regs.o[3] = from->o3;
272         to->integer.sparc_regs.o[4] = from->o4;
273         to->integer.sparc_regs.o[5] = from->o5;
274         to->integer.sparc_regs.o[6] = from->o6;
275         to->integer.sparc_regs.o[7] = from->o7;
276         to->integer.sparc_regs.l[0] = from->l0;
277         to->integer.sparc_regs.l[1] = from->l1;
278         to->integer.sparc_regs.l[2] = from->l2;
279         to->integer.sparc_regs.l[3] = from->l3;
280         to->integer.sparc_regs.l[4] = from->l4;
281         to->integer.sparc_regs.l[5] = from->l5;
282         to->integer.sparc_regs.l[6] = from->l6;
283         to->integer.sparc_regs.l[7] = from->l7;
284         to->integer.sparc_regs.i[0] = from->i0;
285         to->integer.sparc_regs.i[1] = from->i1;
286         to->integer.sparc_regs.i[2] = from->i2;
287         to->integer.sparc_regs.i[3] = from->i3;
288         to->integer.sparc_regs.i[4] = from->i4;
289         to->integer.sparc_regs.i[5] = from->i5;
290         to->integer.sparc_regs.i[6] = from->i6;
291         to->integer.sparc_regs.i[7] = from->i7;
292     }
293     if (flags & CONTEXT_FLOATING_POINT)
294     {
295         /* FIXME */
296     }
297     return STATUS_SUCCESS;
298 }
299
300
301 /***********************************************************************
302  *           context_from_server
303  *
304  * Convert a register context from the server format.
305  */
306 NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
307 {
308     if (from->cpu != CPU_SPARC) return STATUS_INVALID_PARAMETER;
309
310     to->ContextFlags = CONTEXT_SPARC;
311     if (from->flags & SERVER_CTX_CONTROL)
312     {
313         to->ContextFlags |= CONTEXT_CONTROL;
314         to->psr = from->ctl.sparc_regs.psr;
315         to->pc  = from->ctl.sparc_regs.pc;
316         to->npc = from->ctl.sparc_regs.npc;
317         to->y   = from->ctl.sparc_regs.y;
318         to->wim = from->ctl.sparc_regs.wim;
319         to->tbr = from->ctl.sparc_regs.tbr;
320     }
321     if (from->flags & SERVER_CTX_INTEGER)
322     {
323         to->ContextFlags |= CONTEXT_INTEGER;
324         to->g0 = from->integer.sparc_regs.g[0];
325         to->g1 = from->integer.sparc_regs.g[1];
326         to->g2 = from->integer.sparc_regs.g[2];
327         to->g3 = from->integer.sparc_regs.g[3];
328         to->g4 = from->integer.sparc_regs.g[4];
329         to->g5 = from->integer.sparc_regs.g[5];
330         to->g6 = from->integer.sparc_regs.g[6];
331         to->g7 = from->integer.sparc_regs.g[7];
332         to->o0 = from->integer.sparc_regs.o[0];
333         to->o1 = from->integer.sparc_regs.o[1];
334         to->o2 = from->integer.sparc_regs.o[2];
335         to->o3 = from->integer.sparc_regs.o[3];
336         to->o4 = from->integer.sparc_regs.o[4];
337         to->o5 = from->integer.sparc_regs.o[5];
338         to->o6 = from->integer.sparc_regs.o[6];
339         to->o7 = from->integer.sparc_regs.o[7];
340         to->l0 = from->integer.sparc_regs.l[0];
341         to->l1 = from->integer.sparc_regs.l[1];
342         to->l2 = from->integer.sparc_regs.l[2];
343         to->l3 = from->integer.sparc_regs.l[3];
344         to->l4 = from->integer.sparc_regs.l[4];
345         to->l5 = from->integer.sparc_regs.l[5];
346         to->l6 = from->integer.sparc_regs.l[6];
347         to->l7 = from->integer.sparc_regs.l[7];
348         to->i0 = from->integer.sparc_regs.i[0];
349         to->i1 = from->integer.sparc_regs.i[1];
350         to->i2 = from->integer.sparc_regs.i[2];
351         to->i3 = from->integer.sparc_regs.i[3];
352         to->i4 = from->integer.sparc_regs.i[4];
353         to->i5 = from->integer.sparc_regs.i[5];
354         to->i6 = from->integer.sparc_regs.i[6];
355         to->i7 = from->integer.sparc_regs.i[7];
356     }
357     if (from->flags & SERVER_CTX_FLOATING_POINT)
358     {
359         /* FIXME */
360     }
361     return STATUS_SUCCESS;
362 }
363
364
365 /**********************************************************************
366  *              segv_handler
367  *
368  * Handler for SIGSEGV.
369  */
370 static void segv_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
371 {
372     EXCEPTION_RECORD rec;
373     CONTEXT context;
374     NTSTATUS status;
375
376     rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
377
378     /* we want the page-fault case to be fast */
379     if ( info->si_code == SEGV_ACCERR )
380         if (!(rec.ExceptionCode = virtual_handle_fault( info->si_addr, 0 ))) return;
381
382     save_context( &context, ucontext );
383     rec.ExceptionRecord  = NULL;
384     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
385     rec.ExceptionAddress = (LPVOID)context.pc;
386     rec.NumberParameters = 2;
387     rec.ExceptionInformation[0] = 0;  /* FIXME: read/write access ? */
388     rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
389
390     status = raise_exception( &rec, &context, TRUE );
391     if (status) raise_status( status, &rec );
392     restore_context( &context, ucontext );
393 }
394
395 /**********************************************************************
396  *              bus_handler
397  *
398  * Handler for SIGBUS.
399  */
400 static void bus_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
401 {
402     EXCEPTION_RECORD rec;
403     CONTEXT context;
404     NTSTATUS status;
405
406     save_context( &context, ucontext );
407     rec.ExceptionRecord  = NULL;
408     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
409     rec.ExceptionAddress = (LPVOID)context.pc;
410     rec.NumberParameters = 0;
411
412     if ( info->si_code == BUS_ADRALN )
413         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
414     else
415         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
416
417     status = raise_exception( &rec, &context, TRUE );
418     if (status) raise_status( status, &rec );
419     restore_context( &context, ucontext );
420 }
421
422 /**********************************************************************
423  *              ill_handler
424  *
425  * Handler for SIGILL.
426  */
427 static void ill_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
428 {
429     EXCEPTION_RECORD rec;
430     CONTEXT context;
431     NTSTATUS status;
432
433     switch ( info->si_code )
434     {
435     default:
436     case ILL_ILLOPC:
437     case ILL_ILLOPN:
438     case ILL_ILLADR:
439     case ILL_ILLTRP:
440         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
441         break;
442
443     case ILL_PRVOPC:
444     case ILL_PRVREG:
445         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
446         break;
447
448     case ILL_BADSTK:
449         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
450         break;
451     }
452
453     save_context( &context, ucontext );
454     rec.ExceptionRecord  = NULL;
455     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
456     rec.ExceptionAddress = (LPVOID)context.pc;
457     rec.NumberParameters = 0;
458     status = raise_exception( &rec, &context, TRUE );
459     if (status) raise_status( status, &rec );
460     restore_context( &context, ucontext );
461 }
462
463
464 /**********************************************************************
465  *              trap_handler
466  *
467  * Handler for SIGTRAP.
468  */
469 static void trap_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
470 {
471     EXCEPTION_RECORD rec;
472     CONTEXT context;
473     NTSTATUS status;
474
475     switch ( info->si_code )
476     {
477     case TRAP_TRACE:
478         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
479         break;
480     case TRAP_BRKPT:
481     default:
482         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
483         break;
484     }
485
486     save_context( &context, ucontext );
487     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
488     rec.ExceptionRecord  = NULL;
489     rec.ExceptionAddress = (LPVOID)context.pc;
490     rec.NumberParameters = 0;
491     status = raise_exception( &rec, &context, TRUE );
492     if (status) raise_status( status, &rec );
493     restore_context( &context, ucontext );
494 }
495
496
497 /**********************************************************************
498  *              fpe_handler
499  *
500  * Handler for SIGFPE.
501  */
502 static void fpe_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
503 {
504     EXCEPTION_RECORD rec;
505     CONTEXT context;
506     NTSTATUS status;
507
508     switch ( info->si_code )
509     {
510     case FPE_FLTSUB:
511         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
512         break;
513     case FPE_INTDIV:
514         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
515         break;
516     case FPE_INTOVF:
517         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
518         break;
519     case FPE_FLTDIV:
520         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
521         break;
522     case FPE_FLTOVF:
523         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
524         break;
525     case FPE_FLTUND:
526         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
527         break;
528     case FPE_FLTRES:
529         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
530         break;
531     case FPE_FLTINV:
532     default:
533         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
534         break;
535     }
536
537     save_context( &context, ucontext );
538     save_fpu( &context, ucontext );
539     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
540     rec.ExceptionRecord  = NULL;
541     rec.ExceptionAddress = (LPVOID)context.pc;
542     rec.NumberParameters = 0;
543     status = raise_exception( &rec, &context, TRUE );
544     if (status) raise_status( status, &rec );
545     restore_context( &context, ucontext );
546     restore_fpu( &context, ucontext );
547 }
548
549
550 /**********************************************************************
551  *              int_handler
552  *
553  * Handler for SIGINT.
554  */
555 static void int_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
556 {
557     if (!dispatch_signal(SIGINT))
558     {
559         EXCEPTION_RECORD rec;
560         CONTEXT context;
561         NTSTATUS status;
562
563         save_context( &context, ucontext );
564         rec.ExceptionCode    = CONTROL_C_EXIT;
565         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
566         rec.ExceptionRecord  = NULL;
567         rec.ExceptionAddress = (LPVOID)context.pc;
568         rec.NumberParameters = 0;
569         status = raise_exception( &rec, &context, TRUE );
570         if (status) raise_status( status, &rec );
571         restore_context( &context, ucontext );
572     }
573 }
574
575 /**********************************************************************
576  *              abrt_handler
577  *
578  * Handler for SIGABRT.
579  */
580 static HANDLER_DEF(abrt_handler)
581 {
582     EXCEPTION_RECORD rec;
583     CONTEXT context;
584     NTSTATUS status;
585
586     save_context( &context, HANDLER_CONTEXT );
587     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
588     rec.ExceptionFlags   = EH_NONCONTINUABLE;
589     rec.ExceptionRecord  = NULL;
590     rec.ExceptionAddress = (LPVOID)context.pc;
591     rec.NumberParameters = 0;
592     status = raise_exception( &rec, &context, TRUE );
593     if (status) raise_status( status, &rec );
594     restore_context( &context, HANDLER_CONTEXT );
595 }
596
597
598 /**********************************************************************
599  *              quit_handler
600  *
601  * Handler for SIGQUIT.
602  */
603 static HANDLER_DEF(quit_handler)
604 {
605     abort_thread(0);
606 }
607
608
609 /**********************************************************************
610  *              usr1_handler
611  *
612  * Handler for SIGUSR1, used to signal a thread that it got suspended.
613  */
614 static HANDLER_DEF(usr1_handler)
615 {
616     CONTEXT context;
617
618     save_context( &context, HANDLER_CONTEXT );
619     wait_suspend( &context );
620     restore_context( &context, HANDLER_CONTEXT );
621 }
622
623
624 /**********************************************************************
625  *              get_signal_stack_total_size
626  *
627  * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
628  * Must be a power of two.
629  */
630 size_t get_signal_stack_total_size(void)
631 {
632     assert( sizeof(TEB) <= getpagesize() );
633     return getpagesize();  /* this is just for the TEB, we don't need a signal stack */
634 }
635
636
637 /***********************************************************************
638  *           set_handler
639  *
640  * Set a signal handler
641  */
642 static int set_handler( int sig, void (*func)() )
643 {
644     struct sigaction sig_act;
645
646     sig_act.sa_sigaction = func;
647     sig_act.sa_mask = server_block_set;
648     sig_act.sa_flags = SA_SIGINFO;
649
650     return sigaction( sig, &sig_act, NULL );
651 }
652
653
654 /***********************************************************************
655  *           __wine_set_signal_handler   (NTDLL.@)
656  */
657 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
658 {
659     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
660     if (handlers[sig] != NULL) return -2;
661     handlers[sig] = wsh;
662     return 0;
663 }
664
665
666 /**********************************************************************
667  *              signal_init_thread
668  */
669 void signal_init_thread( TEB *teb )
670 {
671     static int init_done;
672
673     if (!init_done)
674     {
675         pthread_key_create( &teb_key, NULL );
676         init_done = 1;
677     }
678     pthread_setspecific( teb_key, teb );
679 }
680
681
682 /**********************************************************************
683  *              signal_init_process
684  */
685 void signal_init_process(void)
686 {
687     if (set_handler( SIGINT,  (void (*)())int_handler  ) == -1) goto error;
688     if (set_handler( SIGFPE,  (void (*)())fpe_handler  ) == -1) goto error;
689     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
690     if (set_handler( SIGILL,  (void (*)())ill_handler  ) == -1) goto error;
691     if (set_handler( SIGBUS,  (void (*)())bus_handler  ) == -1) goto error;
692     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
693     if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
694     if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
695     if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
696     /* 'ta 6' tells the kernel to synthesize any unaligned accesses this 
697        process makes, instead of just signalling an error and terminating
698        the process.  wine-devel did not reach a conclusion on whether
699        this is correct, because that is what x86 does, or it is harmful 
700        because it could obscure problems in user code */
701     asm("ta 6"); /* 6 == ST_FIX_ALIGN defined in sys/trap.h */
702     return;
703
704  error:
705     perror("sigaction");
706     exit(1);
707 }
708
709
710 /**********************************************************************
711  *              __wine_enter_vm86
712  */
713 void __wine_enter_vm86( CONTEXT *context )
714 {
715     MESSAGE("vm86 mode not supported on this platform\n");
716 }
717
718 /***********************************************************************
719  *              RtlRaiseException (NTDLL.@)
720  */
721 void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec )
722 {
723     CONTEXT context;
724     NTSTATUS status;
725
726     RtlCaptureContext( &context );
727     rec->ExceptionAddress = (void *)context.pc;
728     status = raise_exception( rec, &context, TRUE );
729     if (status) raise_status( status, rec );
730 }
731
732 /**********************************************************************
733  *              DbgBreakPoint   (NTDLL.@)
734  */
735 void WINAPI DbgBreakPoint(void)
736 {
737      kill(getpid(), SIGTRAP);
738 }
739
740 /**********************************************************************
741  *              DbgUserBreakPoint   (NTDLL.@)
742  */
743 void WINAPI DbgUserBreakPoint(void)
744 {
745      kill(getpid(), SIGTRAP);
746 }
747
748 /**********************************************************************
749  *           NtCurrentTeb   (NTDLL.@)
750  */
751 TEB * WINAPI NtCurrentTeb(void)
752 {
753     return pthread_getspecific( teb_key );
754 }
755
756 #endif  /* __sparc__ */