Dead
[official-gcc.git] / gomp-20050608-branch / gcc / ada / init.c
blobeb10d6363f1633256225c5db7bcabf1b221ce55d
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. */
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;
111 #ifndef IN_RTS
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). */
115 #endif
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 */
138 char
139 __gnat_get_interrupt_state (int intrup)
141 if (intrup >= __gl_num_interrupt_states)
142 return 'n';
143 else
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) */
162 void
163 __gnat_set_globals (int main_priority,
164 int time_slice_val,
165 char wc_encoding,
166 char locking_policy,
167 char queuing_policy,
168 char task_dispatching_policy,
169 char *restrictions,
170 char *interrupt_states,
171 int num_interrupt_states,
172 int unreserve_all_interrupts,
173 int exception_tracebacks,
174 int zero_cost_exceptions,
175 int detect_blocking,
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
188 in any case.
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
207 be checked. */
209 if (already_called)
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;
225 return;
227 already_called = 1;
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
248 release is out. */
250 /* ??? ditto for __gl_default_stack_size, new in 5.04 */
252 #ifdef IN_RTS
253 __gl_zero_cost_exceptions = zero_cost_exceptions;
254 __gl_default_stack_size = default_stack_size;
255 #else
256 __gl_zero_cost_exceptions = 0;
257 /* We never build the compiler to run in ZCX mode currently anyway. */
258 #endif
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
277 instance).
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
297 front-ends.
299 We now follow the Java way for most targets, via adjust_context_for_raise
300 below. */
302 /***************/
303 /* AIX Section */
304 /***************/
306 #if defined (_AIX)
308 #include <signal.h>
309 #include <sys/time.h>
311 /* Some versions of AIX don't define SA_NODEFER. */
313 #ifndef SA_NODEFER
314 #define SA_NODEFER 0
315 #endif /* SA_NODEFER */
317 /* Versions of AIX before 4.3 don't have nanosleep but provide
318 nsleep instead. */
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);
334 static void
335 __gnat_error_handler (int sig)
337 struct Exception_Data *exception;
338 const char *msg;
340 switch (sig)
342 case SIGSEGV:
343 /* FIXME: we need to detect the case of a *real* SIGSEGV */
344 exception = &storage_error;
345 msg = "stack overflow or erroneous memory access";
346 break;
348 case SIGBUS:
349 exception = &constraint_error;
350 msg = "SIGBUS";
351 break;
353 case SIGFPE:
354 exception = &constraint_error;
355 msg = "SIGFPE";
356 break;
358 default:
359 exception = &program_error;
360 msg = "unhandled signal";
363 Raise_From_Signal_Handler (exception, msg);
366 void
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;
394 /*****************/
395 /* Tru64 section */
396 /*****************/
398 #elif defined(__alpha__) && defined(__osf__)
400 #include <signal.h>
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);
408 static void
409 __gnat_error_handler
410 (int sig, siginfo_t *sip, struct sigcontext *context ATTRIBUTE_UNUSED)
412 struct Exception_Data *exception;
413 static int recurse = 0;
414 const char *msg;
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. */
424 switch (sig)
426 case SIGSEGV:
427 /* If the problem was permissions, this is a constraint error.
428 Likewise if the failing address isn't maximally aligned or if
429 we've recursed.
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
436 || recurse)
438 exception = &constraint_error;
439 msg = "SIGSEGV";
441 else
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. */
447 recurse++;
448 ((volatile char *)
449 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
450 msg = "stack overflow (or erroneous memory access)";
451 exception = &storage_error;
453 break;
455 case SIGBUS:
456 exception = &program_error;
457 msg = "SIGBUS";
458 break;
460 case SIGFPE:
461 exception = &constraint_error;
462 msg = "SIGFPE";
463 break;
465 default:
466 exception = &program_error;
467 msg = "unhandled signal";
470 recurse = 0;
471 Raise_From_Signal_Handler (exception, (char *) msg);
474 void
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. */
504 #define SC_GP 29
506 char *
507 __gnat_get_code_loc (struct sigcontext *context)
509 return (char *) context->sc_pc;
512 void
513 __gnat_set_code_loc (struct sigcontext *context, char *pc)
515 context->sc_pc = (long) pc;
519 size_t
520 __gnat_machine_state_length (void)
522 return sizeof (struct sigcontext);
525 /********************/
526 /* PA HP-UX section */
527 /********************/
529 #elif defined (__hppa__) && defined (__hpux__)
531 #include <signal.h>
532 #include <sys/ucontext.h>
534 static void
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
542 void
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 ++;
549 else
550 mcontext->ss_narrow.ss_pcoq_head ++;
553 static void
554 __gnat_error_handler
555 (int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED, void *ucontext)
557 struct Exception_Data *exception;
558 const char *msg;
560 switch (sig)
562 case SIGSEGV:
563 /* FIXME: we need to detect the case of a *real* SIGSEGV */
564 exception = &storage_error;
565 msg = "stack overflow or erroneous memory access";
566 break;
568 case SIGBUS:
569 exception = &constraint_error;
570 msg = "SIGBUS";
571 break;
573 case SIGFPE:
574 exception = &constraint_error;
575 msg = "SIGFPE";
576 break;
578 default:
579 exception = &program_error;
580 msg = "unhandled signal";
583 __gnat_adjust_context_for_raise (sig, ucontext);
585 Raise_From_Signal_Handler (exception, msg);
588 void
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
598 handler itself. */
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). */
604 stack_t stack;
606 stack.ss_sp = handler_stack;
607 stack.ss_size = sizeof (handler_stack);
608 stack.ss_flags = 0;
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__))
638 #include <signal.h>
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
644 header files */
646 #if !defined (NULL)
647 #define NULL ((void *) 0)
648 #endif
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
657 void
658 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
660 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
662 #if defined (i386)
663 mcontext->gregs[REG_EIP]++;
664 #elif defined (__x86_64__)
665 mcontext->gregs[REG_RIP]++;
666 #elif defined (__ia64__)
667 mcontext->sc_ip++;
668 #endif
671 static void
672 __gnat_error_handler (int sig,
673 siginfo_t *siginfo ATTRIBUTE_UNUSED,
674 void *ucontext)
676 struct Exception_Data *exception;
677 const char *msg;
678 static int recurse = 0;
680 switch (sig)
682 case SIGSEGV:
683 /* If the problem was permissions, this is a constraint error.
684 Likewise if the failing address isn't maximally aligned or if
685 we've recursed.
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. */
690 if (recurse)
692 exception = &constraint_error;
693 msg = "SIGSEGV";
695 else
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:
704 recurse++;
705 ((volatile char *)
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;
719 break;
721 case SIGBUS:
722 exception = &constraint_error;
723 msg = "SIGBUS";
724 break;
726 case SIGFPE:
727 exception = &constraint_error;
728 msg = "SIGFPE";
729 break;
731 default:
732 exception = &program_error;
733 msg = "unhandled signal";
735 recurse = 0;
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);
747 void
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)
781 #include <signal.h>
783 static void __gnat_error_handler (int);
785 static void
786 __gnat_error_handler (int sig)
788 struct Exception_Data *exception;
789 const char *msg;
791 switch (sig)
793 case SIGSEGV:
794 exception = &storage_error;
795 msg = "stack overflow or erroneous memory access";
796 break;
798 case SIGBUS:
799 exception = &constraint_error;
800 msg = "SIGBUS";
801 break;
803 case SIGFPE:
804 exception = &constraint_error;
805 msg = "SIGFPE";
806 break;
808 default:
809 exception = &program_error;
810 msg = "unhandled signal";
813 Raise_From_Signal_Handler (exception, msg);
816 void
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;
826 act.sa_flags = 0;
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;
842 /****************/
843 /* IRIX Section */
844 /****************/
846 #elif defined (sgi)
848 #include <signal.h>
849 #include <siginfo.h>
851 #ifndef NULL
852 #define NULL 0
853 #endif
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
863 man page:
865 SA_SIGINFO [...]
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.
873 static void
874 __gnat_error_handler (int sig, int code, sigcontext_t *sc ATTRIBUTE_UNUSED)
876 struct Exception_Data *exception;
877 const char *msg;
879 switch (sig)
881 case SIGSEGV:
882 if (code == EFAULT)
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
902 page. */
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)";
910 else
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)";
919 break;
921 case SIGBUS:
922 /* Map all bus errors to Program_Error. */
923 exception = &program_error;
924 msg = "SIGBUS";
925 break;
927 case SIGFPE:
928 /* Map all fpe errors to Constraint_Error. */
929 exception = &constraint_error;
930 msg = "SIGFPE";
931 break;
933 case SIGADAABORT:
934 if ((*Check_Abort_Status) ())
936 exception = &_abort_signal;
937 msg = "";
939 else
940 return;
942 break;
944 default:
945 /* Everything else is a Program_Error. */
946 exception = &program_error;
947 msg = "unhandled signal";
950 Raise_From_Signal_Handler (exception, msg);
953 void
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)
990 #include <signal.h>
991 #include <siginfo.h>
993 static void __gnat_error_handler (int, siginfo_t *);
995 static void
996 __gnat_error_handler (int sig, siginfo_t *sip)
998 struct Exception_Data *exception;
999 static int recurse = 0;
1000 const char *msg;
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. */
1010 switch (sig)
1012 case SIGSEGV:
1013 /* If the problem was permissions, this is a constraint error.
1014 Likewise if the failing address isn't maximally aligned or if
1015 we've recursed.
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
1022 || recurse)
1024 exception = &constraint_error;
1025 msg = "SIGSEGV";
1027 else
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. */
1033 recurse++;
1034 ((volatile char *)
1035 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1036 exception = &storage_error;
1037 msg = "stack overflow (or erroneous memory access)";
1039 break;
1041 case SIGBUS:
1042 exception = &program_error;
1043 msg = "SIGBUS";
1044 break;
1046 case SIGFPE:
1047 exception = &constraint_error;
1048 msg = "SIGFPE";
1049 break;
1051 default:
1052 exception = &program_error;
1053 msg = "unhandled signal";
1056 recurse = 0;
1058 Raise_From_Signal_Handler (exception, msg);
1061 void
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;
1087 /***************/
1088 /* VMS Section */
1089 /***************/
1091 #elif defined (VMS)
1093 long __gnat_error_handler (int *, void *);
1095 #ifdef __IA64
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
1099 #else
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
1103 #endif
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 */
1112 #endif
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 {
1140 const int *cond;
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
1149 #ifdef IN_RTS. */
1151 #ifdef IN_RTS
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},
1248 {0, 0}
1251 #if 0
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},
1257 #endif
1259 #endif /* IN_RTS */
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},
1266 {0, 0}
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
1289 lifetime.
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
1296 very simple. */
1298 typedef int
1299 resignal_predicate (int code);
1301 const int *cond_resignal_table [] = {
1302 &CMA$_EXIT_THREAD,
1303 &SS$_DEBUG,
1304 &LIB$_KEYNOTFOU,
1305 &LIB$_ACTIMAGE,
1306 (int *) RDB$_STREAM_EOF,
1307 (int *) FDL$_UNPRIKW,
1311 /* Default GNAT predicate for resignaling conditions. */
1313 static int
1314 __gnat_default_resignal_p (int code)
1316 int i, iexcept;
1318 for (i = 0, iexcept = 0;
1319 cond_resignal_table [i] &&
1320 !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1321 i++);
1323 return iexcept;
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. */
1334 void
1335 __gnat_set_resignal_predicate (resignal_predicate * predicate)
1337 if (predicate == 0)
1338 __gnat_resignal_p = __gnat_default_resignal_p;
1339 else
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. */
1350 static int
1351 copy_msg (msgdesc, message)
1352 struct descriptor_s *msgdesc;
1353 char *message;
1355 int len = strlen (message);
1356 int copy_len;
1358 /* Check for buffer overflow and skip */
1359 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1361 strcat (message, "\r\n");
1362 len += 2;
1365 /* Check for buffer overflow and truncate if necessary */
1366 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1367 msgdesc->len :
1368 Default_Exception_Msg_Max_Length - 1 - len);
1369 strncpy (&message [len], msgdesc->adr, copy_len);
1370 message [len + copy_len] = 0;
1372 return 0;
1375 long
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;
1390 #ifdef IN_RTS
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);
1396 if (exception)
1398 message [0] = 0;
1400 /* Subtract PC & PSL fields which messes with PUTMSG */
1401 sigargs [0] -= 2;
1402 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1403 sigargs [0] += 2;
1404 msg = 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;
1411 #endif
1413 if (exception == 0)
1414 switch (sigargs[1])
1416 case SS$_ACCVIO:
1417 if (sigargs[3] == 0)
1419 exception = &constraint_error;
1420 msg = "access zero";
1422 else
1424 exception = &storage_error;
1425 msg = "stack overflow (or erroneous memory access)";
1427 break;
1429 case SS$_STKOVF:
1430 exception = &storage_error;
1431 msg = "stack overflow";
1432 break;
1434 case SS$_HPARITH:
1435 #ifndef IN_RTS
1436 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1437 #else
1439 exception = &constraint_error;
1440 msg = "arithmetic error";
1442 #endif
1443 break;
1445 default:
1446 #ifdef IN_RTS
1448 int i;
1450 /* Scan the DEC Ada exception condition table for a match and fetch
1451 the associated GNAT exception pointer */
1452 for (i = 0;
1453 dec_ada_cond_except_table [i].cond &&
1454 !LIB$MATCH_COND (&sigargs [1],
1455 &dec_ada_cond_except_table [i].cond);
1456 i++);
1457 exception = (struct Exception_Data *)
1458 dec_ada_cond_except_table [i].except;
1460 if (!exception)
1462 /* Scan the VMS standard condition table for a match and fetch
1463 the associated GNAT exception pointer */
1464 for (i = 0;
1465 cond_except_table [i].cond &&
1466 !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1467 i++);
1468 exception =(struct Exception_Data *) cond_except_table [i].except;
1470 if (!exception)
1471 /* User programs expect Non_Ada_Error to be raised, reference
1472 DEC Ada test CXCONDHAN. */
1473 exception = &Non_Ada_Error;
1476 #else
1477 exception = &program_error;
1478 #endif
1479 message [0] = 0;
1480 /* Subtract PC & PSL fields which messes with PUTMSG */
1481 sigargs [0] -= 2;
1482 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1483 sigargs [0] += 2;
1484 msg = message;
1485 break;
1488 __gnat_adjust_context_for_raise (0, (void *)sigargs);
1489 Raise_From_Signal_Handler (exception, msg);
1492 long
1493 __gnat_error_handler (int *sigargs, void *mechargs)
1495 return __gnat_handle_vms_condition (sigargs, mechargs);
1498 void
1499 __gnat_install_handler (void)
1501 long prvhnd ATTRIBUTE_UNUSED;
1503 #if !defined (IN_RTS)
1504 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1505 #endif
1507 #if defined (IN_RTS) && defined (__IA64)
1508 if (getenv ("DBG$TDBG"))
1509 printf ("DBG$TDBG defined, __gnat_error_handler not installed!\n");
1510 else
1511 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1512 #endif
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);
1527 #endif
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
1542 void
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];
1553 (*pc_slot) ++;
1556 #endif
1558 /*******************/
1559 /* FreeBSD Section */
1560 /*******************/
1562 #elif defined (__FreeBSD__)
1564 #include <signal.h>
1565 #include <unistd.h>
1567 static void __gnat_error_handler (int, int, struct sigcontext *);
1569 static void
1570 __gnat_error_handler (int sig, int code __attribute__ ((unused)),
1571 struct sigcontext *sc __attribute__ ((unused)))
1573 struct Exception_Data *exception;
1574 const char *msg;
1576 switch (sig)
1578 case SIGFPE:
1579 exception = &constraint_error;
1580 msg = "SIGFPE";
1581 break;
1583 case SIGILL:
1584 exception = &constraint_error;
1585 msg = "SIGILL";
1586 break;
1588 case SIGSEGV:
1589 exception = &storage_error;
1590 msg = "stack overflow or erroneous memory access";
1591 break;
1593 case SIGBUS:
1594 exception = &constraint_error;
1595 msg = "SIGBUS";
1596 break;
1598 default:
1599 exception = &program_error;
1600 msg = "unhandled signal";
1603 Raise_From_Signal_Handler (exception, msg);
1606 void
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)
1633 #include <signal.h>
1634 #include <taskLib.h>
1636 #ifndef __RTP__
1637 #include <intLib.h>
1638 #include <iv.h>
1639 #endif
1641 #ifdef VTHREADS
1642 #include "private/vThreadsP.h"
1643 #endif
1645 static void __gnat_error_handler (int, int, struct sigcontext *);
1646 void __gnat_map_signal (int);
1648 #ifndef __RTP__
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);
1660 #endif
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);
1669 long
1670 getpid (void)
1672 return taskIdSelf ();
1674 #endif
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 */
1678 void
1679 __gnat_clear_exception_count (void)
1681 #ifdef VTHREADS
1682 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1684 currentTask->vThreads.excCnt = 0;
1685 #endif
1688 /* Exported to s-intman-vxworks.adb in order to handle different signal
1689 to exception mappings in different VxWorks versions */
1690 void
1691 __gnat_map_signal (int sig)
1693 struct Exception_Data *exception;
1694 const char *msg;
1696 switch (sig)
1698 case SIGFPE:
1699 exception = &constraint_error;
1700 msg = "SIGFPE";
1701 break;
1702 #ifdef VTHREADS
1703 case SIGILL:
1704 exception = &constraint_error;
1705 msg = "Floating point exception or SIGILL";
1706 break;
1707 case SIGSEGV:
1708 exception = &storage_error;
1709 msg = "SIGSEGV: possible stack overflow";
1710 break;
1711 case SIGBUS:
1712 exception = &storage_error;
1713 msg = "SIGBUS: possible stack overflow";
1714 break;
1715 #else
1716 case SIGILL:
1717 exception = &constraint_error;
1718 msg = "SIGILL";
1719 break;
1720 case SIGSEGV:
1721 exception = &program_error;
1722 msg = "SIGSEGV";
1723 break;
1724 case SIGBUS:
1725 exception = &program_error;
1726 msg = "SIGBUS";
1727 break;
1728 #endif
1729 default:
1730 exception = &program_error;
1731 msg = "unhandled signal";
1734 __gnat_clear_exception_count ();
1735 Raise_From_Signal_Handler (exception, msg);
1738 static void
1739 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1741 sigset_t mask;
1742 int result;
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
1747 we unmask it. */
1748 sigprocmask (SIG_SETMASK, NULL, &mask);
1749 sigdelset (&mask, sig);
1750 sigprocmask (SIG_SETMASK, &mask, NULL);
1752 __gnat_map_signal (sig);
1756 void
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
1781 void
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)
1789 asm ("mtfsb0 25");
1790 asm ("mtfsb0 26");
1791 #endif
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 */
1804 unsigned int fsr;
1806 __asm__("st %%fsr, %0" : "=m" (fsr));
1807 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1808 __asm__("ld %0, %%fsr" : : "m" (fsr));
1810 #endif
1813 /******************/
1814 /* NetBSD Section */
1815 /******************/
1817 #elif defined(__NetBSD__)
1819 #include <signal.h>
1820 #include <unistd.h>
1822 static void
1823 __gnat_error_handler (int sig)
1825 struct Exception_Data *exception;
1826 const char *msg;
1828 switch(sig)
1830 case SIGFPE:
1831 exception = &constraint_error;
1832 msg = "SIGFPE";
1833 break;
1834 case SIGILL:
1835 exception = &constraint_error;
1836 msg = "SIGILL";
1837 break;
1838 case SIGSEGV:
1839 exception = &storage_error;
1840 msg = "stack overflow or erroneous memory access";
1841 break;
1842 case SIGBUS:
1843 exception = &constraint_error;
1844 msg = "SIGBUS";
1845 break;
1846 default:
1847 exception = &program_error;
1848 msg = "unhandled signal";
1851 Raise_From_Signal_Handler(exception, msg);
1854 void
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;
1876 #else
1878 /* For all other versions of GNAT, the handler does nothing */
1880 /*******************/
1881 /* Default Section */
1882 /*******************/
1884 void
1885 __gnat_install_handler (void)
1887 __gnat_handler_installed = 1;
1890 #endif
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
1905 void
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
1911 process thread. */
1913 asm ("finit");
1915 #endif /* Defined __i386__ */
1917 #endif
1919 #ifndef HAVE_GNAT_INIT_FLOAT
1921 /* All targets without a specific __gnat_init_float will use an empty one */
1922 void
1923 __gnat_init_float (void)
1926 #endif
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. */
1940 void
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. */
1966 #endif