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;
104 int __gl_leap_seconds_support = 0;
106 /* Indication of whether synchronous signal handler has already been
107 installed by a previous call to adainit */
108 int __gnat_handler_installed = 0;
111 int __gnat_inside_elab_final_code = 0;
112 /* ??? This variable is obsolete since 2001-08-29 but is kept to allow
113 bootstrap from old GNAT versions (< 3.15). */
116 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
117 is defined. If this is not set them a void implementation will be defined
118 at the end of this unit. */
119 #undef HAVE_GNAT_INIT_FLOAT
121 /******************************/
122 /* __gnat_get_interrupt_state */
123 /******************************/
125 char __gnat_get_interrupt_state (int);
127 /* This routine is called from the runtime as needed to determine the state
128 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
129 in the current partition. The input argument is the interrupt number,
130 and the result is one of the following:
132 'n' this interrupt not set by any Interrupt_State pragma
133 'u' Interrupt_State pragma set state to User
134 'r' Interrupt_State pragma set state to Runtime
135 's' Interrupt_State pragma set state to System */
138 __gnat_get_interrupt_state (int intrup)
140 if (intrup >= __gl_num_interrupt_states)
143 return __gl_interrupt_states [intrup];
146 /***********************************/
147 /* __gnat_get_specific_dispatching */
148 /***********************************/
150 char __gnat_get_specific_dispatching (int);
152 /* This routine is called from the run time as needed to determine the
153 priority specific dispatching policy, as set by a
154 Priority_Specific_Dispatching pragma appearing anywhere in the current
155 partition. The input argument is the priority number, and the result is
156 the upper case first character of the policy name, e.g. 'F' for
157 FIFO_Within_Priorities. A space ' ' is returned if no
158 Priority_Specific_Dispatching pragma is used in the partition. */
161 __gnat_get_specific_dispatching (int priority)
163 if (__gl_num_specific_dispatching == 0)
165 else if (priority >= __gl_num_specific_dispatching)
168 return __gl_priority_specific_dispatching [priority];
173 /**********************/
174 /* __gnat_set_globals */
175 /**********************/
177 /* This routine is kept for boostrapping purposes, since the binder generated
178 file now sets the __gl_* variables directly. */
181 __gnat_set_globals ()
194 #include <sys/time.h>
196 /* Some versions of AIX don't define SA_NODEFER. */
200 #endif /* SA_NODEFER */
202 /* Versions of AIX before 4.3 don't have nanosleep but provide
205 #ifndef _AIXVERSION_430
207 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
210 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
212 return nsleep (Rqtp, Rmtp);
215 #endif /* _AIXVERSION_430 */
217 static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
219 /* __gnat_adjust_context_for_raise - see comments along with the default
220 version later in this file. */
223 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
225 /* We need to adjust the "Instruction Address Register" value, part of a
226 'struct mstsave' wrapped as a jumpbuf in the mcontext field designated by
227 the signal data pointer we get. See sys/context.h + sys/mstsave.h */
229 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
230 mcontext->jmp_context.iar++;
233 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
236 __gnat_error_handler (int sig, siginfo_t * si, void * uc)
238 struct Exception_Data *exception;
244 /* FIXME: we need to detect the case of a *real* SIGSEGV */
245 exception = &storage_error;
246 msg = "stack overflow or erroneous memory access";
250 exception = &constraint_error;
255 exception = &constraint_error;
260 exception = &program_error;
261 msg = "unhandled signal";
264 __gnat_adjust_context_for_raise (sig, uc);
265 Raise_From_Signal_Handler (exception, msg);
269 __gnat_install_handler (void)
271 struct sigaction act;
273 /* Set up signal handler to map synchronous signals to appropriate
274 exceptions. Make sure that the handler isn't interrupted by another
275 signal that might cause a scheduling event! */
277 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
278 act.sa_sigaction = __gnat_error_handler;
279 sigemptyset (&act.sa_mask);
281 /* Do not install handlers if interrupt state is "System" */
282 if (__gnat_get_interrupt_state (SIGABRT) != 's')
283 sigaction (SIGABRT, &act, NULL);
284 if (__gnat_get_interrupt_state (SIGFPE) != 's')
285 sigaction (SIGFPE, &act, NULL);
286 if (__gnat_get_interrupt_state (SIGILL) != 's')
287 sigaction (SIGILL, &act, NULL);
288 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
289 sigaction (SIGSEGV, &act, NULL);
290 if (__gnat_get_interrupt_state (SIGBUS) != 's')
291 sigaction (SIGBUS, &act, NULL);
293 __gnat_handler_installed = 1;
300 #elif defined(__alpha__) && defined(__osf__)
303 #include <sys/siginfo.h>
305 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
306 extern char *__gnat_get_code_loc (struct sigcontext *);
307 extern void __gnat_set_code_loc (struct sigcontext *, char *);
308 extern size_t __gnat_machine_state_length (void);
310 /* __gnat_adjust_context_for_raise - see comments along with the default
311 version later in this file. */
313 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
316 __gnat_adjust_context_for_raise (int signo, void *context)
318 struct sigcontext * sigcontext = (struct sigcontext *) context;
320 /* The fallback code fetches the faulting insn address from sc_pc, so
321 adjust that when need be. For SIGFPE, the required adjustment depends
322 on the trap shadow situation (see man ieee). */
325 /* ??? We never adjust here, considering that sc_pc always
326 designates the instruction following the one which trapped.
327 This is not necessarily true but corresponds to what we have
331 sigcontext->sc_pc ++;
336 (int sig, siginfo_t *sip, struct sigcontext *context)
338 struct Exception_Data *exception;
339 static int recurse = 0;
342 /* Adjusting is required for every fault context, so adjust for this one
343 now, before we possibly trigger a recursive fault below. */
344 __gnat_adjust_context_for_raise (sig, context);
346 /* If this was an explicit signal from a "kill", just resignal it. */
347 if (SI_FROMUSER (sip))
349 signal (sig, SIG_DFL);
350 kill (getpid(), sig);
353 /* Otherwise, treat it as something we handle. */
357 /* If the problem was permissions, this is a constraint error.
358 Likewise if the failing address isn't maximally aligned or if
361 ??? Using a static variable here isn't task-safe, but it's
362 much too hard to do anything else and we're just determining
363 which exception to raise. */
364 if (sip->si_code == SEGV_ACCERR
365 || (((long) sip->si_addr) & 3) != 0
368 exception = &constraint_error;
373 /* See if the page before the faulting page is accessible. Do that
374 by trying to access it. We'd like to simply try to access
375 4096 + the faulting address, but it's not guaranteed to be
376 the actual address, just to be on the same page. */
379 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
380 msg = "stack overflow (or erroneous memory access)";
381 exception = &storage_error;
386 exception = &program_error;
391 exception = &constraint_error;
396 exception = &program_error;
397 msg = "unhandled signal";
401 Raise_From_Signal_Handler (exception, (char *) msg);
405 __gnat_install_handler (void)
407 struct sigaction act;
409 /* Setup signal handler to map synchronous signals to appropriate
410 exceptions. Make sure that the handler isn't interrupted by another
411 signal that might cause a scheduling event! */
413 act.sa_handler = (void (*) (int)) __gnat_error_handler;
414 act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
415 sigemptyset (&act.sa_mask);
417 /* Do not install handlers if interrupt state is "System" */
418 if (__gnat_get_interrupt_state (SIGABRT) != 's')
419 sigaction (SIGABRT, &act, NULL);
420 if (__gnat_get_interrupt_state (SIGFPE) != 's')
421 sigaction (SIGFPE, &act, NULL);
422 if (__gnat_get_interrupt_state (SIGILL) != 's')
423 sigaction (SIGILL, &act, NULL);
424 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
425 sigaction (SIGSEGV, &act, NULL);
426 if (__gnat_get_interrupt_state (SIGBUS) != 's')
427 sigaction (SIGBUS, &act, NULL);
429 __gnat_handler_installed = 1;
432 /* Routines called by s-mastop-tru64.adb. */
437 __gnat_get_code_loc (struct sigcontext *context)
439 return (char *) context->sc_pc;
443 __gnat_set_code_loc (struct sigcontext *context, char *pc)
445 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;
753 #define SIGADAABORT 48
754 #define SIGNAL_STACK_SIZE 4096
755 #define SIGNAL_STACK_ALIGNMENT 64
757 #define Check_Abort_Status \
758 system__soft_links__check_abort_status
759 extern int (*Check_Abort_Status) (void);
761 extern struct Exception_Data _abort_signal;
763 static void __gnat_error_handler (int, int, sigcontext_t *);
765 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
766 connecting that handler, with the effects described in the sigaction
770 If cleared and the signal is caught, the first argument is
771 also the signal number but the second argument is the signal
772 code identifying the cause of the signal. The third argument
773 points to a sigcontext_t structure containing the receiving
774 process's context when the signal was delivered.
778 __gnat_error_handler (int sig, int code, sigcontext_t *sc ATTRIBUTE_UNUSED)
780 struct Exception_Data *exception;
788 exception = &program_error;
789 msg = "SIGSEGV: (Invalid virtual address)";
791 else if (code == ENXIO)
793 exception = &program_error;
794 msg = "SIGSEGV: (Read beyond mapped object)";
796 else if (code == ENOSPC)
798 exception = &program_error; /* ??? storage_error ??? */
799 msg = "SIGSEGV: (Autogrow for file failed)";
801 else if (code == EACCES || code == EEXIST)
803 /* ??? We handle stack overflows here, some of which do trigger
804 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
805 the documented valid codes for SEGV in the signal(5) man
808 /* ??? Re-add smarts to further verify that we launched
809 the stack into a guard page, not an attempt to
810 write to .text or something */
811 exception = &storage_error;
812 msg = "SIGSEGV: (stack overflow or erroneous memory access)";
816 /* Just in case the OS guys did it to us again. Sometimes
817 they fail to document all of the valid codes that are
818 passed to signal handlers, just in case someone depends
819 on knowing all the codes */
820 exception = &program_error;
821 msg = "SIGSEGV: (Undocumented reason)";
826 /* Map all bus errors to Program_Error. */
827 exception = &program_error;
832 /* Map all fpe errors to Constraint_Error. */
833 exception = &constraint_error;
838 if ((*Check_Abort_Status) ())
840 exception = &_abort_signal;
849 /* Everything else is a Program_Error. */
850 exception = &program_error;
851 msg = "unhandled signal";
854 Raise_From_Signal_Handler (exception, msg);
858 __gnat_install_handler (void)
860 struct sigaction act;
862 /* Setup signal handler to map synchronous signals to appropriate
863 exceptions. Make sure that the handler isn't interrupted by another
864 signal that might cause a scheduling event! */
866 act.sa_handler = __gnat_error_handler;
867 act.sa_flags = SA_NODEFER + SA_RESTART;
868 sigfillset (&act.sa_mask);
869 sigemptyset (&act.sa_mask);
871 /* Do not install handlers if interrupt state is "System" */
872 if (__gnat_get_interrupt_state (SIGABRT) != 's')
873 sigaction (SIGABRT, &act, NULL);
874 if (__gnat_get_interrupt_state (SIGFPE) != 's')
875 sigaction (SIGFPE, &act, NULL);
876 if (__gnat_get_interrupt_state (SIGILL) != 's')
877 sigaction (SIGILL, &act, NULL);
878 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
879 sigaction (SIGSEGV, &act, NULL);
880 if (__gnat_get_interrupt_state (SIGBUS) != 's')
881 sigaction (SIGBUS, &act, NULL);
882 if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
883 sigaction (SIGADAABORT, &act, NULL);
885 __gnat_handler_installed = 1;
888 /*******************/
889 /* Solaris Section */
890 /*******************/
892 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
896 #include <sys/ucontext.h>
897 #include <sys/regset.h>
899 /* The code below is common to sparc and x86. Beware of the delay slot
900 differences for signal context adjustments. */
902 #if defined (__sparc)
903 #define RETURN_ADDR_OFFSET 8
905 #define RETURN_ADDR_OFFSET 0
908 /* Likewise regarding how the "instruction pointer" register slot can
909 be identified in signal machine contexts. We have either "REG_PC"
910 or "PC" at hand, depending on the target CPU and solaris version. */
912 #if !defined (REG_PC)
916 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
918 /* __gnat_adjust_context_for_raise - see comments along with the default
919 version later in this file. */
921 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
924 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
927 mcontext_t *mcontext = & ((ucontext_t *)ucontext)->uc_mcontext;
928 mcontext->gregs[REG_PC] += (1 - RETURN_ADDR_OFFSET);
932 __gnat_error_handler (int sig, siginfo_t *sip, ucontext_t *uctx)
934 struct Exception_Data *exception;
935 static int recurse = 0;
938 /* Adjusting is required for every fault context, so adjust for this one
939 now, before we possibly trigger a recursive fault below. */
940 __gnat_adjust_context_for_raise (sig, (void *)uctx);
942 /* If this was an explicit signal from a "kill", just resignal it. */
943 if (SI_FROMUSER (sip))
945 signal (sig, SIG_DFL);
946 kill (getpid(), sig);
949 /* Otherwise, treat it as something we handle. */
953 /* If the problem was permissions, this is a constraint error.
954 Likewise if the failing address isn't maximally aligned or if
957 ??? Using a static variable here isn't task-safe, but it's
958 much too hard to do anything else and we're just determining
959 which exception to raise. */
960 if (sip->si_code == SEGV_ACCERR
961 || (((long) sip->si_addr) & 3) != 0
964 exception = &constraint_error;
969 /* See if the page before the faulting page is accessible. Do that
970 by trying to access it. We'd like to simply try to access
971 4096 + the faulting address, but it's not guaranteed to be
972 the actual address, just to be on the same page. */
975 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
976 exception = &storage_error;
977 msg = "stack overflow (or erroneous memory access)";
982 exception = &program_error;
987 exception = &constraint_error;
992 exception = &program_error;
993 msg = "unhandled signal";
998 Raise_From_Signal_Handler (exception, msg);
1002 __gnat_install_handler (void)
1004 struct sigaction act;
1006 /* Set up signal handler to map synchronous signals to appropriate
1007 exceptions. Make sure that the handler isn't interrupted by another
1008 signal that might cause a scheduling event! */
1010 act.sa_handler = __gnat_error_handler;
1011 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1012 sigemptyset (&act.sa_mask);
1014 /* Do not install handlers if interrupt state is "System" */
1015 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1016 sigaction (SIGABRT, &act, NULL);
1017 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1018 sigaction (SIGFPE, &act, NULL);
1019 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1020 sigaction (SIGSEGV, &act, NULL);
1021 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1022 sigaction (SIGBUS, &act, NULL);
1024 __gnat_handler_installed = 1;
1033 long __gnat_error_handler (int *, void *);
1036 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1037 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1038 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1040 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1041 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1042 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1045 #if defined (IN_RTS) && !defined (__IA64)
1047 /* The prehandler actually gets control first on a condition. It swaps the
1048 stack pointer and calls the handler (__gnat_error_handler). */
1049 extern long __gnat_error_prehandler (void);
1051 extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
1054 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1055 Most of these are also defined in the header file ssdef.h which has not
1056 yet been converted to be recognized by Gnu C. */
1058 /* Defining these as macros, as opposed to external addresses, allows
1059 them to be used in a case statement (below */
1060 #define SS$_ACCVIO 12
1061 #define SS$_HPARITH 1284
1062 #define SS$_STKOVF 1364
1063 #define SS$_RESIGNAL 2328
1065 /* These codes are in standard message libraries */
1066 extern int CMA$_EXIT_THREAD;
1067 extern int SS$_DEBUG;
1068 extern int SS$_INTDIV;
1069 extern int LIB$_KEYNOTFOU;
1070 extern int LIB$_ACTIMAGE;
1071 extern int MTH$_FLOOVEMAT; /* Some ACVC_21 CXA tests */
1073 /* These codes are non standard, which is to say the author is
1074 not sure if they are defined in the standard message libraries
1075 so keep them as macros for now. */
1076 #define RDB$_STREAM_EOF 20480426
1077 #define FDL$_UNPRIKW 11829410
1079 struct cond_except {
1081 const struct Exception_Data *except;
1084 struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1086 /* Conditions that don't have an Ada exception counterpart must raise
1087 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1088 referenced by user programs, not the compiler or tools. Hence the
1093 #define Status_Error ada__io_exceptions__status_error
1094 extern struct Exception_Data Status_Error;
1096 #define Mode_Error ada__io_exceptions__mode_error
1097 extern struct Exception_Data Mode_Error;
1099 #define Name_Error ada__io_exceptions__name_error
1100 extern struct Exception_Data Name_Error;
1102 #define Use_Error ada__io_exceptions__use_error
1103 extern struct Exception_Data Use_Error;
1105 #define Device_Error ada__io_exceptions__device_error
1106 extern struct Exception_Data Device_Error;
1108 #define End_Error ada__io_exceptions__end_error
1109 extern struct Exception_Data End_Error;
1111 #define Data_Error ada__io_exceptions__data_error
1112 extern struct Exception_Data Data_Error;
1114 #define Layout_Error ada__io_exceptions__layout_error
1115 extern struct Exception_Data Layout_Error;
1117 #define Non_Ada_Error system__aux_dec__non_ada_error
1118 extern struct Exception_Data Non_Ada_Error;
1120 #define Coded_Exception system__vms_exception_table__coded_exception
1121 extern struct Exception_Data *Coded_Exception (Exception_Code);
1123 #define Base_Code_In system__vms_exception_table__base_code_in
1124 extern Exception_Code Base_Code_In (Exception_Code);
1126 /* DEC Ada exceptions are not defined in a header file, so they
1127 must be declared as external addresses */
1129 extern int ADA$_PROGRAM_ERROR;
1130 extern int ADA$_LOCK_ERROR;
1131 extern int ADA$_EXISTENCE_ERROR;
1132 extern int ADA$_KEY_ERROR;
1133 extern int ADA$_KEYSIZERR;
1134 extern int ADA$_STAOVF;
1135 extern int ADA$_CONSTRAINT_ERRO;
1136 extern int ADA$_IOSYSFAILED;
1137 extern int ADA$_LAYOUT_ERROR;
1138 extern int ADA$_STORAGE_ERROR;
1139 extern int ADA$_DATA_ERROR;
1140 extern int ADA$_DEVICE_ERROR;
1141 extern int ADA$_END_ERROR;
1142 extern int ADA$_MODE_ERROR;
1143 extern int ADA$_NAME_ERROR;
1144 extern int ADA$_STATUS_ERROR;
1145 extern int ADA$_NOT_OPEN;
1146 extern int ADA$_ALREADY_OPEN;
1147 extern int ADA$_USE_ERROR;
1148 extern int ADA$_UNSUPPORTED;
1149 extern int ADA$_FAC_MODE_MISMAT;
1150 extern int ADA$_ORG_MISMATCH;
1151 extern int ADA$_RFM_MISMATCH;
1152 extern int ADA$_RAT_MISMATCH;
1153 extern int ADA$_MRS_MISMATCH;
1154 extern int ADA$_MRN_MISMATCH;
1155 extern int ADA$_KEY_MISMATCH;
1156 extern int ADA$_MAXLINEXC;
1157 extern int ADA$_LINEXCMRS;
1159 /* DEC Ada specific conditions */
1160 static const struct cond_except dec_ada_cond_except_table [] = {
1161 {&ADA$_PROGRAM_ERROR, &program_error},
1162 {&ADA$_USE_ERROR, &Use_Error},
1163 {&ADA$_KEYSIZERR, &program_error},
1164 {&ADA$_STAOVF, &storage_error},
1165 {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1166 {&ADA$_IOSYSFAILED, &Device_Error},
1167 {&ADA$_LAYOUT_ERROR, &Layout_Error},
1168 {&ADA$_STORAGE_ERROR, &storage_error},
1169 {&ADA$_DATA_ERROR, &Data_Error},
1170 {&ADA$_DEVICE_ERROR, &Device_Error},
1171 {&ADA$_END_ERROR, &End_Error},
1172 {&ADA$_MODE_ERROR, &Mode_Error},
1173 {&ADA$_NAME_ERROR, &Name_Error},
1174 {&ADA$_STATUS_ERROR, &Status_Error},
1175 {&ADA$_NOT_OPEN, &Use_Error},
1176 {&ADA$_ALREADY_OPEN, &Use_Error},
1177 {&ADA$_USE_ERROR, &Use_Error},
1178 {&ADA$_UNSUPPORTED, &Use_Error},
1179 {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1180 {&ADA$_ORG_MISMATCH, &Use_Error},
1181 {&ADA$_RFM_MISMATCH, &Use_Error},
1182 {&ADA$_RAT_MISMATCH, &Use_Error},
1183 {&ADA$_MRS_MISMATCH, &Use_Error},
1184 {&ADA$_MRN_MISMATCH, &Use_Error},
1185 {&ADA$_KEY_MISMATCH, &Use_Error},
1186 {&ADA$_MAXLINEXC, &constraint_error},
1187 {&ADA$_LINEXCMRS, &constraint_error},
1192 /* Already handled by a pragma Import_Exception
1193 in Aux_IO_Exceptions */
1194 {&ADA$_LOCK_ERROR, &Lock_Error},
1195 {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1196 {&ADA$_KEY_ERROR, &Key_Error},
1201 /* Non DEC Ada specific conditions. We could probably also put
1202 SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
1203 static const struct cond_except cond_except_table [] = {
1204 {&MTH$_FLOOVEMAT, &constraint_error},
1205 {&SS$_INTDIV, &constraint_error},
1209 /* To deal with VMS conditions and their mapping to Ada exceptions,
1210 the __gnat_error_handler routine below is installed as an exception
1211 vector having precedence over DEC frame handlers. Some conditions
1212 still need to be handled by such handlers, however, in which case
1213 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
1214 instance the use of a third party library compiled with DECAda and
1215 performing it's own exception handling internally.
1217 To allow some user-level flexibility, which conditions should be
1218 resignaled is controlled by a predicate function, provided with the
1219 condition value and returning a boolean indication stating whether
1220 this condition should be resignaled or not.
1222 That predicate function is called indirectly, via a function pointer,
1223 by __gnat_error_handler, and changing that pointer is allowed to the
1224 the user code by way of the __gnat_set_resignal_predicate interface.
1226 The user level function may then implement what it likes, including
1227 for instance the maintenance of a dynamic data structure if the set
1228 of to be resignalled conditions has to change over the program's
1231 ??? This is not a perfect solution to deal with the possible
1232 interactions between the GNAT and the DECAda exception handling
1233 models and better (more general) schemes are studied. This is so
1234 just provided as a convenient workaround in the meantime, and
1235 should be use with caution since the implementation has been kept
1239 resignal_predicate (int code);
1241 const int *cond_resignal_table [] = {
1246 (int *) RDB$_STREAM_EOF,
1247 (int *) FDL$_UNPRIKW,
1251 const int facility_resignal_table [] = {
1252 0x1380000, /* RDB */
1253 0x2220000, /* SQL */
1257 /* Default GNAT predicate for resignaling conditions. */
1260 __gnat_default_resignal_p (int code)
1264 for (i = 0; facility_resignal_table [i]; i++)
1265 if ((code & 0xfff0000) == facility_resignal_table [i])
1268 for (i = 0, iexcept = 0;
1269 cond_resignal_table [i] &&
1270 !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1276 /* Static pointer to predicate that the __gnat_error_handler exception
1277 vector invokes to determine if it should resignal a condition. */
1279 static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1281 /* User interface to change the predicate pointer to PREDICATE. Reset to
1282 the default if PREDICATE is null. */
1285 __gnat_set_resignal_predicate (resignal_predicate * predicate)
1288 __gnat_resignal_p = __gnat_default_resignal_p;
1290 __gnat_resignal_p = predicate;
1293 /* Should match System.Parameters.Default_Exception_Msg_Max_Length */
1294 #define Default_Exception_Msg_Max_Length 512
1296 /* Action routine for SYS$PUTMSG. There may be
1297 multiple conditions, each with text to be appended to
1298 MESSAGE and separated by line termination. */
1301 copy_msg (msgdesc, message)
1302 struct descriptor_s *msgdesc;
1305 int len = strlen (message);
1308 /* Check for buffer overflow and skip */
1309 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1311 strcat (message, "\r\n");
1315 /* Check for buffer overflow and truncate if necessary */
1316 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1318 Default_Exception_Msg_Max_Length - 1 - len);
1319 strncpy (&message [len], msgdesc->adr, copy_len);
1320 message [len + copy_len] = 0;
1326 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1328 struct Exception_Data *exception = 0;
1329 Exception_Code base_code;
1330 struct descriptor_s gnat_facility = {4,0,"GNAT"};
1331 char message [Default_Exception_Msg_Max_Length];
1333 const char *msg = "";
1335 /* Check for conditions to resignal which aren't effected by pragma
1336 Import_Exception. */
1337 if (__gnat_resignal_p (sigargs [1]))
1338 return SS$_RESIGNAL;
1341 /* See if it's an imported exception. Beware that registered exceptions
1342 are bound to their base code, with the severity bits masked off. */
1343 base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1344 exception = Coded_Exception (base_code);
1350 /* Subtract PC & PSL fields which messes with PUTMSG */
1352 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1356 exception->Name_Length = 19;
1357 /* The full name really should be get sys$getmsg returns. ??? */
1358 exception->Full_Name = "IMPORTED_EXCEPTION";
1359 exception->Import_Code = base_code;
1362 /* Do not adjust the program counter as already points to the next
1363 instruction (just after the call to LIB$STOP). */
1364 Raise_From_Signal_Handler (exception, msg);
1373 if (sigargs[3] == 0)
1375 exception = &constraint_error;
1376 msg = "access zero";
1380 exception = &storage_error;
1381 msg = "stack overflow (or erroneous memory access)";
1383 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1387 exception = &storage_error;
1388 msg = "stack overflow";
1389 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1394 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1396 exception = &constraint_error;
1397 msg = "arithmetic error";
1398 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1407 /* Scan the DEC Ada exception condition table for a match and fetch
1408 the associated GNAT exception pointer */
1410 dec_ada_cond_except_table [i].cond &&
1411 !LIB$MATCH_COND (&sigargs [1],
1412 &dec_ada_cond_except_table [i].cond);
1414 exception = (struct Exception_Data *)
1415 dec_ada_cond_except_table [i].except;
1419 /* Scan the VMS standard condition table for a match and fetch
1420 the associated GNAT exception pointer */
1422 cond_except_table [i].cond &&
1423 !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1425 exception = (struct Exception_Data *)
1426 cond_except_table [i].except;
1429 /* User programs expect Non_Ada_Error to be raised, reference
1430 DEC Ada test CXCONDHAN. */
1431 exception = &Non_Ada_Error;
1435 exception = &program_error;
1438 /* Subtract PC & PSL fields which messes with PUTMSG */
1440 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1446 Raise_From_Signal_Handler (exception, msg);
1450 __gnat_error_handler (int *sigargs, void *mechargs)
1452 return __gnat_handle_vms_condition (sigargs, mechargs);
1456 __gnat_install_handler (void)
1458 long prvhnd ATTRIBUTE_UNUSED;
1460 #if !defined (IN_RTS)
1461 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1464 /* On alpha-vms, we avoid the global vector annoyance thanks to frame based
1465 handlers to turn conditions into exceptions since GCC 3.4. The global
1466 vector is still required for earlier GCC versions. We're resorting to
1467 the __gnat_error_prehandler assembly function in this case. */
1469 #if defined (IN_RTS) && defined (__alpha__)
1470 if ((__GNUC__ * 10 + __GNUC_MINOR__) < 34)
1472 char * c = (char *) xmalloc (2049);
1474 __gnat_error_prehandler_stack = &c[2048];
1475 SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1479 __gnat_handler_installed = 1;
1482 /* __gnat_adjust_context_for_raise for alpha - see comments along with the
1483 default version later in this file. */
1485 #if defined (IN_RTS) && defined (__alpha__)
1487 #include <vms/chfctxdef.h>
1488 #include <vms/chfdef.h>
1490 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1493 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1495 /* Add one to the address of the instruction signaling the condition,
1496 located in the sigargs array. */
1498 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1499 CHF$SIGNAL_ARRAY * sigargs
1500 = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1502 int vcount = sigargs->chf$is_sig_args;
1503 int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1510 /* __gnat_adjust_context_for_raise for ia64. */
1512 #if defined (IN_RTS) && defined (__IA64)
1514 #include <vms/chfctxdef.h>
1515 #include <vms/chfdef.h>
1517 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1519 typedef unsigned long long u64;
1522 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1524 /* Add one to the address of the instruction signaling the condition,
1525 located in the 64bits sigargs array. */
1527 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1529 CHF64$SIGNAL_ARRAY *chfsig64
1530 = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1533 = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1535 u64 * ih_pc_loc = post_sigarray - 2;
1542 /*******************/
1543 /* FreeBSD Section */
1544 /*******************/
1546 #elif defined (__FreeBSD__)
1549 #include <sys/ucontext.h>
1552 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1553 void __gnat_adjust_context_for_raise (int, void*);
1555 /* __gnat_adjust_context_for_raise - see comments along with the default
1556 version later in this file. */
1558 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1561 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1563 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
1568 __gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
1569 ucontext_t *ucontext)
1571 struct Exception_Data *exception;
1577 exception = &constraint_error;
1582 exception = &constraint_error;
1587 exception = &storage_error;
1588 msg = "stack overflow or erroneous memory access";
1592 exception = &constraint_error;
1597 exception = &program_error;
1598 msg = "unhandled signal";
1601 __gnat_adjust_context_for_raise (sig, ucontext);
1602 Raise_From_Signal_Handler (exception, msg);
1606 __gnat_install_handler ()
1608 struct sigaction act;
1610 /* Set up signal handler to map synchronous signals to appropriate
1611 exceptions. Make sure that the handler isn't interrupted by another
1612 signal that might cause a scheduling event! */
1615 = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1616 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1617 (void) sigemptyset (&act.sa_mask);
1619 (void) sigaction (SIGILL, &act, NULL);
1620 (void) sigaction (SIGFPE, &act, NULL);
1621 (void) sigaction (SIGSEGV, &act, NULL);
1622 (void) sigaction (SIGBUS, &act, NULL);
1624 __gnat_handler_installed = 1;
1627 /*******************/
1628 /* VxWorks Section */
1629 /*******************/
1631 #elif defined(__vxworks)
1634 #include <taskLib.h>
1642 #include "private/vThreadsP.h"
1645 static void __gnat_error_handler (int, int, struct sigcontext *);
1646 void __gnat_map_signal (int);
1650 /* Directly vectored Interrupt routines are not supported when using RTPs */
1652 extern int __gnat_inum_to_ivec (int);
1654 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1656 __gnat_inum_to_ivec (int num)
1658 return INUM_TO_IVEC (num);
1662 #if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1664 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1665 on Alpha VxWorks and VxWorks 6.x (including RTPs). */
1667 extern long getpid (void);
1672 return taskIdSelf ();
1676 /* VxWorks expects the field excCnt to be zeroed when a signal is handled.
1677 The VxWorks version of longjmp does this; gcc's builtin_longjmp does not */
1679 __gnat_clear_exception_count (void)
1682 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1684 currentTask->vThreads.excCnt = 0;
1688 /* Exported to s-intman-vxworks.adb in order to handle different signal
1689 to exception mappings in different VxWorks versions */
1691 __gnat_map_signal (int sig)
1693 struct Exception_Data *exception;
1699 exception = &constraint_error;
1704 exception = &constraint_error;
1705 msg = "Floating point exception or SIGILL";
1708 exception = &storage_error;
1709 msg = "SIGSEGV: possible stack overflow";
1712 exception = &storage_error;
1713 msg = "SIGBUS: possible stack overflow";
1717 /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
1718 since stack checking uses the probing mechanism. */
1720 exception = &constraint_error;
1724 exception = &storage_error;
1725 msg = "SIGSEGV: possible stack overflow";
1728 /* In kernel mode a SIGILL is most likely due to a stack overflow,
1729 since stack checking uses the stack limit mechanism. */
1731 exception = &storage_error;
1732 msg = "SIGILL: possible stack overflow";
1735 exception = &program_error;
1740 exception = &program_error;
1745 exception = &program_error;
1746 msg = "unhandled signal";
1749 __gnat_clear_exception_count ();
1750 Raise_From_Signal_Handler (exception, msg);
1754 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1759 /* VxWorks will always mask out the signal during the signal handler and
1760 will reenable it on a longjmp. GNAT does not generate a longjmp to
1761 return from a signal handler so the signal will still be masked unless
1763 sigprocmask (SIG_SETMASK, NULL, &mask);
1764 sigdelset (&mask, sig);
1765 sigprocmask (SIG_SETMASK, &mask, NULL);
1767 __gnat_map_signal (sig);
1772 __gnat_install_handler (void)
1774 struct sigaction act;
1776 /* Setup signal handler to map synchronous signals to appropriate
1777 exceptions. Make sure that the handler isn't interrupted by another
1778 signal that might cause a scheduling event! */
1780 act.sa_handler = __gnat_error_handler;
1781 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1782 sigemptyset (&act.sa_mask);
1784 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1785 applies to vectored hardware interrupts, not signals */
1786 sigaction (SIGFPE, &act, NULL);
1787 sigaction (SIGILL, &act, NULL);
1788 sigaction (SIGSEGV, &act, NULL);
1789 sigaction (SIGBUS, &act, NULL);
1791 __gnat_handler_installed = 1;
1794 #define HAVE_GNAT_INIT_FLOAT
1797 __gnat_init_float (void)
1799 /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1800 to get correct Ada semantics. Note that for AE653 vThreads, the HW
1801 overflow settings are an OS configuration issue. The instructions
1802 below have no effect */
1803 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1808 #if (defined (__i386__) || defined (i386)) && !defined (VTHREADS)
1809 /* This is used to properly initialize the FPU on an x86 for each
1814 /* Similarly for sparc64. Achieved by masking bits in the Trap Enable Mask
1815 field of the Floating-point Status Register (see the SPARC Architecture
1816 Manual Version 9, p 48). */
1817 #if defined (sparc64)
1819 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1820 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1821 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1822 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1823 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1827 __asm__("st %%fsr, %0" : "=m" (fsr));
1828 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1829 __asm__("ld %0, %%fsr" : : "m" (fsr));
1834 /* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
1835 (if not null) when a new task is created. It is initialized by
1836 System.Stack_Checking.Operations.Initialize_Stack_Limit.
1837 The use of a hook avoids to drag stack checking subprograms if stack
1838 checking is not used. */
1839 void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
1842 /******************/
1843 /* NetBSD Section */
1844 /******************/
1846 #elif defined(__NetBSD__)
1852 __gnat_error_handler (int sig)
1854 struct Exception_Data *exception;
1860 exception = &constraint_error;
1864 exception = &constraint_error;
1868 exception = &storage_error;
1869 msg = "stack overflow or erroneous memory access";
1872 exception = &constraint_error;
1876 exception = &program_error;
1877 msg = "unhandled signal";
1880 Raise_From_Signal_Handler(exception, msg);
1884 __gnat_install_handler(void)
1886 struct sigaction act;
1888 act.sa_handler = __gnat_error_handler;
1889 act.sa_flags = SA_NODEFER | SA_RESTART;
1890 sigemptyset (&act.sa_mask);
1892 /* Do not install handlers if interrupt state is "System" */
1893 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1894 sigaction (SIGFPE, &act, NULL);
1895 if (__gnat_get_interrupt_state (SIGILL) != 's')
1896 sigaction (SIGILL, &act, NULL);
1897 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1898 sigaction (SIGSEGV, &act, NULL);
1899 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1900 sigaction (SIGBUS, &act, NULL);
1902 __gnat_handler_installed = 1;
1907 /* For all other versions of GNAT, the handler does nothing */
1909 /*******************/
1910 /* Default Section */
1911 /*******************/
1914 __gnat_install_handler (void)
1916 __gnat_handler_installed = 1;
1921 /*********************/
1922 /* __gnat_init_float */
1923 /*********************/
1925 /* This routine is called as each process thread is created, for possible
1926 initialization of the FP processor. This version is used under INTERIX,
1927 WIN32 and could be used under OS/2 */
1929 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1930 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1932 #define HAVE_GNAT_INIT_FLOAT
1935 __gnat_init_float (void)
1937 #if defined (__i386__) || defined (i386)
1939 /* This is used to properly initialize the FPU on an x86 for each
1944 #endif /* Defined __i386__ */
1948 #ifndef HAVE_GNAT_INIT_FLOAT
1950 /* All targets without a specific __gnat_init_float will use an empty one */
1952 __gnat_init_float (void)
1957 /***********************************/
1958 /* __gnat_adjust_context_for_raise */
1959 /***********************************/
1961 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1963 /* All targets without a specific version will use an empty one */
1965 /* Given UCONTEXT a pointer to a context structure received by a signal
1966 handler for SIGNO, perform the necessary adjustments to let the handler
1967 raise an exception. Calls to this routine are not conditioned by the
1968 propagation scheme in use. */
1971 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
1972 void *ucontext ATTRIBUTE_UNUSED)
1974 /* Adjustments are currently required for the GCC ZCX propagation scheme
1975 only. These adjustments (described below) are harmless for the other
1976 schemes, so may be applied unconditionally. */
1978 /* Adjustments required for a GCC ZCX propagation scheme:
1979 ------------------------------------------------------
1981 The GCC unwinder expects to be dealing with call return addresses, since
1982 this is the "nominal" case of what we retrieve while unwinding a regular
1985 To evaluate if a handler applies at some point identified by a return
1986 address, the propagation engine needs to determine what region the
1987 corresponding call instruction pertains to. Because the return address
1988 may not be attached to the same region as the call, the unwinder always
1989 subtracts "some" amount from a return address to search the region
1990 tables, amount chosen to ensure that the resulting address is inside the
1993 When we raise an exception from a signal handler, e.g. to transform a
1994 SIGSEGV into Storage_Error, things need to appear as if the signal
1995 handler had been "called" by the instruction which triggered the signal,
1996 so that exception handlers that apply there are considered. What the
1997 unwinder will retrieve as the return address from the signal handler is
1998 what it will find as the faulting instruction address in the signal
1999 context pushed by the kernel. Leaving this address untouched looses, if
2000 the triggering instruction happens to be the very first of a region, as
2001 the later adjustments performed by the unwinder would yield an address
2002 outside that region. We need to compensate for the unwinder adjustments
2003 at some point, and this is what this routine is expected to do.
2005 signo is passed because on some targets for some signals the PC in
2006 context points to the instruction after the faulting one, in which case
2007 the unwinder adjustment is still desired.
2009 We used to perform the compensation in the GCC unwinding fallback macro.
2010 The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
2011 describes a couple of issues with this approach. First, on some targets
2012 the adjustment to apply depends on the triggering signal, which is not
2013 easily accessible from the macro. Besides, other languages, e.g. Java,
2014 deal with this by performing the adjustment in the signal handler before
2015 the raise, so fallback adjustments just break those front-ends. */