* invoke.texi (OpenMP): Added index entry.
[official-gcc.git] / gcc / ada / init.c
blob9e3307974531ca3b33ee77de1d50c4b29ad04602
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * I N I T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 1992-2006, Free Software Foundation, Inc. *
10 * *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 2, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
17 * for more details. You should have received a copy of the GNU General *
18 * Public License distributed with GNAT; see file COPYING. If not, write *
19 * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
21 * *
22 * As a special exception, if you link this file with other files to *
23 * produce an executable, this file does not by itself cause the resulting *
24 * executable to be covered by the GNU General Public License. This except- *
25 * ion does not however invalidate any other reasons why the executable *
26 * file might be covered by the GNU Public License. *
27 * *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 * *
31 ****************************************************************************/
33 /* This unit contains initialization circuits that are system dependent. A
34 major part of the functionality involved involves stack overflow checking.
35 The GCC backend generates probe instructions to test for stack overflow.
36 For details on the exact approach used to generate these probes, see the
37 "Using and Porting GCC" manual, in particular the "Stack Checking" section
38 and the subsection "Specifying How Stack Checking is Done". The handlers
39 installed by this file are used to handle resulting signals that come
40 from these probes failing (i.e. touching protected pages) */
42 /* 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. */
48 #ifdef __vxworks
49 #include "vxWorks.h"
50 #endif
52 #ifdef IN_RTS
53 #include "tconfig.h"
54 #include "tsystem.h"
55 #include <sys/stat.h>
57 /* We don't have libiberty, so us malloc. */
58 #define xmalloc(S) malloc (S)
59 #else
60 #include "config.h"
61 #include "system.h"
62 #endif
64 #include "adaint.h"
65 #include "raise.h"
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. */
78 #ifdef CERT
79 #define Raise_From_Signal_Handler \
80 __gnat_raise_exception
81 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
82 #else
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 *);
86 #endif
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;
109 #ifndef IN_RTS
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). */
113 #endif
115 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
116 is defined. If this is not set them a void implementation will be defined
117 at the end of this unit. */
118 #undef HAVE_GNAT_INIT_FLOAT
120 /******************************/
121 /* __gnat_get_interrupt_state */
122 /******************************/
124 char __gnat_get_interrupt_state (int);
126 /* This routine is called from the runtime as needed to determine the state
127 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
128 in the current partition. The input argument is the interrupt number,
129 and the result is one of the following:
131 'n' this interrupt not set by any Interrupt_State pragma
132 'u' Interrupt_State pragma set state to User
133 'r' Interrupt_State pragma set state to Runtime
134 's' Interrupt_State pragma set state to System */
136 char
137 __gnat_get_interrupt_state (int intrup)
139 if (intrup >= __gl_num_interrupt_states)
140 return 'n';
141 else
142 return __gl_interrupt_states [intrup];
145 /***********************************/
146 /* __gnat_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. */
159 char
160 __gnat_get_specific_dispatching (int priority)
162 if (__gl_num_specific_dispatching == 0)
163 return ' ';
164 else if (priority >= __gl_num_specific_dispatching)
165 return 'F';
166 else
167 return __gl_priority_specific_dispatching [priority];
170 #ifndef IN_RTS
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. */
179 void
180 __gnat_set_globals ()
184 #endif
186 /* Notes on the Zero Cost Exceptions scheme and its impact on the signal
187 handlers implemented below :
189 What we call Zero Cost Exceptions is implemented using the GCC eh
190 circuitry, even if the underlying implementation is setjmp/longjmp
191 based. In any case ...
193 The GCC unwinder expects to be dealing with call return addresses, since
194 this is the "nominal" case of what we retrieve while unwinding a regular
195 call chain. To evaluate if a handler applies at some point in this chain,
196 the propagation engine needs to determine what region the corresponding
197 call instruction pertains to. The return address may not be attached to the
198 same region as the call, so the unwinder unconditionally subtracts "some"
199 amount to the return addresses it gets to search the region tables. The
200 exact amount is computed to ensure that the resulting address is inside the
201 call instruction, and is thus target dependent (think about delay slots for
202 instance).
204 When we raise an exception from a signal handler, e.g. to transform a
205 SIGSEGV into Storage_Error, things need to appear as if the signal handler
206 had been "called" by the instruction which triggered the signal, so that
207 exception handlers that apply there are considered. What the unwinder will
208 retrieve as the return address from the signal handler is what it will find
209 as the faulting instruction address in the corresponding signal context
210 pushed by the kernel. Leaving this address untouched may loose, because if
211 the triggering instruction happens to be the very first of a region, the
212 later adjustments performed by the unwinder would yield an address outside
213 that region. We need to compensate for those adjustments at some point,
214 which we used to do in the GCC unwinding fallback macro.
216 The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
217 describes a couple of issues with the fallback based compensation approach.
218 First, on some targets the adjustment to apply depends on the triggering
219 signal, which is not easily accessible from the macro. Besides, other
220 languages, e.g. Java, deal with this by performing the adjustment in the
221 signal handler before the raise, so fallback adjustments just break those
222 front-ends.
224 We now follow the Java way for most targets, via adjust_context_for_raise
225 below. */
227 /***************/
228 /* AIX Section */
229 /***************/
231 #if defined (_AIX)
233 #include <signal.h>
234 #include <sys/time.h>
236 /* Some versions of AIX don't define SA_NODEFER. */
238 #ifndef SA_NODEFER
239 #define SA_NODEFER 0
240 #endif /* SA_NODEFER */
242 /* Versions of AIX before 4.3 don't have nanosleep but provide
243 nsleep instead. */
245 #ifndef _AIXVERSION_430
247 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
250 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
252 return nsleep (Rqtp, Rmtp);
255 #endif /* _AIXVERSION_430 */
257 static void __gnat_error_handler (int);
259 static void
260 __gnat_error_handler (int sig)
262 struct Exception_Data *exception;
263 const char *msg;
265 switch (sig)
267 case SIGSEGV:
268 /* FIXME: we need to detect the case of a *real* SIGSEGV */
269 exception = &storage_error;
270 msg = "stack overflow or erroneous memory access";
271 break;
273 case SIGBUS:
274 exception = &constraint_error;
275 msg = "SIGBUS";
276 break;
278 case SIGFPE:
279 exception = &constraint_error;
280 msg = "SIGFPE";
281 break;
283 default:
284 exception = &program_error;
285 msg = "unhandled signal";
288 Raise_From_Signal_Handler (exception, msg);
291 void
292 __gnat_install_handler (void)
294 struct sigaction act;
296 /* Set up signal handler to map synchronous signals to appropriate
297 exceptions. Make sure that the handler isn't interrupted by another
298 signal that might cause a scheduling event! */
300 act.sa_handler = __gnat_error_handler;
301 act.sa_flags = SA_NODEFER | SA_RESTART;
302 sigemptyset (&act.sa_mask);
304 /* Do not install handlers if interrupt state is "System" */
305 if (__gnat_get_interrupt_state (SIGABRT) != 's')
306 sigaction (SIGABRT, &act, NULL);
307 if (__gnat_get_interrupt_state (SIGFPE) != 's')
308 sigaction (SIGFPE, &act, NULL);
309 if (__gnat_get_interrupt_state (SIGILL) != 's')
310 sigaction (SIGILL, &act, NULL);
311 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
312 sigaction (SIGSEGV, &act, NULL);
313 if (__gnat_get_interrupt_state (SIGBUS) != 's')
314 sigaction (SIGBUS, &act, NULL);
316 __gnat_handler_installed = 1;
319 /*****************/
320 /* Tru64 section */
321 /*****************/
323 #elif defined(__alpha__) && defined(__osf__)
325 #include <signal.h>
326 #include <sys/siginfo.h>
328 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
329 extern char *__gnat_get_code_loc (struct sigcontext *);
330 extern void __gnat_set_code_loc (struct sigcontext *, char *);
331 extern size_t __gnat_machine_state_length (void);
333 static void
334 __gnat_error_handler
335 (int sig, siginfo_t *sip, struct sigcontext *context ATTRIBUTE_UNUSED)
337 struct Exception_Data *exception;
338 static int recurse = 0;
339 const char *msg;
341 /* If this was an explicit signal from a "kill", just resignal it. */
342 if (SI_FROMUSER (sip))
344 signal (sig, SIG_DFL);
345 kill (getpid(), sig);
348 /* Otherwise, treat it as something we handle. */
349 switch (sig)
351 case SIGSEGV:
352 /* If the problem was permissions, this is a constraint error.
353 Likewise if the failing address isn't maximally aligned or if
354 we've recursed.
356 ??? Using a static variable here isn't task-safe, but it's
357 much too hard to do anything else and we're just determining
358 which exception to raise. */
359 if (sip->si_code == SEGV_ACCERR
360 || (((long) sip->si_addr) & 3) != 0
361 || recurse)
363 exception = &constraint_error;
364 msg = "SIGSEGV";
366 else
368 /* See if the page before the faulting page is accessible. Do that
369 by trying to access it. We'd like to simply try to access
370 4096 + the faulting address, but it's not guaranteed to be
371 the actual address, just to be on the same page. */
372 recurse++;
373 ((volatile char *)
374 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
375 msg = "stack overflow (or erroneous memory access)";
376 exception = &storage_error;
378 break;
380 case SIGBUS:
381 exception = &program_error;
382 msg = "SIGBUS";
383 break;
385 case SIGFPE:
386 exception = &constraint_error;
387 msg = "SIGFPE";
388 break;
390 default:
391 exception = &program_error;
392 msg = "unhandled signal";
395 recurse = 0;
396 Raise_From_Signal_Handler (exception, (char *) msg);
399 void
400 __gnat_install_handler (void)
402 struct sigaction act;
404 /* Setup signal handler to map synchronous signals to appropriate
405 exceptions. Make sure that the handler isn't interrupted by another
406 signal that might cause a scheduling event! */
408 act.sa_handler = (void (*) (int)) __gnat_error_handler;
409 act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
410 sigemptyset (&act.sa_mask);
412 /* Do not install handlers if interrupt state is "System" */
413 if (__gnat_get_interrupt_state (SIGABRT) != 's')
414 sigaction (SIGABRT, &act, NULL);
415 if (__gnat_get_interrupt_state (SIGFPE) != 's')
416 sigaction (SIGFPE, &act, NULL);
417 if (__gnat_get_interrupt_state (SIGILL) != 's')
418 sigaction (SIGILL, &act, NULL);
419 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
420 sigaction (SIGSEGV, &act, NULL);
421 if (__gnat_get_interrupt_state (SIGBUS) != 's')
422 sigaction (SIGBUS, &act, NULL);
424 __gnat_handler_installed = 1;
427 /* Routines called by s-mastop-tru64.adb. */
429 #define SC_GP 29
431 char *
432 __gnat_get_code_loc (struct sigcontext *context)
434 return (char *) context->sc_pc;
437 void
438 __gnat_set_code_loc (struct sigcontext *context, char *pc)
440 context->sc_pc = (long) pc;
444 size_t
445 __gnat_machine_state_length (void)
447 return sizeof (struct sigcontext);
450 /********************/
451 /* PA HP-UX section */
452 /********************/
454 #elif defined (__hppa__) && defined (__hpux__)
456 #include <signal.h>
457 #include <sys/ucontext.h>
459 static void
460 __gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext);
462 /* __gnat_adjust_context_for_raise - see comments along with the default
463 version later in this file. */
465 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
467 void
468 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
470 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
472 if (UseWideRegs (mcontext))
473 mcontext->ss_wide.ss_32.ss_pcoq_head_lo ++;
474 else
475 mcontext->ss_narrow.ss_pcoq_head ++;
478 static void
479 __gnat_error_handler
480 (int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED, void *ucontext)
482 struct Exception_Data *exception;
483 const char *msg;
485 switch (sig)
487 case SIGSEGV:
488 /* FIXME: we need to detect the case of a *real* SIGSEGV */
489 exception = &storage_error;
490 msg = "stack overflow or erroneous memory access";
491 break;
493 case SIGBUS:
494 exception = &constraint_error;
495 msg = "SIGBUS";
496 break;
498 case SIGFPE:
499 exception = &constraint_error;
500 msg = "SIGFPE";
501 break;
503 default:
504 exception = &program_error;
505 msg = "unhandled signal";
508 __gnat_adjust_context_for_raise (sig, ucontext);
510 Raise_From_Signal_Handler (exception, msg);
513 void
514 __gnat_install_handler (void)
516 struct sigaction act;
518 /* Set up signal handler to map synchronous signals to appropriate
519 exceptions. Make sure that the handler isn't interrupted by another
520 signal that might cause a scheduling event! Also setup an alternate
521 stack region for the handler execution so that stack overflows can be
522 handled properly, avoiding a SEGV generation from stack usage by the
523 handler itself. */
525 static char handler_stack[SIGSTKSZ*2];
526 /* SIGSTKSZ appeared to be "short" for the needs in some contexts
527 (e.g. experiments with GCC ZCX exceptions). */
529 stack_t stack;
531 stack.ss_sp = handler_stack;
532 stack.ss_size = sizeof (handler_stack);
533 stack.ss_flags = 0;
535 sigaltstack (&stack, NULL);
537 act.sa_sigaction = __gnat_error_handler;
538 act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK | SA_SIGINFO;
539 sigemptyset (&act.sa_mask);
541 /* Do not install handlers if interrupt state is "System" */
542 if (__gnat_get_interrupt_state (SIGABRT) != 's')
543 sigaction (SIGABRT, &act, NULL);
544 if (__gnat_get_interrupt_state (SIGFPE) != 's')
545 sigaction (SIGFPE, &act, NULL);
546 if (__gnat_get_interrupt_state (SIGILL) != 's')
547 sigaction (SIGILL, &act, NULL);
548 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
549 sigaction (SIGSEGV, &act, NULL);
550 if (__gnat_get_interrupt_state (SIGBUS) != 's')
551 sigaction (SIGBUS, &act, NULL);
553 __gnat_handler_installed = 1;
556 /*********************/
557 /* GNU/Linux Section */
558 /*********************/
560 #elif defined (linux) && (defined (i386) || defined (__x86_64__) \
561 || defined (__ia64__))
563 #include <signal.h>
565 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
566 #include <sys/ucontext.h>
568 /* GNU/Linux, which uses glibc, does not define NULL in included
569 header files */
571 #if !defined (NULL)
572 #define NULL ((void *) 0)
573 #endif
575 #if defined (MaRTE)
577 /* MaRTE OS provides its own version of sigaction, sigfillset, and
578 sigemptyset (overriding these symbol names). We want to make sure that
579 the versions provided by the underlying C library are used here (these
580 versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
581 and fake_linux_sigemptyset, respectively). The MaRTE library will not
582 always be present (it will not be linked if no tasking constructs are
583 used), so we use the weak symbol mechanism to point always to the symbols
584 defined within the C library. */
586 #pragma weak linux_sigaction
587 int linux_sigaction (int signum, const struct sigaction *act,
588 struct sigaction *oldact) {
589 return sigaction (signum, act, oldact);
591 #define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
593 #pragma weak fake_linux_sigfillset
594 void fake_linux_sigfillset (sigset_t *set) {
595 sigfillset (set);
597 #define sigfillset(set) fake_linux_sigfillset (set)
599 #pragma weak fake_linux_sigemptyset
600 void fake_linux_sigemptyset (sigset_t *set) {
601 sigemptyset (set);
603 #define sigemptyset(set) fake_linux_sigemptyset (set)
605 #endif
607 static void __gnat_error_handler (int, siginfo_t *siginfo, void *ucontext);
609 /* __gnat_adjust_context_for_raise - see comments along with the default
610 version later in this file. */
612 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
614 void
615 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
617 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
619 #if defined (i386)
620 mcontext->gregs[REG_EIP]++;
621 #elif defined (__x86_64__)
622 mcontext->gregs[REG_RIP]++;
623 #elif defined (__ia64__)
624 mcontext->sc_ip++;
625 #endif
628 static void
629 __gnat_error_handler (int sig,
630 siginfo_t *siginfo ATTRIBUTE_UNUSED,
631 void *ucontext)
633 struct Exception_Data *exception;
634 const char *msg;
635 static int recurse = 0;
637 switch (sig)
639 case SIGSEGV:
640 /* If the problem was permissions, this is a constraint error.
641 Likewise if the failing address isn't maximally aligned or if
642 we've recursed.
644 ??? Using a static variable here isn't task-safe, but it's
645 much too hard to do anything else and we're just determining
646 which exception to raise. */
647 if (recurse)
649 exception = &constraint_error;
650 msg = "SIGSEGV";
652 else
654 /* Here we would like a discrimination test to see whether the
655 page before the faulting address is accessible. Unfortunately
656 Linux seems to have no way of giving us the faulting address.
658 In versions of a-init.c before 1.95, we had a test of the page
659 before the stack pointer using:
661 recurse++;
662 ((volatile char *)
663 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
665 but that's wrong, since it tests the stack pointer location, and
666 the current stack probe code does not move the stack pointer
667 until all probes succeed.
669 For now we simply do not attempt any discrimination at all. Note
670 that this is quite acceptable, since a "real" SIGSEGV can only
671 occur as the result of an erroneous program */
673 msg = "stack overflow (or erroneous memory access)";
674 exception = &storage_error;
676 break;
678 case SIGBUS:
679 exception = &constraint_error;
680 msg = "SIGBUS";
681 break;
683 case SIGFPE:
684 exception = &constraint_error;
685 msg = "SIGFPE";
686 break;
688 default:
689 exception = &program_error;
690 msg = "unhandled signal";
692 recurse = 0;
694 /* We adjust the interrupted context here (and not in the
695 MD_FALLBACK_FRAME_STATE_FOR macro) because recent versions of the Native
696 POSIX Thread Library (NPTL) are compiled with DWARF 2 unwind information,
697 and hence the later macro is never executed for signal frames. */
699 __gnat_adjust_context_for_raise (sig, ucontext);
701 Raise_From_Signal_Handler (exception, msg);
704 void
705 __gnat_install_handler (void)
707 struct sigaction act;
709 /* Set up signal handler to map synchronous signals to appropriate
710 exceptions. Make sure that the handler isn't interrupted by another
711 signal that might cause a scheduling event! */
713 act.sa_sigaction = __gnat_error_handler;
714 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
715 sigemptyset (&act.sa_mask);
717 /* Do not install handlers if interrupt state is "System" */
718 if (__gnat_get_interrupt_state (SIGABRT) != 's')
719 sigaction (SIGABRT, &act, NULL);
720 if (__gnat_get_interrupt_state (SIGFPE) != 's')
721 sigaction (SIGFPE, &act, NULL);
722 if (__gnat_get_interrupt_state (SIGILL) != 's')
723 sigaction (SIGILL, &act, NULL);
724 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
725 sigaction (SIGSEGV, &act, NULL);
726 if (__gnat_get_interrupt_state (SIGBUS) != 's')
727 sigaction (SIGBUS, &act, NULL);
729 __gnat_handler_installed = 1;
732 /*******************/
733 /* Interix Section */
734 /*******************/
736 #elif defined (__INTERIX)
738 #include <signal.h>
740 static void __gnat_error_handler (int);
742 static void
743 __gnat_error_handler (int sig)
745 struct Exception_Data *exception;
746 const char *msg;
748 switch (sig)
750 case SIGSEGV:
751 exception = &storage_error;
752 msg = "stack overflow or erroneous memory access";
753 break;
755 case SIGBUS:
756 exception = &constraint_error;
757 msg = "SIGBUS";
758 break;
760 case SIGFPE:
761 exception = &constraint_error;
762 msg = "SIGFPE";
763 break;
765 default:
766 exception = &program_error;
767 msg = "unhandled signal";
770 Raise_From_Signal_Handler (exception, msg);
773 void
774 __gnat_install_handler (void)
776 struct sigaction act;
778 /* Set up signal handler to map synchronous signals to appropriate
779 exceptions. Make sure that the handler isn't interrupted by another
780 signal that might cause a scheduling event! */
782 act.sa_handler = __gnat_error_handler;
783 act.sa_flags = 0;
784 sigemptyset (&act.sa_mask);
786 /* Handlers for signals besides SIGSEGV cause c974013 to hang */
787 /* sigaction (SIGILL, &act, NULL); */
788 /* sigaction (SIGABRT, &act, NULL); */
789 /* sigaction (SIGFPE, &act, NULL); */
790 /* sigaction (SIGBUS, &act, NULL); */
792 /* Do not install handlers if interrupt state is "System" */
793 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
794 sigaction (SIGSEGV, &act, NULL);
796 __gnat_handler_installed = 1;
799 /****************/
800 /* IRIX Section */
801 /****************/
803 #elif defined (sgi)
805 #include <signal.h>
806 #include <siginfo.h>
808 #ifndef NULL
809 #define NULL 0
810 #endif
812 #define SIGADAABORT 48
813 #define SIGNAL_STACK_SIZE 4096
814 #define SIGNAL_STACK_ALIGNMENT 64
816 #define Check_Abort_Status \
817 system__soft_links__check_abort_status
818 extern int (*Check_Abort_Status) (void);
820 extern struct Exception_Data _abort_signal;
822 static void __gnat_error_handler (int, int, sigcontext_t *);
824 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
825 connecting that handler, with the effects described in the sigaction
826 man page:
828 SA_SIGINFO [...]
829 If cleared and the signal is caught, the first argument is
830 also the signal number but the second argument is the signal
831 code identifying the cause of the signal. The third argument
832 points to a sigcontext_t structure containing the receiving
833 process's context when the signal was delivered.
836 static void
837 __gnat_error_handler (int sig, int code, sigcontext_t *sc ATTRIBUTE_UNUSED)
839 struct Exception_Data *exception;
840 const char *msg;
842 switch (sig)
844 case SIGSEGV:
845 if (code == EFAULT)
847 exception = &program_error;
848 msg = "SIGSEGV: (Invalid virtual address)";
850 else if (code == ENXIO)
852 exception = &program_error;
853 msg = "SIGSEGV: (Read beyond mapped object)";
855 else if (code == ENOSPC)
857 exception = &program_error; /* ??? storage_error ??? */
858 msg = "SIGSEGV: (Autogrow for file failed)";
860 else if (code == EACCES || code == EEXIST)
862 /* ??? We handle stack overflows here, some of which do trigger
863 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
864 the documented valid codes for SEGV in the signal(5) man
865 page. */
867 /* ??? Re-add smarts to further verify that we launched
868 the stack into a guard page, not an attempt to
869 write to .text or something */
870 exception = &storage_error;
871 msg = "SIGSEGV: (stack overflow or erroneous memory access)";
873 else
875 /* Just in case the OS guys did it to us again. Sometimes
876 they fail to document all of the valid codes that are
877 passed to signal handlers, just in case someone depends
878 on knowing all the codes */
879 exception = &program_error;
880 msg = "SIGSEGV: (Undocumented reason)";
882 break;
884 case SIGBUS:
885 /* Map all bus errors to Program_Error. */
886 exception = &program_error;
887 msg = "SIGBUS";
888 break;
890 case SIGFPE:
891 /* Map all fpe errors to Constraint_Error. */
892 exception = &constraint_error;
893 msg = "SIGFPE";
894 break;
896 case SIGADAABORT:
897 if ((*Check_Abort_Status) ())
899 exception = &_abort_signal;
900 msg = "";
902 else
903 return;
905 break;
907 default:
908 /* Everything else is a Program_Error. */
909 exception = &program_error;
910 msg = "unhandled signal";
913 Raise_From_Signal_Handler (exception, msg);
916 void
917 __gnat_install_handler (void)
919 struct sigaction act;
921 /* Setup signal handler to map synchronous signals to appropriate
922 exceptions. Make sure that the handler isn't interrupted by another
923 signal that might cause a scheduling event! */
925 act.sa_handler = __gnat_error_handler;
926 act.sa_flags = SA_NODEFER + SA_RESTART;
927 sigfillset (&act.sa_mask);
928 sigemptyset (&act.sa_mask);
930 /* Do not install handlers if interrupt state is "System" */
931 if (__gnat_get_interrupt_state (SIGABRT) != 's')
932 sigaction (SIGABRT, &act, NULL);
933 if (__gnat_get_interrupt_state (SIGFPE) != 's')
934 sigaction (SIGFPE, &act, NULL);
935 if (__gnat_get_interrupt_state (SIGILL) != 's')
936 sigaction (SIGILL, &act, NULL);
937 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
938 sigaction (SIGSEGV, &act, NULL);
939 if (__gnat_get_interrupt_state (SIGBUS) != 's')
940 sigaction (SIGBUS, &act, NULL);
941 if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
942 sigaction (SIGADAABORT, &act, NULL);
944 __gnat_handler_installed = 1;
947 /*******************/
948 /* Solaris Section */
949 /*******************/
951 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
953 #include <signal.h>
954 #include <siginfo.h>
956 static void __gnat_error_handler (int, siginfo_t *);
958 static void
959 __gnat_error_handler (int sig, siginfo_t *sip)
961 struct Exception_Data *exception;
962 static int recurse = 0;
963 const char *msg;
965 /* If this was an explicit signal from a "kill", just resignal it. */
966 if (SI_FROMUSER (sip))
968 signal (sig, SIG_DFL);
969 kill (getpid(), sig);
972 /* Otherwise, treat it as something we handle. */
973 switch (sig)
975 case SIGSEGV:
976 /* If the problem was permissions, this is a constraint error.
977 Likewise if the failing address isn't maximally aligned or if
978 we've recursed.
980 ??? Using a static variable here isn't task-safe, but it's
981 much too hard to do anything else and we're just determining
982 which exception to raise. */
983 if (sip->si_code == SEGV_ACCERR
984 || (((long) sip->si_addr) & 3) != 0
985 || recurse)
987 exception = &constraint_error;
988 msg = "SIGSEGV";
990 else
992 /* See if the page before the faulting page is accessible. Do that
993 by trying to access it. We'd like to simply try to access
994 4096 + the faulting address, but it's not guaranteed to be
995 the actual address, just to be on the same page. */
996 recurse++;
997 ((volatile char *)
998 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
999 exception = &storage_error;
1000 msg = "stack overflow (or erroneous memory access)";
1002 break;
1004 case SIGBUS:
1005 exception = &program_error;
1006 msg = "SIGBUS";
1007 break;
1009 case SIGFPE:
1010 exception = &constraint_error;
1011 msg = "SIGFPE";
1012 break;
1014 default:
1015 exception = &program_error;
1016 msg = "unhandled signal";
1019 recurse = 0;
1021 Raise_From_Signal_Handler (exception, msg);
1024 void
1025 __gnat_install_handler (void)
1027 struct sigaction act;
1029 /* Set up signal handler to map synchronous signals to appropriate
1030 exceptions. Make sure that the handler isn't interrupted by another
1031 signal that might cause a scheduling event! */
1033 act.sa_handler = __gnat_error_handler;
1034 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1035 sigemptyset (&act.sa_mask);
1037 /* Do not install handlers if interrupt state is "System" */
1038 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1039 sigaction (SIGABRT, &act, NULL);
1040 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1041 sigaction (SIGFPE, &act, NULL);
1042 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1043 sigaction (SIGSEGV, &act, NULL);
1044 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1045 sigaction (SIGBUS, &act, NULL);
1047 __gnat_handler_installed = 1;
1050 /***************/
1051 /* VMS Section */
1052 /***************/
1054 #elif defined (VMS)
1056 long __gnat_error_handler (int *, void *);
1058 #ifdef __IA64
1059 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1060 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1061 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1062 #else
1063 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1064 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1065 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1066 #endif
1068 #if defined (IN_RTS) && !defined (__IA64)
1070 /* The prehandler actually gets control first on a condition. It swaps the
1071 stack pointer and calls the handler (__gnat_error_handler). */
1072 extern long __gnat_error_prehandler (void);
1074 extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
1075 #endif
1077 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1078 Most of these are also defined in the header file ssdef.h which has not
1079 yet been converted to be recognized by Gnu C. */
1081 /* Defining these as macros, as opposed to external addresses, allows
1082 them to be used in a case statement (below */
1083 #define SS$_ACCVIO 12
1084 #define SS$_HPARITH 1284
1085 #define SS$_STKOVF 1364
1086 #define SS$_RESIGNAL 2328
1088 /* These codes are in standard message libraries */
1089 extern int CMA$_EXIT_THREAD;
1090 extern int SS$_DEBUG;
1091 extern int SS$_INTDIV;
1092 extern int LIB$_KEYNOTFOU;
1093 extern int LIB$_ACTIMAGE;
1094 extern int MTH$_FLOOVEMAT; /* Some ACVC_21 CXA tests */
1096 /* These codes are non standard, which is to say the author is
1097 not sure if they are defined in the standard message libraries
1098 so keep them as macros for now. */
1099 #define RDB$_STREAM_EOF 20480426
1100 #define FDL$_UNPRIKW 11829410
1102 struct cond_except {
1103 const int *cond;
1104 const struct Exception_Data *except;
1107 struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1109 /* Conditions that don't have an Ada exception counterpart must raise
1110 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1111 referenced by user programs, not the compiler or tools. Hence the
1112 #ifdef IN_RTS. */
1114 #ifdef IN_RTS
1116 #define Status_Error ada__io_exceptions__status_error
1117 extern struct Exception_Data Status_Error;
1119 #define Mode_Error ada__io_exceptions__mode_error
1120 extern struct Exception_Data Mode_Error;
1122 #define Name_Error ada__io_exceptions__name_error
1123 extern struct Exception_Data Name_Error;
1125 #define Use_Error ada__io_exceptions__use_error
1126 extern struct Exception_Data Use_Error;
1128 #define Device_Error ada__io_exceptions__device_error
1129 extern struct Exception_Data Device_Error;
1131 #define End_Error ada__io_exceptions__end_error
1132 extern struct Exception_Data End_Error;
1134 #define Data_Error ada__io_exceptions__data_error
1135 extern struct Exception_Data Data_Error;
1137 #define Layout_Error ada__io_exceptions__layout_error
1138 extern struct Exception_Data Layout_Error;
1140 #define Non_Ada_Error system__aux_dec__non_ada_error
1141 extern struct Exception_Data Non_Ada_Error;
1143 #define Coded_Exception system__vms_exception_table__coded_exception
1144 extern struct Exception_Data *Coded_Exception (Exception_Code);
1146 #define Base_Code_In system__vms_exception_table__base_code_in
1147 extern Exception_Code Base_Code_In (Exception_Code);
1149 /* DEC Ada exceptions are not defined in a header file, so they
1150 must be declared as external addresses */
1152 extern int ADA$_PROGRAM_ERROR;
1153 extern int ADA$_LOCK_ERROR;
1154 extern int ADA$_EXISTENCE_ERROR;
1155 extern int ADA$_KEY_ERROR;
1156 extern int ADA$_KEYSIZERR;
1157 extern int ADA$_STAOVF;
1158 extern int ADA$_CONSTRAINT_ERRO;
1159 extern int ADA$_IOSYSFAILED;
1160 extern int ADA$_LAYOUT_ERROR;
1161 extern int ADA$_STORAGE_ERROR;
1162 extern int ADA$_DATA_ERROR;
1163 extern int ADA$_DEVICE_ERROR;
1164 extern int ADA$_END_ERROR;
1165 extern int ADA$_MODE_ERROR;
1166 extern int ADA$_NAME_ERROR;
1167 extern int ADA$_STATUS_ERROR;
1168 extern int ADA$_NOT_OPEN;
1169 extern int ADA$_ALREADY_OPEN;
1170 extern int ADA$_USE_ERROR;
1171 extern int ADA$_UNSUPPORTED;
1172 extern int ADA$_FAC_MODE_MISMAT;
1173 extern int ADA$_ORG_MISMATCH;
1174 extern int ADA$_RFM_MISMATCH;
1175 extern int ADA$_RAT_MISMATCH;
1176 extern int ADA$_MRS_MISMATCH;
1177 extern int ADA$_MRN_MISMATCH;
1178 extern int ADA$_KEY_MISMATCH;
1179 extern int ADA$_MAXLINEXC;
1180 extern int ADA$_LINEXCMRS;
1182 /* DEC Ada specific conditions */
1183 static const struct cond_except dec_ada_cond_except_table [] = {
1184 {&ADA$_PROGRAM_ERROR, &program_error},
1185 {&ADA$_USE_ERROR, &Use_Error},
1186 {&ADA$_KEYSIZERR, &program_error},
1187 {&ADA$_STAOVF, &storage_error},
1188 {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1189 {&ADA$_IOSYSFAILED, &Device_Error},
1190 {&ADA$_LAYOUT_ERROR, &Layout_Error},
1191 {&ADA$_STORAGE_ERROR, &storage_error},
1192 {&ADA$_DATA_ERROR, &Data_Error},
1193 {&ADA$_DEVICE_ERROR, &Device_Error},
1194 {&ADA$_END_ERROR, &End_Error},
1195 {&ADA$_MODE_ERROR, &Mode_Error},
1196 {&ADA$_NAME_ERROR, &Name_Error},
1197 {&ADA$_STATUS_ERROR, &Status_Error},
1198 {&ADA$_NOT_OPEN, &Use_Error},
1199 {&ADA$_ALREADY_OPEN, &Use_Error},
1200 {&ADA$_USE_ERROR, &Use_Error},
1201 {&ADA$_UNSUPPORTED, &Use_Error},
1202 {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1203 {&ADA$_ORG_MISMATCH, &Use_Error},
1204 {&ADA$_RFM_MISMATCH, &Use_Error},
1205 {&ADA$_RAT_MISMATCH, &Use_Error},
1206 {&ADA$_MRS_MISMATCH, &Use_Error},
1207 {&ADA$_MRN_MISMATCH, &Use_Error},
1208 {&ADA$_KEY_MISMATCH, &Use_Error},
1209 {&ADA$_MAXLINEXC, &constraint_error},
1210 {&ADA$_LINEXCMRS, &constraint_error},
1211 {0, 0}
1214 #if 0
1215 /* Already handled by a pragma Import_Exception
1216 in Aux_IO_Exceptions */
1217 {&ADA$_LOCK_ERROR, &Lock_Error},
1218 {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1219 {&ADA$_KEY_ERROR, &Key_Error},
1220 #endif
1222 #endif /* IN_RTS */
1224 /* Non DEC Ada specific conditions. We could probably also put
1225 SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
1226 static const struct cond_except cond_except_table [] = {
1227 {&MTH$_FLOOVEMAT, &constraint_error},
1228 {&SS$_INTDIV, &constraint_error},
1229 {0, 0}
1232 /* To deal with VMS conditions and their mapping to Ada exceptions,
1233 the __gnat_error_handler routine below is installed as an exception
1234 vector having precedence over DEC frame handlers. Some conditions
1235 still need to be handled by such handlers, however, in which case
1236 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
1237 instance the use of a third party library compiled with DECAda and
1238 performing it's own exception handling internally.
1240 To allow some user-level flexibility, which conditions should be
1241 resignaled is controlled by a predicate function, provided with the
1242 condition value and returning a boolean indication stating whether
1243 this condition should be resignaled or not.
1245 That predicate function is called indirectly, via a function pointer,
1246 by __gnat_error_handler, and changing that pointer is allowed to the
1247 the user code by way of the __gnat_set_resignal_predicate interface.
1249 The user level function may then implement what it likes, including
1250 for instance the maintenance of a dynamic data structure if the set
1251 of to be resignalled conditions has to change over the program's
1252 lifetime.
1254 ??? This is not a perfect solution to deal with the possible
1255 interactions between the GNAT and the DECAda exception handling
1256 models and better (more general) schemes are studied. This is so
1257 just provided as a convenient workaround in the meantime, and
1258 should be use with caution since the implementation has been kept
1259 very simple. */
1261 typedef int
1262 resignal_predicate (int code);
1264 const int *cond_resignal_table [] = {
1265 &CMA$_EXIT_THREAD,
1266 &SS$_DEBUG,
1267 &LIB$_KEYNOTFOU,
1268 &LIB$_ACTIMAGE,
1269 (int *) RDB$_STREAM_EOF,
1270 (int *) FDL$_UNPRIKW,
1274 const int facility_resignal_table [] = {
1275 0x1380000, /* RDB */
1276 0x2220000, /* SQL */
1280 /* Default GNAT predicate for resignaling conditions. */
1282 static int
1283 __gnat_default_resignal_p (int code)
1285 int i, iexcept;
1287 for (i = 0; facility_resignal_table [i]; i++)
1288 if ((code & 0xfff0000) == facility_resignal_table [i])
1289 return 1;
1291 for (i = 0, iexcept = 0;
1292 cond_resignal_table [i] &&
1293 !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1294 i++);
1296 return iexcept;
1299 /* Static pointer to predicate that the __gnat_error_handler exception
1300 vector invokes to determine if it should resignal a condition. */
1302 static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1304 /* User interface to change the predicate pointer to PREDICATE. Reset to
1305 the default if PREDICATE is null. */
1307 void
1308 __gnat_set_resignal_predicate (resignal_predicate * predicate)
1310 if (predicate == 0)
1311 __gnat_resignal_p = __gnat_default_resignal_p;
1312 else
1313 __gnat_resignal_p = predicate;
1316 /* Should match System.Parameters.Default_Exception_Msg_Max_Length */
1317 #define Default_Exception_Msg_Max_Length 512
1319 /* Action routine for SYS$PUTMSG. There may be
1320 multiple conditions, each with text to be appended to
1321 MESSAGE and separated by line termination. */
1323 static int
1324 copy_msg (msgdesc, message)
1325 struct descriptor_s *msgdesc;
1326 char *message;
1328 int len = strlen (message);
1329 int copy_len;
1331 /* Check for buffer overflow and skip */
1332 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1334 strcat (message, "\r\n");
1335 len += 2;
1338 /* Check for buffer overflow and truncate if necessary */
1339 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1340 msgdesc->len :
1341 Default_Exception_Msg_Max_Length - 1 - len);
1342 strncpy (&message [len], msgdesc->adr, copy_len);
1343 message [len + copy_len] = 0;
1345 return 0;
1348 long
1349 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1351 struct Exception_Data *exception = 0;
1352 Exception_Code base_code;
1353 struct descriptor_s gnat_facility = {4,0,"GNAT"};
1354 char message [Default_Exception_Msg_Max_Length];
1356 const char *msg = "";
1358 /* Check for conditions to resignal which aren't effected by pragma
1359 Import_Exception. */
1360 if (__gnat_resignal_p (sigargs [1]))
1361 return SS$_RESIGNAL;
1363 #ifdef IN_RTS
1364 /* See if it's an imported exception. Beware that registered exceptions
1365 are bound to their base code, with the severity bits masked off. */
1366 base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1367 exception = Coded_Exception (base_code);
1369 if (exception)
1371 message [0] = 0;
1373 /* Subtract PC & PSL fields which messes with PUTMSG */
1374 sigargs [0] -= 2;
1375 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1376 sigargs [0] += 2;
1377 msg = message;
1379 exception->Name_Length = 19;
1380 /* The full name really should be get sys$getmsg returns. ??? */
1381 exception->Full_Name = "IMPORTED_EXCEPTION";
1382 exception->Import_Code = base_code;
1384 #endif
1386 if (exception == 0)
1387 switch (sigargs[1])
1389 case SS$_ACCVIO:
1390 if (sigargs[3] == 0)
1392 exception = &constraint_error;
1393 msg = "access zero";
1395 else
1397 exception = &storage_error;
1398 msg = "stack overflow (or erroneous memory access)";
1400 break;
1402 case SS$_STKOVF:
1403 exception = &storage_error;
1404 msg = "stack overflow";
1405 break;
1407 case SS$_HPARITH:
1408 #ifndef IN_RTS
1409 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1410 #else
1412 exception = &constraint_error;
1413 msg = "arithmetic error";
1415 #endif
1416 break;
1418 default:
1419 #ifdef IN_RTS
1421 int i;
1423 /* Scan the DEC Ada exception condition table for a match and fetch
1424 the associated GNAT exception pointer */
1425 for (i = 0;
1426 dec_ada_cond_except_table [i].cond &&
1427 !LIB$MATCH_COND (&sigargs [1],
1428 &dec_ada_cond_except_table [i].cond);
1429 i++);
1430 exception = (struct Exception_Data *)
1431 dec_ada_cond_except_table [i].except;
1433 if (!exception)
1435 /* Scan the VMS standard condition table for a match and fetch
1436 the associated GNAT exception pointer */
1437 for (i = 0;
1438 cond_except_table [i].cond &&
1439 !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1440 i++);
1441 exception =(struct Exception_Data *) cond_except_table [i].except;
1443 if (!exception)
1444 /* User programs expect Non_Ada_Error to be raised, reference
1445 DEC Ada test CXCONDHAN. */
1446 exception = &Non_Ada_Error;
1449 #else
1450 exception = &program_error;
1451 #endif
1452 message [0] = 0;
1453 /* Subtract PC & PSL fields which messes with PUTMSG */
1454 sigargs [0] -= 2;
1455 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1456 sigargs [0] += 2;
1457 msg = message;
1458 break;
1461 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1462 Raise_From_Signal_Handler (exception, msg);
1465 long
1466 __gnat_error_handler (int *sigargs, void *mechargs)
1468 return __gnat_handle_vms_condition (sigargs, mechargs);
1471 void
1472 __gnat_install_handler (void)
1474 long prvhnd ATTRIBUTE_UNUSED;
1476 #if !defined (IN_RTS)
1477 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1478 #endif
1480 /* On alpha-vms, we avoid the global vector annoyance thanks to frame based
1481 handlers to turn conditions into exceptions since GCC 3.4. The global
1482 vector is still required for earlier GCC versions. We're resorting to
1483 the __gnat_error_prehandler assembly function in this case. */
1485 #if defined (IN_RTS) && defined (__alpha__)
1486 if ((__GNUC__ * 10 + __GNUC_MINOR__) < 34)
1488 char * c = (char *) xmalloc (2049);
1490 __gnat_error_prehandler_stack = &c[2048];
1491 SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1493 #endif
1495 __gnat_handler_installed = 1;
1498 /* __gnat_adjust_context_for_raise for alpha - see comments along with the
1499 default version later in this file. */
1501 #if defined (IN_RTS) && defined (__alpha__)
1503 #include <vms/chfctxdef.h>
1504 #include <vms/chfdef.h>
1506 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1508 void
1509 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1511 /* Add one to the address of the instruction signaling the condition,
1512 located in the sigargs array. */
1514 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1515 CHF$SIGNAL_ARRAY * sigargs
1516 = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1518 int vcount = sigargs->chf$is_sig_args;
1519 int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1521 (*pc_slot) ++;
1524 #endif
1526 /* __gnat_adjust_context_for_raise for ia64. */
1528 #if defined (IN_RTS) && defined (__IA64)
1530 #include <vms/chfctxdef.h>
1531 #include <vms/chfdef.h>
1533 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1535 typedef unsigned long long u64;
1537 void
1538 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1540 /* Add one to the address of the instruction signaling the condition,
1541 located in the 64bits sigargs array. */
1543 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1545 CHF64$SIGNAL_ARRAY *chfsig64
1546 = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1548 u64 * post_sigarray
1549 = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1551 u64 * ih_pc_loc = post_sigarray - 2;
1553 (*ih_pc_loc) ++;
1556 #endif
1558 /*******************/
1559 /* FreeBSD Section */
1560 /*******************/
1562 #elif defined (__FreeBSD__)
1564 #include <signal.h>
1565 #include <sys/ucontext.h>
1566 #include <unistd.h>
1568 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1569 void __gnat_adjust_context_for_raise (int, void*);
1571 /* __gnat_adjust_context_for_raise - see comments along with the default
1572 version later in this file. */
1574 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1576 void
1577 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1579 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
1580 mcontext->mc_eip++;
1583 static void
1584 __gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
1585 ucontext_t *ucontext)
1587 struct Exception_Data *exception;
1588 const char *msg;
1590 switch (sig)
1592 case SIGFPE:
1593 exception = &constraint_error;
1594 msg = "SIGFPE";
1595 break;
1597 case SIGILL:
1598 exception = &constraint_error;
1599 msg = "SIGILL";
1600 break;
1602 case SIGSEGV:
1603 exception = &storage_error;
1604 msg = "stack overflow or erroneous memory access";
1605 break;
1607 case SIGBUS:
1608 exception = &constraint_error;
1609 msg = "SIGBUS";
1610 break;
1612 default:
1613 exception = &program_error;
1614 msg = "unhandled signal";
1617 __gnat_adjust_context_for_raise (sig, ucontext);
1618 Raise_From_Signal_Handler (exception, msg);
1621 void
1622 __gnat_install_handler ()
1624 struct sigaction act;
1626 /* Set up signal handler to map synchronous signals to appropriate
1627 exceptions. Make sure that the handler isn't interrupted by another
1628 signal that might cause a scheduling event! */
1630 act.sa_handler = __gnat_error_handler;
1631 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1632 (void) sigemptyset (&act.sa_mask);
1634 (void) sigaction (SIGILL, &act, NULL);
1635 (void) sigaction (SIGFPE, &act, NULL);
1636 (void) sigaction (SIGSEGV, &act, NULL);
1637 (void) sigaction (SIGBUS, &act, NULL);
1639 __gnat_handler_installed = 1;
1642 /*******************/
1643 /* VxWorks Section */
1644 /*******************/
1646 #elif defined(__vxworks)
1648 #include <signal.h>
1649 #include <taskLib.h>
1651 #ifndef __RTP__
1652 #include <intLib.h>
1653 #include <iv.h>
1654 #endif
1656 #ifdef VTHREADS
1657 #include "private/vThreadsP.h"
1658 #endif
1660 static void __gnat_error_handler (int, int, struct sigcontext *);
1661 void __gnat_map_signal (int);
1663 #ifndef __RTP__
1665 /* Directly vectored Interrupt routines are not supported when using RTPs */
1667 extern int __gnat_inum_to_ivec (int);
1669 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1671 __gnat_inum_to_ivec (int num)
1673 return INUM_TO_IVEC (num);
1675 #endif
1677 #if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1679 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1680 on Alpha VxWorks and VxWorks 6.x (including RTPs). */
1682 extern long getpid (void);
1684 long
1685 getpid (void)
1687 return taskIdSelf ();
1689 #endif
1691 /* VxWorks expects the field excCnt to be zeroed when a signal is handled.
1692 The VxWorks version of longjmp does this; gcc's builtin_longjmp does not */
1693 void
1694 __gnat_clear_exception_count (void)
1696 #ifdef VTHREADS
1697 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1699 currentTask->vThreads.excCnt = 0;
1700 #endif
1703 /* Exported to s-intman-vxworks.adb in order to handle different signal
1704 to exception mappings in different VxWorks versions */
1705 void
1706 __gnat_map_signal (int sig)
1708 struct Exception_Data *exception;
1709 const char *msg;
1711 switch (sig)
1713 case SIGFPE:
1714 exception = &constraint_error;
1715 msg = "SIGFPE";
1716 break;
1717 #ifdef VTHREADS
1718 case SIGILL:
1719 exception = &constraint_error;
1720 msg = "Floating point exception or SIGILL";
1721 break;
1722 case SIGSEGV:
1723 exception = &storage_error;
1724 msg = "SIGSEGV: possible stack overflow";
1725 break;
1726 case SIGBUS:
1727 exception = &storage_error;
1728 msg = "SIGBUS: possible stack overflow";
1729 break;
1730 #else
1731 case SIGILL:
1732 exception = &constraint_error;
1733 msg = "SIGILL";
1734 break;
1735 case SIGSEGV:
1736 exception = &program_error;
1737 msg = "SIGSEGV";
1738 break;
1739 case SIGBUS:
1740 exception = &program_error;
1741 msg = "SIGBUS";
1742 break;
1743 #endif
1744 default:
1745 exception = &program_error;
1746 msg = "unhandled signal";
1749 __gnat_clear_exception_count ();
1750 Raise_From_Signal_Handler (exception, msg);
1753 static void
1754 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1756 sigset_t mask;
1757 int result;
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
1762 we unmask it. */
1763 sigprocmask (SIG_SETMASK, NULL, &mask);
1764 sigdelset (&mask, sig);
1765 sigprocmask (SIG_SETMASK, &mask, NULL);
1767 __gnat_map_signal (sig);
1771 void
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
1796 void
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)
1804 asm ("mtfsb0 25");
1805 asm ("mtfsb0 26");
1806 #endif
1808 /* Similarly for sparc64. Achieved by masking bits in the Trap Enable Mask
1809 field of the Floating-point Status Register (see the SPARC Architecture
1810 Manual Version 9, p 48). */
1811 #if defined (sparc64)
1813 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1814 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1815 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1816 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1817 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1819 unsigned int fsr;
1821 __asm__("st %%fsr, %0" : "=m" (fsr));
1822 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1823 __asm__("ld %0, %%fsr" : : "m" (fsr));
1825 #endif
1828 /******************/
1829 /* NetBSD Section */
1830 /******************/
1832 #elif defined(__NetBSD__)
1834 #include <signal.h>
1835 #include <unistd.h>
1837 static void
1838 __gnat_error_handler (int sig)
1840 struct Exception_Data *exception;
1841 const char *msg;
1843 switch(sig)
1845 case SIGFPE:
1846 exception = &constraint_error;
1847 msg = "SIGFPE";
1848 break;
1849 case SIGILL:
1850 exception = &constraint_error;
1851 msg = "SIGILL";
1852 break;
1853 case SIGSEGV:
1854 exception = &storage_error;
1855 msg = "stack overflow or erroneous memory access";
1856 break;
1857 case SIGBUS:
1858 exception = &constraint_error;
1859 msg = "SIGBUS";
1860 break;
1861 default:
1862 exception = &program_error;
1863 msg = "unhandled signal";
1866 Raise_From_Signal_Handler(exception, msg);
1869 void
1870 __gnat_install_handler(void)
1872 struct sigaction act;
1874 act.sa_handler = __gnat_error_handler;
1875 act.sa_flags = SA_NODEFER | SA_RESTART;
1876 sigemptyset (&act.sa_mask);
1878 /* Do not install handlers if interrupt state is "System" */
1879 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1880 sigaction (SIGFPE, &act, NULL);
1881 if (__gnat_get_interrupt_state (SIGILL) != 's')
1882 sigaction (SIGILL, &act, NULL);
1883 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1884 sigaction (SIGSEGV, &act, NULL);
1885 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1886 sigaction (SIGBUS, &act, NULL);
1888 __gnat_handler_installed = 1;
1891 #else
1893 /* For all other versions of GNAT, the handler does nothing */
1895 /*******************/
1896 /* Default Section */
1897 /*******************/
1899 void
1900 __gnat_install_handler (void)
1902 __gnat_handler_installed = 1;
1905 #endif
1907 /*********************/
1908 /* __gnat_init_float */
1909 /*********************/
1911 /* This routine is called as each process thread is created, for possible
1912 initialization of the FP processor. This version is used under INTERIX,
1913 WIN32 and could be used under OS/2 */
1915 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1916 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1918 #define HAVE_GNAT_INIT_FLOAT
1920 void
1921 __gnat_init_float (void)
1923 #if defined (__i386__) || defined (i386)
1925 /* This is used to properly initialize the FPU on an x86 for each
1926 process thread. */
1928 asm ("finit");
1930 #endif /* Defined __i386__ */
1932 #endif
1934 #ifndef HAVE_GNAT_INIT_FLOAT
1936 /* All targets without a specific __gnat_init_float will use an empty one */
1937 void
1938 __gnat_init_float (void)
1941 #endif
1943 /***********************************/
1944 /* __gnat_adjust_context_for_raise */
1945 /***********************************/
1947 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1949 /* All targets without a specific version will use an empty one */
1951 /* UCONTEXT is a pointer to a context structure received by a signal handler
1952 about to propagate an exception. Adjust it to compensate the fact that the
1953 generic unwinder thinks the corresponding PC is a call return address. */
1955 void
1956 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
1957 void *ucontext ATTRIBUTE_UNUSED)
1959 /* The point is that the interrupted context PC typically is the address
1960 that we should search an EH region for, which is different from the call
1961 return address case. The target independent part of the GCC unwinder
1962 don't differentiate the two situations, so we compensate here for the
1963 adjustments it will blindly make.
1965 signo is passed because on some targets for some signals the PC in
1966 context points to the instruction after the faulting one, in which case
1967 the unwinder adjustment is still desired. */
1969 /* On a number of targets, we have arranged for the adjustment to be
1970 performed by the MD_FALLBACK_FRAME_STATE circuitry, so we don't provide a
1971 specific instance of this routine. The MD_FALLBACK doesn't have access
1972 to the signal number, though, so the compensation is systematic there and
1973 might be wrong in some cases. */
1975 /* Having the compensation wrong leads to potential failures. A very
1976 typical case is what happens when there is no compensation and a signal
1977 triggers for the first instruction in a region : the unwinder adjustment
1978 has it search in the wrong EH region. */
1981 #endif