Skip several gcc.dg/builtin-dynamic-object-size tests on hppa*-*-hpux*
[official-gcc.git] / gcc / ada / init.c
blob53ca1421111e1b95bd7de2fed6be15efb87be305
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * I N I T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 1992-2023, 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 s-init.ads, s-init.adb and the
42 s-init-*.adb variants. All these files implement the required functionality
43 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 #include "version.h" /* for _WRS_VXWORKS_MAJOR */
50 #endif
52 #ifdef __ANDROID__
53 #undef __linux__
54 #endif
56 #ifdef IN_RTS
58 #ifdef STANDALONE
59 #include "runtime.h"
60 #else
61 #include "tconfig.h"
62 #include "tsystem.h"
63 #endif
65 #include <sys/stat.h>
67 /* We don't have libiberty, so use malloc. */
68 #define xmalloc(S) malloc (S)
69 #else
70 #include "config.h"
71 #include "system.h"
72 #endif
74 #include "adaint.h"
75 #include "raise.h"
77 #ifdef __cplusplus
78 extern "C" {
79 #endif
81 extern void __gnat_raise_program_error (const void *, int);
83 /* Addresses of exception data blocks for predefined exceptions. Tasking_Error
84 is not used in this unit, and the abort signal is only used on IRIX.
85 ??? Revisit this part since IRIX is no longer supported. */
86 extern struct Exception_Data constraint_error;
87 extern struct Exception_Data numeric_error;
88 extern struct Exception_Data program_error;
89 extern struct Exception_Data storage_error;
91 /* For the Cert run time we use the regular raise exception routine because
92 __gnat_raise_from_signal_handler is not available. */
93 #ifdef CERT
94 #define Raise_From_Signal_Handler __gnat_raise_exception
95 #else
96 #define Raise_From_Signal_Handler __gnat_raise_from_signal_handler
97 #endif
99 extern void Raise_From_Signal_Handler (struct Exception_Data *, const void *)
100 ATTRIBUTE_NORETURN;
102 /* Global values computed by the binder. Note that these variables are
103 declared here, not in the binder file, to avoid having unresolved
104 references in the shared libgnat. */
105 int __gl_main_priority = -1;
106 int __gl_main_cpu = -1;
107 int __gl_time_slice_val = -1;
108 char __gl_wc_encoding = 'n';
109 char __gl_locking_policy = ' ';
110 char __gl_queuing_policy = ' ';
111 char __gl_task_dispatching_policy = ' ';
112 char *__gl_priority_specific_dispatching = 0;
113 int __gl_num_specific_dispatching = 0;
114 char *__gl_interrupt_states = 0;
115 int __gl_num_interrupt_states = 0;
116 int __gl_unreserve_all_interrupts = 0;
117 int __gl_exception_tracebacks = 0;
118 int __gl_exception_tracebacks_symbolic = 0;
119 int __gl_detect_blocking = 0;
120 int __gl_default_stack_size = -1;
121 int __gl_leap_seconds_support = 0;
122 int __gl_canonical_streams = 0;
123 char *__gl_bind_env_addr = NULL;
124 int __gl_xdr_stream = 0;
126 /* This value is not used anymore, but kept for bootstrapping purpose. */
127 int __gl_zero_cost_exceptions = 0;
129 /* Indication of whether synchronous signal handler has already been
130 installed by a previous call to adainit. */
131 int __gnat_handler_installed = 0;
133 #ifndef IN_RTS
134 int __gnat_inside_elab_final_code = 0;
135 /* ??? This variable is obsolete since 2001-08-29 but is kept to allow
136 bootstrap from old GNAT versions (< 3.15). */
137 #endif
139 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
140 is defined. If this is not set then a void implementation will be defined
141 at the end of this unit. */
142 #undef HAVE_GNAT_INIT_FLOAT
144 /******************************/
145 /* __gnat_get_interrupt_state */
146 /******************************/
148 char __gnat_get_interrupt_state (int);
150 /* This routine is called from the runtime as needed to determine the state
151 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
152 in the current partition. The input argument is the interrupt number,
153 and the result is one of the following:
155 'n' this interrupt not set by any Interrupt_State pragma
156 'u' Interrupt_State pragma set state to User
157 'r' Interrupt_State pragma set state to Runtime
158 's' Interrupt_State pragma set state to System */
160 char
161 __gnat_get_interrupt_state (int intrup)
163 if (intrup >= __gl_num_interrupt_states)
164 return 'n';
165 else
166 return __gl_interrupt_states [intrup];
169 /***********************************/
170 /* __gnat_get_specific_dispatching */
171 /***********************************/
173 char __gnat_get_specific_dispatching (int);
175 /* This routine is called from the runtime as needed to determine the
176 priority specific dispatching policy, as set by a
177 Priority_Specific_Dispatching pragma appearing anywhere in the current
178 partition. The input argument is the priority number, and the result
179 is the upper case first character of the policy name, e.g. 'F' for
180 FIFO_Within_Priorities. A space ' ' is returned if no
181 Priority_Specific_Dispatching pragma is used in the partition. */
183 char
184 __gnat_get_specific_dispatching (int priority)
186 if (__gl_num_specific_dispatching == 0)
187 return ' ';
188 else if (priority >= __gl_num_specific_dispatching)
189 return 'F';
190 else
191 return __gl_priority_specific_dispatching [priority];
194 #ifndef IN_RTS
196 /**********************/
197 /* __gnat_set_globals */
198 /**********************/
200 /* This routine is kept for bootstrapping purposes, since the binder generated
201 file now sets the __gl_* variables directly. */
203 void
204 __gnat_set_globals (void)
208 #endif
210 /***************/
211 /* AIX Section */
212 /***************/
214 #if defined (_AIX)
216 #include <signal.h>
217 #include <sys/time.h>
219 /* Some versions of AIX don't define SA_NODEFER. */
221 #ifndef SA_NODEFER
222 #define SA_NODEFER 0
223 #endif /* SA_NODEFER */
225 /* Versions of AIX before 4.3 don't have nanosleep but provide
226 nsleep instead. */
228 #ifndef _AIXVERSION_430
230 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
233 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
235 return nsleep (Rqtp, Rmtp);
238 #endif /* _AIXVERSION_430 */
240 static void
241 __gnat_error_handler (int sig,
242 siginfo_t *si ATTRIBUTE_UNUSED,
243 void *ucontext ATTRIBUTE_UNUSED)
245 struct Exception_Data *exception;
246 const char *msg;
248 switch (sig)
250 case SIGSEGV:
251 /* ??? we need to detect the case of a *real* SIGSEGV. */
252 exception = &storage_error;
253 msg = "stack overflow or erroneous memory access";
254 break;
256 case SIGBUS:
257 exception = &constraint_error;
258 msg = "SIGBUS";
259 break;
261 case SIGFPE:
262 exception = &constraint_error;
263 msg = "SIGFPE";
264 break;
266 default:
267 exception = &program_error;
268 msg = "unhandled signal";
271 Raise_From_Signal_Handler (exception, msg);
274 void
275 __gnat_install_handler (void)
277 struct sigaction act;
279 /* Set up signal handler to map synchronous signals to appropriate
280 exceptions. Make sure that the handler isn't interrupted by another
281 signal that might cause a scheduling event! */
283 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
284 act.sa_sigaction = __gnat_error_handler;
285 sigemptyset (&act.sa_mask);
287 /* Do not install handlers if interrupt state is "System". */
288 if (__gnat_get_interrupt_state (SIGABRT) != 's')
289 sigaction (SIGABRT, &act, NULL);
290 if (__gnat_get_interrupt_state (SIGFPE) != 's')
291 sigaction (SIGFPE, &act, NULL);
292 if (__gnat_get_interrupt_state (SIGILL) != 's')
293 sigaction (SIGILL, &act, NULL);
294 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
295 sigaction (SIGSEGV, &act, NULL);
296 if (__gnat_get_interrupt_state (SIGBUS) != 's')
297 sigaction (SIGBUS, &act, NULL);
299 __gnat_handler_installed = 1;
302 /*****************/
303 /* HP-UX section */
304 /*****************/
306 #elif defined (__hpux__)
308 #include <signal.h>
309 #include <sys/ucontext.h>
311 #if defined (IN_RTS) && defined (__ia64__)
313 #include <sys/uc_access.h>
315 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
317 void
318 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
320 ucontext_t *uc = (ucontext_t *) ucontext;
321 uint64_t ip;
323 /* Adjust on itanium, as GetIPInfo is not supported. */
324 __uc_get_ip (uc, &ip);
325 __uc_set_ip (uc, ip + 1);
327 #endif /* IN_RTS && __ia64__ */
329 /* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
330 propagation after the required low level adjustments. */
332 static void
333 __gnat_error_handler (int sig, siginfo_t *si ATTRIBUTE_UNUSED, void *ucontext)
335 struct Exception_Data *exception;
336 const char *msg;
338 __gnat_adjust_context_for_raise (sig, ucontext);
340 switch (sig)
342 case SIGSEGV:
343 /* ??? we need to detect the case of a *real* SIGSEGV. */
344 exception = &storage_error;
345 msg = "stack overflow or erroneous memory access";
346 break;
348 case SIGBUS:
349 exception = &constraint_error;
350 msg = "SIGBUS";
351 break;
353 case SIGFPE:
354 exception = &constraint_error;
355 msg = "SIGFPE";
356 break;
358 default:
359 exception = &program_error;
360 msg = "unhandled signal";
363 Raise_From_Signal_Handler (exception, msg);
366 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
367 #if defined (__hppa__)
368 char __gnat_alternate_stack[16 * 1024]; /* 2 * SIGSTKSZ */
369 #else
370 char __gnat_alternate_stack[128 * 1024]; /* MINSIGSTKSZ */
371 #endif
373 void
374 __gnat_install_handler (void)
376 struct sigaction act;
378 /* Set up signal handler to map synchronous signals to appropriate
379 exceptions. Make sure that the handler isn't interrupted by another
380 signal that might cause a scheduling event! Also setup an alternate
381 stack region for the handler execution so that stack overflows can be
382 handled properly, avoiding a SEGV generation from stack usage by the
383 handler itself. */
385 stack_t stack;
386 stack.ss_sp = __gnat_alternate_stack;
387 stack.ss_size = sizeof (__gnat_alternate_stack);
388 stack.ss_flags = 0;
389 sigaltstack (&stack, NULL);
391 act.sa_sigaction = __gnat_error_handler;
392 act.sa_flags = SA_NODEFER | SA_RESTART | 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 (SIGBUS) != 's')
403 sigaction (SIGBUS, &act, NULL);
404 act.sa_flags |= SA_ONSTACK;
405 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
406 sigaction (SIGSEGV, &act, NULL);
408 __gnat_handler_installed = 1;
411 /*********************/
412 /* GNU/Linux Section */
413 /*********************/
415 #elif defined (__linux__)
417 #include <signal.h>
419 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
420 #include <sys/ucontext.h>
422 /* GNU/Linux, which uses glibc, does not define NULL in included
423 header files. */
425 #if !defined (NULL)
426 #define NULL ((void *) 0)
427 #endif
429 #if defined (MaRTE)
431 /* MaRTE OS provides its own version of sigaction, sigfillset, and
432 sigemptyset (overriding these symbol names). We want to make sure that
433 the versions provided by the underlying C library are used here (these
434 versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
435 and fake_linux_sigemptyset, respectively). The MaRTE library will not
436 always be present (it will not be linked if no tasking constructs are
437 used), so we use the weak symbol mechanism to point always to the symbols
438 defined within the C library. */
440 #pragma weak linux_sigaction
441 int linux_sigaction (int signum, const struct sigaction *act,
442 struct sigaction *oldact)
444 return sigaction (signum, act, oldact);
446 #define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
448 #pragma weak fake_linux_sigfillset
449 void fake_linux_sigfillset (sigset_t *set)
451 sigfillset (set);
453 #define sigfillset(set) fake_linux_sigfillset (set)
455 #pragma weak fake_linux_sigemptyset
456 void fake_linux_sigemptyset (sigset_t *set)
458 sigemptyset (set);
460 #define sigemptyset(set) fake_linux_sigemptyset (set)
462 #endif
464 #if defined (__i386__) || defined (__x86_64__) || defined (__ia64__) \
465 || defined (__ARMEL__)
467 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
469 void
470 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
472 #ifndef STANDALONE
473 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
475 /* On the i386 and x86-64 architectures, stack checking is performed by
476 means of probes with moving stack pointer, that is to say the probed
477 address is always the value of the stack pointer. Upon hitting the
478 guard page, the stack pointer therefore points to an inaccessible
479 address and an alternate signal stack is needed to run the handler.
480 But there is an additional twist: on these architectures, the EH
481 return code writes the address of the handler at the target CFA's
482 value on the stack before doing the jump. As a consequence, if
483 there is an active handler in the frame whose stack has overflowed,
484 the stack pointer must nevertheless point to an accessible address
485 by the time the EH return is executed.
487 We therefore adjust the saved value of the stack pointer by the size
488 of one page + a small dope of 4 words, in order to make sure that it
489 points to an accessible address in case it's used as the target CFA.
490 The stack checking code guarantees that this address is unused by the
491 time this happens. */
493 #if defined (__i386__)
494 unsigned long *pc = (unsigned long *)mcontext->gregs[REG_EIP];
495 /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode. */
496 if (signo == SIGSEGV && pc && *pc == 0x00240c83)
497 mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
498 #elif defined (__x86_64__)
499 unsigned long long *pc = (unsigned long long *)mcontext->gregs[REG_RIP];
500 if (signo == SIGSEGV && pc
501 /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode. */
502 && ((*pc & 0xffffffffffLL) == 0x00240c8348LL
503 /* The pattern may also be "orl $0x0,(%esp)" for a probe in
504 x32 mode. */
505 || (*pc & 0xffffffffLL) == 0x00240c83LL))
506 mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
507 #elif defined (__ia64__)
508 /* ??? The IA-64 unwinder doesn't compensate for signals. */
509 mcontext->sc_ip++;
510 #elif defined (__ARMEL__)
511 /* ARM Bump has to be an even number because of odd/even architecture. */
512 mcontext->arm_pc+=2;
513 #ifdef __thumb2__
514 #define CPSR_THUMB_BIT 5
515 /* For thumb, the return address much have the low order bit set, otherwise
516 the unwinder will reset to "arm" mode upon return. As long as the
517 compilation unit containing the landing pad is compiled with the same
518 mode (arm vs thumb) as the signaling compilation unit, this works. */
519 if (mcontext->arm_cpsr & (1<<CPSR_THUMB_BIT))
520 mcontext->arm_pc+=1;
521 #endif
522 #endif
523 #endif
526 #endif
528 static void
529 __gnat_error_handler (int sig, siginfo_t *si ATTRIBUTE_UNUSED, void *ucontext)
531 struct Exception_Data *exception;
532 const char *msg;
534 /* Adjusting is required for every fault context, so adjust for this one
535 now, before we possibly trigger a recursive fault below. */
536 __gnat_adjust_context_for_raise (sig, ucontext);
538 switch (sig)
540 case SIGSEGV:
541 /* Here we would like a discrimination test to see whether the page
542 before the faulting address is accessible. Unfortunately, Linux
543 seems to have no way of giving us the faulting address.
545 In old versions of init.c, we had a test of the page before the
546 stack pointer:
548 ((volatile char *)
549 ((long) si->esp_at_signal & - getpagesize ()))[getpagesize ()];
551 but that's wrong since it tests the stack pointer location and the
552 stack probing code may not move it until all probes succeed.
554 For now we simply do not attempt any discrimination at all. Note
555 that this is quite acceptable, since a "real" SIGSEGV can only
556 occur as the result of an erroneous program. */
557 exception = &storage_error;
558 msg = "stack overflow or erroneous memory access";
559 break;
561 case SIGBUS:
562 exception = &storage_error;
563 msg = "SIGBUS: possible stack overflow";
564 break;
566 case SIGFPE:
567 exception = &constraint_error;
568 msg = "SIGFPE";
569 break;
571 default:
572 exception = &program_error;
573 msg = "unhandled signal";
576 Raise_From_Signal_Handler (exception, msg);
579 #ifndef __ia64__
580 #define HAVE_GNAT_ALTERNATE_STACK 1
581 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
582 char __gnat_alternate_stack[32 * 1024];
583 #endif
585 #ifdef __XENO__
586 #include <sys/mman.h>
587 #include <native/task.h>
589 RT_TASK main_task;
590 #endif
592 void
593 __gnat_install_handler (void)
595 struct sigaction act;
597 #ifdef __XENO__
598 int prio;
600 if (__gl_main_priority == -1)
601 prio = 49;
602 else
603 prio = __gl_main_priority;
605 /* Avoid memory swapping for this program */
607 mlockall (MCL_CURRENT|MCL_FUTURE);
609 /* Turn the current Linux task into a native Xenomai task */
611 rt_task_shadow (&main_task, "environment_task", prio, T_FPU);
612 #endif
614 /* Set up signal handler to map synchronous signals to appropriate
615 exceptions. Make sure that the handler isn't interrupted by another
616 signal that might cause a scheduling event! Also setup an alternate
617 stack region for the handler execution so that stack overflows can be
618 handled properly, avoiding a SEGV generation from stack usage by the
619 handler itself. */
621 act.sa_sigaction = __gnat_error_handler;
622 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
623 sigemptyset (&act.sa_mask);
625 /* Do not install handlers if interrupt state is "System". */
626 if (__gnat_get_interrupt_state (SIGABRT) != 's')
627 sigaction (SIGABRT, &act, NULL);
628 if (__gnat_get_interrupt_state (SIGFPE) != 's')
629 sigaction (SIGFPE, &act, NULL);
630 if (__gnat_get_interrupt_state (SIGILL) != 's')
631 sigaction (SIGILL, &act, NULL);
632 if (__gnat_get_interrupt_state (SIGBUS) != 's')
633 sigaction (SIGBUS, &act, NULL);
634 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
636 #ifdef HAVE_GNAT_ALTERNATE_STACK
637 /* Setup an alternate stack region for the handler execution so that
638 stack overflows can be handled properly, avoiding a SEGV generation
639 from stack usage by the handler itself. */
640 stack_t stack;
642 stack.ss_sp = __gnat_alternate_stack;
643 stack.ss_size = sizeof (__gnat_alternate_stack);
644 stack.ss_flags = 0;
645 sigaltstack (&stack, NULL);
647 act.sa_flags |= SA_ONSTACK;
648 #endif
649 sigaction (SIGSEGV, &act, NULL);
652 __gnat_handler_installed = 1;
655 /*******************/
656 /* LynxOS Section */
657 /*******************/
659 #elif defined (__Lynx__)
661 #include <signal.h>
662 #include <unistd.h>
664 /* SA_SIGINFO is not supported by default on LynxOS, so all we have
665 available here is the "sig" argument. On newer LynxOS versions it's
666 possible to support SA_SIGINFO by setting a kernel configuration macro.
668 To wit:
670 #define NONPOSIX_SA_HANDLER_PROTO (0)
672 This macro must be set to 1 in either sys/bsp.<bspname>/uparam.h
673 or in the associated uparam.h customization file sys/bsp.<bspname>/xparam.h
674 (uparam.h includes xparam.h for customization)
676 The NONPOSIX_SA_HANDLER_PROTO macro makes it possible to provide
677 signal-catching function with 'info' and 'context' input parameters
678 even if SA_SIGINFO flag is not set or it is set for a non-realtime signal.
680 It also allows signal-catching function to update thread context even
681 if SA_UPDATECTX flag is not set.
683 This would be useful, but relying on that would transmit the requirement
684 to users to configure that feature as well, which is undesirable. */
686 static void
687 __gnat_error_handler (int sig)
689 struct Exception_Data *exception;
690 const char *msg;
692 switch(sig)
694 case SIGFPE:
695 exception = &constraint_error;
696 msg = "SIGFPE";
697 break;
698 case SIGILL:
699 exception = &constraint_error;
700 msg = "SIGILL";
701 break;
702 case SIGSEGV:
703 exception = &storage_error;
704 msg = "stack overflow or erroneous memory access";
705 break;
706 case SIGBUS:
707 exception = &constraint_error;
708 msg = "SIGBUS";
709 break;
710 default:
711 exception = &program_error;
712 msg = "unhandled signal";
715 Raise_From_Signal_Handler (exception, msg);
718 void
719 __gnat_install_handler (void)
721 struct sigaction act;
723 act.sa_handler = __gnat_error_handler;
724 act.sa_flags = 0x0;
725 sigemptyset (&act.sa_mask);
727 /* Do not install handlers if interrupt state is "System". */
728 if (__gnat_get_interrupt_state (SIGFPE) != 's')
729 sigaction (SIGFPE, &act, NULL);
730 if (__gnat_get_interrupt_state (SIGILL) != 's')
731 sigaction (SIGILL, &act, NULL);
732 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
733 sigaction (SIGSEGV, &act, NULL);
734 if (__gnat_get_interrupt_state (SIGBUS) != 's')
735 sigaction (SIGBUS, &act, NULL);
737 __gnat_handler_installed = 1;
740 /*******************/
741 /* Solaris Section */
742 /*******************/
744 #elif defined (__sun__) && !defined (__vxworks)
746 #include <signal.h>
747 #include <siginfo.h>
748 #include <sys/ucontext.h>
749 #include <sys/regset.h>
751 static void
752 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext ATTRIBUTE_UNUSED)
754 struct Exception_Data *exception;
755 static int recurse = 0;
756 const char *msg;
758 switch (sig)
760 case SIGSEGV:
761 /* If the problem was permissions, this is a constraint error.
762 Likewise if the failing address isn't maximally aligned or if
763 we've recursed.
765 ??? Using a static variable here isn't task-safe, but it's
766 much too hard to do anything else and we're just determining
767 which exception to raise. */
768 if (si->si_code == SEGV_ACCERR
769 || (long) si->si_addr == 0
770 || (((long) si->si_addr) & 3) != 0
771 || recurse)
773 exception = &constraint_error;
774 msg = "SIGSEGV";
776 else
778 /* See if the page before the faulting page is accessible. Do that
779 by trying to access it. We'd like to simply try to access
780 4096 + the faulting address, but it's not guaranteed to be
781 the actual address, just to be on the same page. */
782 recurse++;
783 ((volatile char *)
784 ((long) si->si_addr & - getpagesize ()))[getpagesize ()];
785 exception = &storage_error;
786 msg = "stack overflow or erroneous memory access";
788 break;
790 case SIGBUS:
791 exception = &program_error;
792 msg = "SIGBUS";
793 break;
795 case SIGFPE:
796 exception = &constraint_error;
797 msg = "SIGFPE";
798 break;
800 default:
801 exception = &program_error;
802 msg = "unhandled signal";
805 recurse = 0;
806 Raise_From_Signal_Handler (exception, msg);
809 void
810 __gnat_install_handler (void)
812 struct sigaction act;
814 /* Set up signal handler to map synchronous signals to appropriate
815 exceptions. Make sure that the handler isn't interrupted by another
816 signal that might cause a scheduling event! */
818 act.sa_sigaction = __gnat_error_handler;
819 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
820 sigemptyset (&act.sa_mask);
822 /* Do not install handlers if interrupt state is "System". */
823 if (__gnat_get_interrupt_state (SIGABRT) != 's')
824 sigaction (SIGABRT, &act, NULL);
825 if (__gnat_get_interrupt_state (SIGFPE) != 's')
826 sigaction (SIGFPE, &act, NULL);
827 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
828 sigaction (SIGSEGV, &act, NULL);
829 if (__gnat_get_interrupt_state (SIGBUS) != 's')
830 sigaction (SIGBUS, &act, NULL);
832 __gnat_handler_installed = 1;
835 /***************/
836 /* VMS Section */
837 /***************/
839 #elif defined (VMS)
841 /* Routine called from binder to override default feature values. */
842 void __gnat_set_features (void);
843 int __gnat_features_set = 0;
844 void (*__gnat_ctrl_c_handler) (void) = 0;
846 #ifdef __IA64
847 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
848 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
849 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
850 #else
851 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
852 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
853 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
854 #endif
856 /* Masks for facility identification. */
857 #define FAC_MASK 0x0fff0000
858 #define DECADA_M_FACILITY 0x00310000
860 /* Define macro symbols for the VMS conditions that become Ada exceptions.
861 It would be better to just include <ssdef.h> */
863 #define SS$_CONTINUE 1
864 #define SS$_ACCVIO 12
865 #define SS$_HPARITH 1284
866 #define SS$_INTDIV 1156
867 #define SS$_STKOVF 1364
868 #define SS$_CONTROLC 1617
869 #define SS$_RESIGNAL 2328
871 #define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
873 /* The following codes must be resignalled, and not handled here. */
875 /* These codes are in standard message libraries. */
876 extern int C$_SIGKILL;
877 extern int C$_SIGINT;
878 extern int SS$_DEBUG;
879 extern int LIB$_KEYNOTFOU;
880 extern int LIB$_ACTIMAGE;
882 /* These codes are non standard, which is to say the author is
883 not sure if they are defined in the standard message libraries
884 so keep them as macros for now. */
885 #define RDB$_STREAM_EOF 20480426
886 #define FDL$_UNPRIKW 11829410
887 #define CMA$_EXIT_THREAD 4227492
889 struct cond_sigargs
891 unsigned int sigarg;
892 unsigned int sigargval;
895 struct cond_subtests
897 unsigned int num;
898 const struct cond_sigargs sigargs[];
901 struct cond_except
903 unsigned int cond;
904 const struct Exception_Data *except;
905 unsigned int needs_adjust; /* 1 = adjust PC, 0 = no adjust */
906 const struct cond_subtests *subtests;
909 struct descriptor_s
911 unsigned short len, mbz;
912 __char_ptr32 adr;
915 /* Conditions that don't have an Ada exception counterpart must raise
916 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
917 referenced by user programs, not the compiler or tools. Hence the
918 #ifdef IN_RTS. */
920 #ifdef IN_RTS
922 #define Status_Error ada__io_exceptions__status_error
923 extern struct Exception_Data Status_Error;
925 #define Mode_Error ada__io_exceptions__mode_error
926 extern struct Exception_Data Mode_Error;
928 #define Name_Error ada__io_exceptions__name_error
929 extern struct Exception_Data Name_Error;
931 #define Use_Error ada__io_exceptions__use_error
932 extern struct Exception_Data Use_Error;
934 #define Device_Error ada__io_exceptions__device_error
935 extern struct Exception_Data Device_Error;
937 #define End_Error ada__io_exceptions__end_error
938 extern struct Exception_Data End_Error;
940 #define Data_Error ada__io_exceptions__data_error
941 extern struct Exception_Data Data_Error;
943 #define Layout_Error ada__io_exceptions__layout_error
944 extern struct Exception_Data Layout_Error;
946 #define Non_Ada_Error system__aux_dec__non_ada_error
947 extern struct Exception_Data Non_Ada_Error;
949 #define Coded_Exception system__vms_exception_table__coded_exception
950 extern struct Exception_Data *Coded_Exception (void *);
952 #define Base_Code_In system__vms_exception_table__base_code_in
953 extern void *Base_Code_In (void *);
955 /* DEC Ada exceptions are not defined in a header file, so they
956 must be declared. */
958 #define ADA$_ALREADY_OPEN 0x0031a594
959 #define ADA$_CONSTRAINT_ERRO 0x00318324
960 #define ADA$_DATA_ERROR 0x003192c4
961 #define ADA$_DEVICE_ERROR 0x003195e4
962 #define ADA$_END_ERROR 0x00319904
963 #define ADA$_FAC_MODE_MISMAT 0x0031a8b3
964 #define ADA$_IOSYSFAILED 0x0031af04
965 #define ADA$_KEYSIZERR 0x0031aa3c
966 #define ADA$_KEY_MISMATCH 0x0031a8e3
967 #define ADA$_LAYOUT_ERROR 0x00319c24
968 #define ADA$_LINEXCMRS 0x0031a8f3
969 #define ADA$_MAXLINEXC 0x0031a8eb
970 #define ADA$_MODE_ERROR 0x00319f44
971 #define ADA$_MRN_MISMATCH 0x0031a8db
972 #define ADA$_MRS_MISMATCH 0x0031a8d3
973 #define ADA$_NAME_ERROR 0x0031a264
974 #define ADA$_NOT_OPEN 0x0031a58c
975 #define ADA$_ORG_MISMATCH 0x0031a8bb
976 #define ADA$_PROGRAM_ERROR 0x00318964
977 #define ADA$_RAT_MISMATCH 0x0031a8cb
978 #define ADA$_RFM_MISMATCH 0x0031a8c3
979 #define ADA$_STAOVF 0x00318cac
980 #define ADA$_STATUS_ERROR 0x0031a584
981 #define ADA$_STORAGE_ERROR 0x00318c84
982 #define ADA$_UNSUPPORTED 0x0031a8ab
983 #define ADA$_USE_ERROR 0x0031a8a4
985 /* DEC Ada specific conditions. */
986 static const struct cond_except dec_ada_cond_except_table [] =
988 {ADA$_PROGRAM_ERROR, &program_error, 0, 0},
989 {ADA$_USE_ERROR, &Use_Error, 0, 0},
990 {ADA$_KEYSIZERR, &program_error, 0, 0},
991 {ADA$_STAOVF, &storage_error, 0, 0},
992 {ADA$_CONSTRAINT_ERRO, &constraint_error, 0, 0},
993 {ADA$_IOSYSFAILED, &Device_Error, 0, 0},
994 {ADA$_LAYOUT_ERROR, &Layout_Error, 0, 0},
995 {ADA$_STORAGE_ERROR, &storage_error, 0, 0},
996 {ADA$_DATA_ERROR, &Data_Error, 0, 0},
997 {ADA$_DEVICE_ERROR, &Device_Error, 0, 0},
998 {ADA$_END_ERROR, &End_Error, 0, 0},
999 {ADA$_MODE_ERROR, &Mode_Error, 0, 0},
1000 {ADA$_NAME_ERROR, &Name_Error, 0, 0},
1001 {ADA$_STATUS_ERROR, &Status_Error, 0, 0},
1002 {ADA$_NOT_OPEN, &Use_Error, 0, 0},
1003 {ADA$_ALREADY_OPEN, &Use_Error, 0, 0},
1004 {ADA$_USE_ERROR, &Use_Error, 0, 0},
1005 {ADA$_UNSUPPORTED, &Use_Error, 0, 0},
1006 {ADA$_FAC_MODE_MISMAT, &Use_Error, 0, 0},
1007 {ADA$_ORG_MISMATCH, &Use_Error, 0, 0},
1008 {ADA$_RFM_MISMATCH, &Use_Error, 0, 0},
1009 {ADA$_RAT_MISMATCH, &Use_Error, 0, 0},
1010 {ADA$_MRS_MISMATCH, &Use_Error, 0, 0},
1011 {ADA$_MRN_MISMATCH, &Use_Error, 0, 0},
1012 {ADA$_KEY_MISMATCH, &Use_Error, 0, 0},
1013 {ADA$_MAXLINEXC, &constraint_error, 0, 0},
1014 {ADA$_LINEXCMRS, &constraint_error, 0, 0},
1016 #if 0
1017 /* Already handled by a pragma Import_Exception
1018 in Aux_IO_Exceptions */
1019 {ADA$_LOCK_ERROR, &Lock_Error, 0, 0},
1020 {ADA$_EXISTENCE_ERROR, &Existence_Error, 0, 0},
1021 {ADA$_KEY_ERROR, &Key_Error, 0, 0},
1022 #endif
1024 {0, 0, 0, 0}
1027 #endif /* IN_RTS */
1029 /* Non-DEC Ada specific conditions that map to Ada exceptions. */
1031 /* Subtest for ACCVIO Constraint_Error, kept for compatibility,
1032 in hindsight should have just made ACCVIO == Storage_Error. */
1033 #define ACCVIO_VIRTUAL_ADDR 3
1034 static const struct cond_subtests accvio_c_e =
1035 {1, /* number of subtests below */
1037 { ACCVIO_VIRTUAL_ADDR, 0 }
1041 /* Macro flag to adjust PC which gets off by one for some conditions,
1042 not sure if this is reliably true, PC could be off by more for
1043 HPARITH for example, unless a trapb is inserted. */
1044 #define NEEDS_ADJUST 1
1046 static const struct cond_except system_cond_except_table [] =
1048 {MTH$_FLOOVEMAT, &constraint_error, 0, 0},
1049 {SS$_INTDIV, &constraint_error, 0, 0},
1050 {SS$_HPARITH, &constraint_error, NEEDS_ADJUST, 0},
1051 {SS$_ACCVIO, &constraint_error, NEEDS_ADJUST, &accvio_c_e},
1052 {SS$_ACCVIO, &storage_error, NEEDS_ADJUST, 0},
1053 {SS$_STKOVF, &storage_error, NEEDS_ADJUST, 0},
1054 {0, 0, 0, 0}
1057 /* To deal with VMS conditions and their mapping to Ada exceptions,
1058 the __gnat_error_handler routine below is installed as an exception
1059 vector having precedence over DEC frame handlers. Some conditions
1060 still need to be handled by such handlers, however, in which case
1061 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
1062 instance the use of a third party library compiled with DECAda and
1063 performing its own exception handling internally.
1065 To allow some user-level flexibility, which conditions should be
1066 resignaled is controlled by a predicate function, provided with the
1067 condition value and returning a boolean indication stating whether
1068 this condition should be resignaled or not.
1070 That predicate function is called indirectly, via a function pointer,
1071 by __gnat_error_handler, and changing that pointer is allowed to the
1072 user code by way of the __gnat_set_resignal_predicate interface.
1074 The user level function may then implement what it likes, including
1075 for instance the maintenance of a dynamic data structure if the set
1076 of to be resignalled conditions has to change over the program's
1077 lifetime.
1079 ??? This is not a perfect solution to deal with the possible
1080 interactions between the GNAT and the DECAda exception handling
1081 models and better (more general) schemes are studied. This is so
1082 just provided as a convenient workaround in the meantime, and
1083 should be use with caution since the implementation has been kept
1084 very simple. */
1086 typedef int resignal_predicate (int code);
1088 static const int * const cond_resignal_table [] =
1090 &C$_SIGKILL,
1091 (int *)CMA$_EXIT_THREAD,
1092 &SS$_DEBUG,
1093 &LIB$_KEYNOTFOU,
1094 &LIB$_ACTIMAGE,
1095 (int *) RDB$_STREAM_EOF,
1096 (int *) FDL$_UNPRIKW,
1100 static const int facility_resignal_table [] =
1102 0x1380000, /* RDB */
1103 0x2220000, /* SQL */
1107 /* Default GNAT predicate for resignaling conditions. */
1109 static int
1110 __gnat_default_resignal_p (int code)
1112 int i, iexcept;
1114 for (i = 0; facility_resignal_table [i]; i++)
1115 if ((code & FAC_MASK) == facility_resignal_table [i])
1116 return 1;
1118 for (i = 0, iexcept = 0;
1119 cond_resignal_table [i]
1120 && !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1121 i++);
1123 return iexcept;
1126 /* Static pointer to predicate that the __gnat_error_handler exception
1127 vector invokes to determine if it should resignal a condition. */
1129 static resignal_predicate *__gnat_resignal_p = __gnat_default_resignal_p;
1131 /* User interface to change the predicate pointer to PREDICATE. Reset to
1132 the default if PREDICATE is null. */
1134 void
1135 __gnat_set_resignal_predicate (resignal_predicate *predicate)
1137 if (predicate == NULL)
1138 __gnat_resignal_p = __gnat_default_resignal_p;
1139 else
1140 __gnat_resignal_p = predicate;
1143 /* Should match System.Parameters.Default_Exception_Msg_Max_Length. */
1144 #define Default_Exception_Msg_Max_Length 512
1146 /* Action routine for SYS$PUTMSG. There may be multiple
1147 conditions, each with text to be appended to MESSAGE
1148 and separated by line termination. */
1149 static int
1150 copy_msg (struct descriptor_s *msgdesc, char *message)
1152 int len = strlen (message);
1153 int copy_len;
1155 /* Check for buffer overflow and skip. */
1156 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1158 strcat (message, "\r\n");
1159 len += 2;
1162 /* Check for buffer overflow and truncate if necessary. */
1163 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1164 msgdesc->len :
1165 Default_Exception_Msg_Max_Length - 1 - len);
1166 strncpy (&message [len], msgdesc->adr, copy_len);
1167 message [len + copy_len] = 0;
1169 return 0;
1172 /* Scan TABLE for a match for the condition contained in SIGARGS,
1173 and return the entry, or the empty entry if no match found. */
1174 static const struct cond_except *
1175 scan_conditions ( int *sigargs, const struct cond_except *table [])
1177 int i;
1178 struct cond_except entry;
1180 /* Scan the exception condition table for a match and fetch
1181 the associated GNAT exception pointer. */
1182 for (i = 0; (*table) [i].cond; i++)
1184 unsigned int match = LIB$MATCH_COND (&sigargs [1], &(*table) [i].cond);
1185 const struct cond_subtests *subtests = (*table) [i].subtests;
1187 if (match)
1189 if (!subtests)
1191 return &(*table) [i];
1193 else
1195 unsigned int ii;
1196 int num = (*subtests).num;
1198 /* Perform subtests to differentiate exception. */
1199 for (ii = 0; ii < num; ii++)
1201 unsigned int arg = (*subtests).sigargs [ii].sigarg;
1202 unsigned int argval = (*subtests).sigargs [ii].sigargval;
1204 if (sigargs [arg] != argval)
1206 num = 0;
1207 break;
1211 /* All subtests passed. */
1212 if (num == (*subtests).num)
1213 return &(*table) [i];
1218 /* No match, return the null terminating entry. */
1219 return &(*table) [i];
1222 /* __gnat_handle_vms_condtition is both a frame based handler
1223 for the runtime, and an exception vector for the compiler. */
1224 long
1225 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1227 struct Exception_Data *exception = 0;
1228 unsigned int needs_adjust = 0;
1229 void *base_code;
1230 struct descriptor_s gnat_facility = {4, 0, "GNAT"};
1231 char message [Default_Exception_Msg_Max_Length];
1233 const char *msg = "";
1235 /* Check for conditions to resignal which aren't effected by pragma
1236 Import_Exception. */
1237 if (__gnat_resignal_p (sigargs [1]))
1238 return SS$_RESIGNAL;
1239 #ifndef IN_RTS
1240 /* toplev.cc handles this for compiler. */
1241 if (sigargs [1] == SS$_HPARITH)
1242 return SS$_RESIGNAL;
1243 #endif
1245 #ifdef IN_RTS
1246 /* See if it's an imported exception. Beware that registered exceptions
1247 are bound to their base code, with the severity bits masked off. */
1248 base_code = Base_Code_In ((void *) sigargs[1]);
1249 exception = Coded_Exception (base_code);
1250 #endif
1252 if (exception == 0)
1253 #ifdef IN_RTS
1255 int i;
1256 struct cond_except cond;
1257 const struct cond_except *cond_table;
1258 const struct cond_except *cond_tables [] = {dec_ada_cond_except_table,
1259 system_cond_except_table,
1261 unsigned int ctrlc = SS$_CONTROLC;
1262 unsigned int *sigint = &C$_SIGINT;
1263 int ctrlc_match = LIB$MATCH_COND (&sigargs [1], &ctrlc);
1264 int sigint_match = LIB$MATCH_COND (&sigargs [1], &sigint);
1266 extern int SYS$DCLAST (void (*astadr)(), unsigned long long astprm,
1267 unsigned int acmode);
1269 /* If SS$_CONTROLC has been imported as an exception, it will take
1270 priority over a Ctrl/C handler. See above. SIGINT has a
1271 different condition value due to it's DECCCRTL roots and it's
1272 the condition that gets raised for a "kill -INT". */
1273 if ((ctrlc_match || sigint_match) && __gnat_ctrl_c_handler)
1275 SYS$DCLAST (__gnat_ctrl_c_handler, 0, 0);
1276 return SS$_CONTINUE;
1279 i = 0;
1280 while ((cond_table = cond_tables[i++]) && !exception)
1282 cond = *scan_conditions (sigargs, &cond_table);
1283 exception = (struct Exception_Data *) cond.except;
1286 if (exception)
1287 needs_adjust = cond.needs_adjust;
1288 else
1289 /* User programs expect Non_Ada_Error to be raised if no match,
1290 reference DEC Ada test CXCONDHAN. */
1291 exception = &Non_Ada_Error;
1293 #else
1295 /* Pretty much everything is just a program error in the compiler */
1296 exception = &program_error;
1298 #endif
1300 message[0] = 0;
1301 /* Subtract PC & PSL fields as per ABI for SYS$PUTMSG. */
1302 sigargs[0] -= 2;
1304 extern int SYS$PUTMSG (void *, int (*)(), void *, unsigned long long);
1306 /* If it was a DEC Ada specific condtiion, make it GNAT otherwise
1307 keep the old facility. */
1308 if ((sigargs [1] & FAC_MASK) == DECADA_M_FACILITY)
1309 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility,
1310 (unsigned long long ) message);
1311 else
1312 SYS$PUTMSG (sigargs, copy_msg, 0,
1313 (unsigned long long ) message);
1315 /* Add back PC & PSL fields as per ABI for SYS$PUTMSG. */
1316 sigargs[0] += 2;
1317 msg = message;
1319 if (needs_adjust)
1320 __gnat_adjust_context_for_raise (sigargs [1], (void *)mechargs);
1322 Raise_From_Signal_Handler (exception, msg);
1325 #if defined (IN_RTS) && defined (__IA64)
1326 /* Called only from adasigio.b32. This is a band aid to avoid going
1327 through the VMS signal handling code which results in a 0x8000 per
1328 handled exception memory leak in P2 space (see VMS source listing
1329 sys/lis/exception.lis) due to the allocation of working space that
1330 is expected to be deallocated upon return from the condition handler,
1331 which doesn't return in GNAT compiled code. */
1332 void
1333 GNAT$STOP (int *sigargs)
1335 /* Note that there are no mechargs. We rely on the fact that condtions
1336 raised from DEClib I/O do not require an "adjust". Also the count
1337 will be off by 2, since LIB$STOP didn't get a chance to add the
1338 PC and PSL fields, so we bump it so PUTMSG comes out right. */
1339 sigargs [0] += 2;
1340 __gnat_handle_vms_condition (sigargs, 0);
1342 #endif
1344 void
1345 __gnat_install_handler (void)
1347 long prvhnd ATTRIBUTE_UNUSED;
1349 #if !defined (IN_RTS)
1350 extern int SYS$SETEXV (unsigned int vector, int (*addres)(),
1351 unsigned int accmode, void *(*(prvhnd)));
1352 SYS$SETEXV (1, __gnat_handle_vms_condition, 3, &prvhnd);
1353 #endif
1355 __gnat_handler_installed = 1;
1358 /* __gnat_adjust_context_for_raise for Alpha - see comments along with the
1359 default version later in this file. */
1361 #if defined (IN_RTS) && defined (__alpha__)
1363 #include <vms/chfctxdef.h>
1364 #include <vms/chfdef.h>
1366 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1368 void
1369 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1371 if (signo == SS$_HPARITH)
1373 /* Sub one to the address of the instruction signaling the condition,
1374 located in the sigargs array. */
1376 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1377 CHF$SIGNAL_ARRAY * sigargs
1378 = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1380 int vcount = sigargs->chf$is_sig_args;
1381 int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1383 (*pc_slot)--;
1387 #endif
1389 /* __gnat_adjust_context_for_raise for ia64. */
1391 #if defined (IN_RTS) && defined (__IA64)
1393 #include <vms/chfctxdef.h>
1394 #include <vms/chfdef.h>
1396 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1398 typedef unsigned long long u64;
1400 void
1401 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1403 /* Add one to the address of the instruction signaling the condition,
1404 located in the 64bits sigargs array. */
1406 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1408 CHF64$SIGNAL_ARRAY *chfsig64
1409 = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1411 u64 * post_sigarray
1412 = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1414 u64 * ih_pc_loc = post_sigarray - 2;
1416 (*ih_pc_loc) ++;
1419 #endif
1421 /* Easier interface for LIB$GET_LOGICAL: put the equivalence of NAME into BUF,
1422 always NUL terminated. In case of error or if the result is longer than
1423 LEN (length of BUF) an empty string is written info BUF. */
1425 static void
1426 __gnat_vms_get_logical (const char *name, char *buf, int len)
1428 struct descriptor_s name_desc, result_desc;
1429 int status;
1430 unsigned short rlen;
1432 /* Build the descriptor for NAME. */
1433 name_desc.len = strlen (name);
1434 name_desc.mbz = 0;
1435 name_desc.adr = (char *)name;
1437 /* Build the descriptor for the result. */
1438 result_desc.len = len;
1439 result_desc.mbz = 0;
1440 result_desc.adr = buf;
1442 status = LIB$GET_LOGICAL (&name_desc, &result_desc, &rlen);
1444 if ((status & 1) == 1 && rlen < len)
1445 buf[rlen] = 0;
1446 else
1447 buf[0] = 0;
1450 /* Size of a page on ia64 and alpha VMS. */
1451 #define VMS_PAGESIZE 8192
1453 /* User mode. */
1454 #define PSL__C_USER 3
1456 /* No access. */
1457 #define PRT__C_NA 0
1459 /* Descending region. */
1460 #define VA__M_DESCEND 1
1462 /* Get by virtual address. */
1463 #define VA___REGSUM_BY_VA 1
1465 /* Memory region summary. */
1466 struct regsum
1468 unsigned long long q_region_id;
1469 unsigned int l_flags;
1470 unsigned int l_region_protection;
1471 void *pq_start_va;
1472 unsigned long long q_region_size;
1473 void *pq_first_free_va;
1476 extern int SYS$GET_REGION_INFO (unsigned int, unsigned long long *,
1477 void *, void *, unsigned int,
1478 void *, unsigned int *);
1479 extern int SYS$EXPREG_64 (unsigned long long *, unsigned long long,
1480 unsigned int, unsigned int, void **,
1481 unsigned long long *);
1482 extern int SYS$SETPRT_64 (void *, unsigned long long, unsigned int,
1483 unsigned int, void **, unsigned long long *,
1484 unsigned int *);
1486 /* Add a guard page in the memory region containing ADDR at ADDR +/- SIZE.
1487 (The sign depends on the kind of the memory region). */
1489 static int
1490 __gnat_set_stack_guard_page (void *addr, unsigned long size)
1492 int status;
1493 void *ret_va;
1494 unsigned long long ret_len;
1495 unsigned int ret_prot;
1496 void *start_va;
1497 unsigned long long length;
1498 unsigned int retlen;
1499 struct regsum buffer;
1501 /* Get the region for ADDR. */
1502 status = SYS$GET_REGION_INFO
1503 (VA___REGSUM_BY_VA, NULL, addr, NULL, sizeof (buffer), &buffer, &retlen);
1505 if ((status & 1) != 1)
1506 return -1;
1508 /* Extend the region. */
1509 status = SYS$EXPREG_64 (&buffer.q_region_id,
1510 size, 0, 0, &start_va, &length);
1512 if ((status & 1) != 1)
1513 return -1;
1515 /* Create a guard page. */
1516 if (!(buffer.l_flags & VA__M_DESCEND))
1517 start_va = (void *)((unsigned long long)start_va + length - VMS_PAGESIZE);
1519 status = SYS$SETPRT_64 (start_va, VMS_PAGESIZE, PSL__C_USER, PRT__C_NA,
1520 &ret_va, &ret_len, &ret_prot);
1522 if ((status & 1) != 1)
1523 return -1;
1524 return 0;
1527 /* Read logicals to limit the stack(s) size. */
1529 static void
1530 __gnat_set_stack_limit (void)
1532 #ifdef __ia64__
1533 void *sp;
1534 unsigned long size;
1535 char value[16];
1536 char *e;
1538 /* The main stack. */
1539 __gnat_vms_get_logical ("GNAT_STACK_SIZE", value, sizeof (value));
1540 size = strtoul (value, &e, 0);
1541 if (e > value && *e == 0)
1543 asm ("mov %0=sp" : "=r" (sp));
1544 __gnat_set_stack_guard_page (sp, size * 1024);
1547 /* The register stack. */
1548 __gnat_vms_get_logical ("GNAT_RBS_SIZE", value, sizeof (value));
1549 size = strtoul (value, &e, 0);
1550 if (e > value && *e == 0)
1552 asm ("mov %0=ar.bsp" : "=r" (sp));
1553 __gnat_set_stack_guard_page (sp, size * 1024);
1555 #endif
1558 #ifdef IN_RTS
1559 extern int SYS$IEEE_SET_FP_CONTROL (void *, void *, void *);
1560 #define K_TRUE 1
1561 #define __int64 long long
1562 #define __NEW_STARLET
1563 #include <vms/ieeedef.h>
1564 #endif
1566 /* Feature logical name and global variable address pair.
1567 If we ever add another feature logical to this list, the
1568 feature struct will need to be enhanced to take into account
1569 possible values for *gl_addr. */
1570 struct feature {
1571 const char *name;
1572 int *gl_addr;
1575 /* Default values for GNAT features set by environment or binder. */
1576 int __gl_heap_size = 64;
1578 /* Default float format is 'I' meaning IEEE. If gnatbind detetcts that a
1579 VAX Float format is specified, it will set this global variable to 'V'.
1580 Subsequently __gnat_set_features will test the variable and if set for
1581 VAX Float will call a Starlet function to enable trapping for invalid
1582 operation, drivide by zero, and overflow. This will prevent the VMS runtime
1583 (specifically OTS$CHECK_FP_MODE) from complaining about inconsistent
1584 floating point settings in a mixed language program. Ideally the setting
1585 would be determined at link time based on settings in the object files,
1586 however the VMS linker seems to take the setting from the first object
1587 in the link, e.g. pcrt0.o which is float representation neutral. */
1588 char __gl_float_format = 'I';
1590 /* Array feature logical names and global variable addresses. */
1591 static const struct feature features[] =
1593 {"GNAT$NO_MALLOC_64", &__gl_heap_size},
1594 {0, 0}
1597 void
1598 __gnat_set_features (void)
1600 int i;
1601 char buff[16];
1602 #ifdef IN_RTS
1603 IEEE clrmsk, setmsk, prvmsk;
1605 clrmsk.ieee$q_flags = 0LL;
1606 setmsk.ieee$q_flags = 0LL;
1607 #endif
1609 /* Loop through features array and test name for enable/disable. */
1610 for (i = 0; features[i].name; i++)
1612 __gnat_vms_get_logical (features[i].name, buff, sizeof (buff));
1614 if (strcmp (buff, "ENABLE") == 0
1615 || strcmp (buff, "TRUE") == 0
1616 || strcmp (buff, "1") == 0)
1617 *features[i].gl_addr = 32;
1618 else if (strcmp (buff, "DISABLE") == 0
1619 || strcmp (buff, "FALSE") == 0
1620 || strcmp (buff, "0") == 0)
1621 *features[i].gl_addr = 64;
1624 /* Features to artificially limit the stack size. */
1625 __gnat_set_stack_limit ();
1627 #ifdef IN_RTS
1628 if (__gl_float_format == 'V')
1630 setmsk.ieee$v_trap_enable_inv = K_TRUE;
1631 setmsk.ieee$v_trap_enable_dze = K_TRUE;
1632 setmsk.ieee$v_trap_enable_ovf = K_TRUE;
1633 SYS$IEEE_SET_FP_CONTROL (&clrmsk, &setmsk, &prvmsk);
1635 #endif
1637 __gnat_features_set = 1;
1640 /* Return true if the VMS version is 7.x. */
1642 extern unsigned int LIB$GETSYI (int *, ...);
1644 #define SYI$_VERSION 0x1000
1647 __gnat_is_vms_v7 (void)
1649 struct descriptor_s desc;
1650 char version[8];
1651 int status;
1652 int code = SYI$_VERSION;
1654 desc.len = sizeof (version);
1655 desc.mbz = 0;
1656 desc.adr = version;
1658 status = LIB$GETSYI (&code, 0, &desc);
1659 if ((status & 1) == 1 && version[1] == '7' && version[2] == '.')
1660 return 1;
1661 else
1662 return 0;
1665 /*******************/
1666 /* FreeBSD Section */
1667 /*******************/
1669 #elif defined (__FreeBSD__) || defined (__DragonFly__)
1671 #include <signal.h>
1672 #include <sys/ucontext.h>
1673 #include <unistd.h>
1675 static void
1676 __gnat_error_handler (int sig,
1677 siginfo_t *si ATTRIBUTE_UNUSED,
1678 void *ucontext ATTRIBUTE_UNUSED)
1680 struct Exception_Data *exception;
1681 const char *msg;
1683 switch (sig)
1685 case SIGFPE:
1686 exception = &constraint_error;
1687 msg = "SIGFPE";
1688 break;
1690 case SIGILL:
1691 exception = &constraint_error;
1692 msg = "SIGILL";
1693 break;
1695 case SIGSEGV:
1696 exception = &storage_error;
1697 msg = "stack overflow or erroneous memory access";
1698 break;
1700 case SIGBUS:
1701 exception = &storage_error;
1702 msg = "SIGBUS: possible stack overflow";
1703 break;
1705 default:
1706 exception = &program_error;
1707 msg = "unhandled signal";
1710 Raise_From_Signal_Handler (exception, msg);
1713 void
1714 __gnat_install_handler (void)
1716 struct sigaction act;
1718 /* Set up signal handler to map synchronous signals to appropriate
1719 exceptions. Make sure that the handler isn't interrupted by another
1720 signal that might cause a scheduling event! */
1722 act.sa_sigaction
1723 = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1724 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1725 (void) sigemptyset (&act.sa_mask);
1727 (void) sigaction (SIGILL, &act, NULL);
1728 (void) sigaction (SIGFPE, &act, NULL);
1729 (void) sigaction (SIGSEGV, &act, NULL);
1730 (void) sigaction (SIGBUS, &act, NULL);
1732 __gnat_handler_installed = 1;
1735 /*************************************/
1736 /* VxWorks Section (including Vx653) */
1737 /*************************************/
1739 #elif defined(__vxworks)
1741 #include <signal.h>
1742 #include <taskLib.h>
1743 #if (defined (__i386__) || defined (__x86_64__)) && !defined (VTHREADS)
1744 #include <sysLib.h>
1745 #endif
1747 #include "sigtramp.h"
1749 #ifndef __RTP__
1750 #include <intLib.h>
1751 #include <iv.h>
1752 #endif
1754 #if ((defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6))) && !defined(__RTP__)
1755 #define VXWORKS_FORCE_GUARD_PAGE 1
1756 #include <vmLib.h>
1757 extern size_t vxIntStackOverflowSize;
1758 #define INT_OVERFLOW_SIZE vxIntStackOverflowSize
1759 #endif
1761 /* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
1762 handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
1763 doesn't. A similar issue is present VxWorks 7.2 and affects ZCX as well
1764 as builtin_longjmp. This field only exists in Kernel mode, not RTP. */
1765 #if defined(VTHREADS) || (!defined(__RTP__) && (_WRS_VXWORKS_MAJOR >= 7))
1766 # ifdef VTHREADS
1767 # include "private/vThreadsP.h"
1768 # define EXCCNT vThreads.excCnt
1769 # else
1770 # include "private/taskLibP.h"
1771 # define EXCCNT excCnt
1772 # endif
1773 # define CLEAR_EXCEPTION_COUNT() \
1774 do \
1776 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf(); \
1777 currentTask->EXCCNT = 0; \
1778 } while (0)
1779 #else
1780 # define CLEAR_EXCEPTION_COUNT()
1781 #endif
1783 #ifndef __RTP__
1785 /* Directly vectored Interrupt routines are not supported when using RTPs. */
1787 extern void * __gnat_inum_to_ivec (int);
1789 /* This is needed by the GNAT run time to handle Vxworks interrupts. */
1790 void *
1791 __gnat_inum_to_ivec (int num)
1793 return (void *) INUM_TO_IVEC (num);
1795 #endif
1797 #if !defined(__alpha_vxworks) && ((_WRS_VXWORKS_MAJOR != 6) && (_WRS_VXWORKS_MAJOR != 7)) && !defined(__RTP__)
1799 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1800 on Alpha VxWorks and VxWorks 6.x (including RTPs). */
1802 extern long getpid (void);
1804 long
1805 getpid (void)
1807 return taskIdSelf ();
1809 #endif
1811 /* When stack checking is performed by probing a guard page on the stack,
1812 sometimes this guard page is not properly reset on VxWorks. We need to
1813 manually reset it in this case.
1814 This function returns TRUE in case the guard page was hit by the
1815 signal. */
1816 static int
1817 __gnat_reset_guard_page (int sig)
1819 /* On ARM VxWorks 6.x and x86_64 VxWorks 7, the guard page is left un-armed
1820 by the kernel after being violated, so subsequent violations aren't
1821 detected.
1822 So we retrieve the address of the guard page from the TCB and compare it
1823 with the page that is violated and re-arm that page if there's a match. */
1824 #if defined (VXWORKS_FORCE_GUARD_PAGE)
1826 /* Ignore signals that are not stack overflow signals */
1827 if (sig != SIGSEGV && sig != SIGBUS && sig != SIGILL) return FALSE;
1829 /* If the target does not support guard pages, INT_OVERFLOW_SIZE will be 0 */
1830 if (INT_OVERFLOW_SIZE == 0) return FALSE;
1832 TASK_ID tid = taskIdSelf ();
1833 WIND_TCB *pTcb = taskTcb (tid);
1834 VIRT_ADDR guardPage = (VIRT_ADDR) pTcb->pStackEnd - INT_OVERFLOW_SIZE;
1835 UINT stateMask = VM_STATE_MASK_VALID;
1836 UINT guardState = VM_STATE_VALID_NOT;
1838 #if (_WRS_VXWORKS_MAJOR >= 7)
1839 stateMask |= MMU_ATTR_SPL_MSK;
1840 guardState |= MMU_ATTR_NO_BLOCK;
1841 #endif
1843 UINT nState;
1844 vmStateGet (NULL, guardPage, &nState);
1845 if ((nState & VM_STATE_MASK_VALID) != VM_STATE_VALID_NOT)
1847 /* If the guard page has a valid state, we need to reset to
1848 invalid state here */
1849 vmStateSet (NULL, guardPage, INT_OVERFLOW_SIZE, stateMask, guardState);
1850 return TRUE;
1852 #endif /* VXWORKS_FORCE_GUARD_PAGE */
1853 return FALSE;
1856 /* Handle different SIGnal to exception mappings in different VxWorks
1857 versions. */
1858 void
1859 __gnat_map_signal (int sig,
1860 siginfo_t *si ATTRIBUTE_UNUSED,
1861 void *sc ATTRIBUTE_UNUSED)
1863 struct Exception_Data *exception;
1864 const char *msg;
1866 switch (sig)
1868 case SIGFPE:
1869 exception = &constraint_error;
1870 msg = "SIGFPE";
1871 break;
1872 #ifdef VTHREADS
1873 #ifdef __VXWORKSMILS__
1874 case SIGILL:
1875 exception = &storage_error;
1876 msg = "SIGILL: possible stack overflow";
1877 break;
1878 case SIGSEGV:
1879 exception = &storage_error;
1880 msg = "SIGSEGV";
1881 break;
1882 case SIGBUS:
1883 exception = &program_error;
1884 msg = "SIGBUS";
1885 break;
1886 #else
1887 case SIGILL:
1888 exception = &constraint_error;
1889 msg = "Floating point exception or SIGILL";
1890 break;
1891 case SIGSEGV:
1892 exception = &storage_error;
1893 msg = "SIGSEGV";
1894 break;
1895 case SIGBUS:
1896 exception = &storage_error;
1897 msg = "SIGBUS: possible stack overflow";
1898 break;
1899 #endif
1900 #elif (_WRS_VXWORKS_MAJOR >= 6)
1901 case SIGILL:
1902 exception = &constraint_error;
1903 msg = "SIGILL";
1904 break;
1905 #ifdef __RTP__
1906 /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
1907 since stack checking uses the probing mechanism. */
1908 case SIGSEGV:
1909 exception = &storage_error;
1910 msg = "SIGSEGV: possible stack overflow";
1911 break;
1912 case SIGBUS:
1913 exception = &program_error;
1914 msg = "SIGBUS";
1915 break;
1916 #else
1917 /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
1918 case SIGSEGV:
1919 exception = &storage_error;
1920 msg = "SIGSEGV";
1921 break;
1922 case SIGBUS:
1923 exception = &storage_error;
1924 msg = "SIGBUS: possible stack overflow";
1925 break;
1926 #endif
1927 #else
1928 /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
1929 since stack checking uses the stack limit mechanism. */
1930 case SIGILL:
1931 exception = &storage_error;
1932 msg = "SIGILL: possible stack overflow";
1933 break;
1934 case SIGSEGV:
1935 exception = &storage_error;
1936 msg = "SIGSEGV";
1937 break;
1938 case SIGBUS:
1939 exception = &program_error;
1940 msg = "SIGBUS";
1941 break;
1942 #endif
1943 default:
1944 exception = &program_error;
1945 msg = "unhandled signal";
1948 if (__gnat_reset_guard_page (sig))
1950 /* Set the exception message: we know for sure that we have a
1951 stack overflow here */
1952 exception = &storage_error;
1954 switch (sig)
1956 case SIGSEGV:
1957 msg = "SIGSEGV: stack overflow";
1958 break;
1959 case SIGBUS:
1960 msg = "SIGBUS: stack overflow";
1961 break;
1962 case SIGILL:
1963 msg = "SIGILL: stack overflow";
1964 break;
1968 CLEAR_EXCEPTION_COUNT ();
1969 Raise_From_Signal_Handler (exception, msg);
1972 #if defined (ARMEL) && (_WRS_VXWORKS_MAJOR >= 7) && !defined (__aarch64__)
1974 /* ARM-vx7 case with arm unwinding exceptions */
1975 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1977 #include <arch/../regs.h>
1978 #ifndef __RTP__
1979 #include <sigLib.h>
1980 #else
1981 #include <signal.h>
1982 #include <regs.h>
1983 #include <ucontext.h>
1984 #endif /* __RTP__ */
1986 void
1987 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
1988 void *sc ATTRIBUTE_UNUSED)
1990 /* In case of ARM exceptions, the registers context have the PC pointing
1991 to the instruction that raised the signal. However the unwinder expects
1992 the instruction to be in the range ]PC,PC+1]. */
1993 uintptr_t *pc_addr;
1994 #ifdef __RTP__
1995 mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext;
1996 pc_addr = (uintptr_t*)&mcontext->regs.pc;
1997 #else
1998 struct sigcontext * sctx = (struct sigcontext *) sc;
1999 pc_addr = (uintptr_t*)&sctx->sc_pregs->pc;
2000 #endif
2001 /* ARM Bump has to be an even number because of odd/even architecture. */
2002 *pc_addr += 2;
2004 #endif /* ARMEL && _WRS_VXWORKS_MAJOR >= 7 */
2006 /* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
2007 propagation after the required low level adjustments. */
2009 static void
2010 __gnat_error_handler (int sig, siginfo_t *si, void *sc)
2012 sigset_t mask;
2014 /* VxWorks on e500v2 clears the SPE bit of the MSR when entering CPU
2015 exception state. To allow the handler and exception to work properly
2016 when they contain SPE instructions, we need to set it back before doing
2017 anything else.
2018 This mechanism is only need in kernel mode. */
2019 #if !(defined (__RTP__) || defined (VTHREADS)) && ((CPU == PPCE500V2) || (CPU == PPC85XX))
2020 unsigned msr;
2021 /* Read the MSR value */
2022 asm volatile ("mfmsr %0" : "=r" (msr));
2023 /* Force the SPE bit if not set. */
2024 if ((msr & 0x02000000) == 0)
2026 msr |= 0x02000000;
2027 /* Store to MSR */
2028 asm volatile ("mtmsr %0" : : "r" (msr));
2030 #endif
2032 /* VxWorks will always mask out the signal during the signal handler and
2033 will reenable it on a longjmp. GNAT does not generate a longjmp to
2034 return from a signal handler so the signal will still be masked unless
2035 we unmask it. */
2036 sigprocmask (SIG_SETMASK, NULL, &mask);
2037 sigdelset (&mask, sig);
2038 sigprocmask (SIG_SETMASK, &mask, NULL);
2040 #if defined (__ARMEL__) || defined (__PPC__) || defined (__i386__) || defined (__x86_64__) || defined (__aarch64__)
2041 /* On certain targets, kernel mode, we process signals through a Call Frame
2042 Info trampoline, voiding the need for myriads of fallback_frame_state
2043 variants in the ZCX runtime. We have no simple way to distinguish ZCX
2044 from SJLJ here, so we do this for SJLJ as well even though this is not
2045 necessary. This only incurs a few extra instructions and a tiny
2046 amount of extra stack usage. */
2048 #ifdef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2049 /* We need to sometimes to adjust the PC in case of signals so that it
2050 doesn't reference the exception that actually raised the signal but the
2051 instruction before it. */
2052 __gnat_adjust_context_for_raise (sig, sc);
2053 #endif
2055 __gnat_sigtramp (sig, (void *)si, (void *)sc,
2056 (__sigtramphandler_t *)&__gnat_map_signal);
2058 #else
2059 __gnat_map_signal (sig, si, sc);
2060 #endif
2063 #if defined(__leon__) && defined(_WRS_KERNEL)
2064 /* For LEON VxWorks we need to install a trap handler for stack overflow */
2066 extern void excEnt (void);
2067 /* VxWorks exception handler entry */
2069 struct trap_entry {
2070 unsigned long inst_first;
2071 unsigned long inst_second;
2072 unsigned long inst_third;
2073 unsigned long inst_fourth;
2075 /* Four instructions representing entries in the trap table */
2077 struct trap_entry *trap_0_entry;
2078 /* We will set the location of the entry for software trap 0 in the trap
2079 table. */
2080 #endif
2082 void
2083 __gnat_install_handler (void)
2085 struct sigaction act;
2087 /* Setup signal handler to map synchronous signals to appropriate
2088 exceptions. Make sure that the handler isn't interrupted by another
2089 signal that might cause a scheduling event! */
2091 act.sa_sigaction = __gnat_error_handler;
2092 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
2093 sigemptyset (&act.sa_mask);
2095 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
2096 applies to vectored hardware interrupts, not signals. */
2097 sigaction (SIGFPE, &act, NULL);
2098 sigaction (SIGILL, &act, NULL);
2099 sigaction (SIGSEGV, &act, NULL);
2100 sigaction (SIGBUS, &act, NULL);
2102 #if defined(__leon__) && defined(_WRS_KERNEL)
2103 /* Specific to the LEON VxWorks kernel run-time library */
2105 /* For stack checking the compiler triggers a software trap 0 (ta 0) in
2106 case of overflow (we use the stack limit mechanism). We need to install
2107 the trap handler here for this software trap (the OS does not handle
2108 it) as if it were a data_access_exception (trap 9). We do the same as
2109 if we put in the trap table a VXSPARC_BAD_TRAP(9). Software trap 0 is
2110 located at vector 0x80, and each entry takes 4 words. */
2112 trap_0_entry = (struct trap_entry *)(intVecBaseGet () + 0x80 * 4);
2114 /* mov 0x9, %l7 */
2116 trap_0_entry->inst_first = 0xae102000 + 9;
2118 /* sethi %hi(excEnt), %l6 */
2120 /* The 22 most significant bits of excEnt are obtained shifting 10 times
2121 to the right. */
2123 trap_0_entry->inst_second = 0x2d000000 + ((unsigned long)excEnt >> 10);
2125 /* jmp %l6+%lo(excEnt) */
2127 /* The 10 least significant bits of excEnt are obtained by masking */
2129 trap_0_entry->inst_third = 0x81c5a000 + ((unsigned long)excEnt & 0x3ff);
2131 /* rd %psr, %l0 */
2133 trap_0_entry->inst_fourth = 0xa1480000;
2134 #endif
2136 #ifdef __HANDLE_VXSIM_SC
2137 /* By experiment, found that sysModel () returns the following string
2138 prefix for vxsim when running on Linux and Windows. */
2140 char *model = sysModel ();
2141 if ((strncmp (model, "Linux", 5) == 0)
2142 || (strncmp (model, "Windows", 7) == 0)
2143 || (strncmp (model, "SIMLINUX", 8) == 0) /* vx7 */
2144 || (strncmp (model, "SIMNT", 5) == 0)) /* ditto */
2145 __gnat_set_is_vxsim (TRUE);
2147 #endif
2149 __gnat_handler_installed = 1;
2152 #define HAVE_GNAT_INIT_FLOAT
2154 void
2155 __gnat_init_float (void)
2157 /* Disable overflow/underflow exceptions on the PPC processor, needed
2158 to get correct Ada semantics. Note that for AE653 vThreads, the HW
2159 overflow settings are an OS configuration issue. The instructions
2160 below have no effect. */
2161 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && (!defined (VTHREADS) || defined (__VXWORKSMILS__))
2162 #if defined (__SPE__)
2164 /* For e500v2, do nothing and leave the responsibility to install the
2165 handler and enable the exceptions to the BSP. */
2167 #else
2168 asm ("mtfsb0 25");
2169 asm ("mtfsb0 26");
2170 #endif
2171 #endif
2173 #if (defined (__i386__) || defined (__x86_64__)) && !defined (VTHREADS)
2174 /* This is used to properly initialize the FPU on an x86 for each
2175 process thread. */
2176 asm ("finit");
2177 #endif
2179 /* Similarly for SPARC64. Achieved by masking bits in the Trap Enable Mask
2180 field of the Floating-point Status Register (see the SPARC Architecture
2181 Manual Version 9, p 48). */
2182 #if defined (sparc64)
2184 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
2185 #define FSR_TEM_OFM (1 << 26) /* Overflow */
2186 #define FSR_TEM_UFM (1 << 25) /* Underflow */
2187 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
2188 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
2190 unsigned int fsr;
2192 __asm__("st %%fsr, %0" : "=m" (fsr));
2193 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
2194 __asm__("ld %0, %%fsr" : : "m" (fsr));
2196 #endif
2199 /* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
2200 (if not null) when a new task is created. It is initialized by
2201 System.Stack_Checking.Operations.Initialize_Stack_Limit.
2202 The use of a hook avoids to drag stack checking subprograms if stack
2203 checking is not used. */
2204 void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
2206 /******************/
2207 /* NetBSD Section */
2208 /******************/
2210 #elif defined(__NetBSD__)
2212 #include <signal.h>
2213 #include <unistd.h>
2215 static void
2216 __gnat_error_handler (int sig)
2218 struct Exception_Data *exception;
2219 const char *msg;
2221 switch(sig)
2223 case SIGFPE:
2224 exception = &constraint_error;
2225 msg = "SIGFPE";
2226 break;
2227 case SIGILL:
2228 exception = &constraint_error;
2229 msg = "SIGILL";
2230 break;
2231 case SIGSEGV:
2232 exception = &storage_error;
2233 msg = "stack overflow or erroneous memory access";
2234 break;
2235 case SIGBUS:
2236 exception = &constraint_error;
2237 msg = "SIGBUS";
2238 break;
2239 default:
2240 exception = &program_error;
2241 msg = "unhandled signal";
2244 Raise_From_Signal_Handler (exception, msg);
2247 void
2248 __gnat_install_handler (void)
2250 struct sigaction act;
2252 act.sa_handler = __gnat_error_handler;
2253 act.sa_flags = SA_NODEFER | SA_RESTART;
2254 sigemptyset (&act.sa_mask);
2256 /* Do not install handlers if interrupt state is "System". */
2257 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2258 sigaction (SIGFPE, &act, NULL);
2259 if (__gnat_get_interrupt_state (SIGILL) != 's')
2260 sigaction (SIGILL, &act, NULL);
2261 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2262 sigaction (SIGSEGV, &act, NULL);
2263 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2264 sigaction (SIGBUS, &act, NULL);
2266 __gnat_handler_installed = 1;
2269 /*******************/
2270 /* OpenBSD Section */
2271 /*******************/
2273 #elif defined(__OpenBSD__)
2275 #include <signal.h>
2276 #include <unistd.h>
2278 static void
2279 __gnat_error_handler (int sig)
2281 struct Exception_Data *exception;
2282 const char *msg;
2284 switch(sig)
2286 case SIGFPE:
2287 exception = &constraint_error;
2288 msg = "SIGFPE";
2289 break;
2290 case SIGILL:
2291 exception = &constraint_error;
2292 msg = "SIGILL";
2293 break;
2294 case SIGSEGV:
2295 exception = &storage_error;
2296 msg = "stack overflow or erroneous memory access";
2297 break;
2298 case SIGBUS:
2299 exception = &constraint_error;
2300 msg = "SIGBUS";
2301 break;
2302 default:
2303 exception = &program_error;
2304 msg = "unhandled signal";
2307 Raise_From_Signal_Handler (exception, msg);
2310 void
2311 __gnat_install_handler (void)
2313 struct sigaction act;
2315 act.sa_handler = __gnat_error_handler;
2316 act.sa_flags = SA_NODEFER | SA_RESTART;
2317 sigemptyset (&act.sa_mask);
2319 /* Do not install handlers if interrupt state is "System" */
2320 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2321 sigaction (SIGFPE, &act, NULL);
2322 if (__gnat_get_interrupt_state (SIGILL) != 's')
2323 sigaction (SIGILL, &act, NULL);
2324 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2325 sigaction (SIGSEGV, &act, NULL);
2326 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2327 sigaction (SIGBUS, &act, NULL);
2329 __gnat_handler_installed = 1;
2332 /******************/
2333 /* Darwin Section */
2334 /******************/
2336 #elif defined(__APPLE__)
2338 #include <TargetConditionals.h>
2339 #include <signal.h>
2340 #include <stdlib.h>
2341 #include <sys/syscall.h>
2342 #include <sys/sysctl.h>
2344 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
2345 char __gnat_alternate_stack[32 * 1024]; /* 1 * MINSIGSTKSZ */
2347 /* Defined in xnu unix_signal.c.
2348 Tell the kernel to re-use alt stack when delivering a signal. */
2349 #define UC_RESET_ALT_STACK 0x80000000
2351 #if !(defined (__arm__) || defined (__arm64__) || TARGET_IPHONE_SIMULATOR)
2352 #include <mach/mach_vm.h>
2353 #include <mach/mach_init.h>
2354 #include <mach/vm_statistics.h>
2355 #endif
2357 #ifdef __arm64__
2358 #include <sys/ucontext.h>
2359 #include "sigtramp.h"
2360 #endif
2362 /* Return true if ADDR is within a stack guard area. */
2363 static int
2364 __gnat_is_stack_guard (mach_vm_address_t addr)
2366 #if !(defined (__arm__) || defined (__arm64__) || TARGET_IPHONE_SIMULATOR)
2367 kern_return_t kret;
2368 vm_region_submap_info_data_64_t info;
2369 mach_vm_address_t start;
2370 mach_vm_size_t size;
2371 natural_t depth;
2372 mach_msg_type_number_t count;
2374 count = VM_REGION_SUBMAP_INFO_COUNT_64;
2375 start = addr;
2376 size = -1;
2377 depth = 9999;
2378 kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
2379 (vm_region_recurse_info_t) &info, &count);
2380 if (kret == KERN_SUCCESS
2381 && addr >= start && addr < (start + size)
2382 && info.protection == VM_PROT_NONE
2383 && info.user_tag == VM_MEMORY_STACK)
2384 return 1;
2385 return 0;
2386 #else
2387 /* Pagezero for arm. */
2388 return addr >= 4096;
2389 #endif
2392 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2394 #if defined (__x86_64__)
2395 static int
2396 __darwin_major_version (void)
2398 static int cache = -1;
2399 if (cache < 0)
2401 int mib[2] = {CTL_KERN, KERN_OSRELEASE};
2402 size_t len;
2404 /* Find out how big the buffer needs to be (and set cache to 0
2405 on failure). */
2406 if (sysctl (mib, 2, NULL, &len, NULL, 0) == 0)
2408 char release[len];
2409 sysctl (mib, 2, release, &len, NULL, 0);
2410 /* Darwin releases are of the form L.M.N where L is the major
2411 version, so strtol will return L. */
2412 cache = (int) strtol (release, NULL, 10);
2414 else
2416 cache = 0;
2419 return cache;
2421 #endif
2423 void
2424 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2425 void *ucontext ATTRIBUTE_UNUSED)
2427 #if defined (__x86_64__)
2428 if (__darwin_major_version () < 12)
2430 /* Work around radar #10302855, where the unwinders (libunwind or
2431 libgcc_s depending on the system revision) and the DWARF unwind
2432 data for sigtramp have different ideas about register numbering,
2433 causing rbx and rdx to be transposed. */
2434 ucontext_t *uc = (ucontext_t *)ucontext;
2435 unsigned long t = uc->uc_mcontext->__ss.__rbx;
2437 uc->uc_mcontext->__ss.__rbx = uc->uc_mcontext->__ss.__rdx;
2438 uc->uc_mcontext->__ss.__rdx = t;
2440 #elif defined(__arm64__)
2441 /* Even though the CFI is marked as a signal frame, we need this. */
2442 ucontext_t *uc = (ucontext_t *)ucontext;
2443 uc->uc_mcontext->__ss.__pc++;
2444 #endif
2447 static void
2448 __gnat_map_signal (int sig, siginfo_t *si, void *mcontext ATTRIBUTE_UNUSED)
2450 struct Exception_Data *exception;
2451 const char *msg;
2453 switch (sig)
2455 case SIGSEGV:
2456 case SIGBUS:
2457 if (__gnat_is_stack_guard ((unsigned long)si->si_addr))
2459 #ifdef __arm64__
2460 /* ??? This is a kludge to make stack checking work. The problem is
2461 that the trampoline doesn't restore LR and, consequently, doesn't
2462 make it possible to unwind past an interrupted frame which hasn"t
2463 saved LR on the stack yet. Therefore, for probes in the prologue
2464 (32-bit probes as opposed to standard 64-bit probes), we make the
2465 unwinder skip the not-yet-established frame altogether. */
2466 mcontext_t mc = (mcontext_t)mcontext;
2467 if (!(*(unsigned int *)(mc->__ss.__pc-1) & ((unsigned int)1 << 30)))
2468 mc->__ss.__pc = mc->__ss.__lr;
2469 #endif
2470 exception = &storage_error;
2471 msg = "stack overflow";
2473 else
2475 exception = &constraint_error;
2476 msg = "erroneous memory access";
2479 /* Reset the use of alt stack, so that the alt stack will be used
2480 for the next signal delivery.
2481 The stack can't be used in case of stack checking. */
2482 syscall (SYS_sigreturn, NULL, UC_RESET_ALT_STACK);
2483 break;
2485 case SIGFPE:
2486 exception = &constraint_error;
2487 msg = "SIGFPE";
2488 break;
2490 default:
2491 exception = &program_error;
2492 msg = "unhandled signal";
2495 Raise_From_Signal_Handler (exception, msg);
2498 static void
2499 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
2501 __gnat_adjust_context_for_raise (sig, ucontext);
2503 /* The Darwin libc comes with a signal trampoline, except for ARM64. */
2504 #ifdef __arm64__
2505 __gnat_sigtramp (sig, (void *)si, ucontext,
2506 (__sigtramphandler_t *)&__gnat_map_signal);
2507 #else
2508 __gnat_map_signal (sig, si, ucontext);
2509 #endif
2512 void
2513 __gnat_install_handler (void)
2515 struct sigaction act;
2517 /* Set up signal handler to map synchronous signals to appropriate
2518 exceptions. Make sure that the handler isn't interrupted by another
2519 signal that might cause a scheduling event! Also setup an alternate
2520 stack region for the handler execution so that stack overflows can be
2521 handled properly, avoiding a SEGV generation from stack usage by the
2522 handler itself (and it is required by Darwin). */
2524 stack_t stack;
2525 stack.ss_sp = __gnat_alternate_stack;
2526 stack.ss_size = sizeof (__gnat_alternate_stack);
2527 stack.ss_flags = 0;
2528 sigaltstack (&stack, NULL);
2530 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2531 act.sa_sigaction = __gnat_error_handler;
2532 sigemptyset (&act.sa_mask);
2534 /* Do not install handlers if interrupt state is "System". */
2535 if (__gnat_get_interrupt_state (SIGABRT) != 's')
2536 sigaction (SIGABRT, &act, NULL);
2537 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2538 sigaction (SIGFPE, &act, NULL);
2539 if (__gnat_get_interrupt_state (SIGILL) != 's')
2540 sigaction (SIGILL, &act, NULL);
2542 act.sa_flags |= SA_ONSTACK;
2543 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2544 sigaction (SIGSEGV, &act, NULL);
2545 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2546 sigaction (SIGBUS, &act, NULL);
2548 __gnat_handler_installed = 1;
2551 #elif defined(__QNX__)
2553 /***************/
2554 /* QNX Section */
2555 /***************/
2557 #include <signal.h>
2558 #include <unistd.h>
2559 #include <string.h>
2560 #include <errno.h>
2561 #include "sigtramp.h"
2563 #if defined (__ARMEL__) && !defined (__aarch64__)
2565 /* ARM-QNX case with arm unwinding exceptions */
2566 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2568 #include <ucontext.h>
2569 #include <arm/cpu.h>
2570 #include <stdint.h>
2572 void
2573 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2574 void *sc ATTRIBUTE_UNUSED)
2576 /* In case of ARM exceptions, the registers context have the PC pointing
2577 to the instruction that raised the signal. However the unwinder expects
2578 the instruction to be in the range [PC+2,PC+3]. */
2579 uintptr_t *pc_addr;
2580 mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext;
2581 pc_addr = (uintptr_t *)&mcontext->cpu.gpr [ARM_REG_PC];
2583 /* ARM Bump has to be an even number because of odd/even architecture. */
2584 *pc_addr += 2;
2585 #ifdef __thumb2__
2586 /* For thumb, the return address must have the low order bit set, otherwise
2587 the unwinder will reset to "arm" mode upon return. As long as the
2588 compilation unit containing the landing pad is compiled with the same
2589 mode (arm vs thumb) as the signaling compilation unit, this works. */
2590 if (mcontext->cpu.spsr & ARM_CPSR_T)
2591 *pc_addr += 1;
2592 #endif
2594 #endif /* ARMEL */
2596 void
2597 __gnat_map_signal (int sig,
2598 siginfo_t *si ATTRIBUTE_UNUSED,
2599 void *mcontext ATTRIBUTE_UNUSED)
2601 struct Exception_Data *exception;
2602 const char *msg;
2604 switch(sig)
2606 case SIGFPE:
2607 exception = &constraint_error;
2608 msg = "SIGFPE";
2609 break;
2610 case SIGILL:
2611 exception = &constraint_error;
2612 msg = "SIGILL";
2613 break;
2614 case SIGSEGV:
2615 exception = &storage_error;
2616 msg = "stack overflow or erroneous memory access";
2617 break;
2618 case SIGBUS:
2619 exception = &constraint_error;
2620 msg = "SIGBUS";
2621 break;
2622 default:
2623 exception = &program_error;
2624 msg = "unhandled signal";
2627 Raise_From_Signal_Handler (exception, msg);
2630 static void
2631 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
2633 #ifdef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2634 /* We need to sometimes to adjust the PC in case of signals so that it
2635 doesn't reference the exception that actually raised the signal but the
2636 instruction before it. */
2637 __gnat_adjust_context_for_raise (sig, ucontext);
2638 #endif
2640 __gnat_sigtramp (sig, (void *) si, (void *) ucontext,
2641 (__sigtramphandler_t *)&__gnat_map_signal);
2644 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
2645 /* sigaltstack is currently not supported by QNX7 */
2646 char __gnat_alternate_stack[0];
2648 void
2649 __gnat_install_handler (void)
2651 struct sigaction act;
2652 int err;
2654 act.sa_sigaction = __gnat_error_handler;
2655 act.sa_flags = SA_NODEFER | SA_SIGINFO;
2656 sigemptyset (&act.sa_mask);
2658 /* Do not install handlers if interrupt state is "System" */
2659 if (__gnat_get_interrupt_state (SIGFPE) != 's') {
2660 err = sigaction (SIGFPE, &act, NULL);
2661 if (err == -1) {
2662 err = errno;
2663 perror ("error while attaching SIGFPE");
2664 perror (strerror (err));
2667 if (__gnat_get_interrupt_state (SIGILL) != 's') {
2668 err = sigaction (SIGILL, &act, NULL);
2669 if (err == -1) {
2670 err = errno;
2671 perror ("error while attaching SIGILL");
2672 perror (strerror (err));
2675 if (__gnat_get_interrupt_state (SIGSEGV) != 's') {
2676 err = sigaction (SIGSEGV, &act, NULL);
2677 if (err == -1) {
2678 err = errno;
2679 perror ("error while attaching SIGSEGV");
2680 perror (strerror (err));
2683 if (__gnat_get_interrupt_state (SIGBUS) != 's') {
2684 err = sigaction (SIGBUS, &act, NULL);
2685 if (err == -1) {
2686 err = errno;
2687 perror ("error while attaching SIGBUS");
2688 perror (strerror (err));
2691 __gnat_handler_installed = 1;
2694 /*****************/
2695 /* RTEMS Section */
2696 /*****************/
2698 #elif defined(__rtems__)
2700 #include <signal.h>
2701 #include <unistd.h>
2703 static void
2704 __gnat_error_handler (int sig)
2706 struct Exception_Data *exception;
2707 const char *msg;
2709 switch(sig)
2711 case SIGFPE:
2712 exception = &constraint_error;
2713 msg = "SIGFPE";
2714 break;
2715 case SIGILL:
2716 exception = &constraint_error;
2717 msg = "SIGILL";
2718 break;
2719 case SIGSEGV:
2720 exception = &storage_error;
2721 msg = "erroneous memory access";
2722 break;
2723 case SIGBUS:
2724 exception = &constraint_error;
2725 msg = "SIGBUS";
2726 break;
2727 default:
2728 exception = &program_error;
2729 msg = "unhandled signal";
2732 Raise_From_Signal_Handler (exception, msg);
2735 void
2736 __gnat_install_handler (void)
2738 struct sigaction act;
2740 act.sa_handler = __gnat_error_handler;
2741 sigemptyset (&act.sa_mask);
2743 /* Do not install handlers if interrupt state is "System". */
2744 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2745 sigaction (SIGFPE, &act, NULL);
2746 if (__gnat_get_interrupt_state (SIGILL) != 's')
2747 sigaction (SIGILL, &act, NULL);
2748 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2749 sigaction (SIGSEGV, &act, NULL);
2750 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2751 sigaction (SIGBUS, &act, NULL);
2753 __gnat_handler_installed = 1;
2756 #elif defined (__DJGPP__)
2758 void
2759 __gnat_install_handler ()
2761 __gnat_handler_installed = 1;
2764 #elif defined(__ANDROID__)
2766 /*******************/
2767 /* Android Section */
2768 /*******************/
2770 #include <signal.h>
2771 #include <sys/ucontext.h>
2772 #include "sigtramp.h"
2774 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2776 void
2777 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
2779 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
2781 /* ARM Bump has to be an even number because of odd/even architecture. */
2782 ((mcontext_t *) mcontext)->arm_pc += 2;
2785 static void
2786 __gnat_map_signal (int sig,
2787 siginfo_t *si ATTRIBUTE_UNUSED,
2788 void *mcontext ATTRIBUTE_UNUSED)
2790 struct Exception_Data *exception;
2791 const char *msg;
2793 switch (sig)
2795 case SIGSEGV:
2796 exception = &storage_error;
2797 msg = "stack overflow or erroneous memory access";
2798 break;
2800 case SIGBUS:
2801 exception = &constraint_error;
2802 msg = "SIGBUS";
2803 break;
2805 case SIGFPE:
2806 exception = &constraint_error;
2807 msg = "SIGFPE";
2808 break;
2810 default:
2811 exception = &program_error;
2812 msg = "unhandled signal";
2815 Raise_From_Signal_Handler (exception, msg);
2818 static void
2819 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
2821 __gnat_adjust_context_for_raise (sig, ucontext);
2823 __gnat_sigtramp (sig, (void *) si, (void *) ucontext,
2824 (__sigtramphandler_t *)&__gnat_map_signal);
2827 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
2828 char __gnat_alternate_stack[16 * 1024];
2830 void
2831 __gnat_install_handler (void)
2833 struct sigaction act;
2835 /* Set up signal handler to map synchronous signals to appropriate
2836 exceptions. Make sure that the handler isn't interrupted by another
2837 signal that might cause a scheduling event! Also setup an alternate
2838 stack region for the handler execution so that stack overflows can be
2839 handled properly, avoiding a SEGV generation from stack usage by the
2840 handler itself. */
2842 stack_t stack;
2843 stack.ss_sp = __gnat_alternate_stack;
2844 stack.ss_size = sizeof (__gnat_alternate_stack);
2845 stack.ss_flags = 0;
2846 sigaltstack (&stack, NULL);
2848 act.sa_sigaction = __gnat_error_handler;
2849 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2850 sigemptyset (&act.sa_mask);
2852 sigaction (SIGABRT, &act, NULL);
2853 sigaction (SIGFPE, &act, NULL);
2854 sigaction (SIGILL, &act, NULL);
2855 sigaction (SIGBUS, &act, NULL);
2856 act.sa_flags |= SA_ONSTACK;
2857 sigaction (SIGSEGV, &act, NULL);
2859 __gnat_handler_installed = 1;
2862 #else
2864 /* For all other versions of GNAT, the handler does nothing. */
2866 /*******************/
2867 /* Default Section */
2868 /*******************/
2870 void
2871 __gnat_install_handler (void)
2873 __gnat_handler_installed = 1;
2876 #endif
2878 /*********************/
2879 /* __gnat_init_float */
2880 /*********************/
2882 #if defined (_WIN32) || defined (__INTERIX) || defined (__linux__) \
2883 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
2884 || defined (__OpenBSD__) || defined (__DragonFly__) || defined(__QNX__)
2886 #define HAVE_GNAT_INIT_FLOAT
2888 void
2889 __gnat_init_float (void)
2891 #if defined (__i386__) || defined (__x86_64__)
2892 /* This is used to properly initialize the FPU to 64-bit precision on an x86
2893 for each process thread and also for floating-point I/O. */
2894 asm ("finit");
2895 #endif
2897 #endif
2899 #ifndef HAVE_GNAT_INIT_FLOAT
2901 /* All targets without a specific __gnat_init_float will use an empty one. */
2902 void
2903 __gnat_init_float (void)
2906 #endif
2908 /***********************************/
2909 /* __gnat_adjust_context_for_raise */
2910 /***********************************/
2912 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2914 /* All targets without a specific version will use an empty one. */
2916 /* Given UCONTEXT a pointer to a context structure received by a signal
2917 handler for SIGNO, perform the necessary adjustments to let the handler
2918 raise an exception. Calls to this routine are not conditioned by the
2919 propagation scheme in use. */
2921 void
2922 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2923 void *ucontext ATTRIBUTE_UNUSED)
2925 /* We used to compensate here for the raised from call vs raised from signal
2926 exception discrepancy with the GCC ZCX scheme, but this now can be dealt
2927 with generically in the unwinder (see GCC PR other/26208). This however
2928 requires the use of the _Unwind_GetIPInfo routine in raise-gcc.c, which
2929 is predicated on the definition of HAVE_GETIPINFO at compile time. Only
2930 the VMS ports still do the compensation described in the few lines below.
2932 *** Call vs signal exception discrepancy with GCC ZCX scheme ***
2934 The GCC unwinder expects to be dealing with call return addresses, since
2935 this is the "nominal" case of what we retrieve while unwinding a regular
2936 call chain.
2938 To evaluate if a handler applies at some point identified by a return
2939 address, the propagation engine needs to determine what region the
2940 corresponding call instruction pertains to. Because the return address
2941 may not be attached to the same region as the call, the unwinder always
2942 subtracts "some" amount from a return address to search the region
2943 tables, amount chosen to ensure that the resulting address is inside the
2944 call instruction.
2946 When we raise an exception from a signal handler, e.g. to transform a
2947 SIGSEGV into Storage_Error, things need to appear as if the signal
2948 handler had been "called" by the instruction which triggered the signal,
2949 so that exception handlers that apply there are considered. What the
2950 unwinder will retrieve as the return address from the signal handler is
2951 what it will find as the faulting instruction address in the signal
2952 context pushed by the kernel. Leaving this address untouched looses, if
2953 the triggering instruction happens to be the very first of a region, as
2954 the later adjustments performed by the unwinder would yield an address
2955 outside that region. We need to compensate for the unwinder adjustments
2956 at some point, and this is what this routine is expected to do.
2958 signo is passed because on some targets for some signals the PC in
2959 context points to the instruction after the faulting one, in which case
2960 the unwinder adjustment is still desired. */
2963 #endif
2965 #ifdef __cplusplus
2967 #endif