Typo in last patch.
[official-gcc.git] / gcc / ada / init.c
blob9d79b6c3c0e233f87b286b8313c2e3f2a92d237e
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * I N I T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 1992-2004 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;
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 */
140 char
141 __gnat_get_interrupt_state (int intrup)
143 if (intrup >= __gl_num_interrupt_states)
144 return 'n';
145 else
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) */
164 void
165 __gnat_set_globals (int main_priority,
166 int time_slice_val,
167 char wc_encoding,
168 char locking_policy,
169 char queuing_policy,
170 char task_dispatching_policy,
171 char *restrictions,
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
188 in any case.
190 We do not check either for the consistency of exception tracebacks,
191 because exception tracebacks are not normally set in Stand-Alone
192 libraries. If a library or the main program set the exception
193 tracebacks, then they are never reset afterwards (see below).
195 The value of main_priority is meaningful only when we are invoked
196 from the main program elaboration routine of an Ada application.
197 Checking the consistency of this parameter should therefore not be
198 done. Since it is assured that the main program elaboration will
199 always invoke this procedure before any library elaboration
200 routine, only the value of main_priority during the first call
201 should be taken into account and all the subsequent ones should be
202 ignored. Note that the case where the main program is not written
203 in Ada is also properly handled, since the default value will then
204 be used for this parameter.
206 For identical reasons, the consistency of time_slice_val should not
207 be checked. */
209 if (already_called)
211 if (__gl_locking_policy != locking_policy
212 || __gl_queuing_policy != queuing_policy
213 || __gl_task_dispatching_policy != task_dispatching_policy
214 || __gl_unreserve_all_interrupts != unreserve_all_interrupts
215 || __gl_zero_cost_exceptions != zero_cost_exceptions)
216 __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;
224 return;
226 already_called = 1;
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
246 release is out. */
248 #ifdef IN_RTS
249 __gl_zero_cost_exceptions = zero_cost_exceptions;
250 #else
251 __gl_zero_cost_exceptions = 0;
252 /* We never build the compiler to run in ZCX mode currently anyway. */
253 #endif
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
281 instance).
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 /***********************************/
314 #if defined (_AIX)
316 #include <signal.h>
317 #include <sys/time.h>
319 /* Some versions of AIX don't define SA_NODEFER. */
321 #ifndef SA_NODEFER
322 #define SA_NODEFER 0
323 #endif /* SA_NODEFER */
325 /* Versions of AIX before 4.3 don't have nanosleep but provide
326 nsleep instead. */
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);
342 static void
343 __gnat_error_handler (int sig)
345 struct Exception_Data *exception;
346 const char *msg;
348 switch (sig)
350 case SIGSEGV:
351 /* FIXME: we need to detect the case of a *real* SIGSEGV */
352 exception = &storage_error;
353 msg = "stack overflow or erroneous memory access";
354 break;
356 case SIGBUS:
357 exception = &constraint_error;
358 msg = "SIGBUS";
359 break;
361 case SIGFPE:
362 exception = &constraint_error;
363 msg = "SIGFPE";
364 break;
366 default:
367 exception = &program_error;
368 msg = "unhandled signal";
371 Raise_From_Signal_Handler (exception, msg);
374 void
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;
402 void
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 (). */
417 void
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. */
433 #include <signal.h>
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 *);
444 static void
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;
450 const char *msg;
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. */
460 switch (sig)
462 case SIGSEGV:
463 /* If the problem was permissions, this is a constraint error.
464 Likewise if the failing address isn't maximally aligned or if
465 we've recursed.
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
472 || recurse)
474 exception = &constraint_error;
475 msg = "SIGSEGV";
477 else
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. */
483 recurse++;
484 ((volatile char *)
485 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
486 msg = "stack overflow (or erroneous memory access)";
487 exception = &storage_error;
489 break;
491 case SIGBUS:
492 exception = &program_error;
493 msg = "SIGBUS";
494 break;
496 case SIGFPE:
497 exception = &constraint_error;
498 msg = "SIGFPE";
499 break;
501 default:
502 exception = &program_error;
503 msg = "unhandled signal";
506 recurse = 0;
507 mstate = (struct sigcontext *) (*Get_Machine_State_Addr) ();
508 if (mstate != 0)
509 *mstate = *context;
511 Raise_From_Signal_Handler (exception, (char *) msg);
514 void
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;
542 void
543 __gnat_initialize (void)
547 /* Routines called by 5amastop.adb. */
549 #define SC_GP 29
551 char *
552 __gnat_get_code_loc (struct sigcontext *context)
554 return (char *) context->sc_pc;
557 void
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);
565 size_t
566 __gnat_machine_state_length (void)
568 return sizeof (struct sigcontext);
571 /************************************/
572 /* __gnat_initialize (HPUX Version) */
573 /************************************/
575 #elif defined (hpux)
577 #include <signal.h>
579 static void __gnat_error_handler (int);
581 static void
582 __gnat_error_handler (int sig)
584 struct Exception_Data *exception;
585 char *msg;
587 switch (sig)
589 case SIGSEGV:
590 /* FIXME: we need to detect the case of a *real* SIGSEGV */
591 exception = &storage_error;
592 msg = "stack overflow or erroneous memory access";
593 break;
595 case SIGBUS:
596 exception = &constraint_error;
597 msg = "SIGBUS";
598 break;
600 case SIGFPE:
601 exception = &constraint_error;
602 msg = "SIGFPE";
603 break;
605 default:
606 exception = &program_error;
607 msg = "unhandled signal";
610 Raise_From_Signal_Handler (exception, msg);
613 void
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
623 handler itself. */
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). */
629 stack_t stack;
631 stack.ss_sp = handler_stack;
632 stack.ss_size = sizeof (handler_stack);
633 stack.ss_flags = 0;
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;
656 void
657 __gnat_initialize (void)
661 /*****************************************/
662 /* __gnat_initialize (GNU/Linux Version) */
663 /*****************************************/
665 #elif defined (linux) && defined (i386) && !defined (__RT__)
667 #include <signal.h>
668 #include <asm/sigcontext.h>
670 /* GNU/Linux, which uses glibc, does not define NULL in included
671 header files */
673 #if !defined (NULL)
674 #define NULL ((void *) 0)
675 #endif
677 struct Machine_State
679 unsigned long eip;
680 unsigned long ebx;
681 unsigned long esp;
682 unsigned long ebp;
683 unsigned long esi;
684 unsigned long edi;
687 static void __gnat_error_handler (int);
689 static void
690 __gnat_error_handler (int sig)
692 struct Exception_Data *exception;
693 const char *msg;
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;
706 switch (sig)
708 case SIGSEGV:
709 /* If the problem was permissions, this is a constraint error.
710 Likewise if the failing address isn't maximally aligned or if
711 we've recursed.
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. */
716 if (recurse)
718 exception = &constraint_error;
719 msg = "SIGSEGV";
721 else
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:
730 recurse++;
731 ((volatile char *)
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;
745 break;
747 case SIGBUS:
748 exception = &constraint_error;
749 msg = "SIGBUS";
750 break;
752 case SIGFPE:
753 exception = &constraint_error;
754 msg = "SIGFPE";
755 break;
757 default:
758 exception = &program_error;
759 msg = "unhandled signal";
762 mstate = (*Get_Machine_State_Addr) ();
763 if (mstate)
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;
773 recurse = 0;
774 Raise_From_Signal_Handler (exception, msg);
777 void
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;
805 void
806 __gnat_initialize (void)
810 /******************************************/
811 /* __gnat_initialize (NT-mingw32 Version) */
812 /******************************************/
814 #elif defined (__MINGW32__)
815 #include <windows.h>
817 static LONG WINAPI __gnat_error_handler (PEXCEPTION_POINTERS);
819 /* __gnat_initialize (mingw32). */
821 static LONG WINAPI
822 __gnat_error_handler (PEXCEPTION_POINTERS info)
824 static int recurse;
825 struct Exception_Data *exception;
826 const char *msg;
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
834 || recurse)
836 exception = &program_error;
837 msg = "EXCEPTION_ACCESS_VIOLATION";
839 else
841 /* See if the page before the faulting page is accessible. Do that
842 by trying to access it. */
843 recurse++;
844 * ((volatile char *) (info->ExceptionRecord->ExceptionInformation[1]
845 + 4096));
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 recurse = 0;
932 Raise_From_Signal_Handler (exception, msg);
933 return 0; /* This is never reached, avoid compiler warning */
936 void
937 __gnat_install_handler (void)
939 SetUnhandledExceptionFilter (__gnat_error_handler);
940 __gnat_handler_installed = 1;
943 void
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 */
956 __gnat_plist_init();
959 /***************************************/
960 /* __gnat_initialize (Interix Version) */
961 /***************************************/
963 #elif defined (__INTERIX)
965 #include <signal.h>
967 static void __gnat_error_handler (int);
969 static void
970 __gnat_error_handler (int sig)
972 struct Exception_Data *exception;
973 char *msg;
975 switch (sig)
977 case SIGSEGV:
978 exception = &storage_error;
979 msg = "stack overflow or erroneous memory access";
980 break;
982 case SIGBUS:
983 exception = &constraint_error;
984 msg = "SIGBUS";
985 break;
987 case SIGFPE:
988 exception = &constraint_error;
989 msg = "SIGFPE";
990 break;
992 default:
993 exception = &program_error;
994 msg = "unhandled signal";
997 Raise_From_Signal_Handler (exception, msg);
1000 void
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;
1010 act.sa_flags = 0;
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;
1026 void
1027 __gnat_initialize (void)
1029 __gnat_init_float ();
1032 /**************************************/
1033 /* __gnat_initialize (LynxOS Version) */
1034 /**************************************/
1036 #elif defined (__Lynx__)
1038 void
1039 __gnat_initialize (void)
1041 __gnat_init_float ();
1044 /*********************************/
1045 /* __gnat_install_handler (Lynx) */
1046 /*********************************/
1048 void
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 */
1060 void
1061 __gnat_initialize (void)
1065 /*********************************/
1066 /* __gnat_install_handler (OS/2) */
1067 /*********************************/
1069 void
1070 __gnat_install_handler (void)
1072 __gnat_handler_installed = 1;
1075 /***********************************/
1076 /* __gnat_initialize (SGI Version) */
1077 /***********************************/
1079 #elif defined (sgi)
1081 #include <signal.h>
1082 #include <siginfo.h>
1084 #ifndef NULL
1085 #define NULL 0
1086 #endif
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
1101 man page:
1103 SA_SIGINFO [...]
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.
1111 static void
1112 __gnat_error_handler (int sig, int code, sigcontext_t *sc)
1114 struct Machine_State *mstate;
1115 struct Exception_Data *exception;
1116 const char *msg;
1118 switch (sig)
1120 case SIGSEGV:
1121 if (code == EFAULT)
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
1141 page. */
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)";
1149 else
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)";
1158 break;
1160 case SIGBUS:
1161 /* Map all bus errors to Program_Error. */
1162 exception = &program_error;
1163 msg = "SIGBUS";
1164 break;
1166 case SIGFPE:
1167 /* Map all fpe errors to Constraint_Error. */
1168 exception = &constraint_error;
1169 msg = "SIGFPE";
1170 break;
1172 case SIGADAABORT:
1173 if ((*Check_Abort_Status) ())
1175 exception = &_abort_signal;
1176 msg = "";
1178 else
1179 return;
1181 break;
1183 default:
1184 /* Everything else is a Program_Error. */
1185 exception = &program_error;
1186 msg = "unhandled signal";
1189 mstate = (*Get_Machine_State_Addr) ();
1190 if (mstate != 0)
1191 memcpy ((void *) mstate, (const void *) sc, sizeof (sigcontext_t));
1193 Raise_From_Signal_Handler (exception, msg);
1196 void
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;
1227 void
1228 __gnat_initialize (void)
1232 /*************************************************/
1233 /* __gnat_initialize (Solaris and SunOS Version) */
1234 /*************************************************/
1236 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
1238 #include <signal.h>
1239 #include <siginfo.h>
1241 static void __gnat_error_handler (int, siginfo_t *);
1243 static void
1244 __gnat_error_handler (int sig, siginfo_t *sip)
1246 struct Exception_Data *exception;
1247 static int recurse = 0;
1248 const char *msg;
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. */
1258 switch (sig)
1260 case SIGSEGV:
1261 /* If the problem was permissions, this is a constraint error.
1262 Likewise if the failing address isn't maximally aligned or if
1263 we've recursed.
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
1270 || recurse)
1272 exception = &constraint_error;
1273 msg = "SIGSEGV";
1275 else
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. */
1281 recurse++;
1282 ((volatile char *)
1283 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1284 exception = &storage_error;
1285 msg = "stack overflow (or erroneous memory access)";
1287 break;
1289 case SIGBUS:
1290 exception = &program_error;
1291 msg = "SIGBUS";
1292 break;
1294 case SIGFPE:
1295 exception = &constraint_error;
1296 msg = "SIGFPE";
1297 break;
1299 default:
1300 exception = &program_error;
1301 msg = "unhandled signal";
1304 recurse = 0;
1306 Raise_From_Signal_Handler (exception, msg);
1309 void
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;
1335 void
1336 __gnat_initialize (void)
1340 /***********************************/
1341 /* __gnat_initialize (VMS Version) */
1342 /***********************************/
1344 #elif defined (VMS)
1346 #ifdef __IA64
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
1350 #else
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
1354 #endif
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 */
1363 #endif
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
1368 #ifdef IN_RTS. */
1370 #ifdef IN_RTS
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);
1379 #endif
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
1385 raise them. */
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 *);
1404 long
1405 __gnat_error_handler (int *sigargs, void *mechargs)
1407 struct Exception_Data *exception = 0;
1408 Exception_Code base_code;
1410 char *msg = "";
1411 char message[256];
1412 long prvhnd;
1413 struct descriptor_s msgdesc;
1414 int msg_flag = 0x000f; /* 1 bit for each of the four message parts */
1415 unsigned short outlen;
1416 char curr_icb[544];
1417 long curr_invo_handle;
1418 long *mstate;
1420 /* Resignaled condtions aren't effected by by pragma Import_Exception */
1422 switch (sigargs[1])
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;
1445 #ifdef IN_RTS
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);
1451 if (exception)
1453 msgdesc.len = 256;
1454 msgdesc.mbz = 0;
1455 msgdesc.adr = message;
1456 SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1457 message[outlen] = 0;
1458 msg = message;
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;
1465 #endif
1467 if (exception == 0)
1468 switch (sigargs[1])
1470 case SS$_ACCVIO:
1471 if (sigargs[3] == 0)
1473 exception = &constraint_error;
1474 msg = "access zero";
1476 else
1478 exception = &storage_error;
1479 msg = "stack overflow (or erroneous memory access)";
1481 break;
1483 case SS$_STKOVF:
1484 exception = &storage_error;
1485 msg = "stack overflow";
1486 break;
1488 case SS$_INTDIV:
1489 exception = &constraint_error;
1490 msg = "division by zero";
1491 break;
1493 case SS$_HPARITH:
1494 #ifndef IN_RTS
1495 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1496 #else
1498 exception = &constraint_error;
1499 msg = "arithmetic error";
1501 #endif
1502 break;
1504 case MTH$_FLOOVEMAT:
1505 exception = &constraint_error;
1506 msg = "floating overflow in math library";
1507 break;
1509 case SS$_CE24VRU:
1510 exception = &constraint_error;
1511 msg = "";
1512 break;
1514 case SS$_C980VTE:
1515 exception = &program_error;
1516 msg = "";
1517 break;
1519 default:
1520 #ifndef IN_RTS
1521 exception = &program_error;
1522 #else
1523 /* User programs expect Non_Ada_Error to be raised, reference
1524 DEC Ada test CXCONDHAN. */
1525 exception = &Non_Ada_Error;
1526 #endif
1527 msgdesc.len = 256;
1528 msgdesc.mbz = 0;
1529 msgdesc.adr = message;
1530 SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1531 message[outlen] = 0;
1532 msg = message;
1533 break;
1536 mstate = (long *) (*Get_Machine_State_Addr) ();
1537 if (mstate != 0)
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);
1548 void
1549 __gnat_install_handler (void)
1551 long prvhnd;
1552 #if defined (IN_RTS) && !defined (__IA64)
1553 char *c;
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);
1561 #else
1562 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1563 #endif
1564 __gnat_handler_installed = 1;
1567 void
1568 __gnat_initialize(void)
1572 /*************************************************/
1573 /* __gnat_initialize (FreeBSD version) */
1574 /*************************************************/
1576 #elif defined (__FreeBSD__)
1578 #include <signal.h>
1579 #include <unistd.h>
1581 static void
1582 __gnat_error_handler (sig, code, sc)
1583 int sig;
1584 int code;
1585 struct sigcontext *sc;
1587 struct Exception_Data *exception;
1588 char *msg;
1590 switch (sig)
1592 case SIGFPE:
1593 exception = &constraint_error;
1594 msg = "SIGFPE";
1595 break;
1597 case SIGILL:
1598 exception = &constraint_error;
1599 msg = "SIGILL";
1600 break;
1602 case SIGSEGV:
1603 exception = &storage_error;
1604 msg = "stack overflow or erroneous memory access";
1605 break;
1607 case SIGBUS:
1608 exception = &constraint_error;
1609 msg = "SIGBUS";
1610 break;
1612 default:
1613 exception = &program_error;
1614 msg = "unhandled signal";
1617 Raise_From_Signal_Handler (exception, msg);
1620 void
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 ();
1641 void
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)
1660 #include <signal.h>
1661 #include <taskLib.h>
1662 #include <intLib.h>
1663 #include <iv.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
1672 on Alpha VxWorks */
1674 extern long getpid (void);
1676 long
1677 getpid (void)
1679 return taskIdSelf ();
1681 #endif
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 */
1692 void
1693 __gnat_map_signal (int sig)
1695 struct Exception_Data *exception;
1696 char *msg;
1698 switch (sig)
1700 case SIGFPE:
1701 exception = &constraint_error;
1702 msg = "SIGFPE";
1703 break;
1704 case SIGILL:
1705 exception = &constraint_error;
1706 msg = "SIGILL";
1707 break;
1708 case SIGSEGV:
1709 exception = &program_error;
1710 msg = "SIGSEGV";
1711 break;
1712 case SIGBUS:
1713 #ifdef VTHREADS
1714 exception = &storage_error;
1715 msg = "SIGBUS: possible stack overflow";
1716 #else
1717 exception = &program_error;
1718 msg = "SIGBUS";
1719 #endif
1720 break;
1721 default:
1722 exception = &program_error;
1723 msg = "unhandled signal";
1726 Raise_From_Signal_Handler (exception, msg);
1729 static void
1730 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1732 sigset_t mask;
1733 int result;
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
1738 we unmask it. */
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);
1752 void
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
1777 void
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)
1783 asm ("mtfsb0 25");
1784 asm ("mtfsb0 26");
1785 #endif
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 */
1798 unsigned int fsr;
1800 __asm__("st %%fsr, %0" : "=m" (fsr));
1801 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1802 __asm__("ld %0, %%fsr" : : "m" (fsr));
1804 #endif
1807 void
1808 __gnat_initialize (void)
1810 __gnat_init_float ();
1812 /* On targets where we might be using the ZCX scheme, we need to register
1813 the frame tables.
1815 For application "modules", the crtstuff objects linked in (crtbegin/endS)
1816 are tailored to provide this service a-la C++ constructor fashion,
1817 typically triggered by the dynamic loader. This is achieved by way of a
1818 special variable declaration in the crt object, the name of which has
1819 been deduced by analyzing the output of the "munching" step documented
1820 for C++. The de-registration call is handled symetrically, a-la C++
1821 destructor fashion and typically triggered by the dynamic unloader. With
1822 this scheme, a mixed Ada/C++ application has to be linked and loaded as
1823 separate modules for each language, which is not unreasonable anyway.
1825 For applications statically linked with the kernel, the module scheme
1826 above would lead to duplicated symbols because the VxWorks kernel build
1827 "munches" by default. To prevent those conflicts, we link against
1828 crtbegin/end objects that don't include the special variable and directly
1829 call the appropriate function here. We'll never unload that, so there is
1830 no de-registration to worry about.
1832 We can differentiate by looking at the __module_has_ctors value provided
1833 by each class of crt objects. As of today, selecting the crt set intended
1834 for applications to be statically linked with the kernel is triggered by
1835 adding "-static" to the gcc *link* command line options.
1837 This is a first approach, tightly synchronized with a number of GCC
1838 configuration and crtstuff changes. We need to ensure that those changes
1839 are there to activate this circuitry. */
1841 #if DWARF2_UNWIND_INFO && defined (_ARCH_PPC)
1843 extern const int __module_has_ctors;
1844 extern void __do_global_ctors ();
1846 if (! __module_has_ctors)
1847 __do_global_ctors ();
1849 #endif
1852 /********************************/
1853 /* __gnat_initialize for NetBSD */
1854 /********************************/
1856 #elif defined(__NetBSD__)
1858 #include <signal.h>
1859 #include <unistd.h>
1861 static void
1862 __gnat_error_handler (int sig)
1864 struct Exception_Data *exception;
1865 const char *msg;
1867 switch(sig)
1869 case SIGFPE:
1870 exception = &constraint_error;
1871 msg = "SIGFPE";
1872 break;
1873 case SIGILL:
1874 exception = &constraint_error;
1875 msg = "SIGILL";
1876 break;
1877 case SIGSEGV:
1878 exception = &storage_error;
1879 msg = "stack overflow or erroneous memory access";
1880 break;
1881 case SIGBUS:
1882 exception = &constraint_error;
1883 msg = "SIGBUS";
1884 break;
1885 default:
1886 exception = &program_error;
1887 msg = "unhandled signal";
1890 Raise_From_Signal_Handler(exception, msg);
1893 void
1894 __gnat_install_handler(void)
1896 struct sigaction act;
1898 act.sa_handler = __gnat_error_handler;
1899 act.sa_flags = SA_NODEFER | SA_RESTART;
1900 sigemptyset (&act.sa_mask);
1902 /* Do not install handlers if interrupt state is "System" */
1903 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1904 sigaction (SIGFPE, &act, NULL);
1905 if (__gnat_get_interrupt_state (SIGILL) != 's')
1906 sigaction (SIGILL, &act, NULL);
1907 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1908 sigaction (SIGSEGV, &act, NULL);
1909 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1910 sigaction (SIGBUS, &act, NULL);
1912 __gnat_handler_installed = 1;
1915 void
1916 __gnat_initialize (void)
1918 __gnat_install_handler ();
1919 __gnat_init_float ();
1922 #else
1924 /* For all other versions of GNAT, the initialize routine and handler
1925 installation do nothing */
1927 /***************************************/
1928 /* __gnat_initialize (Default Version) */
1929 /***************************************/
1931 void
1932 __gnat_initialize (void)
1936 /********************************************/
1937 /* __gnat_install_handler (Default Version) */
1938 /********************************************/
1940 void
1941 __gnat_install_handler (void)
1943 __gnat_handler_installed = 1;
1946 #endif
1948 /*********************/
1949 /* __gnat_init_float */
1950 /*********************/
1952 /* This routine is called as each process thread is created, for possible
1953 initialization of the FP processor. This version is used under INTERIX,
1954 WIN32 and could be used under OS/2 */
1956 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1957 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1959 #define HAVE_GNAT_INIT_FLOAT
1961 void
1962 __gnat_init_float (void)
1964 #if defined (__i386__) || defined (i386)
1966 /* This is used to properly initialize the FPU on an x86 for each
1967 process thread. */
1969 asm ("finit");
1971 #endif /* Defined __i386__ */
1973 #endif
1975 #ifndef HAVE_GNAT_INIT_FLOAT
1977 /* All targets without a specific __gnat_init_float will use an empty one */
1978 void
1979 __gnat_init_float (void)
1982 #endif