1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2012, Free Software Foundation, Inc. *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 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. *
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. *
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/>. *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
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). */
45 /* This file should be kept synchronized with 2sinit.ads, 2sinit.adb,
46 s-init-ae653-cert.adb and s-init-xi-sparc.adb. All these files implement
47 the required functionality for different targets. */
49 /* The following include is here to meet the published VxWorks requirement
50 that the __vxworks header appear before any other include. */
60 /* We don't have libiberty, so use malloc. */
61 #define xmalloc(S) malloc (S)
70 extern void __gnat_raise_program_error (const char *, int);
72 /* Addresses of exception data blocks for predefined exceptions. Tasking_Error
73 is not used in this unit, and the abort signal is only used on IRIX.
74 ??? Revisit this part since IRIX is no longer supported. */
75 extern struct Exception_Data constraint_error
;
76 extern struct Exception_Data numeric_error
;
77 extern struct Exception_Data program_error
;
78 extern struct Exception_Data storage_error
;
80 /* For the Cert run time we use the regular raise exception routine because
81 Raise_From_Signal_Handler is not available. */
83 #define Raise_From_Signal_Handler \
84 __gnat_raise_exception
85 extern void Raise_From_Signal_Handler (struct Exception_Data
*, const char *);
87 #define Raise_From_Signal_Handler \
88 ada__exceptions__raise_from_signal_handler
89 extern void Raise_From_Signal_Handler (struct Exception_Data
*, const char *);
92 /* Global values computed by the binder. */
93 int __gl_main_priority
= -1;
94 int __gl_main_cpu
= -1;
95 int __gl_time_slice_val
= -1;
96 char __gl_wc_encoding
= 'n';
97 char __gl_locking_policy
= ' ';
98 char __gl_queuing_policy
= ' ';
99 char __gl_task_dispatching_policy
= ' ';
100 char *__gl_priority_specific_dispatching
= 0;
101 int __gl_num_specific_dispatching
= 0;
102 char *__gl_interrupt_states
= 0;
103 int __gl_num_interrupt_states
= 0;
104 int __gl_unreserve_all_interrupts
= 0;
105 int __gl_exception_tracebacks
= 0;
106 int __gl_zero_cost_exceptions
= 0;
107 int __gl_detect_blocking
= 0;
108 int __gl_default_stack_size
= -1;
109 int __gl_leap_seconds_support
= 0;
110 int __gl_canonical_streams
= 0;
112 /* Indication of whether synchronous signal handler has already been
113 installed by a previous call to adainit. */
114 int __gnat_handler_installed
= 0;
117 int __gnat_inside_elab_final_code
= 0;
118 /* ??? This variable is obsolete since 2001-08-29 but is kept to allow
119 bootstrap from old GNAT versions (< 3.15). */
122 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
123 is defined. If this is not set then a void implementation will be defined
124 at the end of this unit. */
125 #undef HAVE_GNAT_INIT_FLOAT
127 /******************************/
128 /* __gnat_get_interrupt_state */
129 /******************************/
131 char __gnat_get_interrupt_state (int);
133 /* This routine is called from the runtime as needed to determine the state
134 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
135 in the current partition. The input argument is the interrupt number,
136 and the result is one of the following:
138 'n' this interrupt not set by any Interrupt_State pragma
139 'u' Interrupt_State pragma set state to User
140 'r' Interrupt_State pragma set state to Runtime
141 's' Interrupt_State pragma set state to System */
144 __gnat_get_interrupt_state (int intrup
)
146 if (intrup
>= __gl_num_interrupt_states
)
149 return __gl_interrupt_states
[intrup
];
152 /***********************************/
153 /* __gnat_get_specific_dispatching */
154 /***********************************/
156 char __gnat_get_specific_dispatching (int);
158 /* This routine is called from the runtime as needed to determine the
159 priority specific dispatching policy, as set by a
160 Priority_Specific_Dispatching pragma appearing anywhere in the current
161 partition. The input argument is the priority number, and the result
162 is the upper case first character of the policy name, e.g. 'F' for
163 FIFO_Within_Priorities. A space ' ' is returned if no
164 Priority_Specific_Dispatching pragma is used in the partition. */
167 __gnat_get_specific_dispatching (int priority
)
169 if (__gl_num_specific_dispatching
== 0)
171 else if (priority
>= __gl_num_specific_dispatching
)
174 return __gl_priority_specific_dispatching
[priority
];
179 /**********************/
180 /* __gnat_set_globals */
181 /**********************/
183 /* This routine is kept for bootstrapping purposes, since the binder generated
184 file now sets the __gl_* variables directly. */
187 __gnat_set_globals (void)
200 #include <sys/time.h>
202 /* Some versions of AIX don't define SA_NODEFER. */
206 #endif /* SA_NODEFER */
208 /* Versions of AIX before 4.3 don't have nanosleep but provide
211 #ifndef _AIXVERSION_430
213 extern int nanosleep (struct timestruc_t
*, struct timestruc_t
*);
216 nanosleep (struct timestruc_t
*Rqtp
, struct timestruc_t
*Rmtp
)
218 return nsleep (Rqtp
, Rmtp
);
221 #endif /* _AIXVERSION_430 */
223 /* Version of AIX before 5.3 don't have pthread_condattr_setclock:
224 * supply it as a weak symbol here so that if linking on a 5.3 or newer
225 * machine, we get the real one.
228 #ifndef _AIXVERSION_530
229 #pragma weak pthread_condattr_setclock
231 pthread_condattr_setclock (pthread_condattr_t
*attr
, clockid_t cl
) {
237 __gnat_error_handler (int sig
,
238 siginfo_t
*si ATTRIBUTE_UNUSED
,
239 void *ucontext ATTRIBUTE_UNUSED
)
241 struct Exception_Data
*exception
;
247 /* FIXME: we need to detect the case of a *real* SIGSEGV. */
248 exception
= &storage_error
;
249 msg
= "stack overflow or erroneous memory access";
253 exception
= &constraint_error
;
258 exception
= &constraint_error
;
263 exception
= &program_error
;
264 msg
= "unhandled signal";
267 Raise_From_Signal_Handler (exception
, msg
);
271 __gnat_install_handler (void)
273 struct sigaction act
;
275 /* Set up signal handler to map synchronous signals to appropriate
276 exceptions. Make sure that the handler isn't interrupted by another
277 signal that might cause a scheduling event! */
279 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_SIGINFO
;
280 act
.sa_sigaction
= __gnat_error_handler
;
281 sigemptyset (&act
.sa_mask
);
283 /* Do not install handlers if interrupt state is "System". */
284 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
285 sigaction (SIGABRT
, &act
, NULL
);
286 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
287 sigaction (SIGFPE
, &act
, NULL
);
288 if (__gnat_get_interrupt_state (SIGILL
) != 's')
289 sigaction (SIGILL
, &act
, NULL
);
290 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
291 sigaction (SIGSEGV
, &act
, NULL
);
292 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
293 sigaction (SIGBUS
, &act
, NULL
);
295 __gnat_handler_installed
= 1;
302 #elif defined (__hpux__)
305 #include <sys/ucontext.h>
307 #if defined (IN_RTS) && defined (__ia64__)
309 #include <sys/uc_access.h>
311 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
314 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
, void *ucontext
)
316 ucontext_t
*uc
= (ucontext_t
*) ucontext
;
319 /* Adjust on itanium, as GetIPInfo is not supported. */
320 __uc_get_ip (uc
, &ip
);
321 __uc_set_ip (uc
, ip
+ 1);
323 #endif /* IN_RTS && __ia64__ */
325 /* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
326 propagation after the required low level adjustments. */
329 __gnat_error_handler (int sig
,
330 siginfo_t
*si ATTRIBUTE_UNUSED
,
331 void *ucontext ATTRIBUTE_UNUSED
)
333 struct Exception_Data
*exception
;
336 __gnat_adjust_context_for_raise (sig
, ucontext
);
341 /* FIXME: we need to detect the case of a *real* SIGSEGV. */
342 exception
= &storage_error
;
343 msg
= "stack overflow or erroneous memory access";
347 exception
= &constraint_error
;
352 exception
= &constraint_error
;
357 exception
= &program_error
;
358 msg
= "unhandled signal";
361 Raise_From_Signal_Handler (exception
, msg
);
364 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
365 #if defined (__hppa__)
366 char __gnat_alternate_stack
[16 * 1024]; /* 2 * SIGSTKSZ */
368 char __gnat_alternate_stack
[128 * 1024]; /* MINSIGSTKSZ */
372 __gnat_install_handler (void)
374 struct sigaction act
;
376 /* Set up signal handler to map synchronous signals to appropriate
377 exceptions. Make sure that the handler isn't interrupted by another
378 signal that might cause a scheduling event! Also setup an alternate
379 stack region for the handler execution so that stack overflows can be
380 handled properly, avoiding a SEGV generation from stack usage by the
384 stack
.ss_sp
= __gnat_alternate_stack
;
385 stack
.ss_size
= sizeof (__gnat_alternate_stack
);
387 sigaltstack (&stack
, NULL
);
389 act
.sa_sigaction
= __gnat_error_handler
;
390 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_SIGINFO
;
391 sigemptyset (&act
.sa_mask
);
393 /* Do not install handlers if interrupt state is "System". */
394 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
395 sigaction (SIGABRT
, &act
, NULL
);
396 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
397 sigaction (SIGFPE
, &act
, NULL
);
398 if (__gnat_get_interrupt_state (SIGILL
) != 's')
399 sigaction (SIGILL
, &act
, NULL
);
400 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
401 sigaction (SIGBUS
, &act
, NULL
);
402 act
.sa_flags
|= SA_ONSTACK
;
403 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
404 sigaction (SIGSEGV
, &act
, NULL
);
406 __gnat_handler_installed
= 1;
409 /*********************/
410 /* GNU/Linux Section */
411 /*********************/
413 #elif defined (linux)
417 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
418 #include <sys/ucontext.h>
420 /* GNU/Linux, which uses glibc, does not define NULL in included
424 #define NULL ((void *) 0)
429 /* MaRTE OS provides its own version of sigaction, sigfillset, and
430 sigemptyset (overriding these symbol names). We want to make sure that
431 the versions provided by the underlying C library are used here (these
432 versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
433 and fake_linux_sigemptyset, respectively). The MaRTE library will not
434 always be present (it will not be linked if no tasking constructs are
435 used), so we use the weak symbol mechanism to point always to the symbols
436 defined within the C library. */
438 #pragma weak linux_sigaction
439 int linux_sigaction (int signum
, const struct sigaction
*act
,
440 struct sigaction
*oldact
) {
441 return sigaction (signum
, act
, oldact
);
443 #define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
445 #pragma weak fake_linux_sigfillset
446 void fake_linux_sigfillset (sigset_t
*set
) {
449 #define sigfillset(set) fake_linux_sigfillset (set)
451 #pragma weak fake_linux_sigemptyset
452 void fake_linux_sigemptyset (sigset_t
*set
) {
455 #define sigemptyset(set) fake_linux_sigemptyset (set)
459 #if defined (i386) || defined (__x86_64__) || defined (__ia64__)
461 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
464 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
, void *ucontext
)
466 mcontext_t
*mcontext
= &((ucontext_t
*) ucontext
)->uc_mcontext
;
468 /* On the i386 and x86-64 architectures, stack checking is performed by
469 means of probes with moving stack pointer, that is to say the probed
470 address is always the value of the stack pointer. Upon hitting the
471 guard page, the stack pointer therefore points to an inaccessible
472 address and an alternate signal stack is needed to run the handler.
473 But there is an additional twist: on these architectures, the EH
474 return code writes the address of the handler at the target CFA's
475 value on the stack before doing the jump. As a consequence, if
476 there is an active handler in the frame whose stack has overflowed,
477 the stack pointer must nevertheless point to an accessible address
478 by the time the EH return is executed.
480 We therefore adjust the saved value of the stack pointer by the size
481 of one page + a small dope of 4 words, in order to make sure that it
482 points to an accessible address in case it's used as the target CFA.
483 The stack checking code guarantees that this address is unused by the
484 time this happens. */
487 unsigned long *pc
= (unsigned long *)mcontext
->gregs
[REG_EIP
];
488 /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode. */
489 if (signo
== SIGSEGV
&& pc
&& *pc
== 0x00240c83)
490 mcontext
->gregs
[REG_ESP
] += 4096 + 4 * sizeof (unsigned long);
491 #elif defined (__x86_64__)
492 unsigned long long *pc
= (unsigned long long *)mcontext
->gregs
[REG_RIP
];
493 if (signo
== SIGSEGV
&& pc
494 /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode. */
495 && ((*pc
& 0xffffffffffLL
) == 0x00240c8348LL
496 /* The pattern may also be "orl $0x0,(%esp)" for a probe in
498 || (*pc
& 0xffffffffLL
) == 0x00240c83LL
))
499 mcontext
->gregs
[REG_RSP
] += 4096 + 4 * sizeof (unsigned long);
500 #elif defined (__ia64__)
501 /* ??? The IA-64 unwinder doesn't compensate for signals. */
509 __gnat_error_handler (int sig
, siginfo_t
*si ATTRIBUTE_UNUSED
, void *ucontext
)
511 struct Exception_Data
*exception
;
514 /* Adjusting is required for every fault context, so adjust for this one
515 now, before we possibly trigger a recursive fault below. */
516 __gnat_adjust_context_for_raise (sig
, ucontext
);
521 /* Here we would like a discrimination test to see whether the page
522 before the faulting address is accessible. Unfortunately, Linux
523 seems to have no way of giving us the faulting address.
525 In old versions of init.c, we had a test of the page before the
529 ((long) si->esp_at_signal & - getpagesize ()))[getpagesize ()];
531 but that's wrong since it tests the stack pointer location and the
532 stack probing code may not move it until all probes succeed.
534 For now we simply do not attempt any discrimination at all. Note
535 that this is quite acceptable, since a "real" SIGSEGV can only
536 occur as the result of an erroneous program. */
537 exception
= &storage_error
;
538 msg
= "stack overflow or erroneous memory access";
542 exception
= &storage_error
;
543 msg
= "SIGBUS: possible stack overflow";
547 exception
= &constraint_error
;
552 exception
= &program_error
;
553 msg
= "unhandled signal";
556 Raise_From_Signal_Handler (exception
, msg
);
559 #if defined (i386) || defined (__x86_64__) || defined (__powerpc__)
560 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
561 char __gnat_alternate_stack
[16 * 1024]; /* 2 * SIGSTKSZ */
565 #include <sys/mman.h>
566 #include <native/task.h>
572 __gnat_install_handler (void)
574 struct sigaction act
;
579 if (__gl_main_priority
== -1)
582 prio
= __gl_main_priority
;
584 /* Avoid memory swapping for this program */
586 mlockall (MCL_CURRENT
|MCL_FUTURE
);
588 /* Turn the current Linux task into a native Xenomai task */
590 rt_task_shadow(&main_task
, "environment_task", prio
, T_FPU
);
593 /* Set up signal handler to map synchronous signals to appropriate
594 exceptions. Make sure that the handler isn't interrupted by another
595 signal that might cause a scheduling event! Also setup an alternate
596 stack region for the handler execution so that stack overflows can be
597 handled properly, avoiding a SEGV generation from stack usage by the
600 #if defined (i386) || defined (__x86_64__) || defined (__powerpc__)
602 stack
.ss_sp
= __gnat_alternate_stack
;
603 stack
.ss_size
= sizeof (__gnat_alternate_stack
);
605 sigaltstack (&stack
, NULL
);
608 act
.sa_sigaction
= __gnat_error_handler
;
609 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_SIGINFO
;
610 sigemptyset (&act
.sa_mask
);
612 /* Do not install handlers if interrupt state is "System". */
613 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
614 sigaction (SIGABRT
, &act
, NULL
);
615 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
616 sigaction (SIGFPE
, &act
, NULL
);
617 if (__gnat_get_interrupt_state (SIGILL
) != 's')
618 sigaction (SIGILL
, &act
, NULL
);
619 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
620 sigaction (SIGBUS
, &act
, NULL
);
621 #if defined (i386) || defined (__x86_64__) || defined (__powerpc__)
622 act
.sa_flags
|= SA_ONSTACK
;
624 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
625 sigaction (SIGSEGV
, &act
, NULL
);
627 __gnat_handler_installed
= 1;
630 /*******************/
632 /*******************/
634 #elif defined (__Lynx__)
640 __gnat_error_handler (int sig
)
642 struct Exception_Data
*exception
;
648 exception
= &constraint_error
;
652 exception
= &constraint_error
;
656 exception
= &storage_error
;
657 msg
= "stack overflow or erroneous memory access";
660 exception
= &constraint_error
;
664 exception
= &program_error
;
665 msg
= "unhandled signal";
668 Raise_From_Signal_Handler(exception
, msg
);
672 __gnat_install_handler(void)
674 struct sigaction act
;
676 act
.sa_handler
= __gnat_error_handler
;
678 sigemptyset (&act
.sa_mask
);
680 /* Do not install handlers if interrupt state is "System". */
681 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
682 sigaction (SIGFPE
, &act
, NULL
);
683 if (__gnat_get_interrupt_state (SIGILL
) != 's')
684 sigaction (SIGILL
, &act
, NULL
);
685 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
686 sigaction (SIGSEGV
, &act
, NULL
);
687 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
688 sigaction (SIGBUS
, &act
, NULL
);
690 __gnat_handler_installed
= 1;
693 /*******************/
694 /* Solaris Section */
695 /*******************/
697 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
701 #include <sys/ucontext.h>
702 #include <sys/regset.h>
704 /* The code below is common to SPARC and x86. Beware of the delay slot
705 differences for signal context adjustments. */
707 #if defined (__sparc)
708 #define RETURN_ADDR_OFFSET 8
710 #define RETURN_ADDR_OFFSET 0
714 __gnat_error_handler (int sig
, siginfo_t
*si
, void *ucontext ATTRIBUTE_UNUSED
)
716 struct Exception_Data
*exception
;
717 static int recurse
= 0;
723 /* If the problem was permissions, this is a constraint error.
724 Likewise if the failing address isn't maximally aligned or if
727 ??? Using a static variable here isn't task-safe, but it's
728 much too hard to do anything else and we're just determining
729 which exception to raise. */
730 if (si
->si_code
== SEGV_ACCERR
731 || (long) si
->si_addr
== 0
732 || (((long) si
->si_addr
) & 3) != 0
735 exception
= &constraint_error
;
740 /* See if the page before the faulting page is accessible. Do that
741 by trying to access it. We'd like to simply try to access
742 4096 + the faulting address, but it's not guaranteed to be
743 the actual address, just to be on the same page. */
746 ((long) si
->si_addr
& - getpagesize ()))[getpagesize ()];
747 exception
= &storage_error
;
748 msg
= "stack overflow or erroneous memory access";
753 exception
= &program_error
;
758 exception
= &constraint_error
;
763 exception
= &program_error
;
764 msg
= "unhandled signal";
768 Raise_From_Signal_Handler (exception
, msg
);
772 __gnat_install_handler (void)
774 struct sigaction act
;
776 /* Set up signal handler to map synchronous signals to appropriate
777 exceptions. Make sure that the handler isn't interrupted by another
778 signal that might cause a scheduling event! */
780 act
.sa_sigaction
= __gnat_error_handler
;
781 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_SIGINFO
;
782 sigemptyset (&act
.sa_mask
);
784 /* Do not install handlers if interrupt state is "System". */
785 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
786 sigaction (SIGABRT
, &act
, NULL
);
787 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
788 sigaction (SIGFPE
, &act
, NULL
);
789 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
790 sigaction (SIGSEGV
, &act
, NULL
);
791 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
792 sigaction (SIGBUS
, &act
, NULL
);
794 __gnat_handler_installed
= 1;
803 /* Routine called from binder to override default feature values. */
804 void __gnat_set_features (void);
805 int __gnat_features_set
= 0;
808 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
809 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
810 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
812 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
813 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
814 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
817 /* Define macro symbols for the VMS conditions that become Ada exceptions.
818 Most of these are also defined in the header file ssdef.h which has not
819 yet been converted to be recognized by GNU C. */
821 /* Defining these as macros, as opposed to external addresses, allows
822 them to be used in a case statement below. */
823 #define SS$_ACCVIO 12
824 #define SS$_HPARITH 1284
825 #define SS$_STKOVF 1364
826 #define SS$_RESIGNAL 2328
828 /* These codes are in standard message libraries. */
829 extern int C$_SIGKILL
;
830 extern int SS$_DEBUG
;
831 extern int LIB$_KEYNOTFOU
;
832 extern int LIB$_ACTIMAGE
;
833 #define CMA$_EXIT_THREAD 4227492
834 #define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
835 #define SS$_INTDIV 1156
837 /* These codes are non standard, which is to say the author is
838 not sure if they are defined in the standard message libraries
839 so keep them as macros for now. */
840 #define RDB$_STREAM_EOF 20480426
841 #define FDL$_UNPRIKW 11829410
845 const struct Exception_Data
*except
;
848 struct descriptor_s
{
849 unsigned short len
, mbz
;
853 /* Conditions that don't have an Ada exception counterpart must raise
854 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
855 referenced by user programs, not the compiler or tools. Hence the
860 #define Status_Error ada__io_exceptions__status_error
861 extern struct Exception_Data Status_Error
;
863 #define Mode_Error ada__io_exceptions__mode_error
864 extern struct Exception_Data Mode_Error
;
866 #define Name_Error ada__io_exceptions__name_error
867 extern struct Exception_Data Name_Error
;
869 #define Use_Error ada__io_exceptions__use_error
870 extern struct Exception_Data Use_Error
;
872 #define Device_Error ada__io_exceptions__device_error
873 extern struct Exception_Data Device_Error
;
875 #define End_Error ada__io_exceptions__end_error
876 extern struct Exception_Data End_Error
;
878 #define Data_Error ada__io_exceptions__data_error
879 extern struct Exception_Data Data_Error
;
881 #define Layout_Error ada__io_exceptions__layout_error
882 extern struct Exception_Data Layout_Error
;
884 #define Non_Ada_Error system__aux_dec__non_ada_error
885 extern struct Exception_Data Non_Ada_Error
;
887 #define Coded_Exception system__vms_exception_table__coded_exception
888 extern struct Exception_Data
*Coded_Exception (Exception_Code
);
890 #define Base_Code_In system__vms_exception_table__base_code_in
891 extern Exception_Code
Base_Code_In (Exception_Code
);
893 /* DEC Ada exceptions are not defined in a header file, so they
896 #define ADA$_ALREADY_OPEN 0x0031a594
897 #define ADA$_CONSTRAINT_ERRO 0x00318324
898 #define ADA$_DATA_ERROR 0x003192c4
899 #define ADA$_DEVICE_ERROR 0x003195e4
900 #define ADA$_END_ERROR 0x00319904
901 #define ADA$_FAC_MODE_MISMAT 0x0031a8b3
902 #define ADA$_IOSYSFAILED 0x0031af04
903 #define ADA$_KEYSIZERR 0x0031aa3c
904 #define ADA$_KEY_MISMATCH 0x0031a8e3
905 #define ADA$_LAYOUT_ERROR 0x00319c24
906 #define ADA$_LINEXCMRS 0x0031a8f3
907 #define ADA$_MAXLINEXC 0x0031a8eb
908 #define ADA$_MODE_ERROR 0x00319f44
909 #define ADA$_MRN_MISMATCH 0x0031a8db
910 #define ADA$_MRS_MISMATCH 0x0031a8d3
911 #define ADA$_NAME_ERROR 0x0031a264
912 #define ADA$_NOT_OPEN 0x0031a58c
913 #define ADA$_ORG_MISMATCH 0x0031a8bb
914 #define ADA$_PROGRAM_ERROR 0x00318964
915 #define ADA$_RAT_MISMATCH 0x0031a8cb
916 #define ADA$_RFM_MISMATCH 0x0031a8c3
917 #define ADA$_STAOVF 0x00318cac
918 #define ADA$_STATUS_ERROR 0x0031a584
919 #define ADA$_STORAGE_ERROR 0x00318c84
920 #define ADA$_UNSUPPORTED 0x0031a8ab
921 #define ADA$_USE_ERROR 0x0031a8a4
923 /* DEC Ada specific conditions. */
924 static const struct cond_except dec_ada_cond_except_table
[] = {
925 {ADA$_PROGRAM_ERROR
, &program_error
},
926 {ADA$_USE_ERROR
, &Use_Error
},
927 {ADA$_KEYSIZERR
, &program_error
},
928 {ADA$_STAOVF
, &storage_error
},
929 {ADA$_CONSTRAINT_ERRO
, &constraint_error
},
930 {ADA$_IOSYSFAILED
, &Device_Error
},
931 {ADA$_LAYOUT_ERROR
, &Layout_Error
},
932 {ADA$_STORAGE_ERROR
, &storage_error
},
933 {ADA$_DATA_ERROR
, &Data_Error
},
934 {ADA$_DEVICE_ERROR
, &Device_Error
},
935 {ADA$_END_ERROR
, &End_Error
},
936 {ADA$_MODE_ERROR
, &Mode_Error
},
937 {ADA$_NAME_ERROR
, &Name_Error
},
938 {ADA$_STATUS_ERROR
, &Status_Error
},
939 {ADA$_NOT_OPEN
, &Use_Error
},
940 {ADA$_ALREADY_OPEN
, &Use_Error
},
941 {ADA$_USE_ERROR
, &Use_Error
},
942 {ADA$_UNSUPPORTED
, &Use_Error
},
943 {ADA$_FAC_MODE_MISMAT
, &Use_Error
},
944 {ADA$_ORG_MISMATCH
, &Use_Error
},
945 {ADA$_RFM_MISMATCH
, &Use_Error
},
946 {ADA$_RAT_MISMATCH
, &Use_Error
},
947 {ADA$_MRS_MISMATCH
, &Use_Error
},
948 {ADA$_MRN_MISMATCH
, &Use_Error
},
949 {ADA$_KEY_MISMATCH
, &Use_Error
},
950 {ADA$_MAXLINEXC
, &constraint_error
},
951 {ADA$_LINEXCMRS
, &constraint_error
},
954 /* Already handled by a pragma Import_Exception
955 in Aux_IO_Exceptions */
956 {ADA$_LOCK_ERROR
, &Lock_Error
},
957 {ADA$_EXISTENCE_ERROR
, &Existence_Error
},
958 {ADA$_KEY_ERROR
, &Key_Error
},
966 /* Non-DEC Ada specific conditions. We could probably also put
967 SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
968 static const struct cond_except cond_except_table
[] = {
969 {MTH$_FLOOVEMAT
, &constraint_error
},
970 {SS$_INTDIV
, &constraint_error
},
974 /* To deal with VMS conditions and their mapping to Ada exceptions,
975 the __gnat_error_handler routine below is installed as an exception
976 vector having precedence over DEC frame handlers. Some conditions
977 still need to be handled by such handlers, however, in which case
978 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
979 instance the use of a third party library compiled with DECAda and
980 performing its own exception handling internally.
982 To allow some user-level flexibility, which conditions should be
983 resignaled is controlled by a predicate function, provided with the
984 condition value and returning a boolean indication stating whether
985 this condition should be resignaled or not.
987 That predicate function is called indirectly, via a function pointer,
988 by __gnat_error_handler, and changing that pointer is allowed to the
989 user code by way of the __gnat_set_resignal_predicate interface.
991 The user level function may then implement what it likes, including
992 for instance the maintenance of a dynamic data structure if the set
993 of to be resignalled conditions has to change over the program's
996 ??? This is not a perfect solution to deal with the possible
997 interactions between the GNAT and the DECAda exception handling
998 models and better (more general) schemes are studied. This is so
999 just provided as a convenient workaround in the meantime, and
1000 should be use with caution since the implementation has been kept
1004 resignal_predicate (int code
);
1006 static const int * const cond_resignal_table
[] = {
1008 (int *)CMA$_EXIT_THREAD
,
1012 (int *) RDB$_STREAM_EOF
,
1013 (int *) FDL$_UNPRIKW
,
1017 static const int facility_resignal_table
[] = {
1018 0x1380000, /* RDB */
1019 0x2220000, /* SQL */
1023 /* Default GNAT predicate for resignaling conditions. */
1026 __gnat_default_resignal_p (int code
)
1030 for (i
= 0; facility_resignal_table
[i
]; i
++)
1031 if ((code
& 0xfff0000) == facility_resignal_table
[i
])
1034 for (i
= 0, iexcept
= 0;
1035 cond_resignal_table
[i
]
1036 && !(iexcept
= LIB$
MATCH_COND (&code
, &cond_resignal_table
[i
]));
1042 /* Static pointer to predicate that the __gnat_error_handler exception
1043 vector invokes to determine if it should resignal a condition. */
1045 static resignal_predicate
*__gnat_resignal_p
= __gnat_default_resignal_p
;
1047 /* User interface to change the predicate pointer to PREDICATE. Reset to
1048 the default if PREDICATE is null. */
1051 __gnat_set_resignal_predicate (resignal_predicate
*predicate
)
1053 if (predicate
== NULL
)
1054 __gnat_resignal_p
= __gnat_default_resignal_p
;
1056 __gnat_resignal_p
= predicate
;
1059 /* Should match System.Parameters.Default_Exception_Msg_Max_Length. */
1060 #define Default_Exception_Msg_Max_Length 512
1062 /* Action routine for SYS$PUTMSG. There may be multiple
1063 conditions, each with text to be appended to MESSAGE
1064 and separated by line termination. */
1067 copy_msg (struct descriptor_s
*msgdesc
, char *message
)
1069 int len
= strlen (message
);
1072 /* Check for buffer overflow and skip. */
1073 if (len
> 0 && len
<= Default_Exception_Msg_Max_Length
- 3)
1075 strcat (message
, "\r\n");
1079 /* Check for buffer overflow and truncate if necessary. */
1080 copy_len
= (len
+ msgdesc
->len
<= Default_Exception_Msg_Max_Length
- 1 ?
1082 Default_Exception_Msg_Max_Length
- 1 - len
);
1083 strncpy (&message
[len
], msgdesc
->adr
, copy_len
);
1084 message
[len
+ copy_len
] = 0;
1090 __gnat_handle_vms_condition (int *sigargs
, void *mechargs
)
1092 struct Exception_Data
*exception
= 0;
1093 Exception_Code base_code
;
1094 struct descriptor_s gnat_facility
= {4, 0, "GNAT"};
1095 char message
[Default_Exception_Msg_Max_Length
];
1097 const char *msg
= "";
1099 /* Check for conditions to resignal which aren't effected by pragma
1100 Import_Exception. */
1101 if (__gnat_resignal_p (sigargs
[1]))
1102 return SS$_RESIGNAL
;
1105 /* See if it's an imported exception. Beware that registered exceptions
1106 are bound to their base code, with the severity bits masked off. */
1107 base_code
= Base_Code_In ((Exception_Code
) sigargs
[1]);
1108 exception
= Coded_Exception (base_code
);
1114 /* Subtract PC & PSL fields which messes with PUTMSG. */
1116 SYS$
PUTMSG (sigargs
, copy_msg
, &gnat_facility
, message
);
1120 exception
->Name_Length
= 19;
1121 /* ??? The full name really should be get SYS$GETMSG returns. */
1122 exception
->Full_Name
= "IMPORTED_EXCEPTION";
1123 exception
->Import_Code
= base_code
;
1126 /* Do not adjust the program counter as already points to the next
1127 instruction (just after the call to LIB$STOP). */
1128 Raise_From_Signal_Handler (exception
, msg
);
1137 if (sigargs
[3] == 0)
1139 exception
= &constraint_error
;
1140 msg
= "access zero";
1144 exception
= &storage_error
;
1145 msg
= "stack overflow or erroneous memory access";
1147 __gnat_adjust_context_for_raise (SS$_ACCVIO
, (void *)mechargs
);
1151 exception
= &storage_error
;
1152 msg
= "stack overflow";
1153 __gnat_adjust_context_for_raise (SS$_STKOVF
, (void *)mechargs
);
1158 return SS$_RESIGNAL
; /* toplev.c handles for compiler */
1160 exception
= &constraint_error
;
1161 msg
= "arithmetic error";
1162 __gnat_adjust_context_for_raise (SS$_HPARITH
, (void *)mechargs
);
1171 /* Scan the DEC Ada exception condition table for a match and fetch
1172 the associated GNAT exception pointer. */
1174 dec_ada_cond_except_table
[i
].cond
&&
1175 !LIB$
MATCH_COND (&sigargs
[1],
1176 &dec_ada_cond_except_table
[i
].cond
);
1178 exception
= (struct Exception_Data
*)
1179 dec_ada_cond_except_table
[i
].except
;
1183 /* Scan the VMS standard condition table for a match and fetch
1184 the associated GNAT exception pointer. */
1186 cond_except_table
[i
].cond
&&
1187 !LIB$
MATCH_COND (&sigargs
[1], &cond_except_table
[i
].cond
);
1189 exception
= (struct Exception_Data
*)
1190 cond_except_table
[i
].except
;
1193 /* User programs expect Non_Ada_Error to be raised, reference
1194 DEC Ada test CXCONDHAN. */
1195 exception
= &Non_Ada_Error
;
1199 exception
= &program_error
;
1202 /* Subtract PC & PSL fields which messes with PUTMSG. */
1204 SYS$
PUTMSG (sigargs
, copy_msg
, &gnat_facility
, message
);
1210 Raise_From_Signal_Handler (exception
, msg
);
1214 __gnat_install_handler (void)
1216 long prvhnd ATTRIBUTE_UNUSED
;
1218 #if !defined (IN_RTS)
1219 SYS$
SETEXV (1, __gnat_handle_vms_condition
, 3, &prvhnd
);
1222 __gnat_handler_installed
= 1;
1225 /* __gnat_adjust_context_for_raise for Alpha - see comments along with the
1226 default version later in this file. */
1228 #if defined (IN_RTS) && defined (__alpha__)
1230 #include <vms/chfctxdef.h>
1231 #include <vms/chfdef.h>
1233 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1236 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
, void *ucontext
)
1238 if (signo
== SS$_HPARITH
)
1240 /* Sub one to the address of the instruction signaling the condition,
1241 located in the sigargs array. */
1243 CHF$MECH_ARRAY
* mechargs
= (CHF$MECH_ARRAY
*) ucontext
;
1244 CHF$SIGNAL_ARRAY
* sigargs
1245 = (CHF$SIGNAL_ARRAY
*) mechargs
->chf$q_mch_sig_addr
;
1247 int vcount
= sigargs
->chf$is_sig_args
;
1248 int * pc_slot
= & (&sigargs
->chf$l_sig_name
)[vcount
-2];
1256 /* __gnat_adjust_context_for_raise for ia64. */
1258 #if defined (IN_RTS) && defined (__IA64)
1260 #include <vms/chfctxdef.h>
1261 #include <vms/chfdef.h>
1263 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1265 typedef unsigned long long u64
;
1268 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
, void *ucontext
)
1270 /* Add one to the address of the instruction signaling the condition,
1271 located in the 64bits sigargs array. */
1273 CHF$MECH_ARRAY
* mechargs
= (CHF$MECH_ARRAY
*) ucontext
;
1275 CHF64$SIGNAL_ARRAY
*chfsig64
1276 = (CHF64$SIGNAL_ARRAY
*) mechargs
->chf$ph_mch_sig64_addr
;
1279 = (u64
*)chfsig64
+ 1 + chfsig64
->chf64$l_sig_args
;
1281 u64
* ih_pc_loc
= post_sigarray
- 2;
1288 /* Easier interface for LIB$GET_LOGICAL: put the equivalence of NAME into BUF,
1289 always NUL terminated. In case of error or if the result is longer than
1290 LEN (length of BUF) an empty string is written info BUF. */
1293 __gnat_vms_get_logical (const char *name
, char *buf
, int len
)
1295 struct descriptor_s name_desc
, result_desc
;
1297 unsigned short rlen
;
1299 /* Build the descriptor for NAME. */
1300 name_desc
.len
= strlen (name
);
1302 name_desc
.adr
= (char *)name
;
1304 /* Build the descriptor for the result. */
1305 result_desc
.len
= len
;
1306 result_desc
.mbz
= 0;
1307 result_desc
.adr
= buf
;
1309 status
= LIB$
GET_LOGICAL (&name_desc
, &result_desc
, &rlen
);
1311 if ((status
& 1) == 1 && rlen
< len
)
1317 /* Size of a page on ia64 and alpha VMS. */
1318 #define VMS_PAGESIZE 8192
1321 #define PSL__C_USER 3
1326 /* Descending region. */
1327 #define VA__M_DESCEND 1
1329 /* Get by virtual address. */
1330 #define VA___REGSUM_BY_VA 1
1332 /* Memory region summary. */
1335 unsigned long long q_region_id
;
1336 unsigned int l_flags
;
1337 unsigned int l_region_protection
;
1339 unsigned long long q_region_size
;
1340 void *pq_first_free_va
;
1343 extern int SYS$
GET_REGION_INFO (unsigned int, unsigned long long *,
1344 void *, void *, unsigned int,
1345 void *, unsigned int *);
1346 extern int SYS$
EXPREG_64 (unsigned long long *, unsigned long long,
1347 unsigned int, unsigned int, void **,
1348 unsigned long long *);
1349 extern int SYS$
SETPRT_64 (void *, unsigned long long, unsigned int,
1350 unsigned int, void **, unsigned long long *,
1352 extern int SYS$
PUTMSG (void *, int (*)(), void *, unsigned long long);
1354 /* Add a guard page in the memory region containing ADDR at ADDR +/- SIZE.
1355 (The sign depends on the kind of the memory region). */
1358 __gnat_set_stack_guard_page (void *addr
, unsigned long size
)
1362 unsigned long long ret_len
;
1363 unsigned int ret_prot
;
1365 unsigned long long length
;
1366 unsigned int retlen
;
1367 struct regsum buffer
;
1369 /* Get the region for ADDR. */
1370 status
= SYS$GET_REGION_INFO
1371 (VA___REGSUM_BY_VA
, NULL
, addr
, NULL
, sizeof (buffer
), &buffer
, &retlen
);
1373 if ((status
& 1) != 1)
1376 /* Extend the region. */
1377 status
= SYS$
EXPREG_64 (&buffer
.q_region_id
,
1378 size
, 0, 0, &start_va
, &length
);
1380 if ((status
& 1) != 1)
1383 /* Create a guard page. */
1384 if (!(buffer
.l_flags
& VA__M_DESCEND
))
1385 start_va
= (void *)((unsigned long long)start_va
+ length
- VMS_PAGESIZE
);
1387 status
= SYS$
SETPRT_64 (start_va
, VMS_PAGESIZE
, PSL__C_USER
, PRT__C_NA
,
1388 &ret_va
, &ret_len
, &ret_prot
);
1390 if ((status
& 1) != 1)
1395 /* Read logicals to limit the stack(s) size. */
1398 __gnat_set_stack_limit (void)
1406 /* The main stack. */
1407 __gnat_vms_get_logical ("GNAT_STACK_SIZE", value
, sizeof (value
));
1408 size
= strtoul (value
, &e
, 0);
1409 if (e
> value
&& *e
== 0)
1411 asm ("mov %0=sp" : "=r" (sp
));
1412 __gnat_set_stack_guard_page (sp
, size
* 1024);
1415 /* The register stack. */
1416 __gnat_vms_get_logical ("GNAT_RBS_SIZE", value
, sizeof (value
));
1417 size
= strtoul (value
, &e
, 0);
1418 if (e
> value
&& *e
== 0)
1420 asm ("mov %0=ar.bsp" : "=r" (sp
));
1421 __gnat_set_stack_guard_page (sp
, size
* 1024);
1426 /* Feature logical name and global variable address pair.
1427 If we ever add another feature logical to this list, the
1428 feature struct will need to be enhanced to take into account
1429 possible values for *gl_addr. */
1435 /* Default values for GNAT features set by environment. */
1436 int __gl_heap_size
= 64;
1438 /* Array feature logical names and global variable addresses. */
1439 static const struct feature features
[] = {
1440 {"GNAT$NO_MALLOC_64", &__gl_heap_size
},
1445 __gnat_set_features (void)
1450 /* Loop through features array and test name for enable/disable. */
1451 for (i
= 0; features
[i
].name
; i
++)
1453 __gnat_vms_get_logical (features
[i
].name
, buff
, sizeof (buff
));
1455 if (strcmp (buff
, "ENABLE") == 0
1456 || strcmp (buff
, "TRUE") == 0
1457 || strcmp (buff
, "1") == 0)
1458 *features
[i
].gl_addr
= 32;
1459 else if (strcmp (buff
, "DISABLE") == 0
1460 || strcmp (buff
, "FALSE") == 0
1461 || strcmp (buff
, "0") == 0)
1462 *features
[i
].gl_addr
= 64;
1465 /* Features to artificially limit the stack size. */
1466 __gnat_set_stack_limit ();
1468 __gnat_features_set
= 1;
1471 /* Return true if the VMS version is 7.x. */
1473 extern unsigned int LIB$
GETSYI (int *, ...);
1475 #define SYI$_VERSION 0x1000
1478 __gnat_is_vms_v7 (void)
1480 struct descriptor_s desc
;
1483 int code
= SYI$_VERSION
;
1485 desc
.len
= sizeof (version
);
1489 status
= LIB$
GETSYI (&code
, 0, &desc
);
1490 if ((status
& 1) == 1 && version
[1] == '7' && version
[2] == '.')
1496 /*******************/
1497 /* FreeBSD Section */
1498 /*******************/
1500 #elif defined (__FreeBSD__)
1503 #include <sys/ucontext.h>
1507 __gnat_error_handler (int sig
,
1508 siginfo_t
*si ATTRIBUTE_UNUSED
,
1509 void *ucontext ATTRIBUTE_UNUSED
)
1511 struct Exception_Data
*exception
;
1517 exception
= &constraint_error
;
1522 exception
= &constraint_error
;
1527 exception
= &storage_error
;
1528 msg
= "stack overflow or erroneous memory access";
1532 exception
= &storage_error
;
1533 msg
= "SIGBUS: possible stack overflow";
1537 exception
= &program_error
;
1538 msg
= "unhandled signal";
1541 Raise_From_Signal_Handler (exception
, msg
);
1545 __gnat_install_handler ()
1547 struct sigaction act
;
1549 /* Set up signal handler to map synchronous signals to appropriate
1550 exceptions. Make sure that the handler isn't interrupted by another
1551 signal that might cause a scheduling event! */
1554 = (void (*)(int, struct __siginfo
*, void*)) __gnat_error_handler
;
1555 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_SIGINFO
;
1556 (void) sigemptyset (&act
.sa_mask
);
1558 (void) sigaction (SIGILL
, &act
, NULL
);
1559 (void) sigaction (SIGFPE
, &act
, NULL
);
1560 (void) sigaction (SIGSEGV
, &act
, NULL
);
1561 (void) sigaction (SIGBUS
, &act
, NULL
);
1563 __gnat_handler_installed
= 1;
1566 /*******************/
1567 /* VxWorks Section */
1568 /*******************/
1570 #elif defined(__vxworks)
1573 #include <taskLib.h>
1581 #include "private/vThreadsP.h"
1584 void __gnat_error_handler (int, void *, struct sigcontext
*);
1588 /* Directly vectored Interrupt routines are not supported when using RTPs. */
1590 extern int __gnat_inum_to_ivec (int);
1592 /* This is needed by the GNAT run time to handle Vxworks interrupts. */
1594 __gnat_inum_to_ivec (int num
)
1596 return INUM_TO_IVEC (num
);
1600 #if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1602 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1603 on Alpha VxWorks and VxWorks 6.x (including RTPs). */
1605 extern long getpid (void);
1610 return taskIdSelf ();
1614 /* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
1615 handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
1618 __gnat_clear_exception_count (void)
1621 WIND_TCB
*currentTask
= (WIND_TCB
*) taskIdSelf();
1623 currentTask
->vThreads
.excCnt
= 0;
1627 /* Handle different SIGnal to exception mappings in different VxWorks
1630 __gnat_map_signal (int sig
, void *si ATTRIBUTE_UNUSED
,
1631 struct sigcontext
*sc ATTRIBUTE_UNUSED
)
1633 struct Exception_Data
*exception
;
1639 exception
= &constraint_error
;
1643 #ifdef __VXWORKSMILS__
1645 exception
= &storage_error
;
1646 msg
= "SIGILL: possible stack overflow";
1649 exception
= &storage_error
;
1653 exception
= &program_error
;
1658 exception
= &constraint_error
;
1659 msg
= "Floating point exception or SIGILL";
1662 exception
= &storage_error
;
1666 exception
= &storage_error
;
1667 msg
= "SIGBUS: possible stack overflow";
1670 #elif (_WRS_VXWORKS_MAJOR == 6)
1672 exception
= &constraint_error
;
1676 /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
1677 since stack checking uses the probing mechanism. */
1679 exception
= &storage_error
;
1680 msg
= "SIGSEGV: possible stack overflow";
1683 exception
= &program_error
;
1687 /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
1689 exception
= &storage_error
;
1693 exception
= &storage_error
;
1694 msg
= "SIGBUS: possible stack overflow";
1698 /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
1699 since stack checking uses the stack limit mechanism. */
1701 exception
= &storage_error
;
1702 msg
= "SIGILL: possible stack overflow";
1705 exception
= &storage_error
;
1709 exception
= &program_error
;
1714 exception
= &program_error
;
1715 msg
= "unhandled signal";
1718 __gnat_clear_exception_count ();
1719 Raise_From_Signal_Handler (exception
, msg
);
1722 /* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
1723 propagation after the required low level adjustments. */
1726 __gnat_error_handler (int sig
, void *si
, struct sigcontext
*sc
)
1730 /* VxWorks will always mask out the signal during the signal handler and
1731 will reenable it on a longjmp. GNAT does not generate a longjmp to
1732 return from a signal handler so the signal will still be masked unless
1734 sigprocmask (SIG_SETMASK
, NULL
, &mask
);
1735 sigdelset (&mask
, sig
);
1736 sigprocmask (SIG_SETMASK
, &mask
, NULL
);
1738 #if defined (__PPC__) && defined(_WRS_KERNEL)
1739 /* On PowerPC, kernel mode, we process signals through a Call Frame Info
1740 trampoline, voiding the need for myriads of fallback_frame_state
1741 variants in the ZCX runtime. We have no simple way to distinguish ZCX
1742 from SJLJ here, so we do this for SJLJ as well even though this is not
1743 necessary. This only incurs a few extra instructions and a tiny
1744 amount of extra stack usage. */
1746 #include "sigtramp.h"
1748 __gnat_sigtramp (sig
, (void *)si
, (void *)sc
,
1749 (sighandler_t
*)&__gnat_map_signal
);
1752 __gnat_map_signal (sig
, si
, sc
);
1757 __gnat_install_handler (void)
1759 struct sigaction act
;
1761 /* Setup signal handler to map synchronous signals to appropriate
1762 exceptions. Make sure that the handler isn't interrupted by another
1763 signal that might cause a scheduling event! */
1765 act
.sa_handler
= __gnat_error_handler
;
1766 act
.sa_flags
= SA_SIGINFO
| SA_ONSTACK
;
1767 sigemptyset (&act
.sa_mask
);
1769 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1770 applies to vectored hardware interrupts, not signals. */
1771 sigaction (SIGFPE
, &act
, NULL
);
1772 sigaction (SIGILL
, &act
, NULL
);
1773 sigaction (SIGSEGV
, &act
, NULL
);
1774 sigaction (SIGBUS
, &act
, NULL
);
1776 __gnat_handler_installed
= 1;
1779 #define HAVE_GNAT_INIT_FLOAT
1782 __gnat_init_float (void)
1784 /* Disable overflow/underflow exceptions on the PPC processor, needed
1785 to get correct Ada semantics. Note that for AE653 vThreads, the HW
1786 overflow settings are an OS configuration issue. The instructions
1787 below have no effect. */
1788 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && (!defined (VTHREADS) || defined (__VXWORKSMILS__))
1789 #if defined (__SPE__)
1791 const unsigned long spefscr_mask
= 0xfffffff3;
1792 unsigned long spefscr
;
1793 asm ("mfspr %0, 512" : "=r" (spefscr
));
1794 spefscr
= spefscr
& spefscr_mask
;
1795 asm ("mtspr 512, %0\n\tisync" : : "r" (spefscr
));
1803 #if (defined (__i386__) || defined (i386)) && !defined (VTHREADS)
1804 /* This is used to properly initialize the FPU on an x86 for each
1809 /* Similarly for SPARC64. Achieved by masking bits in the Trap Enable Mask
1810 field of the Floating-point Status Register (see the SPARC Architecture
1811 Manual Version 9, p 48). */
1812 #if defined (sparc64)
1814 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1815 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1816 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1817 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1818 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1822 __asm__("st %%fsr, %0" : "=m" (fsr
));
1823 fsr
&= ~(FSR_TEM_OFM
| FSR_TEM_UFM
);
1824 __asm__("ld %0, %%fsr" : : "m" (fsr
));
1829 /* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
1830 (if not null) when a new task is created. It is initialized by
1831 System.Stack_Checking.Operations.Initialize_Stack_Limit.
1832 The use of a hook avoids to drag stack checking subprograms if stack
1833 checking is not used. */
1834 void (*__gnat_set_stack_limit_hook
)(void) = (void (*)(void))0;
1836 /******************/
1837 /* NetBSD Section */
1838 /******************/
1840 #elif defined(__NetBSD__)
1846 __gnat_error_handler (int sig
)
1848 struct Exception_Data
*exception
;
1854 exception
= &constraint_error
;
1858 exception
= &constraint_error
;
1862 exception
= &storage_error
;
1863 msg
= "stack overflow or erroneous memory access";
1866 exception
= &constraint_error
;
1870 exception
= &program_error
;
1871 msg
= "unhandled signal";
1874 Raise_From_Signal_Handler(exception
, msg
);
1878 __gnat_install_handler(void)
1880 struct sigaction act
;
1882 act
.sa_handler
= __gnat_error_handler
;
1883 act
.sa_flags
= SA_NODEFER
| SA_RESTART
;
1884 sigemptyset (&act
.sa_mask
);
1886 /* Do not install handlers if interrupt state is "System". */
1887 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
1888 sigaction (SIGFPE
, &act
, NULL
);
1889 if (__gnat_get_interrupt_state (SIGILL
) != 's')
1890 sigaction (SIGILL
, &act
, NULL
);
1891 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
1892 sigaction (SIGSEGV
, &act
, NULL
);
1893 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
1894 sigaction (SIGBUS
, &act
, NULL
);
1896 __gnat_handler_installed
= 1;
1899 /*******************/
1900 /* OpenBSD Section */
1901 /*******************/
1903 #elif defined(__OpenBSD__)
1909 __gnat_error_handler (int sig
)
1911 struct Exception_Data
*exception
;
1917 exception
= &constraint_error
;
1921 exception
= &constraint_error
;
1925 exception
= &storage_error
;
1926 msg
= "stack overflow or erroneous memory access";
1929 exception
= &constraint_error
;
1933 exception
= &program_error
;
1934 msg
= "unhandled signal";
1937 Raise_From_Signal_Handler(exception
, msg
);
1941 __gnat_install_handler(void)
1943 struct sigaction act
;
1945 act
.sa_handler
= __gnat_error_handler
;
1946 act
.sa_flags
= SA_NODEFER
| SA_RESTART
;
1947 sigemptyset (&act
.sa_mask
);
1949 /* Do not install handlers if interrupt state is "System" */
1950 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
1951 sigaction (SIGFPE
, &act
, NULL
);
1952 if (__gnat_get_interrupt_state (SIGILL
) != 's')
1953 sigaction (SIGILL
, &act
, NULL
);
1954 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
1955 sigaction (SIGSEGV
, &act
, NULL
);
1956 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
1957 sigaction (SIGBUS
, &act
, NULL
);
1959 __gnat_handler_installed
= 1;
1962 /******************/
1963 /* Darwin Section */
1964 /******************/
1966 #elif defined(__APPLE__)
1969 #include <sys/syscall.h>
1970 #include <mach/mach_vm.h>
1971 #include <mach/mach_init.h>
1972 #include <mach/vm_statistics.h>
1974 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
1975 char __gnat_alternate_stack
[32 * 1024]; /* 1 * MINSIGSTKSZ */
1977 /* Defined in xnu unix_signal.c.
1978 Tell the kernel to re-use alt stack when delivering a signal. */
1979 #define UC_RESET_ALT_STACK 0x80000000
1981 /* Return true if ADDR is within a stack guard area. */
1983 __gnat_is_stack_guard (mach_vm_address_t addr
)
1986 vm_region_submap_info_data_64_t info
;
1987 mach_vm_address_t start
;
1988 mach_vm_size_t size
;
1990 mach_msg_type_number_t count
;
1992 count
= VM_REGION_SUBMAP_INFO_COUNT_64
;
1996 kret
= mach_vm_region_recurse (mach_task_self (), &start
, &size
, &depth
,
1997 (vm_region_recurse_info_t
) &info
, &count
);
1998 if (kret
== KERN_SUCCESS
1999 && addr
>= start
&& addr
< (start
+ size
)
2000 && info
.protection
== VM_PROT_NONE
2001 && info
.user_tag
== VM_MEMORY_STACK
)
2006 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2009 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
,
2010 void *ucontext ATTRIBUTE_UNUSED
)
2012 #if defined (__x86_64__)
2013 /* Work around radar #10302855/pr50678, where the unwinders (libunwind or
2014 libgcc_s depending on the system revision) and the DWARF unwind data for
2015 the sigtramp have different ideas about register numbering (causing rbx
2016 and rdx to be transposed).. */
2017 ucontext_t
*uc
= (ucontext_t
*)ucontext
;
2018 unsigned long t
= uc
->uc_mcontext
->__ss
.__rbx
;
2020 uc
->uc_mcontext
->__ss
.__rbx
= uc
->uc_mcontext
->__ss
.__rdx
;
2021 uc
->uc_mcontext
->__ss
.__rdx
= t
;
2026 __gnat_error_handler (int sig
, siginfo_t
*si
, void *ucontext
)
2028 struct Exception_Data
*exception
;
2031 __gnat_adjust_context_for_raise (sig
, ucontext
);
2037 if (__gnat_is_stack_guard ((unsigned long)si
->si_addr
))
2039 exception
= &storage_error
;
2040 msg
= "stack overflow";
2044 exception
= &constraint_error
;
2045 msg
= "erroneous memory access";
2047 /* Reset the use of alt stack, so that the alt stack will be used
2048 for the next signal delivery.
2049 The stack can't be used in case of stack checking. */
2050 syscall (SYS_sigreturn
, NULL
, UC_RESET_ALT_STACK
);
2054 exception
= &constraint_error
;
2059 exception
= &program_error
;
2060 msg
= "unhandled signal";
2063 Raise_From_Signal_Handler (exception
, msg
);
2067 __gnat_install_handler (void)
2069 struct sigaction act
;
2071 /* Set up signal handler to map synchronous signals to appropriate
2072 exceptions. Make sure that the handler isn't interrupted by another
2073 signal that might cause a scheduling event! Also setup an alternate
2074 stack region for the handler execution so that stack overflows can be
2075 handled properly, avoiding a SEGV generation from stack usage by the
2076 handler itself (and it is required by Darwin). */
2079 stack
.ss_sp
= __gnat_alternate_stack
;
2080 stack
.ss_size
= sizeof (__gnat_alternate_stack
);
2082 sigaltstack (&stack
, NULL
);
2084 act
.sa_flags
= SA_NODEFER
| SA_RESTART
| SA_SIGINFO
;
2085 act
.sa_sigaction
= __gnat_error_handler
;
2086 sigemptyset (&act
.sa_mask
);
2088 /* Do not install handlers if interrupt state is "System". */
2089 if (__gnat_get_interrupt_state (SIGABRT
) != 's')
2090 sigaction (SIGABRT
, &act
, NULL
);
2091 if (__gnat_get_interrupt_state (SIGFPE
) != 's')
2092 sigaction (SIGFPE
, &act
, NULL
);
2093 if (__gnat_get_interrupt_state (SIGILL
) != 's')
2094 sigaction (SIGILL
, &act
, NULL
);
2096 act
.sa_flags
|= SA_ONSTACK
;
2097 if (__gnat_get_interrupt_state (SIGSEGV
) != 's')
2098 sigaction (SIGSEGV
, &act
, NULL
);
2099 if (__gnat_get_interrupt_state (SIGBUS
) != 's')
2100 sigaction (SIGBUS
, &act
, NULL
);
2102 __gnat_handler_installed
= 1;
2107 /* For all other versions of GNAT, the handler does nothing. */
2109 /*******************/
2110 /* Default Section */
2111 /*******************/
2114 __gnat_install_handler (void)
2116 __gnat_handler_installed
= 1;
2121 /*********************/
2122 /* __gnat_init_float */
2123 /*********************/
2125 /* This routine is called as each process thread is created, for possible
2126 initialization of the FP processor. This version is used under INTERIX
2129 #if defined (_WIN32) || defined (__INTERIX) \
2130 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
2131 || defined (__OpenBSD__)
2133 #define HAVE_GNAT_INIT_FLOAT
2136 __gnat_init_float (void)
2138 #if defined (__i386__) || defined (i386) || defined (__x86_64)
2140 /* This is used to properly initialize the FPU on an x86 for each
2145 #endif /* Defined __i386__ */
2149 #ifndef HAVE_GNAT_INIT_FLOAT
2151 /* All targets without a specific __gnat_init_float will use an empty one. */
2153 __gnat_init_float (void)
2158 /***********************************/
2159 /* __gnat_adjust_context_for_raise */
2160 /***********************************/
2162 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2164 /* All targets without a specific version will use an empty one. */
2166 /* Given UCONTEXT a pointer to a context structure received by a signal
2167 handler for SIGNO, perform the necessary adjustments to let the handler
2168 raise an exception. Calls to this routine are not conditioned by the
2169 propagation scheme in use. */
2172 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED
,
2173 void *ucontext ATTRIBUTE_UNUSED
)
2175 /* We used to compensate here for the raised from call vs raised from signal
2176 exception discrepancy with the GCC ZCX scheme, but this now can be dealt
2177 with generically in the unwinder (see GCC PR other/26208). This however
2178 requires the use of the _Unwind_GetIPInfo routine in raise-gcc.c, which
2179 is predicated on the definition of HAVE_GETIPINFO at compile time. Only
2180 the VMS ports still do the compensation described in the few lines below.
2182 *** Call vs signal exception discrepancy with GCC ZCX scheme ***
2184 The GCC unwinder expects to be dealing with call return addresses, since
2185 this is the "nominal" case of what we retrieve while unwinding a regular
2188 To evaluate if a handler applies at some point identified by a return
2189 address, the propagation engine needs to determine what region the
2190 corresponding call instruction pertains to. Because the return address
2191 may not be attached to the same region as the call, the unwinder always
2192 subtracts "some" amount from a return address to search the region
2193 tables, amount chosen to ensure that the resulting address is inside the
2196 When we raise an exception from a signal handler, e.g. to transform a
2197 SIGSEGV into Storage_Error, things need to appear as if the signal
2198 handler had been "called" by the instruction which triggered the signal,
2199 so that exception handlers that apply there are considered. What the
2200 unwinder will retrieve as the return address from the signal handler is
2201 what it will find as the faulting instruction address in the signal
2202 context pushed by the kernel. Leaving this address untouched looses, if
2203 the triggering instruction happens to be the very first of a region, as
2204 the later adjustments performed by the unwinder would yield an address
2205 outside that region. We need to compensate for the unwinder adjustments
2206 at some point, and this is what this routine is expected to do.
2208 signo is passed because on some targets for some signals the PC in
2209 context points to the instruction after the faulting one, in which case
2210 the unwinder adjustment is still desired. */