push 20d539bd3127e997ce79233e3988ba5740356ce5
[wine/hacks.git] / dlls / ntdll / signal_sparc.c
blobbd7b49b10029d429f0dcc33cca344000a4e298d0
1 /*
2 * Sparc signal handling routines
4 * Copyright 1999 Ulrich Weigand
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.
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.
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
21 #ifdef __sparc__
23 #include "config.h"
24 #include "wine/port.h"
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>
36 #include "ntstatus.h"
37 #define WIN32_NO_STATUS
38 #include "windef.h"
39 #include "winternl.h"
40 #include "winnt.h"
42 #include "wine/exception.h"
43 #include "ntdll_misc.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(seh);
49 static pthread_key_t teb_key;
51 #define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, ucontext_t *__context )
52 #define HANDLER_CONTEXT (__context)
54 typedef int (*wine_signal_handler)(unsigned int sig);
56 static wine_signal_handler handlers[256];
58 /***********************************************************************
59 * dispatch_signal
61 static inline int dispatch_signal(unsigned int sig)
63 if (handlers[sig] == NULL) return 0;
64 return handlers[sig](sig);
69 * FIXME: All this works only on Solaris for now
72 /**********************************************************************
73 * save_context
75 static void save_context( CONTEXT *context, ucontext_t *ucontext )
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 */
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];
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];
105 /* FIXME: what if the current register window isn't saved? */
106 if ( ucontext->uc_mcontext.gwins && ucontext->uc_mcontext.gwins->wbcnt > 0 )
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];
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];
130 /**********************************************************************
131 * restore_context
133 static void restore_context( CONTEXT *context, ucontext_t *ucontext )
135 /* FIXME */
138 /**********************************************************************
139 * save_fpu
141 static void save_fpu( CONTEXT *context, ucontext_t *ucontext )
143 /* FIXME */
146 /**********************************************************************
147 * restore_fpu
149 static void restore_fpu( CONTEXT *context, ucontext_t *ucontext )
151 /* FIXME */
155 /**********************************************************************
156 * call_stack_handlers
158 * Call the stack handlers chain.
160 static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
162 EXCEPTION_POINTERS ptrs;
164 FIXME( "not implemented on Sparc\n" );
166 /* hack: call unhandled exception filter directly */
167 ptrs.ExceptionRecord = rec;
168 ptrs.ContextRecord = context;
169 unhandled_exception_filter( &ptrs );
170 return STATUS_UNHANDLED_EXCEPTION;
174 /*******************************************************************
175 * raise_exception
177 * Implementation of NtRaiseException.
179 static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
181 NTSTATUS status;
183 if (first_chance)
185 DWORD c;
187 TRACE( "code=%x flags=%x addr=%p ip=%x tid=%04x\n",
188 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
189 context->pc, GetCurrentThreadId() );
190 for (c = 0; c < rec->NumberParameters; c++)
191 TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
192 if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
194 if (rec->ExceptionInformation[1] >> 16)
195 MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
196 rec->ExceptionAddress,
197 (char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
198 else
199 MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
200 rec->ExceptionAddress,
201 (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
203 else
205 /* FIXME: dump context */
208 status = send_debug_event( rec, TRUE, context );
209 if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
210 return STATUS_SUCCESS;
212 if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
213 return STATUS_SUCCESS;
215 if ((status = call_stack_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION)
216 return status;
219 /* last chance exception */
221 status = send_debug_event( rec, FALSE, context );
222 if (status != DBG_CONTINUE)
224 if (rec->ExceptionFlags & EH_STACK_INVALID)
225 ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
226 else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION)
227 ERR("Process attempted to continue execution after noncontinuable exception.\n");
228 else
229 ERR("Unhandled exception code %x flags %x addr %p\n",
230 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
231 NtTerminateProcess( NtCurrentProcess(), 1 );
233 return STATUS_SUCCESS;
237 /***********************************************************************
238 * RtlCaptureContext (NTDLL.@)
240 void WINAPI RtlCaptureContext( CONTEXT *context )
242 FIXME("not implemented\n");
243 memset( context, 0, sizeof(*context) );
247 /***********************************************************************
248 * set_cpu_context
250 * Set the new CPU context.
252 void set_cpu_context( const CONTEXT *context )
254 FIXME("not implemented\n");
258 /***********************************************************************
259 * copy_context
261 * Copy a register context according to the flags.
263 void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
265 flags &= ~CONTEXT_SPARC; /* get rid of CPU id */
266 if (flags & CONTEXT_CONTROL)
268 to->psr = from->psr;
269 to->pc = from->pc;
270 to->npc = from->npc;
271 to->y = from->y;
272 to->wim = from->wim;
273 to->tbr = from->tbr;
275 if (flags & CONTEXT_INTEGER)
277 to->g0 = from->g0;
278 to->g1 = from->g1;
279 to->g2 = from->g2;
280 to->g3 = from->g3;
281 to->g4 = from->g4;
282 to->g5 = from->g5;
283 to->g6 = from->g6;
284 to->g7 = from->g7;
285 to->o0 = from->o0;
286 to->o1 = from->o1;
287 to->o2 = from->o2;
288 to->o3 = from->o3;
289 to->o4 = from->o4;
290 to->o5 = from->o5;
291 to->o6 = from->o6;
292 to->o7 = from->o7;
293 to->l0 = from->l0;
294 to->l1 = from->l1;
295 to->l2 = from->l2;
296 to->l3 = from->l3;
297 to->l4 = from->l4;
298 to->l5 = from->l5;
299 to->l6 = from->l6;
300 to->l7 = from->l7;
301 to->i0 = from->i0;
302 to->i1 = from->i1;
303 to->i2 = from->i2;
304 to->i3 = from->i3;
305 to->i4 = from->i4;
306 to->i5 = from->i5;
307 to->i6 = from->i6;
308 to->i7 = from->i7;
310 if (flags & CONTEXT_FLOATING_POINT)
312 /* FIXME */
317 /***********************************************************************
318 * context_to_server
320 * Convert a register context to the server format.
322 NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
324 DWORD flags = from->ContextFlags & ~CONTEXT_SPARC; /* get rid of CPU id */
326 memset( to, 0, sizeof(*to) );
327 to->cpu = CPU_SPARC;
329 if (flags & CONTEXT_CONTROL)
331 to->flags |= SERVER_CTX_CONTROL;
332 to->ctl.sparc_regs.psr = from->psr;
333 to->ctl.sparc_regs.pc = from->pc;
334 to->ctl.sparc_regs.npc = from->npc;
335 to->ctl.sparc_regs.y = from->y;
336 to->ctl.sparc_regs.wim = from->wim;
337 to->ctl.sparc_regs.tbr = from->tbr;
339 if (flags & CONTEXT_INTEGER)
341 to->flags |= SERVER_CTX_INTEGER;
342 to->integer.sparc_regs.g[0] = from->g0;
343 to->integer.sparc_regs.g[1] = from->g1;
344 to->integer.sparc_regs.g[2] = from->g2;
345 to->integer.sparc_regs.g[3] = from->g3;
346 to->integer.sparc_regs.g[4] = from->g4;
347 to->integer.sparc_regs.g[5] = from->g5;
348 to->integer.sparc_regs.g[6] = from->g6;
349 to->integer.sparc_regs.g[7] = from->g7;
350 to->integer.sparc_regs.o[0] = from->o0;
351 to->integer.sparc_regs.o[1] = from->o1;
352 to->integer.sparc_regs.o[2] = from->o2;
353 to->integer.sparc_regs.o[3] = from->o3;
354 to->integer.sparc_regs.o[4] = from->o4;
355 to->integer.sparc_regs.o[5] = from->o5;
356 to->integer.sparc_regs.o[6] = from->o6;
357 to->integer.sparc_regs.o[7] = from->o7;
358 to->integer.sparc_regs.l[0] = from->l0;
359 to->integer.sparc_regs.l[1] = from->l1;
360 to->integer.sparc_regs.l[2] = from->l2;
361 to->integer.sparc_regs.l[3] = from->l3;
362 to->integer.sparc_regs.l[4] = from->l4;
363 to->integer.sparc_regs.l[5] = from->l5;
364 to->integer.sparc_regs.l[6] = from->l6;
365 to->integer.sparc_regs.l[7] = from->l7;
366 to->integer.sparc_regs.i[0] = from->i0;
367 to->integer.sparc_regs.i[1] = from->i1;
368 to->integer.sparc_regs.i[2] = from->i2;
369 to->integer.sparc_regs.i[3] = from->i3;
370 to->integer.sparc_regs.i[4] = from->i4;
371 to->integer.sparc_regs.i[5] = from->i5;
372 to->integer.sparc_regs.i[6] = from->i6;
373 to->integer.sparc_regs.i[7] = from->i7;
375 if (flags & CONTEXT_FLOATING_POINT)
377 /* FIXME */
379 return STATUS_SUCCESS;
383 /***********************************************************************
384 * context_from_server
386 * Convert a register context from the server format.
388 NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
390 if (from->cpu != CPU_SPARC) return STATUS_INVALID_PARAMETER;
392 to->ContextFlags = CONTEXT_SPARC;
393 if (from->flags & SERVER_CTX_CONTROL)
395 to->ContextFlags |= CONTEXT_CONTROL;
396 to->psr = from->ctl.sparc_regs.psr;
397 to->pc = from->ctl.sparc_regs.pc;
398 to->npc = from->ctl.sparc_regs.npc;
399 to->y = from->ctl.sparc_regs.y;
400 to->wim = from->ctl.sparc_regs.wim;
401 to->tbr = from->ctl.sparc_regs.tbr;
403 if (from->flags & SERVER_CTX_INTEGER)
405 to->ContextFlags |= CONTEXT_INTEGER;
406 to->g0 = from->integer.sparc_regs.g[0];
407 to->g1 = from->integer.sparc_regs.g[1];
408 to->g2 = from->integer.sparc_regs.g[2];
409 to->g3 = from->integer.sparc_regs.g[3];
410 to->g4 = from->integer.sparc_regs.g[4];
411 to->g5 = from->integer.sparc_regs.g[5];
412 to->g6 = from->integer.sparc_regs.g[6];
413 to->g7 = from->integer.sparc_regs.g[7];
414 to->o0 = from->integer.sparc_regs.o[0];
415 to->o1 = from->integer.sparc_regs.o[1];
416 to->o2 = from->integer.sparc_regs.o[2];
417 to->o3 = from->integer.sparc_regs.o[3];
418 to->o4 = from->integer.sparc_regs.o[4];
419 to->o5 = from->integer.sparc_regs.o[5];
420 to->o6 = from->integer.sparc_regs.o[6];
421 to->o7 = from->integer.sparc_regs.o[7];
422 to->l0 = from->integer.sparc_regs.l[0];
423 to->l1 = from->integer.sparc_regs.l[1];
424 to->l2 = from->integer.sparc_regs.l[2];
425 to->l3 = from->integer.sparc_regs.l[3];
426 to->l4 = from->integer.sparc_regs.l[4];
427 to->l5 = from->integer.sparc_regs.l[5];
428 to->l6 = from->integer.sparc_regs.l[6];
429 to->l7 = from->integer.sparc_regs.l[7];
430 to->i0 = from->integer.sparc_regs.i[0];
431 to->i1 = from->integer.sparc_regs.i[1];
432 to->i2 = from->integer.sparc_regs.i[2];
433 to->i3 = from->integer.sparc_regs.i[3];
434 to->i4 = from->integer.sparc_regs.i[4];
435 to->i5 = from->integer.sparc_regs.i[5];
436 to->i6 = from->integer.sparc_regs.i[6];
437 to->i7 = from->integer.sparc_regs.i[7];
439 if (from->flags & SERVER_CTX_FLOATING_POINT)
441 /* FIXME */
443 return STATUS_SUCCESS;
447 /**********************************************************************
448 * segv_handler
450 * Handler for SIGSEGV.
452 static void segv_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
454 EXCEPTION_RECORD rec;
455 CONTEXT context;
456 NTSTATUS status;
458 rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
460 /* we want the page-fault case to be fast */
461 if ( info->si_code == SEGV_ACCERR )
462 if (!(rec.ExceptionCode = virtual_handle_fault( info->si_addr, 0 ))) return;
464 save_context( &context, ucontext );
465 rec.ExceptionRecord = NULL;
466 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
467 rec.ExceptionAddress = (LPVOID)context.pc;
468 rec.NumberParameters = 2;
469 rec.ExceptionInformation[0] = 0; /* FIXME: read/write access ? */
470 rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
472 status = raise_exception( &rec, &context, TRUE );
473 if (status) raise_status( status, &rec );
474 restore_context( &context, ucontext );
477 /**********************************************************************
478 * bus_handler
480 * Handler for SIGBUS.
482 static void bus_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
484 EXCEPTION_RECORD rec;
485 CONTEXT context;
486 NTSTATUS status;
488 save_context( &context, ucontext );
489 rec.ExceptionRecord = NULL;
490 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
491 rec.ExceptionAddress = (LPVOID)context.pc;
492 rec.NumberParameters = 0;
494 if ( info->si_code == BUS_ADRALN )
495 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
496 else
497 rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
499 status = raise_exception( &rec, &context, TRUE );
500 if (status) raise_status( status, &rec );
501 restore_context( &context, ucontext );
504 /**********************************************************************
505 * ill_handler
507 * Handler for SIGILL.
509 static void ill_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
511 EXCEPTION_RECORD rec;
512 CONTEXT context;
513 NTSTATUS status;
515 switch ( info->si_code )
517 default:
518 case ILL_ILLOPC:
519 case ILL_ILLOPN:
520 case ILL_ILLADR:
521 case ILL_ILLTRP:
522 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
523 break;
525 case ILL_PRVOPC:
526 case ILL_PRVREG:
527 rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
528 break;
530 case ILL_BADSTK:
531 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
532 break;
535 save_context( &context, ucontext );
536 rec.ExceptionRecord = NULL;
537 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
538 rec.ExceptionAddress = (LPVOID)context.pc;
539 rec.NumberParameters = 0;
540 status = raise_exception( &rec, &context, TRUE );
541 if (status) raise_status( status, &rec );
542 restore_context( &context, ucontext );
546 /**********************************************************************
547 * trap_handler
549 * Handler for SIGTRAP.
551 static void trap_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
553 EXCEPTION_RECORD rec;
554 CONTEXT context;
555 NTSTATUS status;
557 switch ( info->si_code )
559 case TRAP_TRACE:
560 rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
561 break;
562 case TRAP_BRKPT:
563 default:
564 rec.ExceptionCode = EXCEPTION_BREAKPOINT;
565 break;
568 save_context( &context, ucontext );
569 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
570 rec.ExceptionRecord = NULL;
571 rec.ExceptionAddress = (LPVOID)context.pc;
572 rec.NumberParameters = 0;
573 status = raise_exception( &rec, &context, TRUE );
574 if (status) raise_status( status, &rec );
575 restore_context( &context, ucontext );
579 /**********************************************************************
580 * fpe_handler
582 * Handler for SIGFPE.
584 static void fpe_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
586 EXCEPTION_RECORD rec;
587 CONTEXT context;
588 NTSTATUS status;
590 switch ( info->si_code )
592 case FPE_FLTSUB:
593 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
594 break;
595 case FPE_INTDIV:
596 rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
597 break;
598 case FPE_INTOVF:
599 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
600 break;
601 case FPE_FLTDIV:
602 rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
603 break;
604 case FPE_FLTOVF:
605 rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
606 break;
607 case FPE_FLTUND:
608 rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
609 break;
610 case FPE_FLTRES:
611 rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
612 break;
613 case FPE_FLTINV:
614 default:
615 rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
616 break;
619 save_context( &context, ucontext );
620 save_fpu( &context, ucontext );
621 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
622 rec.ExceptionRecord = NULL;
623 rec.ExceptionAddress = (LPVOID)context.pc;
624 rec.NumberParameters = 0;
625 status = raise_exception( &rec, &context, TRUE );
626 if (status) raise_status( status, &rec );
627 restore_context( &context, ucontext );
628 restore_fpu( &context, ucontext );
632 /**********************************************************************
633 * int_handler
635 * Handler for SIGINT.
637 static void int_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
639 if (!dispatch_signal(SIGINT))
641 EXCEPTION_RECORD rec;
642 CONTEXT context;
643 NTSTATUS status;
645 save_context( &context, ucontext );
646 rec.ExceptionCode = CONTROL_C_EXIT;
647 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
648 rec.ExceptionRecord = NULL;
649 rec.ExceptionAddress = (LPVOID)context.pc;
650 rec.NumberParameters = 0;
651 status = raise_exception( &rec, &context, TRUE );
652 if (status) raise_status( status, &rec );
653 restore_context( &context, ucontext );
657 /**********************************************************************
658 * abrt_handler
660 * Handler for SIGABRT.
662 static HANDLER_DEF(abrt_handler)
664 EXCEPTION_RECORD rec;
665 CONTEXT context;
666 NTSTATUS status;
668 save_context( &context, HANDLER_CONTEXT );
669 rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
670 rec.ExceptionFlags = EH_NONCONTINUABLE;
671 rec.ExceptionRecord = NULL;
672 rec.ExceptionAddress = (LPVOID)context.pc;
673 rec.NumberParameters = 0;
674 status = raise_exception( &rec, &context, TRUE );
675 if (status) raise_status( status, &rec );
676 restore_context( &context, HANDLER_CONTEXT );
680 /**********************************************************************
681 * quit_handler
683 * Handler for SIGQUIT.
685 static HANDLER_DEF(quit_handler)
687 abort_thread(0);
691 /**********************************************************************
692 * usr1_handler
694 * Handler for SIGUSR1, used to signal a thread that it got suspended.
696 static HANDLER_DEF(usr1_handler)
698 CONTEXT context;
700 save_context( &context, HANDLER_CONTEXT );
701 wait_suspend( &context );
702 restore_context( &context, HANDLER_CONTEXT );
706 /**********************************************************************
707 * get_signal_stack_total_size
709 * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
710 * Must be a power of two.
712 size_t get_signal_stack_total_size(void)
714 assert( sizeof(TEB) <= getpagesize() );
715 return getpagesize(); /* this is just for the TEB, we don't need a signal stack */
719 /***********************************************************************
720 * set_handler
722 * Set a signal handler
724 static int set_handler( int sig, void (*func)() )
726 struct sigaction sig_act;
728 sig_act.sa_sigaction = func;
729 sig_act.sa_mask = server_block_set;
730 sig_act.sa_flags = SA_SIGINFO;
732 return sigaction( sig, &sig_act, NULL );
736 /***********************************************************************
737 * __wine_set_signal_handler (NTDLL.@)
739 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
741 if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
742 if (handlers[sig] != NULL) return -2;
743 handlers[sig] = wsh;
744 return 0;
748 /**********************************************************************
749 * signal_init_thread
751 void signal_init_thread( TEB *teb )
753 static int init_done;
755 if (!init_done)
757 pthread_key_create( &teb_key, NULL );
758 init_done = 1;
760 pthread_setspecific( teb_key, teb );
764 /**********************************************************************
765 * signal_init_process
767 void signal_init_process(void)
769 if (set_handler( SIGINT, (void (*)())int_handler ) == -1) goto error;
770 if (set_handler( SIGFPE, (void (*)())fpe_handler ) == -1) goto error;
771 if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
772 if (set_handler( SIGILL, (void (*)())ill_handler ) == -1) goto error;
773 if (set_handler( SIGBUS, (void (*)())bus_handler ) == -1) goto error;
774 if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
775 if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
776 if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
777 if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
778 /* 'ta 6' tells the kernel to synthesize any unaligned accesses this
779 process makes, instead of just signalling an error and terminating
780 the process. wine-devel did not reach a conclusion on whether
781 this is correct, because that is what x86 does, or it is harmful
782 because it could obscure problems in user code */
783 asm("ta 6"); /* 6 == ST_FIX_ALIGN defined in sys/trap.h */
784 return;
786 error:
787 perror("sigaction");
788 exit(1);
792 /**********************************************************************
793 * __wine_enter_vm86
795 void __wine_enter_vm86( CONTEXT *context )
797 MESSAGE("vm86 mode not supported on this platform\n");
800 /***********************************************************************
801 * RtlUnwind (NTDLL.@)
803 void WINAPI RtlUnwind( PVOID pEndFrame, PVOID targetIp, PEXCEPTION_RECORD pRecord, PVOID retval )
805 FIXME( "Not implemented on Sparc\n" );
808 /*******************************************************************
809 * NtRaiseException (NTDLL.@)
811 NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
813 NTSTATUS status = raise_exception( rec, context, first_chance );
814 if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context );
815 return status;
818 /***********************************************************************
819 * RtlRaiseException (NTDLL.@)
821 void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec )
823 CONTEXT context;
824 NTSTATUS status;
826 RtlCaptureContext( &context );
827 rec->ExceptionAddress = (void *)context.pc;
828 status = raise_exception( rec, &context, TRUE );
829 if (status) raise_status( status, rec );
832 /**********************************************************************
833 * DbgBreakPoint (NTDLL.@)
835 void WINAPI DbgBreakPoint(void)
837 kill(getpid(), SIGTRAP);
840 /**********************************************************************
841 * DbgUserBreakPoint (NTDLL.@)
843 void WINAPI DbgUserBreakPoint(void)
845 kill(getpid(), SIGTRAP);
848 /**********************************************************************
849 * NtCurrentTeb (NTDLL.@)
851 TEB * WINAPI NtCurrentTeb(void)
853 return pthread_getspecific( teb_key );
856 #endif /* __sparc__ */