This commit was manufactured by cvs2svn to create branch
[official-gcc.git] / gcc / ada / init.c
blob6d0480da9e27aace7ae2d07b7f2a26fd031b6717
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * I N I T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 1992-2003 Free Software Foundation, Inc. *
10 * *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 2, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
17 * for more details. You should have received a copy of the GNU General *
18 * Public License distributed with GNAT; see file COPYING. If not, write *
19 * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, *
20 * MA 02111-1307, USA. *
21 * *
22 * As a special exception, if you link this file with other files to *
23 * produce an executable, this file does not by itself cause the resulting *
24 * executable to be covered by the GNU General Public License. This except- *
25 * ion does not however invalidate any other reasons why the executable *
26 * file might be covered by the GNU Public License. *
27 * *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 * *
31 ****************************************************************************/
33 /* This unit contains initialization circuits that are system dependent. A
34 major part of the functionality involved involves stack overflow checking.
35 The GCC backend generates probe instructions to test for stack overflow.
36 For details on the exact approach used to generate these probes, see the
37 "Using and Porting GCC" manual, in particular the "Stack Checking" section
38 and the subsection "Specifying How Stack Checking is Done". The handlers
39 installed by this file are used to handle resulting signals that come
40 from these probes failing (i.e. touching protected pages) */
42 /* The following include is here to meet the published VxWorks requirement
43 that the __vxworks header appear before any other include. */
44 #ifdef __vxworks
45 #include "vxWorks.h"
46 #endif
48 #ifdef IN_RTS
49 #include "tconfig.h"
50 #include "tsystem.h"
51 #include <sys/stat.h>
53 /* We don't have libiberty, so us malloc. */
54 #define xmalloc(S) malloc (S)
55 #else
56 #include "config.h"
57 #include "system.h"
58 #endif
60 #include "adaint.h"
61 #include "raise.h"
63 extern void __gnat_raise_program_error (const char *, int);
65 /* Addresses of exception data blocks for predefined exceptions. */
66 extern struct Exception_Data constraint_error;
67 extern struct Exception_Data numeric_error;
68 extern struct Exception_Data program_error;
69 extern struct Exception_Data storage_error;
70 extern struct Exception_Data tasking_error;
71 extern struct Exception_Data _abort_signal;
73 #define Lock_Task system__soft_links__lock_task
74 extern void (*Lock_Task) (void);
76 #define Unlock_Task system__soft_links__unlock_task
77 extern void (*Unlock_Task) (void);
79 #define Get_Machine_State_Addr \
80 system__soft_links__get_machine_state_addr
81 extern struct Machine_State *(*Get_Machine_State_Addr) (void);
83 #define Check_Abort_Status \
84 system__soft_links__check_abort_status
85 extern int (*Check_Abort_Status) (void);
87 #define Raise_From_Signal_Handler \
88 ada__exceptions__raise_from_signal_handler
89 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
91 #define Propagate_Signal_Exception \
92 __gnat_propagate_sig_exc
93 extern void Propagate_Signal_Exception (struct Machine_State *,
94 struct Exception_Data *,
95 const char *);
97 /* Copies of global values computed by the binder */
98 int __gl_main_priority = -1;
99 int __gl_time_slice_val = -1;
100 char __gl_wc_encoding = 'n';
101 char __gl_locking_policy = ' ';
102 char __gl_queuing_policy = ' ';
103 char __gl_task_dispatching_policy = ' ';
104 char *__gl_restrictions = 0;
105 char *__gl_interrupt_states = 0;
106 int __gl_num_interrupt_states = 0;
107 int __gl_unreserve_all_interrupts = 0;
108 int __gl_exception_tracebacks = 0;
109 int __gl_zero_cost_exceptions = 0;
111 /* Indication of whether synchronous signal handler has already been
112 installed by a previous call to adainit */
113 int __gnat_handler_installed = 0;
115 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
116 is defined. If this is not set them a void implementation will be defined
117 at the end of this unit. */
118 #undef HAVE_GNAT_INIT_FLOAT
120 /******************************/
121 /* __gnat_get_interrupt_state */
122 /******************************/
124 char __gnat_get_interrupt_state (int);
126 /* This routine is called from the runtime as needed to determine the state
127 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
128 in the current partition. The input argument is the interrupt number,
129 and the result is one of the following:
131 'n' this interrupt not set by any Interrupt_State pragma
132 'u' Interrupt_State pragma set state to User
133 'r' Interrupt_State pragma set state to Runtime
134 's' Interrupt_State pragma set state to System */
136 char
137 __gnat_get_interrupt_state (int intrup)
139 if (intrup >= __gl_num_interrupt_states)
140 return 'n';
141 else
142 return __gl_interrupt_states [intrup];
145 /**********************/
146 /* __gnat_set_globals */
147 /**********************/
149 /* This routine is called from the binder generated main program. It copies
150 the values for global quantities computed by the binder into the following
151 global locations. The reason that we go through this copy, rather than just
152 define the global locations in the binder generated file, is that they are
153 referenced from the runtime, which may be in a shared library, and the
154 binder file is not in the shared library. Global references across library
155 boundaries like this are not handled correctly in all systems. */
157 void
158 __gnat_set_globals (int main_priority,
159 int time_slice_val,
160 char wc_encoding,
161 char locking_policy,
162 char queuing_policy,
163 char task_dispatching_policy,
164 char *restrictions,
165 char *interrupt_states,
166 int num_interrupt_states,
167 int unreserve_all_interrupts,
168 int exception_tracebacks,
169 int zero_cost_exceptions)
171 static int already_called = 0;
173 /* If this procedure has been already called once, check that the
174 arguments in this call are consistent with the ones in the previous
175 calls. Otherwise, raise a Program_Error exception.
177 We do not check for consistency of the wide character encoding
178 method. This default affects only Wide_Text_IO where no explicit
179 coding method is given, and there is no particular reason to let
180 this default be affected by the source representation of a library
181 in any case.
183 We do not check either for the consistency of exception tracebacks,
184 because exception tracebacks are not normally set in Stand-Alone
185 libraries. If a library or the main program set the exception
186 tracebacks, then they are never reset afterwards (see below).
188 The value of main_priority is meaningful only when we are invoked
189 from the main program elaboration routine of an Ada application.
190 Checking the consistency of this parameter should therefore not be
191 done. Since it is assured that the main program elaboration will
192 always invoke this procedure before any library elaboration
193 routine, only the value of main_priority during the first call
194 should be taken into account and all the subsequent ones should be
195 ignored. Note that the case where the main program is not written
196 in Ada is also properly handled, since the default value will then
197 be used for this parameter.
199 For identical reasons, the consistency of time_slice_val should not
200 be checked. */
202 if (already_called)
204 if (__gl_locking_policy != locking_policy
205 || __gl_queuing_policy != queuing_policy
206 || __gl_task_dispatching_policy != task_dispatching_policy
207 || __gl_unreserve_all_interrupts != unreserve_all_interrupts
208 || __gl_zero_cost_exceptions != zero_cost_exceptions)
209 __gnat_raise_program_error (__FILE__, __LINE__);
211 /* If either a library or the main program set the exception traceback
212 flag, it is never reset later */
214 if (exception_tracebacks != 0)
215 __gl_exception_tracebacks = exception_tracebacks;
217 return;
219 already_called = 1;
221 __gl_main_priority = main_priority;
222 __gl_time_slice_val = time_slice_val;
223 __gl_wc_encoding = wc_encoding;
224 __gl_locking_policy = locking_policy;
225 __gl_queuing_policy = queuing_policy;
226 __gl_restrictions = restrictions;
227 __gl_interrupt_states = interrupt_states;
228 __gl_num_interrupt_states = num_interrupt_states;
229 __gl_task_dispatching_policy = task_dispatching_policy;
230 __gl_unreserve_all_interrupts = unreserve_all_interrupts;
231 __gl_exception_tracebacks = exception_tracebacks;
233 /* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
234 a-except.adb, which is also part of the compiler sources. Since the
235 compiler is built with an older release of GNAT, the call generated by
236 the old binder to this function does not provide any value for the
237 corresponding argument, so the global has to be initialized in some
238 reasonable other way. This could be removed as soon as the next major
239 release is out. */
241 #ifdef IN_RTS
242 __gl_zero_cost_exceptions = zero_cost_exceptions;
243 #else
244 __gl_zero_cost_exceptions = 0;
245 /* We never build the compiler to run in ZCX mode currently anyway. */
246 #endif
249 /*********************/
250 /* __gnat_initialize */
251 /*********************/
253 /* __gnat_initialize is called at the start of execution of an Ada program
254 (the call is generated by the binder). The standard routine does nothing
255 at all; the intention is that this be replaced by system specific
256 code where initialization is required. */
258 /***********************************/
259 /* __gnat_initialize (AIX Version) */
260 /***********************************/
262 #if defined (_AIX)
264 #include <signal.h>
265 #include <sys/time.h>
267 /* Some versions of AIX don't define SA_NODEFER. */
269 #ifndef SA_NODEFER
270 #define SA_NODEFER 0
271 #endif /* SA_NODEFER */
273 /* Versions of AIX before 4.3 don't have nanosleep but provide
274 nsleep instead. */
276 #ifndef _AIXVERSION_430
278 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
281 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
283 return nsleep (Rqtp, Rmtp);
286 #endif /* _AIXVERSION_430 */
288 static void __gnat_error_handler (int);
290 static void
291 __gnat_error_handler (int sig)
293 struct Exception_Data *exception;
294 const char *msg;
296 switch (sig)
298 case SIGSEGV:
299 /* FIXME: we need to detect the case of a *real* SIGSEGV */
300 exception = &storage_error;
301 msg = "stack overflow or erroneous memory access";
302 break;
304 case SIGBUS:
305 exception = &constraint_error;
306 msg = "SIGBUS";
307 break;
309 case SIGFPE:
310 exception = &constraint_error;
311 msg = "SIGFPE";
312 break;
314 default:
315 exception = &program_error;
316 msg = "unhandled signal";
319 Raise_From_Signal_Handler (exception, msg);
322 void
323 __gnat_install_handler (void)
325 struct sigaction act;
327 /* Set up signal handler to map synchronous signals to appropriate
328 exceptions. Make sure that the handler isn't interrupted by another
329 signal that might cause a scheduling event! */
331 act.sa_handler = __gnat_error_handler;
332 act.sa_flags = SA_NODEFER | SA_RESTART;
333 sigemptyset (&act.sa_mask);
335 /* Do not install handlers if interrupt state is "System" */
336 if (__gnat_get_interrupt_state (SIGABRT) != 's')
337 sigaction (SIGABRT, &act, NULL);
338 if (__gnat_get_interrupt_state (SIGFPE) != 's')
339 sigaction (SIGFPE, &act, NULL);
340 if (__gnat_get_interrupt_state (SIGILL) != 's')
341 sigaction (SIGILL, &act, NULL);
342 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
343 sigaction (SIGSEGV, &act, NULL);
344 if (__gnat_get_interrupt_state (SIGBUS) != 's')
345 sigaction (SIGBUS, &act, NULL);
347 __gnat_handler_installed = 1;
350 void
351 __gnat_initialize (void)
355 /***************************************/
356 /* __gnat_initialize (RTEMS version) */
357 /***************************************/
359 #elif defined(__rtems__)
361 extern void __gnat_install_handler (void);
363 /* For RTEMS, each bsp will provide a custom __gnat_install_handler (). */
365 void
366 __gnat_initialize (void)
368 __gnat_install_handler ();
371 /****************************************/
372 /* __gnat_initialize (Dec Unix Version) */
373 /****************************************/
375 #elif defined(__alpha__) && defined(__osf__) && ! defined(__alpha_vxworks)
377 /* Note: it seems that __osf__ is defined for the Alpha VXWorks case. Not
378 clear that this is reasonable, but in any case we have to be sure to
379 exclude this case in the above test. */
381 #include <signal.h>
382 #include <sys/siginfo.h>
384 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
385 extern char *__gnat_get_code_loc (struct sigcontext *);
386 extern void __gnat_enter_handler (struct sigcontext *, char *);
387 extern size_t __gnat_machine_state_length (void);
389 extern long exc_lookup_gp (char *);
390 extern void exc_resume (struct sigcontext *);
392 static void
393 __gnat_error_handler (int sig, siginfo_t *sip, struct sigcontext *context)
395 struct Exception_Data *exception;
396 static int recurse = 0;
397 struct sigcontext *mstate;
398 const char *msg;
400 /* If this was an explicit signal from a "kill", just resignal it. */
401 if (SI_FROMUSER (sip))
403 signal (sig, SIG_DFL);
404 kill (getpid(), sig);
407 /* Otherwise, treat it as something we handle. */
408 switch (sig)
410 case SIGSEGV:
411 /* If the problem was permissions, this is a constraint error.
412 Likewise if the failing address isn't maximally aligned or if
413 we've recursed.
415 ??? Using a static variable here isn't task-safe, but it's
416 much too hard to do anything else and we're just determining
417 which exception to raise. */
418 if (sip->si_code == SEGV_ACCERR
419 || (((long) sip->si_addr) & 3) != 0
420 || recurse)
422 exception = &constraint_error;
423 msg = "SIGSEGV";
425 else
427 /* See if the page before the faulting page is accessible. Do that
428 by trying to access it. We'd like to simply try to access
429 4096 + the faulting address, but it's not guaranteed to be
430 the actual address, just to be on the same page. */
431 recurse++;
432 ((volatile char *)
433 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
434 msg = "stack overflow (or erroneous memory access)";
435 exception = &storage_error;
437 break;
439 case SIGBUS:
440 exception = &program_error;
441 msg = "SIGBUS";
442 break;
444 case SIGFPE:
445 exception = &constraint_error;
446 msg = "SIGFPE";
447 break;
449 default:
450 exception = &program_error;
451 msg = "unhandled signal";
454 recurse = 0;
455 mstate = (struct sigcontext *) (*Get_Machine_State_Addr) ();
456 if (mstate != 0)
457 *mstate = *context;
459 Raise_From_Signal_Handler (exception, (char *) msg);
462 void
463 __gnat_install_handler (void)
465 struct sigaction act;
467 /* Setup signal handler to map synchronous signals to appropriate
468 exceptions. Make sure that the handler isn't interrupted by another
469 signal that might cause a scheduling event! */
471 act.sa_handler = (void (*) (int)) __gnat_error_handler;
472 act.sa_flags = SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_SIGINFO;
473 sigemptyset (&act.sa_mask);
475 /* Do not install handlers if interrupt state is "System" */
476 if (__gnat_get_interrupt_state (SIGABRT) != 's')
477 sigaction (SIGABRT, &act, NULL);
478 if (__gnat_get_interrupt_state (SIGFPE) != 's')
479 sigaction (SIGFPE, &act, NULL);
480 if (__gnat_get_interrupt_state (SIGILL) != 's')
481 sigaction (SIGILL, &act, NULL);
482 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
483 sigaction (SIGSEGV, &act, NULL);
484 if (__gnat_get_interrupt_state (SIGBUS) != 's')
485 sigaction (SIGBUS, &act, NULL);
487 __gnat_handler_installed = 1;
490 void
491 __gnat_initialize (void)
495 /* Routines called by 5amastop.adb. */
497 #define SC_GP 29
499 char *
500 __gnat_get_code_loc (struct sigcontext *context)
502 return (char *) context->sc_pc;
505 void
506 __gnat_enter_handler ( struct sigcontext *context, char *pc)
508 context->sc_pc = (long) pc;
509 context->sc_regs[SC_GP] = exc_lookup_gp (pc);
510 exc_resume (context);
513 size_t
514 __gnat_machine_state_length (void)
516 return sizeof (struct sigcontext);
519 /************************************/
520 /* __gnat_initialize (HPUX Version) */
521 /************************************/
523 #elif defined (hpux)
525 #include <signal.h>
527 static void __gnat_error_handler (int);
529 static void
530 __gnat_error_handler (int sig)
532 struct Exception_Data *exception;
533 char *msg;
535 switch (sig)
537 case SIGSEGV:
538 /* FIXME: we need to detect the case of a *real* SIGSEGV */
539 exception = &storage_error;
540 msg = "stack overflow or erroneous memory access";
541 break;
543 case SIGBUS:
544 exception = &constraint_error;
545 msg = "SIGBUS";
546 break;
548 case SIGFPE:
549 exception = &constraint_error;
550 msg = "SIGFPE";
551 break;
553 default:
554 exception = &program_error;
555 msg = "unhandled signal";
558 Raise_From_Signal_Handler (exception, msg);
561 void
562 __gnat_install_handler (void)
564 struct sigaction act;
566 /* Set up signal handler to map synchronous signals to appropriate
567 exceptions. Make sure that the handler isn't interrupted by another
568 signal that might cause a scheduling event! Also setup an alternate
569 stack region for the handler execution so that stack overflows can be
570 handled properly, avoiding a SEGV generation from stack usage by the
571 handler itself. */
573 static char handler_stack[SIGSTKSZ*2];
574 /* SIGSTKSZ appeared to be "short" for the needs in some contexts
575 (e.g. experiments with GCC ZCX exceptions). */
577 stack_t stack;
579 stack.ss_sp = handler_stack;
580 stack.ss_size = sizeof (handler_stack);
581 stack.ss_flags = 0;
583 sigaltstack (&stack, NULL);
585 act.sa_handler = __gnat_error_handler;
586 act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK;
587 sigemptyset (&act.sa_mask);
589 /* Do not install handlers if interrupt state is "System" */
590 if (__gnat_get_interrupt_state (SIGABRT) != 's')
591 sigaction (SIGABRT, &act, NULL);
592 if (__gnat_get_interrupt_state (SIGFPE) != 's')
593 sigaction (SIGFPE, &act, NULL);
594 if (__gnat_get_interrupt_state (SIGILL) != 's')
595 sigaction (SIGILL, &act, NULL);
596 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
597 sigaction (SIGSEGV, &act, NULL);
598 if (__gnat_get_interrupt_state (SIGBUS) != 's')
599 sigaction (SIGBUS, &act, NULL);
601 __gnat_handler_installed = 1;
604 void
605 __gnat_initialize (void)
609 /*****************************************/
610 /* __gnat_initialize (GNU/Linux Version) */
611 /*****************************************/
613 #elif defined (linux) && defined (i386) && !defined (__RT__)
615 #include <signal.h>
616 #include <asm/sigcontext.h>
618 /* GNU/Linux, which uses glibc, does not define NULL in included
619 header files */
621 #if !defined (NULL)
622 #define NULL ((void *) 0)
623 #endif
625 struct Machine_State
627 unsigned long eip;
628 unsigned long ebx;
629 unsigned long esp;
630 unsigned long ebp;
631 unsigned long esi;
632 unsigned long edi;
635 static void __gnat_error_handler (int);
637 static void
638 __gnat_error_handler (int sig)
640 struct Exception_Data *exception;
641 const char *msg;
642 static int recurse = 0;
644 struct sigcontext *info
645 = (struct sigcontext *) (((char *) &sig) + sizeof (int));
647 /* The Linux kernel does not document how to get the machine state in a
648 signal handler, but in fact the necessary data is in a sigcontext_struct
649 value that is on the stack immediately above the signal number
650 parameter, and the above messing accesses this value on the stack. */
652 struct Machine_State *mstate;
654 switch (sig)
656 case SIGSEGV:
657 /* If the problem was permissions, this is a constraint error.
658 Likewise if the failing address isn't maximally aligned or if
659 we've recursed.
661 ??? Using a static variable here isn't task-safe, but it's
662 much too hard to do anything else and we're just determining
663 which exception to raise. */
664 if (recurse)
666 exception = &constraint_error;
667 msg = "SIGSEGV";
669 else
671 /* Here we would like a discrimination test to see whether the
672 page before the faulting address is accessible. Unfortunately
673 Linux seems to have no way of giving us the faulting address.
675 In versions of a-init.c before 1.95, we had a test of the page
676 before the stack pointer using:
678 recurse++;
679 ((volatile char *)
680 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
682 but that's wrong, since it tests the stack pointer location, and
683 the current stack probe code does not move the stack pointer
684 until all probes succeed.
686 For now we simply do not attempt any discrimination at all. Note
687 that this is quite acceptable, since a "real" SIGSEGV can only
688 occur as the result of an erroneous program */
690 msg = "stack overflow (or erroneous memory access)";
691 exception = &storage_error;
693 break;
695 case SIGBUS:
696 exception = &constraint_error;
697 msg = "SIGBUS";
698 break;
700 case SIGFPE:
701 exception = &constraint_error;
702 msg = "SIGFPE";
703 break;
705 default:
706 exception = &program_error;
707 msg = "unhandled signal";
710 mstate = (*Get_Machine_State_Addr) ();
711 if (mstate)
713 mstate->eip = info->eip;
714 mstate->ebx = info->ebx;
715 mstate->esp = info->esp_at_signal;
716 mstate->ebp = info->ebp;
717 mstate->esi = info->esi;
718 mstate->edi = info->edi;
721 recurse = 0;
722 Raise_From_Signal_Handler (exception, msg);
725 void
726 __gnat_install_handler (void)
728 struct sigaction act;
730 /* Set up signal handler to map synchronous signals to appropriate
731 exceptions. Make sure that the handler isn't interrupted by another
732 signal that might cause a scheduling event! */
734 act.sa_handler = __gnat_error_handler;
735 act.sa_flags = SA_NODEFER | SA_RESTART;
736 sigemptyset (&act.sa_mask);
738 /* Do not install handlers if interrupt state is "System" */
739 if (__gnat_get_interrupt_state (SIGABRT) != 's')
740 sigaction (SIGABRT, &act, NULL);
741 if (__gnat_get_interrupt_state (SIGFPE) != 's')
742 sigaction (SIGFPE, &act, NULL);
743 if (__gnat_get_interrupt_state (SIGILL) != 's')
744 sigaction (SIGILL, &act, NULL);
745 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
746 sigaction (SIGSEGV, &act, NULL);
747 if (__gnat_get_interrupt_state (SIGBUS) != 's')
748 sigaction (SIGBUS, &act, NULL);
750 __gnat_handler_installed = 1;
753 void
754 __gnat_initialize (void)
758 /******************************************/
759 /* __gnat_initialize (NT-mingw32 Version) */
760 /******************************************/
762 #elif defined (__MINGW32__)
763 #include <windows.h>
765 static LONG WINAPI __gnat_error_handler (PEXCEPTION_POINTERS);
767 /* __gnat_initialize (mingw32). */
769 static LONG WINAPI
770 __gnat_error_handler (PEXCEPTION_POINTERS info)
772 static int recurse;
773 struct Exception_Data *exception;
774 const char *msg;
776 switch (info->ExceptionRecord->ExceptionCode)
778 case EXCEPTION_ACCESS_VIOLATION:
779 /* If the failing address isn't maximally-aligned or if we've
780 recursed, this is a program error. */
781 if ((info->ExceptionRecord->ExceptionInformation[1] & 3) != 0
782 || recurse)
784 exception = &program_error;
785 msg = "EXCEPTION_ACCESS_VIOLATION";
787 else
789 /* See if the page before the faulting page is accessible. Do that
790 by trying to access it. */
791 recurse++;
792 * ((volatile char *) (info->ExceptionRecord->ExceptionInformation[1]
793 + 4096));
794 exception = &storage_error;
795 msg = "stack overflow (or erroneous memory access)";
797 break;
799 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
800 exception = &constraint_error;
801 msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
802 break;
804 case EXCEPTION_DATATYPE_MISALIGNMENT:
805 exception = &constraint_error;
806 msg = "EXCEPTION_DATATYPE_MISALIGNMENT";
807 break;
809 case EXCEPTION_FLT_DENORMAL_OPERAND:
810 exception = &constraint_error;
811 msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
812 break;
814 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
815 exception = &constraint_error;
816 msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
817 break;
819 case EXCEPTION_FLT_INVALID_OPERATION:
820 exception = &constraint_error;
821 msg = "EXCEPTION_FLT_INVALID_OPERATION";
822 break;
824 case EXCEPTION_FLT_OVERFLOW:
825 exception = &constraint_error;
826 msg = "EXCEPTION_FLT_OVERFLOW";
827 break;
829 case EXCEPTION_FLT_STACK_CHECK:
830 exception = &program_error;
831 msg = "EXCEPTION_FLT_STACK_CHECK";
832 break;
834 case EXCEPTION_FLT_UNDERFLOW:
835 exception = &constraint_error;
836 msg = "EXCEPTION_FLT_UNDERFLOW";
837 break;
839 case EXCEPTION_INT_DIVIDE_BY_ZERO:
840 exception = &constraint_error;
841 msg = "EXCEPTION_INT_DIVIDE_BY_ZERO";
842 break;
844 case EXCEPTION_INT_OVERFLOW:
845 exception = &constraint_error;
846 msg = "EXCEPTION_INT_OVERFLOW";
847 break;
849 case EXCEPTION_INVALID_DISPOSITION:
850 exception = &program_error;
851 msg = "EXCEPTION_INVALID_DISPOSITION";
852 break;
854 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
855 exception = &program_error;
856 msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
857 break;
859 case EXCEPTION_PRIV_INSTRUCTION:
860 exception = &program_error;
861 msg = "EXCEPTION_PRIV_INSTRUCTION";
862 break;
864 case EXCEPTION_SINGLE_STEP:
865 exception = &program_error;
866 msg = "EXCEPTION_SINGLE_STEP";
867 break;
869 case EXCEPTION_STACK_OVERFLOW:
870 exception = &storage_error;
871 msg = "EXCEPTION_STACK_OVERFLOW";
872 break;
874 default:
875 exception = &program_error;
876 msg = "unhandled signal";
879 recurse = 0;
880 Raise_From_Signal_Handler (exception, msg);
881 return 0; /* This is never reached, avoid compiler warning */
884 void
885 __gnat_install_handler (void)
887 SetUnhandledExceptionFilter (__gnat_error_handler);
888 __gnat_handler_installed = 1;
891 void
892 __gnat_initialize (void)
895 /* Initialize floating-point coprocessor. This call is needed because
896 the MS libraries default to 64-bit precision instead of 80-bit
897 precision, and we require the full precision for proper operation,
898 given that we have set Max_Digits etc with this in mind */
900 __gnat_init_float ();
902 /* initialize a lock for a process handle list - see a-adaint.c for the
903 implementation of __gnat_portable_no_block_spawn, __gnat_portable_wait */
904 __gnat_plist_init();
907 /***************************************/
908 /* __gnat_initialize (Interix Version) */
909 /***************************************/
911 #elif defined (__INTERIX)
913 #include <signal.h>
915 static void __gnat_error_handler (int);
917 static void
918 __gnat_error_handler (int sig)
920 struct Exception_Data *exception;
921 char *msg;
923 switch (sig)
925 case SIGSEGV:
926 exception = &storage_error;
927 msg = "stack overflow or erroneous memory access";
928 break;
930 case SIGBUS:
931 exception = &constraint_error;
932 msg = "SIGBUS";
933 break;
935 case SIGFPE:
936 exception = &constraint_error;
937 msg = "SIGFPE";
938 break;
940 default:
941 exception = &program_error;
942 msg = "unhandled signal";
945 Raise_From_Signal_Handler (exception, msg);
948 void
949 __gnat_install_handler (void)
951 struct sigaction act;
953 /* Set up signal handler to map synchronous signals to appropriate
954 exceptions. Make sure that the handler isn't interrupted by another
955 signal that might cause a scheduling event! */
957 act.sa_handler = __gnat_error_handler;
958 act.sa_flags = 0;
959 sigemptyset (&act.sa_mask);
961 /* Handlers for signals besides SIGSEGV cause c974013 to hang */
962 /* sigaction (SIGILL, &act, NULL); */
963 /* sigaction (SIGABRT, &act, NULL); */
964 /* sigaction (SIGFPE, &act, NULL); */
965 /* sigaction (SIGBUS, &act, NULL); */
967 /* Do not install handlers if interrupt state is "System" */
968 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
969 sigaction (SIGSEGV, &act, NULL);
971 __gnat_handler_installed = 1;
974 void
975 __gnat_initialize (void)
977 __gnat_init_float ();
980 /**************************************/
981 /* __gnat_initialize (LynxOS Version) */
982 /**************************************/
984 #elif defined (__Lynx__)
986 void
987 __gnat_initialize (void)
989 __gnat_init_float ();
992 /*********************************/
993 /* __gnat_install_handler (Lynx) */
994 /*********************************/
996 void
997 __gnat_install_handler (void)
999 __gnat_handler_installed = 1;
1002 /****************************/
1003 /* __gnat_initialize (OS/2) */
1004 /****************************/
1006 #elif defined (__EMX__) /* OS/2 dependent initialization */
1008 void
1009 __gnat_initialize (void)
1013 /*********************************/
1014 /* __gnat_install_handler (OS/2) */
1015 /*********************************/
1017 void
1018 __gnat_install_handler (void)
1020 __gnat_handler_installed = 1;
1023 /***********************************/
1024 /* __gnat_initialize (SGI Version) */
1025 /***********************************/
1027 #elif defined (sgi)
1029 #include <signal.h>
1030 #include <siginfo.h>
1032 #ifndef NULL
1033 #define NULL 0
1034 #endif
1036 #define SIGADAABORT 48
1037 #define SIGNAL_STACK_SIZE 4096
1038 #define SIGNAL_STACK_ALIGNMENT 64
1040 struct Machine_State
1042 sigcontext_t context;
1045 static void __gnat_error_handler (int, int, sigcontext_t *);
1047 static void
1048 __gnat_error_handler (int sig, int code, sigcontext_t *sc)
1050 struct Machine_State *mstate;
1051 struct Exception_Data *exception;
1052 const char *msg;
1054 switch (sig)
1056 case SIGSEGV:
1057 if (code == EFAULT)
1059 exception = &program_error;
1060 msg = "SIGSEGV: (Invalid virtual address)";
1062 else if (code == ENXIO)
1064 exception = &program_error;
1065 msg = "SIGSEGV: (Read beyond mapped object)";
1067 else if (code == ENOSPC)
1069 exception = &program_error; /* ??? storage_error ??? */
1070 msg = "SIGSEGV: (Autogrow for file failed)";
1072 else if (code == EACCES)
1074 /* ??? Re-add smarts to further verify that we launched
1075 the stack into a guard page, not an attempt to
1076 write to .text or something */
1077 exception = &storage_error;
1078 msg = "SIGSEGV: (stack overflow or erroneous memory access)";
1080 else
1082 /* Just in case the OS guys did it to us again. Sometimes
1083 they fail to document all of the valid codes that are
1084 passed to signal handlers, just in case someone depends
1085 on knowing all the codes */
1086 exception = &program_error;
1087 msg = "SIGSEGV: (Undocumented reason)";
1089 break;
1091 case SIGBUS:
1092 /* Map all bus errors to Program_Error. */
1093 exception = &program_error;
1094 msg = "SIGBUS";
1095 break;
1097 case SIGFPE:
1098 /* Map all fpe errors to Constraint_Error. */
1099 exception = &constraint_error;
1100 msg = "SIGFPE";
1101 break;
1103 case SIGADAABORT:
1104 if ((*Check_Abort_Status) ())
1106 exception = &_abort_signal;
1107 msg = "";
1109 else
1110 return;
1112 break;
1114 default:
1115 /* Everything else is a Program_Error. */
1116 exception = &program_error;
1117 msg = "unhandled signal";
1120 mstate = (*Get_Machine_State_Addr) ();
1121 if (mstate != 0)
1122 memcpy ((void *) mstate, (const void *) sc, sizeof (sigcontext_t));
1124 Raise_From_Signal_Handler (exception, msg);
1127 void
1128 __gnat_install_handler (void)
1130 struct sigaction act;
1132 /* Setup signal handler to map synchronous signals to appropriate
1133 exceptions. Make sure that the handler isn't interrupted by another
1134 signal that might cause a scheduling event! */
1136 act.sa_handler = __gnat_error_handler;
1137 act.sa_flags = SA_NODEFER + SA_RESTART;
1138 sigfillset (&act.sa_mask);
1139 sigemptyset (&act.sa_mask);
1141 /* Do not install handlers if interrupt state is "System" */
1142 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1143 sigaction (SIGABRT, &act, NULL);
1144 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1145 sigaction (SIGFPE, &act, NULL);
1146 if (__gnat_get_interrupt_state (SIGILL) != 's')
1147 sigaction (SIGILL, &act, NULL);
1148 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1149 sigaction (SIGSEGV, &act, NULL);
1150 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1151 sigaction (SIGBUS, &act, NULL);
1152 if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
1153 sigaction (SIGADAABORT, &act, NULL);
1155 __gnat_handler_installed = 1;
1158 void
1159 __gnat_initialize (void)
1163 /*************************************************/
1164 /* __gnat_initialize (Solaris and SunOS Version) */
1165 /*************************************************/
1167 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
1169 #include <signal.h>
1170 #include <siginfo.h>
1172 static void __gnat_error_handler (int, siginfo_t *);
1174 static void
1175 __gnat_error_handler (int sig, siginfo_t *sip)
1177 struct Exception_Data *exception;
1178 static int recurse = 0;
1179 const char *msg;
1181 /* If this was an explicit signal from a "kill", just resignal it. */
1182 if (SI_FROMUSER (sip))
1184 signal (sig, SIG_DFL);
1185 kill (getpid(), sig);
1188 /* Otherwise, treat it as something we handle. */
1189 switch (sig)
1191 case SIGSEGV:
1192 /* If the problem was permissions, this is a constraint error.
1193 Likewise if the failing address isn't maximally aligned or if
1194 we've recursed.
1196 ??? Using a static variable here isn't task-safe, but it's
1197 much too hard to do anything else and we're just determining
1198 which exception to raise. */
1199 if (sip->si_code == SEGV_ACCERR
1200 || (((long) sip->si_addr) & 3) != 0
1201 || recurse)
1203 exception = &constraint_error;
1204 msg = "SIGSEGV";
1206 else
1208 /* See if the page before the faulting page is accessible. Do that
1209 by trying to access it. We'd like to simply try to access
1210 4096 + the faulting address, but it's not guaranteed to be
1211 the actual address, just to be on the same page. */
1212 recurse++;
1213 ((volatile char *)
1214 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1215 exception = &storage_error;
1216 msg = "stack overflow (or erroneous memory access)";
1218 break;
1220 case SIGBUS:
1221 exception = &program_error;
1222 msg = "SIGBUS";
1223 break;
1225 case SIGFPE:
1226 exception = &constraint_error;
1227 msg = "SIGFPE";
1228 break;
1230 default:
1231 exception = &program_error;
1232 msg = "unhandled signal";
1235 recurse = 0;
1237 Raise_From_Signal_Handler (exception, msg);
1240 void
1241 __gnat_install_handler (void)
1243 struct sigaction act;
1245 /* Set up signal handler to map synchronous signals to appropriate
1246 exceptions. Make sure that the handler isn't interrupted by another
1247 signal that might cause a scheduling event! */
1249 act.sa_handler = __gnat_error_handler;
1250 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1251 sigemptyset (&act.sa_mask);
1253 /* Do not install handlers if interrupt state is "System" */
1254 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1255 sigaction (SIGABRT, &act, NULL);
1256 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1257 sigaction (SIGFPE, &act, NULL);
1258 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1259 sigaction (SIGSEGV, &act, NULL);
1260 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1261 sigaction (SIGBUS, &act, NULL);
1263 __gnat_handler_installed = 1;
1266 void
1267 __gnat_initialize (void)
1271 /***********************************/
1272 /* __gnat_initialize (VMS Version) */
1273 /***********************************/
1275 #elif defined (VMS)
1277 /* The prehandler actually gets control first on a condition. It swaps the
1278 stack pointer and calls the handler (__gnat_error_handler). */
1279 extern long __gnat_error_prehandler (void);
1281 extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
1283 /* Conditions that don't have an Ada exception counterpart must raise
1284 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1285 referenced by user programs, not the compiler or tools. Hence the
1286 #ifdef IN_RTS. */
1288 #ifdef IN_RTS
1289 #define Non_Ada_Error system__aux_dec__non_ada_error
1290 extern struct Exception_Data Non_Ada_Error;
1292 #define Coded_Exception system__vms_exception_table__coded_exception
1293 extern struct Exception_Data *Coded_Exception (int);
1294 #endif
1296 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1297 Most of these are also defined in the header file ssdef.h which has not
1298 yet been converted to be recoginized by Gnu C. Some, which couldn't be
1299 located, are assigned names based on the DEC test suite tests which
1300 raise them. */
1302 #define SS$_ACCVIO 12
1303 #define SS$_DEBUG 1132
1304 #define SS$_INTDIV 1156
1305 #define SS$_HPARITH 1284
1306 #define SS$_STKOVF 1364
1307 #define SS$_RESIGNAL 2328
1308 #define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
1309 #define SS$_CE24VRU 3253636 /* Write to unopened file */
1310 #define SS$_C980VTE 3246436 /* AST requests time slice */
1311 #define CMA$_EXIT_THREAD 4227492
1312 #define CMA$_EXCCOPLOS 4228108
1313 #define CMA$_ALERTED 4227460
1315 struct descriptor_s {unsigned short len, mbz; char *adr; };
1317 long __gnat_error_handler (int *, void *);
1319 long
1320 __gnat_error_handler (int *sigargs, void *mechargs)
1322 struct Exception_Data *exception = 0;
1323 char *msg = "";
1324 char message[256];
1325 long prvhnd;
1326 struct descriptor_s msgdesc;
1327 int msg_flag = 0x000f; /* 1 bit for each of the four message parts */
1328 unsigned short outlen;
1329 char curr_icb[544];
1330 long curr_invo_handle;
1331 long *mstate;
1333 /* Resignaled condtions aren't effected by by pragma Import_Exception */
1335 switch (sigargs[1])
1338 case CMA$_EXIT_THREAD:
1339 return SS$_RESIGNAL;
1341 case SS$_DEBUG: /* Gdb attach, resignal to merge activate gdbstub. */
1342 return SS$_RESIGNAL;
1344 case 1409786: /* Nickerson bug #33 ??? */
1345 return SS$_RESIGNAL;
1347 case 1381050: /* Nickerson bug #33 ??? */
1348 return SS$_RESIGNAL;
1350 case 11829410: /* Resignalled as Use_Error for CE10VRC */
1351 return SS$_RESIGNAL;
1355 #ifdef IN_RTS
1356 /* See if it's an imported exception. Mask off severity bits. */
1357 exception = Coded_Exception (sigargs[1] & 0xfffffff8);
1358 if (exception)
1360 msgdesc.len = 256;
1361 msgdesc.mbz = 0;
1362 msgdesc.adr = message;
1363 SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1364 message[outlen] = 0;
1365 msg = message;
1367 exception->Name_Length = 19;
1368 /* The full name really should be get sys$getmsg returns. ??? */
1369 exception->Full_Name = "IMPORTED_EXCEPTION";
1370 exception->Import_Code = sigargs[1] & 0xfffffff8;
1372 #endif
1374 if (exception == 0)
1375 switch (sigargs[1])
1377 case SS$_ACCVIO:
1378 if (sigargs[3] == 0)
1380 exception = &constraint_error;
1381 msg = "access zero";
1383 else
1385 exception = &storage_error;
1386 msg = "stack overflow (or erroneous memory access)";
1388 break;
1390 case SS$_STKOVF:
1391 exception = &storage_error;
1392 msg = "stack overflow";
1393 break;
1395 case SS$_INTDIV:
1396 exception = &constraint_error;
1397 msg = "division by zero";
1398 break;
1400 case SS$_HPARITH:
1401 #ifndef IN_RTS
1402 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1403 #else
1405 exception = &constraint_error;
1406 msg = "arithmetic error";
1408 #endif
1409 break;
1411 case MTH$_FLOOVEMAT:
1412 exception = &constraint_error;
1413 msg = "floating overflow in math library";
1414 break;
1416 case SS$_CE24VRU:
1417 exception = &constraint_error;
1418 msg = "";
1419 break;
1421 case SS$_C980VTE:
1422 exception = &program_error;
1423 msg = "";
1424 break;
1426 default:
1427 #ifndef IN_RTS
1428 exception = &program_error;
1429 #else
1430 /* User programs expect Non_Ada_Error to be raised, reference
1431 DEC Ada test CXCONDHAN. */
1432 exception = &Non_Ada_Error;
1433 #endif
1434 msgdesc.len = 256;
1435 msgdesc.mbz = 0;
1436 msgdesc.adr = message;
1437 SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1438 message[outlen] = 0;
1439 msg = message;
1440 break;
1443 mstate = (long *) (*Get_Machine_State_Addr) ();
1444 if (mstate != 0)
1446 LIB$GET_CURR_INVO_CONTEXT (&curr_icb);
1447 LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
1448 LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
1449 curr_invo_handle = LIB$GET_INVO_HANDLE (&curr_icb);
1450 *mstate = curr_invo_handle;
1452 Raise_From_Signal_Handler (exception, msg);
1455 void
1456 __gnat_install_handler (void)
1458 long prvhnd;
1459 char *c;
1461 c = (char *) xmalloc (2049);
1463 __gnat_error_prehandler_stack = &c[2048];
1465 /* __gnat_error_prehandler is an assembly function. */
1466 SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1467 __gnat_handler_installed = 1;
1470 void
1471 __gnat_initialize(void)
1475 /*************************************************/
1476 /* __gnat_initialize (FreeBSD version) */
1477 /*************************************************/
1479 #elif defined (__FreeBSD__)
1481 #include <signal.h>
1482 #include <unistd.h>
1484 static void
1485 __gnat_error_handler (sig, code, sc)
1486 int sig;
1487 int code;
1488 struct sigcontext *sc;
1490 struct Exception_Data *exception;
1491 char *msg;
1493 switch (sig)
1495 case SIGFPE:
1496 exception = &constraint_error;
1497 msg = "SIGFPE";
1498 break;
1500 case SIGILL:
1501 exception = &constraint_error;
1502 msg = "SIGILL";
1503 break;
1505 case SIGSEGV:
1506 exception = &storage_error;
1507 msg = "stack overflow or erroneous memory access";
1508 break;
1510 case SIGBUS:
1511 exception = &constraint_error;
1512 msg = "SIGBUS";
1513 break;
1515 default:
1516 exception = &program_error;
1517 msg = "unhandled signal";
1520 Raise_From_Signal_Handler (exception, msg);
1523 void
1524 __gnat_install_handler ()
1526 struct sigaction act;
1528 /* Set up signal handler to map synchronous signals to appropriate
1529 exceptions. Make sure that the handler isn't interrupted by another
1530 signal that might cause a scheduling event! */
1532 act.sa_handler = __gnat_error_handler;
1533 act.sa_flags = SA_NODEFER | SA_RESTART;
1534 (void) sigemptyset (&act.sa_mask);
1536 (void) sigaction (SIGILL, &act, NULL);
1537 (void) sigaction (SIGFPE, &act, NULL);
1538 (void) sigaction (SIGSEGV, &act, NULL);
1539 (void) sigaction (SIGBUS, &act, NULL);
1542 void __gnat_init_float ();
1544 void
1545 __gnat_initialize ()
1547 __gnat_install_handler ();
1549 /* XXX - Initialize floating-point coprocessor. This call is
1550 needed because FreeBSD defaults to 64-bit precision instead
1551 of 80-bit precision? We require the full precision for
1552 proper operation, given that we have set Max_Digits etc
1553 with this in mind */
1554 __gnat_init_float ();
1557 /***************************************/
1558 /* __gnat_initialize (VXWorks Version) */
1559 /***************************************/
1561 #elif defined(__vxworks)
1563 #include <signal.h>
1564 #include <taskLib.h>
1565 #include <intLib.h>
1566 #include <iv.h>
1568 extern int __gnat_inum_to_ivec (int);
1569 static void __gnat_error_handler (int, int, struct sigcontext *);
1570 void __gnat_map_signal (int);
1572 #ifndef __alpha_vxworks
1574 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1575 on Alpha VxWorks */
1577 extern long getpid (void);
1579 long
1580 getpid (void)
1582 return taskIdSelf ();
1584 #endif
1586 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1588 __gnat_inum_to_ivec (int num)
1590 return INUM_TO_IVEC (num);
1593 /* Exported to 5zintman.adb in order to handle different signal
1594 to exception mappings in different VxWorks versions */
1595 void
1596 __gnat_map_signal (int sig)
1598 struct Exception_Data *exception;
1599 char *msg;
1601 switch (sig)
1603 case SIGFPE:
1604 exception = &constraint_error;
1605 msg = "SIGFPE";
1606 break;
1607 case SIGILL:
1608 exception = &constraint_error;
1609 msg = "SIGILL";
1610 break;
1611 case SIGSEGV:
1612 exception = &program_error;
1613 msg = "SIGSEGV";
1614 break;
1615 case SIGBUS:
1616 #ifdef VTHREADS
1617 exception = &storage_error;
1618 msg = "SIGBUS: possible stack overflow";
1619 #else
1620 exception = &program_error;
1621 msg = "SIGBUS";
1622 #endif
1623 break;
1624 default:
1625 exception = &program_error;
1626 msg = "unhandled signal";
1629 Raise_From_Signal_Handler (exception, msg);
1632 static void
1633 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1635 sigset_t mask;
1636 int result;
1638 /* VxWorks will always mask out the signal during the signal handler and
1639 will reenable it on a longjmp. GNAT does not generate a longjmp to
1640 return from a signal handler so the signal will still be masked unless
1641 we unmask it. */
1642 sigprocmask (SIG_SETMASK, NULL, &mask);
1643 sigdelset (&mask, sig);
1644 sigprocmask (SIG_SETMASK, &mask, NULL);
1646 /* VxWorks will suspend the task when it gets a hardware exception. We
1647 take the liberty of resuming the task for the application. */
1648 if (taskIsSuspended (taskIdSelf ()) != 0)
1649 taskResume (taskIdSelf ());
1651 __gnat_map_signal (sig);
1655 void
1656 __gnat_install_handler (void)
1658 struct sigaction act;
1660 /* Setup signal handler to map synchronous signals to appropriate
1661 exceptions. Make sure that the handler isn't interrupted by another
1662 signal that might cause a scheduling event! */
1664 act.sa_handler = __gnat_error_handler;
1665 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1666 sigemptyset (&act.sa_mask);
1668 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1669 applies to vectored hardware interrupts, not signals */
1670 sigaction (SIGFPE, &act, NULL);
1671 sigaction (SIGILL, &act, NULL);
1672 sigaction (SIGSEGV, &act, NULL);
1673 sigaction (SIGBUS, &act, NULL);
1675 __gnat_handler_installed = 1;
1678 #define HAVE_GNAT_INIT_FLOAT
1680 void
1681 __gnat_init_float (void)
1683 /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1684 to get correct Ada semantic. */
1685 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT)
1686 asm ("mtfsb0 25");
1687 asm ("mtfsb0 26");
1688 #endif
1690 /* Similarily for sparc64. Achieved by masking bits in the Trap Enable Mask
1691 field of the Floating-point Status Register (see the Sparc Architecture
1692 Manual Version 9, p 48). */
1693 #if defined (sparc64)
1695 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1696 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1697 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1698 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1699 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1701 unsigned int fsr;
1703 __asm__("st %%fsr, %0" : "=m" (fsr));
1704 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1705 __asm__("ld %0, %%fsr" : : "m" (fsr));
1707 #endif
1710 void
1711 __gnat_initialize (void)
1713 __gnat_init_float ();
1715 /* Assume an environment task stack size of 20kB.
1717 Using a constant is necessary because we do not want each Ada application
1718 to depend on the optional taskShow library,
1719 which is required to get the actual stack information.
1721 The consequence of this is that with -fstack-check
1722 the environment task must have an actual stack size
1723 of at least 20kB and the usable size will be about 14kB.
1726 __gnat_set_stack_size (14336);
1727 /* Allow some head room for the stack checking code, and for
1728 stack space consumed during initialization */
1731 /********************************/
1732 /* __gnat_initialize for NetBSD */
1733 /********************************/
1735 #elif defined(__NetBSD__)
1737 #include <signal.h>
1738 #include <unistd.h>
1740 static void
1741 __gnat_error_handler (int sig)
1743 struct Exception_Data *exception;
1744 const char *msg;
1746 switch(sig)
1748 case SIGFPE:
1749 exception = &constraint_error;
1750 msg = "SIGFPE";
1751 break;
1752 case SIGILL:
1753 exception = &constraint_error;
1754 msg = "SIGILL";
1755 break;
1756 case SIGSEGV:
1757 exception = &storage_error;
1758 msg = "stack overflow or erroneous memory access";
1759 break;
1760 case SIGBUS:
1761 exception = &constraint_error;
1762 msg = "SIGBUS";
1763 break;
1764 default:
1765 exception = &program_error;
1766 msg = "unhandled signal";
1769 Raise_From_Signal_Handler(exception, msg);
1772 void
1773 __gnat_install_handler(void)
1775 struct sigaction act;
1777 act.sa_handler = __gnat_error_handler;
1778 act.sa_flags = SA_NODEFER | SA_RESTART;
1779 sigemptyset (&act.sa_mask);
1781 /* Do not install handlers if interrupt state is "System" */
1782 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1783 sigaction (SIGFPE, &act, NULL);
1784 if (__gnat_get_interrupt_state (SIGILL) != 's')
1785 sigaction (SIGILL, &act, NULL);
1786 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1787 sigaction (SIGSEGV, &act, NULL);
1788 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1789 sigaction (SIGBUS, &act, NULL);
1791 __gnat_handler_installed = 1;
1794 void
1795 __gnat_initialize (void)
1797 __gnat_install_handler ();
1798 __gnat_init_float ();
1801 #else
1803 /* For all other versions of GNAT, the initialize routine and handler
1804 installation do nothing */
1806 /***************************************/
1807 /* __gnat_initialize (Default Version) */
1808 /***************************************/
1810 void
1811 __gnat_initialize (void)
1815 /********************************************/
1816 /* __gnat_install_handler (Default Version) */
1817 /********************************************/
1819 void
1820 __gnat_install_handler (void)
1822 __gnat_handler_installed = 1;
1825 #endif
1827 /*********************/
1828 /* __gnat_init_float */
1829 /*********************/
1831 /* This routine is called as each process thread is created, for possible
1832 initialization of the FP processor. This version is used under INTERIX,
1833 WIN32 and could be used under OS/2 */
1835 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1836 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1838 #define HAVE_GNAT_INIT_FLOAT
1840 void
1841 __gnat_init_float (void)
1843 #if defined (__i386__) || defined (i386)
1845 /* This is used to properly initialize the FPU on an x86 for each
1846 process thread. */
1848 asm ("finit");
1850 #endif /* Defined __i386__ */
1852 #endif
1854 #ifndef HAVE_GNAT_INIT_FLOAT
1856 /* All targets without a specific __gnat_init_float will use an empty one */
1857 void
1858 __gnat_init_float (void)
1861 #endif