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