1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2006, 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. */
70 extern struct Exception_Data constraint_error
;
71 extern struct Exception_Data numeric_error
;
72 extern struct Exception_Data program_error
;
73 extern struct Exception_Data storage_error
;
74 extern struct Exception_Data tasking_error
;
75 extern struct Exception_Data _abort_signal
;
77 #define Lock_Task system__soft_links__lock_task
78 extern void (*Lock_Task
) (void);
80 #define Unlock_Task system__soft_links__unlock_task
81 extern void (*Unlock_Task
) (void);
83 #define Check_Abort_Status \
84 system__soft_links__check_abort_status
85 extern int (*Check_Abort_Status
) (void);
87 #define Raise_From_Signal_Handler \
88 ada__exceptions__raise_from_signal_handler
89 extern void Raise_From_Signal_Handler (struct Exception_Data
*, const char *);
91 /* Copies of global values computed by the binder */
92 int __gl_main_priority
= -1;
93 int __gl_time_slice_val
= -1;
94 char __gl_wc_encoding
= 'n';
95 char __gl_locking_policy
= ' ';
96 char __gl_queuing_policy
= ' ';
97 char __gl_task_dispatching_policy
= ' ';
98 char *__gl_restrictions
= 0;
99 char *__gl_interrupt_states
= 0;
100 int __gl_num_interrupt_states
= 0;
101 int __gl_unreserve_all_interrupts
= 0;
102 int __gl_exception_tracebacks
= 0;
103 int __gl_zero_cost_exceptions
= 0;
104 int __gl_detect_blocking
= 0;
105 int __gl_default_stack_size
= -1;
107 /* Indication of whether synchronous signal handler has already been
108 installed by a previous call to adainit */
109 int __gnat_handler_installed
= 0;
112 int __gnat_inside_elab_final_code
= 0;
113 /* ??? This variable is obsolete since 2001-08-29 but is kept to allow
114 bootstrap from old GNAT versions (< 3.15). */
117 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
118 is defined. If this is not set them a void implementation will be defined
119 at the end of this unit. */
120 #undef HAVE_GNAT_INIT_FLOAT
122 /******************************/
123 /* __gnat_get_interrupt_state */
124 /******************************/
126 char __gnat_get_interrupt_state (int);
128 /* This routine is called from the runtime as needed to determine the state
129 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
130 in the current partition. The input argument is the interrupt number,
131 and the result is one of the following:
133 'n' this interrupt not set by any Interrupt_State pragma
134 'u' Interrupt_State pragma set state to User
135 'r' Interrupt_State pragma set state to Runtime
136 's' Interrupt_State pragma set state to System */
139 __gnat_get_interrupt_state (int intrup
)
141 if (intrup
>= __gl_num_interrupt_states
)
144 return __gl_interrupt_states
[intrup
];
147 /**********************/
148 /* __gnat_set_globals */
149 /**********************/
151 /* This routine is called from the binder generated main program. It copies
152 the values for global quantities computed by the binder into the following
153 global locations. The reason that we go through this copy, rather than just
154 define the global locations in the binder generated file, is that they are
155 referenced from the runtime, which may be in a shared library, and the
156 binder file is not in the shared library. Global references across library
157 boundaries like this are not handled correctly in all systems. */
159 /* For detailed description of the parameters to this routine, see the
160 section titled Run-Time Globals in package Bindgen (bindgen.adb) */
163 __gnat_set_globals (int main_priority
,
168 char task_dispatching_policy
,
170 char *interrupt_states
,
171 int num_interrupt_states
,
172 int unreserve_all_interrupts
,
173 int exception_tracebacks
,
174 int zero_cost_exceptions
,
176 int default_stack_size
)
178 static int already_called
= 0;
180 /* If this procedure has been already called once, check that the
181 arguments in this call are consistent with the ones in the previous
182 calls. Otherwise, raise a Program_Error exception.
184 We do not check for consistency of the wide character encoding
185 method. This default affects only Wide_Text_IO where no explicit
186 coding method is given, and there is no particular reason to let
187 this default be affected by the source representation of a library
190 We do not check either for the consistency of exception tracebacks,
191 because exception tracebacks are not normally set in Stand-Alone
192 libraries. If a library or the main program set the exception
193 tracebacks, then they are never reset afterwards (see below).
195 The value of main_priority is meaningful only when we are invoked
196 from the main program elaboration routine of an Ada application.
197 Checking the consistency of this parameter should therefore not be
198 done. Since it is assured that the main program elaboration will
199 always invoke this procedure before any library elaboration
200 routine, only the value of main_priority during the first call
201 should be taken into account and all the subsequent ones should be
202 ignored. Note that the case where the main program is not written
203 in Ada is also properly handled, since the default value will then
204 be used for this parameter.
206 For identical reasons, the consistency of time_slice_val should not
211 if (__gl_locking_policy
!= locking_policy
212 || __gl_queuing_policy
!= queuing_policy
213 || __gl_task_dispatching_policy
!= task_dispatching_policy
214 || __gl_unreserve_all_interrupts
!= unreserve_all_interrupts
215 || __gl_zero_cost_exceptions
!= zero_cost_exceptions
216 || __gl_default_stack_size
!= default_stack_size
)
217 __gnat_raise_program_error (__FILE__
, __LINE__
);
219 /* If either a library or the main program set the exception traceback
220 flag, it is never reset later */
222 if (exception_tracebacks
!= 0)
223 __gl_exception_tracebacks
= exception_tracebacks
;
229 __gl_main_priority
= main_priority
;
230 __gl_time_slice_val
= time_slice_val
;
231 __gl_wc_encoding
= wc_encoding
;
232 __gl_locking_policy
= locking_policy
;
233 __gl_queuing_policy
= queuing_policy
;
234 __gl_restrictions
= restrictions
;
235 __gl_interrupt_states
= interrupt_states
;
236 __gl_num_interrupt_states
= num_interrupt_states
;
237 __gl_task_dispatching_policy
= task_dispatching_policy
;
238 __gl_unreserve_all_interrupts
= unreserve_all_interrupts
;
239 __gl_exception_tracebacks
= exception_tracebacks
;
240 __gl_detect_blocking
= detect_blocking
;
242 /* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
243 a-except.adb, which is also part of the compiler sources. Since the
244 compiler is built with an older release of GNAT, the call generated by
245 the old binder to this function does not provide any value for the
246 corresponding argument, so the global has to be initialized in some
247 reasonable other way. This could be removed as soon as the next major
250 /* ??? ditto for __gl_default_stack_size, new in 5.04 */
253 __gl_zero_cost_exceptions
= zero_cost_exceptions
;
254 __gl_default_stack_size
= default_stack_size
;
256 __gl_zero_cost_exceptions
= 0;
257 /* We never build the compiler to run in ZCX mode currently anyway. */
261 /* Notes on the Zero Cost Exceptions scheme and its impact on the signal
262 handlers implemented below :
264 What we call Zero Cost Exceptions is implemented using the GCC eh
265 circuitry, even if the underlying implementation is setjmp/longjmp
266 based. In any case ...
268 The GCC unwinder expects to be dealing with call return addresses, since
269 this is the "nominal" case of what we retrieve while unwinding a regular
270 call chain. To evaluate if a handler applies at some point in this chain,
271 the propagation engine needs to determine what region the corresponding
272 call instruction pertains to. The return address may not be attached to the
273 same region as the call, so the unwinder unconditionally subtracts "some"
274 amount to the return addresses it gets to search the region tables. The
275 exact amount is computed to ensure that the resulting address is inside the
276 call instruction, and is thus target dependent (think about delay slots for
279 When we raise an exception from a signal handler, e.g. to transform a
280 SIGSEGV into Storage_Error, things need to appear as if the signal handler
281 had been "called" by the instruction which triggered the signal, so that
282 exception handlers that apply there are considered. What the unwinder will
283 retrieve as the return address from the signal handler is what it will find
284 as the faulting instruction address in the corresponding signal context
285 pushed by the kernel. Leaving this address untouched may loose, because if
286 the triggering instruction happens to be the very first of a region, the
287 later adjustments performed by the unwinder would yield an address outside
288 that region. We need to compensate for those adjustments at some point,
289 which we used to do in the GCC unwinding fallback macro.
291 The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
292 describes a couple of issues with the fallback based compensation approach.
293 First, on some targets the adjustment to apply depends on the triggering
294 signal, which is not easily accessible from the macro. Besides, other
295 languages, e.g. Java, deal with this by performing the adjustment in the
296 signal handler before the raise, so fallback adjustments just break those
299 We now follow the Java way for most targets, via adjust_context_for_raise
309 #include <sys/time.h>
311 /* Some versions of AIX don't define SA_NODEFER. */
315 #endif /* SA_NODEFER */
317 /* Versions of AIX before 4.3 don't have nanosleep but provide
320 #ifndef _AIXVERSION_430
322 extern int nanosleep (struct timestruc_t
*, struct timestruc_t
*);
325 nanosleep (struct timestruc_t
*Rqtp
, struct timestruc_t
*Rmtp
)
327 return nsleep (Rqtp
, Rmtp
);
330 #endif /* _AIXVERSION_430 */
332 static void __gnat_error_handler (int);
335 __gnat_error_handler (int sig
)
337 struct Exception_Data
*exception
;
343 /* FIXME: we need to detect the case of a *real* SIGSEGV */
344 exception
= &storage_error
;
345 msg
= "stack overflow or erroneous memory access";
349 exception
= &constraint_error
;
354 exception
= &constraint_error
;
359 exception
= &program_error
;
360 msg
= "unhandled signal";
363 Raise_From_Signal_Handler (exception
, msg
);
367 __gnat_install_handler (void)
369 struct sigaction act
;
371 /* Set up signal handler to map synchronous signals to appropriate
372 exceptions. Make sure that the handler isn't interrupted by another
373 signal that might cause a scheduling event! */
375 act
.sa_handler
= __gnat_error_handler
;
376 act
.sa_flags
= SA_NODEFER
| SA_RESTART
;
377 sigemptyset (&act
.sa_mask
);
379 /* Do not install handlers if interrupt state is "System" */
380 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
381 sigaction (SIGABRT
, &act
, NULL
);
382 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
383 sigaction (SIGFPE
, &act
, NULL
);
384 if (__gnat_get_interrupt_state (SIGILL
) != 's')
385 sigaction (SIGILL
, &act
, NULL
);
386 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
387 sigaction (SIGSEGV
, &act
, NULL
);
388 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
389 sigaction (SIGBUS
, &act
, NULL
);
391 __gnat_handler_installed
= 1;
398 #elif defined(__alpha__) && defined(__osf__)
401 #include <sys/siginfo.h>
403 static void __gnat_error_handler (int, siginfo_t
*, struct sigcontext
*);
404 extern char *__gnat_get_code_loc (struct sigcontext
*);
405 extern void __gnat_set_code_loc (struct sigcontext
*, char *);
406 extern size_t __gnat_machine_state_length (void);
410 (int sig
, siginfo_t
*sip
, struct sigcontext
*context ATTRIBUTE_UNUSED
)
412 struct Exception_Data
*exception
;
413 static int recurse
= 0;
416 /* If this was an explicit signal from a "kill", just resignal it. */
417 if (SI_FROMUSER (sip
))
419 signal (sig
, SIG_DFL
);
420 kill (getpid(), sig
);
423 /* Otherwise, treat it as something we handle. */
427 /* If the problem was permissions, this is a constraint error.
428 Likewise if the failing address isn't maximally aligned or if
431 ??? Using a static variable here isn't task-safe, but it's
432 much too hard to do anything else and we're just determining
433 which exception to raise. */
434 if (sip
->si_code
== SEGV_ACCERR
435 || (((long) sip
->si_addr
) & 3) != 0
438 exception
= &constraint_error
;
443 /* See if the page before the faulting page is accessible. Do that
444 by trying to access it. We'd like to simply try to access
445 4096 + the faulting address, but it's not guaranteed to be
446 the actual address, just to be on the same page. */
449 ((long) sip
->si_addr
& - getpagesize ()))[getpagesize ()];
450 msg
= "stack overflow (or erroneous memory access)";
451 exception
= &storage_error
;
456 exception
= &program_error
;
461 exception
= &constraint_error
;
466 exception
= &program_error
;
467 msg
= "unhandled signal";
471 Raise_From_Signal_Handler (exception
, (char *) msg
);
475 __gnat_install_handler (void)
477 struct sigaction act
;
479 /* Setup signal handler to map synchronous signals to appropriate
480 exceptions. Make sure that the handler isn't interrupted by another
481 signal that might cause a scheduling event! */
483 act
.sa_handler
= (void (*) (int)) __gnat_error_handler
;
484 act
.sa_flags
= SA_RESTART
| SA_NODEFER
| SA_SIGINFO
;
485 sigemptyset (&act
.sa_mask
);
487 /* Do not install handlers if interrupt state is "System" */
488 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
489 sigaction (SIGABRT
, &act
, NULL
);
490 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
491 sigaction (SIGFPE
, &act
, NULL
);
492 if (__gnat_get_interrupt_state (SIGILL
) != 's')
493 sigaction (SIGILL
, &act
, NULL
);
494 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
495 sigaction (SIGSEGV
, &act
, NULL
);
496 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
497 sigaction (SIGBUS
, &act
, NULL
);
499 __gnat_handler_installed
= 1;
502 /* Routines called by s-mastop-tru64.adb. */
507 __gnat_get_code_loc (struct sigcontext
*context
)
509 return (char *) context
->sc_pc
;
513 __gnat_set_code_loc (struct sigcontext
*context
, char *pc
)
515 context
->sc_pc
= (long) pc
;
520 __gnat_machine_state_length (void)
522 return sizeof (struct sigcontext
);
525 /********************/
526 /* PA HP-UX section */
527 /********************/
529 #elif defined (__hppa__) && defined (__hpux__)
532 #include <sys/ucontext.h>
535 __gnat_error_handler (int sig
, siginfo_t
*siginfo
, void *ucontext
);
537 /* __gnat_adjust_context_for_raise - see comments along with the default
538 version later in this file. */
540 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
543 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
, void *ucontext
)
545 mcontext_t
*mcontext
= &((ucontext_t
*) ucontext
)->uc_mcontext
;
547 if (UseWideRegs (mcontext
))
548 mcontext
->ss_wide
.ss_32
.ss_pcoq_head_lo
++;
550 mcontext
->ss_narrow
.ss_pcoq_head
++;
555 (int sig
, siginfo_t
*siginfo ATTRIBUTE_UNUSED
, void *ucontext
)
557 struct Exception_Data
*exception
;
563 /* FIXME: we need to detect the case of a *real* SIGSEGV */
564 exception
= &storage_error
;
565 msg
= "stack overflow or erroneous memory access";
569 exception
= &constraint_error
;
574 exception
= &constraint_error
;
579 exception
= &program_error
;
580 msg
= "unhandled signal";
583 __gnat_adjust_context_for_raise (sig
, ucontext
);
585 Raise_From_Signal_Handler (exception
, msg
);
589 __gnat_install_handler (void)
591 struct sigaction act
;
593 /* Set up signal handler to map synchronous signals to appropriate
594 exceptions. Make sure that the handler isn't interrupted by another
595 signal that might cause a scheduling event! Also setup an alternate
596 stack region for the handler execution so that stack overflows can be
597 handled properly, avoiding a SEGV generation from stack usage by the
600 static char handler_stack
[SIGSTKSZ
*2];
601 /* SIGSTKSZ appeared to be "short" for the needs in some contexts
602 (e.g. experiments with GCC ZCX exceptions). */
606 stack
.ss_sp
= handler_stack
;
607 stack
.ss_size
= sizeof (handler_stack
);
610 sigaltstack (&stack
, NULL
);
612 act
.sa_sigaction
= __gnat_error_handler
;
613 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_ONSTACK
| SA_SIGINFO
;
614 sigemptyset (&act
.sa_mask
);
616 /* Do not install handlers if interrupt state is "System" */
617 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
618 sigaction (SIGABRT
, &act
, NULL
);
619 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
620 sigaction (SIGFPE
, &act
, NULL
);
621 if (__gnat_get_interrupt_state (SIGILL
) != 's')
622 sigaction (SIGILL
, &act
, NULL
);
623 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
624 sigaction (SIGSEGV
, &act
, NULL
);
625 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
626 sigaction (SIGBUS
, &act
, NULL
);
628 __gnat_handler_installed
= 1;
631 /*********************/
632 /* GNU/Linux Section */
633 /*********************/
635 #elif defined (linux) && (defined (i386) || defined (__x86_64__) \
636 || defined (__ia64__))
640 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
641 #include <sys/ucontext.h>
643 /* GNU/Linux, which uses glibc, does not define NULL in included
647 #define NULL ((void *) 0)
650 static void __gnat_error_handler (int, siginfo_t
*siginfo
, void *ucontext
);
652 /* __gnat_adjust_context_for_raise - see comments along with the default
653 version later in this file. */
655 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
658 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
, void *ucontext
)
660 mcontext_t
*mcontext
= &((ucontext_t
*) ucontext
)->uc_mcontext
;
663 mcontext
->gregs
[REG_EIP
]++;
664 #elif defined (__x86_64__)
665 mcontext
->gregs
[REG_RIP
]++;
666 #elif defined (__ia64__)
672 __gnat_error_handler (int sig
,
673 siginfo_t
*siginfo ATTRIBUTE_UNUSED
,
676 struct Exception_Data
*exception
;
678 static int recurse
= 0;
683 /* If the problem was permissions, this is a constraint error.
684 Likewise if the failing address isn't maximally aligned or if
687 ??? Using a static variable here isn't task-safe, but it's
688 much too hard to do anything else and we're just determining
689 which exception to raise. */
692 exception
= &constraint_error
;
697 /* Here we would like a discrimination test to see whether the
698 page before the faulting address is accessible. Unfortunately
699 Linux seems to have no way of giving us the faulting address.
701 In versions of a-init.c before 1.95, we had a test of the page
702 before the stack pointer using:
706 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
708 but that's wrong, since it tests the stack pointer location, and
709 the current stack probe code does not move the stack pointer
710 until all probes succeed.
712 For now we simply do not attempt any discrimination at all. Note
713 that this is quite acceptable, since a "real" SIGSEGV can only
714 occur as the result of an erroneous program */
716 msg
= "stack overflow (or erroneous memory access)";
717 exception
= &storage_error
;
722 exception
= &constraint_error
;
727 exception
= &constraint_error
;
732 exception
= &program_error
;
733 msg
= "unhandled signal";
737 /* We adjust the interrupted context here (and not in the
738 MD_FALLBACK_FRAME_STATE_FOR macro) because recent versions of the Native
739 POSIX Thread Library (NPTL) are compiled with DWARF 2 unwind information,
740 and hence the later macro is never executed for signal frames. */
742 __gnat_adjust_context_for_raise (sig
, ucontext
);
744 Raise_From_Signal_Handler (exception
, msg
);
748 __gnat_install_handler (void)
750 struct sigaction act
;
752 /* Set up signal handler to map synchronous signals to appropriate
753 exceptions. Make sure that the handler isn't interrupted by another
754 signal that might cause a scheduling event! */
756 act
.sa_sigaction
= __gnat_error_handler
;
757 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_SIGINFO
;
758 sigemptyset (&act
.sa_mask
);
760 /* Do not install handlers if interrupt state is "System" */
761 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
762 sigaction (SIGABRT
, &act
, NULL
);
763 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
764 sigaction (SIGFPE
, &act
, NULL
);
765 if (__gnat_get_interrupt_state (SIGILL
) != 's')
766 sigaction (SIGILL
, &act
, NULL
);
767 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
768 sigaction (SIGSEGV
, &act
, NULL
);
769 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
770 sigaction (SIGBUS
, &act
, NULL
);
772 __gnat_handler_installed
= 1;
775 /*******************/
776 /* Interix Section */
777 /*******************/
779 #elif defined (__INTERIX)
783 static void __gnat_error_handler (int);
786 __gnat_error_handler (int sig
)
788 struct Exception_Data
*exception
;
794 exception
= &storage_error
;
795 msg
= "stack overflow or erroneous memory access";
799 exception
= &constraint_error
;
804 exception
= &constraint_error
;
809 exception
= &program_error
;
810 msg
= "unhandled signal";
813 Raise_From_Signal_Handler (exception
, msg
);
817 __gnat_install_handler (void)
819 struct sigaction act
;
821 /* Set up signal handler to map synchronous signals to appropriate
822 exceptions. Make sure that the handler isn't interrupted by another
823 signal that might cause a scheduling event! */
825 act
.sa_handler
= __gnat_error_handler
;
827 sigemptyset (&act
.sa_mask
);
829 /* Handlers for signals besides SIGSEGV cause c974013 to hang */
830 /* sigaction (SIGILL, &act, NULL); */
831 /* sigaction (SIGABRT, &act, NULL); */
832 /* sigaction (SIGFPE, &act, NULL); */
833 /* sigaction (SIGBUS, &act, NULL); */
835 /* Do not install handlers if interrupt state is "System" */
836 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
837 sigaction (SIGSEGV
, &act
, NULL
);
839 __gnat_handler_installed
= 1;
855 #define SIGADAABORT 48
856 #define SIGNAL_STACK_SIZE 4096
857 #define SIGNAL_STACK_ALIGNMENT 64
859 static void __gnat_error_handler (int, int, sigcontext_t
*);
861 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
862 connecting that handler, with the effects described in the sigaction
866 If cleared and the signal is caught, the first argument is
867 also the signal number but the second argument is the signal
868 code identifying the cause of the signal. The third argument
869 points to a sigcontext_t structure containing the receiving
870 process's context when the signal was delivered.
874 __gnat_error_handler (int sig
, int code
, sigcontext_t
*sc ATTRIBUTE_UNUSED
)
876 struct Exception_Data
*exception
;
884 exception
= &program_error
;
885 msg
= "SIGSEGV: (Invalid virtual address)";
887 else if (code
== ENXIO
)
889 exception
= &program_error
;
890 msg
= "SIGSEGV: (Read beyond mapped object)";
892 else if (code
== ENOSPC
)
894 exception
= &program_error
; /* ??? storage_error ??? */
895 msg
= "SIGSEGV: (Autogrow for file failed)";
897 else if (code
== EACCES
|| code
== EEXIST
)
899 /* ??? We handle stack overflows here, some of which do trigger
900 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
901 the documented valid codes for SEGV in the signal(5) man
904 /* ??? Re-add smarts to further verify that we launched
905 the stack into a guard page, not an attempt to
906 write to .text or something */
907 exception
= &storage_error
;
908 msg
= "SIGSEGV: (stack overflow or erroneous memory access)";
912 /* Just in case the OS guys did it to us again. Sometimes
913 they fail to document all of the valid codes that are
914 passed to signal handlers, just in case someone depends
915 on knowing all the codes */
916 exception
= &program_error
;
917 msg
= "SIGSEGV: (Undocumented reason)";
922 /* Map all bus errors to Program_Error. */
923 exception
= &program_error
;
928 /* Map all fpe errors to Constraint_Error. */
929 exception
= &constraint_error
;
934 if ((*Check_Abort_Status
) ())
936 exception
= &_abort_signal
;
945 /* Everything else is a Program_Error. */
946 exception
= &program_error
;
947 msg
= "unhandled signal";
950 Raise_From_Signal_Handler (exception
, msg
);
954 __gnat_install_handler (void)
956 struct sigaction act
;
958 /* Setup signal handler to map synchronous signals to appropriate
959 exceptions. Make sure that the handler isn't interrupted by another
960 signal that might cause a scheduling event! */
962 act
.sa_handler
= __gnat_error_handler
;
963 act
.sa_flags
= SA_NODEFER
+ SA_RESTART
;
964 sigfillset (&act
.sa_mask
);
965 sigemptyset (&act
.sa_mask
);
967 /* Do not install handlers if interrupt state is "System" */
968 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
969 sigaction (SIGABRT
, &act
, NULL
);
970 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
971 sigaction (SIGFPE
, &act
, NULL
);
972 if (__gnat_get_interrupt_state (SIGILL
) != 's')
973 sigaction (SIGILL
, &act
, NULL
);
974 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
975 sigaction (SIGSEGV
, &act
, NULL
);
976 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
977 sigaction (SIGBUS
, &act
, NULL
);
978 if (__gnat_get_interrupt_state (SIGADAABORT
) != 's')
979 sigaction (SIGADAABORT
, &act
, NULL
);
981 __gnat_handler_installed
= 1;
984 /*******************/
985 /* Solaris Section */
986 /*******************/
988 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
993 static void __gnat_error_handler (int, siginfo_t
*);
996 __gnat_error_handler (int sig
, siginfo_t
*sip
)
998 struct Exception_Data
*exception
;
999 static int recurse
= 0;
1002 /* If this was an explicit signal from a "kill", just resignal it. */
1003 if (SI_FROMUSER (sip
))
1005 signal (sig
, SIG_DFL
);
1006 kill (getpid(), sig
);
1009 /* Otherwise, treat it as something we handle. */
1013 /* If the problem was permissions, this is a constraint error.
1014 Likewise if the failing address isn't maximally aligned or if
1017 ??? Using a static variable here isn't task-safe, but it's
1018 much too hard to do anything else and we're just determining
1019 which exception to raise. */
1020 if (sip
->si_code
== SEGV_ACCERR
1021 || (((long) sip
->si_addr
) & 3) != 0
1024 exception
= &constraint_error
;
1029 /* See if the page before the faulting page is accessible. Do that
1030 by trying to access it. We'd like to simply try to access
1031 4096 + the faulting address, but it's not guaranteed to be
1032 the actual address, just to be on the same page. */
1035 ((long) sip
->si_addr
& - getpagesize ()))[getpagesize ()];
1036 exception
= &storage_error
;
1037 msg
= "stack overflow (or erroneous memory access)";
1042 exception
= &program_error
;
1047 exception
= &constraint_error
;
1052 exception
= &program_error
;
1053 msg
= "unhandled signal";
1058 Raise_From_Signal_Handler (exception
, msg
);
1062 __gnat_install_handler (void)
1064 struct sigaction act
;
1066 /* Set up signal handler to map synchronous signals to appropriate
1067 exceptions. Make sure that the handler isn't interrupted by another
1068 signal that might cause a scheduling event! */
1070 act
.sa_handler
= __gnat_error_handler
;
1071 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_SIGINFO
;
1072 sigemptyset (&act
.sa_mask
);
1074 /* Do not install handlers if interrupt state is "System" */
1075 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
1076 sigaction (SIGABRT
, &act
, NULL
);
1077 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
1078 sigaction (SIGFPE
, &act
, NULL
);
1079 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
1080 sigaction (SIGSEGV
, &act
, NULL
);
1081 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
1082 sigaction (SIGBUS
, &act
, NULL
);
1084 __gnat_handler_installed
= 1;
1093 long __gnat_error_handler (int *, void *);
1096 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1097 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1098 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1100 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1101 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1102 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1105 #if defined (IN_RTS) && !defined (__IA64)
1107 /* The prehandler actually gets control first on a condition. It swaps the
1108 stack pointer and calls the handler (__gnat_error_handler). */
1109 extern long __gnat_error_prehandler (void);
1111 extern char *__gnat_error_prehandler_stack
; /* Alternate signal stack */
1114 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1115 Most of these are also defined in the header file ssdef.h which has not
1116 yet been converted to be recognized by Gnu C. */
1118 /* Defining these as macros, as opposed to external addresses, allows
1119 them to be used in a case statement (below */
1120 #define SS$_ACCVIO 12
1121 #define SS$_HPARITH 1284
1122 #define SS$_STKOVF 1364
1123 #define SS$_RESIGNAL 2328
1125 /* These codes are in standard message libraries */
1126 extern int CMA$_EXIT_THREAD
;
1127 extern int SS$_DEBUG
;
1128 extern int SS$_INTDIV
;
1129 extern int LIB$_KEYNOTFOU
;
1130 extern int LIB$_ACTIMAGE
;
1131 extern int MTH$_FLOOVEMAT
; /* Some ACVC_21 CXA tests */
1133 /* These codes are non standard, which is to say the author is
1134 not sure if they are defined in the standard message libraries
1135 so keep them as macros for now. */
1136 #define RDB$_STREAM_EOF 20480426
1137 #define FDL$_UNPRIKW 11829410
1139 struct cond_except
{
1141 const struct Exception_Data
*except
;
1144 struct descriptor_s
{unsigned short len
, mbz
; __char_ptr32 adr
; };
1146 /* Conditions that don't have an Ada exception counterpart must raise
1147 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1148 referenced by user programs, not the compiler or tools. Hence the
1153 #define Status_Error ada__io_exceptions__status_error
1154 extern struct Exception_Data Status_Error
;
1156 #define Mode_Error ada__io_exceptions__mode_error
1157 extern struct Exception_Data Mode_Error
;
1159 #define Name_Error ada__io_exceptions__name_error
1160 extern struct Exception_Data Name_Error
;
1162 #define Use_Error ada__io_exceptions__use_error
1163 extern struct Exception_Data Use_Error
;
1165 #define Device_Error ada__io_exceptions__device_error
1166 extern struct Exception_Data Device_Error
;
1168 #define End_Error ada__io_exceptions__end_error
1169 extern struct Exception_Data End_Error
;
1171 #define Data_Error ada__io_exceptions__data_error
1172 extern struct Exception_Data Data_Error
;
1174 #define Layout_Error ada__io_exceptions__layout_error
1175 extern struct Exception_Data Layout_Error
;
1177 #define Non_Ada_Error system__aux_dec__non_ada_error
1178 extern struct Exception_Data Non_Ada_Error
;
1180 #define Coded_Exception system__vms_exception_table__coded_exception
1181 extern struct Exception_Data
*Coded_Exception (Exception_Code
);
1183 #define Base_Code_In system__vms_exception_table__base_code_in
1184 extern Exception_Code
Base_Code_In (Exception_Code
);
1186 /* DEC Ada exceptions are not defined in a header file, so they
1187 must be declared as external addresses */
1189 extern int ADA$_PROGRAM_ERROR
__attribute__ ((weak
));
1190 extern int ADA$_LOCK_ERROR
__attribute__ ((weak
));
1191 extern int ADA$_EXISTENCE_ERROR
__attribute__ ((weak
));
1192 extern int ADA$_KEY_ERROR
__attribute__ ((weak
));
1193 extern int ADA$_KEYSIZERR
__attribute__ ((weak
));
1194 extern int ADA$_STAOVF
__attribute__ ((weak
));
1195 extern int ADA$_CONSTRAINT_ERRO
__attribute__ ((weak
));
1196 extern int ADA$_IOSYSFAILED
__attribute__ ((weak
));
1197 extern int ADA$_LAYOUT_ERROR
__attribute__ ((weak
));
1198 extern int ADA$_STORAGE_ERROR
__attribute__ ((weak
));
1199 extern int ADA$_DATA_ERROR
__attribute__ ((weak
));
1200 extern int ADA$_DEVICE_ERROR
__attribute__ ((weak
));
1201 extern int ADA$_END_ERROR
__attribute__ ((weak
));
1202 extern int ADA$_MODE_ERROR
__attribute__ ((weak
));
1203 extern int ADA$_NAME_ERROR
__attribute__ ((weak
));
1204 extern int ADA$_STATUS_ERROR
__attribute__ ((weak
));
1205 extern int ADA$_NOT_OPEN
__attribute__ ((weak
));
1206 extern int ADA$_ALREADY_OPEN
__attribute__ ((weak
));
1207 extern int ADA$_USE_ERROR
__attribute__ ((weak
));
1208 extern int ADA$_UNSUPPORTED
__attribute__ ((weak
));
1209 extern int ADA$_FAC_MODE_MISMAT
__attribute__ ((weak
));
1210 extern int ADA$_ORG_MISMATCH
__attribute__ ((weak
));
1211 extern int ADA$_RFM_MISMATCH
__attribute__ ((weak
));
1212 extern int ADA$_RAT_MISMATCH
__attribute__ ((weak
));
1213 extern int ADA$_MRS_MISMATCH
__attribute__ ((weak
));
1214 extern int ADA$_MRN_MISMATCH
__attribute__ ((weak
));
1215 extern int ADA$_KEY_MISMATCH
__attribute__ ((weak
));
1216 extern int ADA$_MAXLINEXC
__attribute__ ((weak
));
1217 extern int ADA$_LINEXCMRS
__attribute__ ((weak
));
1219 /* DEC Ada specific conditions */
1220 static const struct cond_except dec_ada_cond_except_table
[] = {
1221 {&ADA$_PROGRAM_ERROR
, &program_error
},
1222 {&ADA$_USE_ERROR
, &Use_Error
},
1223 {&ADA$_KEYSIZERR
, &program_error
},
1224 {&ADA$_STAOVF
, &storage_error
},
1225 {&ADA$_CONSTRAINT_ERRO
, &constraint_error
},
1226 {&ADA$_IOSYSFAILED
, &Device_Error
},
1227 {&ADA$_LAYOUT_ERROR
, &Layout_Error
},
1228 {&ADA$_STORAGE_ERROR
, &storage_error
},
1229 {&ADA$_DATA_ERROR
, &Data_Error
},
1230 {&ADA$_DEVICE_ERROR
, &Device_Error
},
1231 {&ADA$_END_ERROR
, &End_Error
},
1232 {&ADA$_MODE_ERROR
, &Mode_Error
},
1233 {&ADA$_NAME_ERROR
, &Name_Error
},
1234 {&ADA$_STATUS_ERROR
, &Status_Error
},
1235 {&ADA$_NOT_OPEN
, &Use_Error
},
1236 {&ADA$_ALREADY_OPEN
, &Use_Error
},
1237 {&ADA$_USE_ERROR
, &Use_Error
},
1238 {&ADA$_UNSUPPORTED
, &Use_Error
},
1239 {&ADA$_FAC_MODE_MISMAT
, &Use_Error
},
1240 {&ADA$_ORG_MISMATCH
, &Use_Error
},
1241 {&ADA$_RFM_MISMATCH
, &Use_Error
},
1242 {&ADA$_RAT_MISMATCH
, &Use_Error
},
1243 {&ADA$_MRS_MISMATCH
, &Use_Error
},
1244 {&ADA$_MRN_MISMATCH
, &Use_Error
},
1245 {&ADA$_KEY_MISMATCH
, &Use_Error
},
1246 {&ADA$_MAXLINEXC
, &constraint_error
},
1247 {&ADA$_LINEXCMRS
, &constraint_error
},
1252 /* Already handled by a pragma Import_Exception
1253 in Aux_IO_Exceptions */
1254 {&ADA$_LOCK_ERROR
, &Lock_Error
},
1255 {&ADA$_EXISTENCE_ERROR
, &Existence_Error
},
1256 {&ADA$_KEY_ERROR
, &Key_Error
},
1261 /* Non DEC Ada specific conditions. We could probably also put
1262 SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
1263 static const struct cond_except cond_except_table
[] = {
1264 {&MTH$_FLOOVEMAT
, &constraint_error
},
1265 {&SS$_INTDIV
, &constraint_error
},
1269 /* To deal with VMS conditions and their mapping to Ada exceptions,
1270 the __gnat_error_handler routine below is installed as an exception
1271 vector having precedence over DEC frame handlers. Some conditions
1272 still need to be handled by such handlers, however, in which case
1273 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
1274 instance the use of a third party library compiled with DECAda and
1275 performing it's own exception handling internally.
1277 To allow some user-level flexibility, which conditions should be
1278 resignaled is controlled by a predicate function, provided with the
1279 condition value and returning a boolean indication stating whether
1280 this condition should be resignaled or not.
1282 That predicate function is called indirectly, via a function pointer,
1283 by __gnat_error_handler, and changing that pointer is allowed to the
1284 the user code by way of the __gnat_set_resignal_predicate interface.
1286 The user level function may then implement what it likes, including
1287 for instance the maintenance of a dynamic data structure if the set
1288 of to be resignalled conditions has to change over the program's
1291 ??? This is not a perfect solution to deal with the possible
1292 interactions between the GNAT and the DECAda exception handling
1293 models and better (more general) schemes are studied. This is so
1294 just provided as a convenient workaround in the meantime, and
1295 should be use with caution since the implementation has been kept
1299 resignal_predicate (int code
);
1301 const int *cond_resignal_table
[] = {
1306 (int *) RDB$_STREAM_EOF
,
1307 (int *) FDL$_UNPRIKW
,
1311 /* Default GNAT predicate for resignaling conditions. */
1314 __gnat_default_resignal_p (int code
)
1318 for (i
= 0, iexcept
= 0;
1319 cond_resignal_table
[i
] &&
1320 !(iexcept
= LIB$
MATCH_COND (&code
, &cond_resignal_table
[i
]));
1326 /* Static pointer to predicate that the __gnat_error_handler exception
1327 vector invokes to determine if it should resignal a condition. */
1329 static resignal_predicate
* __gnat_resignal_p
= __gnat_default_resignal_p
;
1331 /* User interface to change the predicate pointer to PREDICATE. Reset to
1332 the default if PREDICATE is null. */
1335 __gnat_set_resignal_predicate (resignal_predicate
* predicate
)
1338 __gnat_resignal_p
= __gnat_default_resignal_p
;
1340 __gnat_resignal_p
= predicate
;
1343 /* Should match System.Parameters.Default_Exception_Msg_Max_Length */
1344 #define Default_Exception_Msg_Max_Length 512
1346 /* Action routine for SYS$PUTMSG. There may be
1347 multiple conditions, each with text to be appended to
1348 MESSAGE and separated by line termination. */
1351 copy_msg (msgdesc
, message
)
1352 struct descriptor_s
*msgdesc
;
1355 int len
= strlen (message
);
1358 /* Check for buffer overflow and skip */
1359 if (len
> 0 && len
<= Default_Exception_Msg_Max_Length
- 3)
1361 strcat (message
, "\r\n");
1365 /* Check for buffer overflow and truncate if necessary */
1366 copy_len
= (len
+ msgdesc
->len
<= Default_Exception_Msg_Max_Length
- 1 ?
1368 Default_Exception_Msg_Max_Length
- 1 - len
);
1369 strncpy (&message
[len
], msgdesc
->adr
, copy_len
);
1370 message
[len
+ copy_len
] = 0;
1376 __gnat_handle_vms_condition (int *sigargs
, void *mechargs
)
1378 struct Exception_Data
*exception
= 0;
1379 Exception_Code base_code
;
1380 struct descriptor_s gnat_facility
= {4,0,"GNAT"};
1381 char message
[Default_Exception_Msg_Max_Length
];
1383 const char *msg
= "";
1385 /* Check for conditions to resignal which aren't effected by pragma
1386 Import_Exception. */
1387 if (__gnat_resignal_p (sigargs
[1]))
1388 return SS$_RESIGNAL
;
1391 /* See if it's an imported exception. Beware that registered exceptions
1392 are bound to their base code, with the severity bits masked off. */
1393 base_code
= Base_Code_In ((Exception_Code
) sigargs
[1]);
1394 exception
= Coded_Exception (base_code
);
1400 /* Subtract PC & PSL fields which messes with PUTMSG */
1402 SYS$
PUTMSG (sigargs
, copy_msg
, &gnat_facility
, message
);
1406 exception
->Name_Length
= 19;
1407 /* The full name really should be get sys$getmsg returns. ??? */
1408 exception
->Full_Name
= "IMPORTED_EXCEPTION";
1409 exception
->Import_Code
= base_code
;
1417 if (sigargs
[3] == 0)
1419 exception
= &constraint_error
;
1420 msg
= "access zero";
1424 exception
= &storage_error
;
1425 msg
= "stack overflow (or erroneous memory access)";
1430 exception
= &storage_error
;
1431 msg
= "stack overflow";
1436 return SS$_RESIGNAL
; /* toplev.c handles for compiler */
1439 exception
= &constraint_error
;
1440 msg
= "arithmetic error";
1450 /* Scan the DEC Ada exception condition table for a match and fetch
1451 the associated GNAT exception pointer */
1453 dec_ada_cond_except_table
[i
].cond
&&
1454 !LIB$
MATCH_COND (&sigargs
[1],
1455 &dec_ada_cond_except_table
[i
].cond
);
1457 exception
= (struct Exception_Data
*)
1458 dec_ada_cond_except_table
[i
].except
;
1462 /* Scan the VMS standard condition table for a match and fetch
1463 the associated GNAT exception pointer */
1465 cond_except_table
[i
].cond
&&
1466 !LIB$
MATCH_COND (&sigargs
[1], &cond_except_table
[i
].cond
);
1468 exception
=(struct Exception_Data
*) cond_except_table
[i
].except
;
1471 /* User programs expect Non_Ada_Error to be raised, reference
1472 DEC Ada test CXCONDHAN. */
1473 exception
= &Non_Ada_Error
;
1477 exception
= &program_error
;
1480 /* Subtract PC & PSL fields which messes with PUTMSG */
1482 SYS$
PUTMSG (sigargs
, copy_msg
, &gnat_facility
, message
);
1488 __gnat_adjust_context_for_raise (0, (void *)sigargs
);
1489 Raise_From_Signal_Handler (exception
, msg
);
1493 __gnat_error_handler (int *sigargs
, void *mechargs
)
1495 return __gnat_handle_vms_condition (sigargs
, mechargs
);
1499 __gnat_install_handler (void)
1501 long prvhnd ATTRIBUTE_UNUSED
;
1503 #if !defined (IN_RTS)
1504 SYS$
SETEXV (1, __gnat_error_handler
, 3, &prvhnd
);
1507 #if defined (IN_RTS) && defined (__IA64)
1508 if (getenv ("DBG$TDBG"))
1509 printf ("DBG$TDBG defined, __gnat_error_handler not installed!\n");
1511 SYS$
SETEXV (1, __gnat_error_handler
, 3, &prvhnd
);
1514 /* On alpha-vms, we avoid the global vector annoyance thanks to frame based
1515 handlers to turn conditions into exceptions since GCC 3.4. The global
1516 vector is still required for earlier GCC versions. We're resorting to
1517 the __gnat_error_prehandler assembly function in this case. */
1519 #if defined (IN_RTS) && defined (__alpha__)
1520 if ((__GNUC__
* 10 + __GNUC_MINOR__
) < 34)
1522 char * c
= (char *) xmalloc (2049);
1524 __gnat_error_prehandler_stack
= &c
[2048];
1525 SYS$
SETEXV (1, __gnat_error_prehandler
, 3, &prvhnd
);
1529 __gnat_handler_installed
= 1;
1532 /* __gnat_adjust_context_for_raise for alpha - see comments along with the
1533 default version later in this file. */
1535 #if defined (IN_RTS) && defined (__alpha__)
1537 #include <vms/chfctxdef.h>
1538 #include <vms/chfdef.h>
1540 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1543 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
, void *ucontext
)
1545 /* Add one to the address of the instruction signaling the condition,
1546 located in the sigargs array. */
1548 CHF$SIGNAL_ARRAY
* sigargs
= (CHF$SIGNAL_ARRAY
*) ucontext
;
1550 int vcount
= sigargs
->chf$is_sig_args
;
1551 int * pc_slot
= & (&sigargs
->chf$l_sig_name
)[vcount
-2];
1558 /*******************/
1559 /* FreeBSD Section */
1560 /*******************/
1562 #elif defined (__FreeBSD__)
1567 static void __gnat_error_handler (int, int, struct sigcontext
*);
1570 __gnat_error_handler (int sig
, int code
__attribute__ ((unused
)),
1571 struct sigcontext
*sc
__attribute__ ((unused
)))
1573 struct Exception_Data
*exception
;
1579 exception
= &constraint_error
;
1584 exception
= &constraint_error
;
1589 exception
= &storage_error
;
1590 msg
= "stack overflow or erroneous memory access";
1594 exception
= &constraint_error
;
1599 exception
= &program_error
;
1600 msg
= "unhandled signal";
1603 Raise_From_Signal_Handler (exception
, msg
);
1607 __gnat_install_handler ()
1609 struct sigaction act
;
1611 /* Set up signal handler to map synchronous signals to appropriate
1612 exceptions. Make sure that the handler isn't interrupted by another
1613 signal that might cause a scheduling event! */
1615 act
.sa_handler
= __gnat_error_handler
;
1616 act
.sa_flags
= SA_NODEFER
| SA_RESTART
;
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 exception
= &constraint_error
;
1721 exception
= &program_error
;
1725 exception
= &program_error
;
1730 exception
= &program_error
;
1731 msg
= "unhandled signal";
1734 __gnat_clear_exception_count ();
1735 Raise_From_Signal_Handler (exception
, msg
);
1739 __gnat_error_handler (int sig
, int code
, struct sigcontext
*sc
)
1744 /* VxWorks will always mask out the signal during the signal handler and
1745 will reenable it on a longjmp. GNAT does not generate a longjmp to
1746 return from a signal handler so the signal will still be masked unless
1748 sigprocmask (SIG_SETMASK
, NULL
, &mask
);
1749 sigdelset (&mask
, sig
);
1750 sigprocmask (SIG_SETMASK
, &mask
, NULL
);
1752 __gnat_map_signal (sig
);
1757 __gnat_install_handler (void)
1759 struct sigaction act
;
1761 /* Setup signal handler to map synchronous signals to appropriate
1762 exceptions. Make sure that the handler isn't interrupted by another
1763 signal that might cause a scheduling event! */
1765 act
.sa_handler
= __gnat_error_handler
;
1766 act
.sa_flags
= SA_SIGINFO
| SA_ONSTACK
;
1767 sigemptyset (&act
.sa_mask
);
1769 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1770 applies to vectored hardware interrupts, not signals */
1771 sigaction (SIGFPE
, &act
, NULL
);
1772 sigaction (SIGILL
, &act
, NULL
);
1773 sigaction (SIGSEGV
, &act
, NULL
);
1774 sigaction (SIGBUS
, &act
, NULL
);
1776 __gnat_handler_installed
= 1;
1779 #define HAVE_GNAT_INIT_FLOAT
1782 __gnat_init_float (void)
1784 /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1785 to get correct Ada semantics. Note that for AE653 vThreads, the HW
1786 overflow settings are an OS configuration issue. The instructions
1787 below have no effect */
1788 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1793 /* Similarly for sparc64. Achieved by masking bits in the Trap Enable Mask
1794 field of the Floating-point Status Register (see the Sparc Architecture
1795 Manual Version 9, p 48). */
1796 #if defined (sparc64)
1798 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1799 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1800 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1801 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1802 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1806 __asm__("st %%fsr, %0" : "=m" (fsr
));
1807 fsr
&= ~(FSR_TEM_OFM
| FSR_TEM_UFM
);
1808 __asm__("ld %0, %%fsr" : : "m" (fsr
));
1813 /******************/
1814 /* NetBSD Section */
1815 /******************/
1817 #elif defined(__NetBSD__)
1823 __gnat_error_handler (int sig
)
1825 struct Exception_Data
*exception
;
1831 exception
= &constraint_error
;
1835 exception
= &constraint_error
;
1839 exception
= &storage_error
;
1840 msg
= "stack overflow or erroneous memory access";
1843 exception
= &constraint_error
;
1847 exception
= &program_error
;
1848 msg
= "unhandled signal";
1851 Raise_From_Signal_Handler(exception
, msg
);
1855 __gnat_install_handler(void)
1857 struct sigaction act
;
1859 act
.sa_handler
= __gnat_error_handler
;
1860 act
.sa_flags
= SA_NODEFER
| SA_RESTART
;
1861 sigemptyset (&act
.sa_mask
);
1863 /* Do not install handlers if interrupt state is "System" */
1864 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
1865 sigaction (SIGFPE
, &act
, NULL
);
1866 if (__gnat_get_interrupt_state (SIGILL
) != 's')
1867 sigaction (SIGILL
, &act
, NULL
);
1868 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
1869 sigaction (SIGSEGV
, &act
, NULL
);
1870 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
1871 sigaction (SIGBUS
, &act
, NULL
);
1873 __gnat_handler_installed
= 1;
1878 /* For all other versions of GNAT, the handler does nothing */
1880 /*******************/
1881 /* Default Section */
1882 /*******************/
1885 __gnat_install_handler (void)
1887 __gnat_handler_installed
= 1;
1892 /*********************/
1893 /* __gnat_init_float */
1894 /*********************/
1896 /* This routine is called as each process thread is created, for possible
1897 initialization of the FP processor. This version is used under INTERIX,
1898 WIN32 and could be used under OS/2 */
1900 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1901 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1903 #define HAVE_GNAT_INIT_FLOAT
1906 __gnat_init_float (void)
1908 #if defined (__i386__) || defined (i386)
1910 /* This is used to properly initialize the FPU on an x86 for each
1915 #endif /* Defined __i386__ */
1919 #ifndef HAVE_GNAT_INIT_FLOAT
1921 /* All targets without a specific __gnat_init_float will use an empty one */
1923 __gnat_init_float (void)
1928 /***********************************/
1929 /* __gnat_adjust_context_for_raise */
1930 /***********************************/
1932 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1934 /* All targets without a specific version will use an empty one */
1936 /* UCONTEXT is a pointer to a context structure received by a signal handler
1937 about to propagate an exception. Adjust it to compensate the fact that the
1938 generic unwinder thinks the corresponding PC is a call return address. */
1941 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
,
1942 void *ucontext ATTRIBUTE_UNUSED
)
1944 /* The point is that the interrupted context PC typically is the address
1945 that we should search an EH region for, which is different from the call
1946 return address case. The target independent part of the GCC unwinder
1947 don't differentiate the two situations, so we compensate here for the
1948 adjustments it will blindly make.
1950 signo is passed because on some targets for some signals the PC in
1951 context points to the instruction after the faulting one, in which case
1952 the unwinder adjustment is still desired. */
1954 /* On a number of targets, we have arranged for the adjustment to be
1955 performed by the MD_FALLBACK_FRAME_STATE circuitry, so we don't provide a
1956 specific instance of this routine. The MD_FALLBACK doesn't have access
1957 to the signal number, though, so the compensation is systematic there and
1958 might be wrong in some cases. */
1960 /* Having the compensation wrong leads to potential failures. A very
1961 typical case is what happens when there is no compensation and a signal
1962 triggers for the first instruction in a region : the unwinder adjustment
1963 has it search in the wrong EH region. */