1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2003 Free Software Foundation, Inc. *
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. *
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. *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
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. */
53 /* We don't have libiberty, so us malloc. */
54 #define xmalloc(S) malloc (S)
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) PARAMS ((void));
76 #define Unlock_Task system__soft_links__unlock_task
77 extern void (*Unlock_Task) PARAMS ((void));
79 #define Get_Machine_State_Addr \
80 system__soft_links__get_machine_state_addr
81 extern struct Machine_State *(*Get_Machine_State_Addr) PARAMS ((void));
83 #define Check_Abort_Status \
84 system__soft_links__check_abort_status
85 extern int (*Check_Abort_Status) PARAMS ((void));
87 #define Raise_From_Signal_Handler \
88 ada__exceptions__raise_from_signal_handler
89 extern void Raise_From_Signal_Handler PARAMS ((struct Exception_Data *,
92 #define Propagate_Signal_Exception \
93 __gnat_propagate_sig_exc
94 extern void Propagate_Signal_Exception
95 PARAMS ((struct Machine_State *, struct Exception_Data *, 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 */
137 __gnat_get_interrupt_state (intrup)
140 if (intrup >= __gl_num_interrupt_states)
143 return __gl_interrupt_states [intrup];
146 /**********************/
147 /* __gnat_set_globals */
148 /**********************/
150 /* This routine is called from the binder generated main program. It copies
151 the values for global quantities computed by the binder into the following
152 global locations. The reason that we go through this copy, rather than just
153 define the global locations in the binder generated file, is that they are
154 referenced from the runtime, which may be in a shared library, and the
155 binder file is not in the shared library. Global references across library
156 boundaries like this are not handled correctly in all systems. */
159 __gnat_set_globals (main_priority,
164 task_dispatching_policy,
167 num_interrupt_states,
168 unreserve_all_interrupts,
169 exception_tracebacks,
170 zero_cost_exceptions)
176 char task_dispatching_policy;
178 char *interrupt_states;
179 int num_interrupt_states;
180 int unreserve_all_interrupts;
181 int exception_tracebacks;
182 int zero_cost_exceptions;
184 static int already_called = 0;
186 /* If this procedure has been already called once, check that the
187 arguments in this call are consistent with the ones in the previous
188 calls. Otherwise, raise a Program_Error exception.
190 We do not check for consistency of the wide character encoding
191 method. This default affects only Wide_Text_IO where no explicit
192 coding method is given, and there is no particular reason to let
193 this default be affected by the source representation of a library
196 We do not check either for the consistency of exception tracebacks,
197 because exception tracebacks are not normally set in Stand-Alone
198 libraries. If a library or the main program set the exception
199 tracebacks, then they are never reset afterwards (see below).
201 The value of main_priority is meaningful only when we are invoked
202 from the main program elaboration routine of an Ada application.
203 Checking the consistency of this parameter should therefore not be
204 done. Since it is assured that the main program elaboration will
205 always invoke this procedure before any library elaboration
206 routine, only the value of main_priority during the first call
207 should be taken into account and all the subsequent ones should be
208 ignored. Note that the case where the main program is not written
209 in Ada is also properly handled, since the default value will then
210 be used for this parameter.
212 For identical reasons, the consistency of time_slice_val should not
217 if (__gl_locking_policy != locking_policy
218 || __gl_queuing_policy != queuing_policy
219 || __gl_task_dispatching_policy != task_dispatching_policy
220 || __gl_unreserve_all_interrupts != unreserve_all_interrupts
221 || __gl_zero_cost_exceptions != zero_cost_exceptions)
222 __gnat_raise_program_error (__FILE__, __LINE__);
224 /* If either a library or the main program set the exception traceback
225 flag, it is never reset later */
227 if (exception_tracebacks != 0)
228 __gl_exception_tracebacks = exception_tracebacks;
234 __gl_main_priority = main_priority;
235 __gl_time_slice_val = time_slice_val;
236 __gl_wc_encoding = wc_encoding;
237 __gl_locking_policy = locking_policy;
238 __gl_queuing_policy = queuing_policy;
239 __gl_restrictions = restrictions;
240 __gl_interrupt_states = interrupt_states;
241 __gl_num_interrupt_states = num_interrupt_states;
242 __gl_task_dispatching_policy = task_dispatching_policy;
243 __gl_unreserve_all_interrupts = unreserve_all_interrupts;
244 __gl_exception_tracebacks = exception_tracebacks;
246 /* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
247 a-except.adb, which is also part of the compiler sources. Since the
248 compiler is built with an older release of GNAT, the call generated by
249 the old binder to this function does not provide any value for the
250 corresponding argument, so the global has to be initialized in some
251 reasonable other way. This could be removed as soon as the next major
255 __gl_zero_cost_exceptions = zero_cost_exceptions;
257 __gl_zero_cost_exceptions = 0;
258 /* We never build the compiler to run in ZCX mode currently anyway. */
262 /*********************/
263 /* __gnat_initialize */
264 /*********************/
266 /* __gnat_initialize is called at the start of execution of an Ada program
267 (the call is generated by the binder). The standard routine does nothing
268 at all; the intention is that this be replaced by system specific
269 code where initialization is required. */
271 /***********************************/
272 /* __gnat_initialize (AIX Version) */
273 /***********************************/
278 #include <sys/time.h>
280 /* Some versions of AIX don't define SA_NODEFER. */
284 #endif /* SA_NODEFER */
286 /* Versions of AIX before 4.3 don't have nanosleep but provide
289 #ifndef _AIXVERSION_430
291 extern int nanosleep PARAMS ((struct timestruc_t *, struct timestruc_t *));
294 nanosleep (Rqtp, Rmtp)
295 struct timestruc_t *Rqtp, *Rmtp;
297 return nsleep (Rqtp, Rmtp);
300 #endif /* _AIXVERSION_430 */
302 static void __gnat_error_handler PARAMS ((int));
305 __gnat_error_handler (sig)
308 struct Exception_Data *exception;
314 /* FIXME: we need to detect the case of a *real* SIGSEGV */
315 exception = &storage_error;
316 msg = "stack overflow or erroneous memory access";
320 exception = &constraint_error;
325 exception = &constraint_error;
330 exception = &program_error;
331 msg = "unhandled signal";
334 Raise_From_Signal_Handler (exception, msg);
338 __gnat_install_handler ()
340 struct sigaction act;
342 /* Set up signal handler to map synchronous signals to appropriate
343 exceptions. Make sure that the handler isn't interrupted by another
344 signal that might cause a scheduling event! */
346 act.sa_handler = __gnat_error_handler;
347 act.sa_flags = SA_NODEFER | SA_RESTART;
348 sigemptyset (&act.sa_mask);
350 /* Do not install handlers if interrupt state is "System" */
351 if (__gnat_get_interrupt_state (SIGABRT) != 's')
352 sigaction (SIGABRT, &act, NULL);
353 if (__gnat_get_interrupt_state (SIGFPE) != 's')
354 sigaction (SIGFPE, &act, NULL);
355 if (__gnat_get_interrupt_state (SIGILL) != 's')
356 sigaction (SIGILL, &act, NULL);
357 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
358 sigaction (SIGSEGV, &act, NULL);
359 if (__gnat_get_interrupt_state (SIGBUS) != 's')
360 sigaction (SIGBUS, &act, NULL);
362 __gnat_handler_installed = 1;
370 /****************************************/
371 /* __gnat_initialize (Dec Unix Version) */
372 /****************************************/
374 #elif defined(__alpha__) && defined(__osf__) && ! defined(__alpha_vxworks)
376 /* Note: it seems that __osf__ is defined for the Alpha VXWorks case. Not
377 clear that this is reasonable, but in any case we have to be sure to
378 exclude this case in the above test. */
381 #include <sys/siginfo.h>
383 static void __gnat_error_handler PARAMS ((int, siginfo_t *,
384 struct sigcontext *));
385 extern char *__gnat_get_code_loc PARAMS ((struct sigcontext *));
386 extern void __gnat_enter_handler PARAMS ((struct sigcontext *, char *));
387 extern size_t __gnat_machine_state_length PARAMS ((void));
389 extern long exc_lookup_gp PARAMS ((char *));
390 extern void exc_resume PARAMS ((struct sigcontext *));
393 __gnat_error_handler (sig, sip, context)
396 struct sigcontext *context;
398 struct Exception_Data *exception;
399 static int recurse = 0;
400 struct sigcontext *mstate;
403 /* If this was an explicit signal from a "kill", just resignal it. */
404 if (SI_FROMUSER (sip))
406 signal (sig, SIG_DFL);
407 kill (getpid(), sig);
410 /* Otherwise, treat it as something we handle. */
414 /* If the problem was permissions, this is a constraint error.
415 Likewise if the failing address isn't maximally aligned or if
418 ??? Using a static variable here isn't task-safe, but it's
419 much too hard to do anything else and we're just determining
420 which exception to raise. */
421 if (sip->si_code == SEGV_ACCERR
422 || (((long) sip->si_addr) & 3) != 0
425 exception = &constraint_error;
430 /* See if the page before the faulting page is accessible. Do that
431 by trying to access it. We'd like to simply try to access
432 4096 + the faulting address, but it's not guaranteed to be
433 the actual address, just to be on the same page. */
436 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
437 msg = "stack overflow (or erroneous memory access)";
438 exception = &storage_error;
443 exception = &program_error;
448 exception = &constraint_error;
453 exception = &program_error;
454 msg = "unhandled signal";
458 mstate = (struct sigcontext *) (*Get_Machine_State_Addr) ();
462 Raise_From_Signal_Handler (exception, (char *) msg);
466 __gnat_install_handler ()
468 struct sigaction act;
470 /* Setup signal handler to map synchronous signals to appropriate
471 exceptions. Make sure that the handler isn't interrupted by another
472 signal that might cause a scheduling event! */
474 act.sa_handler = (void (*) PARAMS ((int))) __gnat_error_handler;
475 act.sa_flags = SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_SIGINFO;
476 sigemptyset (&act.sa_mask);
478 /* Do not install handlers if interrupt state is "System" */
479 if (__gnat_get_interrupt_state (SIGABRT) != 's')
480 sigaction (SIGABRT, &act, NULL);
481 if (__gnat_get_interrupt_state (SIGFPE) != 's')
482 sigaction (SIGFPE, &act, NULL);
483 if (__gnat_get_interrupt_state (SIGILL) != 's')
484 sigaction (SIGILL, &act, NULL);
485 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
486 sigaction (SIGSEGV, &act, NULL);
487 if (__gnat_get_interrupt_state (SIGBUS) != 's')
488 sigaction (SIGBUS, &act, NULL);
490 __gnat_handler_installed = 1;
498 /* Routines called by 5amastop.adb. */
503 __gnat_get_code_loc (context)
504 struct sigcontext *context;
506 return (char *) context->sc_pc;
510 __gnat_enter_handler (context, pc)
511 struct sigcontext *context;
514 context->sc_pc = (long) pc;
515 context->sc_regs[SC_GP] = exc_lookup_gp (pc);
516 exc_resume (context);
520 __gnat_machine_state_length ()
522 return sizeof (struct sigcontext);
525 /************************************/
526 /* __gnat_initialize (HPUX Version) */
527 /************************************/
533 static void __gnat_error_handler PARAMS ((int));
536 __gnat_error_handler (sig)
539 struct Exception_Data *exception;
545 /* FIXME: we need to detect the case of a *real* SIGSEGV */
546 exception = &storage_error;
547 msg = "stack overflow or erroneous memory access";
551 exception = &constraint_error;
556 exception = &constraint_error;
561 exception = &program_error;
562 msg = "unhandled signal";
565 Raise_From_Signal_Handler (exception, msg);
569 __gnat_install_handler ()
571 struct sigaction act;
573 /* Set up signal handler to map synchronous signals to appropriate
574 exceptions. Make sure that the handler isn't interrupted by another
575 signal that might cause a scheduling event! Also setup an alternate
576 stack region for the handler execution so that stack overflows can be
577 handled properly, avoiding a SEGV generation from stack usage by the
580 static char handler_stack[SIGSTKSZ*2];
581 /* SIGSTKSZ appeared to be "short" for the needs in some contexts
582 (e.g. experiments with GCC ZCX exceptions). */
586 stack.ss_sp = handler_stack;
587 stack.ss_size = sizeof (handler_stack);
590 sigaltstack (&stack, NULL);
592 act.sa_handler = __gnat_error_handler;
593 act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK;
594 sigemptyset (&act.sa_mask);
596 /* Do not install handlers if interrupt state is "System" */
597 if (__gnat_get_interrupt_state (SIGABRT) != 's')
598 sigaction (SIGABRT, &act, NULL);
599 if (__gnat_get_interrupt_state (SIGFPE) != 's')
600 sigaction (SIGFPE, &act, NULL);
601 if (__gnat_get_interrupt_state (SIGILL) != 's')
602 sigaction (SIGILL, &act, NULL);
603 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
604 sigaction (SIGSEGV, &act, NULL);
605 if (__gnat_get_interrupt_state (SIGBUS) != 's')
606 sigaction (SIGBUS, &act, NULL);
608 __gnat_handler_installed = 1;
616 /*****************************************/
617 /* __gnat_initialize (GNU/Linux Version) */
618 /*****************************************/
620 #elif defined (linux) && defined (i386) && !defined (__RT__)
623 #include <asm/sigcontext.h>
625 /* GNU/Linux, which uses glibc, does not define NULL in included
629 #define NULL ((void *) 0)
642 static void __gnat_error_handler PARAMS ((int));
645 __gnat_error_handler (sig)
648 struct Exception_Data *exception;
650 static int recurse = 0;
652 struct sigcontext *info
653 = (struct sigcontext *) (((char *) &sig) + sizeof (int));
655 /* The Linux kernel does not document how to get the machine state in a
656 signal handler, but in fact the necessary data is in a sigcontext_struct
657 value that is on the stack immediately above the signal number
658 parameter, and the above messing accesses this value on the stack. */
660 struct Machine_State *mstate;
665 /* If the problem was permissions, this is a constraint error.
666 Likewise if the failing address isn't maximally aligned or if
669 ??? Using a static variable here isn't task-safe, but it's
670 much too hard to do anything else and we're just determining
671 which exception to raise. */
674 exception = &constraint_error;
679 /* Here we would like a discrimination test to see whether the
680 page before the faulting address is accessible. Unfortunately
681 Linux seems to have no way of giving us the faulting address.
683 In versions of a-init.c before 1.95, we had a test of the page
684 before the stack pointer using:
688 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
690 but that's wrong, since it tests the stack pointer location, and
691 the current stack probe code does not move the stack pointer
692 until all probes succeed.
694 For now we simply do not attempt any discrimination at all. Note
695 that this is quite acceptable, since a "real" SIGSEGV can only
696 occur as the result of an erroneous program */
698 msg = "stack overflow (or erroneous memory access)";
699 exception = &storage_error;
704 exception = &constraint_error;
709 exception = &constraint_error;
714 exception = &program_error;
715 msg = "unhandled signal";
718 mstate = (*Get_Machine_State_Addr)();
721 mstate->eip = info->eip;
722 mstate->ebx = info->ebx;
723 mstate->esp = info->esp_at_signal;
724 mstate->ebp = info->ebp;
725 mstate->esi = info->esi;
726 mstate->edi = info->edi;
730 Raise_From_Signal_Handler (exception, msg);
734 __gnat_install_handler ()
736 struct sigaction act;
738 /* Set up signal handler to map synchronous signals to appropriate
739 exceptions. Make sure that the handler isn't interrupted by another
740 signal that might cause a scheduling event! */
742 act.sa_handler = __gnat_error_handler;
743 act.sa_flags = SA_NODEFER | SA_RESTART;
744 sigemptyset (&act.sa_mask);
746 /* Do not install handlers if interrupt state is "System" */
747 if (__gnat_get_interrupt_state (SIGABRT) != 's')
748 sigaction (SIGABRT, &act, NULL);
749 if (__gnat_get_interrupt_state (SIGFPE) != 's')
750 sigaction (SIGFPE, &act, NULL);
751 if (__gnat_get_interrupt_state (SIGILL) != 's')
752 sigaction (SIGILL, &act, NULL);
753 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
754 sigaction (SIGSEGV, &act, NULL);
755 if (__gnat_get_interrupt_state (SIGBUS) != 's')
756 sigaction (SIGBUS, &act, NULL);
758 __gnat_handler_installed = 1;
766 /******************************************/
767 /* __gnat_initialize (NT-mingw32 Version) */
768 /******************************************/
770 #elif defined (__MINGW32__)
773 static LONG WINAPI __gnat_error_handler PARAMS ((PEXCEPTION_POINTERS));
775 /* __gnat_initialize (mingw32). */
778 __gnat_error_handler (info)
779 PEXCEPTION_POINTERS info;
782 struct Exception_Data *exception;
785 switch (info->ExceptionRecord->ExceptionCode)
787 case EXCEPTION_ACCESS_VIOLATION:
788 /* If the failing address isn't maximally-aligned or if we've
789 recursed, this is a program error. */
790 if ((info->ExceptionRecord->ExceptionInformation[1] & 3) != 0
793 exception = &program_error;
794 msg = "EXCEPTION_ACCESS_VIOLATION";
798 /* See if the page before the faulting page is accessible. Do that
799 by trying to access it. */
801 * ((volatile char *) (info->ExceptionRecord->ExceptionInformation[1]
803 exception = &storage_error;
804 msg = "stack overflow (or erroneous memory access)";
808 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
809 exception = &constraint_error;
810 msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
813 case EXCEPTION_DATATYPE_MISALIGNMENT:
814 exception = &constraint_error;
815 msg = "EXCEPTION_DATATYPE_MISALIGNMENT";
818 case EXCEPTION_FLT_DENORMAL_OPERAND:
819 exception = &constraint_error;
820 msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
823 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
824 exception = &constraint_error;
825 msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
828 case EXCEPTION_FLT_INVALID_OPERATION:
829 exception = &constraint_error;
830 msg = "EXCEPTION_FLT_INVALID_OPERATION";
833 case EXCEPTION_FLT_OVERFLOW:
834 exception = &constraint_error;
835 msg = "EXCEPTION_FLT_OVERFLOW";
838 case EXCEPTION_FLT_STACK_CHECK:
839 exception = &program_error;
840 msg = "EXCEPTION_FLT_STACK_CHECK";
843 case EXCEPTION_FLT_UNDERFLOW:
844 exception = &constraint_error;
845 msg = "EXCEPTION_FLT_UNDERFLOW";
848 case EXCEPTION_INT_DIVIDE_BY_ZERO:
849 exception = &constraint_error;
850 msg = "EXCEPTION_INT_DIVIDE_BY_ZERO";
853 case EXCEPTION_INT_OVERFLOW:
854 exception = &constraint_error;
855 msg = "EXCEPTION_INT_OVERFLOW";
858 case EXCEPTION_INVALID_DISPOSITION:
859 exception = &program_error;
860 msg = "EXCEPTION_INVALID_DISPOSITION";
863 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
864 exception = &program_error;
865 msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
868 case EXCEPTION_PRIV_INSTRUCTION:
869 exception = &program_error;
870 msg = "EXCEPTION_PRIV_INSTRUCTION";
873 case EXCEPTION_SINGLE_STEP:
874 exception = &program_error;
875 msg = "EXCEPTION_SINGLE_STEP";
878 case EXCEPTION_STACK_OVERFLOW:
879 exception = &storage_error;
880 msg = "EXCEPTION_STACK_OVERFLOW";
884 exception = &program_error;
885 msg = "unhandled signal";
889 Raise_From_Signal_Handler (exception, msg);
890 return 0; /* This is never reached, avoid compiler warning */
894 __gnat_install_handler ()
896 SetUnhandledExceptionFilter (__gnat_error_handler);
897 __gnat_handler_installed = 1;
904 /* Initialize floating-point coprocessor. This call is needed because
905 the MS libraries default to 64-bit precision instead of 80-bit
906 precision, and we require the full precision for proper operation,
907 given that we have set Max_Digits etc with this in mind */
909 __gnat_init_float ();
911 /* initialize a lock for a process handle list - see a-adaint.c for the
912 implementation of __gnat_portable_no_block_spawn, __gnat_portable_wait */
916 /***************************************/
917 /* __gnat_initialize (Interix Version) */
918 /***************************************/
920 #elif defined (__INTERIX)
924 static void __gnat_error_handler PARAMS ((int));
927 __gnat_error_handler (sig)
930 struct Exception_Data *exception;
936 exception = &storage_error;
937 msg = "stack overflow or erroneous memory access";
941 exception = &constraint_error;
946 exception = &constraint_error;
951 exception = &program_error;
952 msg = "unhandled signal";
955 Raise_From_Signal_Handler (exception, msg);
959 __gnat_install_handler ()
961 struct sigaction act;
963 /* Set up signal handler to map synchronous signals to appropriate
964 exceptions. Make sure that the handler isn't interrupted by another
965 signal that might cause a scheduling event! */
967 act.sa_handler = __gnat_error_handler;
969 sigemptyset (&act.sa_mask);
971 /* Handlers for signals besides SIGSEGV cause c974013 to hang */
972 /* sigaction (SIGILL, &act, NULL); */
973 /* sigaction (SIGABRT, &act, NULL); */
974 /* sigaction (SIGFPE, &act, NULL); */
975 /* sigaction (SIGBUS, &act, NULL); */
977 /* Do not install handlers if interrupt state is "System" */
978 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
979 sigaction (SIGSEGV, &act, NULL);
981 __gnat_handler_installed = 1;
987 __gnat_init_float ();
990 /**************************************/
991 /* __gnat_initialize (LynxOS Version) */
992 /**************************************/
994 #elif defined (__Lynx__)
999 __gnat_init_float ();
1002 /*********************************/
1003 /* __gnat_install_handler (Lynx) */
1004 /*********************************/
1007 __gnat_install_handler ()
1009 __gnat_handler_installed = 1;
1012 /****************************/
1013 /* __gnat_initialize (OS/2) */
1014 /****************************/
1016 #elif defined (__EMX__) /* OS/2 dependent initialization */
1019 __gnat_initialize ()
1023 /*********************************/
1024 /* __gnat_install_handler (OS/2) */
1025 /*********************************/
1028 __gnat_install_handler ()
1030 __gnat_handler_installed = 1;
1033 /***********************************/
1034 /* __gnat_initialize (SGI Version) */
1035 /***********************************/
1040 #include <siginfo.h>
1046 #define SIGADAABORT 48
1047 #define SIGNAL_STACK_SIZE 4096
1048 #define SIGNAL_STACK_ALIGNMENT 64
1050 struct Machine_State
1052 sigcontext_t context;
1055 static void __gnat_error_handler PARAMS ((int, int, sigcontext_t *));
1058 __gnat_error_handler (sig, code, sc)
1063 struct Machine_State *mstate;
1064 struct Exception_Data *exception;
1072 exception = &program_error;
1073 msg = "SIGSEGV: (Invalid virtual address)";
1075 else if (code == ENXIO)
1077 exception = &program_error;
1078 msg = "SIGSEGV: (Read beyond mapped object)";
1080 else if (code == ENOSPC)
1082 exception = &program_error; /* ??? storage_error ??? */
1083 msg = "SIGSEGV: (Autogrow for file failed)";
1085 else if (code == EACCES)
1087 /* ??? Re-add smarts to further verify that we launched
1088 the stack into a guard page, not an attempt to
1089 write to .text or something */
1090 exception = &storage_error;
1091 msg = "SIGSEGV: (stack overflow or erroneous memory access)";
1095 /* Just in case the OS guys did it to us again. Sometimes
1096 they fail to document all of the valid codes that are
1097 passed to signal handlers, just in case someone depends
1098 on knowing all the codes */
1099 exception = &program_error;
1100 msg = "SIGSEGV: (Undocumented reason)";
1105 /* Map all bus errors to Program_Error. */
1106 exception = &program_error;
1111 /* Map all fpe errors to Constraint_Error. */
1112 exception = &constraint_error;
1117 if ((*Check_Abort_Status) ())
1119 exception = &_abort_signal;
1128 /* Everything else is a Program_Error. */
1129 exception = &program_error;
1130 msg = "unhandled signal";
1133 mstate = (*Get_Machine_State_Addr)();
1135 memcpy ((void *) mstate, (const void *) sc, sizeof (sigcontext_t));
1137 Raise_From_Signal_Handler (exception, msg);
1141 __gnat_install_handler ()
1143 struct sigaction act;
1145 /* Setup signal handler to map synchronous signals to appropriate
1146 exceptions. Make sure that the handler isn't interrupted by another
1147 signal that might cause a scheduling event! */
1149 act.sa_handler = __gnat_error_handler;
1150 act.sa_flags = SA_NODEFER + SA_RESTART;
1151 sigfillset (&act.sa_mask);
1152 sigemptyset (&act.sa_mask);
1154 /* Do not install handlers if interrupt state is "System" */
1155 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1156 sigaction (SIGABRT, &act, NULL);
1157 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1158 sigaction (SIGFPE, &act, NULL);
1159 if (__gnat_get_interrupt_state (SIGILL) != 's')
1160 sigaction (SIGILL, &act, NULL);
1161 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1162 sigaction (SIGSEGV, &act, NULL);
1163 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1164 sigaction (SIGBUS, &act, NULL);
1165 if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
1166 sigaction (SIGADAABORT, &act, NULL);
1168 __gnat_handler_installed = 1;
1172 __gnat_initialize ()
1176 /*************************************************/
1177 /* __gnat_initialize (Solaris and SunOS Version) */
1178 /*************************************************/
1180 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
1183 #include <siginfo.h>
1185 static void __gnat_error_handler PARAMS ((int, siginfo_t *));
1188 __gnat_error_handler (sig, sip)
1192 struct Exception_Data *exception;
1193 static int recurse = 0;
1196 /* If this was an explicit signal from a "kill", just resignal it. */
1197 if (SI_FROMUSER (sip))
1199 signal (sig, SIG_DFL);
1200 kill (getpid(), sig);
1203 /* Otherwise, treat it as something we handle. */
1207 /* If the problem was permissions, this is a constraint error.
1208 Likewise if the failing address isn't maximally aligned or if
1211 ??? Using a static variable here isn't task-safe, but it's
1212 much too hard to do anything else and we're just determining
1213 which exception to raise. */
1214 if (sip->si_code == SEGV_ACCERR
1215 || (((long) sip->si_addr) & 3) != 0
1218 exception = &constraint_error;
1223 /* See if the page before the faulting page is accessible. Do that
1224 by trying to access it. We'd like to simply try to access
1225 4096 + the faulting address, but it's not guaranteed to be
1226 the actual address, just to be on the same page. */
1229 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1230 exception = &storage_error;
1231 msg = "stack overflow (or erroneous memory access)";
1236 exception = &program_error;
1241 exception = &constraint_error;
1246 exception = &program_error;
1247 msg = "unhandled signal";
1252 Raise_From_Signal_Handler (exception, msg);
1256 __gnat_install_handler ()
1258 struct sigaction act;
1260 /* Set up signal handler to map synchronous signals to appropriate
1261 exceptions. Make sure that the handler isn't interrupted by another
1262 signal that might cause a scheduling event! */
1264 act.sa_handler = __gnat_error_handler;
1265 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1266 sigemptyset (&act.sa_mask);
1268 /* Do not install handlers if interrupt state is "System" */
1269 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1270 sigaction (SIGABRT, &act, NULL);
1271 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1272 sigaction (SIGFPE, &act, NULL);
1273 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1274 sigaction (SIGSEGV, &act, NULL);
1275 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1276 sigaction (SIGBUS, &act, NULL);
1278 __gnat_handler_installed = 1;
1282 __gnat_initialize ()
1286 /***********************************/
1287 /* __gnat_initialize (VMS Version) */
1288 /***********************************/
1292 /* The prehandler actually gets control first on a condition. It swaps the
1293 stack pointer and calls the handler (__gnat_error_handler). */
1294 extern long __gnat_error_prehandler ();
1296 extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
1298 /* Conditions that don't have an Ada exception counterpart must raise
1299 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1300 referenced by user programs, not the compiler or tools. Hence the
1304 #define Non_Ada_Error system__aux_dec__non_ada_error
1305 extern struct Exception_Data Non_Ada_Error;
1307 #define Coded_Exception system__vms_exception_table__coded_exception
1308 extern struct Exception_Data *Coded_Exception (int);
1311 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1312 Most of these are also defined in the header file ssdef.h which has not
1313 yet been converted to be recoginized by Gnu C. Some, which couldn't be
1314 located, are assigned names based on the DEC test suite tests which
1317 #define SS$_ACCVIO 12
1318 #define SS$_DEBUG 1132
1319 #define SS$_INTDIV 1156
1320 #define SS$_HPARITH 1284
1321 #define SS$_STKOVF 1364
1322 #define SS$_RESIGNAL 2328
1323 #define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
1324 #define SS$_CE24VRU 3253636 /* Write to unopened file */
1325 #define SS$_C980VTE 3246436 /* AST requests time slice */
1326 #define CMA$_EXIT_THREAD 4227492
1327 #define CMA$_EXCCOPLOS 4228108
1328 #define CMA$_ALERTED 4227460
1330 struct descriptor_s {unsigned short len, mbz; char *adr; };
1332 long __gnat_error_handler PARAMS ((int *, void *));
1335 __gnat_error_handler (sigargs, mechargs)
1339 struct Exception_Data *exception = 0;
1343 struct descriptor_s msgdesc;
1344 int msg_flag = 0x000f; /* 1 bit for each of the four message parts */
1345 unsigned short outlen;
1347 long curr_invo_handle;
1350 /* Resignaled condtions aren't effected by by pragma Import_Exception */
1355 case CMA$_EXIT_THREAD:
1356 return SS$_RESIGNAL;
1358 case SS$_DEBUG: /* Gdb attach, resignal to merge activate gdbstub. */
1359 return SS$_RESIGNAL;
1361 case 1409786: /* Nickerson bug #33 ??? */
1362 return SS$_RESIGNAL;
1364 case 1381050: /* Nickerson bug #33 ??? */
1365 return SS$_RESIGNAL;
1367 case 11829410: /* Resignalled as Use_Error for CE10VRC */
1368 return SS$_RESIGNAL;
1373 /* See if it's an imported exception. Mask off severity bits. */
1374 exception = Coded_Exception (sigargs[1] & 0xfffffff8);
1379 msgdesc.adr = message;
1380 SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1381 message[outlen] = 0;
1384 exception->Name_Length = 19;
1385 /* The full name really should be get sys$getmsg returns. ??? */
1386 exception->Full_Name = "IMPORTED_EXCEPTION";
1387 exception->Import_Code = sigargs[1] & 0xfffffff8;
1395 if (sigargs[3] == 0)
1397 exception = &constraint_error;
1398 msg = "access zero";
1402 exception = &storage_error;
1403 msg = "stack overflow (or erroneous memory access)";
1408 exception = &storage_error;
1409 msg = "stack overflow";
1413 exception = &constraint_error;
1414 msg = "division by zero";
1419 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1422 exception = &constraint_error;
1423 msg = "arithmetic error";
1428 case MTH$_FLOOVEMAT:
1429 exception = &constraint_error;
1430 msg = "floating overflow in math library";
1434 exception = &constraint_error;
1439 exception = &program_error;
1445 exception = &program_error;
1447 /* User programs expect Non_Ada_Error to be raised, reference
1448 DEC Ada test CXCONDHAN. */
1449 exception = &Non_Ada_Error;
1453 msgdesc.adr = message;
1454 SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1455 message[outlen] = 0;
1460 mstate = (long *) (*Get_Machine_State_Addr) ();
1463 LIB$GET_CURR_INVO_CONTEXT (&curr_icb);
1464 LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
1465 LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
1466 curr_invo_handle = LIB$GET_INVO_HANDLE (&curr_icb);
1467 *mstate = curr_invo_handle;
1469 Raise_From_Signal_Handler (exception, msg);
1473 __gnat_install_handler ()
1478 c = (char *) xmalloc (2049);
1480 __gnat_error_prehandler_stack = &c[2048];
1482 /* __gnat_error_prehandler is an assembly function. */
1483 SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1484 __gnat_handler_installed = 1;
1492 /***************************************/
1493 /* __gnat_initialize (VXWorks Version) */
1494 /***************************************/
1496 #elif defined(__vxworks)
1499 #include <taskLib.h>
1503 extern int __gnat_inum_to_ivec (int);
1504 static void __gnat_error_handler (int, int, struct sigcontext *);
1506 #ifndef __alpha_vxworks
1508 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1511 extern long getpid PARAMS ((void));
1516 return taskIdSelf ();
1520 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1522 __gnat_inum_to_ivec (num)
1525 return INUM_TO_IVEC (num);
1529 __gnat_error_handler (sig, code, sc)
1532 struct sigcontext *sc;
1534 struct Exception_Data *exception;
1539 /* VxWorks will always mask out the signal during the signal handler and
1540 will reenable it on a longjmp. GNAT does not generate a longjmp to
1541 return from a signal handler so the signal will still be masked unless
1543 sigprocmask (SIG_SETMASK, NULL, &mask);
1544 sigdelset (&mask, sig);
1545 sigprocmask (SIG_SETMASK, &mask, NULL);
1547 /* VxWorks will suspend the task when it gets a hardware exception. We
1548 take the liberty of resuming the task for the application. */
1549 if (taskIsSuspended (taskIdSelf ()) != 0)
1550 taskResume (taskIdSelf ());
1555 exception = &constraint_error;
1559 exception = &constraint_error;
1563 exception = &program_error;
1567 exception = &program_error;
1571 exception = &program_error;
1572 msg = "unhandled signal";
1575 Raise_From_Signal_Handler (exception, msg);
1579 __gnat_install_handler ()
1581 struct sigaction act;
1583 /* Setup signal handler to map synchronous signals to appropriate
1584 exceptions. Make sure that the handler isn't interrupted by another
1585 signal that might cause a scheduling event! */
1587 act.sa_handler = __gnat_error_handler;
1588 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1589 sigemptyset (&act.sa_mask);
1591 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1592 applies to vectored hardware interrupts, not signals */
1593 sigaction (SIGFPE, &act, NULL);
1594 sigaction (SIGILL, &act, NULL);
1595 sigaction (SIGSEGV, &act, NULL);
1596 sigaction (SIGBUS, &act, NULL);
1598 __gnat_handler_installed = 1;
1601 #define HAVE_GNAT_INIT_FLOAT
1604 __gnat_init_float ()
1606 /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1607 to get correct Ada semantic. */
1608 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT)
1613 /* Similarily for sparc64. Achieved by masking bits in the Trap Enable Mask
1614 field of the Floating-point Status Register (see the Sparc Architecture
1615 Manual Version 9, p 48). */
1616 #if defined (sparc64)
1618 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1619 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1620 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1621 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1622 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1626 __asm__("st %%fsr, %0" : "=m" (fsr));
1627 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1628 __asm__("ld %0, %%fsr" : : "m" (fsr));
1634 __gnat_initialize ()
1636 __gnat_init_float ();
1638 /* Assume an environment task stack size of 20kB.
1640 Using a constant is necessary because we do not want each Ada application
1641 to depend on the optional taskShow library,
1642 which is required to get the actual stack information.
1644 The consequence of this is that with -fstack-check
1645 the environment task must have an actual stack size
1646 of at least 20kB and the usable size will be about 14kB.
1649 __gnat_set_stack_size (14336);
1650 /* Allow some head room for the stack checking code, and for
1651 stack space consumed during initialization */
1654 /********************************/
1655 /* __gnat_initialize for NetBSD */
1656 /********************************/
1658 #elif defined(__NetBSD__)
1664 __gnat_error_handler (sig)
1667 struct Exception_Data *exception;
1673 exception = &constraint_error;
1677 exception = &constraint_error;
1681 exception = &storage_error;
1682 msg = "stack overflow or erroneous memory access";
1685 exception = &constraint_error;
1689 exception = &program_error;
1690 msg = "unhandled signal";
1693 Raise_From_Signal_Handler(exception, msg);
1697 __gnat_install_handler()
1699 struct sigaction act;
1701 act.sa_handler = __gnat_error_handler;
1702 act.sa_flags = SA_NODEFER | SA_RESTART;
1703 sigemptyset (&act.sa_mask);
1705 /* Do not install handlers if interrupt state is "System" */
1706 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1707 sigaction (SIGFPE, &act, NULL);
1708 if (__gnat_get_interrupt_state (SIGILL) != 's')
1709 sigaction (SIGILL, &act, NULL);
1710 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1711 sigaction (SIGSEGV, &act, NULL);
1712 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1713 sigaction (SIGBUS, &act, NULL);
1717 __gnat_initialize ()
1719 __gnat_install_handler ();
1720 __gnat_init_float ();
1723 /***************************************/
1724 /* __gnat_initialize (RTEMS version) */
1725 /***************************************/
1727 #elif defined(__rtems__)
1729 extern void __gnat_install_handler ();
1731 /* For RTEMS, each bsp will provide a custom __gnat_install_handler (). */
1734 __gnat_initialize ()
1736 __gnat_install_handler ();
1739 /***************************************/
1740 /* __gnat_initialize (RTEMS version) */
1741 /***************************************/
1743 #elif defined(__rtems__)
1745 extern void __gnat_install_handler ();
1747 /* For RTEMS, each bsp will provide a custom __gnat_install_handler (). */
1750 __gnat_initialize ()
1752 __gnat_install_handler ();
1757 /* For all other versions of GNAT, the initialize routine and handler
1758 installation do nothing */
1760 /***************************************/
1761 /* __gnat_initialize (Default Version) */
1762 /***************************************/
1765 __gnat_initialize ()
1769 /********************************************/
1770 /* __gnat_install_handler (Default Version) */
1771 /********************************************/
1774 __gnat_install_handler ()
1776 __gnat_handler_installed = 1;
1781 /*********************/
1782 /* __gnat_init_float */
1783 /*********************/
1785 /* This routine is called as each process thread is created, for possible
1786 initialization of the FP processor. This version is used under INTERIX,
1787 WIN32 and could be used under OS/2 */
1789 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1790 || defined (__Lynx__) || defined(__NetBSD__)
1792 #define HAVE_GNAT_INIT_FLOAT
1795 __gnat_init_float ()
1797 #if defined (__i386__) || defined (i386)
1799 /* This is used to properly initialize the FPU on an x86 for each
1804 #endif /* Defined __i386__ */
1808 #ifndef HAVE_GNAT_INIT_FLOAT
1810 /* All targets without a specific __gnat_init_float will use an empty one */
1812 __gnat_init_float ()