1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2005, 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, 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, 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 /* This file should be kept synchronized with 2sinit.ads, 2sinit.adb, and
43 5zinit.adb. All these files implement the required functionality for
46 /* The following include is here to meet the published VxWorks requirement
47 that the __vxworks header appear before any other include. */
57 /* We don't have libiberty, so us malloc. */
58 #define xmalloc(S) malloc (S)
67 extern void __gnat_raise_program_error (const char *, int);
69 /* Addresses of exception data blocks for predefined exceptions. */
70 extern struct Exception_Data constraint_error;
71 extern struct Exception_Data numeric_error;
72 extern struct Exception_Data program_error;
73 extern struct Exception_Data storage_error;
74 extern struct Exception_Data tasking_error;
75 extern struct Exception_Data _abort_signal;
77 #define Lock_Task system__soft_links__lock_task
78 extern void (*Lock_Task) (void);
80 #define Unlock_Task system__soft_links__unlock_task
81 extern void (*Unlock_Task) (void);
83 #define Get_Machine_State_Addr \
84 system__soft_links__get_machine_state_addr
85 extern struct Machine_State *(*Get_Machine_State_Addr) (void);
87 #define Check_Abort_Status \
88 system__soft_links__check_abort_status
89 extern int (*Check_Abort_Status) (void);
91 #define Raise_From_Signal_Handler \
92 ada__exceptions__raise_from_signal_handler
93 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
95 #define Propagate_Signal_Exception \
96 __gnat_propagate_sig_exc
97 extern void Propagate_Signal_Exception (struct Machine_State *,
98 struct Exception_Data *,
101 /* Copies of global values computed by the binder */
102 int __gl_main_priority = -1;
103 int __gl_time_slice_val = -1;
104 char __gl_wc_encoding = 'n';
105 char __gl_locking_policy = ' ';
106 char __gl_queuing_policy = ' ';
107 char __gl_task_dispatching_policy = ' ';
108 char *__gl_restrictions = 0;
109 char *__gl_interrupt_states = 0;
110 int __gl_num_interrupt_states = 0;
111 int __gl_unreserve_all_interrupts = 0;
112 int __gl_exception_tracebacks = 0;
113 int __gl_zero_cost_exceptions = 0;
114 int __gl_detect_blocking = 0;
116 /* Indication of whether synchronous signal handler has already been
117 installed by a previous call to adainit */
118 int __gnat_handler_installed = 0;
120 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
121 is defined. If this is not set them a void implementation will be defined
122 at the end of this unit. */
123 #undef HAVE_GNAT_INIT_FLOAT
125 /******************************/
126 /* __gnat_get_interrupt_state */
127 /******************************/
129 char __gnat_get_interrupt_state (int);
131 /* This routine is called from the runtime as needed to determine the state
132 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
133 in the current partition. The input argument is the interrupt number,
134 and the result is one of the following:
136 'n' this interrupt not set by any Interrupt_State pragma
137 'u' Interrupt_State pragma set state to User
138 'r' Interrupt_State pragma set state to Runtime
139 's' Interrupt_State pragma set state to System */
142 __gnat_get_interrupt_state (int intrup)
144 if (intrup >= __gl_num_interrupt_states)
147 return __gl_interrupt_states [intrup];
150 /**********************/
151 /* __gnat_set_globals */
152 /**********************/
154 /* This routine is called from the binder generated main program. It copies
155 the values for global quantities computed by the binder into the following
156 global locations. The reason that we go through this copy, rather than just
157 define the global locations in the binder generated file, is that they are
158 referenced from the runtime, which may be in a shared library, and the
159 binder file is not in the shared library. Global references across library
160 boundaries like this are not handled correctly in all systems. */
162 /* For detailed description of the parameters to this routine, see the
163 section titled Run-Time Globals in package Bindgen (bindgen.adb) */
166 __gnat_set_globals (int main_priority,
171 char task_dispatching_policy,
173 char *interrupt_states,
174 int num_interrupt_states,
175 int unreserve_all_interrupts,
176 int exception_tracebacks,
177 int zero_cost_exceptions,
180 static int already_called = 0;
182 /* If this procedure has been already called once, check that the
183 arguments in this call are consistent with the ones in the previous
184 calls. Otherwise, raise a Program_Error exception.
186 We do not check for consistency of the wide character encoding
187 method. This default affects only Wide_Text_IO where no explicit
188 coding method is given, and there is no particular reason to let
189 this default be affected by the source representation of a library
192 We do not check either for the consistency of exception tracebacks,
193 because exception tracebacks are not normally set in Stand-Alone
194 libraries. If a library or the main program set the exception
195 tracebacks, then they are never reset afterwards (see below).
197 The value of main_priority is meaningful only when we are invoked
198 from the main program elaboration routine of an Ada application.
199 Checking the consistency of this parameter should therefore not be
200 done. Since it is assured that the main program elaboration will
201 always invoke this procedure before any library elaboration
202 routine, only the value of main_priority during the first call
203 should be taken into account and all the subsequent ones should be
204 ignored. Note that the case where the main program is not written
205 in Ada is also properly handled, since the default value will then
206 be used for this parameter.
208 For identical reasons, the consistency of time_slice_val should not
213 if (__gl_locking_policy != locking_policy
214 || __gl_queuing_policy != queuing_policy
215 || __gl_task_dispatching_policy != task_dispatching_policy
216 || __gl_unreserve_all_interrupts != unreserve_all_interrupts
217 || __gl_zero_cost_exceptions != zero_cost_exceptions)
218 __gnat_raise_program_error (__FILE__, __LINE__);
220 /* If either a library or the main program set the exception traceback
221 flag, it is never reset later */
223 if (exception_tracebacks != 0)
224 __gl_exception_tracebacks = exception_tracebacks;
230 __gl_main_priority = main_priority;
231 __gl_time_slice_val = time_slice_val;
232 __gl_wc_encoding = wc_encoding;
233 __gl_locking_policy = locking_policy;
234 __gl_queuing_policy = queuing_policy;
235 __gl_restrictions = restrictions;
236 __gl_interrupt_states = interrupt_states;
237 __gl_num_interrupt_states = num_interrupt_states;
238 __gl_task_dispatching_policy = task_dispatching_policy;
239 __gl_unreserve_all_interrupts = unreserve_all_interrupts;
240 __gl_exception_tracebacks = exception_tracebacks;
241 __gl_detect_blocking = detect_blocking;
243 /* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
244 a-except.adb, which is also part of the compiler sources. Since the
245 compiler is built with an older release of GNAT, the call generated by
246 the old binder to this function does not provide any value for the
247 corresponding argument, so the global has to be initialized in some
248 reasonable other way. This could be removed as soon as the next major
252 __gl_zero_cost_exceptions = zero_cost_exceptions;
254 __gl_zero_cost_exceptions = 0;
255 /* We never build the compiler to run in ZCX mode currently anyway. */
259 /* Notes on the Zero Cost Exceptions scheme and its impact on the signal
260 handlers implemented below :
262 What we call Zero Cost Exceptions is implemented using the GCC eh
263 circuitry, even if the underlying implementation is setjmp/longjmp
264 based. In any case ...
266 The GCC unwinder expects to be dealing with call return addresses, since
267 this is the "nominal" case of what we retrieve while unwinding a regular
268 call chain. To evaluate if a handler applies at some point in this chain,
269 the propagation engine needs to determine what region the corresponding
270 call instruction pertains to. The return address may not be attached to the
271 same region as the call, so the unwinder unconditionally subtracts "some"
272 amount to the return addresses it gets to search the region tables. The
273 exact amount is computed to ensure that the resulting address is inside the
274 call instruction, and is thus target dependent (think about delay slots for
277 When we raise an exception from a signal handler, e.g. to transform a
278 SIGSEGV into Storage_Error, things need to appear as if the signal handler
279 had been "called" by the instruction which triggered the signal, so that
280 exception handlers that apply there are considered. What the unwinder will
281 retrieve as the return address from the signal handler is what it will find
282 as the faulting instruction address in the corresponding signal context
283 pushed by the kernel. Leaving this address untouched may loose, because if
284 the triggering instruction happens to be the very first of a region, the
285 later adjustments performed by the unwinder would yield an address outside
286 that region. We need to compensate for those adjustments at some point,
287 which we currently do in the GCC unwinding fallback macro.
289 The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
290 describes a couple of issues with our current approach. Basically: on some
291 targets the adjustment to apply depends on the triggering signal, which is
292 not easily accessible from the macro, and we actually do not tackle this as
293 of today. Besides, other languages, e.g. Java, deal with this by performing
294 the adjustment in the signal handler before the raise, so our adjustments
295 may break those front-ends.
297 To have it all right, we should either find a way to deal with the signal
298 variants from the macro and convert Java on all targets (ugh), or remove
299 our macro adjustments and update our signal handlers a-la-java way. The
300 latter option appears the simplest, although some targets have their share
301 of subtleties to account for. See for instance the syscall(SYS_sigaction)
302 story in libjava/include/i386-signal.h. */
311 #include <sys/time.h>
313 /* Some versions of AIX don't define SA_NODEFER. */
317 #endif /* SA_NODEFER */
319 /* Versions of AIX before 4.3 don't have nanosleep but provide
322 #ifndef _AIXVERSION_430
324 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
327 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
329 return nsleep (Rqtp, Rmtp);
332 #endif /* _AIXVERSION_430 */
334 static void __gnat_error_handler (int);
337 __gnat_error_handler (int sig)
339 struct Exception_Data *exception;
345 /* FIXME: we need to detect the case of a *real* SIGSEGV */
346 exception = &storage_error;
347 msg = "stack overflow or erroneous memory access";
351 exception = &constraint_error;
356 exception = &constraint_error;
361 exception = &program_error;
362 msg = "unhandled signal";
365 Raise_From_Signal_Handler (exception, msg);
369 __gnat_install_handler (void)
371 struct sigaction act;
373 /* Set up signal handler to map synchronous signals to appropriate
374 exceptions. Make sure that the handler isn't interrupted by another
375 signal that might cause a scheduling event! */
377 act.sa_handler = __gnat_error_handler;
378 act.sa_flags = SA_NODEFER | SA_RESTART;
379 sigemptyset (&act.sa_mask);
381 /* Do not install handlers if interrupt state is "System" */
382 if (__gnat_get_interrupt_state (SIGABRT) != 's')
383 sigaction (SIGABRT, &act, NULL);
384 if (__gnat_get_interrupt_state (SIGFPE) != 's')
385 sigaction (SIGFPE, &act, NULL);
386 if (__gnat_get_interrupt_state (SIGILL) != 's')
387 sigaction (SIGILL, &act, NULL);
388 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
389 sigaction (SIGSEGV, &act, NULL);
390 if (__gnat_get_interrupt_state (SIGBUS) != 's')
391 sigaction (SIGBUS, &act, NULL);
393 __gnat_handler_installed = 1;
400 #elif defined(__alpha__) && defined(__osf__)
403 #include <sys/siginfo.h>
405 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
406 extern char *__gnat_get_code_loc (struct sigcontext *);
407 extern void __gnat_set_code_loc (struct sigcontext *, char *);
408 extern void __gnat_enter_handler (struct sigcontext *, char *);
409 extern size_t __gnat_machine_state_length (void);
411 extern long exc_lookup_gp (char *);
412 extern void exc_resume (struct sigcontext *);
415 __gnat_error_handler (int sig, siginfo_t *sip, struct sigcontext *context)
417 struct Exception_Data *exception;
418 static int recurse = 0;
419 struct sigcontext *mstate;
422 /* If this was an explicit signal from a "kill", just resignal it. */
423 if (SI_FROMUSER (sip))
425 signal (sig, SIG_DFL);
426 kill (getpid(), sig);
429 /* Otherwise, treat it as something we handle. */
433 /* If the problem was permissions, this is a constraint error.
434 Likewise if the failing address isn't maximally aligned or if
437 ??? Using a static variable here isn't task-safe, but it's
438 much too hard to do anything else and we're just determining
439 which exception to raise. */
440 if (sip->si_code == SEGV_ACCERR
441 || (((long) sip->si_addr) & 3) != 0
444 exception = &constraint_error;
449 /* See if the page before the faulting page is accessible. Do that
450 by trying to access it. We'd like to simply try to access
451 4096 + the faulting address, but it's not guaranteed to be
452 the actual address, just to be on the same page. */
455 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
456 msg = "stack overflow (or erroneous memory access)";
457 exception = &storage_error;
462 exception = &program_error;
467 exception = &constraint_error;
472 exception = &program_error;
473 msg = "unhandled signal";
477 mstate = (struct sigcontext *) (*Get_Machine_State_Addr) ();
481 Raise_From_Signal_Handler (exception, (char *) msg);
485 __gnat_install_handler (void)
487 struct sigaction act;
489 /* Setup signal handler to map synchronous signals to appropriate
490 exceptions. Make sure that the handler isn't interrupted by another
491 signal that might cause a scheduling event! */
493 act.sa_handler = (void (*) (int)) __gnat_error_handler;
494 act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
495 sigemptyset (&act.sa_mask);
497 /* Do not install handlers if interrupt state is "System" */
498 if (__gnat_get_interrupt_state (SIGABRT) != 's')
499 sigaction (SIGABRT, &act, NULL);
500 if (__gnat_get_interrupt_state (SIGFPE) != 's')
501 sigaction (SIGFPE, &act, NULL);
502 if (__gnat_get_interrupt_state (SIGILL) != 's')
503 sigaction (SIGILL, &act, NULL);
504 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
505 sigaction (SIGSEGV, &act, NULL);
506 if (__gnat_get_interrupt_state (SIGBUS) != 's')
507 sigaction (SIGBUS, &act, NULL);
509 __gnat_handler_installed = 1;
512 /* Routines called by s-mastop-tru64.adb. */
517 __gnat_get_code_loc (struct sigcontext *context)
519 return (char *) context->sc_pc;
523 __gnat_set_code_loc (struct sigcontext *context, char *pc)
525 context->sc_pc = (long) pc;
530 __gnat_enter_handler (struct sigcontext *context, char *pc)
532 context->sc_pc = (long) pc;
533 context->sc_regs[SC_GP] = exc_lookup_gp (pc);
534 exc_resume (context);
538 __gnat_machine_state_length (void)
540 return sizeof (struct sigcontext);
543 /********************/
544 /* PA HP-UX section */
545 /********************/
547 #elif defined (__hppa__) && defined (__hpux__)
550 #include <sys/ucontext.h>
553 __gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext);
555 /* __gnat_adjust_context_for_raise - see comments along with the default
556 version later in this file. */
558 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
561 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
563 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
565 if (UseWideRegs (mcontext))
566 mcontext->ss_wide.ss_32.ss_pcoq_head_lo ++;
568 mcontext->ss_narrow.ss_pcoq_head ++;
572 __gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext)
574 struct Exception_Data *exception;
580 /* FIXME: we need to detect the case of a *real* SIGSEGV */
581 exception = &storage_error;
582 msg = "stack overflow or erroneous memory access";
586 exception = &constraint_error;
591 exception = &constraint_error;
596 exception = &program_error;
597 msg = "unhandled signal";
600 __gnat_adjust_context_for_raise (sig, ucontext);
602 Raise_From_Signal_Handler (exception, msg);
606 __gnat_install_handler (void)
608 struct sigaction act;
610 /* Set up signal handler to map synchronous signals to appropriate
611 exceptions. Make sure that the handler isn't interrupted by another
612 signal that might cause a scheduling event! Also setup an alternate
613 stack region for the handler execution so that stack overflows can be
614 handled properly, avoiding a SEGV generation from stack usage by the
617 static char handler_stack[SIGSTKSZ*2];
618 /* SIGSTKSZ appeared to be "short" for the needs in some contexts
619 (e.g. experiments with GCC ZCX exceptions). */
623 stack.ss_sp = handler_stack;
624 stack.ss_size = sizeof (handler_stack);
627 sigaltstack (&stack, NULL);
629 act.sa_sigaction = __gnat_error_handler;
630 act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK | SA_SIGINFO;
631 sigemptyset (&act.sa_mask);
633 /* Do not install handlers if interrupt state is "System" */
634 if (__gnat_get_interrupt_state (SIGABRT) != 's')
635 sigaction (SIGABRT, &act, NULL);
636 if (__gnat_get_interrupt_state (SIGFPE) != 's')
637 sigaction (SIGFPE, &act, NULL);
638 if (__gnat_get_interrupt_state (SIGILL) != 's')
639 sigaction (SIGILL, &act, NULL);
640 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
641 sigaction (SIGSEGV, &act, NULL);
642 if (__gnat_get_interrupt_state (SIGBUS) != 's')
643 sigaction (SIGBUS, &act, NULL);
645 __gnat_handler_installed = 1;
648 /*********************/
649 /* GNU/Linux Section */
650 /*********************/
652 #elif defined (linux) && (defined (i386) || defined (__x86_64__))
656 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
657 #include <sys/ucontext.h>
659 /* GNU/Linux, which uses glibc, does not define NULL in included
663 #define NULL ((void *) 0)
666 static void __gnat_error_handler (int, siginfo_t *siginfo, void *ucontext);
668 /* __gnat_adjust_context_for_raise - see comments along with the default
669 version later in this file. */
671 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
674 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
676 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
679 mcontext->gregs[REG_EIP]++;
680 #elif defined (__x86_64__)
681 mcontext->gregs[REG_RIP]++;
686 __gnat_error_handler (int sig,
687 siginfo_t *siginfo ATTRIBUTE_UNUSED,
690 struct Exception_Data *exception;
692 static int recurse = 0;
697 /* If the problem was permissions, this is a constraint error.
698 Likewise if the failing address isn't maximally aligned or if
701 ??? Using a static variable here isn't task-safe, but it's
702 much too hard to do anything else and we're just determining
703 which exception to raise. */
706 exception = &constraint_error;
711 /* Here we would like a discrimination test to see whether the
712 page before the faulting address is accessible. Unfortunately
713 Linux seems to have no way of giving us the faulting address.
715 In versions of a-init.c before 1.95, we had a test of the page
716 before the stack pointer using:
720 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
722 but that's wrong, since it tests the stack pointer location, and
723 the current stack probe code does not move the stack pointer
724 until all probes succeed.
726 For now we simply do not attempt any discrimination at all. Note
727 that this is quite acceptable, since a "real" SIGSEGV can only
728 occur as the result of an erroneous program */
730 msg = "stack overflow (or erroneous memory access)";
731 exception = &storage_error;
736 exception = &constraint_error;
741 exception = &constraint_error;
746 exception = &program_error;
747 msg = "unhandled signal";
751 /* We adjust the interrupted context here (and not in the
752 MD_FALLBACK_FRAME_STATE_FOR macro) because recent versions of the Native
753 POSIX Thread Library (NPTL) are compiled with DWARF 2 unwind information,
754 and hence the later macro is never executed for signal frames. */
756 __gnat_adjust_context_for_raise (sig, ucontext);
758 Raise_From_Signal_Handler (exception, msg);
762 __gnat_install_handler (void)
764 struct sigaction act;
766 /* Set up signal handler to map synchronous signals to appropriate
767 exceptions. Make sure that the handler isn't interrupted by another
768 signal that might cause a scheduling event! */
770 act.sa_sigaction = __gnat_error_handler;
771 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
772 sigemptyset (&act.sa_mask);
774 /* Do not install handlers if interrupt state is "System" */
775 if (__gnat_get_interrupt_state (SIGABRT) != 's')
776 sigaction (SIGABRT, &act, NULL);
777 if (__gnat_get_interrupt_state (SIGFPE) != 's')
778 sigaction (SIGFPE, &act, NULL);
779 if (__gnat_get_interrupt_state (SIGILL) != 's')
780 sigaction (SIGILL, &act, NULL);
781 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
782 sigaction (SIGSEGV, &act, NULL);
783 if (__gnat_get_interrupt_state (SIGBUS) != 's')
784 sigaction (SIGBUS, &act, NULL);
786 __gnat_handler_installed = 1;
789 /*******************/
790 /* Interix Section */
791 /*******************/
793 #elif defined (__INTERIX)
797 static void __gnat_error_handler (int);
800 __gnat_error_handler (int sig)
802 struct Exception_Data *exception;
808 exception = &storage_error;
809 msg = "stack overflow or erroneous memory access";
813 exception = &constraint_error;
818 exception = &constraint_error;
823 exception = &program_error;
824 msg = "unhandled signal";
827 Raise_From_Signal_Handler (exception, msg);
831 __gnat_install_handler (void)
833 struct sigaction act;
835 /* Set up signal handler to map synchronous signals to appropriate
836 exceptions. Make sure that the handler isn't interrupted by another
837 signal that might cause a scheduling event! */
839 act.sa_handler = __gnat_error_handler;
841 sigemptyset (&act.sa_mask);
843 /* Handlers for signals besides SIGSEGV cause c974013 to hang */
844 /* sigaction (SIGILL, &act, NULL); */
845 /* sigaction (SIGABRT, &act, NULL); */
846 /* sigaction (SIGFPE, &act, NULL); */
847 /* sigaction (SIGBUS, &act, NULL); */
849 /* Do not install handlers if interrupt state is "System" */
850 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
851 sigaction (SIGSEGV, &act, NULL);
853 __gnat_handler_installed = 1;
869 #define SIGADAABORT 48
870 #define SIGNAL_STACK_SIZE 4096
871 #define SIGNAL_STACK_ALIGNMENT 64
875 sigcontext_t context;
878 static void __gnat_error_handler (int, int, sigcontext_t *);
880 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
881 connecting that handler, with the effects described in the sigaction
885 If cleared and the signal is caught, the first argument is
886 also the signal number but the second argument is the signal
887 code identifying the cause of the signal. The third argument
888 points to a sigcontext_t structure containing the receiving
889 process's context when the signal was delivered.
893 __gnat_error_handler (int sig, int code, sigcontext_t *sc)
895 struct Machine_State *mstate;
896 struct Exception_Data *exception;
904 exception = &program_error;
905 msg = "SIGSEGV: (Invalid virtual address)";
907 else if (code == ENXIO)
909 exception = &program_error;
910 msg = "SIGSEGV: (Read beyond mapped object)";
912 else if (code == ENOSPC)
914 exception = &program_error; /* ??? storage_error ??? */
915 msg = "SIGSEGV: (Autogrow for file failed)";
917 else if (code == EACCES || code == EEXIST)
919 /* ??? We handle stack overflows here, some of which do trigger
920 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
921 the documented valid codes for SEGV in the signal(5) man
924 /* ??? Re-add smarts to further verify that we launched
925 the stack into a guard page, not an attempt to
926 write to .text or something */
927 exception = &storage_error;
928 msg = "SIGSEGV: (stack overflow or erroneous memory access)";
932 /* Just in case the OS guys did it to us again. Sometimes
933 they fail to document all of the valid codes that are
934 passed to signal handlers, just in case someone depends
935 on knowing all the codes */
936 exception = &program_error;
937 msg = "SIGSEGV: (Undocumented reason)";
942 /* Map all bus errors to Program_Error. */
943 exception = &program_error;
948 /* Map all fpe errors to Constraint_Error. */
949 exception = &constraint_error;
954 if ((*Check_Abort_Status) ())
956 exception = &_abort_signal;
965 /* Everything else is a Program_Error. */
966 exception = &program_error;
967 msg = "unhandled signal";
970 mstate = (*Get_Machine_State_Addr) ();
972 memcpy ((void *) mstate, (const void *) sc, sizeof (sigcontext_t));
974 Raise_From_Signal_Handler (exception, msg);
978 __gnat_install_handler (void)
980 struct sigaction act;
982 /* Setup signal handler to map synchronous signals to appropriate
983 exceptions. Make sure that the handler isn't interrupted by another
984 signal that might cause a scheduling event! */
986 act.sa_handler = __gnat_error_handler;
987 act.sa_flags = SA_NODEFER + SA_RESTART;
988 sigfillset (&act.sa_mask);
989 sigemptyset (&act.sa_mask);
991 /* Do not install handlers if interrupt state is "System" */
992 if (__gnat_get_interrupt_state (SIGABRT) != 's')
993 sigaction (SIGABRT, &act, NULL);
994 if (__gnat_get_interrupt_state (SIGFPE) != 's')
995 sigaction (SIGFPE, &act, NULL);
996 if (__gnat_get_interrupt_state (SIGILL) != 's')
997 sigaction (SIGILL, &act, NULL);
998 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
999 sigaction (SIGSEGV, &act, NULL);
1000 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1001 sigaction (SIGBUS, &act, NULL);
1002 if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
1003 sigaction (SIGADAABORT, &act, NULL);
1005 __gnat_handler_installed = 1;
1008 /*******************/
1009 /* Solaris Section */
1010 /*******************/
1012 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
1015 #include <siginfo.h>
1017 static void __gnat_error_handler (int, siginfo_t *);
1020 __gnat_error_handler (int sig, siginfo_t *sip)
1022 struct Exception_Data *exception;
1023 static int recurse = 0;
1026 /* If this was an explicit signal from a "kill", just resignal it. */
1027 if (SI_FROMUSER (sip))
1029 signal (sig, SIG_DFL);
1030 kill (getpid(), sig);
1033 /* Otherwise, treat it as something we handle. */
1037 /* If the problem was permissions, this is a constraint error.
1038 Likewise if the failing address isn't maximally aligned or if
1041 ??? Using a static variable here isn't task-safe, but it's
1042 much too hard to do anything else and we're just determining
1043 which exception to raise. */
1044 if (sip->si_code == SEGV_ACCERR
1045 || (((long) sip->si_addr) & 3) != 0
1048 exception = &constraint_error;
1053 /* See if the page before the faulting page is accessible. Do that
1054 by trying to access it. We'd like to simply try to access
1055 4096 + the faulting address, but it's not guaranteed to be
1056 the actual address, just to be on the same page. */
1059 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1060 exception = &storage_error;
1061 msg = "stack overflow (or erroneous memory access)";
1066 exception = &program_error;
1071 exception = &constraint_error;
1076 exception = &program_error;
1077 msg = "unhandled signal";
1082 Raise_From_Signal_Handler (exception, msg);
1086 __gnat_install_handler (void)
1088 struct sigaction act;
1090 /* Set up signal handler to map synchronous signals to appropriate
1091 exceptions. Make sure that the handler isn't interrupted by another
1092 signal that might cause a scheduling event! */
1094 act.sa_handler = __gnat_error_handler;
1095 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1096 sigemptyset (&act.sa_mask);
1098 /* Do not install handlers if interrupt state is "System" */
1099 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1100 sigaction (SIGABRT, &act, NULL);
1101 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1102 sigaction (SIGFPE, &act, NULL);
1103 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1104 sigaction (SIGSEGV, &act, NULL);
1105 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1106 sigaction (SIGBUS, &act, NULL);
1108 __gnat_handler_installed = 1;
1117 long __gnat_error_handler (int *, void *);
1120 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1121 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1122 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1124 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1125 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1126 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1129 #if defined (IN_RTS) && !defined (__IA64)
1131 /* The prehandler actually gets control first on a condition. It swaps the
1132 stack pointer and calls the handler (__gnat_error_handler). */
1133 extern long __gnat_error_prehandler (void);
1135 extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
1138 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1139 Most of these are also defined in the header file ssdef.h which has not
1140 yet been converted to be recognized by Gnu C. */
1142 /* Defining these as macros, as opposed to external addresses, allows
1143 them to be used in a case statement (below */
1144 #define SS$_ACCVIO 12
1145 #define SS$_HPARITH 1284
1146 #define SS$_STKOVF 1364
1147 #define SS$_RESIGNAL 2328
1149 /* These codes are in standard message libraries */
1150 extern int CMA$_EXIT_THREAD;
1151 extern int SS$_DEBUG;
1152 extern int SS$_INTDIV;
1153 extern int LIB$_KEYNOTFOU;
1154 extern int LIB$_ACTIMAGE;
1155 extern int MTH$_FLOOVEMAT; /* Some ACVC_21 CXA tests */
1157 /* These codes are non standard, which is to say the author is
1158 not sure if they are defined in the standard message libraries
1159 so keep them as macros for now. */
1160 #define RDB$_STREAM_EOF 20480426
1161 #define FDL$_UNPRIKW 11829410
1163 struct cond_except {
1165 const struct Exception_Data *except;
1168 struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1170 /* Conditions that don't have an Ada exception counterpart must raise
1171 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1172 referenced by user programs, not the compiler or tools. Hence the
1177 #define Status_Error ada__io_exceptions__status_error
1178 extern struct Exception_Data Status_Error;
1180 #define Mode_Error ada__io_exceptions__mode_error
1181 extern struct Exception_Data Mode_Error;
1183 #define Name_Error ada__io_exceptions__name_error
1184 extern struct Exception_Data Name_Error;
1186 #define Use_Error ada__io_exceptions__use_error
1187 extern struct Exception_Data Use_Error;
1189 #define Device_Error ada__io_exceptions__device_error
1190 extern struct Exception_Data Device_Error;
1192 #define End_Error ada__io_exceptions__end_error
1193 extern struct Exception_Data End_Error;
1195 #define Data_Error ada__io_exceptions__data_error
1196 extern struct Exception_Data Data_Error;
1198 #define Layout_Error ada__io_exceptions__layout_error
1199 extern struct Exception_Data Layout_Error;
1201 #define Non_Ada_Error system__aux_dec__non_ada_error
1202 extern struct Exception_Data Non_Ada_Error;
1204 #define Coded_Exception system__vms_exception_table__coded_exception
1205 extern struct Exception_Data *Coded_Exception (Exception_Code);
1207 #define Base_Code_In system__vms_exception_table__base_code_in
1208 extern Exception_Code Base_Code_In (Exception_Code);
1210 /* DEC Ada exceptions are not defined in a header file, so they
1211 must be declared as external addresses */
1213 extern int ADA$_PROGRAM_ERROR __attribute__ ((weak));
1214 extern int ADA$_LOCK_ERROR __attribute__ ((weak));
1215 extern int ADA$_EXISTENCE_ERROR __attribute__ ((weak));
1216 extern int ADA$_KEY_ERROR __attribute__ ((weak));
1217 extern int ADA$_KEYSIZERR __attribute__ ((weak));
1218 extern int ADA$_STAOVF __attribute__ ((weak));
1219 extern int ADA$_CONSTRAINT_ERRO __attribute__ ((weak));
1220 extern int ADA$_IOSYSFAILED __attribute__ ((weak));
1221 extern int ADA$_LAYOUT_ERROR __attribute__ ((weak));
1222 extern int ADA$_STORAGE_ERROR __attribute__ ((weak));
1223 extern int ADA$_DATA_ERROR __attribute__ ((weak));
1224 extern int ADA$_DEVICE_ERROR __attribute__ ((weak));
1225 extern int ADA$_END_ERROR __attribute__ ((weak));
1226 extern int ADA$_MODE_ERROR __attribute__ ((weak));
1227 extern int ADA$_NAME_ERROR __attribute__ ((weak));
1228 extern int ADA$_STATUS_ERROR __attribute__ ((weak));
1229 extern int ADA$_NOT_OPEN __attribute__ ((weak));
1230 extern int ADA$_ALREADY_OPEN __attribute__ ((weak));
1231 extern int ADA$_USE_ERROR __attribute__ ((weak));
1232 extern int ADA$_UNSUPPORTED __attribute__ ((weak));
1233 extern int ADA$_FAC_MODE_MISMAT __attribute__ ((weak));
1234 extern int ADA$_ORG_MISMATCH __attribute__ ((weak));
1235 extern int ADA$_RFM_MISMATCH __attribute__ ((weak));
1236 extern int ADA$_RAT_MISMATCH __attribute__ ((weak));
1237 extern int ADA$_MRS_MISMATCH __attribute__ ((weak));
1238 extern int ADA$_MRN_MISMATCH __attribute__ ((weak));
1239 extern int ADA$_KEY_MISMATCH __attribute__ ((weak));
1240 extern int ADA$_MAXLINEXC __attribute__ ((weak));
1241 extern int ADA$_LINEXCMRS __attribute__ ((weak));
1243 /* DEC Ada specific conditions */
1244 static const struct cond_except dec_ada_cond_except_table [] = {
1245 {&ADA$_PROGRAM_ERROR, &program_error},
1246 {&ADA$_USE_ERROR, &Use_Error},
1247 {&ADA$_KEYSIZERR, &program_error},
1248 {&ADA$_STAOVF, &storage_error},
1249 {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1250 {&ADA$_IOSYSFAILED, &Device_Error},
1251 {&ADA$_LAYOUT_ERROR, &Layout_Error},
1252 {&ADA$_STORAGE_ERROR, &storage_error},
1253 {&ADA$_DATA_ERROR, &Data_Error},
1254 {&ADA$_DEVICE_ERROR, &Device_Error},
1255 {&ADA$_END_ERROR, &End_Error},
1256 {&ADA$_MODE_ERROR, &Mode_Error},
1257 {&ADA$_NAME_ERROR, &Name_Error},
1258 {&ADA$_STATUS_ERROR, &Status_Error},
1259 {&ADA$_NOT_OPEN, &Use_Error},
1260 {&ADA$_ALREADY_OPEN, &Use_Error},
1261 {&ADA$_USE_ERROR, &Use_Error},
1262 {&ADA$_UNSUPPORTED, &Use_Error},
1263 {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1264 {&ADA$_ORG_MISMATCH, &Use_Error},
1265 {&ADA$_RFM_MISMATCH, &Use_Error},
1266 {&ADA$_RAT_MISMATCH, &Use_Error},
1267 {&ADA$_MRS_MISMATCH, &Use_Error},
1268 {&ADA$_MRN_MISMATCH, &Use_Error},
1269 {&ADA$_KEY_MISMATCH, &Use_Error},
1270 {&ADA$_MAXLINEXC, &constraint_error},
1271 {&ADA$_LINEXCMRS, &constraint_error},
1276 /* Already handled by a pragma Import_Exception
1277 in Aux_IO_Exceptions */
1278 {&ADA$_LOCK_ERROR, &Lock_Error},
1279 {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1280 {&ADA$_KEY_ERROR, &Key_Error},
1285 /* Non DEC Ada specific conditions. We could probably also put
1286 SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
1287 static const struct cond_except cond_except_table [] = {
1288 {&MTH$_FLOOVEMAT, &constraint_error},
1289 {&SS$_INTDIV, &constraint_error},
1293 /* To deal with VMS conditions and their mapping to Ada exceptions,
1294 the __gnat_error_handler routine below is installed as an exception
1295 vector having precedence over DEC frame handlers. Some conditions
1296 still need to be handled by such handlers, however, in which case
1297 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
1298 instance the use of a third party library compiled with DECAda and
1299 performing it's own exception handling internally.
1301 To allow some user-level flexibility, which conditions should be
1302 resignaled is controlled by a predicate function, provided with the
1303 condition value and returning a boolean indication stating whether
1304 this condition should be resignaled or not.
1306 That predicate function is called indirectly, via a function pointer,
1307 by __gnat_error_handler, and changing that pointer is allowed to the
1308 the user code by way of the __gnat_set_resignal_predicate interface.
1310 The user level function may then implement what it likes, including
1311 for instance the maintenance of a dynamic data structure if the set
1312 of to be resignalled conditions has to change over the program's
1315 ??? This is not a perfect solution to deal with the possible
1316 interactions between the GNAT and the DECAda exception handling
1317 models and better (more general) schemes are studied. This is so
1318 just provided as a convenient workaround in the meantime, and
1319 should be use with caution since the implementation has been kept
1323 resignal_predicate (int code);
1325 const int *cond_resignal_table [] = {
1330 (int *) RDB$_STREAM_EOF,
1331 (int *) FDL$_UNPRIKW,
1335 /* Default GNAT predicate for resignaling conditions. */
1338 __gnat_default_resignal_p (int code)
1342 for (i = 0, iexcept = 0;
1343 cond_resignal_table [i] &&
1344 !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1350 /* Static pointer to predicate that the __gnat_error_handler exception
1351 vector invokes to determine if it should resignal a condition. */
1353 static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1355 /* User interface to change the predicate pointer to PREDICATE. Reset to
1356 the default if PREDICATE is null. */
1359 __gnat_set_resignal_predicate (resignal_predicate * predicate)
1362 __gnat_resignal_p = __gnat_default_resignal_p;
1364 __gnat_resignal_p = predicate;
1367 /* Should match System.Parameters.Default_Exception_Msg_Max_Length */
1368 #define Default_Exception_Msg_Max_Length 512
1370 /* Action routine for SYS$PUTMSG. There may be
1371 multiple conditions, each with text to be appended to
1372 MESSAGE and separated by line termination. */
1375 copy_msg (msgdesc, message)
1376 struct descriptor_s *msgdesc;
1379 int len = strlen (message);
1382 /* Check for buffer overflow and skip */
1383 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1385 strcat (message, "\r\n");
1389 /* Check for buffer overflow and truncate if necessary */
1390 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1392 len + msgdesc->len - Default_Exception_Msg_Max_Length);
1393 strncpy (&message [len], msgdesc->adr, copy_len);
1394 message [len + copy_len] = 0;
1400 __gnat_error_handler (int *sigargs, void *mechargs)
1402 struct Exception_Data *exception = 0;
1403 Exception_Code base_code;
1404 struct descriptor_s gnat_facility = {4,0,"GNAT"};
1405 char message [Default_Exception_Msg_Max_Length];
1409 long curr_invo_handle;
1412 /* Check for conditions to resignal which aren't effected by pragma
1413 Import_Exception. */
1414 if (__gnat_resignal_p (sigargs [1]))
1415 return SS$_RESIGNAL;
1418 /* See if it's an imported exception. Beware that registered exceptions
1419 are bound to their base code, with the severity bits masked off. */
1420 base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1421 exception = Coded_Exception (base_code);
1426 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1429 exception->Name_Length = 19;
1430 /* The full name really should be get sys$getmsg returns. ??? */
1431 exception->Full_Name = "IMPORTED_EXCEPTION";
1432 exception->Import_Code = base_code;
1440 if (sigargs[3] == 0)
1442 exception = &constraint_error;
1443 msg = "access zero";
1447 exception = &storage_error;
1448 msg = "stack overflow (or erroneous memory access)";
1453 exception = &storage_error;
1454 msg = "stack overflow";
1459 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1462 exception = &constraint_error;
1463 msg = "arithmetic error";
1473 /* Scan the DEC Ada exception condition table for a match and fetch the
1474 associated GNAT exception pointer */
1476 dec_ada_cond_except_table [i].cond &&
1477 !LIB$MATCH_COND (&sigargs [1], &dec_ada_cond_except_table [i].cond);
1479 exception = (struct Exception_Data *) dec_ada_cond_except_table [i].except;
1482 /* DEC Ada exceptions never have a PC and PSL appended, but LIB$STOP
1483 (which is how we got here from Bliss code)
1484 allows slots for them and the result is 2 words of garbage on the
1485 end, so the count must be decremented. */
1489 /* Scan the VMS standard condition table for a match and fetch the
1490 associated GNAT exception pointer */
1492 cond_except_table [i].cond &&
1493 !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1495 exception =(struct Exception_Data *) cond_except_table [i].except;
1498 /* User programs expect Non_Ada_Error to be raised, reference
1499 DEC Ada test CXCONDHAN. */
1500 exception = &Non_Ada_Error;
1504 exception = &program_error;
1507 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1512 mstate = (long *) (*Get_Machine_State_Addr) ();
1515 lib_get_curr_invo_context (&curr_icb);
1516 lib_get_prev_invo_context (&curr_icb);
1517 lib_get_prev_invo_context (&curr_icb);
1518 curr_invo_handle = lib_get_invo_handle (&curr_icb);
1519 *mstate = curr_invo_handle;
1521 Raise_From_Signal_Handler (exception, msg);
1525 __gnat_install_handler (void)
1528 #if defined (IN_RTS) && !defined (__IA64)
1531 c = (char *) xmalloc (2049);
1533 __gnat_error_prehandler_stack = &c[2048];
1535 /* __gnat_error_prehandler is an assembly function. */
1536 SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1538 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1541 __gnat_handler_installed = 1;
1544 /*******************/
1545 /* FreeBSD Section */
1546 /*******************/
1548 #elif defined (__FreeBSD__)
1553 static void __gnat_error_handler (int, int, struct sigcontext *);
1556 __gnat_error_handler (int sig, int code __attribute__ ((unused)),
1557 struct sigcontext *sc __attribute__ ((unused)))
1559 struct Exception_Data *exception;
1565 exception = &constraint_error;
1570 exception = &constraint_error;
1575 exception = &storage_error;
1576 msg = "stack overflow or erroneous memory access";
1580 exception = &constraint_error;
1585 exception = &program_error;
1586 msg = "unhandled signal";
1589 Raise_From_Signal_Handler (exception, msg);
1593 __gnat_install_handler ()
1595 struct sigaction act;
1597 /* Set up signal handler to map synchronous signals to appropriate
1598 exceptions. Make sure that the handler isn't interrupted by another
1599 signal that might cause a scheduling event! */
1601 act.sa_handler = __gnat_error_handler;
1602 act.sa_flags = SA_NODEFER | SA_RESTART;
1603 (void) sigemptyset (&act.sa_mask);
1605 (void) sigaction (SIGILL, &act, NULL);
1606 (void) sigaction (SIGFPE, &act, NULL);
1607 (void) sigaction (SIGSEGV, &act, NULL);
1608 (void) sigaction (SIGBUS, &act, NULL);
1610 __gnat_handler_installed = 1;
1613 /*******************/
1614 /* VxWorks Section */
1615 /*******************/
1617 #elif defined(__vxworks)
1620 #include <taskLib.h>
1625 #include "private/vThreadsP.h"
1628 extern int __gnat_inum_to_ivec (int);
1629 static void __gnat_error_handler (int, int, struct sigcontext *);
1630 void __gnat_map_signal (int);
1632 #ifndef __alpha_vxworks
1634 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1637 extern long getpid (void);
1642 return taskIdSelf ();
1646 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1648 __gnat_inum_to_ivec (int num)
1650 return INUM_TO_IVEC (num);
1653 /* VxWorks expects the field excCnt to be zeroed when a signal is handled.
1654 The VxWorks version of longjmp does this; gcc's builtin_longjmp does not */
1656 __gnat_clear_exception_count (void)
1659 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1661 currentTask->vThreads.excCnt = 0;
1665 /* Exported to 5zintman.adb in order to handle different signal
1666 to exception mappings in different VxWorks versions */
1668 __gnat_map_signal (int sig)
1670 struct Exception_Data *exception;
1676 exception = &constraint_error;
1681 exception = &constraint_error;
1682 msg = "Floating point exception or SIGILL";
1685 exception = &storage_error;
1686 msg = "SIGSEGV: possible stack overflow";
1689 exception = &storage_error;
1690 msg = "SIGBUS: possible stack overflow";
1694 exception = &constraint_error;
1698 exception = &program_error;
1702 exception = &program_error;
1707 exception = &program_error;
1708 msg = "unhandled signal";
1711 __gnat_clear_exception_count ();
1712 Raise_From_Signal_Handler (exception, msg);
1716 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1721 /* VxWorks will always mask out the signal during the signal handler and
1722 will reenable it on a longjmp. GNAT does not generate a longjmp to
1723 return from a signal handler so the signal will still be masked unless
1725 sigprocmask (SIG_SETMASK, NULL, &mask);
1726 sigdelset (&mask, sig);
1727 sigprocmask (SIG_SETMASK, &mask, NULL);
1729 __gnat_map_signal (sig);
1734 __gnat_install_handler (void)
1736 struct sigaction act;
1738 /* Setup signal handler to map synchronous signals to appropriate
1739 exceptions. Make sure that the handler isn't interrupted by another
1740 signal that might cause a scheduling event! */
1742 act.sa_handler = __gnat_error_handler;
1743 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1744 sigemptyset (&act.sa_mask);
1746 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1747 applies to vectored hardware interrupts, not signals */
1748 sigaction (SIGFPE, &act, NULL);
1749 sigaction (SIGILL, &act, NULL);
1750 sigaction (SIGSEGV, &act, NULL);
1751 sigaction (SIGBUS, &act, NULL);
1753 __gnat_handler_installed = 1;
1756 #define HAVE_GNAT_INIT_FLOAT
1759 __gnat_init_float (void)
1761 /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1762 to get correct Ada semantics. Note that for AE653 vThreads, the HW
1763 overflow settings are an OS configuration issue. The instructions
1764 below have no effect */
1765 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1770 /* Similarly for sparc64. Achieved by masking bits in the Trap Enable Mask
1771 field of the Floating-point Status Register (see the Sparc Architecture
1772 Manual Version 9, p 48). */
1773 #if defined (sparc64)
1775 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1776 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1777 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1778 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1779 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1783 __asm__("st %%fsr, %0" : "=m" (fsr));
1784 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1785 __asm__("ld %0, %%fsr" : : "m" (fsr));
1790 /******************/
1791 /* NetBSD Section */
1792 /******************/
1794 #elif defined(__NetBSD__)
1800 __gnat_error_handler (int sig)
1802 struct Exception_Data *exception;
1808 exception = &constraint_error;
1812 exception = &constraint_error;
1816 exception = &storage_error;
1817 msg = "stack overflow or erroneous memory access";
1820 exception = &constraint_error;
1824 exception = &program_error;
1825 msg = "unhandled signal";
1828 Raise_From_Signal_Handler(exception, msg);
1832 __gnat_install_handler(void)
1834 struct sigaction act;
1836 act.sa_handler = __gnat_error_handler;
1837 act.sa_flags = SA_NODEFER | SA_RESTART;
1838 sigemptyset (&act.sa_mask);
1840 /* Do not install handlers if interrupt state is "System" */
1841 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1842 sigaction (SIGFPE, &act, NULL);
1843 if (__gnat_get_interrupt_state (SIGILL) != 's')
1844 sigaction (SIGILL, &act, NULL);
1845 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1846 sigaction (SIGSEGV, &act, NULL);
1847 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1848 sigaction (SIGBUS, &act, NULL);
1850 __gnat_handler_installed = 1;
1855 /* For all other versions of GNAT, the handler does nothing */
1857 /*******************/
1858 /* Default Section */
1859 /*******************/
1862 __gnat_install_handler (void)
1864 __gnat_handler_installed = 1;
1869 /*********************/
1870 /* __gnat_init_float */
1871 /*********************/
1873 /* This routine is called as each process thread is created, for possible
1874 initialization of the FP processor. This version is used under INTERIX,
1875 WIN32 and could be used under OS/2 */
1877 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1878 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1880 #define HAVE_GNAT_INIT_FLOAT
1883 __gnat_init_float (void)
1885 #if defined (__i386__) || defined (i386)
1887 /* This is used to properly initialize the FPU on an x86 for each
1892 #endif /* Defined __i386__ */
1896 #ifndef HAVE_GNAT_INIT_FLOAT
1898 /* All targets without a specific __gnat_init_float will use an empty one */
1900 __gnat_init_float (void)
1905 /***********************************/
1906 /* __gnat_adjust_context_for_raise */
1907 /***********************************/
1909 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1911 /* All targets without a specific version will use an empty one */
1913 /* UCONTEXT is a pointer to a context structure received by a signal handler
1914 about to propagate an exception. Adjust it to compensate the fact that the
1915 generic unwinder thinks the corresponding PC is a call return address. */
1918 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
1919 void *ucontext ATTRIBUTE_UNUSED)
1921 /* The point is that the interrupted context PC typically is the address
1922 that we should search an EH region for, which is different from the call
1923 return address case. The target independent part of the GCC unwinder
1924 don't differentiate the two situations, so we compensate here for the
1925 adjustments it will blindly make.
1927 signo is passed because on some targets for some signals the PC in
1928 context points to the instruction after the faulting one, in which case
1929 the unwinder adjustment is still desired. */
1931 /* On a number of targets, we have arranged for the adjustment to be
1932 performed by the MD_FALLBACK_FRAME_STATE circuitry, so we don't provide a
1933 specific instance of this routine. The MD_FALLBACK doesn't have access
1934 to the signal number, though, so the compensation is systematic there and
1935 might be wrong in some cases. */
1937 /* Having the compensation wrong leads to potential failures. A very
1938 typical case is what happens when there is no compensation and a signal
1939 triggers for the first instruction in a region : the unwinder adjustment
1940 has it search in the wrong EH region. */