1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2007, 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,
43 s-init-ae653-cert.adb and s-init-xi-sparc.adb. All these files implement
44 the required functionality for different targets. */
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. Tasking_Error
70 is not used in this unit, and the abort signal is only used on IRIX. */
71 extern struct Exception_Data constraint_error;
72 extern struct Exception_Data numeric_error;
73 extern struct Exception_Data program_error;
74 extern struct Exception_Data storage_error;
76 /* For the Cert run time we use the regular raise exception routine because
77 Raise_From_Signal_Handler is not available. */
79 #define Raise_From_Signal_Handler \
80 __gnat_raise_exception
81 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
83 #define Raise_From_Signal_Handler \
84 ada__exceptions__raise_from_signal_handler
85 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
88 /* Global values computed by the binder */
89 int __gl_main_priority = -1;
90 int __gl_time_slice_val = -1;
91 char __gl_wc_encoding = 'n';
92 char __gl_locking_policy = ' ';
93 char __gl_queuing_policy = ' ';
94 char __gl_task_dispatching_policy = ' ';
95 char *__gl_priority_specific_dispatching = 0;
96 int __gl_num_specific_dispatching = 0;
97 char *__gl_interrupt_states = 0;
98 int __gl_num_interrupt_states = 0;
99 int __gl_unreserve_all_interrupts = 0;
100 int __gl_exception_tracebacks = 0;
101 int __gl_zero_cost_exceptions = 0;
102 int __gl_detect_blocking = 0;
103 int __gl_default_stack_size = -1;
105 /* Indication of whether synchronous signal handler has already been
106 installed by a previous call to adainit */
107 int __gnat_handler_installed = 0;
110 int __gnat_inside_elab_final_code = 0;
111 /* ??? This variable is obsolete since 2001-08-29 but is kept to allow
112 bootstrap from old GNAT versions (< 3.15). */
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 (int intrup)
139 if (intrup >= __gl_num_interrupt_states)
142 return __gl_interrupt_states [intrup];
145 /***********************************/
146 /* __gnat_get_specific_dispatching */
147 /***********************************/
149 char __gnat_get_specific_dispatching (int);
151 /* This routine is called from the run time as needed to determine the
152 priority specific dispatching policy, as set by a
153 Priority_Specific_Dispatching pragma appearing anywhere in the current
154 partition. The input argument is the priority number, and the result is
155 the upper case first character of the policy name, e.g. 'F' for
156 FIFO_Within_Priorities. A space ' ' is returned if no
157 Priority_Specific_Dispatching pragma is used in the partition. */
160 __gnat_get_specific_dispatching (int priority)
162 if (__gl_num_specific_dispatching == 0)
164 else if (priority >= __gl_num_specific_dispatching)
167 return __gl_priority_specific_dispatching [priority];
172 /**********************/
173 /* __gnat_set_globals */
174 /**********************/
176 /* This routine is kept for boostrapping purposes, since the binder generated
177 file now sets the __gl_* variables directly. */
180 __gnat_set_globals ()
193 #include <sys/time.h>
195 /* Some versions of AIX don't define SA_NODEFER. */
199 #endif /* SA_NODEFER */
201 /* Versions of AIX before 4.3 don't have nanosleep but provide
204 #ifndef _AIXVERSION_430
206 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
209 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
211 return nsleep (Rqtp, Rmtp);
214 #endif /* _AIXVERSION_430 */
216 static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
218 /* __gnat_adjust_context_for_raise - see comments along with the default
219 version later in this file. */
222 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
224 /* We need to adjust the "Instruction Address Register" value, part of a
225 'struct mstsave' wrapped as a jumpbuf in the mcontext field designated by
226 the signal data pointer we get. See sys/context.h + sys/mstsave.h */
228 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
229 mcontext->jmp_context.iar++;
232 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
235 __gnat_error_handler (int sig, siginfo_t * si, void * uc)
237 struct Exception_Data *exception;
243 /* FIXME: we need to detect the case of a *real* SIGSEGV */
244 exception = &storage_error;
245 msg = "stack overflow or erroneous memory access";
249 exception = &constraint_error;
254 exception = &constraint_error;
259 exception = &program_error;
260 msg = "unhandled signal";
263 __gnat_adjust_context_for_raise (sig, uc);
264 Raise_From_Signal_Handler (exception, msg);
268 __gnat_install_handler (void)
270 struct sigaction act;
272 /* Set up signal handler to map synchronous signals to appropriate
273 exceptions. Make sure that the handler isn't interrupted by another
274 signal that might cause a scheduling event! */
276 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
277 act.sa_sigaction = __gnat_error_handler;
278 sigemptyset (&act.sa_mask);
280 /* Do not install handlers if interrupt state is "System" */
281 if (__gnat_get_interrupt_state (SIGABRT) != 's')
282 sigaction (SIGABRT, &act, NULL);
283 if (__gnat_get_interrupt_state (SIGFPE) != 's')
284 sigaction (SIGFPE, &act, NULL);
285 if (__gnat_get_interrupt_state (SIGILL) != 's')
286 sigaction (SIGILL, &act, NULL);
287 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
288 sigaction (SIGSEGV, &act, NULL);
289 if (__gnat_get_interrupt_state (SIGBUS) != 's')
290 sigaction (SIGBUS, &act, NULL);
292 __gnat_handler_installed = 1;
299 #elif defined(__alpha__) && defined(__osf__)
302 #include <sys/siginfo.h>
304 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
305 extern char *__gnat_get_code_loc (struct sigcontext *);
306 extern void __gnat_set_code_loc (struct sigcontext *, char *);
307 extern size_t __gnat_machine_state_length (void);
309 /* __gnat_adjust_context_for_raise - see comments along with the default
310 version later in this file. */
312 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
315 __gnat_adjust_context_for_raise (int signo, void *context)
317 struct sigcontext * sigcontext = (struct sigcontext *) context;
319 /* The fallback code fetches the faulting insn address from sc_pc, so
320 adjust that when need be. For SIGFPE, the required adjustment depends
321 on the trap shadow situation (see man ieee). */
324 /* ??? We never adjust here, considering that sc_pc always
325 designates the instruction following the one which trapped.
326 This is not necessarily true but corresponds to what we have
330 sigcontext->sc_pc ++;
335 (int sig, siginfo_t *sip, struct sigcontext *context)
337 struct Exception_Data *exception;
338 static int recurse = 0;
341 /* Adjusting is required for every fault context, so adjust for this one
342 now, before we possibly trigger a recursive fault below. */
343 __gnat_adjust_context_for_raise (sig, context);
345 /* If this was an explicit signal from a "kill", just resignal it. */
346 if (SI_FROMUSER (sip))
348 signal (sig, SIG_DFL);
349 kill (getpid(), sig);
352 /* Otherwise, treat it as something we handle. */
356 /* If the problem was permissions, this is a constraint error.
357 Likewise if the failing address isn't maximally aligned or if
360 ??? Using a static variable here isn't task-safe, but it's
361 much too hard to do anything else and we're just determining
362 which exception to raise. */
363 if (sip->si_code == SEGV_ACCERR
364 || (((long) sip->si_addr) & 3) != 0
367 exception = &constraint_error;
372 /* See if the page before the faulting page is accessible. Do that
373 by trying to access it. We'd like to simply try to access
374 4096 + the faulting address, but it's not guaranteed to be
375 the actual address, just to be on the same page. */
378 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
379 msg = "stack overflow (or erroneous memory access)";
380 exception = &storage_error;
385 exception = &program_error;
390 exception = &constraint_error;
395 exception = &program_error;
396 msg = "unhandled signal";
400 Raise_From_Signal_Handler (exception, (char *) msg);
404 __gnat_install_handler (void)
406 struct sigaction act;
408 /* Setup signal handler to map synchronous signals to appropriate
409 exceptions. Make sure that the handler isn't interrupted by another
410 signal that might cause a scheduling event! */
412 act.sa_handler = (void (*) (int)) __gnat_error_handler;
413 act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
414 sigemptyset (&act.sa_mask);
416 /* Do not install handlers if interrupt state is "System" */
417 if (__gnat_get_interrupt_state (SIGABRT) != 's')
418 sigaction (SIGABRT, &act, NULL);
419 if (__gnat_get_interrupt_state (SIGFPE) != 's')
420 sigaction (SIGFPE, &act, NULL);
421 if (__gnat_get_interrupt_state (SIGILL) != 's')
422 sigaction (SIGILL, &act, NULL);
423 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
424 sigaction (SIGSEGV, &act, NULL);
425 if (__gnat_get_interrupt_state (SIGBUS) != 's')
426 sigaction (SIGBUS, &act, NULL);
428 __gnat_handler_installed = 1;
431 /* Routines called by s-mastop-tru64.adb. */
436 __gnat_get_code_loc (struct sigcontext *context)
438 return (char *) context->sc_pc;
442 __gnat_set_code_loc (struct sigcontext *context, char *pc)
444 context->sc_pc = (long) pc;
449 __gnat_machine_state_length (void)
451 return sizeof (struct sigcontext);
458 #elif defined (__hpux__)
461 #include <sys/ucontext.h>
464 __gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext);
466 #if defined (__hppa__)
468 /* __gnat_adjust_context_for_raise - see comments along with the default
469 version later in this file. */
471 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
474 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
476 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
478 if (UseWideRegs (mcontext))
479 mcontext->ss_wide.ss_32.ss_pcoq_head_lo ++;
481 mcontext->ss_narrow.ss_pcoq_head ++;
488 (int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED, void *ucontext)
490 struct Exception_Data *exception;
496 /* FIXME: we need to detect the case of a *real* SIGSEGV */
497 exception = &storage_error;
498 msg = "stack overflow or erroneous memory access";
502 exception = &constraint_error;
507 exception = &constraint_error;
512 exception = &program_error;
513 msg = "unhandled signal";
516 __gnat_adjust_context_for_raise (sig, ucontext);
518 Raise_From_Signal_Handler (exception, msg);
522 __gnat_install_handler (void)
524 struct sigaction act;
526 /* Set up signal handler to map synchronous signals to appropriate
527 exceptions. Make sure that the handler isn't interrupted by another
528 signal that might cause a scheduling event! Also setup an alternate
529 stack region for the handler execution so that stack overflows can be
530 handled properly, avoiding a SEGV generation from stack usage by the
533 static char handler_stack[SIGSTKSZ*2];
534 /* SIGSTKSZ appeared to be "short" for the needs in some contexts
535 (e.g. experiments with GCC ZCX exceptions). */
539 stack.ss_sp = handler_stack;
540 stack.ss_size = sizeof (handler_stack);
543 sigaltstack (&stack, NULL);
545 act.sa_sigaction = __gnat_error_handler;
546 act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK | SA_SIGINFO;
547 sigemptyset (&act.sa_mask);
549 /* Do not install handlers if interrupt state is "System" */
550 if (__gnat_get_interrupt_state (SIGABRT) != 's')
551 sigaction (SIGABRT, &act, NULL);
552 if (__gnat_get_interrupt_state (SIGFPE) != 's')
553 sigaction (SIGFPE, &act, NULL);
554 if (__gnat_get_interrupt_state (SIGILL) != 's')
555 sigaction (SIGILL, &act, NULL);
556 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
557 sigaction (SIGSEGV, &act, NULL);
558 if (__gnat_get_interrupt_state (SIGBUS) != 's')
559 sigaction (SIGBUS, &act, NULL);
561 __gnat_handler_installed = 1;
564 /*********************/
565 /* GNU/Linux Section */
566 /*********************/
568 #elif defined (linux) && (defined (i386) || defined (__x86_64__) \
569 || defined (__ia64__))
573 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
574 #include <sys/ucontext.h>
576 /* GNU/Linux, which uses glibc, does not define NULL in included
580 #define NULL ((void *) 0)
585 /* MaRTE OS provides its own version of sigaction, sigfillset, and
586 sigemptyset (overriding these symbol names). We want to make sure that
587 the versions provided by the underlying C library are used here (these
588 versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
589 and fake_linux_sigemptyset, respectively). The MaRTE library will not
590 always be present (it will not be linked if no tasking constructs are
591 used), so we use the weak symbol mechanism to point always to the symbols
592 defined within the C library. */
594 #pragma weak linux_sigaction
595 int linux_sigaction (int signum, const struct sigaction *act,
596 struct sigaction *oldact) {
597 return sigaction (signum, act, oldact);
599 #define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
601 #pragma weak fake_linux_sigfillset
602 void fake_linux_sigfillset (sigset_t *set) {
605 #define sigfillset(set) fake_linux_sigfillset (set)
607 #pragma weak fake_linux_sigemptyset
608 void fake_linux_sigemptyset (sigset_t *set) {
611 #define sigemptyset(set) fake_linux_sigemptyset (set)
615 static void __gnat_error_handler (int, siginfo_t *siginfo, void *ucontext);
617 /* __gnat_adjust_context_for_raise - see comments along with the default
618 version later in this file. */
620 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
623 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
625 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
628 mcontext->gregs[REG_EIP]++;
629 #elif defined (__x86_64__)
630 mcontext->gregs[REG_RIP]++;
631 #elif defined (__ia64__)
637 __gnat_error_handler (int sig,
638 siginfo_t *siginfo ATTRIBUTE_UNUSED,
641 struct Exception_Data *exception;
643 static int recurse = 0;
648 /* If the problem was permissions, this is a constraint error.
649 Likewise if the failing address isn't maximally aligned or if
652 ??? Using a static variable here isn't task-safe, but it's
653 much too hard to do anything else and we're just determining
654 which exception to raise. */
657 exception = &constraint_error;
662 /* Here we would like a discrimination test to see whether the
663 page before the faulting address is accessible. Unfortunately
664 Linux seems to have no way of giving us the faulting address.
666 In versions of a-init.c before 1.95, we had a test of the page
667 before the stack pointer using:
671 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
673 but that's wrong, since it tests the stack pointer location, and
674 the current stack probe code does not move the stack pointer
675 until all probes succeed.
677 For now we simply do not attempt any discrimination at all. Note
678 that this is quite acceptable, since a "real" SIGSEGV can only
679 occur as the result of an erroneous program */
681 msg = "stack overflow (or erroneous memory access)";
682 exception = &storage_error;
687 exception = &constraint_error;
692 exception = &constraint_error;
697 exception = &program_error;
698 msg = "unhandled signal";
702 /* We adjust the interrupted context here (and not in the
703 MD_FALLBACK_FRAME_STATE_FOR macro) because recent versions of the Native
704 POSIX Thread Library (NPTL) are compiled with DWARF 2 unwind information,
705 and hence the later macro is never executed for signal frames. */
707 __gnat_adjust_context_for_raise (sig, ucontext);
709 Raise_From_Signal_Handler (exception, msg);
713 __gnat_install_handler (void)
715 struct sigaction act;
717 /* Set up signal handler to map synchronous signals to appropriate
718 exceptions. Make sure that the handler isn't interrupted by another
719 signal that might cause a scheduling event! */
721 act.sa_sigaction = __gnat_error_handler;
722 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
723 sigemptyset (&act.sa_mask);
725 /* Do not install handlers if interrupt state is "System" */
726 if (__gnat_get_interrupt_state (SIGABRT) != 's')
727 sigaction (SIGABRT, &act, NULL);
728 if (__gnat_get_interrupt_state (SIGFPE) != 's')
729 sigaction (SIGFPE, &act, NULL);
730 if (__gnat_get_interrupt_state (SIGILL) != 's')
731 sigaction (SIGILL, &act, NULL);
732 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
733 sigaction (SIGSEGV, &act, NULL);
734 if (__gnat_get_interrupt_state (SIGBUS) != 's')
735 sigaction (SIGBUS, &act, NULL);
737 __gnat_handler_installed = 1;
740 /*******************/
741 /* Interix Section */
742 /*******************/
744 #elif defined (__INTERIX)
748 static void __gnat_error_handler (int);
751 __gnat_error_handler (int sig)
753 struct Exception_Data *exception;
759 exception = &storage_error;
760 msg = "stack overflow or erroneous memory access";
764 exception = &constraint_error;
769 exception = &constraint_error;
774 exception = &program_error;
775 msg = "unhandled signal";
778 Raise_From_Signal_Handler (exception, msg);
782 __gnat_install_handler (void)
784 struct sigaction act;
786 /* Set up signal handler to map synchronous signals to appropriate
787 exceptions. Make sure that the handler isn't interrupted by another
788 signal that might cause a scheduling event! */
790 act.sa_handler = __gnat_error_handler;
792 sigemptyset (&act.sa_mask);
794 /* Handlers for signals besides SIGSEGV cause c974013 to hang */
795 /* sigaction (SIGILL, &act, NULL); */
796 /* sigaction (SIGABRT, &act, NULL); */
797 /* sigaction (SIGFPE, &act, NULL); */
798 /* sigaction (SIGBUS, &act, NULL); */
800 /* Do not install handlers if interrupt state is "System" */
801 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
802 sigaction (SIGSEGV, &act, NULL);
804 __gnat_handler_installed = 1;
820 #define SIGADAABORT 48
821 #define SIGNAL_STACK_SIZE 4096
822 #define SIGNAL_STACK_ALIGNMENT 64
824 #define Check_Abort_Status \
825 system__soft_links__check_abort_status
826 extern int (*Check_Abort_Status) (void);
828 extern struct Exception_Data _abort_signal;
830 static void __gnat_error_handler (int, int, sigcontext_t *);
832 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
833 connecting that handler, with the effects described in the sigaction
837 If cleared and the signal is caught, the first argument is
838 also the signal number but the second argument is the signal
839 code identifying the cause of the signal. The third argument
840 points to a sigcontext_t structure containing the receiving
841 process's context when the signal was delivered.
845 __gnat_error_handler (int sig, int code, sigcontext_t *sc ATTRIBUTE_UNUSED)
847 struct Exception_Data *exception;
855 exception = &program_error;
856 msg = "SIGSEGV: (Invalid virtual address)";
858 else if (code == ENXIO)
860 exception = &program_error;
861 msg = "SIGSEGV: (Read beyond mapped object)";
863 else if (code == ENOSPC)
865 exception = &program_error; /* ??? storage_error ??? */
866 msg = "SIGSEGV: (Autogrow for file failed)";
868 else if (code == EACCES || code == EEXIST)
870 /* ??? We handle stack overflows here, some of which do trigger
871 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
872 the documented valid codes for SEGV in the signal(5) man
875 /* ??? Re-add smarts to further verify that we launched
876 the stack into a guard page, not an attempt to
877 write to .text or something */
878 exception = &storage_error;
879 msg = "SIGSEGV: (stack overflow or erroneous memory access)";
883 /* Just in case the OS guys did it to us again. Sometimes
884 they fail to document all of the valid codes that are
885 passed to signal handlers, just in case someone depends
886 on knowing all the codes */
887 exception = &program_error;
888 msg = "SIGSEGV: (Undocumented reason)";
893 /* Map all bus errors to Program_Error. */
894 exception = &program_error;
899 /* Map all fpe errors to Constraint_Error. */
900 exception = &constraint_error;
905 if ((*Check_Abort_Status) ())
907 exception = &_abort_signal;
916 /* Everything else is a Program_Error. */
917 exception = &program_error;
918 msg = "unhandled signal";
921 Raise_From_Signal_Handler (exception, msg);
925 __gnat_install_handler (void)
927 struct sigaction act;
929 /* Setup signal handler to map synchronous signals to appropriate
930 exceptions. Make sure that the handler isn't interrupted by another
931 signal that might cause a scheduling event! */
933 act.sa_handler = __gnat_error_handler;
934 act.sa_flags = SA_NODEFER + SA_RESTART;
935 sigfillset (&act.sa_mask);
936 sigemptyset (&act.sa_mask);
938 /* Do not install handlers if interrupt state is "System" */
939 if (__gnat_get_interrupt_state (SIGABRT) != 's')
940 sigaction (SIGABRT, &act, NULL);
941 if (__gnat_get_interrupt_state (SIGFPE) != 's')
942 sigaction (SIGFPE, &act, NULL);
943 if (__gnat_get_interrupt_state (SIGILL) != 's')
944 sigaction (SIGILL, &act, NULL);
945 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
946 sigaction (SIGSEGV, &act, NULL);
947 if (__gnat_get_interrupt_state (SIGBUS) != 's')
948 sigaction (SIGBUS, &act, NULL);
949 if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
950 sigaction (SIGADAABORT, &act, NULL);
952 __gnat_handler_installed = 1;
955 /*******************/
956 /* Solaris Section */
957 /*******************/
959 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
963 #include <sys/ucontext.h>
964 #include <sys/regset.h>
966 /* The code below is common to sparc and x86. Beware of the delay slot
967 differences for signal context adjustments. */
969 #if defined (__sparc)
970 #define RETURN_ADDR_OFFSET 8
972 #define RETURN_ADDR_OFFSET 0
975 /* Likewise regarding how the "instruction pointer" register slot can
976 be identified in signal machine contexts. We have either "REG_PC"
977 or "PC" at hand, depending on the target CPU and solaris version. */
979 #if !defined (REG_PC)
983 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
985 /* __gnat_adjust_context_for_raise - see comments along with the default
986 version later in this file. */
988 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
991 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
994 mcontext_t *mcontext = & ((ucontext_t *)ucontext)->uc_mcontext;
995 mcontext->gregs[REG_PC] += (1 - RETURN_ADDR_OFFSET);
999 __gnat_error_handler (int sig, siginfo_t *sip, ucontext_t *uctx)
1001 struct Exception_Data *exception;
1002 static int recurse = 0;
1005 /* Adjusting is required for every fault context, so adjust for this one
1006 now, before we possibly trigger a recursive fault below. */
1007 __gnat_adjust_context_for_raise (sig, (void *)uctx);
1009 /* If this was an explicit signal from a "kill", just resignal it. */
1010 if (SI_FROMUSER (sip))
1012 signal (sig, SIG_DFL);
1013 kill (getpid(), sig);
1016 /* Otherwise, treat it as something we handle. */
1020 /* If the problem was permissions, this is a constraint error.
1021 Likewise if the failing address isn't maximally aligned or if
1024 ??? Using a static variable here isn't task-safe, but it's
1025 much too hard to do anything else and we're just determining
1026 which exception to raise. */
1027 if (sip->si_code == SEGV_ACCERR
1028 || (((long) sip->si_addr) & 3) != 0
1031 exception = &constraint_error;
1036 /* See if the page before the faulting page is accessible. Do that
1037 by trying to access it. We'd like to simply try to access
1038 4096 + the faulting address, but it's not guaranteed to be
1039 the actual address, just to be on the same page. */
1042 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1043 exception = &storage_error;
1044 msg = "stack overflow (or erroneous memory access)";
1049 exception = &program_error;
1054 exception = &constraint_error;
1059 exception = &program_error;
1060 msg = "unhandled signal";
1065 Raise_From_Signal_Handler (exception, msg);
1069 __gnat_install_handler (void)
1071 struct sigaction act;
1073 /* Set up signal handler to map synchronous signals to appropriate
1074 exceptions. Make sure that the handler isn't interrupted by another
1075 signal that might cause a scheduling event! */
1077 act.sa_handler = __gnat_error_handler;
1078 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1079 sigemptyset (&act.sa_mask);
1081 /* Do not install handlers if interrupt state is "System" */
1082 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1083 sigaction (SIGABRT, &act, NULL);
1084 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1085 sigaction (SIGFPE, &act, NULL);
1086 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1087 sigaction (SIGSEGV, &act, NULL);
1088 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1089 sigaction (SIGBUS, &act, NULL);
1091 __gnat_handler_installed = 1;
1100 long __gnat_error_handler (int *, void *);
1103 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1104 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1105 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1107 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1108 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1109 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1112 #if defined (IN_RTS) && !defined (__IA64)
1114 /* The prehandler actually gets control first on a condition. It swaps the
1115 stack pointer and calls the handler (__gnat_error_handler). */
1116 extern long __gnat_error_prehandler (void);
1118 extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
1121 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1122 Most of these are also defined in the header file ssdef.h which has not
1123 yet been converted to be recognized by Gnu C. */
1125 /* Defining these as macros, as opposed to external addresses, allows
1126 them to be used in a case statement (below */
1127 #define SS$_ACCVIO 12
1128 #define SS$_HPARITH 1284
1129 #define SS$_STKOVF 1364
1130 #define SS$_RESIGNAL 2328
1132 /* These codes are in standard message libraries */
1133 extern int CMA$_EXIT_THREAD;
1134 extern int SS$_DEBUG;
1135 extern int SS$_INTDIV;
1136 extern int LIB$_KEYNOTFOU;
1137 extern int LIB$_ACTIMAGE;
1138 extern int MTH$_FLOOVEMAT; /* Some ACVC_21 CXA tests */
1140 /* These codes are non standard, which is to say the author is
1141 not sure if they are defined in the standard message libraries
1142 so keep them as macros for now. */
1143 #define RDB$_STREAM_EOF 20480426
1144 #define FDL$_UNPRIKW 11829410
1146 struct cond_except {
1148 const struct Exception_Data *except;
1151 struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1153 /* Conditions that don't have an Ada exception counterpart must raise
1154 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1155 referenced by user programs, not the compiler or tools. Hence the
1160 #define Status_Error ada__io_exceptions__status_error
1161 extern struct Exception_Data Status_Error;
1163 #define Mode_Error ada__io_exceptions__mode_error
1164 extern struct Exception_Data Mode_Error;
1166 #define Name_Error ada__io_exceptions__name_error
1167 extern struct Exception_Data Name_Error;
1169 #define Use_Error ada__io_exceptions__use_error
1170 extern struct Exception_Data Use_Error;
1172 #define Device_Error ada__io_exceptions__device_error
1173 extern struct Exception_Data Device_Error;
1175 #define End_Error ada__io_exceptions__end_error
1176 extern struct Exception_Data End_Error;
1178 #define Data_Error ada__io_exceptions__data_error
1179 extern struct Exception_Data Data_Error;
1181 #define Layout_Error ada__io_exceptions__layout_error
1182 extern struct Exception_Data Layout_Error;
1184 #define Non_Ada_Error system__aux_dec__non_ada_error
1185 extern struct Exception_Data Non_Ada_Error;
1187 #define Coded_Exception system__vms_exception_table__coded_exception
1188 extern struct Exception_Data *Coded_Exception (Exception_Code);
1190 #define Base_Code_In system__vms_exception_table__base_code_in
1191 extern Exception_Code Base_Code_In (Exception_Code);
1193 /* DEC Ada exceptions are not defined in a header file, so they
1194 must be declared as external addresses */
1196 extern int ADA$_PROGRAM_ERROR;
1197 extern int ADA$_LOCK_ERROR;
1198 extern int ADA$_EXISTENCE_ERROR;
1199 extern int ADA$_KEY_ERROR;
1200 extern int ADA$_KEYSIZERR;
1201 extern int ADA$_STAOVF;
1202 extern int ADA$_CONSTRAINT_ERRO;
1203 extern int ADA$_IOSYSFAILED;
1204 extern int ADA$_LAYOUT_ERROR;
1205 extern int ADA$_STORAGE_ERROR;
1206 extern int ADA$_DATA_ERROR;
1207 extern int ADA$_DEVICE_ERROR;
1208 extern int ADA$_END_ERROR;
1209 extern int ADA$_MODE_ERROR;
1210 extern int ADA$_NAME_ERROR;
1211 extern int ADA$_STATUS_ERROR;
1212 extern int ADA$_NOT_OPEN;
1213 extern int ADA$_ALREADY_OPEN;
1214 extern int ADA$_USE_ERROR;
1215 extern int ADA$_UNSUPPORTED;
1216 extern int ADA$_FAC_MODE_MISMAT;
1217 extern int ADA$_ORG_MISMATCH;
1218 extern int ADA$_RFM_MISMATCH;
1219 extern int ADA$_RAT_MISMATCH;
1220 extern int ADA$_MRS_MISMATCH;
1221 extern int ADA$_MRN_MISMATCH;
1222 extern int ADA$_KEY_MISMATCH;
1223 extern int ADA$_MAXLINEXC;
1224 extern int ADA$_LINEXCMRS;
1226 /* DEC Ada specific conditions */
1227 static const struct cond_except dec_ada_cond_except_table [] = {
1228 {&ADA$_PROGRAM_ERROR, &program_error},
1229 {&ADA$_USE_ERROR, &Use_Error},
1230 {&ADA$_KEYSIZERR, &program_error},
1231 {&ADA$_STAOVF, &storage_error},
1232 {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1233 {&ADA$_IOSYSFAILED, &Device_Error},
1234 {&ADA$_LAYOUT_ERROR, &Layout_Error},
1235 {&ADA$_STORAGE_ERROR, &storage_error},
1236 {&ADA$_DATA_ERROR, &Data_Error},
1237 {&ADA$_DEVICE_ERROR, &Device_Error},
1238 {&ADA$_END_ERROR, &End_Error},
1239 {&ADA$_MODE_ERROR, &Mode_Error},
1240 {&ADA$_NAME_ERROR, &Name_Error},
1241 {&ADA$_STATUS_ERROR, &Status_Error},
1242 {&ADA$_NOT_OPEN, &Use_Error},
1243 {&ADA$_ALREADY_OPEN, &Use_Error},
1244 {&ADA$_USE_ERROR, &Use_Error},
1245 {&ADA$_UNSUPPORTED, &Use_Error},
1246 {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1247 {&ADA$_ORG_MISMATCH, &Use_Error},
1248 {&ADA$_RFM_MISMATCH, &Use_Error},
1249 {&ADA$_RAT_MISMATCH, &Use_Error},
1250 {&ADA$_MRS_MISMATCH, &Use_Error},
1251 {&ADA$_MRN_MISMATCH, &Use_Error},
1252 {&ADA$_KEY_MISMATCH, &Use_Error},
1253 {&ADA$_MAXLINEXC, &constraint_error},
1254 {&ADA$_LINEXCMRS, &constraint_error},
1259 /* Already handled by a pragma Import_Exception
1260 in Aux_IO_Exceptions */
1261 {&ADA$_LOCK_ERROR, &Lock_Error},
1262 {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1263 {&ADA$_KEY_ERROR, &Key_Error},
1268 /* Non DEC Ada specific conditions. We could probably also put
1269 SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
1270 static const struct cond_except cond_except_table [] = {
1271 {&MTH$_FLOOVEMAT, &constraint_error},
1272 {&SS$_INTDIV, &constraint_error},
1276 /* To deal with VMS conditions and their mapping to Ada exceptions,
1277 the __gnat_error_handler routine below is installed as an exception
1278 vector having precedence over DEC frame handlers. Some conditions
1279 still need to be handled by such handlers, however, in which case
1280 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
1281 instance the use of a third party library compiled with DECAda and
1282 performing it's own exception handling internally.
1284 To allow some user-level flexibility, which conditions should be
1285 resignaled is controlled by a predicate function, provided with the
1286 condition value and returning a boolean indication stating whether
1287 this condition should be resignaled or not.
1289 That predicate function is called indirectly, via a function pointer,
1290 by __gnat_error_handler, and changing that pointer is allowed to the
1291 the user code by way of the __gnat_set_resignal_predicate interface.
1293 The user level function may then implement what it likes, including
1294 for instance the maintenance of a dynamic data structure if the set
1295 of to be resignalled conditions has to change over the program's
1298 ??? This is not a perfect solution to deal with the possible
1299 interactions between the GNAT and the DECAda exception handling
1300 models and better (more general) schemes are studied. This is so
1301 just provided as a convenient workaround in the meantime, and
1302 should be use with caution since the implementation has been kept
1306 resignal_predicate (int code);
1308 const int *cond_resignal_table [] = {
1313 (int *) RDB$_STREAM_EOF,
1314 (int *) FDL$_UNPRIKW,
1318 const int facility_resignal_table [] = {
1319 0x1380000, /* RDB */
1320 0x2220000, /* SQL */
1324 /* Default GNAT predicate for resignaling conditions. */
1327 __gnat_default_resignal_p (int code)
1331 for (i = 0; facility_resignal_table [i]; i++)
1332 if ((code & 0xfff0000) == facility_resignal_table [i])
1335 for (i = 0, iexcept = 0;
1336 cond_resignal_table [i] &&
1337 !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1343 /* Static pointer to predicate that the __gnat_error_handler exception
1344 vector invokes to determine if it should resignal a condition. */
1346 static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1348 /* User interface to change the predicate pointer to PREDICATE. Reset to
1349 the default if PREDICATE is null. */
1352 __gnat_set_resignal_predicate (resignal_predicate * predicate)
1355 __gnat_resignal_p = __gnat_default_resignal_p;
1357 __gnat_resignal_p = predicate;
1360 /* Should match System.Parameters.Default_Exception_Msg_Max_Length */
1361 #define Default_Exception_Msg_Max_Length 512
1363 /* Action routine for SYS$PUTMSG. There may be
1364 multiple conditions, each with text to be appended to
1365 MESSAGE and separated by line termination. */
1368 copy_msg (msgdesc, message)
1369 struct descriptor_s *msgdesc;
1372 int len = strlen (message);
1375 /* Check for buffer overflow and skip */
1376 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1378 strcat (message, "\r\n");
1382 /* Check for buffer overflow and truncate if necessary */
1383 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1385 Default_Exception_Msg_Max_Length - 1 - len);
1386 strncpy (&message [len], msgdesc->adr, copy_len);
1387 message [len + copy_len] = 0;
1393 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1395 struct Exception_Data *exception = 0;
1396 Exception_Code base_code;
1397 struct descriptor_s gnat_facility = {4,0,"GNAT"};
1398 char message [Default_Exception_Msg_Max_Length];
1400 const char *msg = "";
1402 /* Check for conditions to resignal which aren't effected by pragma
1403 Import_Exception. */
1404 if (__gnat_resignal_p (sigargs [1]))
1405 return SS$_RESIGNAL;
1408 /* See if it's an imported exception. Beware that registered exceptions
1409 are bound to their base code, with the severity bits masked off. */
1410 base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1411 exception = Coded_Exception (base_code);
1417 /* Subtract PC & PSL fields which messes with PUTMSG */
1419 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1423 exception->Name_Length = 19;
1424 /* The full name really should be get sys$getmsg returns. ??? */
1425 exception->Full_Name = "IMPORTED_EXCEPTION";
1426 exception->Import_Code = base_code;
1429 /* Do not adjust the program counter as already points to the next
1430 instruction (just after the call to LIB$STOP). */
1431 Raise_From_Signal_Handler (exception, msg);
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)";
1450 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1454 exception = &storage_error;
1455 msg = "stack overflow";
1456 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1461 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1463 exception = &constraint_error;
1464 msg = "arithmetic error";
1465 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1474 /* Scan the DEC Ada exception condition table for a match and fetch
1475 the associated GNAT exception pointer */
1477 dec_ada_cond_except_table [i].cond &&
1478 !LIB$MATCH_COND (&sigargs [1],
1479 &dec_ada_cond_except_table [i].cond);
1481 exception = (struct Exception_Data *)
1482 dec_ada_cond_except_table [i].except;
1486 /* Scan the VMS standard condition table for a match and fetch
1487 the associated GNAT exception pointer */
1489 cond_except_table [i].cond &&
1490 !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1492 exception = (struct Exception_Data *)
1493 cond_except_table [i].except;
1496 /* User programs expect Non_Ada_Error to be raised, reference
1497 DEC Ada test CXCONDHAN. */
1498 exception = &Non_Ada_Error;
1502 exception = &program_error;
1505 /* Subtract PC & PSL fields which messes with PUTMSG */
1507 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1513 Raise_From_Signal_Handler (exception, msg);
1517 __gnat_error_handler (int *sigargs, void *mechargs)
1519 return __gnat_handle_vms_condition (sigargs, mechargs);
1523 __gnat_install_handler (void)
1525 long prvhnd ATTRIBUTE_UNUSED;
1527 #if !defined (IN_RTS)
1528 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1531 /* On alpha-vms, we avoid the global vector annoyance thanks to frame based
1532 handlers to turn conditions into exceptions since GCC 3.4. The global
1533 vector is still required for earlier GCC versions. We're resorting to
1534 the __gnat_error_prehandler assembly function in this case. */
1536 #if defined (IN_RTS) && defined (__alpha__)
1537 if ((__GNUC__ * 10 + __GNUC_MINOR__) < 34)
1539 char * c = (char *) xmalloc (2049);
1541 __gnat_error_prehandler_stack = &c[2048];
1542 SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1546 __gnat_handler_installed = 1;
1549 /* __gnat_adjust_context_for_raise for alpha - see comments along with the
1550 default version later in this file. */
1552 #if defined (IN_RTS) && defined (__alpha__)
1554 #include <vms/chfctxdef.h>
1555 #include <vms/chfdef.h>
1557 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1560 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1562 /* Add one to the address of the instruction signaling the condition,
1563 located in the sigargs array. */
1565 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1566 CHF$SIGNAL_ARRAY * sigargs
1567 = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1569 int vcount = sigargs->chf$is_sig_args;
1570 int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1577 /* __gnat_adjust_context_for_raise for ia64. */
1579 #if defined (IN_RTS) && defined (__IA64)
1581 #include <vms/chfctxdef.h>
1582 #include <vms/chfdef.h>
1584 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1586 typedef unsigned long long u64;
1589 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1591 /* Add one to the address of the instruction signaling the condition,
1592 located in the 64bits sigargs array. */
1594 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1596 CHF64$SIGNAL_ARRAY *chfsig64
1597 = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1600 = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1602 u64 * ih_pc_loc = post_sigarray - 2;
1609 /*******************/
1610 /* FreeBSD Section */
1611 /*******************/
1613 #elif defined (__FreeBSD__)
1616 #include <sys/ucontext.h>
1619 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1620 void __gnat_adjust_context_for_raise (int, void*);
1622 /* __gnat_adjust_context_for_raise - see comments along with the default
1623 version later in this file. */
1625 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1628 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1630 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
1635 __gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
1636 ucontext_t *ucontext)
1638 struct Exception_Data *exception;
1644 exception = &constraint_error;
1649 exception = &constraint_error;
1654 exception = &storage_error;
1655 msg = "stack overflow or erroneous memory access";
1659 exception = &constraint_error;
1664 exception = &program_error;
1665 msg = "unhandled signal";
1668 __gnat_adjust_context_for_raise (sig, ucontext);
1669 Raise_From_Signal_Handler (exception, msg);
1673 __gnat_install_handler ()
1675 struct sigaction act;
1677 /* Set up signal handler to map synchronous signals to appropriate
1678 exceptions. Make sure that the handler isn't interrupted by another
1679 signal that might cause a scheduling event! */
1682 = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1683 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1684 (void) sigemptyset (&act.sa_mask);
1686 (void) sigaction (SIGILL, &act, NULL);
1687 (void) sigaction (SIGFPE, &act, NULL);
1688 (void) sigaction (SIGSEGV, &act, NULL);
1689 (void) sigaction (SIGBUS, &act, NULL);
1691 __gnat_handler_installed = 1;
1694 /*******************/
1695 /* VxWorks Section */
1696 /*******************/
1698 #elif defined(__vxworks)
1701 #include <taskLib.h>
1709 #include "private/vThreadsP.h"
1712 static void __gnat_error_handler (int, int, struct sigcontext *);
1713 void __gnat_map_signal (int);
1717 /* Directly vectored Interrupt routines are not supported when using RTPs */
1719 extern int __gnat_inum_to_ivec (int);
1721 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1723 __gnat_inum_to_ivec (int num)
1725 return INUM_TO_IVEC (num);
1729 #if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1731 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1732 on Alpha VxWorks and VxWorks 6.x (including RTPs). */
1734 extern long getpid (void);
1739 return taskIdSelf ();
1743 /* VxWorks expects the field excCnt to be zeroed when a signal is handled.
1744 The VxWorks version of longjmp does this; gcc's builtin_longjmp does not */
1746 __gnat_clear_exception_count (void)
1749 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1751 currentTask->vThreads.excCnt = 0;
1755 /* Exported to s-intman-vxworks.adb in order to handle different signal
1756 to exception mappings in different VxWorks versions */
1758 __gnat_map_signal (int sig)
1760 struct Exception_Data *exception;
1766 exception = &constraint_error;
1771 exception = &constraint_error;
1772 msg = "Floating point exception or SIGILL";
1775 exception = &storage_error;
1776 msg = "SIGSEGV: possible stack overflow";
1779 exception = &storage_error;
1780 msg = "SIGBUS: possible stack overflow";
1784 exception = &constraint_error;
1787 /* In RTP mode a SIGSEGV is most likely due to a stack overflow. This is not
1788 the case in kernel mode where stack overflow detection uses a comparison
1789 method instead of memory probes. */
1792 exception = &storage_error;
1793 msg = "SIGSEGV: possible stack overflow";
1797 exception = &program_error;
1802 exception = &program_error;
1807 exception = &program_error;
1808 msg = "unhandled signal";
1811 __gnat_clear_exception_count ();
1812 Raise_From_Signal_Handler (exception, msg);
1816 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1821 /* VxWorks will always mask out the signal during the signal handler and
1822 will reenable it on a longjmp. GNAT does not generate a longjmp to
1823 return from a signal handler so the signal will still be masked unless
1825 sigprocmask (SIG_SETMASK, NULL, &mask);
1826 sigdelset (&mask, sig);
1827 sigprocmask (SIG_SETMASK, &mask, NULL);
1829 __gnat_map_signal (sig);
1834 __gnat_install_handler (void)
1836 struct sigaction act;
1838 /* Setup signal handler to map synchronous signals to appropriate
1839 exceptions. Make sure that the handler isn't interrupted by another
1840 signal that might cause a scheduling event! */
1842 act.sa_handler = __gnat_error_handler;
1843 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1844 sigemptyset (&act.sa_mask);
1846 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1847 applies to vectored hardware interrupts, not signals */
1848 sigaction (SIGFPE, &act, NULL);
1849 sigaction (SIGILL, &act, NULL);
1850 sigaction (SIGSEGV, &act, NULL);
1851 sigaction (SIGBUS, &act, NULL);
1853 __gnat_handler_installed = 1;
1856 #define HAVE_GNAT_INIT_FLOAT
1859 __gnat_init_float (void)
1861 /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1862 to get correct Ada semantics. Note that for AE653 vThreads, the HW
1863 overflow settings are an OS configuration issue. The instructions
1864 below have no effect */
1865 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1870 #if (defined (__i386__) || defined (i386)) && !defined (VTHREADS)
1871 /* This is used to properly initialize the FPU on an x86 for each
1876 /* Similarly for sparc64. Achieved by masking bits in the Trap Enable Mask
1877 field of the Floating-point Status Register (see the SPARC Architecture
1878 Manual Version 9, p 48). */
1879 #if defined (sparc64)
1881 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1882 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1883 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1884 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1885 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1889 __asm__("st %%fsr, %0" : "=m" (fsr));
1890 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1891 __asm__("ld %0, %%fsr" : : "m" (fsr));
1896 /******************/
1897 /* NetBSD Section */
1898 /******************/
1900 #elif defined(__NetBSD__)
1906 __gnat_error_handler (int sig)
1908 struct Exception_Data *exception;
1914 exception = &constraint_error;
1918 exception = &constraint_error;
1922 exception = &storage_error;
1923 msg = "stack overflow or erroneous memory access";
1926 exception = &constraint_error;
1930 exception = &program_error;
1931 msg = "unhandled signal";
1934 Raise_From_Signal_Handler(exception, msg);
1938 __gnat_install_handler(void)
1940 struct sigaction act;
1942 act.sa_handler = __gnat_error_handler;
1943 act.sa_flags = SA_NODEFER | SA_RESTART;
1944 sigemptyset (&act.sa_mask);
1946 /* Do not install handlers if interrupt state is "System" */
1947 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1948 sigaction (SIGFPE, &act, NULL);
1949 if (__gnat_get_interrupt_state (SIGILL) != 's')
1950 sigaction (SIGILL, &act, NULL);
1951 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1952 sigaction (SIGSEGV, &act, NULL);
1953 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1954 sigaction (SIGBUS, &act, NULL);
1956 __gnat_handler_installed = 1;
1961 /* For all other versions of GNAT, the handler does nothing */
1963 /*******************/
1964 /* Default Section */
1965 /*******************/
1968 __gnat_install_handler (void)
1970 __gnat_handler_installed = 1;
1975 /*********************/
1976 /* __gnat_init_float */
1977 /*********************/
1979 /* This routine is called as each process thread is created, for possible
1980 initialization of the FP processor. This version is used under INTERIX,
1981 WIN32 and could be used under OS/2 */
1983 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1984 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1986 #define HAVE_GNAT_INIT_FLOAT
1989 __gnat_init_float (void)
1991 #if defined (__i386__) || defined (i386)
1993 /* This is used to properly initialize the FPU on an x86 for each
1998 #endif /* Defined __i386__ */
2002 #ifndef HAVE_GNAT_INIT_FLOAT
2004 /* All targets without a specific __gnat_init_float will use an empty one */
2006 __gnat_init_float (void)
2011 /***********************************/
2012 /* __gnat_adjust_context_for_raise */
2013 /***********************************/
2015 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2017 /* All targets without a specific version will use an empty one */
2019 /* Given UCONTEXT a pointer to a context structure received by a signal
2020 handler for SIGNO, perform the necessary adjustments to let the handler
2021 raise an exception. Calls to this routine are not conditioned by the
2022 propagation scheme in use. */
2025 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2026 void *ucontext ATTRIBUTE_UNUSED)
2028 /* Adjustments are currently required for the GCC ZCX propagation scheme
2029 only. These adjustments (described below) are harmless for the other
2030 schemes, so may be applied unconditionally. */
2032 /* Adjustments required for a GCC ZCX propagation scheme:
2033 ------------------------------------------------------
2035 The GCC unwinder expects to be dealing with call return addresses, since
2036 this is the "nominal" case of what we retrieve while unwinding a regular
2039 To evaluate if a handler applies at some point identified by a return
2040 address, the propagation engine needs to determine what region the
2041 corresponding call instruction pertains to. Because the return address
2042 may not be attached to the same region as the call, the unwinder always
2043 subtracts "some" amount from a return address to search the region
2044 tables, amount chosen to ensure that the resulting address is inside the
2047 When we raise an exception from a signal handler, e.g. to transform a
2048 SIGSEGV into Storage_Error, things need to appear as if the signal
2049 handler had been "called" by the instruction which triggered the signal,
2050 so that exception handlers that apply there are considered. What the
2051 unwinder will retrieve as the return address from the signal handler is
2052 what it will find as the faulting instruction address in the signal
2053 context pushed by the kernel. Leaving this address untouched looses, if
2054 the triggering instruction happens to be the very first of a region, as
2055 the later adjustments performed by the unwinder would yield an address
2056 outside that region. We need to compensate for the unwinder adjustments
2057 at some point, and this is what this routine is expected to do.
2059 signo is passed because on some targets for some signals the PC in
2060 context points to the instruction after the faulting one, in which case
2061 the unwinder adjustment is still desired.
2063 We used to perform the compensation in the GCC unwinding fallback macro.
2064 The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
2065 describes a couple of issues with this approach. First, on some targets
2066 the adjustment to apply depends on the triggering signal, which is not
2067 easily accessible from the macro. Besides, other languages, e.g. Java,
2068 deal with this by performing the adjustment in the signal handler before
2069 the raise, so fallback adjustments just break those front-ends. */