cfgexpand: Update partition size when merging variables
[official-gcc.git] / gcc / ada / init.c
blob67ea4dc25798bdeeefe961ec6a5306eb063ea28e
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * I N I T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 1992-2019, 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 char *, 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 Raise_From_Signal_Handler is not available. */
93 #ifdef CERT
94 #define Raise_From_Signal_Handler \
95 __gnat_raise_exception
96 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
97 #else
98 #define Raise_From_Signal_Handler \
99 ada__exceptions__raise_from_signal_handler
100 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
101 #endif
103 /* Global values computed by the binder. Note that these variables are
104 declared here, not in the binder file, to avoid having unresolved
105 references in the shared libgnat. */
106 int __gl_main_priority = -1;
107 int __gl_main_cpu = -1;
108 int __gl_time_slice_val = -1;
109 char __gl_wc_encoding = 'n';
110 char __gl_locking_policy = ' ';
111 char __gl_queuing_policy = ' ';
112 char __gl_task_dispatching_policy = ' ';
113 char *__gl_priority_specific_dispatching = 0;
114 int __gl_num_specific_dispatching = 0;
115 char *__gl_interrupt_states = 0;
116 int __gl_num_interrupt_states = 0;
117 int __gl_unreserve_all_interrupts = 0;
118 int __gl_exception_tracebacks = 0;
119 int __gl_exception_tracebacks_symbolic = 0;
120 int __gl_detect_blocking = 0;
121 int __gl_default_stack_size = -1;
122 int __gl_leap_seconds_support = 0;
123 int __gl_canonical_streams = 0;
124 char *__gl_bind_env_addr = NULL;
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 /* FIXME: 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 /* FIXME: 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 It must be larger than MINSIGSTKSZ and hopefully near 2 * SIGSTKSZ. */
583 # if 16 * 1024 < MINSIGSTKSZ
584 # error "__gnat_alternate_stack too small"
585 # endif
586 char __gnat_alternate_stack[16 * 1024];
587 #endif
589 #ifdef __XENO__
590 #include <sys/mman.h>
591 #include <native/task.h>
593 RT_TASK main_task;
594 #endif
596 void
597 __gnat_install_handler (void)
599 struct sigaction act;
601 #ifdef __XENO__
602 int prio;
604 if (__gl_main_priority == -1)
605 prio = 49;
606 else
607 prio = __gl_main_priority;
609 /* Avoid memory swapping for this program */
611 mlockall (MCL_CURRENT|MCL_FUTURE);
613 /* Turn the current Linux task into a native Xenomai task */
615 rt_task_shadow (&main_task, "environment_task", prio, T_FPU);
616 #endif
618 /* Set up signal handler to map synchronous signals to appropriate
619 exceptions. Make sure that the handler isn't interrupted by another
620 signal that might cause a scheduling event! Also setup an alternate
621 stack region for the handler execution so that stack overflows can be
622 handled properly, avoiding a SEGV generation from stack usage by the
623 handler itself. */
625 act.sa_sigaction = __gnat_error_handler;
626 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
627 sigemptyset (&act.sa_mask);
629 /* Do not install handlers if interrupt state is "System". */
630 if (__gnat_get_interrupt_state (SIGABRT) != 's')
631 sigaction (SIGABRT, &act, NULL);
632 if (__gnat_get_interrupt_state (SIGFPE) != 's')
633 sigaction (SIGFPE, &act, NULL);
634 if (__gnat_get_interrupt_state (SIGILL) != 's')
635 sigaction (SIGILL, &act, NULL);
636 if (__gnat_get_interrupt_state (SIGBUS) != 's')
637 sigaction (SIGBUS, &act, NULL);
638 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
640 #ifdef HAVE_GNAT_ALTERNATE_STACK
641 /* Setup an alternate stack region for the handler execution so that
642 stack overflows can be handled properly, avoiding a SEGV generation
643 from stack usage by the handler itself. */
644 stack_t stack;
646 stack.ss_sp = __gnat_alternate_stack;
647 stack.ss_size = sizeof (__gnat_alternate_stack);
648 stack.ss_flags = 0;
649 sigaltstack (&stack, NULL);
651 act.sa_flags |= SA_ONSTACK;
652 #endif
653 sigaction (SIGSEGV, &act, NULL);
656 __gnat_handler_installed = 1;
659 /*******************/
660 /* LynxOS Section */
661 /*******************/
663 #elif defined (__Lynx__)
665 #include <signal.h>
666 #include <unistd.h>
668 static void
669 __gnat_error_handler (int sig)
671 struct Exception_Data *exception;
672 const char *msg;
674 switch(sig)
676 case SIGFPE:
677 exception = &constraint_error;
678 msg = "SIGFPE";
679 break;
680 case SIGILL:
681 exception = &constraint_error;
682 msg = "SIGILL";
683 break;
684 case SIGSEGV:
685 exception = &storage_error;
686 msg = "stack overflow or erroneous memory access";
687 break;
688 case SIGBUS:
689 exception = &constraint_error;
690 msg = "SIGBUS";
691 break;
692 default:
693 exception = &program_error;
694 msg = "unhandled signal";
697 Raise_From_Signal_Handler (exception, msg);
700 void
701 __gnat_install_handler (void)
703 struct sigaction act;
705 act.sa_handler = __gnat_error_handler;
706 act.sa_flags = 0x0;
707 sigemptyset (&act.sa_mask);
709 /* Do not install handlers if interrupt state is "System". */
710 if (__gnat_get_interrupt_state (SIGFPE) != 's')
711 sigaction (SIGFPE, &act, NULL);
712 if (__gnat_get_interrupt_state (SIGILL) != 's')
713 sigaction (SIGILL, &act, NULL);
714 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
715 sigaction (SIGSEGV, &act, NULL);
716 if (__gnat_get_interrupt_state (SIGBUS) != 's')
717 sigaction (SIGBUS, &act, NULL);
719 __gnat_handler_installed = 1;
722 /*******************/
723 /* Solaris Section */
724 /*******************/
726 #elif defined (__sun__) && !defined (__vxworks)
728 #include <signal.h>
729 #include <siginfo.h>
730 #include <sys/ucontext.h>
731 #include <sys/regset.h>
733 static void
734 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext ATTRIBUTE_UNUSED)
736 struct Exception_Data *exception;
737 static int recurse = 0;
738 const char *msg;
740 switch (sig)
742 case SIGSEGV:
743 /* If the problem was permissions, this is a constraint error.
744 Likewise if the failing address isn't maximally aligned or if
745 we've recursed.
747 ??? Using a static variable here isn't task-safe, but it's
748 much too hard to do anything else and we're just determining
749 which exception to raise. */
750 if (si->si_code == SEGV_ACCERR
751 || (long) si->si_addr == 0
752 || (((long) si->si_addr) & 3) != 0
753 || recurse)
755 exception = &constraint_error;
756 msg = "SIGSEGV";
758 else
760 /* See if the page before the faulting page is accessible. Do that
761 by trying to access it. We'd like to simply try to access
762 4096 + the faulting address, but it's not guaranteed to be
763 the actual address, just to be on the same page. */
764 recurse++;
765 ((volatile char *)
766 ((long) si->si_addr & - getpagesize ()))[getpagesize ()];
767 exception = &storage_error;
768 msg = "stack overflow or erroneous memory access";
770 break;
772 case SIGBUS:
773 exception = &program_error;
774 msg = "SIGBUS";
775 break;
777 case SIGFPE:
778 exception = &constraint_error;
779 msg = "SIGFPE";
780 break;
782 default:
783 exception = &program_error;
784 msg = "unhandled signal";
787 recurse = 0;
788 Raise_From_Signal_Handler (exception, msg);
791 void
792 __gnat_install_handler (void)
794 struct sigaction act;
796 /* Set up signal handler to map synchronous signals to appropriate
797 exceptions. Make sure that the handler isn't interrupted by another
798 signal that might cause a scheduling event! */
800 act.sa_sigaction = __gnat_error_handler;
801 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
802 sigemptyset (&act.sa_mask);
804 /* Do not install handlers if interrupt state is "System". */
805 if (__gnat_get_interrupt_state (SIGABRT) != 's')
806 sigaction (SIGABRT, &act, NULL);
807 if (__gnat_get_interrupt_state (SIGFPE) != 's')
808 sigaction (SIGFPE, &act, NULL);
809 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
810 sigaction (SIGSEGV, &act, NULL);
811 if (__gnat_get_interrupt_state (SIGBUS) != 's')
812 sigaction (SIGBUS, &act, NULL);
814 __gnat_handler_installed = 1;
817 /***************/
818 /* VMS Section */
819 /***************/
821 #elif defined (VMS)
823 /* Routine called from binder to override default feature values. */
824 void __gnat_set_features (void);
825 int __gnat_features_set = 0;
826 void (*__gnat_ctrl_c_handler) (void) = 0;
828 #ifdef __IA64
829 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
830 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
831 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
832 #else
833 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
834 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
835 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
836 #endif
838 /* Masks for facility identification. */
839 #define FAC_MASK 0x0fff0000
840 #define DECADA_M_FACILITY 0x00310000
842 /* Define macro symbols for the VMS conditions that become Ada exceptions.
843 It would be better to just include <ssdef.h> */
845 #define SS$_CONTINUE 1
846 #define SS$_ACCVIO 12
847 #define SS$_HPARITH 1284
848 #define SS$_INTDIV 1156
849 #define SS$_STKOVF 1364
850 #define SS$_CONTROLC 1617
851 #define SS$_RESIGNAL 2328
853 #define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
855 /* The following codes must be resignalled, and not handled here. */
857 /* These codes are in standard message libraries. */
858 extern int C$_SIGKILL;
859 extern int C$_SIGINT;
860 extern int SS$_DEBUG;
861 extern int LIB$_KEYNOTFOU;
862 extern int LIB$_ACTIMAGE;
864 /* These codes are non standard, which is to say the author is
865 not sure if they are defined in the standard message libraries
866 so keep them as macros for now. */
867 #define RDB$_STREAM_EOF 20480426
868 #define FDL$_UNPRIKW 11829410
869 #define CMA$_EXIT_THREAD 4227492
871 struct cond_sigargs
873 unsigned int sigarg;
874 unsigned int sigargval;
877 struct cond_subtests
879 unsigned int num;
880 const struct cond_sigargs sigargs[];
883 struct cond_except
885 unsigned int cond;
886 const struct Exception_Data *except;
887 unsigned int needs_adjust; /* 1 = adjust PC, 0 = no adjust */
888 const struct cond_subtests *subtests;
891 struct descriptor_s
893 unsigned short len, mbz;
894 __char_ptr32 adr;
897 /* Conditions that don't have an Ada exception counterpart must raise
898 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
899 referenced by user programs, not the compiler or tools. Hence the
900 #ifdef IN_RTS. */
902 #ifdef IN_RTS
904 #define Status_Error ada__io_exceptions__status_error
905 extern struct Exception_Data Status_Error;
907 #define Mode_Error ada__io_exceptions__mode_error
908 extern struct Exception_Data Mode_Error;
910 #define Name_Error ada__io_exceptions__name_error
911 extern struct Exception_Data Name_Error;
913 #define Use_Error ada__io_exceptions__use_error
914 extern struct Exception_Data Use_Error;
916 #define Device_Error ada__io_exceptions__device_error
917 extern struct Exception_Data Device_Error;
919 #define End_Error ada__io_exceptions__end_error
920 extern struct Exception_Data End_Error;
922 #define Data_Error ada__io_exceptions__data_error
923 extern struct Exception_Data Data_Error;
925 #define Layout_Error ada__io_exceptions__layout_error
926 extern struct Exception_Data Layout_Error;
928 #define Non_Ada_Error system__aux_dec__non_ada_error
929 extern struct Exception_Data Non_Ada_Error;
931 #define Coded_Exception system__vms_exception_table__coded_exception
932 extern struct Exception_Data *Coded_Exception (void *);
934 #define Base_Code_In system__vms_exception_table__base_code_in
935 extern void *Base_Code_In (void *);
937 /* DEC Ada exceptions are not defined in a header file, so they
938 must be declared. */
940 #define ADA$_ALREADY_OPEN 0x0031a594
941 #define ADA$_CONSTRAINT_ERRO 0x00318324
942 #define ADA$_DATA_ERROR 0x003192c4
943 #define ADA$_DEVICE_ERROR 0x003195e4
944 #define ADA$_END_ERROR 0x00319904
945 #define ADA$_FAC_MODE_MISMAT 0x0031a8b3
946 #define ADA$_IOSYSFAILED 0x0031af04
947 #define ADA$_KEYSIZERR 0x0031aa3c
948 #define ADA$_KEY_MISMATCH 0x0031a8e3
949 #define ADA$_LAYOUT_ERROR 0x00319c24
950 #define ADA$_LINEXCMRS 0x0031a8f3
951 #define ADA$_MAXLINEXC 0x0031a8eb
952 #define ADA$_MODE_ERROR 0x00319f44
953 #define ADA$_MRN_MISMATCH 0x0031a8db
954 #define ADA$_MRS_MISMATCH 0x0031a8d3
955 #define ADA$_NAME_ERROR 0x0031a264
956 #define ADA$_NOT_OPEN 0x0031a58c
957 #define ADA$_ORG_MISMATCH 0x0031a8bb
958 #define ADA$_PROGRAM_ERROR 0x00318964
959 #define ADA$_RAT_MISMATCH 0x0031a8cb
960 #define ADA$_RFM_MISMATCH 0x0031a8c3
961 #define ADA$_STAOVF 0x00318cac
962 #define ADA$_STATUS_ERROR 0x0031a584
963 #define ADA$_STORAGE_ERROR 0x00318c84
964 #define ADA$_UNSUPPORTED 0x0031a8ab
965 #define ADA$_USE_ERROR 0x0031a8a4
967 /* DEC Ada specific conditions. */
968 static const struct cond_except dec_ada_cond_except_table [] =
970 {ADA$_PROGRAM_ERROR, &program_error, 0, 0},
971 {ADA$_USE_ERROR, &Use_Error, 0, 0},
972 {ADA$_KEYSIZERR, &program_error, 0, 0},
973 {ADA$_STAOVF, &storage_error, 0, 0},
974 {ADA$_CONSTRAINT_ERRO, &constraint_error, 0, 0},
975 {ADA$_IOSYSFAILED, &Device_Error, 0, 0},
976 {ADA$_LAYOUT_ERROR, &Layout_Error, 0, 0},
977 {ADA$_STORAGE_ERROR, &storage_error, 0, 0},
978 {ADA$_DATA_ERROR, &Data_Error, 0, 0},
979 {ADA$_DEVICE_ERROR, &Device_Error, 0, 0},
980 {ADA$_END_ERROR, &End_Error, 0, 0},
981 {ADA$_MODE_ERROR, &Mode_Error, 0, 0},
982 {ADA$_NAME_ERROR, &Name_Error, 0, 0},
983 {ADA$_STATUS_ERROR, &Status_Error, 0, 0},
984 {ADA$_NOT_OPEN, &Use_Error, 0, 0},
985 {ADA$_ALREADY_OPEN, &Use_Error, 0, 0},
986 {ADA$_USE_ERROR, &Use_Error, 0, 0},
987 {ADA$_UNSUPPORTED, &Use_Error, 0, 0},
988 {ADA$_FAC_MODE_MISMAT, &Use_Error, 0, 0},
989 {ADA$_ORG_MISMATCH, &Use_Error, 0, 0},
990 {ADA$_RFM_MISMATCH, &Use_Error, 0, 0},
991 {ADA$_RAT_MISMATCH, &Use_Error, 0, 0},
992 {ADA$_MRS_MISMATCH, &Use_Error, 0, 0},
993 {ADA$_MRN_MISMATCH, &Use_Error, 0, 0},
994 {ADA$_KEY_MISMATCH, &Use_Error, 0, 0},
995 {ADA$_MAXLINEXC, &constraint_error, 0, 0},
996 {ADA$_LINEXCMRS, &constraint_error, 0, 0},
998 #if 0
999 /* Already handled by a pragma Import_Exception
1000 in Aux_IO_Exceptions */
1001 {ADA$_LOCK_ERROR, &Lock_Error, 0, 0},
1002 {ADA$_EXISTENCE_ERROR, &Existence_Error, 0, 0},
1003 {ADA$_KEY_ERROR, &Key_Error, 0, 0},
1004 #endif
1006 {0, 0, 0, 0}
1009 #endif /* IN_RTS */
1011 /* Non-DEC Ada specific conditions that map to Ada exceptions. */
1013 /* Subtest for ACCVIO Constraint_Error, kept for compatibility,
1014 in hindsight should have just made ACCVIO == Storage_Error. */
1015 #define ACCVIO_VIRTUAL_ADDR 3
1016 static const struct cond_subtests accvio_c_e =
1017 {1, /* number of subtests below */
1019 { ACCVIO_VIRTUAL_ADDR, 0 }
1023 /* Macro flag to adjust PC which gets off by one for some conditions,
1024 not sure if this is reliably true, PC could be off by more for
1025 HPARITH for example, unless a trapb is inserted. */
1026 #define NEEDS_ADJUST 1
1028 static const struct cond_except system_cond_except_table [] =
1030 {MTH$_FLOOVEMAT, &constraint_error, 0, 0},
1031 {SS$_INTDIV, &constraint_error, 0, 0},
1032 {SS$_HPARITH, &constraint_error, NEEDS_ADJUST, 0},
1033 {SS$_ACCVIO, &constraint_error, NEEDS_ADJUST, &accvio_c_e},
1034 {SS$_ACCVIO, &storage_error, NEEDS_ADJUST, 0},
1035 {SS$_STKOVF, &storage_error, NEEDS_ADJUST, 0},
1036 {0, 0, 0, 0}
1039 /* To deal with VMS conditions and their mapping to Ada exceptions,
1040 the __gnat_error_handler routine below is installed as an exception
1041 vector having precedence over DEC frame handlers. Some conditions
1042 still need to be handled by such handlers, however, in which case
1043 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
1044 instance the use of a third party library compiled with DECAda and
1045 performing its own exception handling internally.
1047 To allow some user-level flexibility, which conditions should be
1048 resignaled is controlled by a predicate function, provided with the
1049 condition value and returning a boolean indication stating whether
1050 this condition should be resignaled or not.
1052 That predicate function is called indirectly, via a function pointer,
1053 by __gnat_error_handler, and changing that pointer is allowed to the
1054 user code by way of the __gnat_set_resignal_predicate interface.
1056 The user level function may then implement what it likes, including
1057 for instance the maintenance of a dynamic data structure if the set
1058 of to be resignalled conditions has to change over the program's
1059 lifetime.
1061 ??? This is not a perfect solution to deal with the possible
1062 interactions between the GNAT and the DECAda exception handling
1063 models and better (more general) schemes are studied. This is so
1064 just provided as a convenient workaround in the meantime, and
1065 should be use with caution since the implementation has been kept
1066 very simple. */
1068 typedef int resignal_predicate (int code);
1070 static const int * const cond_resignal_table [] =
1072 &C$_SIGKILL,
1073 (int *)CMA$_EXIT_THREAD,
1074 &SS$_DEBUG,
1075 &LIB$_KEYNOTFOU,
1076 &LIB$_ACTIMAGE,
1077 (int *) RDB$_STREAM_EOF,
1078 (int *) FDL$_UNPRIKW,
1082 static const int facility_resignal_table [] =
1084 0x1380000, /* RDB */
1085 0x2220000, /* SQL */
1089 /* Default GNAT predicate for resignaling conditions. */
1091 static int
1092 __gnat_default_resignal_p (int code)
1094 int i, iexcept;
1096 for (i = 0; facility_resignal_table [i]; i++)
1097 if ((code & FAC_MASK) == facility_resignal_table [i])
1098 return 1;
1100 for (i = 0, iexcept = 0;
1101 cond_resignal_table [i]
1102 && !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1103 i++);
1105 return iexcept;
1108 /* Static pointer to predicate that the __gnat_error_handler exception
1109 vector invokes to determine if it should resignal a condition. */
1111 static resignal_predicate *__gnat_resignal_p = __gnat_default_resignal_p;
1113 /* User interface to change the predicate pointer to PREDICATE. Reset to
1114 the default if PREDICATE is null. */
1116 void
1117 __gnat_set_resignal_predicate (resignal_predicate *predicate)
1119 if (predicate == NULL)
1120 __gnat_resignal_p = __gnat_default_resignal_p;
1121 else
1122 __gnat_resignal_p = predicate;
1125 /* Should match System.Parameters.Default_Exception_Msg_Max_Length. */
1126 #define Default_Exception_Msg_Max_Length 512
1128 /* Action routine for SYS$PUTMSG. There may be multiple
1129 conditions, each with text to be appended to MESSAGE
1130 and separated by line termination. */
1131 static int
1132 copy_msg (struct descriptor_s *msgdesc, char *message)
1134 int len = strlen (message);
1135 int copy_len;
1137 /* Check for buffer overflow and skip. */
1138 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1140 strcat (message, "\r\n");
1141 len += 2;
1144 /* Check for buffer overflow and truncate if necessary. */
1145 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1146 msgdesc->len :
1147 Default_Exception_Msg_Max_Length - 1 - len);
1148 strncpy (&message [len], msgdesc->adr, copy_len);
1149 message [len + copy_len] = 0;
1151 return 0;
1154 /* Scan TABLE for a match for the condition contained in SIGARGS,
1155 and return the entry, or the empty entry if no match found. */
1156 static const struct cond_except *
1157 scan_conditions ( int *sigargs, const struct cond_except *table [])
1159 int i;
1160 struct cond_except entry;
1162 /* Scan the exception condition table for a match and fetch
1163 the associated GNAT exception pointer. */
1164 for (i = 0; (*table) [i].cond; i++)
1166 unsigned int match = LIB$MATCH_COND (&sigargs [1], &(*table) [i].cond);
1167 const struct cond_subtests *subtests = (*table) [i].subtests;
1169 if (match)
1171 if (!subtests)
1173 return &(*table) [i];
1175 else
1177 unsigned int ii;
1178 int num = (*subtests).num;
1180 /* Perform subtests to differentiate exception. */
1181 for (ii = 0; ii < num; ii++)
1183 unsigned int arg = (*subtests).sigargs [ii].sigarg;
1184 unsigned int argval = (*subtests).sigargs [ii].sigargval;
1186 if (sigargs [arg] != argval)
1188 num = 0;
1189 break;
1193 /* All subtests passed. */
1194 if (num == (*subtests).num)
1195 return &(*table) [i];
1200 /* No match, return the null terminating entry. */
1201 return &(*table) [i];
1204 /* __gnat_handle_vms_condtition is both a frame based handler
1205 for the runtime, and an exception vector for the compiler. */
1206 long
1207 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1209 struct Exception_Data *exception = 0;
1210 unsigned int needs_adjust = 0;
1211 void *base_code;
1212 struct descriptor_s gnat_facility = {4, 0, "GNAT"};
1213 char message [Default_Exception_Msg_Max_Length];
1215 const char *msg = "";
1217 /* Check for conditions to resignal which aren't effected by pragma
1218 Import_Exception. */
1219 if (__gnat_resignal_p (sigargs [1]))
1220 return SS$_RESIGNAL;
1221 #ifndef IN_RTS
1222 /* toplev.c handles this for compiler. */
1223 if (sigargs [1] == SS$_HPARITH)
1224 return SS$_RESIGNAL;
1225 #endif
1227 #ifdef IN_RTS
1228 /* See if it's an imported exception. Beware that registered exceptions
1229 are bound to their base code, with the severity bits masked off. */
1230 base_code = Base_Code_In ((void *) sigargs[1]);
1231 exception = Coded_Exception (base_code);
1232 #endif
1234 if (exception == 0)
1235 #ifdef IN_RTS
1237 int i;
1238 struct cond_except cond;
1239 const struct cond_except *cond_table;
1240 const struct cond_except *cond_tables [] = {dec_ada_cond_except_table,
1241 system_cond_except_table,
1243 unsigned int ctrlc = SS$_CONTROLC;
1244 unsigned int *sigint = &C$_SIGINT;
1245 int ctrlc_match = LIB$MATCH_COND (&sigargs [1], &ctrlc);
1246 int sigint_match = LIB$MATCH_COND (&sigargs [1], &sigint);
1248 extern int SYS$DCLAST (void (*astadr)(), unsigned long long astprm,
1249 unsigned int acmode);
1251 /* If SS$_CONTROLC has been imported as an exception, it will take
1252 priority over a Ctrl/C handler. See above. SIGINT has a
1253 different condition value due to it's DECCCRTL roots and it's
1254 the condition that gets raised for a "kill -INT". */
1255 if ((ctrlc_match || sigint_match) && __gnat_ctrl_c_handler)
1257 SYS$DCLAST (__gnat_ctrl_c_handler, 0, 0);
1258 return SS$_CONTINUE;
1261 i = 0;
1262 while ((cond_table = cond_tables[i++]) && !exception)
1264 cond = *scan_conditions (sigargs, &cond_table);
1265 exception = (struct Exception_Data *) cond.except;
1268 if (exception)
1269 needs_adjust = cond.needs_adjust;
1270 else
1271 /* User programs expect Non_Ada_Error to be raised if no match,
1272 reference DEC Ada test CXCONDHAN. */
1273 exception = &Non_Ada_Error;
1275 #else
1277 /* Pretty much everything is just a program error in the compiler */
1278 exception = &program_error;
1280 #endif
1282 message[0] = 0;
1283 /* Subtract PC & PSL fields as per ABI for SYS$PUTMSG. */
1284 sigargs[0] -= 2;
1286 extern int SYS$PUTMSG (void *, int (*)(), void *, unsigned long long);
1288 /* If it was a DEC Ada specific condtiion, make it GNAT otherwise
1289 keep the old facility. */
1290 if ((sigargs [1] & FAC_MASK) == DECADA_M_FACILITY)
1291 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility,
1292 (unsigned long long ) message);
1293 else
1294 SYS$PUTMSG (sigargs, copy_msg, 0,
1295 (unsigned long long ) message);
1297 /* Add back PC & PSL fields as per ABI for SYS$PUTMSG. */
1298 sigargs[0] += 2;
1299 msg = message;
1301 if (needs_adjust)
1302 __gnat_adjust_context_for_raise (sigargs [1], (void *)mechargs);
1304 Raise_From_Signal_Handler (exception, msg);
1307 #if defined (IN_RTS) && defined (__IA64)
1308 /* Called only from adasigio.b32. This is a band aid to avoid going
1309 through the VMS signal handling code which results in a 0x8000 per
1310 handled exception memory leak in P2 space (see VMS source listing
1311 sys/lis/exception.lis) due to the allocation of working space that
1312 is expected to be deallocated upon return from the condition handler,
1313 which doesn't return in GNAT compiled code. */
1314 void
1315 GNAT$STOP (int *sigargs)
1317 /* Note that there are no mechargs. We rely on the fact that condtions
1318 raised from DEClib I/O do not require an "adjust". Also the count
1319 will be off by 2, since LIB$STOP didn't get a chance to add the
1320 PC and PSL fields, so we bump it so PUTMSG comes out right. */
1321 sigargs [0] += 2;
1322 __gnat_handle_vms_condition (sigargs, 0);
1324 #endif
1326 void
1327 __gnat_install_handler (void)
1329 long prvhnd ATTRIBUTE_UNUSED;
1331 #if !defined (IN_RTS)
1332 extern int SYS$SETEXV (unsigned int vector, int (*addres)(),
1333 unsigned int accmode, void *(*(prvhnd)));
1334 SYS$SETEXV (1, __gnat_handle_vms_condition, 3, &prvhnd);
1335 #endif
1337 __gnat_handler_installed = 1;
1340 /* __gnat_adjust_context_for_raise for Alpha - see comments along with the
1341 default version later in this file. */
1343 #if defined (IN_RTS) && defined (__alpha__)
1345 #include <vms/chfctxdef.h>
1346 #include <vms/chfdef.h>
1348 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1350 void
1351 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1353 if (signo == SS$_HPARITH)
1355 /* Sub one to the address of the instruction signaling the condition,
1356 located in the sigargs array. */
1358 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1359 CHF$SIGNAL_ARRAY * sigargs
1360 = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1362 int vcount = sigargs->chf$is_sig_args;
1363 int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1365 (*pc_slot)--;
1369 #endif
1371 /* __gnat_adjust_context_for_raise for ia64. */
1373 #if defined (IN_RTS) && defined (__IA64)
1375 #include <vms/chfctxdef.h>
1376 #include <vms/chfdef.h>
1378 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1380 typedef unsigned long long u64;
1382 void
1383 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1385 /* Add one to the address of the instruction signaling the condition,
1386 located in the 64bits sigargs array. */
1388 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1390 CHF64$SIGNAL_ARRAY *chfsig64
1391 = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1393 u64 * post_sigarray
1394 = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1396 u64 * ih_pc_loc = post_sigarray - 2;
1398 (*ih_pc_loc) ++;
1401 #endif
1403 /* Easier interface for LIB$GET_LOGICAL: put the equivalence of NAME into BUF,
1404 always NUL terminated. In case of error or if the result is longer than
1405 LEN (length of BUF) an empty string is written info BUF. */
1407 static void
1408 __gnat_vms_get_logical (const char *name, char *buf, int len)
1410 struct descriptor_s name_desc, result_desc;
1411 int status;
1412 unsigned short rlen;
1414 /* Build the descriptor for NAME. */
1415 name_desc.len = strlen (name);
1416 name_desc.mbz = 0;
1417 name_desc.adr = (char *)name;
1419 /* Build the descriptor for the result. */
1420 result_desc.len = len;
1421 result_desc.mbz = 0;
1422 result_desc.adr = buf;
1424 status = LIB$GET_LOGICAL (&name_desc, &result_desc, &rlen);
1426 if ((status & 1) == 1 && rlen < len)
1427 buf[rlen] = 0;
1428 else
1429 buf[0] = 0;
1432 /* Size of a page on ia64 and alpha VMS. */
1433 #define VMS_PAGESIZE 8192
1435 /* User mode. */
1436 #define PSL__C_USER 3
1438 /* No access. */
1439 #define PRT__C_NA 0
1441 /* Descending region. */
1442 #define VA__M_DESCEND 1
1444 /* Get by virtual address. */
1445 #define VA___REGSUM_BY_VA 1
1447 /* Memory region summary. */
1448 struct regsum
1450 unsigned long long q_region_id;
1451 unsigned int l_flags;
1452 unsigned int l_region_protection;
1453 void *pq_start_va;
1454 unsigned long long q_region_size;
1455 void *pq_first_free_va;
1458 extern int SYS$GET_REGION_INFO (unsigned int, unsigned long long *,
1459 void *, void *, unsigned int,
1460 void *, unsigned int *);
1461 extern int SYS$EXPREG_64 (unsigned long long *, unsigned long long,
1462 unsigned int, unsigned int, void **,
1463 unsigned long long *);
1464 extern int SYS$SETPRT_64 (void *, unsigned long long, unsigned int,
1465 unsigned int, void **, unsigned long long *,
1466 unsigned int *);
1468 /* Add a guard page in the memory region containing ADDR at ADDR +/- SIZE.
1469 (The sign depends on the kind of the memory region). */
1471 static int
1472 __gnat_set_stack_guard_page (void *addr, unsigned long size)
1474 int status;
1475 void *ret_va;
1476 unsigned long long ret_len;
1477 unsigned int ret_prot;
1478 void *start_va;
1479 unsigned long long length;
1480 unsigned int retlen;
1481 struct regsum buffer;
1483 /* Get the region for ADDR. */
1484 status = SYS$GET_REGION_INFO
1485 (VA___REGSUM_BY_VA, NULL, addr, NULL, sizeof (buffer), &buffer, &retlen);
1487 if ((status & 1) != 1)
1488 return -1;
1490 /* Extend the region. */
1491 status = SYS$EXPREG_64 (&buffer.q_region_id,
1492 size, 0, 0, &start_va, &length);
1494 if ((status & 1) != 1)
1495 return -1;
1497 /* Create a guard page. */
1498 if (!(buffer.l_flags & VA__M_DESCEND))
1499 start_va = (void *)((unsigned long long)start_va + length - VMS_PAGESIZE);
1501 status = SYS$SETPRT_64 (start_va, VMS_PAGESIZE, PSL__C_USER, PRT__C_NA,
1502 &ret_va, &ret_len, &ret_prot);
1504 if ((status & 1) != 1)
1505 return -1;
1506 return 0;
1509 /* Read logicals to limit the stack(s) size. */
1511 static void
1512 __gnat_set_stack_limit (void)
1514 #ifdef __ia64__
1515 void *sp;
1516 unsigned long size;
1517 char value[16];
1518 char *e;
1520 /* The main stack. */
1521 __gnat_vms_get_logical ("GNAT_STACK_SIZE", value, sizeof (value));
1522 size = strtoul (value, &e, 0);
1523 if (e > value && *e == 0)
1525 asm ("mov %0=sp" : "=r" (sp));
1526 __gnat_set_stack_guard_page (sp, size * 1024);
1529 /* The register stack. */
1530 __gnat_vms_get_logical ("GNAT_RBS_SIZE", value, sizeof (value));
1531 size = strtoul (value, &e, 0);
1532 if (e > value && *e == 0)
1534 asm ("mov %0=ar.bsp" : "=r" (sp));
1535 __gnat_set_stack_guard_page (sp, size * 1024);
1537 #endif
1540 #ifdef IN_RTS
1541 extern int SYS$IEEE_SET_FP_CONTROL (void *, void *, void *);
1542 #define K_TRUE 1
1543 #define __int64 long long
1544 #define __NEW_STARLET
1545 #include <vms/ieeedef.h>
1546 #endif
1548 /* Feature logical name and global variable address pair.
1549 If we ever add another feature logical to this list, the
1550 feature struct will need to be enhanced to take into account
1551 possible values for *gl_addr. */
1552 struct feature {
1553 const char *name;
1554 int *gl_addr;
1557 /* Default values for GNAT features set by environment or binder. */
1558 int __gl_heap_size = 64;
1560 /* Default float format is 'I' meaning IEEE. If gnatbind detetcts that a
1561 VAX Float format is specified, it will set this global variable to 'V'.
1562 Subsequently __gnat_set_features will test the variable and if set for
1563 VAX Float will call a Starlet function to enable trapping for invalid
1564 operation, drivide by zero, and overflow. This will prevent the VMS runtime
1565 (specifically OTS$CHECK_FP_MODE) from complaining about inconsistent
1566 floating point settings in a mixed language program. Ideally the setting
1567 would be determined at link time based on settings in the object files,
1568 however the VMS linker seems to take the setting from the first object
1569 in the link, e.g. pcrt0.o which is float representation neutral. */
1570 char __gl_float_format = 'I';
1572 /* Array feature logical names and global variable addresses. */
1573 static const struct feature features[] =
1575 {"GNAT$NO_MALLOC_64", &__gl_heap_size},
1576 {0, 0}
1579 void
1580 __gnat_set_features (void)
1582 int i;
1583 char buff[16];
1584 #ifdef IN_RTS
1585 IEEE clrmsk, setmsk, prvmsk;
1587 clrmsk.ieee$q_flags = 0LL;
1588 setmsk.ieee$q_flags = 0LL;
1589 #endif
1591 /* Loop through features array and test name for enable/disable. */
1592 for (i = 0; features[i].name; i++)
1594 __gnat_vms_get_logical (features[i].name, buff, sizeof (buff));
1596 if (strcmp (buff, "ENABLE") == 0
1597 || strcmp (buff, "TRUE") == 0
1598 || strcmp (buff, "1") == 0)
1599 *features[i].gl_addr = 32;
1600 else if (strcmp (buff, "DISABLE") == 0
1601 || strcmp (buff, "FALSE") == 0
1602 || strcmp (buff, "0") == 0)
1603 *features[i].gl_addr = 64;
1606 /* Features to artificially limit the stack size. */
1607 __gnat_set_stack_limit ();
1609 #ifdef IN_RTS
1610 if (__gl_float_format == 'V')
1612 setmsk.ieee$v_trap_enable_inv = K_TRUE;
1613 setmsk.ieee$v_trap_enable_dze = K_TRUE;
1614 setmsk.ieee$v_trap_enable_ovf = K_TRUE;
1615 SYS$IEEE_SET_FP_CONTROL (&clrmsk, &setmsk, &prvmsk);
1617 #endif
1619 __gnat_features_set = 1;
1622 /* Return true if the VMS version is 7.x. */
1624 extern unsigned int LIB$GETSYI (int *, ...);
1626 #define SYI$_VERSION 0x1000
1629 __gnat_is_vms_v7 (void)
1631 struct descriptor_s desc;
1632 char version[8];
1633 int status;
1634 int code = SYI$_VERSION;
1636 desc.len = sizeof (version);
1637 desc.mbz = 0;
1638 desc.adr = version;
1640 status = LIB$GETSYI (&code, 0, &desc);
1641 if ((status & 1) == 1 && version[1] == '7' && version[2] == '.')
1642 return 1;
1643 else
1644 return 0;
1647 /*******************/
1648 /* FreeBSD Section */
1649 /*******************/
1651 #elif defined (__FreeBSD__) || defined (__DragonFly__)
1653 #include <signal.h>
1654 #include <sys/ucontext.h>
1655 #include <unistd.h>
1657 static void
1658 __gnat_error_handler (int sig,
1659 siginfo_t *si ATTRIBUTE_UNUSED,
1660 void *ucontext ATTRIBUTE_UNUSED)
1662 struct Exception_Data *exception;
1663 const char *msg;
1665 switch (sig)
1667 case SIGFPE:
1668 exception = &constraint_error;
1669 msg = "SIGFPE";
1670 break;
1672 case SIGILL:
1673 exception = &constraint_error;
1674 msg = "SIGILL";
1675 break;
1677 case SIGSEGV:
1678 exception = &storage_error;
1679 msg = "stack overflow or erroneous memory access";
1680 break;
1682 case SIGBUS:
1683 exception = &storage_error;
1684 msg = "SIGBUS: possible stack overflow";
1685 break;
1687 default:
1688 exception = &program_error;
1689 msg = "unhandled signal";
1692 Raise_From_Signal_Handler (exception, msg);
1695 void
1696 __gnat_install_handler (void)
1698 struct sigaction act;
1700 /* Set up signal handler to map synchronous signals to appropriate
1701 exceptions. Make sure that the handler isn't interrupted by another
1702 signal that might cause a scheduling event! */
1704 act.sa_sigaction
1705 = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1706 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1707 (void) sigemptyset (&act.sa_mask);
1709 (void) sigaction (SIGILL, &act, NULL);
1710 (void) sigaction (SIGFPE, &act, NULL);
1711 (void) sigaction (SIGSEGV, &act, NULL);
1712 (void) sigaction (SIGBUS, &act, NULL);
1714 __gnat_handler_installed = 1;
1717 /*************************************/
1718 /* VxWorks Section (including Vx653) */
1719 /*************************************/
1721 #elif defined(__vxworks)
1723 #include <signal.h>
1724 #include <taskLib.h>
1725 #if (defined (__i386__) || defined (__x86_64__)) && !defined (VTHREADS)
1726 #include <sysLib.h>
1727 #endif
1729 #include "sigtramp.h"
1731 #ifndef __RTP__
1732 #include <intLib.h>
1733 #include <iv.h>
1734 #endif
1736 #if ((defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6))) && !defined(__RTP__)
1737 #define VXWORKS_FORCE_GUARD_PAGE 1
1738 #include <vmLib.h>
1739 extern size_t vxIntStackOverflowSize;
1740 #define INT_OVERFLOW_SIZE vxIntStackOverflowSize
1741 #endif
1743 #ifdef VTHREADS
1744 #include "private/vThreadsP.h"
1745 #endif
1747 #ifndef __RTP__
1749 /* Directly vectored Interrupt routines are not supported when using RTPs. */
1751 extern void * __gnat_inum_to_ivec (int);
1753 /* This is needed by the GNAT run time to handle Vxworks interrupts. */
1754 void *
1755 __gnat_inum_to_ivec (int num)
1757 return (void *) INUM_TO_IVEC (num);
1759 #endif
1761 #if !defined(__alpha_vxworks) && ((_WRS_VXWORKS_MAJOR != 6) && (_WRS_VXWORKS_MAJOR != 7)) && !defined(__RTP__)
1763 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1764 on Alpha VxWorks and VxWorks 6.x (including RTPs). */
1766 extern long getpid (void);
1768 long
1769 getpid (void)
1771 return taskIdSelf ();
1773 #endif
1775 /* When stack checking is performed by probing a guard page on the stack,
1776 sometimes this guard page is not properly reset on VxWorks. We need to
1777 manually reset it in this case.
1778 This function returns TRUE in case the guard page was hit by the
1779 signal. */
1780 static int
1781 __gnat_reset_guard_page (int sig)
1783 /* On ARM VxWorks 6.x and x86_64 VxWorks 7, the guard page is left un-armed
1784 by the kernel after being violated, so subsequent violations aren't
1785 detected.
1786 So we retrieve the address of the guard page from the TCB and compare it
1787 with the page that is violated and re-arm that page if there's a match. */
1788 #if defined (VXWORKS_FORCE_GUARD_PAGE)
1790 /* Ignore signals that are not stack overflow signals */
1791 if (sig != SIGSEGV && sig != SIGBUS && sig != SIGILL) return FALSE;
1793 /* If the target does not support guard pages, INT_OVERFLOW_SIZE will be 0 */
1794 if (INT_OVERFLOW_SIZE == 0) return FALSE;
1796 TASK_ID tid = taskIdSelf ();
1797 WIND_TCB *pTcb = taskTcb (tid);
1798 VIRT_ADDR guardPage = (VIRT_ADDR) pTcb->pStackEnd - INT_OVERFLOW_SIZE;
1799 UINT stateMask = VM_STATE_MASK_VALID;
1800 UINT guardState = VM_STATE_VALID_NOT;
1802 #if (_WRS_VXWORKS_MAJOR >= 7)
1803 stateMask |= MMU_ATTR_SPL_MSK;
1804 guardState |= MMU_ATTR_NO_BLOCK;
1805 #endif
1807 UINT nState;
1808 vmStateGet (NULL, guardPage, &nState);
1809 if ((nState & VM_STATE_MASK_VALID) != VM_STATE_VALID_NOT)
1811 /* If the guard page has a valid state, we need to reset to
1812 invalid state here */
1813 vmStateSet (NULL, guardPage, INT_OVERFLOW_SIZE, stateMask, guardState);
1814 return TRUE;
1816 #endif /* VXWORKS_FORCE_GUARD_PAGE */
1817 return FALSE;
1820 /* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
1821 handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
1822 doesn't. */
1823 void
1824 __gnat_clear_exception_count (void)
1826 #ifdef VTHREADS
1827 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1829 currentTask->vThreads.excCnt = 0;
1830 #endif
1833 /* Handle different SIGnal to exception mappings in different VxWorks
1834 versions. */
1835 void
1836 __gnat_map_signal (int sig,
1837 siginfo_t *si ATTRIBUTE_UNUSED,
1838 void *sc ATTRIBUTE_UNUSED)
1840 struct Exception_Data *exception;
1841 const char *msg;
1843 switch (sig)
1845 case SIGFPE:
1846 exception = &constraint_error;
1847 msg = "SIGFPE";
1848 break;
1849 #ifdef VTHREADS
1850 #ifdef __VXWORKSMILS__
1851 case SIGILL:
1852 exception = &storage_error;
1853 msg = "SIGILL: possible stack overflow";
1854 break;
1855 case SIGSEGV:
1856 exception = &storage_error;
1857 msg = "SIGSEGV";
1858 break;
1859 case SIGBUS:
1860 exception = &program_error;
1861 msg = "SIGBUS";
1862 break;
1863 #else
1864 case SIGILL:
1865 exception = &constraint_error;
1866 msg = "Floating point exception or SIGILL";
1867 break;
1868 case SIGSEGV:
1869 exception = &storage_error;
1870 msg = "SIGSEGV";
1871 break;
1872 case SIGBUS:
1873 exception = &storage_error;
1874 msg = "SIGBUS: possible stack overflow";
1875 break;
1876 #endif
1877 #elif (_WRS_VXWORKS_MAJOR >= 6)
1878 case SIGILL:
1879 exception = &constraint_error;
1880 msg = "SIGILL";
1881 break;
1882 #ifdef __RTP__
1883 /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
1884 since stack checking uses the probing mechanism. */
1885 case SIGSEGV:
1886 exception = &storage_error;
1887 msg = "SIGSEGV: possible stack overflow";
1888 break;
1889 case SIGBUS:
1890 exception = &program_error;
1891 msg = "SIGBUS";
1892 break;
1893 #else
1894 /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
1895 case SIGSEGV:
1896 exception = &storage_error;
1897 msg = "SIGSEGV";
1898 break;
1899 case SIGBUS:
1900 exception = &storage_error;
1901 msg = "SIGBUS: possible stack overflow";
1902 break;
1903 #endif
1904 #else
1905 /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
1906 since stack checking uses the stack limit mechanism. */
1907 case SIGILL:
1908 exception = &storage_error;
1909 msg = "SIGILL: possible stack overflow";
1910 break;
1911 case SIGSEGV:
1912 exception = &storage_error;
1913 msg = "SIGSEGV";
1914 break;
1915 case SIGBUS:
1916 exception = &program_error;
1917 msg = "SIGBUS";
1918 break;
1919 #endif
1920 default:
1921 exception = &program_error;
1922 msg = "unhandled signal";
1925 if (__gnat_reset_guard_page (sig))
1927 /* Set the exception message: we know for sure that we have a
1928 stack overflow here */
1929 exception = &storage_error;
1931 switch (sig)
1933 case SIGSEGV:
1934 msg = "SIGSEGV: stack overflow";
1935 break;
1936 case SIGBUS:
1937 msg = "SIGBUS: stack overflow";
1938 break;
1939 case SIGILL:
1940 msg = "SIGILL: stack overflow";
1941 break;
1944 __gnat_clear_exception_count ();
1945 Raise_From_Signal_Handler (exception, msg);
1948 #if defined (ARMEL) && (_WRS_VXWORKS_MAJOR >= 7) && !defined (__aarch64__)
1950 /* ARM-vx7 case with arm unwinding exceptions */
1951 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1953 #include <arch/../regs.h>
1954 #ifndef __RTP__
1955 #include <sigLib.h>
1956 #else
1957 #include <signal.h>
1958 #include <regs.h>
1959 #include <ucontext.h>
1960 #endif /* __RTP__ */
1962 void
1963 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
1964 void *sc ATTRIBUTE_UNUSED)
1966 /* In case of ARM exceptions, the registers context have the PC pointing
1967 to the instruction that raised the signal. However the unwinder expects
1968 the instruction to be in the range ]PC,PC+1]. */
1969 uintptr_t *pc_addr;
1970 #ifdef __RTP__
1971 mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext;
1972 pc_addr = (uintptr_t*)&mcontext->regs.pc;
1973 #else
1974 struct sigcontext * sctx = (struct sigcontext *) sc;
1975 pc_addr = (uintptr_t*)&sctx->sc_pregs->pc;
1976 #endif
1977 /* ARM Bump has to be an even number because of odd/even architecture. */
1978 *pc_addr += 2;
1980 #endif /* ARMEL && _WRS_VXWORKS_MAJOR >= 7 */
1982 /* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
1983 propagation after the required low level adjustments. */
1985 static void
1986 __gnat_error_handler (int sig, siginfo_t *si, void *sc)
1988 sigset_t mask;
1990 /* VxWorks on e500v2 clears the SPE bit of the MSR when entering CPU
1991 exception state. To allow the handler and exception to work properly
1992 when they contain SPE instructions, we need to set it back before doing
1993 anything else.
1994 This mechanism is only need in kernel mode. */
1995 #if !(defined (__RTP__) || defined (VTHREADS)) && ((CPU == PPCE500V2) || (CPU == PPC85XX))
1996 register unsigned msr;
1997 /* Read the MSR value */
1998 asm volatile ("mfmsr %0" : "=r" (msr));
1999 /* Force the SPE bit if not set. */
2000 if ((msr & 0x02000000) == 0)
2002 msr |= 0x02000000;
2003 /* Store to MSR */
2004 asm volatile ("mtmsr %0" : : "r" (msr));
2006 #endif
2008 /* VxWorks will always mask out the signal during the signal handler and
2009 will reenable it on a longjmp. GNAT does not generate a longjmp to
2010 return from a signal handler so the signal will still be masked unless
2011 we unmask it. */
2012 sigprocmask (SIG_SETMASK, NULL, &mask);
2013 sigdelset (&mask, sig);
2014 sigprocmask (SIG_SETMASK, &mask, NULL);
2016 #if defined (__ARMEL__) || defined (__PPC__) || defined (__i386__) || defined (__x86_64__) || defined (__aarch64__)
2017 /* On certain targets, kernel mode, we process signals through a Call Frame
2018 Info trampoline, voiding the need for myriads of fallback_frame_state
2019 variants in the ZCX runtime. We have no simple way to distinguish ZCX
2020 from SJLJ here, so we do this for SJLJ as well even though this is not
2021 necessary. This only incurs a few extra instructions and a tiny
2022 amount of extra stack usage. */
2024 #ifdef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2025 /* We need to sometimes to adjust the PC in case of signals so that it
2026 doesn't reference the exception that actually raised the signal but the
2027 instruction before it. */
2028 __gnat_adjust_context_for_raise (sig, sc);
2029 #endif
2031 __gnat_sigtramp (sig, (void *)si, (void *)sc,
2032 (__sigtramphandler_t *)&__gnat_map_signal);
2034 #else
2035 __gnat_map_signal (sig, si, sc);
2036 #endif
2039 #if defined(__leon__) && defined(_WRS_KERNEL)
2040 /* For LEON VxWorks we need to install a trap handler for stack overflow */
2042 extern void excEnt (void);
2043 /* VxWorks exception handler entry */
2045 struct trap_entry {
2046 unsigned long inst_first;
2047 unsigned long inst_second;
2048 unsigned long inst_third;
2049 unsigned long inst_fourth;
2051 /* Four instructions representing entries in the trap table */
2053 struct trap_entry *trap_0_entry;
2054 /* We will set the location of the entry for software trap 0 in the trap
2055 table. */
2056 #endif
2058 void
2059 __gnat_install_handler (void)
2061 struct sigaction act;
2063 /* Setup signal handler to map synchronous signals to appropriate
2064 exceptions. Make sure that the handler isn't interrupted by another
2065 signal that might cause a scheduling event! */
2067 act.sa_sigaction = __gnat_error_handler;
2068 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
2069 sigemptyset (&act.sa_mask);
2071 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
2072 applies to vectored hardware interrupts, not signals. */
2073 sigaction (SIGFPE, &act, NULL);
2074 sigaction (SIGILL, &act, NULL);
2075 sigaction (SIGSEGV, &act, NULL);
2076 sigaction (SIGBUS, &act, NULL);
2078 #if defined(__leon__) && defined(_WRS_KERNEL)
2079 /* Specific to the LEON VxWorks kernel run-time library */
2081 /* For stack checking the compiler triggers a software trap 0 (ta 0) in
2082 case of overflow (we use the stack limit mechanism). We need to install
2083 the trap handler here for this software trap (the OS does not handle
2084 it) as if it were a data_access_exception (trap 9). We do the same as
2085 if we put in the trap table a VXSPARC_BAD_TRAP(9). Software trap 0 is
2086 located at vector 0x80, and each entry takes 4 words. */
2088 trap_0_entry = (struct trap_entry *)(intVecBaseGet () + 0x80 * 4);
2090 /* mov 0x9, %l7 */
2092 trap_0_entry->inst_first = 0xae102000 + 9;
2094 /* sethi %hi(excEnt), %l6 */
2096 /* The 22 most significant bits of excEnt are obtained shifting 10 times
2097 to the right. */
2099 trap_0_entry->inst_second = 0x2d000000 + ((unsigned long)excEnt >> 10);
2101 /* jmp %l6+%lo(excEnt) */
2103 /* The 10 least significant bits of excEnt are obtained by masking */
2105 trap_0_entry->inst_third = 0x81c5a000 + ((unsigned long)excEnt & 0x3ff);
2107 /* rd %psr, %l0 */
2109 trap_0_entry->inst_fourth = 0xa1480000;
2110 #endif
2112 #ifdef __HANDLE_VXSIM_SC
2113 /* By experiment, found that sysModel () returns the following string
2114 prefix for vxsim when running on Linux and Windows. */
2116 char *model = sysModel ();
2117 if ((strncmp (model, "Linux", 5) == 0)
2118 || (strncmp (model, "Windows", 7) == 0)
2119 || (strncmp (model, "SIMLINUX", 8) == 0) /* vx7 */
2120 || (strncmp (model, "SIMNT", 5) == 0)) /* ditto */
2121 __gnat_set_is_vxsim (TRUE);
2123 #endif
2125 __gnat_handler_installed = 1;
2128 #define HAVE_GNAT_INIT_FLOAT
2130 void
2131 __gnat_init_float (void)
2133 /* Disable overflow/underflow exceptions on the PPC processor, needed
2134 to get correct Ada semantics. Note that for AE653 vThreads, the HW
2135 overflow settings are an OS configuration issue. The instructions
2136 below have no effect. */
2137 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && (!defined (VTHREADS) || defined (__VXWORKSMILS__))
2138 #if defined (__SPE__)
2140 /* For e500v2, do nothing and leave the responsibility to install the
2141 handler and enable the exceptions to the BSP. */
2143 #else
2144 asm ("mtfsb0 25");
2145 asm ("mtfsb0 26");
2146 #endif
2147 #endif
2149 #if (defined (__i386__) || defined (__x86_64__)) && !defined (VTHREADS)
2150 /* This is used to properly initialize the FPU on an x86 for each
2151 process thread. */
2152 asm ("finit");
2153 #endif
2155 /* Similarly for SPARC64. Achieved by masking bits in the Trap Enable Mask
2156 field of the Floating-point Status Register (see the SPARC Architecture
2157 Manual Version 9, p 48). */
2158 #if defined (sparc64)
2160 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
2161 #define FSR_TEM_OFM (1 << 26) /* Overflow */
2162 #define FSR_TEM_UFM (1 << 25) /* Underflow */
2163 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
2164 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
2166 unsigned int fsr;
2168 __asm__("st %%fsr, %0" : "=m" (fsr));
2169 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
2170 __asm__("ld %0, %%fsr" : : "m" (fsr));
2172 #endif
2175 /* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
2176 (if not null) when a new task is created. It is initialized by
2177 System.Stack_Checking.Operations.Initialize_Stack_Limit.
2178 The use of a hook avoids to drag stack checking subprograms if stack
2179 checking is not used. */
2180 void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
2182 /******************/
2183 /* NetBSD Section */
2184 /******************/
2186 #elif defined(__NetBSD__)
2188 #include <signal.h>
2189 #include <unistd.h>
2191 static void
2192 __gnat_error_handler (int sig)
2194 struct Exception_Data *exception;
2195 const char *msg;
2197 switch(sig)
2199 case SIGFPE:
2200 exception = &constraint_error;
2201 msg = "SIGFPE";
2202 break;
2203 case SIGILL:
2204 exception = &constraint_error;
2205 msg = "SIGILL";
2206 break;
2207 case SIGSEGV:
2208 exception = &storage_error;
2209 msg = "stack overflow or erroneous memory access";
2210 break;
2211 case SIGBUS:
2212 exception = &constraint_error;
2213 msg = "SIGBUS";
2214 break;
2215 default:
2216 exception = &program_error;
2217 msg = "unhandled signal";
2220 Raise_From_Signal_Handler (exception, msg);
2223 void
2224 __gnat_install_handler (void)
2226 struct sigaction act;
2228 act.sa_handler = __gnat_error_handler;
2229 act.sa_flags = SA_NODEFER | SA_RESTART;
2230 sigemptyset (&act.sa_mask);
2232 /* Do not install handlers if interrupt state is "System". */
2233 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2234 sigaction (SIGFPE, &act, NULL);
2235 if (__gnat_get_interrupt_state (SIGILL) != 's')
2236 sigaction (SIGILL, &act, NULL);
2237 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2238 sigaction (SIGSEGV, &act, NULL);
2239 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2240 sigaction (SIGBUS, &act, NULL);
2242 __gnat_handler_installed = 1;
2245 /*******************/
2246 /* OpenBSD Section */
2247 /*******************/
2249 #elif defined(__OpenBSD__)
2251 #include <signal.h>
2252 #include <unistd.h>
2254 static void
2255 __gnat_error_handler (int sig)
2257 struct Exception_Data *exception;
2258 const char *msg;
2260 switch(sig)
2262 case SIGFPE:
2263 exception = &constraint_error;
2264 msg = "SIGFPE";
2265 break;
2266 case SIGILL:
2267 exception = &constraint_error;
2268 msg = "SIGILL";
2269 break;
2270 case SIGSEGV:
2271 exception = &storage_error;
2272 msg = "stack overflow or erroneous memory access";
2273 break;
2274 case SIGBUS:
2275 exception = &constraint_error;
2276 msg = "SIGBUS";
2277 break;
2278 default:
2279 exception = &program_error;
2280 msg = "unhandled signal";
2283 Raise_From_Signal_Handler (exception, msg);
2286 void
2287 __gnat_install_handler (void)
2289 struct sigaction act;
2291 act.sa_handler = __gnat_error_handler;
2292 act.sa_flags = SA_NODEFER | SA_RESTART;
2293 sigemptyset (&act.sa_mask);
2295 /* Do not install handlers if interrupt state is "System" */
2296 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2297 sigaction (SIGFPE, &act, NULL);
2298 if (__gnat_get_interrupt_state (SIGILL) != 's')
2299 sigaction (SIGILL, &act, NULL);
2300 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2301 sigaction (SIGSEGV, &act, NULL);
2302 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2303 sigaction (SIGBUS, &act, NULL);
2305 __gnat_handler_installed = 1;
2308 /******************/
2309 /* Darwin Section */
2310 /******************/
2312 #elif defined(__APPLE__)
2314 #include <TargetConditionals.h>
2315 #include <signal.h>
2316 #include <stdlib.h>
2317 #include <sys/syscall.h>
2318 #include <sys/sysctl.h>
2320 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
2321 char __gnat_alternate_stack[32 * 1024]; /* 1 * MINSIGSTKSZ */
2323 /* Defined in xnu unix_signal.c.
2324 Tell the kernel to re-use alt stack when delivering a signal. */
2325 #define UC_RESET_ALT_STACK 0x80000000
2327 #if !(defined (__arm__) || defined (__arm64__) || TARGET_IPHONE_SIMULATOR)
2328 #include <mach/mach_vm.h>
2329 #include <mach/mach_init.h>
2330 #include <mach/vm_statistics.h>
2331 #endif
2333 #ifdef __arm64__
2334 #include <sys/ucontext.h>
2335 #include "sigtramp.h"
2336 #endif
2338 /* Return true if ADDR is within a stack guard area. */
2339 static int
2340 __gnat_is_stack_guard (mach_vm_address_t addr)
2342 #if !(defined (__arm__) || defined (__arm64__) || TARGET_IPHONE_SIMULATOR)
2343 kern_return_t kret;
2344 vm_region_submap_info_data_64_t info;
2345 mach_vm_address_t start;
2346 mach_vm_size_t size;
2347 natural_t depth;
2348 mach_msg_type_number_t count;
2350 count = VM_REGION_SUBMAP_INFO_COUNT_64;
2351 start = addr;
2352 size = -1;
2353 depth = 9999;
2354 kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
2355 (vm_region_recurse_info_t) &info, &count);
2356 if (kret == KERN_SUCCESS
2357 && addr >= start && addr < (start + size)
2358 && info.protection == VM_PROT_NONE
2359 && info.user_tag == VM_MEMORY_STACK)
2360 return 1;
2361 return 0;
2362 #else
2363 /* Pagezero for arm. */
2364 return addr >= 4096;
2365 #endif
2368 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2370 #if defined (__x86_64__)
2371 static int
2372 __darwin_major_version (void)
2374 static int cache = -1;
2375 if (cache < 0)
2377 int mib[2] = {CTL_KERN, KERN_OSRELEASE};
2378 size_t len;
2380 /* Find out how big the buffer needs to be (and set cache to 0
2381 on failure). */
2382 if (sysctl (mib, 2, NULL, &len, NULL, 0) == 0)
2384 char release[len];
2385 sysctl (mib, 2, release, &len, NULL, 0);
2386 /* Darwin releases are of the form L.M.N where L is the major
2387 version, so strtol will return L. */
2388 cache = (int) strtol (release, NULL, 10);
2390 else
2392 cache = 0;
2395 return cache;
2397 #endif
2399 void
2400 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2401 void *ucontext ATTRIBUTE_UNUSED)
2403 #if defined (__x86_64__)
2404 if (__darwin_major_version () < 12)
2406 /* Work around radar #10302855, where the unwinders (libunwind or
2407 libgcc_s depending on the system revision) and the DWARF unwind
2408 data for sigtramp have different ideas about register numbering,
2409 causing rbx and rdx to be transposed. */
2410 ucontext_t *uc = (ucontext_t *)ucontext;
2411 unsigned long t = uc->uc_mcontext->__ss.__rbx;
2413 uc->uc_mcontext->__ss.__rbx = uc->uc_mcontext->__ss.__rdx;
2414 uc->uc_mcontext->__ss.__rdx = t;
2416 #elif defined(__arm64__)
2417 /* Even though the CFI is marked as a signal frame, we need this. */
2418 ucontext_t *uc = (ucontext_t *)ucontext;
2419 uc->uc_mcontext->__ss.__pc++;
2420 #endif
2423 static void
2424 __gnat_map_signal (int sig, siginfo_t *si, void *mcontext ATTRIBUTE_UNUSED)
2426 struct Exception_Data *exception;
2427 const char *msg;
2429 switch (sig)
2431 case SIGSEGV:
2432 case SIGBUS:
2433 if (__gnat_is_stack_guard ((unsigned long)si->si_addr))
2435 #ifdef __arm64__
2436 /* ??? This is a kludge to make stack checking work. The problem is
2437 that the trampoline doesn't restore LR and, consequently, doesn't
2438 make it possible to unwind past an interrupted frame which hasn"t
2439 saved LR on the stack yet. Therefore, for probes in the prologue
2440 (32-bit probes as opposed to standard 64-bit probes), we make the
2441 unwinder skip the not-yet-established frame altogether. */
2442 mcontext_t mc = (mcontext_t)mcontext;
2443 if (!(*(unsigned int *)(mc->__ss.__pc-1) & ((unsigned int)1 << 30)))
2444 mc->__ss.__pc = mc->__ss.__lr;
2445 #endif
2446 exception = &storage_error;
2447 msg = "stack overflow";
2449 else
2451 exception = &constraint_error;
2452 msg = "erroneous memory access";
2455 /* Reset the use of alt stack, so that the alt stack will be used
2456 for the next signal delivery.
2457 The stack can't be used in case of stack checking. */
2458 syscall (SYS_sigreturn, NULL, UC_RESET_ALT_STACK);
2459 break;
2461 case SIGFPE:
2462 exception = &constraint_error;
2463 msg = "SIGFPE";
2464 break;
2466 default:
2467 exception = &program_error;
2468 msg = "unhandled signal";
2471 Raise_From_Signal_Handler (exception, msg);
2474 static void
2475 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
2477 __gnat_adjust_context_for_raise (sig, ucontext);
2479 /* The Darwin libc comes with a signal trampoline, except for ARM64. */
2480 #ifdef __arm64__
2481 __gnat_sigtramp (sig, (void *)si, ucontext,
2482 (__sigtramphandler_t *)&__gnat_map_signal);
2483 #else
2484 __gnat_map_signal (sig, si, ucontext);
2485 #endif
2488 void
2489 __gnat_install_handler (void)
2491 struct sigaction act;
2493 /* Set up signal handler to map synchronous signals to appropriate
2494 exceptions. Make sure that the handler isn't interrupted by another
2495 signal that might cause a scheduling event! Also setup an alternate
2496 stack region for the handler execution so that stack overflows can be
2497 handled properly, avoiding a SEGV generation from stack usage by the
2498 handler itself (and it is required by Darwin). */
2500 stack_t stack;
2501 stack.ss_sp = __gnat_alternate_stack;
2502 stack.ss_size = sizeof (__gnat_alternate_stack);
2503 stack.ss_flags = 0;
2504 sigaltstack (&stack, NULL);
2506 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2507 act.sa_sigaction = __gnat_error_handler;
2508 sigemptyset (&act.sa_mask);
2510 /* Do not install handlers if interrupt state is "System". */
2511 if (__gnat_get_interrupt_state (SIGABRT) != 's')
2512 sigaction (SIGABRT, &act, NULL);
2513 if (__gnat_get_interrupt_state (SIGFPE) != 's')
2514 sigaction (SIGFPE, &act, NULL);
2515 if (__gnat_get_interrupt_state (SIGILL) != 's')
2516 sigaction (SIGILL, &act, NULL);
2518 act.sa_flags |= SA_ONSTACK;
2519 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2520 sigaction (SIGSEGV, &act, NULL);
2521 if (__gnat_get_interrupt_state (SIGBUS) != 's')
2522 sigaction (SIGBUS, &act, NULL);
2524 __gnat_handler_installed = 1;
2527 #elif defined(__QNX__)
2529 /***************/
2530 /* QNX Section */
2531 /***************/
2533 #include <signal.h>
2534 #include <unistd.h>
2535 #include <string.h>
2536 #include "sigtramp.h"
2538 void
2539 __gnat_map_signal (int sig,
2540 siginfo_t *si ATTRIBUTE_UNUSED,
2541 void *mcontext ATTRIBUTE_UNUSED)
2543 struct Exception_Data *exception;
2544 const char *msg;
2546 switch(sig)
2548 case SIGFPE:
2549 exception = &constraint_error;
2550 msg = "SIGFPE";
2551 break;
2552 case SIGILL:
2553 exception = &constraint_error;
2554 msg = "SIGILL";
2555 break;
2556 case SIGSEGV:
2557 exception = &storage_error;
2558 msg = "stack overflow or erroneous memory access";
2559 break;
2560 case SIGBUS:
2561 exception = &constraint_error;
2562 msg = "SIGBUS";
2563 break;
2564 default:
2565 exception = &program_error;
2566 msg = "unhandled signal";
2569 Raise_From_Signal_Handler (exception, msg);
2572 static void
2573 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
2575 __gnat_sigtramp (sig, (void *) si, (void *) ucontext,
2576 (__sigtramphandler_t *)&__gnat_map_signal);
2579 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
2580 /* sigaltstack is currently not supported by QNX7 */
2581 char __gnat_alternate_stack[0];
2583 void
2584 __gnat_install_handler (void)
2586 struct sigaction act;
2587 int err;
2589 act.sa_handler = __gnat_error_handler;
2590 act.sa_flags = SA_NODEFER | SA_SIGINFO;
2591 sigemptyset (&act.sa_mask);
2593 /* Do not install handlers if interrupt state is "System" */
2594 if (__gnat_get_interrupt_state (SIGFPE) != 's') {
2595 err = sigaction (SIGFPE, &act, NULL);
2596 if (err == -1) {
2597 err = errno;
2598 perror ("error while attaching SIGFPE");
2599 perror (strerror (err));
2602 if (__gnat_get_interrupt_state (SIGILL) != 's') {
2603 sigaction (SIGILL, &act, NULL);
2604 if (err == -1) {
2605 err = errno;
2606 perror ("error while attaching SIGFPE");
2607 perror (strerror (err));
2610 if (__gnat_get_interrupt_state (SIGSEGV) != 's') {
2611 sigaction (SIGSEGV, &act, NULL);
2612 if (err == -1) {
2613 err = errno;
2614 perror ("error while attaching SIGFPE");
2615 perror (strerror (err));
2618 if (__gnat_get_interrupt_state (SIGBUS) != 's') {
2619 sigaction (SIGBUS, &act, NULL);
2620 if (err == -1) {
2621 err = errno;
2622 perror ("error while attaching SIGFPE");
2623 perror (strerror (err));
2626 __gnat_handler_installed = 1;
2629 #elif defined (__DJGPP__)
2631 void
2632 __gnat_install_handler ()
2634 __gnat_handler_installed = 1;
2637 #elif defined(__ANDROID__)
2639 /*******************/
2640 /* Android Section */
2641 /*******************/
2643 #include <signal.h>
2644 #include <sys/ucontext.h>
2645 #include "sigtramp.h"
2647 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2649 void
2650 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
2652 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
2654 /* ARM Bump has to be an even number because of odd/even architecture. */
2655 ((mcontext_t *) mcontext)->arm_pc += 2;
2658 static void
2659 __gnat_map_signal (int sig,
2660 siginfo_t *si ATTRIBUTE_UNUSED,
2661 void *mcontext ATTRIBUTE_UNUSED)
2663 struct Exception_Data *exception;
2664 const char *msg;
2666 switch (sig)
2668 case SIGSEGV:
2669 exception = &storage_error;
2670 msg = "stack overflow or erroneous memory access";
2671 break;
2673 case SIGBUS:
2674 exception = &constraint_error;
2675 msg = "SIGBUS";
2676 break;
2678 case SIGFPE:
2679 exception = &constraint_error;
2680 msg = "SIGFPE";
2681 break;
2683 default:
2684 exception = &program_error;
2685 msg = "unhandled signal";
2688 Raise_From_Signal_Handler (exception, msg);
2691 static void
2692 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
2694 __gnat_adjust_context_for_raise (sig, ucontext);
2696 __gnat_sigtramp (sig, (void *) si, (void *) ucontext,
2697 (__sigtramphandler_t *)&__gnat_map_signal);
2700 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
2701 char __gnat_alternate_stack[16 * 1024];
2703 void
2704 __gnat_install_handler (void)
2706 struct sigaction act;
2708 /* Set up signal handler to map synchronous signals to appropriate
2709 exceptions. Make sure that the handler isn't interrupted by another
2710 signal that might cause a scheduling event! Also setup an alternate
2711 stack region for the handler execution so that stack overflows can be
2712 handled properly, avoiding a SEGV generation from stack usage by the
2713 handler itself. */
2715 stack_t stack;
2716 stack.ss_sp = __gnat_alternate_stack;
2717 stack.ss_size = sizeof (__gnat_alternate_stack);
2718 stack.ss_flags = 0;
2719 sigaltstack (&stack, NULL);
2721 act.sa_sigaction = __gnat_error_handler;
2722 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2723 sigemptyset (&act.sa_mask);
2725 sigaction (SIGABRT, &act, NULL);
2726 sigaction (SIGFPE, &act, NULL);
2727 sigaction (SIGILL, &act, NULL);
2728 sigaction (SIGBUS, &act, NULL);
2729 act.sa_flags |= SA_ONSTACK;
2730 sigaction (SIGSEGV, &act, NULL);
2732 __gnat_handler_installed = 1;
2735 #else
2737 /* For all other versions of GNAT, the handler does nothing. */
2739 /*******************/
2740 /* Default Section */
2741 /*******************/
2743 void
2744 __gnat_install_handler (void)
2746 __gnat_handler_installed = 1;
2749 #endif
2751 /*********************/
2752 /* __gnat_init_float */
2753 /*********************/
2755 /* This routine is called as each process thread is created, for possible
2756 initialization of the FP processor. This version is used under INTERIX
2757 and WIN32. */
2759 #if defined (_WIN32) || defined (__INTERIX) \
2760 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
2761 || defined (__OpenBSD__) || defined (__DragonFly__) || defined(__QNX__)
2763 #define HAVE_GNAT_INIT_FLOAT
2765 void
2766 __gnat_init_float (void)
2768 #if defined (__i386__) || defined (__x86_64__)
2770 /* This is used to properly initialize the FPU on an x86 for each
2771 process thread. */
2773 asm ("finit");
2775 #endif /* Defined __i386__ */
2777 #endif
2779 #ifndef HAVE_GNAT_INIT_FLOAT
2781 /* All targets without a specific __gnat_init_float will use an empty one. */
2782 void
2783 __gnat_init_float (void)
2786 #endif
2788 /***********************************/
2789 /* __gnat_adjust_context_for_raise */
2790 /***********************************/
2792 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2794 /* All targets without a specific version will use an empty one. */
2796 /* Given UCONTEXT a pointer to a context structure received by a signal
2797 handler for SIGNO, perform the necessary adjustments to let the handler
2798 raise an exception. Calls to this routine are not conditioned by the
2799 propagation scheme in use. */
2801 void
2802 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2803 void *ucontext ATTRIBUTE_UNUSED)
2805 /* We used to compensate here for the raised from call vs raised from signal
2806 exception discrepancy with the GCC ZCX scheme, but this now can be dealt
2807 with generically in the unwinder (see GCC PR other/26208). This however
2808 requires the use of the _Unwind_GetIPInfo routine in raise-gcc.c, which
2809 is predicated on the definition of HAVE_GETIPINFO at compile time. Only
2810 the VMS ports still do the compensation described in the few lines below.
2812 *** Call vs signal exception discrepancy with GCC ZCX scheme ***
2814 The GCC unwinder expects to be dealing with call return addresses, since
2815 this is the "nominal" case of what we retrieve while unwinding a regular
2816 call chain.
2818 To evaluate if a handler applies at some point identified by a return
2819 address, the propagation engine needs to determine what region the
2820 corresponding call instruction pertains to. Because the return address
2821 may not be attached to the same region as the call, the unwinder always
2822 subtracts "some" amount from a return address to search the region
2823 tables, amount chosen to ensure that the resulting address is inside the
2824 call instruction.
2826 When we raise an exception from a signal handler, e.g. to transform a
2827 SIGSEGV into Storage_Error, things need to appear as if the signal
2828 handler had been "called" by the instruction which triggered the signal,
2829 so that exception handlers that apply there are considered. What the
2830 unwinder will retrieve as the return address from the signal handler is
2831 what it will find as the faulting instruction address in the signal
2832 context pushed by the kernel. Leaving this address untouched looses, if
2833 the triggering instruction happens to be the very first of a region, as
2834 the later adjustments performed by the unwinder would yield an address
2835 outside that region. We need to compensate for the unwinder adjustments
2836 at some point, and this is what this routine is expected to do.
2838 signo is passed because on some targets for some signals the PC in
2839 context points to the instruction after the faulting one, in which case
2840 the unwinder adjustment is still desired. */
2843 #endif
2845 #ifdef __cplusplus
2847 #endif