PR target/16201
[official-gcc.git] / gcc / ada / init.c
blob7858a2bec5cb114f2b6678215ae9c7586898ce73
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * I N I T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 1992-2005 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, 59 Temple Place - Suite 330, Boston, *
20 * MA 02111-1307, 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, and
43 5zinit.adb. All these files implement the required functionality for
44 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 Get_Machine_State_Addr \
84 system__soft_links__get_machine_state_addr
85 extern struct Machine_State *(*Get_Machine_State_Addr) (void);
87 #define Check_Abort_Status \
88 system__soft_links__check_abort_status
89 extern int (*Check_Abort_Status) (void);
91 #define Raise_From_Signal_Handler \
92 ada__exceptions__raise_from_signal_handler
93 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
95 #define Propagate_Signal_Exception \
96 __gnat_propagate_sig_exc
97 extern void Propagate_Signal_Exception (struct Machine_State *,
98 struct Exception_Data *,
99 const char *);
101 /* Copies of global values computed by the binder */
102 int __gl_main_priority = -1;
103 int __gl_time_slice_val = -1;
104 char __gl_wc_encoding = 'n';
105 char __gl_locking_policy = ' ';
106 char __gl_queuing_policy = ' ';
107 char __gl_task_dispatching_policy = ' ';
108 char *__gl_restrictions = 0;
109 char *__gl_interrupt_states = 0;
110 int __gl_num_interrupt_states = 0;
111 int __gl_unreserve_all_interrupts = 0;
112 int __gl_exception_tracebacks = 0;
113 int __gl_zero_cost_exceptions = 0;
114 int __gl_detect_blocking = 0;
116 /* Indication of whether synchronous signal handler has already been
117 installed by a previous call to adainit */
118 int __gnat_handler_installed = 0;
120 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
121 is defined. If this is not set them a void implementation will be defined
122 at the end of this unit. */
123 #undef HAVE_GNAT_INIT_FLOAT
125 /******************************/
126 /* __gnat_get_interrupt_state */
127 /******************************/
129 char __gnat_get_interrupt_state (int);
131 /* This routine is called from the runtime as needed to determine the state
132 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
133 in the current partition. The input argument is the interrupt number,
134 and the result is one of the following:
136 'n' this interrupt not set by any Interrupt_State pragma
137 'u' Interrupt_State pragma set state to User
138 'r' Interrupt_State pragma set state to Runtime
139 's' Interrupt_State pragma set state to System */
141 char
142 __gnat_get_interrupt_state (int intrup)
144 if (intrup >= __gl_num_interrupt_states)
145 return 'n';
146 else
147 return __gl_interrupt_states [intrup];
150 /**********************/
151 /* __gnat_set_globals */
152 /**********************/
154 /* This routine is called from the binder generated main program. It copies
155 the values for global quantities computed by the binder into the following
156 global locations. The reason that we go through this copy, rather than just
157 define the global locations in the binder generated file, is that they are
158 referenced from the runtime, which may be in a shared library, and the
159 binder file is not in the shared library. Global references across library
160 boundaries like this are not handled correctly in all systems. */
162 /* For detailed description of the parameters to this routine, see the
163 section titled Run-Time Globals in package Bindgen (bindgen.adb) */
165 void
166 __gnat_set_globals (int main_priority,
167 int time_slice_val,
168 char wc_encoding,
169 char locking_policy,
170 char queuing_policy,
171 char task_dispatching_policy,
172 char *restrictions,
173 char *interrupt_states,
174 int num_interrupt_states,
175 int unreserve_all_interrupts,
176 int exception_tracebacks,
177 int zero_cost_exceptions,
178 int detect_blocking)
180 static int already_called = 0;
182 /* If this procedure has been already called once, check that the
183 arguments in this call are consistent with the ones in the previous
184 calls. Otherwise, raise a Program_Error exception.
186 We do not check for consistency of the wide character encoding
187 method. This default affects only Wide_Text_IO where no explicit
188 coding method is given, and there is no particular reason to let
189 this default be affected by the source representation of a library
190 in any case.
192 We do not check either for the consistency of exception tracebacks,
193 because exception tracebacks are not normally set in Stand-Alone
194 libraries. If a library or the main program set the exception
195 tracebacks, then they are never reset afterwards (see below).
197 The value of main_priority is meaningful only when we are invoked
198 from the main program elaboration routine of an Ada application.
199 Checking the consistency of this parameter should therefore not be
200 done. Since it is assured that the main program elaboration will
201 always invoke this procedure before any library elaboration
202 routine, only the value of main_priority during the first call
203 should be taken into account and all the subsequent ones should be
204 ignored. Note that the case where the main program is not written
205 in Ada is also properly handled, since the default value will then
206 be used for this parameter.
208 For identical reasons, the consistency of time_slice_val should not
209 be checked. */
211 if (already_called)
213 if (__gl_locking_policy != locking_policy
214 || __gl_queuing_policy != queuing_policy
215 || __gl_task_dispatching_policy != task_dispatching_policy
216 || __gl_unreserve_all_interrupts != unreserve_all_interrupts
217 || __gl_zero_cost_exceptions != zero_cost_exceptions)
218 __gnat_raise_program_error (__FILE__, __LINE__);
220 /* If either a library or the main program set the exception traceback
221 flag, it is never reset later */
223 if (exception_tracebacks != 0)
224 __gl_exception_tracebacks = exception_tracebacks;
226 return;
228 already_called = 1;
230 __gl_main_priority = main_priority;
231 __gl_time_slice_val = time_slice_val;
232 __gl_wc_encoding = wc_encoding;
233 __gl_locking_policy = locking_policy;
234 __gl_queuing_policy = queuing_policy;
235 __gl_restrictions = restrictions;
236 __gl_interrupt_states = interrupt_states;
237 __gl_num_interrupt_states = num_interrupt_states;
238 __gl_task_dispatching_policy = task_dispatching_policy;
239 __gl_unreserve_all_interrupts = unreserve_all_interrupts;
240 __gl_exception_tracebacks = exception_tracebacks;
241 __gl_detect_blocking = detect_blocking;
243 /* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
244 a-except.adb, which is also part of the compiler sources. Since the
245 compiler is built with an older release of GNAT, the call generated by
246 the old binder to this function does not provide any value for the
247 corresponding argument, so the global has to be initialized in some
248 reasonable other way. This could be removed as soon as the next major
249 release is out. */
251 #ifdef IN_RTS
252 __gl_zero_cost_exceptions = zero_cost_exceptions;
253 #else
254 __gl_zero_cost_exceptions = 0;
255 /* We never build the compiler to run in ZCX mode currently anyway. */
256 #endif
259 /*********************/
260 /* __gnat_initialize */
261 /*********************/
263 /* __gnat_initialize is called at the start of execution of an Ada program
264 (the call is generated by the binder). The standard routine does nothing
265 at all; the intention is that this be replaced by system specific
266 code where initialization is required. */
268 /* Notes on the Zero Cost Exceptions scheme and its impact on the signal
269 handlers implemented below :
271 What we call Zero Cost Exceptions is implemented using the GCC eh
272 circuitry, even if the underlying implementation is setjmp/longjmp
273 based. In any case ...
275 The GCC unwinder expects to be dealing with call return addresses, since
276 this is the "nominal" case of what we retrieve while unwinding a regular
277 call chain. To evaluate if a handler applies at some point in this chain,
278 the propagation engine needs to determine what region the corresponding
279 call instruction pertains to. The return address may not be attached to the
280 same region as the call, so the unwinder unconditionally substracts "some"
281 amount to the return addresses it gets to search the region tables. The
282 exact amount is computed to ensure that the resulting address is inside the
283 call instruction, and is thus target dependant (think about delay slots for
284 instance).
286 When we raise an exception from a signal handler, e.g. to transform a
287 SIGSEGV into Storage_Error, things need to appear as if the signal handler
288 had been "called" by the instruction which triggered the signal, so that
289 exception handlers that apply there are considered. What the unwinder will
290 retrieve as the return address from the signal handler is what it will find
291 as the faulting instruction address in the corresponding signal context
292 pushed by the kernel. Leaving this address untouched may loose, because if
293 the triggering instruction happens to be the very first of a region, the
294 later adjustements performed by the unwinder would yield an address outside
295 that region. We need to compensate for those adjustments at some point,
296 which we currently do in the GCC unwinding fallback macro.
298 The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
299 describes a couple of issues with our current approach. Basically: on some
300 targets the adjustment to apply depends on the triggering signal, which is
301 not easily accessible from the macro, and we actually do not tackle this as
302 of today. Besides, other languages, e.g. Java, deal with this by performing
303 the adjustment in the signal handler before the raise, so our adjustments
304 may break those front-ends.
306 To have it all right, we should either find a way to deal with the signal
307 variants from the macro and convert Java on all targets (ugh), or remove
308 our macro adjustments and update our signal handlers a-la-java way. The
309 latter option appears the simplest, although some targets have their share
310 of subtleties to account for. See for instance the syscall(SYS_sigaction)
311 story in libjava/include/i386-signal.h. */
313 /***********************************/
314 /* __gnat_initialize (AIX Version) */
315 /***********************************/
317 #if defined (_AIX)
319 #include <signal.h>
320 #include <sys/time.h>
322 /* Some versions of AIX don't define SA_NODEFER. */
324 #ifndef SA_NODEFER
325 #define SA_NODEFER 0
326 #endif /* SA_NODEFER */
328 /* Versions of AIX before 4.3 don't have nanosleep but provide
329 nsleep instead. */
331 #ifndef _AIXVERSION_430
333 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
336 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
338 return nsleep (Rqtp, Rmtp);
341 #endif /* _AIXVERSION_430 */
343 static void __gnat_error_handler (int);
345 static void
346 __gnat_error_handler (int sig)
348 struct Exception_Data *exception;
349 const char *msg;
351 switch (sig)
353 case SIGSEGV:
354 /* FIXME: we need to detect the case of a *real* SIGSEGV */
355 exception = &storage_error;
356 msg = "stack overflow or erroneous memory access";
357 break;
359 case SIGBUS:
360 exception = &constraint_error;
361 msg = "SIGBUS";
362 break;
364 case SIGFPE:
365 exception = &constraint_error;
366 msg = "SIGFPE";
367 break;
369 default:
370 exception = &program_error;
371 msg = "unhandled signal";
374 Raise_From_Signal_Handler (exception, msg);
377 void
378 __gnat_install_handler (void)
380 struct sigaction act;
382 /* Set up signal handler to map synchronous signals to appropriate
383 exceptions. Make sure that the handler isn't interrupted by another
384 signal that might cause a scheduling event! */
386 act.sa_handler = __gnat_error_handler;
387 act.sa_flags = SA_NODEFER | SA_RESTART;
388 sigemptyset (&act.sa_mask);
390 /* Do not install handlers if interrupt state is "System" */
391 if (__gnat_get_interrupt_state (SIGABRT) != 's')
392 sigaction (SIGABRT, &act, NULL);
393 if (__gnat_get_interrupt_state (SIGFPE) != 's')
394 sigaction (SIGFPE, &act, NULL);
395 if (__gnat_get_interrupt_state (SIGILL) != 's')
396 sigaction (SIGILL, &act, NULL);
397 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
398 sigaction (SIGSEGV, &act, NULL);
399 if (__gnat_get_interrupt_state (SIGBUS) != 's')
400 sigaction (SIGBUS, &act, NULL);
402 __gnat_handler_installed = 1;
405 void
406 __gnat_initialize (void)
410 /***************************************/
411 /* __gnat_initialize (RTEMS version) */
412 /***************************************/
414 #elif defined(__rtems__)
416 extern void __gnat_install_handler (void);
418 /* For RTEMS, each bsp will provide a custom __gnat_install_handler (). */
420 void
421 __gnat_initialize (void)
423 __gnat_install_handler ();
426 /****************************************/
427 /* __gnat_initialize (Dec Unix Version) */
428 /****************************************/
430 #elif defined(__alpha__) && defined(__osf__) && ! defined(__alpha_vxworks)
432 /* Note: it seems that __osf__ is defined for the Alpha VXWorks case. Not
433 clear that this is reasonable, but in any case we have to be sure to
434 exclude this case in the above test. */
436 #include <signal.h>
437 #include <sys/siginfo.h>
439 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
440 extern char *__gnat_get_code_loc (struct sigcontext *);
441 extern void __gnat_enter_handler (struct sigcontext *, char *);
442 extern size_t __gnat_machine_state_length (void);
444 extern long exc_lookup_gp (char *);
445 extern void exc_resume (struct sigcontext *);
447 static void
448 __gnat_error_handler (int sig, siginfo_t *sip, struct sigcontext *context)
450 struct Exception_Data *exception;
451 static int recurse = 0;
452 struct sigcontext *mstate;
453 const char *msg;
455 /* If this was an explicit signal from a "kill", just resignal it. */
456 if (SI_FROMUSER (sip))
458 signal (sig, SIG_DFL);
459 kill (getpid(), sig);
462 /* Otherwise, treat it as something we handle. */
463 switch (sig)
465 case SIGSEGV:
466 /* If the problem was permissions, this is a constraint error.
467 Likewise if the failing address isn't maximally aligned or if
468 we've recursed.
470 ??? Using a static variable here isn't task-safe, but it's
471 much too hard to do anything else and we're just determining
472 which exception to raise. */
473 if (sip->si_code == SEGV_ACCERR
474 || (((long) sip->si_addr) & 3) != 0
475 || recurse)
477 exception = &constraint_error;
478 msg = "SIGSEGV";
480 else
482 /* See if the page before the faulting page is accessible. Do that
483 by trying to access it. We'd like to simply try to access
484 4096 + the faulting address, but it's not guaranteed to be
485 the actual address, just to be on the same page. */
486 recurse++;
487 ((volatile char *)
488 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
489 msg = "stack overflow (or erroneous memory access)";
490 exception = &storage_error;
492 break;
494 case SIGBUS:
495 exception = &program_error;
496 msg = "SIGBUS";
497 break;
499 case SIGFPE:
500 exception = &constraint_error;
501 msg = "SIGFPE";
502 break;
504 default:
505 exception = &program_error;
506 msg = "unhandled signal";
509 recurse = 0;
510 mstate = (struct sigcontext *) (*Get_Machine_State_Addr) ();
511 if (mstate != 0)
512 *mstate = *context;
514 Raise_From_Signal_Handler (exception, (char *) msg);
517 void
518 __gnat_install_handler (void)
520 struct sigaction act;
522 /* Setup signal handler to map synchronous signals to appropriate
523 exceptions. Make sure that the handler isn't interrupted by another
524 signal that might cause a scheduling event! */
526 act.sa_handler = (void (*) (int)) __gnat_error_handler;
527 act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
528 sigemptyset (&act.sa_mask);
530 /* Do not install handlers if interrupt state is "System" */
531 if (__gnat_get_interrupt_state (SIGABRT) != 's')
532 sigaction (SIGABRT, &act, NULL);
533 if (__gnat_get_interrupt_state (SIGFPE) != 's')
534 sigaction (SIGFPE, &act, NULL);
535 if (__gnat_get_interrupt_state (SIGILL) != 's')
536 sigaction (SIGILL, &act, NULL);
537 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
538 sigaction (SIGSEGV, &act, NULL);
539 if (__gnat_get_interrupt_state (SIGBUS) != 's')
540 sigaction (SIGBUS, &act, NULL);
542 __gnat_handler_installed = 1;
545 void
546 __gnat_initialize (void)
550 /* Routines called by 5amastop.adb. */
552 #define SC_GP 29
554 char *
555 __gnat_get_code_loc (struct sigcontext *context)
557 return (char *) context->sc_pc;
560 void
561 __gnat_enter_handler ( struct sigcontext *context, char *pc)
563 context->sc_pc = (long) pc;
564 context->sc_regs[SC_GP] = exc_lookup_gp (pc);
565 exc_resume (context);
568 size_t
569 __gnat_machine_state_length (void)
571 return sizeof (struct sigcontext);
574 /************************************/
575 /* __gnat_initialize (HPUX Version) */
576 /************************************/
578 #elif defined (__hpux__)
580 #include <signal.h>
582 static void __gnat_error_handler (int);
584 static void
585 __gnat_error_handler (int sig)
587 struct Exception_Data *exception;
588 char *msg;
590 switch (sig)
592 case SIGSEGV:
593 /* FIXME: we need to detect the case of a *real* SIGSEGV */
594 exception = &storage_error;
595 msg = "stack overflow or erroneous memory access";
596 break;
598 case SIGBUS:
599 exception = &constraint_error;
600 msg = "SIGBUS";
601 break;
603 case SIGFPE:
604 exception = &constraint_error;
605 msg = "SIGFPE";
606 break;
608 default:
609 exception = &program_error;
610 msg = "unhandled signal";
613 Raise_From_Signal_Handler (exception, msg);
616 void
617 __gnat_install_handler (void)
619 struct sigaction act;
621 /* Set up signal handler to map synchronous signals to appropriate
622 exceptions. Make sure that the handler isn't interrupted by another
623 signal that might cause a scheduling event! Also setup an alternate
624 stack region for the handler execution so that stack overflows can be
625 handled properly, avoiding a SEGV generation from stack usage by the
626 handler itself. */
628 static char handler_stack[SIGSTKSZ*2];
629 /* SIGSTKSZ appeared to be "short" for the needs in some contexts
630 (e.g. experiments with GCC ZCX exceptions). */
632 stack_t stack;
634 stack.ss_sp = handler_stack;
635 stack.ss_size = sizeof (handler_stack);
636 stack.ss_flags = 0;
638 sigaltstack (&stack, NULL);
640 act.sa_handler = __gnat_error_handler;
641 act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK;
642 sigemptyset (&act.sa_mask);
644 /* Do not install handlers if interrupt state is "System" */
645 if (__gnat_get_interrupt_state (SIGABRT) != 's')
646 sigaction (SIGABRT, &act, NULL);
647 if (__gnat_get_interrupt_state (SIGFPE) != 's')
648 sigaction (SIGFPE, &act, NULL);
649 if (__gnat_get_interrupt_state (SIGILL) != 's')
650 sigaction (SIGILL, &act, NULL);
651 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
652 sigaction (SIGSEGV, &act, NULL);
653 if (__gnat_get_interrupt_state (SIGBUS) != 's')
654 sigaction (SIGBUS, &act, NULL);
656 __gnat_handler_installed = 1;
659 void
660 __gnat_initialize (void)
664 /*****************************************/
665 /* __gnat_initialize (GNU/Linux Version) */
666 /*****************************************/
668 #elif defined (linux) && defined (i386) && !defined (__RT__)
670 #include <signal.h>
671 #include <asm/sigcontext.h>
673 /* GNU/Linux, which uses glibc, does not define NULL in included
674 header files */
676 #if !defined (NULL)
677 #define NULL ((void *) 0)
678 #endif
680 struct Machine_State
682 unsigned long eip;
683 unsigned long ebx;
684 unsigned long esp;
685 unsigned long ebp;
686 unsigned long esi;
687 unsigned long edi;
690 static void __gnat_error_handler (int);
692 static void
693 __gnat_error_handler (int sig)
695 struct Exception_Data *exception;
696 const char *msg;
697 static int recurse = 0;
699 struct sigcontext *info
700 = (struct sigcontext *) (((char *) &sig) + sizeof (int));
702 /* The Linux kernel does not document how to get the machine state in a
703 signal handler, but in fact the necessary data is in a sigcontext_struct
704 value that is on the stack immediately above the signal number
705 parameter, and the above messing accesses this value on the stack. */
707 struct Machine_State *mstate;
709 switch (sig)
711 case SIGSEGV:
712 /* If the problem was permissions, this is a constraint error.
713 Likewise if the failing address isn't maximally aligned or if
714 we've recursed.
716 ??? Using a static variable here isn't task-safe, but it's
717 much too hard to do anything else and we're just determining
718 which exception to raise. */
719 if (recurse)
721 exception = &constraint_error;
722 msg = "SIGSEGV";
724 else
726 /* Here we would like a discrimination test to see whether the
727 page before the faulting address is accessible. Unfortunately
728 Linux seems to have no way of giving us the faulting address.
730 In versions of a-init.c before 1.95, we had a test of the page
731 before the stack pointer using:
733 recurse++;
734 ((volatile char *)
735 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
737 but that's wrong, since it tests the stack pointer location, and
738 the current stack probe code does not move the stack pointer
739 until all probes succeed.
741 For now we simply do not attempt any discrimination at all. Note
742 that this is quite acceptable, since a "real" SIGSEGV can only
743 occur as the result of an erroneous program */
745 msg = "stack overflow (or erroneous memory access)";
746 exception = &storage_error;
748 break;
750 case SIGBUS:
751 exception = &constraint_error;
752 msg = "SIGBUS";
753 break;
755 case SIGFPE:
756 exception = &constraint_error;
757 msg = "SIGFPE";
758 break;
760 default:
761 exception = &program_error;
762 msg = "unhandled signal";
765 mstate = (*Get_Machine_State_Addr) ();
766 if (mstate)
768 mstate->eip = info->eip;
769 mstate->ebx = info->ebx;
770 mstate->esp = info->esp_at_signal;
771 mstate->ebp = info->ebp;
772 mstate->esi = info->esi;
773 mstate->edi = info->edi;
776 recurse = 0;
777 Raise_From_Signal_Handler (exception, msg);
780 void
781 __gnat_install_handler (void)
783 struct sigaction act;
785 /* Set up signal handler to map synchronous signals to appropriate
786 exceptions. Make sure that the handler isn't interrupted by another
787 signal that might cause a scheduling event! */
789 act.sa_handler = __gnat_error_handler;
790 act.sa_flags = SA_NODEFER | SA_RESTART;
791 sigemptyset (&act.sa_mask);
793 /* Do not install handlers if interrupt state is "System" */
794 if (__gnat_get_interrupt_state (SIGABRT) != 's')
795 sigaction (SIGABRT, &act, NULL);
796 if (__gnat_get_interrupt_state (SIGFPE) != 's')
797 sigaction (SIGFPE, &act, NULL);
798 if (__gnat_get_interrupt_state (SIGILL) != 's')
799 sigaction (SIGILL, &act, NULL);
800 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
801 sigaction (SIGSEGV, &act, NULL);
802 if (__gnat_get_interrupt_state (SIGBUS) != 's')
803 sigaction (SIGBUS, &act, NULL);
805 __gnat_handler_installed = 1;
808 void
809 __gnat_initialize (void)
813 /******************************************/
814 /* __gnat_initialize (NT-mingw32 Version) */
815 /******************************************/
817 #elif defined (__MINGW32__)
818 #include <windows.h>
820 static LONG WINAPI __gnat_error_handler (PEXCEPTION_POINTERS);
822 /* __gnat_initialize (mingw32). */
824 static LONG WINAPI
825 __gnat_error_handler (PEXCEPTION_POINTERS info)
827 struct Exception_Data *exception;
828 const char *msg;
830 switch (info->ExceptionRecord->ExceptionCode)
832 case EXCEPTION_ACCESS_VIOLATION:
833 /* If the failing address isn't maximally-aligned or if the page
834 before the faulting page is not accessible, this is a program error.
836 if ((info->ExceptionRecord->ExceptionInformation[1] & 3) != 0
837 || IsBadCodePtr
838 ((void *)(info->ExceptionRecord->ExceptionInformation[1] + 4096)))
840 exception = &program_error;
841 msg = "EXCEPTION_ACCESS_VIOLATION";
843 else
845 /* otherwise it is a stack overflow */
846 exception = &storage_error;
847 msg = "stack overflow (or erroneous memory access)";
849 break;
851 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
852 exception = &constraint_error;
853 msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
854 break;
856 case EXCEPTION_DATATYPE_MISALIGNMENT:
857 exception = &constraint_error;
858 msg = "EXCEPTION_DATATYPE_MISALIGNMENT";
859 break;
861 case EXCEPTION_FLT_DENORMAL_OPERAND:
862 exception = &constraint_error;
863 msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
864 break;
866 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
867 exception = &constraint_error;
868 msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
869 break;
871 case EXCEPTION_FLT_INVALID_OPERATION:
872 exception = &constraint_error;
873 msg = "EXCEPTION_FLT_INVALID_OPERATION";
874 break;
876 case EXCEPTION_FLT_OVERFLOW:
877 exception = &constraint_error;
878 msg = "EXCEPTION_FLT_OVERFLOW";
879 break;
881 case EXCEPTION_FLT_STACK_CHECK:
882 exception = &program_error;
883 msg = "EXCEPTION_FLT_STACK_CHECK";
884 break;
886 case EXCEPTION_FLT_UNDERFLOW:
887 exception = &constraint_error;
888 msg = "EXCEPTION_FLT_UNDERFLOW";
889 break;
891 case EXCEPTION_INT_DIVIDE_BY_ZERO:
892 exception = &constraint_error;
893 msg = "EXCEPTION_INT_DIVIDE_BY_ZERO";
894 break;
896 case EXCEPTION_INT_OVERFLOW:
897 exception = &constraint_error;
898 msg = "EXCEPTION_INT_OVERFLOW";
899 break;
901 case EXCEPTION_INVALID_DISPOSITION:
902 exception = &program_error;
903 msg = "EXCEPTION_INVALID_DISPOSITION";
904 break;
906 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
907 exception = &program_error;
908 msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
909 break;
911 case EXCEPTION_PRIV_INSTRUCTION:
912 exception = &program_error;
913 msg = "EXCEPTION_PRIV_INSTRUCTION";
914 break;
916 case EXCEPTION_SINGLE_STEP:
917 exception = &program_error;
918 msg = "EXCEPTION_SINGLE_STEP";
919 break;
921 case EXCEPTION_STACK_OVERFLOW:
922 exception = &storage_error;
923 msg = "EXCEPTION_STACK_OVERFLOW";
924 break;
926 default:
927 exception = &program_error;
928 msg = "unhandled signal";
931 Raise_From_Signal_Handler (exception, msg);
932 return 0; /* This is never reached, avoid compiler warning */
935 void
936 __gnat_install_handler (void)
938 SetUnhandledExceptionFilter (__gnat_error_handler);
939 __gnat_handler_installed = 1;
942 void
943 __gnat_initialize (void)
946 /* Initialize floating-point coprocessor. This call is needed because
947 the MS libraries default to 64-bit precision instead of 80-bit
948 precision, and we require the full precision for proper operation,
949 given that we have set Max_Digits etc with this in mind */
951 __gnat_init_float ();
953 /* initialize a lock for a process handle list - see a-adaint.c for the
954 implementation of __gnat_portable_no_block_spawn, __gnat_portable_wait */
955 __gnat_plist_init();
958 /***************************************/
959 /* __gnat_initialize (Interix Version) */
960 /***************************************/
962 #elif defined (__INTERIX)
964 #include <signal.h>
966 static void __gnat_error_handler (int);
968 static void
969 __gnat_error_handler (int sig)
971 struct Exception_Data *exception;
972 char *msg;
974 switch (sig)
976 case SIGSEGV:
977 exception = &storage_error;
978 msg = "stack overflow or erroneous memory access";
979 break;
981 case SIGBUS:
982 exception = &constraint_error;
983 msg = "SIGBUS";
984 break;
986 case SIGFPE:
987 exception = &constraint_error;
988 msg = "SIGFPE";
989 break;
991 default:
992 exception = &program_error;
993 msg = "unhandled signal";
996 Raise_From_Signal_Handler (exception, msg);
999 void
1000 __gnat_install_handler (void)
1002 struct sigaction act;
1004 /* Set up signal handler to map synchronous signals to appropriate
1005 exceptions. Make sure that the handler isn't interrupted by another
1006 signal that might cause a scheduling event! */
1008 act.sa_handler = __gnat_error_handler;
1009 act.sa_flags = 0;
1010 sigemptyset (&act.sa_mask);
1012 /* Handlers for signals besides SIGSEGV cause c974013 to hang */
1013 /* sigaction (SIGILL, &act, NULL); */
1014 /* sigaction (SIGABRT, &act, NULL); */
1015 /* sigaction (SIGFPE, &act, NULL); */
1016 /* sigaction (SIGBUS, &act, NULL); */
1018 /* Do not install handlers if interrupt state is "System" */
1019 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1020 sigaction (SIGSEGV, &act, NULL);
1022 __gnat_handler_installed = 1;
1025 void
1026 __gnat_initialize (void)
1028 __gnat_init_float ();
1031 /**************************************/
1032 /* __gnat_initialize (LynxOS Version) */
1033 /**************************************/
1035 #elif defined (__Lynx__)
1037 void
1038 __gnat_initialize (void)
1040 __gnat_init_float ();
1043 /*********************************/
1044 /* __gnat_install_handler (Lynx) */
1045 /*********************************/
1047 void
1048 __gnat_install_handler (void)
1050 __gnat_handler_installed = 1;
1053 /****************************/
1054 /* __gnat_initialize (OS/2) */
1055 /****************************/
1057 #elif defined (__EMX__) /* OS/2 dependent initialization */
1059 void
1060 __gnat_initialize (void)
1064 /*********************************/
1065 /* __gnat_install_handler (OS/2) */
1066 /*********************************/
1068 void
1069 __gnat_install_handler (void)
1071 __gnat_handler_installed = 1;
1074 /***********************************/
1075 /* __gnat_initialize (SGI Version) */
1076 /***********************************/
1078 #elif defined (sgi)
1080 #include <signal.h>
1081 #include <siginfo.h>
1083 #ifndef NULL
1084 #define NULL 0
1085 #endif
1087 #define SIGADAABORT 48
1088 #define SIGNAL_STACK_SIZE 4096
1089 #define SIGNAL_STACK_ALIGNMENT 64
1091 struct Machine_State
1093 sigcontext_t context;
1096 static void __gnat_error_handler (int, int, sigcontext_t *);
1098 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
1099 connecting that handler, with the effects described in the sigaction
1100 man page:
1102 SA_SIGINFO [...]
1103 If cleared and the signal is caught, the first argument is
1104 also the signal number but the second argument is the signal
1105 code identifying the cause of the signal. The third argument
1106 points to a sigcontext_t structure containing the receiving
1107 process's context when the signal was delivered.
1110 static void
1111 __gnat_error_handler (int sig, int code, sigcontext_t *sc)
1113 struct Machine_State *mstate;
1114 struct Exception_Data *exception;
1115 const char *msg;
1117 switch (sig)
1119 case SIGSEGV:
1120 if (code == EFAULT)
1122 exception = &program_error;
1123 msg = "SIGSEGV: (Invalid virtual address)";
1125 else if (code == ENXIO)
1127 exception = &program_error;
1128 msg = "SIGSEGV: (Read beyond mapped object)";
1130 else if (code == ENOSPC)
1132 exception = &program_error; /* ??? storage_error ??? */
1133 msg = "SIGSEGV: (Autogrow for file failed)";
1135 else if (code == EACCES || code == EEXIST)
1137 /* ??? We handle stack overflows here, some of which do trigger
1138 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
1139 the documented valid codes for SEGV in the signal(5) man
1140 page. */
1142 /* ??? Re-add smarts to further verify that we launched
1143 the stack into a guard page, not an attempt to
1144 write to .text or something */
1145 exception = &storage_error;
1146 msg = "SIGSEGV: (stack overflow or erroneous memory access)";
1148 else
1150 /* Just in case the OS guys did it to us again. Sometimes
1151 they fail to document all of the valid codes that are
1152 passed to signal handlers, just in case someone depends
1153 on knowing all the codes */
1154 exception = &program_error;
1155 msg = "SIGSEGV: (Undocumented reason)";
1157 break;
1159 case SIGBUS:
1160 /* Map all bus errors to Program_Error. */
1161 exception = &program_error;
1162 msg = "SIGBUS";
1163 break;
1165 case SIGFPE:
1166 /* Map all fpe errors to Constraint_Error. */
1167 exception = &constraint_error;
1168 msg = "SIGFPE";
1169 break;
1171 case SIGADAABORT:
1172 if ((*Check_Abort_Status) ())
1174 exception = &_abort_signal;
1175 msg = "";
1177 else
1178 return;
1180 break;
1182 default:
1183 /* Everything else is a Program_Error. */
1184 exception = &program_error;
1185 msg = "unhandled signal";
1188 mstate = (*Get_Machine_State_Addr) ();
1189 if (mstate != 0)
1190 memcpy ((void *) mstate, (const void *) sc, sizeof (sigcontext_t));
1192 Raise_From_Signal_Handler (exception, msg);
1195 void
1196 __gnat_install_handler (void)
1198 struct sigaction act;
1200 /* Setup signal handler to map synchronous signals to appropriate
1201 exceptions. Make sure that the handler isn't interrupted by another
1202 signal that might cause a scheduling event! */
1204 act.sa_handler = __gnat_error_handler;
1205 act.sa_flags = SA_NODEFER + SA_RESTART;
1206 sigfillset (&act.sa_mask);
1207 sigemptyset (&act.sa_mask);
1209 /* Do not install handlers if interrupt state is "System" */
1210 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1211 sigaction (SIGABRT, &act, NULL);
1212 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1213 sigaction (SIGFPE, &act, NULL);
1214 if (__gnat_get_interrupt_state (SIGILL) != 's')
1215 sigaction (SIGILL, &act, NULL);
1216 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1217 sigaction (SIGSEGV, &act, NULL);
1218 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1219 sigaction (SIGBUS, &act, NULL);
1220 if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
1221 sigaction (SIGADAABORT, &act, NULL);
1223 __gnat_handler_installed = 1;
1226 void
1227 __gnat_initialize (void)
1231 /*************************************************/
1232 /* __gnat_initialize (Solaris and SunOS Version) */
1233 /*************************************************/
1235 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
1237 #include <signal.h>
1238 #include <siginfo.h>
1240 static void __gnat_error_handler (int, siginfo_t *);
1242 static void
1243 __gnat_error_handler (int sig, siginfo_t *sip)
1245 struct Exception_Data *exception;
1246 static int recurse = 0;
1247 const char *msg;
1249 /* If this was an explicit signal from a "kill", just resignal it. */
1250 if (SI_FROMUSER (sip))
1252 signal (sig, SIG_DFL);
1253 kill (getpid(), sig);
1256 /* Otherwise, treat it as something we handle. */
1257 switch (sig)
1259 case SIGSEGV:
1260 /* If the problem was permissions, this is a constraint error.
1261 Likewise if the failing address isn't maximally aligned or if
1262 we've recursed.
1264 ??? Using a static variable here isn't task-safe, but it's
1265 much too hard to do anything else and we're just determining
1266 which exception to raise. */
1267 if (sip->si_code == SEGV_ACCERR
1268 || (((long) sip->si_addr) & 3) != 0
1269 || recurse)
1271 exception = &constraint_error;
1272 msg = "SIGSEGV";
1274 else
1276 /* See if the page before the faulting page is accessible. Do that
1277 by trying to access it. We'd like to simply try to access
1278 4096 + the faulting address, but it's not guaranteed to be
1279 the actual address, just to be on the same page. */
1280 recurse++;
1281 ((volatile char *)
1282 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1283 exception = &storage_error;
1284 msg = "stack overflow (or erroneous memory access)";
1286 break;
1288 case SIGBUS:
1289 exception = &program_error;
1290 msg = "SIGBUS";
1291 break;
1293 case SIGFPE:
1294 exception = &constraint_error;
1295 msg = "SIGFPE";
1296 break;
1298 default:
1299 exception = &program_error;
1300 msg = "unhandled signal";
1303 recurse = 0;
1305 Raise_From_Signal_Handler (exception, msg);
1308 void
1309 __gnat_install_handler (void)
1311 struct sigaction act;
1313 /* Set up signal handler to map synchronous signals to appropriate
1314 exceptions. Make sure that the handler isn't interrupted by another
1315 signal that might cause a scheduling event! */
1317 act.sa_handler = __gnat_error_handler;
1318 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1319 sigemptyset (&act.sa_mask);
1321 /* Do not install handlers if interrupt state is "System" */
1322 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1323 sigaction (SIGABRT, &act, NULL);
1324 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1325 sigaction (SIGFPE, &act, NULL);
1326 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1327 sigaction (SIGSEGV, &act, NULL);
1328 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1329 sigaction (SIGBUS, &act, NULL);
1331 __gnat_handler_installed = 1;
1334 void
1335 __gnat_initialize (void)
1339 /***********************************/
1340 /* __gnat_initialize (VMS Version) */
1341 /***********************************/
1343 #elif defined (VMS)
1345 #ifdef __IA64
1346 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1347 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1348 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1349 #else
1350 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1351 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1352 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1353 #endif
1355 #if defined (IN_RTS) && !defined (__IA64)
1357 /* The prehandler actually gets control first on a condition. It swaps the
1358 stack pointer and calls the handler (__gnat_error_handler). */
1359 extern long __gnat_error_prehandler (void);
1361 extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
1362 #endif
1364 /* Conditions that don't have an Ada exception counterpart must raise
1365 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1366 referenced by user programs, not the compiler or tools. Hence the
1367 #ifdef IN_RTS. */
1369 #ifdef IN_RTS
1370 #define Non_Ada_Error system__aux_dec__non_ada_error
1371 extern struct Exception_Data Non_Ada_Error;
1373 #define Coded_Exception system__vms_exception_table__coded_exception
1374 extern struct Exception_Data *Coded_Exception (Exception_Code);
1376 #define Base_Code_In system__vms_exception_table__base_code_in
1377 extern Exception_Code Base_Code_In (Exception_Code);
1378 #endif
1380 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1381 Most of these are also defined in the header file ssdef.h which has not
1382 yet been converted to be recoginized by Gnu C. Some, which couldn't be
1383 located, are assigned names based on the DEC test suite tests which
1384 raise them. */
1386 #define SS$_ACCVIO 12
1387 #define SS$_DEBUG 1132
1388 #define SS$_INTDIV 1156
1389 #define SS$_HPARITH 1284
1390 #define SS$_STKOVF 1364
1391 #define SS$_RESIGNAL 2328
1392 #define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
1393 #define SS$_CE24VRU 3253636 /* Write to unopened file */
1394 #define SS$_C980VTE 3246436 /* AST requests time slice */
1395 #define CMA$_EXIT_THREAD 4227492
1396 #define CMA$_EXCCOPLOS 4228108
1397 #define CMA$_ALERTED 4227460
1399 struct descriptor_s {unsigned short len, mbz; char *adr; };
1401 long __gnat_error_handler (int *, void *);
1403 long
1404 __gnat_error_handler (int *sigargs, void *mechargs)
1406 struct Exception_Data *exception = 0;
1407 Exception_Code base_code;
1409 char *msg = "";
1410 char message[256];
1411 long prvhnd;
1412 struct descriptor_s msgdesc;
1413 int msg_flag = 0x000f; /* 1 bit for each of the four message parts */
1414 unsigned short outlen;
1415 char curr_icb[544];
1416 long curr_invo_handle;
1417 long *mstate;
1419 /* Resignaled condtions aren't effected by by pragma Import_Exception */
1421 switch (sigargs[1])
1424 case CMA$_EXIT_THREAD:
1425 return SS$_RESIGNAL;
1427 case SS$_DEBUG: /* Gdb attach, resignal to merge activate gdbstub. */
1428 return SS$_RESIGNAL;
1430 case 1409786: /* Nickerson bug #33 ??? */
1431 return SS$_RESIGNAL;
1433 case 1381050: /* Nickerson bug #33 ??? */
1434 return SS$_RESIGNAL;
1436 case 20480426: /* RDB-E-STREAM_EOF */
1437 return SS$_RESIGNAL;
1439 case 11829410: /* Resignalled as Use_Error for CE10VRC */
1440 return SS$_RESIGNAL;
1444 #ifdef IN_RTS
1445 /* See if it's an imported exception. Beware that registered exceptions
1446 are bound to their base code, with the severity bits masked off. */
1447 base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1448 exception = Coded_Exception (base_code);
1450 if (exception)
1452 msgdesc.len = 256;
1453 msgdesc.mbz = 0;
1454 msgdesc.adr = message;
1455 SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1456 message[outlen] = 0;
1457 msg = message;
1459 exception->Name_Length = 19;
1460 /* The full name really should be get sys$getmsg returns. ??? */
1461 exception->Full_Name = "IMPORTED_EXCEPTION";
1462 exception->Import_Code = base_code;
1464 #endif
1466 if (exception == 0)
1467 switch (sigargs[1])
1469 case SS$_ACCVIO:
1470 if (sigargs[3] == 0)
1472 exception = &constraint_error;
1473 msg = "access zero";
1475 else
1477 exception = &storage_error;
1478 msg = "stack overflow (or erroneous memory access)";
1480 break;
1482 case SS$_STKOVF:
1483 exception = &storage_error;
1484 msg = "stack overflow";
1485 break;
1487 case SS$_INTDIV:
1488 exception = &constraint_error;
1489 msg = "division by zero";
1490 break;
1492 case SS$_HPARITH:
1493 #ifndef IN_RTS
1494 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1495 #else
1497 exception = &constraint_error;
1498 msg = "arithmetic error";
1500 #endif
1501 break;
1503 case MTH$_FLOOVEMAT:
1504 exception = &constraint_error;
1505 msg = "floating overflow in math library";
1506 break;
1508 case SS$_CE24VRU:
1509 exception = &constraint_error;
1510 msg = "";
1511 break;
1513 case SS$_C980VTE:
1514 exception = &program_error;
1515 msg = "";
1516 break;
1518 default:
1519 #ifndef IN_RTS
1520 exception = &program_error;
1521 #else
1522 /* User programs expect Non_Ada_Error to be raised, reference
1523 DEC Ada test CXCONDHAN. */
1524 exception = &Non_Ada_Error;
1525 #endif
1526 msgdesc.len = 256;
1527 msgdesc.mbz = 0;
1528 msgdesc.adr = message;
1529 SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1530 message[outlen] = 0;
1531 msg = message;
1532 break;
1535 mstate = (long *) (*Get_Machine_State_Addr) ();
1536 if (mstate != 0)
1538 lib_get_curr_invo_context (&curr_icb);
1539 lib_get_prev_invo_context (&curr_icb);
1540 lib_get_prev_invo_context (&curr_icb);
1541 curr_invo_handle = lib_get_invo_handle (&curr_icb);
1542 *mstate = curr_invo_handle;
1544 Raise_From_Signal_Handler (exception, msg);
1547 void
1548 __gnat_install_handler (void)
1550 long prvhnd;
1551 #if defined (IN_RTS) && !defined (__IA64)
1552 char *c;
1554 c = (char *) xmalloc (2049);
1556 __gnat_error_prehandler_stack = &c[2048];
1558 /* __gnat_error_prehandler is an assembly function. */
1559 SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1560 #else
1561 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1562 #endif
1563 __gnat_handler_installed = 1;
1566 void
1567 __gnat_initialize(void)
1571 /*************************************************/
1572 /* __gnat_initialize (FreeBSD version) */
1573 /*************************************************/
1575 #elif defined (__FreeBSD__)
1577 #include <signal.h>
1578 #include <unistd.h>
1580 static void __gnat_error_handler (int, int, struct sigcontext *);
1582 static void
1583 __gnat_error_handler (int sig, int code __attribute__ ((unused)),
1584 struct sigcontext *sc __attribute__ ((unused)))
1586 struct Exception_Data *exception;
1587 const char *msg;
1589 switch (sig)
1591 case SIGFPE:
1592 exception = &constraint_error;
1593 msg = "SIGFPE";
1594 break;
1596 case SIGILL:
1597 exception = &constraint_error;
1598 msg = "SIGILL";
1599 break;
1601 case SIGSEGV:
1602 exception = &storage_error;
1603 msg = "stack overflow or erroneous memory access";
1604 break;
1606 case SIGBUS:
1607 exception = &constraint_error;
1608 msg = "SIGBUS";
1609 break;
1611 default:
1612 exception = &program_error;
1613 msg = "unhandled signal";
1616 Raise_From_Signal_Handler (exception, msg);
1619 void
1620 __gnat_install_handler ()
1622 struct sigaction act;
1624 /* Set up signal handler to map synchronous signals to appropriate
1625 exceptions. Make sure that the handler isn't interrupted by another
1626 signal that might cause a scheduling event! */
1628 act.sa_handler = __gnat_error_handler;
1629 act.sa_flags = SA_NODEFER | SA_RESTART;
1630 (void) sigemptyset (&act.sa_mask);
1632 (void) sigaction (SIGILL, &act, NULL);
1633 (void) sigaction (SIGFPE, &act, NULL);
1634 (void) sigaction (SIGSEGV, &act, NULL);
1635 (void) sigaction (SIGBUS, &act, NULL);
1638 void
1639 __gnat_initialize ()
1641 __gnat_install_handler ();
1643 /* XXX - Initialize floating-point coprocessor. This call is
1644 needed because FreeBSD defaults to 64-bit precision instead
1645 of 80-bit precision? We require the full precision for
1646 proper operation, given that we have set Max_Digits etc
1647 with this in mind */
1648 __gnat_init_float ();
1651 /***************************************/
1652 /* __gnat_initialize (VXWorks Version) */
1653 /***************************************/
1655 #elif defined(__vxworks)
1657 #include <signal.h>
1658 #include <taskLib.h>
1659 #include <intLib.h>
1660 #include <iv.h>
1662 #ifdef VTHREADS
1663 #include "private/vThreadsP.h"
1664 #endif
1666 extern int __gnat_inum_to_ivec (int);
1667 static void __gnat_error_handler (int, int, struct sigcontext *);
1668 void __gnat_map_signal (int);
1670 #ifndef __alpha_vxworks
1672 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1673 on Alpha VxWorks */
1675 extern long getpid (void);
1677 long
1678 getpid (void)
1680 return taskIdSelf ();
1682 #endif
1684 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1686 __gnat_inum_to_ivec (int num)
1688 return INUM_TO_IVEC (num);
1691 /* VxWorks expects the field excCnt to be zeroed when a signal is handled.
1692 The VxWorks version of longjmp does this; gcc's builtin_longjmp does not */
1693 void
1694 __gnat_clear_exception_count (void)
1696 #ifdef VTHREADS
1697 taskIdCurrent->vThreads.excCnt = 0;
1698 #endif
1701 /* Exported to 5zintman.adb in order to handle different signal
1702 to exception mappings in different VxWorks versions */
1703 void
1704 __gnat_map_signal (int sig)
1706 struct Exception_Data *exception;
1707 char *msg;
1709 switch (sig)
1711 case SIGFPE:
1712 exception = &constraint_error;
1713 msg = "SIGFPE";
1714 break;
1715 #ifdef VTHREADS
1716 case SIGILL:
1717 exception = &constraint_error;
1718 msg = "Floating point exception or SIGILL";
1719 break;
1720 case SIGSEGV:
1721 exception = &storage_error;
1722 msg = "SIGSEGV: possible stack overflow";
1723 break;
1724 case SIGBUS:
1725 exception = &storage_error;
1726 msg = "SIGBUS: possible stack overflow";
1727 break;
1728 #else
1729 case SIGILL:
1730 exception = &constraint_error;
1731 msg = "SIGILL";
1732 break;
1733 case SIGSEGV:
1734 exception = &program_error;
1735 msg = "SIGSEGV";
1736 break;
1737 case SIGBUS:
1738 exception = &program_error;
1739 msg = "SIGBUS";
1740 break;
1741 #endif
1742 default:
1743 exception = &program_error;
1744 msg = "unhandled signal";
1747 __gnat_clear_exception_count ();
1748 Raise_From_Signal_Handler (exception, msg);
1751 static void
1752 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1754 sigset_t mask;
1755 int result;
1757 /* VxWorks will always mask out the signal during the signal handler and
1758 will reenable it on a longjmp. GNAT does not generate a longjmp to
1759 return from a signal handler so the signal will still be masked unless
1760 we unmask it. */
1761 sigprocmask (SIG_SETMASK, NULL, &mask);
1762 sigdelset (&mask, sig);
1763 sigprocmask (SIG_SETMASK, &mask, NULL);
1765 __gnat_map_signal (sig);
1769 void
1770 __gnat_install_handler (void)
1772 struct sigaction act;
1774 /* Setup signal handler to map synchronous signals to appropriate
1775 exceptions. Make sure that the handler isn't interrupted by another
1776 signal that might cause a scheduling event! */
1778 act.sa_handler = __gnat_error_handler;
1779 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1780 sigemptyset (&act.sa_mask);
1782 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1783 applies to vectored hardware interrupts, not signals */
1784 sigaction (SIGFPE, &act, NULL);
1785 sigaction (SIGILL, &act, NULL);
1786 sigaction (SIGSEGV, &act, NULL);
1787 sigaction (SIGBUS, &act, NULL);
1789 __gnat_handler_installed = 1;
1792 #define HAVE_GNAT_INIT_FLOAT
1794 void
1795 __gnat_init_float (void)
1797 /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1798 to get correct Ada semantics. Note that for AE653 vThreads, the HW
1799 overflow settings are an OS configuration issue. The instructions
1800 below have no effect */
1801 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1802 asm ("mtfsb0 25");
1803 asm ("mtfsb0 26");
1804 #endif
1806 /* Similarily for sparc64. Achieved by masking bits in the Trap Enable Mask
1807 field of the Floating-point Status Register (see the Sparc Architecture
1808 Manual Version 9, p 48). */
1809 #if defined (sparc64)
1811 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1812 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1813 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1814 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1815 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1817 unsigned int fsr;
1819 __asm__("st %%fsr, %0" : "=m" (fsr));
1820 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1821 __asm__("ld %0, %%fsr" : : "m" (fsr));
1823 #endif
1826 void
1827 __gnat_initialize (void)
1829 __gnat_init_float ();
1831 /* On targets where we might be using the ZCX scheme, we need to register
1832 the frame tables.
1834 For applications loaded as a set of "modules", the crtstuff objects
1835 linked in (crtbegin/endS) are tailored to provide this service a-la C++
1836 static constructor fashion, typically triggered by the VxWorks loader.
1837 This is achieved by way of a special variable declaration in the crt
1838 object, the name of which has been deduced by analyzing the output of the
1839 "munching" step documented for C++. The de-registration call is handled
1840 symetrically, a-la C++ destructor fashion and typically triggered by the
1841 dynamic unloader. Note that since the tables shall be registered against
1842 a common datastructure, libgcc should be one of the modules (vs beeing
1843 partially linked against all the others at build time) and shall be
1844 loaded first.
1846 For applications linked with the kernel, the scheme above would lead to
1847 duplicated symbols because the VxWorks kernel build "munches" by default.
1848 To prevent those conflicts, we link against crtbegin/end objects that
1849 don't include the special variable and directly call the appropriate
1850 function here. We'll never unload that, so there is no de-registration to
1851 worry about.
1853 For whole applications loaded as a single module, we may use one scheme
1854 or the other, except for the mixed Ada/C++ case in which the first scheme
1855 would fail for the same reason as in the linked-with-kernel situation.
1857 We can differentiate by looking at the __module_has_ctors value provided
1858 by each class of crt objects. As of today, selecting the crt set with the
1859 static ctors/dtors capabilities (first scheme above) is triggered by
1860 adding "-static" to the gcc *link* command line options. Without this,
1861 the other set of crt objects is fetched.
1863 This is a first approach, tightly synchronized with a number of GCC
1864 configuration and crtstuff changes. We need to ensure that those changes
1865 are there to activate this circuitry. */
1867 #if DWARF2_UNWIND_INFO && defined (_ARCH_PPC)
1869 /* The scheme described above is only useful for the actual ZCX case, and
1870 we don't want any reference to the crt provided symbols otherwise. We
1871 may not link with any of the crt objects in the non-ZCX case, e.g. from
1872 documented procedures instructing the use of -nostdlib, and references
1873 to the ctors symbols here would just remain unsatisfied.
1875 We have no way to avoid those references in the right conditions in this
1876 C module, because we have nothing like a IN_ZCX_RTS macro. This aspect
1877 is then deferred to an Ada routine, which can do that based on a test
1878 against a constant System flag value. */
1880 extern void __gnat_vxw_setup_for_eh (void);
1881 __gnat_vxw_setup_for_eh ();
1883 #endif
1886 /********************************/
1887 /* __gnat_initialize for NetBSD */
1888 /********************************/
1890 #elif defined(__NetBSD__)
1892 #include <signal.h>
1893 #include <unistd.h>
1895 static void
1896 __gnat_error_handler (int sig)
1898 struct Exception_Data *exception;
1899 const char *msg;
1901 switch(sig)
1903 case SIGFPE:
1904 exception = &constraint_error;
1905 msg = "SIGFPE";
1906 break;
1907 case SIGILL:
1908 exception = &constraint_error;
1909 msg = "SIGILL";
1910 break;
1911 case SIGSEGV:
1912 exception = &storage_error;
1913 msg = "stack overflow or erroneous memory access";
1914 break;
1915 case SIGBUS:
1916 exception = &constraint_error;
1917 msg = "SIGBUS";
1918 break;
1919 default:
1920 exception = &program_error;
1921 msg = "unhandled signal";
1924 Raise_From_Signal_Handler(exception, msg);
1927 void
1928 __gnat_install_handler(void)
1930 struct sigaction act;
1932 act.sa_handler = __gnat_error_handler;
1933 act.sa_flags = SA_NODEFER | SA_RESTART;
1934 sigemptyset (&act.sa_mask);
1936 /* Do not install handlers if interrupt state is "System" */
1937 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1938 sigaction (SIGFPE, &act, NULL);
1939 if (__gnat_get_interrupt_state (SIGILL) != 's')
1940 sigaction (SIGILL, &act, NULL);
1941 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1942 sigaction (SIGSEGV, &act, NULL);
1943 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1944 sigaction (SIGBUS, &act, NULL);
1946 __gnat_handler_installed = 1;
1949 void
1950 __gnat_initialize (void)
1952 __gnat_install_handler ();
1953 __gnat_init_float ();
1956 #else
1958 /* For all other versions of GNAT, the initialize routine and handler
1959 installation do nothing */
1961 /***************************************/
1962 /* __gnat_initialize (Default Version) */
1963 /***************************************/
1965 void
1966 __gnat_initialize (void)
1970 /********************************************/
1971 /* __gnat_install_handler (Default Version) */
1972 /********************************************/
1974 void
1975 __gnat_install_handler (void)
1977 __gnat_handler_installed = 1;
1980 #endif
1982 /*********************/
1983 /* __gnat_init_float */
1984 /*********************/
1986 /* This routine is called as each process thread is created, for possible
1987 initialization of the FP processor. This version is used under INTERIX,
1988 WIN32 and could be used under OS/2 */
1990 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1991 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1993 #define HAVE_GNAT_INIT_FLOAT
1995 void
1996 __gnat_init_float (void)
1998 #if defined (__i386__) || defined (i386)
2000 /* This is used to properly initialize the FPU on an x86 for each
2001 process thread. */
2003 asm ("finit");
2005 #endif /* Defined __i386__ */
2007 #endif
2009 #ifndef HAVE_GNAT_INIT_FLOAT
2011 /* All targets without a specific __gnat_init_float will use an empty one */
2012 void
2013 __gnat_init_float (void)
2016 #endif