1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2007, 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 2, 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. See the GNU General Public License *
17 * for more details. You should have received a copy of the GNU General *
18 * Public License distributed with GNAT; see file COPYING. If not, write *
19 * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
22 * As a special exception, if you link this file with other files to *
23 * produce an executable, this file does not by itself cause the resulting *
24 * executable to be covered by the GNU General Public License. This except- *
25 * ion does not however invalidate any other reasons why the executable *
26 * file might be covered by the GNU Public License. *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
31 ****************************************************************************/
33 /* This unit contains initialization circuits that are system dependent. A
34 major part of the functionality involved involves stack overflow checking.
35 The GCC backend generates probe instructions to test for stack overflow.
36 For details on the exact approach used to generate these probes, see the
37 "Using and Porting GCC" manual, in particular the "Stack Checking" section
38 and the subsection "Specifying How Stack Checking is Done". The handlers
39 installed by this file are used to handle resulting signals that come
40 from these probes failing (i.e. touching protected pages) */
42 /* This file should be kept synchronized with 2sinit.ads, 2sinit.adb,
43 s-init-ae653-cert.adb and s-init-xi-sparc.adb. All these files implement
44 the required functionality for different targets. */
46 /* The following include is here to meet the published VxWorks requirement
47 that the __vxworks header appear before any other include. */
57 /* We don't have libiberty, so us malloc. */
58 #define xmalloc(S) malloc (S)
67 extern void __gnat_raise_program_error (const char *, int);
69 /* Addresses of exception data blocks for predefined exceptions. Tasking_Error
70 is not used in this unit, and the abort signal is only used on IRIX. */
71 extern struct Exception_Data constraint_error;
72 extern struct Exception_Data numeric_error;
73 extern struct Exception_Data program_error;
74 extern struct Exception_Data storage_error;
76 /* For the Cert run time we use the regular raise exception routine because
77 Raise_From_Signal_Handler is not available. */
79 #define Raise_From_Signal_Handler \
80 __gnat_raise_exception
81 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
83 #define Raise_From_Signal_Handler \
84 ada__exceptions__raise_from_signal_handler
85 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
88 /* Global values computed by the binder */
89 int __gl_main_priority = -1;
90 int __gl_time_slice_val = -1;
91 char __gl_wc_encoding = 'n';
92 char __gl_locking_policy = ' ';
93 char __gl_queuing_policy = ' ';
94 char __gl_task_dispatching_policy = ' ';
95 char *__gl_priority_specific_dispatching = 0;
96 int __gl_num_specific_dispatching = 0;
97 char *__gl_interrupt_states = 0;
98 int __gl_num_interrupt_states = 0;
99 int __gl_unreserve_all_interrupts = 0;
100 int __gl_exception_tracebacks = 0;
101 int __gl_zero_cost_exceptions = 0;
102 int __gl_detect_blocking = 0;
103 int __gl_default_stack_size = -1;
105 /* Indication of whether synchronous signal handler has already been
106 installed by a previous call to adainit */
107 int __gnat_handler_installed = 0;
110 int __gnat_inside_elab_final_code = 0;
111 /* ??? This variable is obsolete since 2001-08-29 but is kept to allow
112 bootstrap from old GNAT versions (< 3.15). */
115 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
116 is defined. If this is not set them a void implementation will be defined
117 at the end of this unit. */
118 #undef HAVE_GNAT_INIT_FLOAT
120 /******************************/
121 /* __gnat_get_interrupt_state */
122 /******************************/
124 char __gnat_get_interrupt_state (int);
126 /* This routine is called from the runtime as needed to determine the state
127 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
128 in the current partition. The input argument is the interrupt number,
129 and the result is one of the following:
131 'n' this interrupt not set by any Interrupt_State pragma
132 'u' Interrupt_State pragma set state to User
133 'r' Interrupt_State pragma set state to Runtime
134 's' Interrupt_State pragma set state to System */
137 __gnat_get_interrupt_state (int intrup)
139 if (intrup >= __gl_num_interrupt_states)
142 return __gl_interrupt_states [intrup];
145 /***********************************/
146 /* __gnat_get_specific_dispatching */
147 /***********************************/
149 char __gnat_get_specific_dispatching (int);
151 /* This routine is called from the run time as needed to determine the
152 priority specific dispatching policy, as set by a
153 Priority_Specific_Dispatching pragma appearing anywhere in the current
154 partition. The input argument is the priority number, and the result is
155 the upper case first character of the policy name, e.g. 'F' for
156 FIFO_Within_Priorities. A space ' ' is returned if no
157 Priority_Specific_Dispatching pragma is used in the partition. */
160 __gnat_get_specific_dispatching (int priority)
162 if (__gl_num_specific_dispatching == 0)
164 else if (priority >= __gl_num_specific_dispatching)
167 return __gl_priority_specific_dispatching [priority];
172 /**********************/
173 /* __gnat_set_globals */
174 /**********************/
176 /* This routine is kept for boostrapping purposes, since the binder generated
177 file now sets the __gl_* variables directly. */
180 __gnat_set_globals ()
186 /* Notes on the Zero Cost Exceptions scheme and its impact on the signal
187 handlers implemented below :
189 What we call Zero Cost Exceptions is implemented using the GCC eh
190 circuitry, even if the underlying implementation is setjmp/longjmp
191 based. In any case ...
193 The GCC unwinder expects to be dealing with call return addresses, since
194 this is the "nominal" case of what we retrieve while unwinding a regular
195 call chain. To evaluate if a handler applies at some point in this chain,
196 the propagation engine needs to determine what region the corresponding
197 call instruction pertains to. The return address may not be attached to the
198 same region as the call, so the unwinder unconditionally subtracts "some"
199 amount to the return addresses it gets to search the region tables. The
200 exact amount is computed to ensure that the resulting address is inside the
201 call instruction, and is thus target dependent (think about delay slots for
204 When we raise an exception from a signal handler, e.g. to transform a
205 SIGSEGV into Storage_Error, things need to appear as if the signal handler
206 had been "called" by the instruction which triggered the signal, so that
207 exception handlers that apply there are considered. What the unwinder will
208 retrieve as the return address from the signal handler is what it will find
209 as the faulting instruction address in the corresponding signal context
210 pushed by the kernel. Leaving this address untouched may loose, because if
211 the triggering instruction happens to be the very first of a region, the
212 later adjustments performed by the unwinder would yield an address outside
213 that region. We need to compensate for those adjustments at some point,
214 which we used to do in the GCC unwinding fallback macro.
216 The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
217 describes a couple of issues with the fallback based compensation approach.
218 First, on some targets the adjustment to apply depends on the triggering
219 signal, which is not easily accessible from the macro. Besides, other
220 languages, e.g. Java, deal with this by performing the adjustment in the
221 signal handler before the raise, so fallback adjustments just break those
224 We now follow the Java way for most targets, via adjust_context_for_raise
234 #include <sys/time.h>
236 /* Some versions of AIX don't define SA_NODEFER. */
240 #endif /* SA_NODEFER */
242 /* Versions of AIX before 4.3 don't have nanosleep but provide
245 #ifndef _AIXVERSION_430
247 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
250 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
252 return nsleep (Rqtp, Rmtp);
255 #endif /* _AIXVERSION_430 */
257 static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
259 /* __gnat_adjust_context_for_raise - see comments along with the default
260 version later in this file. */
263 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
265 /* We need to adjust the "Instruction Address Register" value, part of a
266 'struct mstsave' wrapped as a jumpbuf in the mcontext field designated by
267 the signal data pointer we get. See sys/context.h + sys/mstsave.h */
269 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
270 mcontext->jmp_context.iar++;
273 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
276 __gnat_error_handler (int sig, siginfo_t * si, void * uc)
278 struct Exception_Data *exception;
284 /* FIXME: we need to detect the case of a *real* SIGSEGV */
285 exception = &storage_error;
286 msg = "stack overflow or erroneous memory access";
290 exception = &constraint_error;
295 exception = &constraint_error;
300 exception = &program_error;
301 msg = "unhandled signal";
304 __gnat_adjust_context_for_raise (sig, uc);
305 Raise_From_Signal_Handler (exception, msg);
309 __gnat_install_handler (void)
311 struct sigaction act;
313 /* Set up signal handler to map synchronous signals to appropriate
314 exceptions. Make sure that the handler isn't interrupted by another
315 signal that might cause a scheduling event! */
317 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
318 act.sa_sigaction = __gnat_error_handler;
319 sigemptyset (&act.sa_mask);
321 /* Do not install handlers if interrupt state is "System" */
322 if (__gnat_get_interrupt_state (SIGABRT) != 's')
323 sigaction (SIGABRT, &act, NULL);
324 if (__gnat_get_interrupt_state (SIGFPE) != 's')
325 sigaction (SIGFPE, &act, NULL);
326 if (__gnat_get_interrupt_state (SIGILL) != 's')
327 sigaction (SIGILL, &act, NULL);
328 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
329 sigaction (SIGSEGV, &act, NULL);
330 if (__gnat_get_interrupt_state (SIGBUS) != 's')
331 sigaction (SIGBUS, &act, NULL);
333 __gnat_handler_installed = 1;
340 #elif defined(__alpha__) && defined(__osf__)
343 #include <sys/siginfo.h>
345 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
346 extern char *__gnat_get_code_loc (struct sigcontext *);
347 extern void __gnat_set_code_loc (struct sigcontext *, char *);
348 extern size_t __gnat_machine_state_length (void);
352 (int sig, siginfo_t *sip, struct sigcontext *context ATTRIBUTE_UNUSED)
354 struct Exception_Data *exception;
355 static int recurse = 0;
358 /* If this was an explicit signal from a "kill", just resignal it. */
359 if (SI_FROMUSER (sip))
361 signal (sig, SIG_DFL);
362 kill (getpid(), sig);
365 /* Otherwise, treat it as something we handle. */
369 /* If the problem was permissions, this is a constraint error.
370 Likewise if the failing address isn't maximally aligned or if
373 ??? Using a static variable here isn't task-safe, but it's
374 much too hard to do anything else and we're just determining
375 which exception to raise. */
376 if (sip->si_code == SEGV_ACCERR
377 || (((long) sip->si_addr) & 3) != 0
380 exception = &constraint_error;
385 /* See if the page before the faulting page is accessible. Do that
386 by trying to access it. We'd like to simply try to access
387 4096 + the faulting address, but it's not guaranteed to be
388 the actual address, just to be on the same page. */
391 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
392 msg = "stack overflow (or erroneous memory access)";
393 exception = &storage_error;
398 exception = &program_error;
403 exception = &constraint_error;
408 exception = &program_error;
409 msg = "unhandled signal";
413 Raise_From_Signal_Handler (exception, (char *) msg);
417 __gnat_install_handler (void)
419 struct sigaction act;
421 /* Setup signal handler to map synchronous signals to appropriate
422 exceptions. Make sure that the handler isn't interrupted by another
423 signal that might cause a scheduling event! */
425 act.sa_handler = (void (*) (int)) __gnat_error_handler;
426 act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
427 sigemptyset (&act.sa_mask);
429 /* Do not install handlers if interrupt state is "System" */
430 if (__gnat_get_interrupt_state (SIGABRT) != 's')
431 sigaction (SIGABRT, &act, NULL);
432 if (__gnat_get_interrupt_state (SIGFPE) != 's')
433 sigaction (SIGFPE, &act, NULL);
434 if (__gnat_get_interrupt_state (SIGILL) != 's')
435 sigaction (SIGILL, &act, NULL);
436 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
437 sigaction (SIGSEGV, &act, NULL);
438 if (__gnat_get_interrupt_state (SIGBUS) != 's')
439 sigaction (SIGBUS, &act, NULL);
441 __gnat_handler_installed = 1;
444 /* Routines called by s-mastop-tru64.adb. */
449 __gnat_get_code_loc (struct sigcontext *context)
451 return (char *) context->sc_pc;
455 __gnat_set_code_loc (struct sigcontext *context, char *pc)
457 context->sc_pc = (long) pc;
462 __gnat_machine_state_length (void)
464 return sizeof (struct sigcontext);
471 #elif defined (__hpux__)
474 #include <sys/ucontext.h>
477 __gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext);
479 #if defined (__hppa__)
481 /* __gnat_adjust_context_for_raise - see comments along with the default
482 version later in this file. */
484 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
487 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
489 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
491 if (UseWideRegs (mcontext))
492 mcontext->ss_wide.ss_32.ss_pcoq_head_lo ++;
494 mcontext->ss_narrow.ss_pcoq_head ++;
501 (int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED, void *ucontext)
503 struct Exception_Data *exception;
509 /* FIXME: we need to detect the case of a *real* SIGSEGV */
510 exception = &storage_error;
511 msg = "stack overflow or erroneous memory access";
515 exception = &constraint_error;
520 exception = &constraint_error;
525 exception = &program_error;
526 msg = "unhandled signal";
529 __gnat_adjust_context_for_raise (sig, ucontext);
531 Raise_From_Signal_Handler (exception, msg);
535 __gnat_install_handler (void)
537 struct sigaction act;
539 /* Set up signal handler to map synchronous signals to appropriate
540 exceptions. Make sure that the handler isn't interrupted by another
541 signal that might cause a scheduling event! Also setup an alternate
542 stack region for the handler execution so that stack overflows can be
543 handled properly, avoiding a SEGV generation from stack usage by the
546 static char handler_stack[SIGSTKSZ*2];
547 /* SIGSTKSZ appeared to be "short" for the needs in some contexts
548 (e.g. experiments with GCC ZCX exceptions). */
552 stack.ss_sp = handler_stack;
553 stack.ss_size = sizeof (handler_stack);
556 sigaltstack (&stack, NULL);
558 act.sa_sigaction = __gnat_error_handler;
559 act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK | SA_SIGINFO;
560 sigemptyset (&act.sa_mask);
562 /* Do not install handlers if interrupt state is "System" */
563 if (__gnat_get_interrupt_state (SIGABRT) != 's')
564 sigaction (SIGABRT, &act, NULL);
565 if (__gnat_get_interrupt_state (SIGFPE) != 's')
566 sigaction (SIGFPE, &act, NULL);
567 if (__gnat_get_interrupt_state (SIGILL) != 's')
568 sigaction (SIGILL, &act, NULL);
569 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
570 sigaction (SIGSEGV, &act, NULL);
571 if (__gnat_get_interrupt_state (SIGBUS) != 's')
572 sigaction (SIGBUS, &act, NULL);
574 __gnat_handler_installed = 1;
577 /*********************/
578 /* GNU/Linux Section */
579 /*********************/
581 #elif defined (linux) && (defined (i386) || defined (__x86_64__) \
582 || defined (__ia64__))
586 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
587 #include <sys/ucontext.h>
589 /* GNU/Linux, which uses glibc, does not define NULL in included
593 #define NULL ((void *) 0)
598 /* MaRTE OS provides its own version of sigaction, sigfillset, and
599 sigemptyset (overriding these symbol names). We want to make sure that
600 the versions provided by the underlying C library are used here (these
601 versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
602 and fake_linux_sigemptyset, respectively). The MaRTE library will not
603 always be present (it will not be linked if no tasking constructs are
604 used), so we use the weak symbol mechanism to point always to the symbols
605 defined within the C library. */
607 #pragma weak linux_sigaction
608 int linux_sigaction (int signum, const struct sigaction *act,
609 struct sigaction *oldact) {
610 return sigaction (signum, act, oldact);
612 #define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
614 #pragma weak fake_linux_sigfillset
615 void fake_linux_sigfillset (sigset_t *set) {
618 #define sigfillset(set) fake_linux_sigfillset (set)
620 #pragma weak fake_linux_sigemptyset
621 void fake_linux_sigemptyset (sigset_t *set) {
624 #define sigemptyset(set) fake_linux_sigemptyset (set)
628 static void __gnat_error_handler (int, siginfo_t *siginfo, void *ucontext);
630 /* __gnat_adjust_context_for_raise - see comments along with the default
631 version later in this file. */
633 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
636 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
638 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
641 mcontext->gregs[REG_EIP]++;
642 #elif defined (__x86_64__)
643 mcontext->gregs[REG_RIP]++;
644 #elif defined (__ia64__)
650 __gnat_error_handler (int sig,
651 siginfo_t *siginfo ATTRIBUTE_UNUSED,
654 struct Exception_Data *exception;
656 static int recurse = 0;
661 /* If the problem was permissions, this is a constraint error.
662 Likewise if the failing address isn't maximally aligned or if
665 ??? Using a static variable here isn't task-safe, but it's
666 much too hard to do anything else and we're just determining
667 which exception to raise. */
670 exception = &constraint_error;
675 /* Here we would like a discrimination test to see whether the
676 page before the faulting address is accessible. Unfortunately
677 Linux seems to have no way of giving us the faulting address.
679 In versions of a-init.c before 1.95, we had a test of the page
680 before the stack pointer using:
684 ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
686 but that's wrong, since it tests the stack pointer location, and
687 the current stack probe code does not move the stack pointer
688 until all probes succeed.
690 For now we simply do not attempt any discrimination at all. Note
691 that this is quite acceptable, since a "real" SIGSEGV can only
692 occur as the result of an erroneous program */
694 msg = "stack overflow (or erroneous memory access)";
695 exception = &storage_error;
700 exception = &constraint_error;
705 exception = &constraint_error;
710 exception = &program_error;
711 msg = "unhandled signal";
715 /* We adjust the interrupted context here (and not in the
716 MD_FALLBACK_FRAME_STATE_FOR macro) because recent versions of the Native
717 POSIX Thread Library (NPTL) are compiled with DWARF 2 unwind information,
718 and hence the later macro is never executed for signal frames. */
720 __gnat_adjust_context_for_raise (sig, ucontext);
722 Raise_From_Signal_Handler (exception, msg);
726 __gnat_install_handler (void)
728 struct sigaction act;
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! */
734 act.sa_sigaction = __gnat_error_handler;
735 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
736 sigemptyset (&act.sa_mask);
738 /* Do not install handlers if interrupt state is "System" */
739 if (__gnat_get_interrupt_state (SIGABRT) != 's')
740 sigaction (SIGABRT, &act, NULL);
741 if (__gnat_get_interrupt_state (SIGFPE) != 's')
742 sigaction (SIGFPE, &act, NULL);
743 if (__gnat_get_interrupt_state (SIGILL) != 's')
744 sigaction (SIGILL, &act, NULL);
745 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
746 sigaction (SIGSEGV, &act, NULL);
747 if (__gnat_get_interrupt_state (SIGBUS) != 's')
748 sigaction (SIGBUS, &act, NULL);
750 __gnat_handler_installed = 1;
753 /*******************/
754 /* Interix Section */
755 /*******************/
757 #elif defined (__INTERIX)
761 static void __gnat_error_handler (int);
764 __gnat_error_handler (int sig)
766 struct Exception_Data *exception;
772 exception = &storage_error;
773 msg = "stack overflow or erroneous memory access";
777 exception = &constraint_error;
782 exception = &constraint_error;
787 exception = &program_error;
788 msg = "unhandled signal";
791 Raise_From_Signal_Handler (exception, msg);
795 __gnat_install_handler (void)
797 struct sigaction act;
799 /* Set up signal handler to map synchronous signals to appropriate
800 exceptions. Make sure that the handler isn't interrupted by another
801 signal that might cause a scheduling event! */
803 act.sa_handler = __gnat_error_handler;
805 sigemptyset (&act.sa_mask);
807 /* Handlers for signals besides SIGSEGV cause c974013 to hang */
808 /* sigaction (SIGILL, &act, NULL); */
809 /* sigaction (SIGABRT, &act, NULL); */
810 /* sigaction (SIGFPE, &act, NULL); */
811 /* sigaction (SIGBUS, &act, NULL); */
813 /* Do not install handlers if interrupt state is "System" */
814 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
815 sigaction (SIGSEGV, &act, NULL);
817 __gnat_handler_installed = 1;
833 #define SIGADAABORT 48
834 #define SIGNAL_STACK_SIZE 4096
835 #define SIGNAL_STACK_ALIGNMENT 64
837 #define Check_Abort_Status \
838 system__soft_links__check_abort_status
839 extern int (*Check_Abort_Status) (void);
841 extern struct Exception_Data _abort_signal;
843 static void __gnat_error_handler (int, int, sigcontext_t *);
845 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
846 connecting that handler, with the effects described in the sigaction
850 If cleared and the signal is caught, the first argument is
851 also the signal number but the second argument is the signal
852 code identifying the cause of the signal. The third argument
853 points to a sigcontext_t structure containing the receiving
854 process's context when the signal was delivered.
858 __gnat_error_handler (int sig, int code, sigcontext_t *sc ATTRIBUTE_UNUSED)
860 struct Exception_Data *exception;
868 exception = &program_error;
869 msg = "SIGSEGV: (Invalid virtual address)";
871 else if (code == ENXIO)
873 exception = &program_error;
874 msg = "SIGSEGV: (Read beyond mapped object)";
876 else if (code == ENOSPC)
878 exception = &program_error; /* ??? storage_error ??? */
879 msg = "SIGSEGV: (Autogrow for file failed)";
881 else if (code == EACCES || code == EEXIST)
883 /* ??? We handle stack overflows here, some of which do trigger
884 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
885 the documented valid codes for SEGV in the signal(5) man
888 /* ??? Re-add smarts to further verify that we launched
889 the stack into a guard page, not an attempt to
890 write to .text or something */
891 exception = &storage_error;
892 msg = "SIGSEGV: (stack overflow or erroneous memory access)";
896 /* Just in case the OS guys did it to us again. Sometimes
897 they fail to document all of the valid codes that are
898 passed to signal handlers, just in case someone depends
899 on knowing all the codes */
900 exception = &program_error;
901 msg = "SIGSEGV: (Undocumented reason)";
906 /* Map all bus errors to Program_Error. */
907 exception = &program_error;
912 /* Map all fpe errors to Constraint_Error. */
913 exception = &constraint_error;
918 if ((*Check_Abort_Status) ())
920 exception = &_abort_signal;
929 /* Everything else is a Program_Error. */
930 exception = &program_error;
931 msg = "unhandled signal";
934 Raise_From_Signal_Handler (exception, msg);
938 __gnat_install_handler (void)
940 struct sigaction act;
942 /* Setup signal handler to map synchronous signals to appropriate
943 exceptions. Make sure that the handler isn't interrupted by another
944 signal that might cause a scheduling event! */
946 act.sa_handler = __gnat_error_handler;
947 act.sa_flags = SA_NODEFER + SA_RESTART;
948 sigfillset (&act.sa_mask);
949 sigemptyset (&act.sa_mask);
951 /* Do not install handlers if interrupt state is "System" */
952 if (__gnat_get_interrupt_state (SIGABRT) != 's')
953 sigaction (SIGABRT, &act, NULL);
954 if (__gnat_get_interrupt_state (SIGFPE) != 's')
955 sigaction (SIGFPE, &act, NULL);
956 if (__gnat_get_interrupt_state (SIGILL) != 's')
957 sigaction (SIGILL, &act, NULL);
958 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
959 sigaction (SIGSEGV, &act, NULL);
960 if (__gnat_get_interrupt_state (SIGBUS) != 's')
961 sigaction (SIGBUS, &act, NULL);
962 if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
963 sigaction (SIGADAABORT, &act, NULL);
965 __gnat_handler_installed = 1;
968 /*******************/
969 /* Solaris Section */
970 /*******************/
972 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
977 static void __gnat_error_handler (int, siginfo_t *);
980 __gnat_error_handler (int sig, siginfo_t *sip)
982 struct Exception_Data *exception;
983 static int recurse = 0;
986 /* If this was an explicit signal from a "kill", just resignal it. */
987 if (SI_FROMUSER (sip))
989 signal (sig, SIG_DFL);
990 kill (getpid(), sig);
993 /* Otherwise, treat it as something we handle. */
997 /* If the problem was permissions, this is a constraint error.
998 Likewise if the failing address isn't maximally aligned or if
1001 ??? Using a static variable here isn't task-safe, but it's
1002 much too hard to do anything else and we're just determining
1003 which exception to raise. */
1004 if (sip->si_code == SEGV_ACCERR
1005 || (((long) sip->si_addr) & 3) != 0
1008 exception = &constraint_error;
1013 /* See if the page before the faulting page is accessible. Do that
1014 by trying to access it. We'd like to simply try to access
1015 4096 + the faulting address, but it's not guaranteed to be
1016 the actual address, just to be on the same page. */
1019 ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1020 exception = &storage_error;
1021 msg = "stack overflow (or erroneous memory access)";
1026 exception = &program_error;
1031 exception = &constraint_error;
1036 exception = &program_error;
1037 msg = "unhandled signal";
1042 Raise_From_Signal_Handler (exception, msg);
1046 __gnat_install_handler (void)
1048 struct sigaction act;
1050 /* Set up signal handler to map synchronous signals to appropriate
1051 exceptions. Make sure that the handler isn't interrupted by another
1052 signal that might cause a scheduling event! */
1054 act.sa_handler = __gnat_error_handler;
1055 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1056 sigemptyset (&act.sa_mask);
1058 /* Do not install handlers if interrupt state is "System" */
1059 if (__gnat_get_interrupt_state (SIGABRT) != 's')
1060 sigaction (SIGABRT, &act, NULL);
1061 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1062 sigaction (SIGFPE, &act, NULL);
1063 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1064 sigaction (SIGSEGV, &act, NULL);
1065 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1066 sigaction (SIGBUS, &act, NULL);
1068 __gnat_handler_installed = 1;
1077 long __gnat_error_handler (int *, void *);
1080 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1081 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1082 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1084 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1085 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1086 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1089 #if defined (IN_RTS) && !defined (__IA64)
1091 /* The prehandler actually gets control first on a condition. It swaps the
1092 stack pointer and calls the handler (__gnat_error_handler). */
1093 extern long __gnat_error_prehandler (void);
1095 extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
1098 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1099 Most of these are also defined in the header file ssdef.h which has not
1100 yet been converted to be recognized by Gnu C. */
1102 /* Defining these as macros, as opposed to external addresses, allows
1103 them to be used in a case statement (below */
1104 #define SS$_ACCVIO 12
1105 #define SS$_HPARITH 1284
1106 #define SS$_STKOVF 1364
1107 #define SS$_RESIGNAL 2328
1109 /* These codes are in standard message libraries */
1110 extern int CMA$_EXIT_THREAD;
1111 extern int SS$_DEBUG;
1112 extern int SS$_INTDIV;
1113 extern int LIB$_KEYNOTFOU;
1114 extern int LIB$_ACTIMAGE;
1115 extern int MTH$_FLOOVEMAT; /* Some ACVC_21 CXA tests */
1117 /* These codes are non standard, which is to say the author is
1118 not sure if they are defined in the standard message libraries
1119 so keep them as macros for now. */
1120 #define RDB$_STREAM_EOF 20480426
1121 #define FDL$_UNPRIKW 11829410
1123 struct cond_except {
1125 const struct Exception_Data *except;
1128 struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1130 /* Conditions that don't have an Ada exception counterpart must raise
1131 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
1132 referenced by user programs, not the compiler or tools. Hence the
1137 #define Status_Error ada__io_exceptions__status_error
1138 extern struct Exception_Data Status_Error;
1140 #define Mode_Error ada__io_exceptions__mode_error
1141 extern struct Exception_Data Mode_Error;
1143 #define Name_Error ada__io_exceptions__name_error
1144 extern struct Exception_Data Name_Error;
1146 #define Use_Error ada__io_exceptions__use_error
1147 extern struct Exception_Data Use_Error;
1149 #define Device_Error ada__io_exceptions__device_error
1150 extern struct Exception_Data Device_Error;
1152 #define End_Error ada__io_exceptions__end_error
1153 extern struct Exception_Data End_Error;
1155 #define Data_Error ada__io_exceptions__data_error
1156 extern struct Exception_Data Data_Error;
1158 #define Layout_Error ada__io_exceptions__layout_error
1159 extern struct Exception_Data Layout_Error;
1161 #define Non_Ada_Error system__aux_dec__non_ada_error
1162 extern struct Exception_Data Non_Ada_Error;
1164 #define Coded_Exception system__vms_exception_table__coded_exception
1165 extern struct Exception_Data *Coded_Exception (Exception_Code);
1167 #define Base_Code_In system__vms_exception_table__base_code_in
1168 extern Exception_Code Base_Code_In (Exception_Code);
1170 /* DEC Ada exceptions are not defined in a header file, so they
1171 must be declared as external addresses */
1173 extern int ADA$_PROGRAM_ERROR;
1174 extern int ADA$_LOCK_ERROR;
1175 extern int ADA$_EXISTENCE_ERROR;
1176 extern int ADA$_KEY_ERROR;
1177 extern int ADA$_KEYSIZERR;
1178 extern int ADA$_STAOVF;
1179 extern int ADA$_CONSTRAINT_ERRO;
1180 extern int ADA$_IOSYSFAILED;
1181 extern int ADA$_LAYOUT_ERROR;
1182 extern int ADA$_STORAGE_ERROR;
1183 extern int ADA$_DATA_ERROR;
1184 extern int ADA$_DEVICE_ERROR;
1185 extern int ADA$_END_ERROR;
1186 extern int ADA$_MODE_ERROR;
1187 extern int ADA$_NAME_ERROR;
1188 extern int ADA$_STATUS_ERROR;
1189 extern int ADA$_NOT_OPEN;
1190 extern int ADA$_ALREADY_OPEN;
1191 extern int ADA$_USE_ERROR;
1192 extern int ADA$_UNSUPPORTED;
1193 extern int ADA$_FAC_MODE_MISMAT;
1194 extern int ADA$_ORG_MISMATCH;
1195 extern int ADA$_RFM_MISMATCH;
1196 extern int ADA$_RAT_MISMATCH;
1197 extern int ADA$_MRS_MISMATCH;
1198 extern int ADA$_MRN_MISMATCH;
1199 extern int ADA$_KEY_MISMATCH;
1200 extern int ADA$_MAXLINEXC;
1201 extern int ADA$_LINEXCMRS;
1203 /* DEC Ada specific conditions */
1204 static const struct cond_except dec_ada_cond_except_table [] = {
1205 {&ADA$_PROGRAM_ERROR, &program_error},
1206 {&ADA$_USE_ERROR, &Use_Error},
1207 {&ADA$_KEYSIZERR, &program_error},
1208 {&ADA$_STAOVF, &storage_error},
1209 {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1210 {&ADA$_IOSYSFAILED, &Device_Error},
1211 {&ADA$_LAYOUT_ERROR, &Layout_Error},
1212 {&ADA$_STORAGE_ERROR, &storage_error},
1213 {&ADA$_DATA_ERROR, &Data_Error},
1214 {&ADA$_DEVICE_ERROR, &Device_Error},
1215 {&ADA$_END_ERROR, &End_Error},
1216 {&ADA$_MODE_ERROR, &Mode_Error},
1217 {&ADA$_NAME_ERROR, &Name_Error},
1218 {&ADA$_STATUS_ERROR, &Status_Error},
1219 {&ADA$_NOT_OPEN, &Use_Error},
1220 {&ADA$_ALREADY_OPEN, &Use_Error},
1221 {&ADA$_USE_ERROR, &Use_Error},
1222 {&ADA$_UNSUPPORTED, &Use_Error},
1223 {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1224 {&ADA$_ORG_MISMATCH, &Use_Error},
1225 {&ADA$_RFM_MISMATCH, &Use_Error},
1226 {&ADA$_RAT_MISMATCH, &Use_Error},
1227 {&ADA$_MRS_MISMATCH, &Use_Error},
1228 {&ADA$_MRN_MISMATCH, &Use_Error},
1229 {&ADA$_KEY_MISMATCH, &Use_Error},
1230 {&ADA$_MAXLINEXC, &constraint_error},
1231 {&ADA$_LINEXCMRS, &constraint_error},
1236 /* Already handled by a pragma Import_Exception
1237 in Aux_IO_Exceptions */
1238 {&ADA$_LOCK_ERROR, &Lock_Error},
1239 {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1240 {&ADA$_KEY_ERROR, &Key_Error},
1245 /* Non DEC Ada specific conditions. We could probably also put
1246 SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
1247 static const struct cond_except cond_except_table [] = {
1248 {&MTH$_FLOOVEMAT, &constraint_error},
1249 {&SS$_INTDIV, &constraint_error},
1253 /* To deal with VMS conditions and their mapping to Ada exceptions,
1254 the __gnat_error_handler routine below is installed as an exception
1255 vector having precedence over DEC frame handlers. Some conditions
1256 still need to be handled by such handlers, however, in which case
1257 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
1258 instance the use of a third party library compiled with DECAda and
1259 performing it's own exception handling internally.
1261 To allow some user-level flexibility, which conditions should be
1262 resignaled is controlled by a predicate function, provided with the
1263 condition value and returning a boolean indication stating whether
1264 this condition should be resignaled or not.
1266 That predicate function is called indirectly, via a function pointer,
1267 by __gnat_error_handler, and changing that pointer is allowed to the
1268 the user code by way of the __gnat_set_resignal_predicate interface.
1270 The user level function may then implement what it likes, including
1271 for instance the maintenance of a dynamic data structure if the set
1272 of to be resignalled conditions has to change over the program's
1275 ??? This is not a perfect solution to deal with the possible
1276 interactions between the GNAT and the DECAda exception handling
1277 models and better (more general) schemes are studied. This is so
1278 just provided as a convenient workaround in the meantime, and
1279 should be use with caution since the implementation has been kept
1283 resignal_predicate (int code);
1285 const int *cond_resignal_table [] = {
1290 (int *) RDB$_STREAM_EOF,
1291 (int *) FDL$_UNPRIKW,
1295 const int facility_resignal_table [] = {
1296 0x1380000, /* RDB */
1297 0x2220000, /* SQL */
1301 /* Default GNAT predicate for resignaling conditions. */
1304 __gnat_default_resignal_p (int code)
1308 for (i = 0; facility_resignal_table [i]; i++)
1309 if ((code & 0xfff0000) == facility_resignal_table [i])
1312 for (i = 0, iexcept = 0;
1313 cond_resignal_table [i] &&
1314 !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1320 /* Static pointer to predicate that the __gnat_error_handler exception
1321 vector invokes to determine if it should resignal a condition. */
1323 static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1325 /* User interface to change the predicate pointer to PREDICATE. Reset to
1326 the default if PREDICATE is null. */
1329 __gnat_set_resignal_predicate (resignal_predicate * predicate)
1332 __gnat_resignal_p = __gnat_default_resignal_p;
1334 __gnat_resignal_p = predicate;
1337 /* Should match System.Parameters.Default_Exception_Msg_Max_Length */
1338 #define Default_Exception_Msg_Max_Length 512
1340 /* Action routine for SYS$PUTMSG. There may be
1341 multiple conditions, each with text to be appended to
1342 MESSAGE and separated by line termination. */
1345 copy_msg (msgdesc, message)
1346 struct descriptor_s *msgdesc;
1349 int len = strlen (message);
1352 /* Check for buffer overflow and skip */
1353 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1355 strcat (message, "\r\n");
1359 /* Check for buffer overflow and truncate if necessary */
1360 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1362 Default_Exception_Msg_Max_Length - 1 - len);
1363 strncpy (&message [len], msgdesc->adr, copy_len);
1364 message [len + copy_len] = 0;
1370 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1372 struct Exception_Data *exception = 0;
1373 Exception_Code base_code;
1374 struct descriptor_s gnat_facility = {4,0,"GNAT"};
1375 char message [Default_Exception_Msg_Max_Length];
1377 const char *msg = "";
1379 /* Check for conditions to resignal which aren't effected by pragma
1380 Import_Exception. */
1381 if (__gnat_resignal_p (sigargs [1]))
1382 return SS$_RESIGNAL;
1385 /* See if it's an imported exception. Beware that registered exceptions
1386 are bound to their base code, with the severity bits masked off. */
1387 base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1388 exception = Coded_Exception (base_code);
1394 /* Subtract PC & PSL fields which messes with PUTMSG */
1396 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1400 exception->Name_Length = 19;
1401 /* The full name really should be get sys$getmsg returns. ??? */
1402 exception->Full_Name = "IMPORTED_EXCEPTION";
1403 exception->Import_Code = base_code;
1406 /* Do not adjust the program counter as already points to the next
1407 instruction (just after the call to LIB$STOP). */
1408 Raise_From_Signal_Handler (exception, msg);
1417 if (sigargs[3] == 0)
1419 exception = &constraint_error;
1420 msg = "access zero";
1424 exception = &storage_error;
1425 msg = "stack overflow (or erroneous memory access)";
1430 exception = &storage_error;
1431 msg = "stack overflow";
1436 return SS$_RESIGNAL; /* toplev.c handles for compiler */
1439 exception = &constraint_error;
1440 msg = "arithmetic error";
1450 /* Scan the DEC Ada exception condition table for a match and fetch
1451 the associated GNAT exception pointer */
1453 dec_ada_cond_except_table [i].cond &&
1454 !LIB$MATCH_COND (&sigargs [1],
1455 &dec_ada_cond_except_table [i].cond);
1457 exception = (struct Exception_Data *)
1458 dec_ada_cond_except_table [i].except;
1462 /* Scan the VMS standard condition table for a match and fetch
1463 the associated GNAT exception pointer */
1465 cond_except_table [i].cond &&
1466 !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1468 exception =(struct Exception_Data *) cond_except_table [i].except;
1471 /* User programs expect Non_Ada_Error to be raised, reference
1472 DEC Ada test CXCONDHAN. */
1473 exception = &Non_Ada_Error;
1477 exception = &program_error;
1480 /* Subtract PC & PSL fields which messes with PUTMSG */
1482 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1488 __gnat_adjust_context_for_raise (0, (void *)mechargs);
1489 Raise_From_Signal_Handler (exception, msg);
1493 __gnat_error_handler (int *sigargs, void *mechargs)
1495 return __gnat_handle_vms_condition (sigargs, mechargs);
1499 __gnat_install_handler (void)
1501 long prvhnd ATTRIBUTE_UNUSED;
1503 #if !defined (IN_RTS)
1504 SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1507 /* On alpha-vms, we avoid the global vector annoyance thanks to frame based
1508 handlers to turn conditions into exceptions since GCC 3.4. The global
1509 vector is still required for earlier GCC versions. We're resorting to
1510 the __gnat_error_prehandler assembly function in this case. */
1512 #if defined (IN_RTS) && defined (__alpha__)
1513 if ((__GNUC__ * 10 + __GNUC_MINOR__) < 34)
1515 char * c = (char *) xmalloc (2049);
1517 __gnat_error_prehandler_stack = &c[2048];
1518 SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1522 __gnat_handler_installed = 1;
1525 /* __gnat_adjust_context_for_raise for alpha - see comments along with the
1526 default version later in this file. */
1528 #if defined (IN_RTS) && defined (__alpha__)
1530 #include <vms/chfctxdef.h>
1531 #include <vms/chfdef.h>
1533 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1536 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1538 /* Add one to the address of the instruction signaling the condition,
1539 located in the sigargs array. */
1541 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1542 CHF$SIGNAL_ARRAY * sigargs
1543 = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1545 int vcount = sigargs->chf$is_sig_args;
1546 int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1553 /* __gnat_adjust_context_for_raise for ia64. */
1555 #if defined (IN_RTS) && defined (__IA64)
1557 #include <vms/chfctxdef.h>
1558 #include <vms/chfdef.h>
1560 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1562 typedef unsigned long long u64;
1565 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1567 /* Add one to the address of the instruction signaling the condition,
1568 located in the 64bits sigargs array. */
1570 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1572 CHF64$SIGNAL_ARRAY *chfsig64
1573 = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1576 = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1578 u64 * ih_pc_loc = post_sigarray - 2;
1585 /*******************/
1586 /* FreeBSD Section */
1587 /*******************/
1589 #elif defined (__FreeBSD__)
1592 #include <sys/ucontext.h>
1595 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1596 void __gnat_adjust_context_for_raise (int, void*);
1598 /* __gnat_adjust_context_for_raise - see comments along with the default
1599 version later in this file. */
1601 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1604 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1606 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
1611 __gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
1612 ucontext_t *ucontext)
1614 struct Exception_Data *exception;
1620 exception = &constraint_error;
1625 exception = &constraint_error;
1630 exception = &storage_error;
1631 msg = "stack overflow or erroneous memory access";
1635 exception = &constraint_error;
1640 exception = &program_error;
1641 msg = "unhandled signal";
1644 __gnat_adjust_context_for_raise (sig, ucontext);
1645 Raise_From_Signal_Handler (exception, msg);
1649 __gnat_install_handler ()
1651 struct sigaction act;
1653 /* Set up signal handler to map synchronous signals to appropriate
1654 exceptions. Make sure that the handler isn't interrupted by another
1655 signal that might cause a scheduling event! */
1658 = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1659 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1660 (void) sigemptyset (&act.sa_mask);
1662 (void) sigaction (SIGILL, &act, NULL);
1663 (void) sigaction (SIGFPE, &act, NULL);
1664 (void) sigaction (SIGSEGV, &act, NULL);
1665 (void) sigaction (SIGBUS, &act, NULL);
1667 __gnat_handler_installed = 1;
1670 /*******************/
1671 /* VxWorks Section */
1672 /*******************/
1674 #elif defined(__vxworks)
1677 #include <taskLib.h>
1685 #include "private/vThreadsP.h"
1688 static void __gnat_error_handler (int, int, struct sigcontext *);
1689 void __gnat_map_signal (int);
1693 /* Directly vectored Interrupt routines are not supported when using RTPs */
1695 extern int __gnat_inum_to_ivec (int);
1697 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1699 __gnat_inum_to_ivec (int num)
1701 return INUM_TO_IVEC (num);
1705 #if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1707 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1708 on Alpha VxWorks and VxWorks 6.x (including RTPs). */
1710 extern long getpid (void);
1715 return taskIdSelf ();
1719 /* VxWorks expects the field excCnt to be zeroed when a signal is handled.
1720 The VxWorks version of longjmp does this; gcc's builtin_longjmp does not */
1722 __gnat_clear_exception_count (void)
1725 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1727 currentTask->vThreads.excCnt = 0;
1731 /* Exported to s-intman-vxworks.adb in order to handle different signal
1732 to exception mappings in different VxWorks versions */
1734 __gnat_map_signal (int sig)
1736 struct Exception_Data *exception;
1742 exception = &constraint_error;
1747 exception = &constraint_error;
1748 msg = "Floating point exception or SIGILL";
1751 exception = &storage_error;
1752 msg = "SIGSEGV: possible stack overflow";
1755 exception = &storage_error;
1756 msg = "SIGBUS: possible stack overflow";
1760 exception = &constraint_error;
1764 exception = &program_error;
1768 exception = &program_error;
1773 exception = &program_error;
1774 msg = "unhandled signal";
1777 __gnat_clear_exception_count ();
1778 Raise_From_Signal_Handler (exception, msg);
1782 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1787 /* VxWorks will always mask out the signal during the signal handler and
1788 will reenable it on a longjmp. GNAT does not generate a longjmp to
1789 return from a signal handler so the signal will still be masked unless
1791 sigprocmask (SIG_SETMASK, NULL, &mask);
1792 sigdelset (&mask, sig);
1793 sigprocmask (SIG_SETMASK, &mask, NULL);
1795 __gnat_map_signal (sig);
1800 __gnat_install_handler (void)
1802 struct sigaction act;
1804 /* Setup signal handler to map synchronous signals to appropriate
1805 exceptions. Make sure that the handler isn't interrupted by another
1806 signal that might cause a scheduling event! */
1808 act.sa_handler = __gnat_error_handler;
1809 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1810 sigemptyset (&act.sa_mask);
1812 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1813 applies to vectored hardware interrupts, not signals */
1814 sigaction (SIGFPE, &act, NULL);
1815 sigaction (SIGILL, &act, NULL);
1816 sigaction (SIGSEGV, &act, NULL);
1817 sigaction (SIGBUS, &act, NULL);
1819 __gnat_handler_installed = 1;
1822 #define HAVE_GNAT_INIT_FLOAT
1825 __gnat_init_float (void)
1827 /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1828 to get correct Ada semantics. Note that for AE653 vThreads, the HW
1829 overflow settings are an OS configuration issue. The instructions
1830 below have no effect */
1831 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1836 #if (defined (__i386__) || defined (i386)) && !defined (VTHREADS)
1837 /* This is used to properly initialize the FPU on an x86 for each
1842 /* Similarly for sparc64. Achieved by masking bits in the Trap Enable Mask
1843 field of the Floating-point Status Register (see the SPARC Architecture
1844 Manual Version 9, p 48). */
1845 #if defined (sparc64)
1847 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
1848 #define FSR_TEM_OFM (1 << 26) /* Overflow */
1849 #define FSR_TEM_UFM (1 << 25) /* Underflow */
1850 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
1851 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
1855 __asm__("st %%fsr, %0" : "=m" (fsr));
1856 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1857 __asm__("ld %0, %%fsr" : : "m" (fsr));
1862 /******************/
1863 /* NetBSD Section */
1864 /******************/
1866 #elif defined(__NetBSD__)
1872 __gnat_error_handler (int sig)
1874 struct Exception_Data *exception;
1880 exception = &constraint_error;
1884 exception = &constraint_error;
1888 exception = &storage_error;
1889 msg = "stack overflow or erroneous memory access";
1892 exception = &constraint_error;
1896 exception = &program_error;
1897 msg = "unhandled signal";
1900 Raise_From_Signal_Handler(exception, msg);
1904 __gnat_install_handler(void)
1906 struct sigaction act;
1908 act.sa_handler = __gnat_error_handler;
1909 act.sa_flags = SA_NODEFER | SA_RESTART;
1910 sigemptyset (&act.sa_mask);
1912 /* Do not install handlers if interrupt state is "System" */
1913 if (__gnat_get_interrupt_state (SIGFPE) != 's')
1914 sigaction (SIGFPE, &act, NULL);
1915 if (__gnat_get_interrupt_state (SIGILL) != 's')
1916 sigaction (SIGILL, &act, NULL);
1917 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1918 sigaction (SIGSEGV, &act, NULL);
1919 if (__gnat_get_interrupt_state (SIGBUS) != 's')
1920 sigaction (SIGBUS, &act, NULL);
1922 __gnat_handler_installed = 1;
1927 /* For all other versions of GNAT, the handler does nothing */
1929 /*******************/
1930 /* Default Section */
1931 /*******************/
1934 __gnat_install_handler (void)
1936 __gnat_handler_installed = 1;
1941 /*********************/
1942 /* __gnat_init_float */
1943 /*********************/
1945 /* This routine is called as each process thread is created, for possible
1946 initialization of the FP processor. This version is used under INTERIX,
1947 WIN32 and could be used under OS/2 */
1949 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1950 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1952 #define HAVE_GNAT_INIT_FLOAT
1955 __gnat_init_float (void)
1957 #if defined (__i386__) || defined (i386)
1959 /* This is used to properly initialize the FPU on an x86 for each
1964 #endif /* Defined __i386__ */
1968 #ifndef HAVE_GNAT_INIT_FLOAT
1970 /* All targets without a specific __gnat_init_float will use an empty one */
1972 __gnat_init_float (void)
1977 /***********************************/
1978 /* __gnat_adjust_context_for_raise */
1979 /***********************************/
1981 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1983 /* All targets without a specific version will use an empty one */
1985 /* UCONTEXT is a pointer to a context structure received by a signal handler
1986 about to propagate an exception. Adjust it to compensate the fact that the
1987 generic unwinder thinks the corresponding PC is a call return address. */
1990 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
1991 void *ucontext ATTRIBUTE_UNUSED)
1993 /* The point is that the interrupted context PC typically is the address
1994 that we should search an EH region for, which is different from the call
1995 return address case. The target independent part of the GCC unwinder
1996 don't differentiate the two situations, so we compensate here for the
1997 adjustments it will blindly make.
1999 signo is passed because on some targets for some signals the PC in
2000 context points to the instruction after the faulting one, in which case
2001 the unwinder adjustment is still desired. */
2003 /* On a number of targets, we have arranged for the adjustment to be
2004 performed by the MD_FALLBACK_FRAME_STATE circuitry, so we don't provide a
2005 specific instance of this routine. The MD_FALLBACK doesn't have access
2006 to the signal number, though, so the compensation is systematic there and
2007 might be wrong in some cases. */
2009 /* Having the compensation wrong leads to potential failures. A very
2010 typical case is what happens when there is no compensation and a signal
2011 triggers for the first instruction in a region : the unwinder adjustment
2012 has it search in the wrong EH region. */