1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2004 Free Software Foundation, Inc. *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 2, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
17 * for more details. You should have received a copy of the GNU General *
18 * Public License distributed with GNAT; see file COPYING. If not, write *
19 * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, *
20 * MA 02111-1307, USA. *
22 * As a special exception, if you link this file with other files to *
23 * produce an executable, this file does not by itself cause the resulting *
24 * executable to be covered by the GNU General Public License. This except- *
25 * ion does not however invalidate any other reasons why the executable *
26 * file might be covered by the GNU Public License. *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
31 ****************************************************************************/
33 /* This unit contains initialization circuits that are system dependent. A
34 major part of the functionality involved involves stack overflow checking.
35 The GCC backend generates probe instructions to test for stack overflow.
36 For details on the exact approach used to generate these probes, see the
37 "Using and Porting GCC" manual, in particular the "Stack Checking" section
38 and the subsection "Specifying How Stack Checking is Done". The handlers
39 installed by this file are used to handle resulting signals that come
40 from these probes failing (i.e. touching protected pages) */
42 /* This file should be kept synchronized with 2sinit.ads, 2sinit.adb, and
43 5zinit.adb. All these files implement the required functionality for
46 /* The following include is here to meet the published VxWorks requirement
47 that the __vxworks header appear before any other include. */
57 /* We don't have libiberty, so us malloc. */
58 #define xmalloc(S) malloc (S)
67 extern void __gnat_raise_program_error (const char *, int);
69 /* Addresses of exception data blocks for predefined exceptions. */
70 extern struct Exception_Data constraint_error
;
71 extern struct Exception_Data numeric_error
;
72 extern struct Exception_Data program_error
;
73 extern struct Exception_Data storage_error
;
74 extern struct Exception_Data tasking_error
;
75 extern struct Exception_Data _abort_signal
;
77 #define Lock_Task system__soft_links__lock_task
78 extern void (*Lock_Task
) (void);
80 #define Unlock_Task system__soft_links__unlock_task
81 extern void (*Unlock_Task
) (void);
83 #define 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
*,
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;
115 /* Indication of whether synchronous signal handler has already been
116 installed by a previous call to adainit */
117 int __gnat_handler_installed
= 0;
119 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
120 is defined. If this is not set them a void implementation will be defined
121 at the end of this unit. */
122 #undef HAVE_GNAT_INIT_FLOAT
124 /******************************/
125 /* __gnat_get_interrupt_state */
126 /******************************/
128 char __gnat_get_interrupt_state (int);
130 /* This routine is called from the runtime as needed to determine the state
131 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
132 in the current partition. The input argument is the interrupt number,
133 and the result is one of the following:
135 'n' this interrupt not set by any Interrupt_State pragma
136 'u' Interrupt_State pragma set state to User
137 'r' Interrupt_State pragma set state to Runtime
138 's' Interrupt_State pragma set state to System */
141 __gnat_get_interrupt_state (int intrup
)
143 if (intrup
>= __gl_num_interrupt_states
)
146 return __gl_interrupt_states
[intrup
];
149 /**********************/
150 /* __gnat_set_globals */
151 /**********************/
153 /* This routine is called from the binder generated main program. It copies
154 the values for global quantities computed by the binder into the following
155 global locations. The reason that we go through this copy, rather than just
156 define the global locations in the binder generated file, is that they are
157 referenced from the runtime, which may be in a shared library, and the
158 binder file is not in the shared library. Global references across library
159 boundaries like this are not handled correctly in all systems. */
161 /* For detailed description of the parameters to this routine, see the
162 section titled Run-Time Globals in package Bindgen (bindgen.adb) */
165 __gnat_set_globals (int main_priority
,
170 char task_dispatching_policy
,
172 char *interrupt_states
,
173 int num_interrupt_states
,
174 int unreserve_all_interrupts
,
175 int exception_tracebacks
,
176 int zero_cost_exceptions
)
178 static int already_called
= 0;
180 /* If this procedure has been already called once, check that the
181 arguments in this call are consistent with the ones in the previous
182 calls. Otherwise, raise a Program_Error exception.
184 We do not check for consistency of the wide character encoding
185 method. This default affects only Wide_Text_IO where no explicit
186 coding method is given, and there is no particular reason to let
187 this default be affected by the source representation of a library
190 We do not check either for the consistency of exception tracebacks,
191 because exception tracebacks are not normally set in Stand-Alone
192 libraries. If a library or the main program set the exception
193 tracebacks, then they are never reset afterwards (see below).
195 The value of main_priority is meaningful only when we are invoked
196 from the main program elaboration routine of an Ada application.
197 Checking the consistency of this parameter should therefore not be
198 done. Since it is assured that the main program elaboration will
199 always invoke this procedure before any library elaboration
200 routine, only the value of main_priority during the first call
201 should be taken into account and all the subsequent ones should be
202 ignored. Note that the case where the main program is not written
203 in Ada is also properly handled, since the default value will then
204 be used for this parameter.
206 For identical reasons, the consistency of time_slice_val should not
211 if (__gl_locking_policy
!= locking_policy
212 || __gl_queuing_policy
!= queuing_policy
213 || __gl_task_dispatching_policy
!= task_dispatching_policy
214 || __gl_unreserve_all_interrupts
!= unreserve_all_interrupts
215 || __gl_zero_cost_exceptions
!= zero_cost_exceptions
)
216 __gnat_raise_program_error (__FILE__
, __LINE__
);
218 /* If either a library or the main program set the exception traceback
219 flag, it is never reset later */
221 if (exception_tracebacks
!= 0)
222 __gl_exception_tracebacks
= exception_tracebacks
;
228 __gl_main_priority
= main_priority
;
229 __gl_time_slice_val
= time_slice_val
;
230 __gl_wc_encoding
= wc_encoding
;
231 __gl_locking_policy
= locking_policy
;
232 __gl_queuing_policy
= queuing_policy
;
233 __gl_restrictions
= restrictions
;
234 __gl_interrupt_states
= interrupt_states
;
235 __gl_num_interrupt_states
= num_interrupt_states
;
236 __gl_task_dispatching_policy
= task_dispatching_policy
;
237 __gl_unreserve_all_interrupts
= unreserve_all_interrupts
;
238 __gl_exception_tracebacks
= exception_tracebacks
;
240 /* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
241 a-except.adb, which is also part of the compiler sources. Since the
242 compiler is built with an older release of GNAT, the call generated by
243 the old binder to this function does not provide any value for the
244 corresponding argument, so the global has to be initialized in some
245 reasonable other way. This could be removed as soon as the next major
249 __gl_zero_cost_exceptions
= zero_cost_exceptions
;
251 __gl_zero_cost_exceptions
= 0;
252 /* We never build the compiler to run in ZCX mode currently anyway. */
256 /*********************/
257 /* __gnat_initialize */
258 /*********************/
260 /* __gnat_initialize is called at the start of execution of an Ada program
261 (the call is generated by the binder). The standard routine does nothing
262 at all; the intention is that this be replaced by system specific
263 code where initialization is required. */
265 /* Notes on the Zero Cost Exceptions scheme and its impact on the signal
266 handlers implemented below :
268 What we call Zero Cost Exceptions is implemented using the GCC eh
269 circuitry, even if the underlying implementation is setjmp/longjmp
270 based. In any case ...
272 The GCC unwinder expects to be dealing with call return addresses, since
273 this is the "nominal" case of what we retrieve while unwinding a regular
274 call chain. To evaluate if a handler applies at some point in this chain,
275 the propagation engine needs to determine what region the corresponding
276 call instruction pertains to. The return address may not be attached to the
277 same region as the call, so the unwinder unconditionally substracts "some"
278 amount to the return addresses it gets to search the region tables. The
279 exact amount is computed to ensure that the resulting address is inside the
280 call instruction, and is thus target dependant (think about delay slots for
283 When we raise an exception from a signal handler, e.g. to transform a
284 SIGSEGV into Storage_Error, things need to appear as if the signal handler
285 had been "called" by the instruction which triggered the signal, so that
286 exception handlers that apply there are considered. What the unwinder will
287 retrieve as the return address from the signal handler is what it will find
288 as the faulting instruction address in the corresponding signal context
289 pushed by the kernel. Leaving this address untouched may loose, because if
290 the triggering instruction happens to be the very first of a region, the
291 later adjustements performed by the unwinder would yield an address outside
292 that region. We need to compensate for those adjustments at some point,
293 which we currently do in the GCC unwinding fallback macro.
295 The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
296 describes a couple of issues with our current approach. Basically: on some
297 targets the adjustment to apply depends on the triggering signal, which is
298 not easily accessible from the macro, and we actually do not tackle this as
299 of today. Besides, other languages, e.g. Java, deal with this by performing
300 the adjustment in the signal handler before the raise, so our adjustments
301 may break those front-ends.
303 To have it all right, we should either find a way to deal with the signal
304 variants from the macro and convert Java on all targets (ugh), or remove
305 our macro adjustments and update our signal handlers a-la-java way. The
306 latter option appears the simplest, although some targets have their share
307 of subtleties to account for. See for instance the syscall(SYS_sigaction)
308 story in libjava/include/i386-signal.h. */
310 /***********************************/
311 /* __gnat_initialize (AIX Version) */
312 /***********************************/
317 #include <sys/time.h>
319 /* Some versions of AIX don't define SA_NODEFER. */
323 #endif /* SA_NODEFER */
325 /* Versions of AIX before 4.3 don't have nanosleep but provide
328 #ifndef _AIXVERSION_430
330 extern int nanosleep (struct timestruc_t
*, struct timestruc_t
*);
333 nanosleep (struct timestruc_t
*Rqtp
, struct timestruc_t
*Rmtp
)
335 return nsleep (Rqtp
, Rmtp
);
338 #endif /* _AIXVERSION_430 */
340 static void __gnat_error_handler (int);
343 __gnat_error_handler (int sig
)
345 struct Exception_Data
*exception
;
351 /* FIXME: we need to detect the case of a *real* SIGSEGV */
352 exception
= &storage_error
;
353 msg
= "stack overflow or erroneous memory access";
357 exception
= &constraint_error
;
362 exception
= &constraint_error
;
367 exception
= &program_error
;
368 msg
= "unhandled signal";
371 Raise_From_Signal_Handler (exception
, msg
);
375 __gnat_install_handler (void)
377 struct sigaction act
;
379 /* Set up signal handler to map synchronous signals to appropriate
380 exceptions. Make sure that the handler isn't interrupted by another
381 signal that might cause a scheduling event! */
383 act
.sa_handler
= __gnat_error_handler
;
384 act
.sa_flags
= SA_NODEFER
| SA_RESTART
;
385 sigemptyset (&act
.sa_mask
);
387 /* Do not install handlers if interrupt state is "System" */
388 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
389 sigaction (SIGABRT
, &act
, NULL
);
390 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
391 sigaction (SIGFPE
, &act
, NULL
);
392 if (__gnat_get_interrupt_state (SIGILL
) != 's')
393 sigaction (SIGILL
, &act
, NULL
);
394 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
395 sigaction (SIGSEGV
, &act
, NULL
);
396 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
397 sigaction (SIGBUS
, &act
, NULL
);
399 __gnat_handler_installed
= 1;
403 __gnat_initialize (void)
407 /***************************************/
408 /* __gnat_initialize (RTEMS version) */
409 /***************************************/
411 #elif defined(__rtems__)
413 extern void __gnat_install_handler (void);
415 /* For RTEMS, each bsp will provide a custom __gnat_install_handler (). */
418 __gnat_initialize (void)
420 __gnat_install_handler ();
423 /****************************************/
424 /* __gnat_initialize (Dec Unix Version) */
425 /****************************************/
427 #elif defined(__alpha__) && defined(__osf__) && ! defined(__alpha_vxworks)
429 /* Note: it seems that __osf__ is defined for the Alpha VXWorks case. Not
430 clear that this is reasonable, but in any case we have to be sure to
431 exclude this case in the above test. */
434 #include <sys/siginfo.h>
436 static void __gnat_error_handler (int, siginfo_t
*, struct sigcontext
*);
437 extern char *__gnat_get_code_loc (struct sigcontext
*);
438 extern void __gnat_enter_handler (struct sigcontext
*, char *);
439 extern size_t __gnat_machine_state_length (void);
441 extern long exc_lookup_gp (char *);
442 extern void exc_resume (struct sigcontext
*);
445 __gnat_error_handler (int sig
, siginfo_t
*sip
, struct sigcontext
*context
)
447 struct Exception_Data
*exception
;
448 static int recurse
= 0;
449 struct sigcontext
*mstate
;
452 /* If this was an explicit signal from a "kill", just resignal it. */
453 if (SI_FROMUSER (sip
))
455 signal (sig
, SIG_DFL
);
456 kill (getpid(), sig
);
459 /* Otherwise, treat it as something we handle. */
463 /* If the problem was permissions, this is a constraint error.
464 Likewise if the failing address isn't maximally aligned or if
467 ??? Using a static variable here isn't task-safe, but it's
468 much too hard to do anything else and we're just determining
469 which exception to raise. */
470 if (sip
->si_code
== SEGV_ACCERR
471 || (((long) sip
->si_addr
) & 3) != 0
474 exception
= &constraint_error
;
479 /* See if the page before the faulting page is accessible. Do that
480 by trying to access it. We'd like to simply try to access
481 4096 + the faulting address, but it's not guaranteed to be
482 the actual address, just to be on the same page. */
485 ((long) sip
->si_addr
& - getpagesize ()))[getpagesize ()];
486 msg
= "stack overflow (or erroneous memory access)";
487 exception
= &storage_error
;
492 exception
= &program_error
;
497 exception
= &constraint_error
;
502 exception
= &program_error
;
503 msg
= "unhandled signal";
507 mstate
= (struct sigcontext
*) (*Get_Machine_State_Addr
) ();
511 Raise_From_Signal_Handler (exception
, (char *) msg
);
515 __gnat_install_handler (void)
517 struct sigaction act
;
519 /* Setup signal handler to map synchronous signals to appropriate
520 exceptions. Make sure that the handler isn't interrupted by another
521 signal that might cause a scheduling event! */
523 act
.sa_handler
= (void (*) (int)) __gnat_error_handler
;
524 act
.sa_flags
= SA_RESTART
| SA_NODEFER
| SA_SIGINFO
;
525 sigemptyset (&act
.sa_mask
);
527 /* Do not install handlers if interrupt state is "System" */
528 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
529 sigaction (SIGABRT
, &act
, NULL
);
530 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
531 sigaction (SIGFPE
, &act
, NULL
);
532 if (__gnat_get_interrupt_state (SIGILL
) != 's')
533 sigaction (SIGILL
, &act
, NULL
);
534 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
535 sigaction (SIGSEGV
, &act
, NULL
);
536 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
537 sigaction (SIGBUS
, &act
, NULL
);
539 __gnat_handler_installed
= 1;
543 __gnat_initialize (void)
547 /* Routines called by 5amastop.adb. */
552 __gnat_get_code_loc (struct sigcontext
*context
)
554 return (char *) context
->sc_pc
;
558 __gnat_enter_handler ( struct sigcontext
*context
, char *pc
)
560 context
->sc_pc
= (long) pc
;
561 context
->sc_regs
[SC_GP
] = exc_lookup_gp (pc
);
562 exc_resume (context
);
566 __gnat_machine_state_length (void)
568 return sizeof (struct sigcontext
);
571 /************************************/
572 /* __gnat_initialize (HPUX Version) */
573 /************************************/
579 static void __gnat_error_handler (int);
582 __gnat_error_handler (int sig
)
584 struct Exception_Data
*exception
;
590 /* FIXME: we need to detect the case of a *real* SIGSEGV */
591 exception
= &storage_error
;
592 msg
= "stack overflow or erroneous memory access";
596 exception
= &constraint_error
;
601 exception
= &constraint_error
;
606 exception
= &program_error
;
607 msg
= "unhandled signal";
610 Raise_From_Signal_Handler (exception
, msg
);
614 __gnat_install_handler (void)
616 struct sigaction act
;
618 /* Set up signal handler to map synchronous signals to appropriate
619 exceptions. Make sure that the handler isn't interrupted by another
620 signal that might cause a scheduling event! Also setup an alternate
621 stack region for the handler execution so that stack overflows can be
622 handled properly, avoiding a SEGV generation from stack usage by the
625 static char handler_stack
[SIGSTKSZ
*2];
626 /* SIGSTKSZ appeared to be "short" for the needs in some contexts
627 (e.g. experiments with GCC ZCX exceptions). */
631 stack
.ss_sp
= handler_stack
;
632 stack
.ss_size
= sizeof (handler_stack
);
635 sigaltstack (&stack
, NULL
);
637 act
.sa_handler
= __gnat_error_handler
;
638 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_ONSTACK
;
639 sigemptyset (&act
.sa_mask
);
641 /* Do not install handlers if interrupt state is "System" */
642 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
643 sigaction (SIGABRT
, &act
, NULL
);
644 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
645 sigaction (SIGFPE
, &act
, NULL
);
646 if (__gnat_get_interrupt_state (SIGILL
) != 's')
647 sigaction (SIGILL
, &act
, NULL
);
648 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
649 sigaction (SIGSEGV
, &act
, NULL
);
650 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
651 sigaction (SIGBUS
, &act
, NULL
);
653 __gnat_handler_installed
= 1;
657 __gnat_initialize (void)
661 /*****************************************/
662 /* __gnat_initialize (GNU/Linux Version) */
663 /*****************************************/
665 #elif defined (linux) && defined (i386) && !defined (__RT__)
668 #include <asm/sigcontext.h>
670 /* GNU/Linux, which uses glibc, does not define NULL in included
674 #define NULL ((void *) 0)
687 static void __gnat_error_handler (int);
690 __gnat_error_handler (int sig
)
692 struct Exception_Data
*exception
;
694 static int recurse
= 0;
696 struct sigcontext
*info
697 = (struct sigcontext
*) (((char *) &sig
) + sizeof (int));
699 /* The Linux kernel does not document how to get the machine state in a
700 signal handler, but in fact the necessary data is in a sigcontext_struct
701 value that is on the stack immediately above the signal number
702 parameter, and the above messing accesses this value on the stack. */
704 struct Machine_State
*mstate
;
709 /* If the problem was permissions, this is a constraint error.
710 Likewise if the failing address isn't maximally aligned or if
713 ??? Using a static variable here isn't task-safe, but it's
714 much too hard to do anything else and we're just determining
715 which exception to raise. */
718 exception
= &constraint_error
;
723 /* Here we would like a discrimination test to see whether the
724 page before the faulting address is accessible. Unfortunately
725 Linux seems to have no way of giving us the faulting address.
727 In versions of a-init.c before 1.95, we had a test of the page
728 before the stack pointer using:
732 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
734 but that's wrong, since it tests the stack pointer location, and
735 the current stack probe code does not move the stack pointer
736 until all probes succeed.
738 For now we simply do not attempt any discrimination at all. Note
739 that this is quite acceptable, since a "real" SIGSEGV can only
740 occur as the result of an erroneous program */
742 msg
= "stack overflow (or erroneous memory access)";
743 exception
= &storage_error
;
748 exception
= &constraint_error
;
753 exception
= &constraint_error
;
758 exception
= &program_error
;
759 msg
= "unhandled signal";
762 mstate
= (*Get_Machine_State_Addr
) ();
765 mstate
->eip
= info
->eip
;
766 mstate
->ebx
= info
->ebx
;
767 mstate
->esp
= info
->esp_at_signal
;
768 mstate
->ebp
= info
->ebp
;
769 mstate
->esi
= info
->esi
;
770 mstate
->edi
= info
->edi
;
774 Raise_From_Signal_Handler (exception
, msg
);
778 __gnat_install_handler (void)
780 struct sigaction act
;
782 /* Set up signal handler to map synchronous signals to appropriate
783 exceptions. Make sure that the handler isn't interrupted by another
784 signal that might cause a scheduling event! */
786 act
.sa_handler
= __gnat_error_handler
;
787 act
.sa_flags
= SA_NODEFER
| SA_RESTART
;
788 sigemptyset (&act
.sa_mask
);
790 /* Do not install handlers if interrupt state is "System" */
791 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
792 sigaction (SIGABRT
, &act
, NULL
);
793 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
794 sigaction (SIGFPE
, &act
, NULL
);
795 if (__gnat_get_interrupt_state (SIGILL
) != 's')
796 sigaction (SIGILL
, &act
, NULL
);
797 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
798 sigaction (SIGSEGV
, &act
, NULL
);
799 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
800 sigaction (SIGBUS
, &act
, NULL
);
802 __gnat_handler_installed
= 1;
806 __gnat_initialize (void)
810 /******************************************/
811 /* __gnat_initialize (NT-mingw32 Version) */
812 /******************************************/
814 #elif defined (__MINGW32__)
817 static LONG WINAPI
__gnat_error_handler (PEXCEPTION_POINTERS
);
819 /* __gnat_initialize (mingw32). */
822 __gnat_error_handler (PEXCEPTION_POINTERS info
)
825 struct Exception_Data
*exception
;
828 switch (info
->ExceptionRecord
->ExceptionCode
)
830 case EXCEPTION_ACCESS_VIOLATION
:
831 /* If the failing address isn't maximally-aligned or if we've
832 recursed, this is a program error. */
833 if ((info
->ExceptionRecord
->ExceptionInformation
[1] & 3) != 0
836 exception
= &program_error
;
837 msg
= "EXCEPTION_ACCESS_VIOLATION";
841 /* See if the page before the faulting page is accessible. Do that
842 by trying to access it. */
844 * ((volatile char *) (info
->ExceptionRecord
->ExceptionInformation
[1]
846 exception
= &storage_error
;
847 msg
= "stack overflow (or erroneous memory access)";
851 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
852 exception
= &constraint_error
;
853 msg
= "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
856 case EXCEPTION_DATATYPE_MISALIGNMENT
:
857 exception
= &constraint_error
;
858 msg
= "EXCEPTION_DATATYPE_MISALIGNMENT";
861 case EXCEPTION_FLT_DENORMAL_OPERAND
:
862 exception
= &constraint_error
;
863 msg
= "EXCEPTION_FLT_DENORMAL_OPERAND";
866 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
867 exception
= &constraint_error
;
868 msg
= "EXCEPTION_FLT_DENORMAL_OPERAND";
871 case EXCEPTION_FLT_INVALID_OPERATION
:
872 exception
= &constraint_error
;
873 msg
= "EXCEPTION_FLT_INVALID_OPERATION";
876 case EXCEPTION_FLT_OVERFLOW
:
877 exception
= &constraint_error
;
878 msg
= "EXCEPTION_FLT_OVERFLOW";
881 case EXCEPTION_FLT_STACK_CHECK
:
882 exception
= &program_error
;
883 msg
= "EXCEPTION_FLT_STACK_CHECK";
886 case EXCEPTION_FLT_UNDERFLOW
:
887 exception
= &constraint_error
;
888 msg
= "EXCEPTION_FLT_UNDERFLOW";
891 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
892 exception
= &constraint_error
;
893 msg
= "EXCEPTION_INT_DIVIDE_BY_ZERO";
896 case EXCEPTION_INT_OVERFLOW
:
897 exception
= &constraint_error
;
898 msg
= "EXCEPTION_INT_OVERFLOW";
901 case EXCEPTION_INVALID_DISPOSITION
:
902 exception
= &program_error
;
903 msg
= "EXCEPTION_INVALID_DISPOSITION";
906 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
907 exception
= &program_error
;
908 msg
= "EXCEPTION_NONCONTINUABLE_EXCEPTION";
911 case EXCEPTION_PRIV_INSTRUCTION
:
912 exception
= &program_error
;
913 msg
= "EXCEPTION_PRIV_INSTRUCTION";
916 case EXCEPTION_SINGLE_STEP
:
917 exception
= &program_error
;
918 msg
= "EXCEPTION_SINGLE_STEP";
921 case EXCEPTION_STACK_OVERFLOW
:
922 exception
= &storage_error
;
923 msg
= "EXCEPTION_STACK_OVERFLOW";
927 exception
= &program_error
;
928 msg
= "unhandled signal";
932 Raise_From_Signal_Handler (exception
, msg
);
933 return 0; /* This is never reached, avoid compiler warning */
937 __gnat_install_handler (void)
939 SetUnhandledExceptionFilter (__gnat_error_handler
);
940 __gnat_handler_installed
= 1;
944 __gnat_initialize (void)
947 /* Initialize floating-point coprocessor. This call is needed because
948 the MS libraries default to 64-bit precision instead of 80-bit
949 precision, and we require the full precision for proper operation,
950 given that we have set Max_Digits etc with this in mind */
952 __gnat_init_float ();
954 /* initialize a lock for a process handle list - see a-adaint.c for the
955 implementation of __gnat_portable_no_block_spawn, __gnat_portable_wait */
959 /***************************************/
960 /* __gnat_initialize (Interix Version) */
961 /***************************************/
963 #elif defined (__INTERIX)
967 static void __gnat_error_handler (int);
970 __gnat_error_handler (int sig
)
972 struct Exception_Data
*exception
;
978 exception
= &storage_error
;
979 msg
= "stack overflow or erroneous memory access";
983 exception
= &constraint_error
;
988 exception
= &constraint_error
;
993 exception
= &program_error
;
994 msg
= "unhandled signal";
997 Raise_From_Signal_Handler (exception
, msg
);
1001 __gnat_install_handler (void)
1003 struct sigaction act
;
1005 /* Set up signal handler to map synchronous signals to appropriate
1006 exceptions. Make sure that the handler isn't interrupted by another
1007 signal that might cause a scheduling event! */
1009 act
.sa_handler
= __gnat_error_handler
;
1011 sigemptyset (&act
.sa_mask
);
1013 /* Handlers for signals besides SIGSEGV cause c974013 to hang */
1014 /* sigaction (SIGILL, &act, NULL); */
1015 /* sigaction (SIGABRT, &act, NULL); */
1016 /* sigaction (SIGFPE, &act, NULL); */
1017 /* sigaction (SIGBUS, &act, NULL); */
1019 /* Do not install handlers if interrupt state is "System" */
1020 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
1021 sigaction (SIGSEGV
, &act
, NULL
);
1023 __gnat_handler_installed
= 1;
1027 __gnat_initialize (void)
1029 __gnat_init_float ();
1032 /**************************************/
1033 /* __gnat_initialize (LynxOS Version) */
1034 /**************************************/
1036 #elif defined (__Lynx__)
1039 __gnat_initialize (void)
1041 __gnat_init_float ();
1044 /*********************************/
1045 /* __gnat_install_handler (Lynx) */
1046 /*********************************/
1049 __gnat_install_handler (void)
1051 __gnat_handler_installed
= 1;
1054 /****************************/
1055 /* __gnat_initialize (OS/2) */
1056 /****************************/
1058 #elif defined (__EMX__) /* OS/2 dependent initialization */
1061 __gnat_initialize (void)
1065 /*********************************/
1066 /* __gnat_install_handler (OS/2) */
1067 /*********************************/
1070 __gnat_install_handler (void)
1072 __gnat_handler_installed
= 1;
1075 /***********************************/
1076 /* __gnat_initialize (SGI Version) */
1077 /***********************************/
1082 #include <siginfo.h>
1088 #define SIGADAABORT 48
1089 #define SIGNAL_STACK_SIZE 4096
1090 #define SIGNAL_STACK_ALIGNMENT 64
1092 struct Machine_State
1094 sigcontext_t context
;
1097 static void __gnat_error_handler (int, int, sigcontext_t
*);
1099 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
1100 connecting that handler, with the effects described in the sigaction
1104 If cleared and the signal is caught, the first argument is
1105 also the signal number but the second argument is the signal
1106 code identifying the cause of the signal. The third argument
1107 points to a sigcontext_t structure containing the receiving
1108 process's context when the signal was delivered.
1112 __gnat_error_handler (int sig
, int code
, sigcontext_t
*sc
)
1114 struct Machine_State
*mstate
;
1115 struct Exception_Data
*exception
;
1123 exception
= &program_error
;
1124 msg
= "SIGSEGV: (Invalid virtual address)";
1126 else if (code
== ENXIO
)
1128 exception
= &program_error
;
1129 msg
= "SIGSEGV: (Read beyond mapped object)";
1131 else if (code
== ENOSPC
)
1133 exception
= &program_error
; /* ??? storage_error ??? */
1134 msg
= "SIGSEGV: (Autogrow for file failed)";
1136 else if (code
== EACCES
|| code
== EEXIST
)
1138 /* ??? We handle stack overflows here, some of which do trigger
1139 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
1140 the documented valid codes for SEGV in the signal(5) man
1143 /* ??? Re-add smarts to further verify that we launched
1144 the stack into a guard page, not an attempt to
1145 write to .text or something */
1146 exception
= &storage_error
;
1147 msg
= "SIGSEGV: (stack overflow or erroneous memory access)";
1151 /* Just in case the OS guys did it to us again. Sometimes
1152 they fail to document all of the valid codes that are
1153 passed to signal handlers, just in case someone depends
1154 on knowing all the codes */
1155 exception
= &program_error
;
1156 msg
= "SIGSEGV: (Undocumented reason)";
1161 /* Map all bus errors to Program_Error. */
1162 exception
= &program_error
;
1167 /* Map all fpe errors to Constraint_Error. */
1168 exception
= &constraint_error
;
1173 if ((*Check_Abort_Status
) ())
1175 exception
= &_abort_signal
;
1184 /* Everything else is a Program_Error. */
1185 exception
= &program_error
;
1186 msg
= "unhandled signal";
1189 mstate
= (*Get_Machine_State_Addr
) ();
1191 memcpy ((void *) mstate
, (const void *) sc
, sizeof (sigcontext_t
));
1193 Raise_From_Signal_Handler (exception
, msg
);
1197 __gnat_install_handler (void)
1199 struct sigaction act
;
1201 /* Setup signal handler to map synchronous signals to appropriate
1202 exceptions. Make sure that the handler isn't interrupted by another
1203 signal that might cause a scheduling event! */
1205 act
.sa_handler
= __gnat_error_handler
;
1206 act
.sa_flags
= SA_NODEFER
+ SA_RESTART
;
1207 sigfillset (&act
.sa_mask
);
1208 sigemptyset (&act
.sa_mask
);
1210 /* Do not install handlers if interrupt state is "System" */
1211 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
1212 sigaction (SIGABRT
, &act
, NULL
);
1213 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
1214 sigaction (SIGFPE
, &act
, NULL
);
1215 if (__gnat_get_interrupt_state (SIGILL
) != 's')
1216 sigaction (SIGILL
, &act
, NULL
);
1217 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
1218 sigaction (SIGSEGV
, &act
, NULL
);
1219 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
1220 sigaction (SIGBUS
, &act
, NULL
);
1221 if (__gnat_get_interrupt_state (SIGADAABORT
) != 's')
1222 sigaction (SIGADAABORT
, &act
, NULL
);
1224 __gnat_handler_installed
= 1;
1228 __gnat_initialize (void)
1232 /*************************************************/
1233 /* __gnat_initialize (Solaris and SunOS Version) */
1234 /*************************************************/
1236 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
1239 #include <siginfo.h>
1241 static void __gnat_error_handler (int, siginfo_t
*);
1244 __gnat_error_handler (int sig
, siginfo_t
*sip
)
1246 struct Exception_Data
*exception
;
1247 static int recurse
= 0;
1250 /* If this was an explicit signal from a "kill", just resignal it. */
1251 if (SI_FROMUSER (sip
))
1253 signal (sig
, SIG_DFL
);
1254 kill (getpid(), sig
);
1257 /* Otherwise, treat it as something we handle. */
1261 /* If the problem was permissions, this is a constraint error.
1262 Likewise if the failing address isn't maximally aligned or if
1265 ??? Using a static variable here isn't task-safe, but it's
1266 much too hard to do anything else and we're just determining
1267 which exception to raise. */
1268 if (sip
->si_code
== SEGV_ACCERR
1269 || (((long) sip
->si_addr
) & 3) != 0
1272 exception
= &constraint_error
;
1277 /* See if the page before the faulting page is accessible. Do that
1278 by trying to access it. We'd like to simply try to access
1279 4096 + the faulting address, but it's not guaranteed to be
1280 the actual address, just to be on the same page. */
1283 ((long) sip
->si_addr
& - getpagesize ()))[getpagesize ()];
1284 exception
= &storage_error
;
1285 msg
= "stack overflow (or erroneous memory access)";
1290 exception
= &program_error
;
1295 exception
= &constraint_error
;
1300 exception
= &program_error
;
1301 msg
= "unhandled signal";
1306 Raise_From_Signal_Handler (exception
, msg
);
1310 __gnat_install_handler (void)
1312 struct sigaction act
;
1314 /* Set up signal handler to map synchronous signals to appropriate
1315 exceptions. Make sure that the handler isn't interrupted by another
1316 signal that might cause a scheduling event! */
1318 act
.sa_handler
= __gnat_error_handler
;
1319 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_SIGINFO
;
1320 sigemptyset (&act
.sa_mask
);
1322 /* Do not install handlers if interrupt state is "System" */
1323 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
1324 sigaction (SIGABRT
, &act
, NULL
);
1325 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
1326 sigaction (SIGFPE
, &act
, NULL
);
1327 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
1328 sigaction (SIGSEGV
, &act
, NULL
);
1329 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
1330 sigaction (SIGBUS
, &act
, NULL
);
1332 __gnat_handler_installed
= 1;
1336 __gnat_initialize (void)
1340 /***********************************/
1341 /* __gnat_initialize (VMS Version) */
1342 /***********************************/
1347 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1348 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1349 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1351 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1352 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1353 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1356 #if defined (IN_RTS) && !defined (__IA64)
1358 /* The prehandler actually gets control first on a condition. It swaps the
1359 stack pointer and calls the handler (__gnat_error_handler). */
1360 extern long __gnat_error_prehandler (void);
1362 extern char *__gnat_error_prehandler_stack
; /* Alternate signal stack */
1365 /* Conditions that don't have an Ada exception counterpart must raise
1366 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1367 referenced by user programs, not the compiler or tools. Hence the
1371 #define Non_Ada_Error system__aux_dec__non_ada_error
1372 extern struct Exception_Data Non_Ada_Error
;
1374 #define Coded_Exception system__vms_exception_table__coded_exception
1375 extern struct Exception_Data
*Coded_Exception (Exception_Code
);
1377 #define Base_Code_In system__vms_exception_table__base_code_in
1378 extern Exception_Code
Base_Code_In (Exception_Code
);
1381 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1382 Most of these are also defined in the header file ssdef.h which has not
1383 yet been converted to be recoginized by Gnu C. Some, which couldn't be
1384 located, are assigned names based on the DEC test suite tests which
1387 #define SS$_ACCVIO 12
1388 #define SS$_DEBUG 1132
1389 #define SS$_INTDIV 1156
1390 #define SS$_HPARITH 1284
1391 #define SS$_STKOVF 1364
1392 #define SS$_RESIGNAL 2328
1393 #define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
1394 #define SS$_CE24VRU 3253636 /* Write to unopened file */
1395 #define SS$_C980VTE 3246436 /* AST requests time slice */
1396 #define CMA$_EXIT_THREAD 4227492
1397 #define CMA$_EXCCOPLOS 4228108
1398 #define CMA$_ALERTED 4227460
1400 struct descriptor_s
{unsigned short len
, mbz
; char *adr
; };
1402 long __gnat_error_handler (int *, void *);
1405 __gnat_error_handler (int *sigargs
, void *mechargs
)
1407 struct Exception_Data
*exception
= 0;
1408 Exception_Code base_code
;
1413 struct descriptor_s msgdesc
;
1414 int msg_flag
= 0x000f; /* 1 bit for each of the four message parts */
1415 unsigned short outlen
;
1417 long curr_invo_handle
;
1420 /* Resignaled condtions aren't effected by by pragma Import_Exception */
1425 case CMA$_EXIT_THREAD
:
1426 return SS$_RESIGNAL
;
1428 case SS$_DEBUG
: /* Gdb attach, resignal to merge activate gdbstub. */
1429 return SS$_RESIGNAL
;
1431 case 1409786: /* Nickerson bug #33 ??? */
1432 return SS$_RESIGNAL
;
1434 case 1381050: /* Nickerson bug #33 ??? */
1435 return SS$_RESIGNAL
;
1437 case 20480426: /* RDB-E-STREAM_EOF */
1438 return SS$_RESIGNAL
;
1440 case 11829410: /* Resignalled as Use_Error for CE10VRC */
1441 return SS$_RESIGNAL
;
1446 /* See if it's an imported exception. Beware that registered exceptions
1447 are bound to their base code, with the severity bits masked off. */
1448 base_code
= Base_Code_In ((Exception_Code
) sigargs
[1]);
1449 exception
= Coded_Exception (base_code
);
1455 msgdesc
.adr
= message
;
1456 SYS$
GETMSG (sigargs
[1], &outlen
, &msgdesc
, msg_flag
, 0);
1457 message
[outlen
] = 0;
1460 exception
->Name_Length
= 19;
1461 /* The full name really should be get sys$getmsg returns. ??? */
1462 exception
->Full_Name
= "IMPORTED_EXCEPTION";
1463 exception
->Import_Code
= base_code
;
1471 if (sigargs
[3] == 0)
1473 exception
= &constraint_error
;
1474 msg
= "access zero";
1478 exception
= &storage_error
;
1479 msg
= "stack overflow (or erroneous memory access)";
1484 exception
= &storage_error
;
1485 msg
= "stack overflow";
1489 exception
= &constraint_error
;
1490 msg
= "division by zero";
1495 return SS$_RESIGNAL
; /* toplev.c handles for compiler */
1498 exception
= &constraint_error
;
1499 msg
= "arithmetic error";
1504 case MTH$_FLOOVEMAT
:
1505 exception
= &constraint_error
;
1506 msg
= "floating overflow in math library";
1510 exception
= &constraint_error
;
1515 exception
= &program_error
;
1521 exception
= &program_error
;
1523 /* User programs expect Non_Ada_Error to be raised, reference
1524 DEC Ada test CXCONDHAN. */
1525 exception
= &Non_Ada_Error
;
1529 msgdesc
.adr
= message
;
1530 SYS$
GETMSG (sigargs
[1], &outlen
, &msgdesc
, msg_flag
, 0);
1531 message
[outlen
] = 0;
1536 mstate
= (long *) (*Get_Machine_State_Addr
) ();
1539 lib_get_curr_invo_context (&curr_icb
);
1540 lib_get_prev_invo_context (&curr_icb
);
1541 lib_get_prev_invo_context (&curr_icb
);
1542 curr_invo_handle
= lib_get_invo_handle (&curr_icb
);
1543 *mstate
= curr_invo_handle
;
1545 Raise_From_Signal_Handler (exception
, msg
);
1549 __gnat_install_handler (void)
1552 #if defined (IN_RTS) && !defined (__IA64)
1555 c
= (char *) xmalloc (2049);
1557 __gnat_error_prehandler_stack
= &c
[2048];
1559 /* __gnat_error_prehandler is an assembly function. */
1560 SYS$
SETEXV (1, __gnat_error_prehandler
, 3, &prvhnd
);
1562 SYS$
SETEXV (1, __gnat_error_handler
, 3, &prvhnd
);
1564 __gnat_handler_installed
= 1;
1568 __gnat_initialize(void)
1572 /*************************************************/
1573 /* __gnat_initialize (FreeBSD version) */
1574 /*************************************************/
1576 #elif defined (__FreeBSD__)
1582 __gnat_error_handler (sig
, code
, sc
)
1585 struct sigcontext
*sc
;
1587 struct Exception_Data
*exception
;
1593 exception
= &constraint_error
;
1598 exception
= &constraint_error
;
1603 exception
= &storage_error
;
1604 msg
= "stack overflow or erroneous memory access";
1608 exception
= &constraint_error
;
1613 exception
= &program_error
;
1614 msg
= "unhandled signal";
1617 Raise_From_Signal_Handler (exception
, msg
);
1621 __gnat_install_handler ()
1623 struct sigaction act
;
1625 /* Set up signal handler to map synchronous signals to appropriate
1626 exceptions. Make sure that the handler isn't interrupted by another
1627 signal that might cause a scheduling event! */
1629 act
.sa_handler
= __gnat_error_handler
;
1630 act
.sa_flags
= SA_NODEFER
| SA_RESTART
;
1631 (void) sigemptyset (&act
.sa_mask
);
1633 (void) sigaction (SIGILL
, &act
, NULL
);
1634 (void) sigaction (SIGFPE
, &act
, NULL
);
1635 (void) sigaction (SIGSEGV
, &act
, NULL
);
1636 (void) sigaction (SIGBUS
, &act
, NULL
);
1639 void __gnat_init_float ();
1642 __gnat_initialize ()
1644 __gnat_install_handler ();
1646 /* XXX - Initialize floating-point coprocessor. This call is
1647 needed because FreeBSD defaults to 64-bit precision instead
1648 of 80-bit precision? We require the full precision for
1649 proper operation, given that we have set Max_Digits etc
1650 with this in mind */
1651 __gnat_init_float ();
1654 /***************************************/
1655 /* __gnat_initialize (VXWorks Version) */
1656 /***************************************/
1658 #elif defined(__vxworks)
1661 #include <taskLib.h>
1665 extern int __gnat_inum_to_ivec (int);
1666 static void __gnat_error_handler (int, int, struct sigcontext
*);
1667 void __gnat_map_signal (int);
1669 #ifndef __alpha_vxworks
1671 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1674 extern long getpid (void);
1679 return taskIdSelf ();
1683 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1685 __gnat_inum_to_ivec (int num
)
1687 return INUM_TO_IVEC (num
);
1690 /* Exported to 5zintman.adb in order to handle different signal
1691 to exception mappings in different VxWorks versions */
1693 __gnat_map_signal (int sig
)
1695 struct Exception_Data
*exception
;
1701 exception
= &constraint_error
;
1705 exception
= &constraint_error
;
1709 exception
= &program_error
;
1714 exception
= &storage_error
;
1715 msg
= "SIGBUS: possible stack overflow";
1717 exception
= &program_error
;
1722 exception
= &program_error
;
1723 msg
= "unhandled signal";
1726 Raise_From_Signal_Handler (exception
, msg
);
1730 __gnat_error_handler (int sig
, int code
, struct sigcontext
*sc
)
1735 /* VxWorks will always mask out the signal during the signal handler and
1736 will reenable it on a longjmp. GNAT does not generate a longjmp to
1737 return from a signal handler so the signal will still be masked unless
1739 sigprocmask (SIG_SETMASK
, NULL
, &mask
);
1740 sigdelset (&mask
, sig
);
1741 sigprocmask (SIG_SETMASK
, &mask
, NULL
);
1743 /* VxWorks will suspend the task when it gets a hardware exception. We
1744 take the liberty of resuming the task for the application. */
1745 if (taskIsSuspended (taskIdSelf ()) != 0)
1746 taskResume (taskIdSelf ());
1748 __gnat_map_signal (sig
);
1753 __gnat_install_handler (void)
1755 struct sigaction act
;
1757 /* Setup signal handler to map synchronous signals to appropriate
1758 exceptions. Make sure that the handler isn't interrupted by another
1759 signal that might cause a scheduling event! */
1761 act
.sa_handler
= __gnat_error_handler
;
1762 act
.sa_flags
= SA_SIGINFO
| SA_ONSTACK
;
1763 sigemptyset (&act
.sa_mask
);
1765 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1766 applies to vectored hardware interrupts, not signals */
1767 sigaction (SIGFPE
, &act
, NULL
);
1768 sigaction (SIGILL
, &act
, NULL
);
1769 sigaction (SIGSEGV
, &act
, NULL
);
1770 sigaction (SIGBUS
, &act
, NULL
);
1772 __gnat_handler_installed
= 1;
1775 #define HAVE_GNAT_INIT_FLOAT
1778 __gnat_init_float (void)
1780 /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1781 to get correct Ada semantic. */
1782 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT)
1787 /* Similarily for sparc64. Achieved by masking bits in the Trap Enable Mask
1788 field of the Floating-point Status Register (see the Sparc Architecture
1789 Manual Version 9, p 48). */
1790 #if defined (sparc64)
1792 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1793 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1794 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1795 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1796 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1800 __asm__("st %%fsr, %0" : "=m" (fsr
));
1801 fsr
&= ~(FSR_TEM_OFM
| FSR_TEM_UFM
);
1802 __asm__("ld %0, %%fsr" : : "m" (fsr
));
1808 __gnat_initialize (void)
1810 __gnat_init_float ();
1812 /* On targets where we might be using the ZCX scheme, we need to register
1815 For applications loaded as a set of "modules", the crtstuff objects
1816 linked in (crtbegin/endS) are tailored to provide this service a-la C++
1817 static constructor fashion, typically triggered by the VxWorks loader.
1818 This is achieved by way of a special variable declaration in the crt
1819 object, the name of which has been deduced by analyzing the output of the
1820 "munching" step documented for C++. The de-registration call is handled
1821 symetrically, a-la C++ destructor fashion and typically triggered by the
1822 dynamic unloader. Note that since the tables shall be registered against
1823 a common datastructure, libgcc should be one of the modules (vs beeing
1824 partially linked against all the others at build time) and shall be
1827 For applications linked with the kernel, the scheme above would lead to
1828 duplicated symbols because the VxWorks kernel build "munches" by default.
1829 To prevent those conflicts, we link against crtbegin/end objects that
1830 don't include the special variable and directly call the appropriate
1831 function here. We'll never unload that, so there is no de-registration to
1834 For whole applications loaded as a single module, we may use one scheme
1835 or the other, except for the mixed Ada/C++ case in which the first scheme
1836 would fail for the same reason as in the linked-with-kernel situation.
1838 We can differentiate by looking at the __module_has_ctors value provided
1839 by each class of crt objects. As of today, selecting the crt set with the
1840 static ctors/dtors capabilities (first scheme above) is triggered by
1841 adding "-static" to the gcc *link* command line options. Without this,
1842 the other set of crt objects is fetched.
1844 This is a first approach, tightly synchronized with a number of GCC
1845 configuration and crtstuff changes. We need to ensure that those changes
1846 are there to activate this circuitry. */
1848 #if DWARF2_UNWIND_INFO && defined (_ARCH_PPC)
1850 extern const int __module_has_ctors
;
1851 extern void __do_global_ctors ();
1853 if (! __module_has_ctors
)
1854 __do_global_ctors ();
1859 /********************************/
1860 /* __gnat_initialize for NetBSD */
1861 /********************************/
1863 #elif defined(__NetBSD__)
1869 __gnat_error_handler (int sig
)
1871 struct Exception_Data
*exception
;
1877 exception
= &constraint_error
;
1881 exception
= &constraint_error
;
1885 exception
= &storage_error
;
1886 msg
= "stack overflow or erroneous memory access";
1889 exception
= &constraint_error
;
1893 exception
= &program_error
;
1894 msg
= "unhandled signal";
1897 Raise_From_Signal_Handler(exception
, msg
);
1901 __gnat_install_handler(void)
1903 struct sigaction act
;
1905 act
.sa_handler
= __gnat_error_handler
;
1906 act
.sa_flags
= SA_NODEFER
| SA_RESTART
;
1907 sigemptyset (&act
.sa_mask
);
1909 /* Do not install handlers if interrupt state is "System" */
1910 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
1911 sigaction (SIGFPE
, &act
, NULL
);
1912 if (__gnat_get_interrupt_state (SIGILL
) != 's')
1913 sigaction (SIGILL
, &act
, NULL
);
1914 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
1915 sigaction (SIGSEGV
, &act
, NULL
);
1916 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
1917 sigaction (SIGBUS
, &act
, NULL
);
1919 __gnat_handler_installed
= 1;
1923 __gnat_initialize (void)
1925 __gnat_install_handler ();
1926 __gnat_init_float ();
1931 /* For all other versions of GNAT, the initialize routine and handler
1932 installation do nothing */
1934 /***************************************/
1935 /* __gnat_initialize (Default Version) */
1936 /***************************************/
1939 __gnat_initialize (void)
1943 /********************************************/
1944 /* __gnat_install_handler (Default Version) */
1945 /********************************************/
1948 __gnat_install_handler (void)
1950 __gnat_handler_installed
= 1;
1955 /*********************/
1956 /* __gnat_init_float */
1957 /*********************/
1959 /* This routine is called as each process thread is created, for possible
1960 initialization of the FP processor. This version is used under INTERIX,
1961 WIN32 and could be used under OS/2 */
1963 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1964 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1966 #define HAVE_GNAT_INIT_FLOAT
1969 __gnat_init_float (void)
1971 #if defined (__i386__) || defined (i386)
1973 /* This is used to properly initialize the FPU on an x86 for each
1978 #endif /* Defined __i386__ */
1982 #ifndef HAVE_GNAT_INIT_FLOAT
1984 /* All targets without a specific __gnat_init_float will use an empty one */
1986 __gnat_init_float (void)