fixing pr42337
[official-gcc.git] / gcc / ada / init.c
blob5e5d1c60b448afcf6679389ab8913a9c664a261c
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * I N I T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 1992-2009, 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 3, 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. *
17 * *
18 * As a special exception under Section 7 of GPL version 3, you are granted *
19 * additional permissions described in the GCC Runtime Library Exception, *
20 * version 3.1, as published by the Free Software Foundation. *
21 * *
22 * You should have received a copy of the GNU General Public License and *
23 * a copy of the GCC Runtime Library Exception along with this program; *
24 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
25 * <http://www.gnu.org/licenses/>. *
26 * *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
29 * *
30 ****************************************************************************/
32 /* This unit contains initialization circuits that are system dependent.
33 A major part of the functionality involves stack overflow checking.
34 The GCC backend generates probe instructions to test for stack overflow.
35 For details on the exact approach used to generate these probes, see the
36 "Using and Porting GCC" manual, in particular the "Stack Checking" section
37 and the subsection "Specifying How Stack Checking is Done". The handlers
38 installed by this file are used to catch the resulting signals that come
39 from these probes failing (i.e. touching protected pages). */
41 /* This file should be kept synchronized with 2sinit.ads, 2sinit.adb,
42 s-init-ae653-cert.adb and s-init-xi-sparc.adb. All these files implement
43 the required functionality for different targets. */
45 /* The following include is here to meet the published VxWorks requirement
46 that the __vxworks header appear before any other include. */
47 #ifdef __vxworks
48 #include "vxWorks.h"
49 #endif
51 #ifdef IN_RTS
52 #include "tconfig.h"
53 #include "tsystem.h"
54 #include <sys/stat.h>
56 /* We don't have libiberty, so use malloc. */
57 #define xmalloc(S) malloc (S)
58 #else
59 #include "config.h"
60 #include "system.h"
61 #endif
63 #include "adaint.h"
64 #include "raise.h"
66 extern void __gnat_raise_program_error (const char *, int);
68 /* Addresses of exception data blocks for predefined exceptions. Tasking_Error
69 is not used in this unit, and the abort signal is only used on IRIX. */
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;
75 /* For the Cert run time we use the regular raise exception routine because
76 Raise_From_Signal_Handler is not available. */
77 #ifdef CERT
78 #define Raise_From_Signal_Handler \
79 __gnat_raise_exception
80 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
81 #else
82 #define Raise_From_Signal_Handler \
83 ada__exceptions__raise_from_signal_handler
84 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
85 #endif
87 /* Global values computed by the binder. */
88 int __gl_main_priority = -1;
89 int __gl_time_slice_val = -1;
90 char __gl_wc_encoding = 'n';
91 char __gl_locking_policy = ' ';
92 char __gl_queuing_policy = ' ';
93 char __gl_task_dispatching_policy = ' ';
94 char *__gl_priority_specific_dispatching = 0;
95 int __gl_num_specific_dispatching = 0;
96 char *__gl_interrupt_states = 0;
97 int __gl_num_interrupt_states = 0;
98 int __gl_unreserve_all_interrupts = 0;
99 int __gl_exception_tracebacks = 0;
100 int __gl_zero_cost_exceptions = 0;
101 int __gl_detect_blocking = 0;
102 int __gl_default_stack_size = -1;
103 int __gl_leap_seconds_support = 0;
104 int __gl_canonical_streams = 0;
106 /* Indication of whether synchronous signal handler has already been
107 installed by a previous call to adainit. */
108 int __gnat_handler_installed = 0;
110 #ifndef IN_RTS
111 int __gnat_inside_elab_final_code = 0;
112 /* ??? This variable is obsolete since 2001-08-29 but is kept to allow
113 bootstrap from old GNAT versions (< 3.15). */
114 #endif
116 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
117 is defined. If this is not set then a void implementation will be defined
118 at the end of this unit. */
119 #undef HAVE_GNAT_INIT_FLOAT
121 /******************************/
122 /* __gnat_get_interrupt_state */
123 /******************************/
125 char __gnat_get_interrupt_state (int);
127 /* This routine is called from the runtime as needed to determine the state
128 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
129 in the current partition. The input argument is the interrupt number,
130 and the result is one of the following:
132 'n' this interrupt not set by any Interrupt_State pragma
133 'u' Interrupt_State pragma set state to User
134 'r' Interrupt_State pragma set state to Runtime
135 's' Interrupt_State pragma set state to System */
137 char
138 __gnat_get_interrupt_state (int intrup)
140 if (intrup >= __gl_num_interrupt_states)
141 return 'n';
142 else
143 return __gl_interrupt_states [intrup];
146 /***********************************/
147 /* __gnat_get_specific_dispatching */
148 /***********************************/
150 char __gnat_get_specific_dispatching (int);
152 /* This routine is called from the runtime as needed to determine the
153 priority specific dispatching policy, as set by a
154 Priority_Specific_Dispatching pragma appearing anywhere in the current
155 partition. The input argument is the priority number, and the result
156 is the upper case first character of the policy name, e.g. 'F' for
157 FIFO_Within_Priorities. A space ' ' is returned if no
158 Priority_Specific_Dispatching pragma is used in the partition. */
160 char
161 __gnat_get_specific_dispatching (int priority)
163 if (__gl_num_specific_dispatching == 0)
164 return ' ';
165 else if (priority >= __gl_num_specific_dispatching)
166 return 'F';
167 else
168 return __gl_priority_specific_dispatching [priority];
171 #ifndef IN_RTS
173 /**********************/
174 /* __gnat_set_globals */
175 /**********************/
177 /* This routine is kept for bootstrapping purposes, since the binder generated
178 file now sets the __gl_* variables directly. */
180 void
181 __gnat_set_globals (void)
185 #endif
187 /***************/
188 /* AIX Section */
189 /***************/
191 #if defined (_AIX)
193 #include <signal.h>
194 #include <sys/time.h>
196 /* Some versions of AIX don't define SA_NODEFER. */
198 #ifndef SA_NODEFER
199 #define SA_NODEFER 0
200 #endif /* SA_NODEFER */
202 /* Versions of AIX before 4.3 don't have nanosleep but provide
203 nsleep instead. */
205 #ifndef _AIXVERSION_430
207 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
210 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
212 return nsleep (Rqtp, Rmtp);
215 #endif /* _AIXVERSION_430 */
217 static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
219 static void
220 __gnat_error_handler (int sig,
221 siginfo_t * si ATTRIBUTE_UNUSED,
222 void * uc ATTRIBUTE_UNUSED)
224 struct Exception_Data *exception;
225 const char *msg;
227 switch (sig)
229 case SIGSEGV:
230 /* FIXME: we need to detect the case of a *real* SIGSEGV. */
231 exception = &storage_error;
232 msg = "stack overflow or erroneous memory access";
233 break;
235 case SIGBUS:
236 exception = &constraint_error;
237 msg = "SIGBUS";
238 break;
240 case SIGFPE:
241 exception = &constraint_error;
242 msg = "SIGFPE";
243 break;
245 default:
246 exception = &program_error;
247 msg = "unhandled signal";
250 Raise_From_Signal_Handler (exception, msg);
253 void
254 __gnat_install_handler (void)
256 struct sigaction act;
258 /* Set up signal handler to map synchronous signals to appropriate
259 exceptions. Make sure that the handler isn't interrupted by another
260 signal that might cause a scheduling event! */
262 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
263 act.sa_sigaction = __gnat_error_handler;
264 sigemptyset (&act.sa_mask);
266 /* Do not install handlers if interrupt state is "System". */
267 if (__gnat_get_interrupt_state (SIGABRT) != 's')
268 sigaction (SIGABRT, &act, NULL);
269 if (__gnat_get_interrupt_state (SIGFPE) != 's')
270 sigaction (SIGFPE, &act, NULL);
271 if (__gnat_get_interrupt_state (SIGILL) != 's')
272 sigaction (SIGILL, &act, NULL);
273 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
274 sigaction (SIGSEGV, &act, NULL);
275 if (__gnat_get_interrupt_state (SIGBUS) != 's')
276 sigaction (SIGBUS, &act, NULL);
278 __gnat_handler_installed = 1;
281 /*****************/
282 /* Tru64 section */
283 /*****************/
285 #elif defined(__alpha__) && defined(__osf__)
287 #include <signal.h>
288 #include <sys/siginfo.h>
290 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
291 extern char *__gnat_get_code_loc (struct sigcontext *);
292 extern void __gnat_set_code_loc (struct sigcontext *, char *);
293 extern size_t __gnat_machine_state_length (void);
295 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
297 void
298 __gnat_adjust_context_for_raise (int signo, void *ucontext)
300 struct sigcontext *sigcontext = (struct sigcontext *) ucontext;
302 /* The unwinder expects the signal context to contain the address of the
303 faulting instruction. For SIGFPE, this depends on the trap shadow
304 situation (see man ieee). We nonetheless always compensate for it,
305 considering that PC designates the instruction following the one that
306 trapped. This is not necessarily true but corresponds to what we have
307 always observed. */
308 if (signo == SIGFPE)
309 sigcontext->sc_pc--;
312 static void
313 __gnat_error_handler
314 (int sig, siginfo_t *sip, struct sigcontext *context)
316 struct Exception_Data *exception;
317 static int recurse = 0;
318 const char *msg;
320 /* Adjusting is required for every fault context, so adjust for this one
321 now, before we possibly trigger a recursive fault below. */
322 __gnat_adjust_context_for_raise (sig, context);
324 /* If this was an explicit signal from a "kill", just resignal it. */
325 if (SI_FROMUSER (sip))
327 signal (sig, SIG_DFL);
328 kill (getpid(), sig);
331 /* Otherwise, treat it as something we handle. */
332 switch (sig)
334 case SIGSEGV:
335 /* If the problem was permissions, this is a constraint error.
336 Likewise if the failing address isn't maximally aligned or if
337 we've recursed.
339 ??? Using a static variable here isn't task-safe, but it's
340 much too hard to do anything else and we're just determining
341 which exception to raise. */
342 if (sip->si_code == SEGV_ACCERR
343 || (((long) sip->si_addr) & 3) != 0
344 || recurse)
346 exception = &constraint_error;
347 msg = "SIGSEGV";
349 else
351 /* See if the page before the faulting page is accessible. Do that
352 by trying to access it. We'd like to simply try to access
353 4096 + the faulting address, but it's not guaranteed to be
354 the actual address, just to be on the same page. */
355 recurse++;
356 ((volatile char *)
357 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
358 msg = "stack overflow (or erroneous memory access)";
359 exception = &storage_error;
361 break;
363 case SIGBUS:
364 exception = &program_error;
365 msg = "SIGBUS";
366 break;
368 case SIGFPE:
369 exception = &constraint_error;
370 msg = "SIGFPE";
371 break;
373 default:
374 exception = &program_error;
375 msg = "unhandled signal";
378 recurse = 0;
379 Raise_From_Signal_Handler (exception, (const char *) msg);
382 void
383 __gnat_install_handler (void)
385 struct sigaction act;
387 /* Setup signal handler to map synchronous signals to appropriate
388 exceptions. Make sure that the handler isn't interrupted by another
389 signal that might cause a scheduling event! */
391 act.sa_handler = (void (*) (int)) __gnat_error_handler;
392 act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
393 sigemptyset (&act.sa_mask);
395 /* Do not install handlers if interrupt state is "System". */
396 if (__gnat_get_interrupt_state (SIGABRT) != 's')
397 sigaction (SIGABRT, &act, NULL);
398 if (__gnat_get_interrupt_state (SIGFPE) != 's')
399 sigaction (SIGFPE, &act, NULL);
400 if (__gnat_get_interrupt_state (SIGILL) != 's')
401 sigaction (SIGILL, &act, NULL);
402 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
403 sigaction (SIGSEGV, &act, NULL);
404 if (__gnat_get_interrupt_state (SIGBUS) != 's')
405 sigaction (SIGBUS, &act, NULL);
407 __gnat_handler_installed = 1;
410 /* Routines called by s-mastop-tru64.adb. */
412 #define SC_GP 29
414 char *
415 __gnat_get_code_loc (struct sigcontext *context)
417 return (char *) context->sc_pc;
420 void
421 __gnat_set_code_loc (struct sigcontext *context, char *pc)
423 context->sc_pc = (long) pc;
426 size_t
427 __gnat_machine_state_length (void)
429 return sizeof (struct sigcontext);
432 /*****************/
433 /* HP-UX section */
434 /*****************/
436 #elif defined (__hpux__)
438 #include <signal.h>
439 #include <sys/ucontext.h>
441 static void
442 __gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext);
444 static void
445 __gnat_error_handler
446 (int sig,
447 siginfo_t *siginfo ATTRIBUTE_UNUSED,
448 void *ucontext ATTRIBUTE_UNUSED)
450 struct Exception_Data *exception;
451 const char *msg;
453 switch (sig)
455 case SIGSEGV:
456 /* FIXME: we need to detect the case of a *real* SIGSEGV. */
457 exception = &storage_error;
458 msg = "stack overflow or erroneous memory access";
459 break;
461 case SIGBUS:
462 exception = &constraint_error;
463 msg = "SIGBUS";
464 break;
466 case SIGFPE:
467 exception = &constraint_error;
468 msg = "SIGFPE";
469 break;
471 default:
472 exception = &program_error;
473 msg = "unhandled signal";
476 Raise_From_Signal_Handler (exception, msg);
479 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
480 #if defined (__hppa__)
481 char __gnat_alternate_stack[16 * 1024]; /* 2 * SIGSTKSZ */
482 #else
483 char __gnat_alternate_stack[128 * 1024]; /* MINSIGSTKSZ */
484 #endif
486 void
487 __gnat_install_handler (void)
489 struct sigaction act;
491 /* Set up signal handler to map synchronous signals to appropriate
492 exceptions. Make sure that the handler isn't interrupted by another
493 signal that might cause a scheduling event! Also setup an alternate
494 stack region for the handler execution so that stack overflows can be
495 handled properly, avoiding a SEGV generation from stack usage by the
496 handler itself. */
498 stack_t stack;
499 stack.ss_sp = __gnat_alternate_stack;
500 stack.ss_size = sizeof (__gnat_alternate_stack);
501 stack.ss_flags = 0;
502 sigaltstack (&stack, NULL);
504 act.sa_sigaction = __gnat_error_handler;
505 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
506 sigemptyset (&act.sa_mask);
508 /* Do not install handlers if interrupt state is "System". */
509 if (__gnat_get_interrupt_state (SIGABRT) != 's')
510 sigaction (SIGABRT, &act, NULL);
511 if (__gnat_get_interrupt_state (SIGFPE) != 's')
512 sigaction (SIGFPE, &act, NULL);
513 if (__gnat_get_interrupt_state (SIGILL) != 's')
514 sigaction (SIGILL, &act, NULL);
515 if (__gnat_get_interrupt_state (SIGBUS) != 's')
516 sigaction (SIGBUS, &act, NULL);
517 act.sa_flags |= SA_ONSTACK;
518 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
519 sigaction (SIGSEGV, &act, NULL);
521 __gnat_handler_installed = 1;
524 /*********************/
525 /* GNU/Linux Section */
526 /*********************/
528 #elif defined (linux)
530 #include <signal.h>
532 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
533 #include <sys/ucontext.h>
535 /* GNU/Linux, which uses glibc, does not define NULL in included
536 header files. */
538 #if !defined (NULL)
539 #define NULL ((void *) 0)
540 #endif
542 #if defined (MaRTE)
544 /* MaRTE OS provides its own version of sigaction, sigfillset, and
545 sigemptyset (overriding these symbol names). We want to make sure that
546 the versions provided by the underlying C library are used here (these
547 versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
548 and fake_linux_sigemptyset, respectively). The MaRTE library will not
549 always be present (it will not be linked if no tasking constructs are
550 used), so we use the weak symbol mechanism to point always to the symbols
551 defined within the C library. */
553 #pragma weak linux_sigaction
554 int linux_sigaction (int signum, const struct sigaction *act,
555 struct sigaction *oldact) {
556 return sigaction (signum, act, oldact);
558 #define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
560 #pragma weak fake_linux_sigfillset
561 void fake_linux_sigfillset (sigset_t *set) {
562 sigfillset (set);
564 #define sigfillset(set) fake_linux_sigfillset (set)
566 #pragma weak fake_linux_sigemptyset
567 void fake_linux_sigemptyset (sigset_t *set) {
568 sigemptyset (set);
570 #define sigemptyset(set) fake_linux_sigemptyset (set)
572 #endif
574 static void __gnat_error_handler (int, siginfo_t *siginfo, void *ucontext);
576 #if defined (i386) || defined (__x86_64__) || defined (__ia64__)
578 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
580 void
581 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
583 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
585 /* On the i386 and x86-64 architectures, stack checking is performed by
586 means of probes with moving stack pointer, that is to say the probed
587 address is always the value of the stack pointer. Upon hitting the
588 guard page, the stack pointer therefore points to an inaccessible
589 address and an alternate signal stack is needed to run the handler.
590 But there is an additional twist: on these architectures, the EH
591 return code writes the address of the handler at the target CFA's
592 value on the stack before doing the jump. As a consequence, if
593 there is an active handler in the frame whose stack has overflowed,
594 the stack pointer must nevertheless point to an accessible address
595 by the time the EH return is executed.
597 We therefore adjust the saved value of the stack pointer by the size
598 of one page + a small dope of 4 words, in order to make sure that it
599 points to an accessible address in case it's used as the target CFA.
600 The stack checking code guarantees that this address is unused by the
601 time this happens. */
603 #if defined (i386)
604 unsigned long *pc = (unsigned long *)mcontext->gregs[REG_EIP];
605 /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode. */
606 if (signo == SIGSEGV && pc && *pc == 0x00240c83)
607 mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
608 #elif defined (__x86_64__)
609 unsigned long *pc = (unsigned long *)mcontext->gregs[REG_RIP];
610 /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode. */
611 if (signo == SIGSEGV && pc && (*pc & 0xffffffffff) == 0x00240c8348)
612 mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
613 #elif defined (__ia64__)
614 /* ??? The IA-64 unwinder doesn't compensate for signals. */
615 mcontext->sc_ip++;
616 #endif
619 #endif
621 static void
622 __gnat_error_handler (int sig,
623 siginfo_t *siginfo ATTRIBUTE_UNUSED,
624 void *ucontext)
626 struct Exception_Data *exception;
627 const char *msg;
628 static int recurse = 0;
630 switch (sig)
632 case SIGSEGV:
633 /* If the problem was permissions, this is a constraint error.
634 Likewise if the failing address isn't maximally aligned or if
635 we've recursed.
637 ??? Using a static variable here isn't task-safe, but it's
638 much too hard to do anything else and we're just determining
639 which exception to raise. */
640 if (recurse)
642 exception = &constraint_error;
643 msg = "SIGSEGV";
645 else
647 /* Here we would like a discrimination test to see whether the
648 page before the faulting address is accessible. Unfortunately
649 Linux seems to have no way of giving us the faulting address.
651 In versions of a-init.c before 1.95, we had a test of the page
652 before the stack pointer using:
654 recurse++;
655 ((volatile char *)
656 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
658 but that's wrong, since it tests the stack pointer location, and
659 the current stack probe code does not move the stack pointer
660 until all probes succeed.
662 For now we simply do not attempt any discrimination at all. Note
663 that this is quite acceptable, since a "real" SIGSEGV can only
664 occur as the result of an erroneous program. */
666 msg = "stack overflow (or erroneous memory access)";
667 exception = &storage_error;
669 break;
671 case SIGBUS:
672 exception = &constraint_error;
673 msg = "SIGBUS";
674 break;
676 case SIGFPE:
677 exception = &constraint_error;
678 msg = "SIGFPE";
679 break;
681 default:
682 exception = &program_error;
683 msg = "unhandled signal";
685 recurse = 0;
687 /* We adjust the interrupted context here (and not in the fallback
688 unwinding routine) because recent versions of the Native POSIX
689 Thread Library (NPTL) are compiled with unwind information, so
690 the fallback routine is never executed for signal frames. */
691 __gnat_adjust_context_for_raise (sig, ucontext);
693 Raise_From_Signal_Handler (exception, msg);
696 #if defined (i386) || defined (__x86_64__)
697 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
698 char __gnat_alternate_stack[16 * 1024]; /* 2 * SIGSTKSZ */
699 #endif
701 #ifdef __XENO__
702 #include <sys/mman.h>
703 #include <native/task.h>
705 RT_TASK main_task;
706 #endif
708 void
709 __gnat_install_handler (void)
711 struct sigaction act;
713 #ifdef __XENO__
714 int prio;
716 if (__gl_main_priority == -1)
717 prio = 49;
718 else
719 prio = __gl_main_priority;
721 /* Avoid memory swapping for this program */
723 mlockall (MCL_CURRENT|MCL_FUTURE);
725 /* Turn the current Linux task into a native Xenomai task */
727 rt_task_shadow(&main_task, "environment_task", prio, T_FPU);
728 #endif
730 /* Set up signal handler to map synchronous signals to appropriate
731 exceptions. Make sure that the handler isn't interrupted by another
732 signal that might cause a scheduling event! Also setup an alternate
733 stack region for the handler execution so that stack overflows can be
734 handled properly, avoiding a SEGV generation from stack usage by the
735 handler itself. */
737 #if defined (i386) || defined (__x86_64__)
738 stack_t stack;
739 stack.ss_sp = __gnat_alternate_stack;
740 stack.ss_size = sizeof (__gnat_alternate_stack);
741 stack.ss_flags = 0;
742 sigaltstack (&stack, NULL);
743 #endif
745 act.sa_sigaction = __gnat_error_handler;
746 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
747 sigemptyset (&act.sa_mask);
749 /* Do not install handlers if interrupt state is "System". */
750 if (__gnat_get_interrupt_state (SIGABRT) != 's')
751 sigaction (SIGABRT, &act, NULL);
752 if (__gnat_get_interrupt_state (SIGFPE) != 's')
753 sigaction (SIGFPE, &act, NULL);
754 if (__gnat_get_interrupt_state (SIGILL) != 's')
755 sigaction (SIGILL, &act, NULL);
756 if (__gnat_get_interrupt_state (SIGBUS) != 's')
757 sigaction (SIGBUS, &act, NULL);
758 #if defined (i386) || defined (__x86_64__)
759 act.sa_flags |= SA_ONSTACK;
760 #endif
761 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
762 sigaction (SIGSEGV, &act, NULL);
764 __gnat_handler_installed = 1;
767 /****************/
768 /* IRIX Section */
769 /****************/
771 #elif defined (sgi)
773 #include <signal.h>
774 #include <siginfo.h>
776 #ifndef NULL
777 #define NULL 0
778 #endif
780 #define SIGADAABORT 48
781 #define SIGNAL_STACK_SIZE 4096
782 #define SIGNAL_STACK_ALIGNMENT 64
784 #define Check_Abort_Status \
785 system__soft_links__check_abort_status
786 extern int (*Check_Abort_Status) (void);
788 extern struct Exception_Data _abort_signal;
790 static void __gnat_error_handler (int, int, sigcontext_t *);
792 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
793 connecting that handler, with the effects described in the sigaction
794 man page:
796 SA_SIGINFO [...]
797 If cleared and the signal is caught, the first argument is
798 also the signal number but the second argument is the signal
799 code identifying the cause of the signal. The third argument
800 points to a sigcontext_t structure containing the receiving
801 process's context when the signal was delivered. */
803 static void
804 __gnat_error_handler (int sig, int code, sigcontext_t *sc ATTRIBUTE_UNUSED)
806 struct Exception_Data *exception;
807 const char *msg;
809 switch (sig)
811 case SIGSEGV:
812 if (code == EFAULT)
814 exception = &program_error;
815 msg = "SIGSEGV: (Invalid virtual address)";
817 else if (code == ENXIO)
819 exception = &program_error;
820 msg = "SIGSEGV: (Read beyond mapped object)";
822 else if (code == ENOSPC)
824 exception = &program_error; /* ??? storage_error ??? */
825 msg = "SIGSEGV: (Autogrow for file failed)";
827 else if (code == EACCES || code == EEXIST)
829 /* ??? We handle stack overflows here, some of which do trigger
830 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
831 the documented valid codes for SEGV in the signal(5) man
832 page. */
834 /* ??? Re-add smarts to further verify that we launched
835 the stack into a guard page, not an attempt to
836 write to .text or something. */
837 exception = &storage_error;
838 msg = "SIGSEGV: (stack overflow or erroneous memory access)";
840 else
842 /* Just in case the OS guys did it to us again. Sometimes
843 they fail to document all of the valid codes that are
844 passed to signal handlers, just in case someone depends
845 on knowing all the codes. */
846 exception = &program_error;
847 msg = "SIGSEGV: (Undocumented reason)";
849 break;
851 case SIGBUS:
852 /* Map all bus errors to Program_Error. */
853 exception = &program_error;
854 msg = "SIGBUS";
855 break;
857 case SIGFPE:
858 /* Map all fpe errors to Constraint_Error. */
859 exception = &constraint_error;
860 msg = "SIGFPE";
861 break;
863 case SIGADAABORT:
864 if ((*Check_Abort_Status) ())
866 exception = &_abort_signal;
867 msg = "";
869 else
870 return;
872 break;
874 default:
875 /* Everything else is a Program_Error. */
876 exception = &program_error;
877 msg = "unhandled signal";
880 Raise_From_Signal_Handler (exception, msg);
883 void
884 __gnat_install_handler (void)
886 struct sigaction act;
888 /* Setup signal handler to map synchronous signals to appropriate
889 exceptions. Make sure that the handler isn't interrupted by another
890 signal that might cause a scheduling event! */
892 act.sa_handler = __gnat_error_handler;
893 act.sa_flags = SA_NODEFER + SA_RESTART;
894 sigfillset (&act.sa_mask);
895 sigemptyset (&act.sa_mask);
897 /* Do not install handlers if interrupt state is "System". */
898 if (__gnat_get_interrupt_state (SIGABRT) != 's')
899 sigaction (SIGABRT, &act, NULL);
900 if (__gnat_get_interrupt_state (SIGFPE) != 's')
901 sigaction (SIGFPE, &act, NULL);
902 if (__gnat_get_interrupt_state (SIGILL) != 's')
903 sigaction (SIGILL, &act, NULL);
904 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
905 sigaction (SIGSEGV, &act, NULL);
906 if (__gnat_get_interrupt_state (SIGBUS) != 's')
907 sigaction (SIGBUS, &act, NULL);
908 if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
909 sigaction (SIGADAABORT, &act, NULL);
911 __gnat_handler_installed = 1;
914 /*******************/
915 /* LynxOS Section */
916 /*******************/
918 #elif defined (__Lynx__)
920 #include <signal.h>
921 #include <unistd.h>
923 static void
924 __gnat_error_handler (int sig)
926 struct Exception_Data *exception;
927 const char *msg;
929 switch(sig)
931 case SIGFPE:
932 exception = &constraint_error;
933 msg = "SIGFPE";
934 break;
935 case SIGILL:
936 exception = &constraint_error;
937 msg = "SIGILL";
938 break;
939 case SIGSEGV:
940 exception = &storage_error;
941 msg = "stack overflow or erroneous memory access";
942 break;
943 case SIGBUS:
944 exception = &constraint_error;
945 msg = "SIGBUS";
946 break;
947 default:
948 exception = &program_error;
949 msg = "unhandled signal";
952 Raise_From_Signal_Handler(exception, msg);
955 void
956 __gnat_install_handler(void)
958 struct sigaction act;
960 act.sa_handler = __gnat_error_handler;
961 act.sa_flags = 0x0;
962 sigemptyset (&act.sa_mask);
964 /* Do not install handlers if interrupt state is "System". */
965 if (__gnat_get_interrupt_state (SIGFPE) != 's')
966 sigaction (SIGFPE, &act, NULL);
967 if (__gnat_get_interrupt_state (SIGILL) != 's')
968 sigaction (SIGILL, &act, NULL);
969 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
970 sigaction (SIGSEGV, &act, NULL);
971 if (__gnat_get_interrupt_state (SIGBUS) != 's')
972 sigaction (SIGBUS, &act, NULL);
974 __gnat_handler_installed = 1;
977 /*******************/
978 /* Solaris Section */
979 /*******************/
981 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
983 #include <signal.h>
984 #include <siginfo.h>
985 #include <sys/ucontext.h>
986 #include <sys/regset.h>
988 /* The code below is common to SPARC and x86. Beware of the delay slot
989 differences for signal context adjustments. */
991 #if defined (__sparc)
992 #define RETURN_ADDR_OFFSET 8
993 #else
994 #define RETURN_ADDR_OFFSET 0
995 #endif
997 /* Likewise regarding how the "instruction pointer" register slot can
998 be identified in signal machine contexts. We have either "REG_PC"
999 or "PC" at hand, depending on the target CPU and Solaris version. */
1001 #if !defined (REG_PC)
1002 #define REG_PC PC
1003 #endif
1005 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1007 static void
1008 __gnat_error_handler (int sig, siginfo_t *sip, ucontext_t *cx ATTRIBUTE_UNUSED)
1010 struct Exception_Data *exception;
1011 static int recurse = 0;
1012 const char *msg;
1014 /* If this was an explicit signal from a "kill", just resignal it. */
1015 if (SI_FROMUSER (sip))
1017 signal (sig, SIG_DFL);
1018 kill (getpid(), sig);
1021 /* Otherwise, treat it as something we handle. */
1022 switch (sig)
1024 case SIGSEGV:
1025 /* If the problem was permissions, this is a constraint error.
1026 Likewise if the failing address isn't maximally aligned or if
1027 we've recursed.
1029 ??? Using a static variable here isn't task-safe, but it's
1030 much too hard to do anything else and we're just determining
1031 which exception to raise. */
1032 if (sip->si_code == SEGV_ACCERR
1033 || (((long) sip->si_addr) & 3) != 0
1034 || recurse)
1036 exception = &constraint_error;
1037 msg = "SIGSEGV";
1039 else
1041 /* See if the page before the faulting page is accessible. Do that
1042 by trying to access it. We'd like to simply try to access
1043 4096 + the faulting address, but it's not guaranteed to be
1044 the actual address, just to be on the same page. */
1045 recurse++;
1046 ((volatile char *)
1047 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1048 exception = &storage_error;
1049 msg = "stack overflow (or erroneous memory access)";
1051 break;
1053 case SIGBUS:
1054 exception = &program_error;
1055 msg = "SIGBUS";
1056 break;
1058 case SIGFPE:
1059 exception = &constraint_error;
1060 msg = "SIGFPE";
1061 break;
1063 default:
1064 exception = &program_error;
1065 msg = "unhandled signal";
1068 recurse = 0;
1070 Raise_From_Signal_Handler (exception, msg);
1073 void
1074 __gnat_install_handler (void)
1076 struct sigaction act;
1078 /* Set up signal handler to map synchronous signals to appropriate
1079 exceptions. Make sure that the handler isn't interrupted by another
1080 signal that might cause a scheduling event! */
1082 act.sa_handler = __gnat_error_handler;
1083 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1084 sigemptyset (&act.sa_mask);
1086 /* Do not install handlers if interrupt state is "System". */
1087 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1088 sigaction (SIGABRT, &act, NULL);
1089 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1090 sigaction (SIGFPE, &act, NULL);
1091 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1092 sigaction (SIGSEGV, &act, NULL);
1093 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1094 sigaction (SIGBUS, &act, NULL);
1096 __gnat_handler_installed = 1;
1099 /***************/
1100 /* VMS Section */
1101 /***************/
1103 #elif defined (VMS)
1105 /* Routine called from binder to override default feature values. */
1106 void __gnat_set_features ();
1107 int __gnat_features_set = 0;
1109 long __gnat_error_handler (int *, void *);
1111 #ifdef __IA64
1112 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1113 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1114 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1115 #else
1116 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1117 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1118 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1119 #endif
1121 #if defined (IN_RTS) && !defined (__IA64)
1123 /* The prehandler actually gets control first on a condition. It swaps the
1124 stack pointer and calls the handler (__gnat_error_handler). */
1125 extern long __gnat_error_prehandler (void);
1127 extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
1128 #endif
1130 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1131 Most of these are also defined in the header file ssdef.h which has not
1132 yet been converted to be recognized by GNU C. */
1134 /* Defining these as macros, as opposed to external addresses, allows
1135 them to be used in a case statement below. */
1136 #define SS$_ACCVIO 12
1137 #define SS$_HPARITH 1284
1138 #define SS$_STKOVF 1364
1139 #define SS$_RESIGNAL 2328
1141 /* These codes are in standard message libraries. */
1142 extern int C$_SIGKILL;
1143 extern int CMA$_EXIT_THREAD;
1144 extern int SS$_DEBUG;
1145 extern int SS$_INTDIV;
1146 extern int LIB$_KEYNOTFOU;
1147 extern int LIB$_ACTIMAGE;
1148 extern int MTH$_FLOOVEMAT; /* Some ACVC_21 CXA tests */
1150 /* These codes are non standard, which is to say the author is
1151 not sure if they are defined in the standard message libraries
1152 so keep them as macros for now. */
1153 #define RDB$_STREAM_EOF 20480426
1154 #define FDL$_UNPRIKW 11829410
1156 struct cond_except {
1157 const int *cond;
1158 const struct Exception_Data *except;
1161 struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1163 /* Conditions that don't have an Ada exception counterpart must raise
1164 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1165 referenced by user programs, not the compiler or tools. Hence the
1166 #ifdef IN_RTS. */
1168 #ifdef IN_RTS
1170 #define Status_Error ada__io_exceptions__status_error
1171 extern struct Exception_Data Status_Error;
1173 #define Mode_Error ada__io_exceptions__mode_error
1174 extern struct Exception_Data Mode_Error;
1176 #define Name_Error ada__io_exceptions__name_error
1177 extern struct Exception_Data Name_Error;
1179 #define Use_Error ada__io_exceptions__use_error
1180 extern struct Exception_Data Use_Error;
1182 #define Device_Error ada__io_exceptions__device_error
1183 extern struct Exception_Data Device_Error;
1185 #define End_Error ada__io_exceptions__end_error
1186 extern struct Exception_Data End_Error;
1188 #define Data_Error ada__io_exceptions__data_error
1189 extern struct Exception_Data Data_Error;
1191 #define Layout_Error ada__io_exceptions__layout_error
1192 extern struct Exception_Data Layout_Error;
1194 #define Non_Ada_Error system__aux_dec__non_ada_error
1195 extern struct Exception_Data Non_Ada_Error;
1197 #define Coded_Exception system__vms_exception_table__coded_exception
1198 extern struct Exception_Data *Coded_Exception (Exception_Code);
1200 #define Base_Code_In system__vms_exception_table__base_code_in
1201 extern Exception_Code Base_Code_In (Exception_Code);
1203 /* DEC Ada exceptions are not defined in a header file, so they
1204 must be declared as external addresses. */
1206 extern int ADA$_PROGRAM_ERROR;
1207 extern int ADA$_LOCK_ERROR;
1208 extern int ADA$_EXISTENCE_ERROR;
1209 extern int ADA$_KEY_ERROR;
1210 extern int ADA$_KEYSIZERR;
1211 extern int ADA$_STAOVF;
1212 extern int ADA$_CONSTRAINT_ERRO;
1213 extern int ADA$_IOSYSFAILED;
1214 extern int ADA$_LAYOUT_ERROR;
1215 extern int ADA$_STORAGE_ERROR;
1216 extern int ADA$_DATA_ERROR;
1217 extern int ADA$_DEVICE_ERROR;
1218 extern int ADA$_END_ERROR;
1219 extern int ADA$_MODE_ERROR;
1220 extern int ADA$_NAME_ERROR;
1221 extern int ADA$_STATUS_ERROR;
1222 extern int ADA$_NOT_OPEN;
1223 extern int ADA$_ALREADY_OPEN;
1224 extern int ADA$_USE_ERROR;
1225 extern int ADA$_UNSUPPORTED;
1226 extern int ADA$_FAC_MODE_MISMAT;
1227 extern int ADA$_ORG_MISMATCH;
1228 extern int ADA$_RFM_MISMATCH;
1229 extern int ADA$_RAT_MISMATCH;
1230 extern int ADA$_MRS_MISMATCH;
1231 extern int ADA$_MRN_MISMATCH;
1232 extern int ADA$_KEY_MISMATCH;
1233 extern int ADA$_MAXLINEXC;
1234 extern int ADA$_LINEXCMRS;
1236 /* DEC Ada specific conditions. */
1237 static const struct cond_except dec_ada_cond_except_table [] = {
1238 {&ADA$_PROGRAM_ERROR, &program_error},
1239 {&ADA$_USE_ERROR, &Use_Error},
1240 {&ADA$_KEYSIZERR, &program_error},
1241 {&ADA$_STAOVF, &storage_error},
1242 {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1243 {&ADA$_IOSYSFAILED, &Device_Error},
1244 {&ADA$_LAYOUT_ERROR, &Layout_Error},
1245 {&ADA$_STORAGE_ERROR, &storage_error},
1246 {&ADA$_DATA_ERROR, &Data_Error},
1247 {&ADA$_DEVICE_ERROR, &Device_Error},
1248 {&ADA$_END_ERROR, &End_Error},
1249 {&ADA$_MODE_ERROR, &Mode_Error},
1250 {&ADA$_NAME_ERROR, &Name_Error},
1251 {&ADA$_STATUS_ERROR, &Status_Error},
1252 {&ADA$_NOT_OPEN, &Use_Error},
1253 {&ADA$_ALREADY_OPEN, &Use_Error},
1254 {&ADA$_USE_ERROR, &Use_Error},
1255 {&ADA$_UNSUPPORTED, &Use_Error},
1256 {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1257 {&ADA$_ORG_MISMATCH, &Use_Error},
1258 {&ADA$_RFM_MISMATCH, &Use_Error},
1259 {&ADA$_RAT_MISMATCH, &Use_Error},
1260 {&ADA$_MRS_MISMATCH, &Use_Error},
1261 {&ADA$_MRN_MISMATCH, &Use_Error},
1262 {&ADA$_KEY_MISMATCH, &Use_Error},
1263 {&ADA$_MAXLINEXC, &constraint_error},
1264 {&ADA$_LINEXCMRS, &constraint_error},
1265 {0, 0}
1268 #if 0
1269 /* Already handled by a pragma Import_Exception
1270 in Aux_IO_Exceptions */
1271 {&ADA$_LOCK_ERROR, &Lock_Error},
1272 {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1273 {&ADA$_KEY_ERROR, &Key_Error},
1274 #endif
1276 #endif /* IN_RTS */
1278 /* Non-DEC Ada specific conditions. We could probably also put
1279 SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
1280 static const struct cond_except cond_except_table [] = {
1281 {&MTH$_FLOOVEMAT, &constraint_error},
1282 {&SS$_INTDIV, &constraint_error},
1283 {0, 0}
1286 /* To deal with VMS conditions and their mapping to Ada exceptions,
1287 the __gnat_error_handler routine below is installed as an exception
1288 vector having precedence over DEC frame handlers. Some conditions
1289 still need to be handled by such handlers, however, in which case
1290 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
1291 instance the use of a third party library compiled with DECAda and
1292 performing its own exception handling internally.
1294 To allow some user-level flexibility, which conditions should be
1295 resignaled is controlled by a predicate function, provided with the
1296 condition value and returning a boolean indication stating whether
1297 this condition should be resignaled or not.
1299 That predicate function is called indirectly, via a function pointer,
1300 by __gnat_error_handler, and changing that pointer is allowed to the
1301 the user code by way of the __gnat_set_resignal_predicate interface.
1303 The user level function may then implement what it likes, including
1304 for instance the maintenance of a dynamic data structure if the set
1305 of to be resignalled conditions has to change over the program's
1306 lifetime.
1308 ??? This is not a perfect solution to deal with the possible
1309 interactions between the GNAT and the DECAda exception handling
1310 models and better (more general) schemes are studied. This is so
1311 just provided as a convenient workaround in the meantime, and
1312 should be use with caution since the implementation has been kept
1313 very simple. */
1315 typedef int
1316 resignal_predicate (int code);
1318 const int *cond_resignal_table [] = {
1319 &C$_SIGKILL,
1320 &CMA$_EXIT_THREAD,
1321 &SS$_DEBUG,
1322 &LIB$_KEYNOTFOU,
1323 &LIB$_ACTIMAGE,
1324 (int *) RDB$_STREAM_EOF,
1325 (int *) FDL$_UNPRIKW,
1329 const int facility_resignal_table [] = {
1330 0x1380000, /* RDB */
1331 0x2220000, /* SQL */
1335 /* Default GNAT predicate for resignaling conditions. */
1337 static int
1338 __gnat_default_resignal_p (int code)
1340 int i, iexcept;
1342 for (i = 0; facility_resignal_table [i]; i++)
1343 if ((code & 0xfff0000) == facility_resignal_table [i])
1344 return 1;
1346 for (i = 0, iexcept = 0;
1347 cond_resignal_table [i] &&
1348 !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1349 i++);
1351 return iexcept;
1354 /* Static pointer to predicate that the __gnat_error_handler exception
1355 vector invokes to determine if it should resignal a condition. */
1357 static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1359 /* User interface to change the predicate pointer to PREDICATE. Reset to
1360 the default if PREDICATE is null. */
1362 void
1363 __gnat_set_resignal_predicate (resignal_predicate * predicate)
1365 if (predicate == 0)
1366 __gnat_resignal_p = __gnat_default_resignal_p;
1367 else
1368 __gnat_resignal_p = predicate;
1371 /* Should match System.Parameters.Default_Exception_Msg_Max_Length. */
1372 #define Default_Exception_Msg_Max_Length 512
1374 /* Action routine for SYS$PUTMSG. There may be multiple
1375 conditions, each with text to be appended to MESSAGE
1376 and separated by line termination. */
1378 static int
1379 copy_msg (msgdesc, message)
1380 struct descriptor_s *msgdesc;
1381 char *message;
1383 int len = strlen (message);
1384 int copy_len;
1386 /* Check for buffer overflow and skip. */
1387 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1389 strcat (message, "\r\n");
1390 len += 2;
1393 /* Check for buffer overflow and truncate if necessary. */
1394 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1395 msgdesc->len :
1396 Default_Exception_Msg_Max_Length - 1 - len);
1397 strncpy (&message [len], msgdesc->adr, copy_len);
1398 message [len + copy_len] = 0;
1400 return 0;
1403 long
1404 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1406 struct Exception_Data *exception = 0;
1407 Exception_Code base_code;
1408 struct descriptor_s gnat_facility = {4,0,"GNAT"};
1409 char message [Default_Exception_Msg_Max_Length];
1411 const char *msg = "";
1413 /* Check for conditions to resignal which aren't effected by pragma
1414 Import_Exception. */
1415 if (__gnat_resignal_p (sigargs [1]))
1416 return SS$_RESIGNAL;
1418 #ifdef IN_RTS
1419 /* See if it's an imported exception. Beware that registered exceptions
1420 are bound to their base code, with the severity bits masked off. */
1421 base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1422 exception = Coded_Exception (base_code);
1424 if (exception)
1426 message [0] = 0;
1428 /* Subtract PC & PSL fields which messes with PUTMSG. */
1429 sigargs [0] -= 2;
1430 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1431 sigargs [0] += 2;
1432 msg = message;
1434 exception->Name_Length = 19;
1435 /* ??? The full name really should be get sys$getmsg returns. */
1436 exception->Full_Name = "IMPORTED_EXCEPTION";
1437 exception->Import_Code = base_code;
1439 #ifdef __IA64
1440 /* Do not adjust the program counter as already points to the next
1441 instruction (just after the call to LIB$STOP). */
1442 Raise_From_Signal_Handler (exception, msg);
1443 #endif
1445 #endif
1447 if (exception == 0)
1448 switch (sigargs[1])
1450 case SS$_ACCVIO:
1451 if (sigargs[3] == 0)
1453 exception = &constraint_error;
1454 msg = "access zero";
1456 else
1458 exception = &storage_error;
1459 msg = "stack overflow (or erroneous memory access)";
1461 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1462 break;
1464 case SS$_STKOVF:
1465 exception = &storage_error;
1466 msg = "stack overflow";
1467 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1468 break;
1470 case SS$_HPARITH:
1471 #ifndef IN_RTS
1472 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1473 #else
1474 exception = &constraint_error;
1475 msg = "arithmetic error";
1476 #ifndef __alpha__
1477 /* No need to adjust pc on Alpha: the pc is already on the instruction
1478 after the trapping one. */
1479 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1480 #endif
1481 #endif
1482 break;
1484 default:
1485 #ifdef IN_RTS
1487 int i;
1489 /* Scan the DEC Ada exception condition table for a match and fetch
1490 the associated GNAT exception pointer. */
1491 for (i = 0;
1492 dec_ada_cond_except_table [i].cond &&
1493 !LIB$MATCH_COND (&sigargs [1],
1494 &dec_ada_cond_except_table [i].cond);
1495 i++);
1496 exception = (struct Exception_Data *)
1497 dec_ada_cond_except_table [i].except;
1499 if (!exception)
1501 /* Scan the VMS standard condition table for a match and fetch
1502 the associated GNAT exception pointer. */
1503 for (i = 0;
1504 cond_except_table [i].cond &&
1505 !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1506 i++);
1507 exception = (struct Exception_Data *)
1508 cond_except_table [i].except;
1510 if (!exception)
1511 /* User programs expect Non_Ada_Error to be raised, reference
1512 DEC Ada test CXCONDHAN. */
1513 exception = &Non_Ada_Error;
1516 #else
1517 exception = &program_error;
1518 #endif
1519 message [0] = 0;
1520 /* Subtract PC & PSL fields which messes with PUTMSG. */
1521 sigargs [0] -= 2;
1522 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1523 sigargs [0] += 2;
1524 msg = message;
1525 break;
1528 Raise_From_Signal_Handler (exception, msg);
1531 long
1532 __gnat_error_handler (int *sigargs, void *mechargs)
1534 return __gnat_handle_vms_condition (sigargs, mechargs);
1537 void
1538 __gnat_install_handler (void)
1540 long prvhnd ATTRIBUTE_UNUSED;
1542 #if !defined (IN_RTS)
1543 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1544 #endif
1546 /* On alpha-vms, we avoid the global vector annoyance thanks to frame based
1547 handlers to turn conditions into exceptions since GCC 3.4. The global
1548 vector is still required for earlier GCC versions. We're resorting to
1549 the __gnat_error_prehandler assembly function in this case. */
1551 #if defined (IN_RTS) && defined (__alpha__)
1552 if ((__GNUC__ * 10 + __GNUC_MINOR__) < 34)
1554 char * c = (char *) xmalloc (2049);
1556 __gnat_error_prehandler_stack = &c[2048];
1557 SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1559 #endif
1561 __gnat_handler_installed = 1;
1564 /* __gnat_adjust_context_for_raise for Alpha - see comments along with the
1565 default version later in this file. */
1567 #if defined (IN_RTS) && defined (__alpha__)
1569 #include <vms/chfctxdef.h>
1570 #include <vms/chfdef.h>
1572 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1574 void
1575 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1577 /* Add one to the address of the instruction signaling the condition,
1578 located in the sigargs array. */
1580 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1581 CHF$SIGNAL_ARRAY * sigargs
1582 = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1584 int vcount = sigargs->chf$is_sig_args;
1585 int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1587 (*pc_slot) ++;
1590 #endif
1592 /* __gnat_adjust_context_for_raise for ia64. */
1594 #if defined (IN_RTS) && defined (__IA64)
1596 #include <vms/chfctxdef.h>
1597 #include <vms/chfdef.h>
1599 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1601 typedef unsigned long long u64;
1603 void
1604 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1606 /* Add one to the address of the instruction signaling the condition,
1607 located in the 64bits sigargs array. */
1609 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1611 CHF64$SIGNAL_ARRAY *chfsig64
1612 = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1614 u64 * post_sigarray
1615 = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1617 u64 * ih_pc_loc = post_sigarray - 2;
1619 (*ih_pc_loc) ++;
1622 #endif
1624 /* Feature logical name and global variable address pair */
1625 struct feature {char *name; int* gl_addr;};
1627 /* Default values for GNAT features set by environment. */
1628 int __gl_no_malloc_64 = 0;
1630 /* Array feature logical names and global variable addresses */
1631 static struct feature features[] = {
1632 {"GNAT$NO_MALLOC_64", &__gl_no_malloc_64},
1633 {0, 0}
1636 void __gnat_set_features ()
1638 struct descriptor_s name_desc, result_desc;
1639 int i, status;
1640 unsigned short rlen;
1642 #define MAXEQUIV 10
1643 char buff [MAXEQUIV];
1645 /* Loop through features array and test name for enable/disable */
1646 for (i=0; features [i].name; i++)
1648 name_desc.len = strlen (features [i].name);
1649 name_desc.mbz = 0;
1650 name_desc.adr = features [i].name;
1652 result_desc.len = MAXEQUIV - 1;
1653 result_desc.mbz = 0;
1654 result_desc.adr = buff;
1656 status = LIB$GET_LOGICAL (&name_desc, &result_desc, &rlen);
1658 if (((status & 1) == 1) && (rlen < MAXEQUIV))
1659 buff [rlen] = 0;
1660 else
1661 strcpy (buff, "");
1663 if (strcmp (buff, "ENABLE") == 0)
1664 *features [i].gl_addr = 1;
1665 else if (strcmp (buff, "DISABLE") == 0)
1666 *features [i].gl_addr = 0;
1669 __gnat_features_set = 1;
1672 /*******************/
1673 /* FreeBSD Section */
1674 /*******************/
1676 #elif defined (__FreeBSD__)
1678 #include <signal.h>
1679 #include <sys/ucontext.h>
1680 #include <unistd.h>
1682 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1684 static void
1685 __gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
1686 ucontext_t *ucontext)
1688 struct Exception_Data *exception;
1689 const char *msg;
1691 switch (sig)
1693 case SIGFPE:
1694 exception = &constraint_error;
1695 msg = "SIGFPE";
1696 break;
1698 case SIGILL:
1699 exception = &constraint_error;
1700 msg = "SIGILL";
1701 break;
1703 case SIGSEGV:
1704 exception = &storage_error;
1705 msg = "stack overflow or erroneous memory access";
1706 break;
1708 case SIGBUS:
1709 exception = &constraint_error;
1710 msg = "SIGBUS";
1711 break;
1713 default:
1714 exception = &program_error;
1715 msg = "unhandled signal";
1718 Raise_From_Signal_Handler (exception, msg);
1721 void
1722 __gnat_install_handler ()
1724 struct sigaction act;
1726 /* Set up signal handler to map synchronous signals to appropriate
1727 exceptions. Make sure that the handler isn't interrupted by another
1728 signal that might cause a scheduling event! */
1730 act.sa_sigaction
1731 = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1732 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1733 (void) sigemptyset (&act.sa_mask);
1735 (void) sigaction (SIGILL, &act, NULL);
1736 (void) sigaction (SIGFPE, &act, NULL);
1737 (void) sigaction (SIGSEGV, &act, NULL);
1738 (void) sigaction (SIGBUS, &act, NULL);
1740 __gnat_handler_installed = 1;
1743 /*******************/
1744 /* VxWorks Section */
1745 /*******************/
1747 #elif defined(__vxworks)
1749 #include <signal.h>
1750 #include <taskLib.h>
1752 #ifndef __RTP__
1753 #include <intLib.h>
1754 #include <iv.h>
1755 #endif
1757 #ifdef VTHREADS
1758 #include "private/vThreadsP.h"
1759 #endif
1761 void __gnat_error_handler (int, void *, struct sigcontext *);
1763 #ifndef __RTP__
1765 /* Directly vectored Interrupt routines are not supported when using RTPs. */
1767 extern int __gnat_inum_to_ivec (int);
1769 /* This is needed by the GNAT run time to handle Vxworks interrupts. */
1771 __gnat_inum_to_ivec (int num)
1773 return INUM_TO_IVEC (num);
1775 #endif
1777 #if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1779 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1780 on Alpha VxWorks and VxWorks 6.x (including RTPs). */
1782 extern long getpid (void);
1784 long
1785 getpid (void)
1787 return taskIdSelf ();
1789 #endif
1791 /* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
1792 handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
1793 doesn't. */
1794 void
1795 __gnat_clear_exception_count (void)
1797 #ifdef VTHREADS
1798 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1800 currentTask->vThreads.excCnt = 0;
1801 #endif
1804 /* Handle different SIGnal to exception mappings in different VxWorks
1805 versions. */
1806 static void
1807 __gnat_map_signal (int sig)
1809 struct Exception_Data *exception;
1810 const char *msg;
1812 switch (sig)
1814 case SIGFPE:
1815 exception = &constraint_error;
1816 msg = "SIGFPE";
1817 break;
1818 #ifdef VTHREADS
1819 case SIGILL:
1820 exception = &constraint_error;
1821 msg = "Floating point exception or SIGILL";
1822 break;
1823 case SIGSEGV:
1824 exception = &storage_error;
1825 msg = "SIGSEGV";
1826 break;
1827 case SIGBUS:
1828 exception = &storage_error;
1829 msg = "SIGBUS: possible stack overflow";
1830 break;
1831 #elif (_WRS_VXWORKS_MAJOR == 6)
1832 case SIGILL:
1833 exception = &constraint_error;
1834 msg = "SIGILL";
1835 break;
1836 #ifdef __RTP__
1837 /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
1838 since stack checking uses the probing mechanism. */
1839 case SIGSEGV:
1840 exception = &storage_error;
1841 msg = "SIGSEGV: possible stack overflow";
1842 break;
1843 case SIGBUS:
1844 exception = &program_error;
1845 msg = "SIGBUS";
1846 break;
1847 #else
1848 /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
1849 case SIGSEGV:
1850 exception = &storage_error;
1851 msg = "SIGSEGV";
1852 break;
1853 case SIGBUS:
1854 exception = &storage_error;
1855 msg = "SIGBUS: possible stack overflow";
1856 break;
1857 #endif
1858 #else
1859 /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
1860 since stack checking uses the stack limit mechanism. */
1861 case SIGILL:
1862 exception = &storage_error;
1863 msg = "SIGILL: possible stack overflow";
1864 break;
1865 case SIGSEGV:
1866 exception = &storage_error;
1867 msg = "SIGSEGV";
1868 break;
1869 case SIGBUS:
1870 exception = &program_error;
1871 msg = "SIGBUS";
1872 break;
1873 #endif
1874 default:
1875 exception = &program_error;
1876 msg = "unhandled signal";
1879 __gnat_clear_exception_count ();
1880 Raise_From_Signal_Handler (exception, msg);
1883 /* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
1884 propagation after the required low level adjustments. */
1886 void
1887 __gnat_error_handler (int sig, void * si ATTRIBUTE_UNUSED,
1888 struct sigcontext * sc)
1890 sigset_t mask;
1892 /* VxWorks will always mask out the signal during the signal handler and
1893 will reenable it on a longjmp. GNAT does not generate a longjmp to
1894 return from a signal handler so the signal will still be masked unless
1895 we unmask it. */
1896 sigprocmask (SIG_SETMASK, NULL, &mask);
1897 sigdelset (&mask, sig);
1898 sigprocmask (SIG_SETMASK, &mask, NULL);
1900 __gnat_map_signal (sig);
1903 void
1904 __gnat_install_handler (void)
1906 struct sigaction act;
1908 /* Setup signal handler to map synchronous signals to appropriate
1909 exceptions. Make sure that the handler isn't interrupted by another
1910 signal that might cause a scheduling event! */
1912 act.sa_handler = __gnat_error_handler;
1913 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1914 sigemptyset (&act.sa_mask);
1916 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1917 applies to vectored hardware interrupts, not signals. */
1918 sigaction (SIGFPE, &act, NULL);
1919 sigaction (SIGILL, &act, NULL);
1920 sigaction (SIGSEGV, &act, NULL);
1921 sigaction (SIGBUS, &act, NULL);
1923 __gnat_handler_installed = 1;
1926 #define HAVE_GNAT_INIT_FLOAT
1928 void
1929 __gnat_init_float (void)
1931 /* Disable overflow/underflow exceptions on the PPC processor, needed
1932 to get correct Ada semantics. Note that for AE653 vThreads, the HW
1933 overflow settings are an OS configuration issue. The instructions
1934 below have no effect. */
1935 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1936 #if defined (__SPE__)
1938 const unsigned long spefscr_mask = 0xfffffff3;
1939 unsigned long spefscr;
1940 asm ("mfspr %0, 512" : "=r" (spefscr));
1941 spefscr = spefscr & spefscr_mask;
1942 asm ("mtspr 512, %0\n\tisync" : : "r" (spefscr));
1944 #else
1945 asm ("mtfsb0 25");
1946 asm ("mtfsb0 26");
1947 #endif
1948 #endif
1950 #if (defined (__i386__) || defined (i386)) && !defined (VTHREADS)
1951 /* This is used to properly initialize the FPU on an x86 for each
1952 process thread. */
1953 asm ("finit");
1954 #endif
1956 /* Similarly for SPARC64. Achieved by masking bits in the Trap Enable Mask
1957 field of the Floating-point Status Register (see the SPARC Architecture
1958 Manual Version 9, p 48). */
1959 #if defined (sparc64)
1961 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1962 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1963 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1964 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1965 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1967 unsigned int fsr;
1969 __asm__("st %%fsr, %0" : "=m" (fsr));
1970 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1971 __asm__("ld %0, %%fsr" : : "m" (fsr));
1973 #endif
1976 /* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
1977 (if not null) when a new task is created. It is initialized by
1978 System.Stack_Checking.Operations.Initialize_Stack_Limit.
1979 The use of a hook avoids to drag stack checking subprograms if stack
1980 checking is not used. */
1981 void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
1983 /******************/
1984 /* NetBSD Section */
1985 /******************/
1987 #elif defined(__NetBSD__)
1989 #include <signal.h>
1990 #include <unistd.h>
1992 static void
1993 __gnat_error_handler (int sig)
1995 struct Exception_Data *exception;
1996 const char *msg;
1998 switch(sig)
2000 case SIGFPE:
2001 exception = &constraint_error;
2002 msg = "SIGFPE";
2003 break;
2004 case SIGILL:
2005 exception = &constraint_error;
2006 msg = "SIGILL";
2007 break;
2008 case SIGSEGV:
2009 exception = &storage_error;
2010 msg = "stack overflow or erroneous memory access";
2011 break;
2012 case SIGBUS:
2013 exception = &constraint_error;
2014 msg = "SIGBUS";
2015 break;
2016 default:
2017 exception = &program_error;
2018 msg = "unhandled signal";
2021 Raise_From_Signal_Handler(exception, msg);
2024 void
2025 __gnat_install_handler(void)
2027 struct sigaction act;
2029 act.sa_handler = __gnat_error_handler;
2030 act.sa_flags = SA_NODEFER | SA_RESTART;
2031 sigemptyset (&act.sa_mask);
2033 /* Do not install handlers if interrupt state is "System". */
2034 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2035 sigaction (SIGFPE, &act, NULL);
2036 if (__gnat_get_interrupt_state (SIGILL) != 's')
2037 sigaction (SIGILL, &act, NULL);
2038 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2039 sigaction (SIGSEGV, &act, NULL);
2040 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2041 sigaction (SIGBUS, &act, NULL);
2043 __gnat_handler_installed = 1;
2046 /*******************/
2047 /* OpenBSD Section */
2048 /*******************/
2050 #elif defined(__OpenBSD__)
2052 #include <signal.h>
2053 #include <unistd.h>
2055 static void
2056 __gnat_error_handler (int sig)
2058 struct Exception_Data *exception;
2059 const char *msg;
2061 switch(sig)
2063 case SIGFPE:
2064 exception = &constraint_error;
2065 msg = "SIGFPE";
2066 break;
2067 case SIGILL:
2068 exception = &constraint_error;
2069 msg = "SIGILL";
2070 break;
2071 case SIGSEGV:
2072 exception = &storage_error;
2073 msg = "stack overflow or erroneous memory access";
2074 break;
2075 case SIGBUS:
2076 exception = &constraint_error;
2077 msg = "SIGBUS";
2078 break;
2079 default:
2080 exception = &program_error;
2081 msg = "unhandled signal";
2084 Raise_From_Signal_Handler(exception, msg);
2087 void
2088 __gnat_install_handler(void)
2090 struct sigaction act;
2092 act.sa_handler = __gnat_error_handler;
2093 act.sa_flags = SA_NODEFER | SA_RESTART;
2094 sigemptyset (&act.sa_mask);
2096 /* Do not install handlers if interrupt state is "System" */
2097 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2098 sigaction (SIGFPE, &act, NULL);
2099 if (__gnat_get_interrupt_state (SIGILL) != 's')
2100 sigaction (SIGILL, &act, NULL);
2101 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2102 sigaction (SIGSEGV, &act, NULL);
2103 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2104 sigaction (SIGBUS, &act, NULL);
2106 __gnat_handler_installed = 1;
2109 /******************/
2110 /* Darwin Section */
2111 /******************/
2113 #elif defined(__APPLE__)
2115 #include <signal.h>
2116 #include <sys/syscall.h>
2117 #include <mach/mach_vm.h>
2118 #include <mach/mach_init.h>
2119 #include <mach/vm_statistics.h>
2121 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
2122 char __gnat_alternate_stack[32 * 1024]; /* 1 * MINSIGSTKSZ */
2124 static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
2126 /* Defined in xnu unix_signal.c.
2127 Tell the kernel to re-use alt stack when delivering a signal. */
2128 #define UC_RESET_ALT_STACK 0x80000000
2130 /* Return true if ADDR is within a stack guard area. */
2131 static int
2132 __gnat_is_stack_guard (mach_vm_address_t addr)
2134 kern_return_t kret;
2135 vm_region_submap_info_data_64_t info;
2136 mach_vm_address_t start;
2137 mach_vm_size_t size;
2138 natural_t depth;
2139 mach_msg_type_number_t count;
2141 count = VM_REGION_SUBMAP_INFO_COUNT_64;
2142 start = addr;
2143 size = -1;
2144 depth = 9999;
2145 kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
2146 (vm_region_recurse_info_t) &info, &count);
2147 if (kret == KERN_SUCCESS
2148 && addr >= start && addr < (start + size)
2149 && info.protection == VM_PROT_NONE
2150 && info.user_tag == VM_MEMORY_STACK)
2151 return 1;
2152 return 0;
2155 static void
2156 __gnat_error_handler (int sig, siginfo_t * si, void * uc ATTRIBUTE_UNUSED)
2158 struct Exception_Data *exception;
2159 const char *msg;
2161 switch (sig)
2163 case SIGSEGV:
2164 case SIGBUS:
2165 if (__gnat_is_stack_guard ((unsigned long)si->si_addr))
2167 exception = &storage_error;
2168 msg = "stack overflow";
2170 else
2172 exception = &constraint_error;
2173 msg = "erroneous memory access";
2175 /* Reset the use of alt stack, so that the alt stack will be used
2176 for the next signal delivery.
2177 The stack can't be used in case of stack checking. */
2178 syscall (SYS_sigreturn, NULL, UC_RESET_ALT_STACK);
2179 break;
2181 case SIGFPE:
2182 exception = &constraint_error;
2183 msg = "SIGFPE";
2184 break;
2186 default:
2187 exception = &program_error;
2188 msg = "unhandled signal";
2191 Raise_From_Signal_Handler (exception, msg);
2194 void
2195 __gnat_install_handler (void)
2197 struct sigaction act;
2199 /* Set up signal handler to map synchronous signals to appropriate
2200 exceptions. Make sure that the handler isn't interrupted by another
2201 signal that might cause a scheduling event! Also setup an alternate
2202 stack region for the handler execution so that stack overflows can be
2203 handled properly, avoiding a SEGV generation from stack usage by the
2204 handler itself (and it is required by Darwin). */
2206 stack_t stack;
2207 stack.ss_sp = __gnat_alternate_stack;
2208 stack.ss_size = sizeof (__gnat_alternate_stack);
2209 stack.ss_flags = 0;
2210 sigaltstack (&stack, NULL);
2212 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2213 act.sa_sigaction = __gnat_error_handler;
2214 sigemptyset (&act.sa_mask);
2216 /* Do not install handlers if interrupt state is "System". */
2217 if (__gnat_get_interrupt_state (SIGABRT) != 's')
2218 sigaction (SIGABRT, &act, NULL);
2219 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2220 sigaction (SIGFPE, &act, NULL);
2221 if (__gnat_get_interrupt_state (SIGILL) != 's')
2222 sigaction (SIGILL, &act, NULL);
2224 act.sa_flags |= SA_ONSTACK;
2225 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2226 sigaction (SIGSEGV, &act, NULL);
2227 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2228 sigaction (SIGBUS, &act, NULL);
2230 __gnat_handler_installed = 1;
2233 #else
2235 /* For all other versions of GNAT, the handler does nothing. */
2237 /*******************/
2238 /* Default Section */
2239 /*******************/
2241 void
2242 __gnat_install_handler (void)
2244 __gnat_handler_installed = 1;
2247 #endif
2249 /*********************/
2250 /* __gnat_init_float */
2251 /*********************/
2253 /* This routine is called as each process thread is created, for possible
2254 initialization of the FP processor. This version is used under INTERIX,
2255 WIN32 and could be used under OS/2. */
2257 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
2258 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
2259 || defined (__OpenBSD__)
2261 #define HAVE_GNAT_INIT_FLOAT
2263 void
2264 __gnat_init_float (void)
2266 #if defined (__i386__) || defined (i386) || defined (__x86_64)
2268 /* This is used to properly initialize the FPU on an x86 for each
2269 process thread. */
2271 asm ("finit");
2273 #endif /* Defined __i386__ */
2275 #endif
2277 #ifndef HAVE_GNAT_INIT_FLOAT
2279 /* All targets without a specific __gnat_init_float will use an empty one. */
2280 void
2281 __gnat_init_float (void)
2284 #endif
2286 /***********************************/
2287 /* __gnat_adjust_context_for_raise */
2288 /***********************************/
2290 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2292 /* All targets without a specific version will use an empty one. */
2294 /* Given UCONTEXT a pointer to a context structure received by a signal
2295 handler for SIGNO, perform the necessary adjustments to let the handler
2296 raise an exception. Calls to this routine are not conditioned by the
2297 propagation scheme in use. */
2299 void
2300 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2301 void *ucontext ATTRIBUTE_UNUSED)
2303 /* We used to compensate here for the raised from call vs raised from signal
2304 exception discrepancy with the GCC ZCX scheme, but this now can be dealt
2305 with generically in the unwinder (see GCC PR other/26208). This however
2306 requires the use of the _Unwind_GetIPInfo routine in raise-gcc.c, which
2307 is predicated on the definition of HAVE_GETIPINFO at compile time. Only
2308 the VMS ports still do the compensation described in the few lines below.
2310 *** Call vs signal exception discrepancy with GCC ZCX scheme ***
2312 The GCC unwinder expects to be dealing with call return addresses, since
2313 this is the "nominal" case of what we retrieve while unwinding a regular
2314 call chain.
2316 To evaluate if a handler applies at some point identified by a return
2317 address, the propagation engine needs to determine what region the
2318 corresponding call instruction pertains to. Because the return address
2319 may not be attached to the same region as the call, the unwinder always
2320 subtracts "some" amount from a return address to search the region
2321 tables, amount chosen to ensure that the resulting address is inside the
2322 call instruction.
2324 When we raise an exception from a signal handler, e.g. to transform a
2325 SIGSEGV into Storage_Error, things need to appear as if the signal
2326 handler had been "called" by the instruction which triggered the signal,
2327 so that exception handlers that apply there are considered. What the
2328 unwinder will retrieve as the return address from the signal handler is
2329 what it will find as the faulting instruction address in the signal
2330 context pushed by the kernel. Leaving this address untouched looses, if
2331 the triggering instruction happens to be the very first of a region, as
2332 the later adjustments performed by the unwinder would yield an address
2333 outside that region. We need to compensate for the unwinder adjustments
2334 at some point, and this is what this routine is expected to do.
2336 signo is passed because on some targets for some signals the PC in
2337 context points to the instruction after the faulting one, in which case
2338 the unwinder adjustment is still desired. */
2341 #endif