OSDN Git Service

2009-04-20 Robert Dewar <dewar@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / init.c
1 /****************************************************************************
2  *                                                                          *
3  *                         GNAT COMPILER COMPONENTS                         *
4  *                                                                          *
5  *                                 I N I T                                  *
6  *                                                                          *
7  *                          C Implementation File                           *
8  *                                                                          *
9  *          Copyright (C) 1992-2009, Free Software Foundation, Inc.         *
10  *                                                                          *
11  * GNAT is free software;  you can  redistribute it  and/or modify it under *
12  * terms of the  GNU General Public License as published  by the Free Soft- *
13  * ware  Foundation;  either version 3,  or (at your option) any later ver- *
14  * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
15  * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
16  * or FITNESS FOR A PARTICULAR PURPOSE.                                     *
17  *                                                                          *
18  * As a special exception under Section 7 of GPL version 3, you are granted *
19  * additional permissions described in the GCC Runtime Library Exception,   *
20  * version 3.1, as published by the Free Software Foundation.               *
21  *                                                                          *
22  * You should have received a copy of the GNU General Public License and    *
23  * a copy of the GCC Runtime Library Exception along with this program;     *
24  * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
25  * <http://www.gnu.org/licenses/>.                                          *
26  *                                                                          *
27  * GNAT was originally developed  by the GNAT team at  New York University. *
28  * Extensive contributions were provided by Ada Core Technologies Inc.      *
29  *                                                                          *
30  ****************************************************************************/
31
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).  */
40
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.  */
44
45 /* The following include is here to meet the published VxWorks requirement
46    that the __vxworks header appear before any other include.  */
47 #ifdef __vxworks
48 #include "vxWorks.h"
49 #endif
50
51 #ifdef IN_RTS
52 #include "tconfig.h"
53 #include "tsystem.h"
54 #include <sys/stat.h>
55
56 /* We don't have libiberty, so use malloc.  */
57 #define xmalloc(S) malloc (S)
58 #else
59 #include "config.h"
60 #include "system.h"
61 #endif
62
63 #include "adaint.h"
64 #include "raise.h"
65
66 extern void __gnat_raise_program_error (const char *, int);
67
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;
74
75 /* For the Cert run time we use the regular raise exception routine because
76    Raise_From_Signal_Handler is not available.  */
77 #ifdef CERT
78 #define Raise_From_Signal_Handler \
79                       __gnat_raise_exception
80 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
81 #else
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 *);
85 #endif
86
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;
105
106 /* Indication of whether synchronous signal handler has already been
107    installed by a previous call to adainit.  */
108 int  __gnat_handler_installed      = 0;
109
110 #ifndef IN_RTS
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).  */
114 #endif
115
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
120
121 /******************************/
122 /* __gnat_get_interrupt_state */
123 /******************************/
124
125 char __gnat_get_interrupt_state (int);
126
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:
131
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  */
136
137 char
138 __gnat_get_interrupt_state (int intrup)
139 {
140   if (intrup >= __gl_num_interrupt_states)
141     return 'n';
142   else
143     return __gl_interrupt_states [intrup];
144 }
145
146 /***********************************/
147 /* __gnat_get_specific_dispatching */
148 /***********************************/
149
150 char __gnat_get_specific_dispatching (int);
151
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.  */
159
160 char
161 __gnat_get_specific_dispatching (int priority)
162 {
163   if (__gl_num_specific_dispatching == 0)
164     return ' ';
165   else if (priority >= __gl_num_specific_dispatching)
166     return 'F';
167   else
168     return __gl_priority_specific_dispatching [priority];
169 }
170
171 #ifndef IN_RTS
172
173 /**********************/
174 /* __gnat_set_globals */
175 /**********************/
176
177 /* This routine is kept for bootstrapping purposes, since the binder generated
178    file now sets the __gl_* variables directly.  */
179
180 void
181 __gnat_set_globals ()
182 {
183 }
184
185 #endif
186
187 /***************/
188 /* AIX Section */
189 /***************/
190
191 #if defined (_AIX)
192
193 #include <signal.h>
194 #include <sys/time.h>
195
196 /* Some versions of AIX don't define SA_NODEFER.  */
197
198 #ifndef SA_NODEFER
199 #define SA_NODEFER 0
200 #endif /* SA_NODEFER */
201
202 /* Versions of AIX before 4.3 don't have nanosleep but provide
203    nsleep instead.  */
204
205 #ifndef _AIXVERSION_430
206
207 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
208
209 int
210 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
211 {
212   return nsleep (Rqtp, Rmtp);
213 }
214
215 #endif /* _AIXVERSION_430 */
216
217 static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
218
219 static void
220 __gnat_error_handler (int sig, siginfo_t * si, void * uc)
221 {
222   struct Exception_Data *exception;
223   const char *msg;
224
225   switch (sig)
226     {
227     case SIGSEGV:
228       /* FIXME: we need to detect the case of a *real* SIGSEGV.  */
229       exception = &storage_error;
230       msg = "stack overflow or erroneous memory access";
231       break;
232
233     case SIGBUS:
234       exception = &constraint_error;
235       msg = "SIGBUS";
236       break;
237
238     case SIGFPE:
239       exception = &constraint_error;
240       msg = "SIGFPE";
241       break;
242
243     default:
244       exception = &program_error;
245       msg = "unhandled signal";
246     }
247
248   Raise_From_Signal_Handler (exception, msg);
249 }
250
251 void
252 __gnat_install_handler (void)
253 {
254   struct sigaction act;
255
256   /* Set up signal handler to map synchronous signals to appropriate
257      exceptions.  Make sure that the handler isn't interrupted by another
258      signal that might cause a scheduling event!  */
259
260   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
261   act.sa_sigaction = __gnat_error_handler;
262   sigemptyset (&act.sa_mask);
263
264   /* Do not install handlers if interrupt state is "System".  */
265   if (__gnat_get_interrupt_state (SIGABRT) != 's')
266     sigaction (SIGABRT, &act, NULL);
267   if (__gnat_get_interrupt_state (SIGFPE) != 's')
268     sigaction (SIGFPE,  &act, NULL);
269   if (__gnat_get_interrupt_state (SIGILL) != 's')
270     sigaction (SIGILL,  &act, NULL);
271   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
272     sigaction (SIGSEGV, &act, NULL);
273   if (__gnat_get_interrupt_state (SIGBUS) != 's')
274     sigaction (SIGBUS,  &act, NULL);
275
276   __gnat_handler_installed = 1;
277 }
278
279 /*****************/
280 /* Tru64 section */
281 /*****************/
282
283 #elif defined(__alpha__) && defined(__osf__)
284
285 #include <signal.h>
286 #include <sys/siginfo.h>
287
288 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
289 extern char *__gnat_get_code_loc (struct sigcontext *);
290 extern void __gnat_set_code_loc (struct sigcontext *, char *);
291 extern size_t __gnat_machine_state_length (void);
292
293 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
294
295 void
296 __gnat_adjust_context_for_raise (int signo, void *ucontext)
297 {
298   struct sigcontext *sigcontext = (struct sigcontext *) ucontext;
299
300   /* The unwinder expects the signal context to contain the address of the
301      faulting instruction.  For SIGFPE, this depends on the trap shadow
302      situation (see man ieee).  We nonetheless always compensate for it,
303      considering that PC designates the instruction following the one that
304      trapped.  This is not necessarily true but corresponds to what we have
305      always observed.  */
306   if (signo == SIGFPE)
307     sigcontext->sc_pc--;
308 }
309
310 static void
311 __gnat_error_handler
312   (int sig, siginfo_t *sip, struct sigcontext *context)
313 {
314   struct Exception_Data *exception;
315   static int recurse = 0;
316   const char *msg;
317
318   /* Adjusting is required for every fault context, so adjust for this one
319      now, before we possibly trigger a recursive fault below.  */
320   __gnat_adjust_context_for_raise (sig, context);
321
322   /* If this was an explicit signal from a "kill", just resignal it.  */
323   if (SI_FROMUSER (sip))
324     {
325       signal (sig, SIG_DFL);
326       kill (getpid(), sig);
327     }
328
329   /* Otherwise, treat it as something we handle.  */
330   switch (sig)
331     {
332     case SIGSEGV:
333       /* If the problem was permissions, this is a constraint error.
334          Likewise if the failing address isn't maximally aligned or if
335          we've recursed.
336
337          ??? Using a static variable here isn't task-safe, but it's
338          much too hard to do anything else and we're just determining
339          which exception to raise.  */
340       if (sip->si_code == SEGV_ACCERR
341           || (((long) sip->si_addr) & 3) != 0
342           || recurse)
343         {
344           exception = &constraint_error;
345           msg = "SIGSEGV";
346         }
347       else
348         {
349           /* See if the page before the faulting page is accessible.  Do that
350              by trying to access it.  We'd like to simply try to access
351              4096 + the faulting address, but it's not guaranteed to be
352              the actual address, just to be on the same page.  */
353           recurse++;
354           ((volatile char *)
355            ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
356           msg = "stack overflow (or erroneous memory access)";
357           exception = &storage_error;
358         }
359       break;
360
361     case SIGBUS:
362       exception = &program_error;
363       msg = "SIGBUS";
364       break;
365
366     case SIGFPE:
367       exception = &constraint_error;
368       msg = "SIGFPE";
369       break;
370
371     default:
372       exception = &program_error;
373       msg = "unhandled signal";
374     }
375
376   recurse = 0;
377   Raise_From_Signal_Handler (exception, (char *) msg);
378 }
379
380 void
381 __gnat_install_handler (void)
382 {
383   struct sigaction act;
384
385   /* Setup signal handler to map synchronous signals to appropriate
386      exceptions. Make sure that the handler isn't interrupted by another
387      signal that might cause a scheduling event!  */
388
389   act.sa_handler = (void (*) (int)) __gnat_error_handler;
390   act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
391   sigemptyset (&act.sa_mask);
392
393   /* Do not install handlers if interrupt state is "System".  */
394   if (__gnat_get_interrupt_state (SIGABRT) != 's')
395     sigaction (SIGABRT, &act, NULL);
396   if (__gnat_get_interrupt_state (SIGFPE) != 's')
397     sigaction (SIGFPE,  &act, NULL);
398   if (__gnat_get_interrupt_state (SIGILL) != 's')
399     sigaction (SIGILL,  &act, NULL);
400   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
401     sigaction (SIGSEGV, &act, NULL);
402   if (__gnat_get_interrupt_state (SIGBUS) != 's')
403     sigaction (SIGBUS,  &act, NULL);
404
405   __gnat_handler_installed = 1;
406 }
407
408 /* Routines called by s-mastop-tru64.adb.  */
409
410 #define SC_GP 29
411
412 char *
413 __gnat_get_code_loc (struct sigcontext *context)
414 {
415   return (char *) context->sc_pc;
416 }
417
418 void
419 __gnat_set_code_loc (struct sigcontext *context, char *pc)
420 {
421   context->sc_pc = (long) pc;
422 }
423
424 size_t
425 __gnat_machine_state_length (void)
426 {
427   return sizeof (struct sigcontext);
428 }
429
430 /*****************/
431 /* HP-UX section */
432 /*****************/
433
434 #elif defined (__hpux__)
435
436 #include <signal.h>
437 #include <sys/ucontext.h>
438
439 static void
440 __gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext);
441
442 static void
443 __gnat_error_handler
444   (int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED, void *ucontext)
445 {
446   struct Exception_Data *exception;
447   const char *msg;
448
449   switch (sig)
450     {
451     case SIGSEGV:
452       /* FIXME: we need to detect the case of a *real* SIGSEGV.  */
453       exception = &storage_error;
454       msg = "stack overflow or erroneous memory access";
455       break;
456
457     case SIGBUS:
458       exception = &constraint_error;
459       msg = "SIGBUS";
460       break;
461
462     case SIGFPE:
463       exception = &constraint_error;
464       msg = "SIGFPE";
465       break;
466
467     default:
468       exception = &program_error;
469       msg = "unhandled signal";
470     }
471
472   Raise_From_Signal_Handler (exception, msg);
473 }
474
475 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
476 #if defined (__hppa__)
477 char __gnat_alternate_stack[16 * 1024]; /* 2 * SIGSTKSZ */
478 #else
479 char __gnat_alternate_stack[128 * 1024]; /* MINSIGSTKSZ */
480 #endif
481
482 void
483 __gnat_install_handler (void)
484 {
485   struct sigaction act;
486
487   /* Set up signal handler to map synchronous signals to appropriate
488      exceptions.  Make sure that the handler isn't interrupted by another
489      signal that might cause a scheduling event!  Also setup an alternate
490      stack region for the handler execution so that stack overflows can be
491      handled properly, avoiding a SEGV generation from stack usage by the
492      handler itself.  */
493
494   stack_t stack;
495   stack.ss_sp = __gnat_alternate_stack;
496   stack.ss_size = sizeof (__gnat_alternate_stack);
497   stack.ss_flags = 0;
498   sigaltstack (&stack, NULL);
499
500   act.sa_sigaction = __gnat_error_handler;
501   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
502   sigemptyset (&act.sa_mask);
503
504   /* Do not install handlers if interrupt state is "System".  */
505   if (__gnat_get_interrupt_state (SIGABRT) != 's')
506     sigaction (SIGABRT, &act, NULL);
507   if (__gnat_get_interrupt_state (SIGFPE) != 's')
508     sigaction (SIGFPE,  &act, NULL);
509   if (__gnat_get_interrupt_state (SIGILL) != 's')
510     sigaction (SIGILL,  &act, NULL);
511   if (__gnat_get_interrupt_state (SIGBUS) != 's')
512     sigaction (SIGBUS,  &act, NULL);
513   act.sa_flags |= SA_ONSTACK;
514   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
515     sigaction (SIGSEGV, &act, NULL);
516
517   __gnat_handler_installed = 1;
518 }
519
520 /*********************/
521 /* GNU/Linux Section */
522 /*********************/
523
524 #elif defined (linux) && (defined (i386) || defined (__x86_64__) \
525                           || defined (__ia64__) || defined (__powerpc__))
526
527 #include <signal.h>
528
529 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
530 #include <sys/ucontext.h>
531
532 /* GNU/Linux, which uses glibc, does not define NULL in included
533    header files.  */
534
535 #if !defined (NULL)
536 #define NULL ((void *) 0)
537 #endif
538
539 #if defined (MaRTE)
540
541 /* MaRTE OS provides its own version of sigaction, sigfillset, and
542    sigemptyset (overriding these symbol names).  We want to make sure that
543    the versions provided by the underlying C library are used here (these
544    versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
545    and fake_linux_sigemptyset, respectively).  The MaRTE library will not
546    always be present (it will not be linked if no tasking constructs are
547    used), so we use the weak symbol mechanism to point always to the symbols
548    defined within the C library.  */
549
550 #pragma weak linux_sigaction
551 int linux_sigaction (int signum, const struct sigaction *act,
552                      struct sigaction *oldact) {
553   return sigaction (signum, act, oldact);
554 }
555 #define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
556
557 #pragma weak fake_linux_sigfillset
558 void fake_linux_sigfillset (sigset_t *set) {
559   sigfillset (set);
560 }
561 #define sigfillset(set) fake_linux_sigfillset (set)
562
563 #pragma weak fake_linux_sigemptyset
564 void fake_linux_sigemptyset (sigset_t *set) {
565   sigemptyset (set);
566 }
567 #define sigemptyset(set) fake_linux_sigemptyset (set)
568
569 #endif
570
571 static void __gnat_error_handler (int, siginfo_t *siginfo, void *ucontext);
572
573 #if defined (i386) || defined (__x86_64__) || defined (__ia64__)
574
575 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
576
577 void
578 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
579 {
580   mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
581
582   /* On the i386 and x86-64 architectures, stack checking is performed by
583      means of probes with moving stack pointer, that is to say the probed
584      address is always the value of the stack pointer.  Upon hitting the
585      guard page, the stack pointer therefore points to an inaccessible
586      address and an alternate signal stack is needed to run the handler.
587      But there is an additional twist: on these architectures, the EH
588      return code writes the address of the handler at the target CFA's
589      value on the stack before doing the jump.  As a consequence, if
590      there is an active handler in the frame whose stack has overflowed,
591      the stack pointer must nevertheless point to an accessible address
592      by the time the EH return is executed.
593
594      We therefore adjust the saved value of the stack pointer by the size
595      of one page + a small dope of 4 words, in order to make sure that it
596      points to an accessible address in case it's used as the target CFA.
597      The stack checking code guarantees that this address is unused by the
598      time this happens.  */
599
600 #if defined (i386)
601   unsigned long pattern = *(unsigned long *)mcontext->gregs[REG_EIP];
602   /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode.  */
603   if (signo == SIGSEGV && pattern == 0x00240c83)
604     mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
605 #elif defined (__x86_64__)
606   unsigned long pattern = *(unsigned long *)mcontext->gregs[REG_RIP];
607   /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode.  */
608   if (signo == SIGSEGV && (pattern & 0xffffffffff) == 0x00240c8348)
609     mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
610 #elif defined (__ia64__)
611   /* ??? The IA-64 unwinder doesn't compensate for signals.  */
612   mcontext->sc_ip++;
613 #endif
614 }
615
616 #endif
617
618 static void
619 __gnat_error_handler (int sig,
620                       siginfo_t *siginfo ATTRIBUTE_UNUSED,
621                       void *ucontext)
622 {
623   struct Exception_Data *exception;
624   const char *msg;
625   static int recurse = 0;
626
627   switch (sig)
628     {
629     case SIGSEGV:
630       /* If the problem was permissions, this is a constraint error.
631        Likewise if the failing address isn't maximally aligned or if
632        we've recursed.
633
634        ??? Using a static variable here isn't task-safe, but it's
635        much too hard to do anything else and we're just determining
636        which exception to raise.  */
637       if (recurse)
638       {
639         exception = &constraint_error;
640         msg = "SIGSEGV";
641       }
642       else
643       {
644         /* Here we would like a discrimination test to see whether the
645            page before the faulting address is accessible. Unfortunately
646            Linux seems to have no way of giving us the faulting address.
647
648            In versions of a-init.c before 1.95, we had a test of the page
649            before the stack pointer using:
650
651             recurse++;
652              ((volatile char *)
653               ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
654
655            but that's wrong, since it tests the stack pointer location, and
656            the current stack probe code does not move the stack pointer
657            until all probes succeed.
658
659            For now we simply do not attempt any discrimination at all. Note
660            that this is quite acceptable, since a "real" SIGSEGV can only
661            occur as the result of an erroneous program.  */
662
663         msg = "stack overflow (or erroneous memory access)";
664         exception = &storage_error;
665       }
666       break;
667
668     case SIGBUS:
669       exception = &constraint_error;
670       msg = "SIGBUS";
671       break;
672
673     case SIGFPE:
674       exception = &constraint_error;
675       msg = "SIGFPE";
676       break;
677
678     default:
679       exception = &program_error;
680       msg = "unhandled signal";
681     }
682   recurse = 0;
683
684   /* We adjust the interrupted context here (and not in the fallback
685      unwinding routine) because recent versions of the Native POSIX
686      Thread Library (NPTL) are compiled with unwind information, so
687      the fallback routine is never executed for signal frames.  */
688   __gnat_adjust_context_for_raise (sig, ucontext);
689
690   Raise_From_Signal_Handler (exception, msg);
691 }
692
693 #if defined (i386) || defined (__x86_64__)
694 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
695 char __gnat_alternate_stack[16 * 1024]; /* 2 * SIGSTKSZ */
696 #endif
697
698 #ifdef __XENO__
699 #include <sys/mman.h>
700 #include <native/task.h>
701
702 RT_TASK main_task;
703 #endif
704
705 void
706 __gnat_install_handler (void)
707 {
708   struct sigaction act;
709
710 #ifdef __XENO__
711   int prio;
712
713   if (__gl_main_priority == -1)
714     prio = 49;
715   else
716     prio = __gl_main_priority;
717
718   /* Avoid memory swapping for this program */
719
720   mlockall (MCL_CURRENT|MCL_FUTURE);
721
722   /* Turn the current Linux task into a native Xenomai task */
723
724   rt_task_shadow(&main_task, "environment_task", prio, T_FPU);
725 #endif
726
727   /* Set up signal handler to map synchronous signals to appropriate
728      exceptions.  Make sure that the handler isn't interrupted by another
729      signal that might cause a scheduling event!  Also setup an alternate
730      stack region for the handler execution so that stack overflows can be
731      handled properly, avoiding a SEGV generation from stack usage by the
732      handler itself.  */
733
734 #if defined (i386) || defined (__x86_64__)
735   stack_t stack;
736   stack.ss_sp = __gnat_alternate_stack;
737   stack.ss_size = sizeof (__gnat_alternate_stack);
738   stack.ss_flags = 0;
739   sigaltstack (&stack, NULL);
740 #endif
741
742   act.sa_sigaction = __gnat_error_handler;
743   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
744   sigemptyset (&act.sa_mask);
745
746   /* Do not install handlers if interrupt state is "System".  */
747   if (__gnat_get_interrupt_state (SIGABRT) != 's')
748     sigaction (SIGABRT, &act, NULL);
749   if (__gnat_get_interrupt_state (SIGFPE) != 's')
750     sigaction (SIGFPE,  &act, NULL);
751   if (__gnat_get_interrupt_state (SIGILL) != 's')
752     sigaction (SIGILL,  &act, NULL);
753   if (__gnat_get_interrupt_state (SIGBUS) != 's')
754     sigaction (SIGBUS,  &act, NULL);
755 #if defined (i386) || defined (__x86_64__)
756   act.sa_flags |= SA_ONSTACK;
757 #endif
758   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
759     sigaction (SIGSEGV, &act, NULL);
760
761   __gnat_handler_installed = 1;
762 }
763
764 /****************/
765 /* IRIX Section */
766 /****************/
767
768 #elif defined (sgi)
769
770 #include <signal.h>
771 #include <siginfo.h>
772
773 #ifndef NULL
774 #define NULL 0
775 #endif
776
777 #define SIGADAABORT 48
778 #define SIGNAL_STACK_SIZE 4096
779 #define SIGNAL_STACK_ALIGNMENT 64
780
781 #define Check_Abort_Status     \
782                       system__soft_links__check_abort_status
783 extern int (*Check_Abort_Status) (void);
784
785 extern struct Exception_Data _abort_signal;
786
787 static void __gnat_error_handler (int, int, sigcontext_t *);
788
789 /* We are not setting the SA_SIGINFO bit in the sigaction flags when
790    connecting that handler, with the effects described in the sigaction
791    man page:
792
793           SA_SIGINFO [...]
794           If cleared and the signal is caught, the first argument is
795           also the signal number but the second argument is the signal
796           code identifying the cause of the signal. The third argument
797           points to a sigcontext_t structure containing the receiving
798           process's context when the signal was delivered.  */
799
800 static void
801 __gnat_error_handler (int sig, int code, sigcontext_t *sc ATTRIBUTE_UNUSED)
802 {
803   struct Exception_Data *exception;
804   const char *msg;
805
806   switch (sig)
807     {
808     case SIGSEGV:
809       if (code == EFAULT)
810         {
811           exception = &program_error;
812           msg = "SIGSEGV: (Invalid virtual address)";
813         }
814       else if (code == ENXIO)
815         {
816           exception = &program_error;
817           msg = "SIGSEGV: (Read beyond mapped object)";
818         }
819       else if (code == ENOSPC)
820         {
821           exception = &program_error; /* ??? storage_error ??? */
822           msg = "SIGSEGV: (Autogrow for file failed)";
823         }
824       else if (code == EACCES || code == EEXIST)
825         {
826           /* ??? We handle stack overflows here, some of which do trigger
827                  SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
828                  the documented valid codes for SEGV in the signal(5) man
829                  page.  */
830
831           /* ??? Re-add smarts to further verify that we launched
832                  the stack into a guard page, not an attempt to
833                  write to .text or something.  */
834           exception = &storage_error;
835           msg = "SIGSEGV: (stack overflow or erroneous memory access)";
836         }
837       else
838         {
839           /* Just in case the OS guys did it to us again.  Sometimes
840              they fail to document all of the valid codes that are
841              passed to signal handlers, just in case someone depends
842              on knowing all the codes.  */
843           exception = &program_error;
844           msg = "SIGSEGV: (Undocumented reason)";
845         }
846       break;
847
848     case SIGBUS:
849       /* Map all bus errors to Program_Error.  */
850       exception = &program_error;
851       msg = "SIGBUS";
852       break;
853
854     case SIGFPE:
855       /* Map all fpe errors to Constraint_Error.  */
856       exception = &constraint_error;
857       msg = "SIGFPE";
858       break;
859
860     case SIGADAABORT:
861       if ((*Check_Abort_Status) ())
862         {
863           exception = &_abort_signal;
864           msg = "";
865         }
866       else
867         return;
868
869       break;
870
871     default:
872       /* Everything else is a Program_Error.  */
873       exception = &program_error;
874       msg = "unhandled signal";
875     }
876
877   Raise_From_Signal_Handler (exception, msg);
878 }
879
880 void
881 __gnat_install_handler (void)
882 {
883   struct sigaction act;
884
885   /* Setup signal handler to map synchronous signals to appropriate
886      exceptions.  Make sure that the handler isn't interrupted by another
887      signal that might cause a scheduling event!  */
888
889   act.sa_handler = __gnat_error_handler;
890   act.sa_flags = SA_NODEFER + SA_RESTART;
891   sigfillset (&act.sa_mask);
892   sigemptyset (&act.sa_mask);
893
894   /* Do not install handlers if interrupt state is "System".  */
895   if (__gnat_get_interrupt_state (SIGABRT) != 's')
896     sigaction (SIGABRT, &act, NULL);
897   if (__gnat_get_interrupt_state (SIGFPE) != 's')
898     sigaction (SIGFPE,  &act, NULL);
899   if (__gnat_get_interrupt_state (SIGILL) != 's')
900     sigaction (SIGILL,  &act, NULL);
901   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
902     sigaction (SIGSEGV, &act, NULL);
903   if (__gnat_get_interrupt_state (SIGBUS) != 's')
904     sigaction (SIGBUS,  &act, NULL);
905   if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
906     sigaction (SIGADAABORT,  &act, NULL);
907
908   __gnat_handler_installed = 1;
909 }
910
911 /*******************/
912 /* LynxOS Section */
913 /*******************/
914
915 #elif defined (__Lynx__)
916
917 #include <signal.h>
918 #include <unistd.h>
919
920 static void
921 __gnat_error_handler (int sig)
922 {
923   struct Exception_Data *exception;
924   const char *msg;
925
926   switch(sig)
927   {
928     case SIGFPE:
929       exception = &constraint_error;
930       msg = "SIGFPE";
931       break;
932     case SIGILL:
933       exception = &constraint_error;
934       msg = "SIGILL";
935       break;
936     case SIGSEGV:
937       exception = &storage_error;
938       msg = "stack overflow or erroneous memory access";
939       break;
940     case SIGBUS:
941       exception = &constraint_error;
942       msg = "SIGBUS";
943       break;
944     default:
945       exception = &program_error;
946       msg = "unhandled signal";
947     }
948
949     Raise_From_Signal_Handler(exception, msg);
950 }
951
952 void
953 __gnat_install_handler(void)
954 {
955   struct sigaction act;
956
957   act.sa_handler = __gnat_error_handler;
958   act.sa_flags = 0x0;
959   sigemptyset (&act.sa_mask);
960
961   /* Do not install handlers if interrupt state is "System".  */
962   if (__gnat_get_interrupt_state (SIGFPE) != 's')
963     sigaction (SIGFPE,  &act, NULL);
964   if (__gnat_get_interrupt_state (SIGILL) != 's')
965     sigaction (SIGILL,  &act, NULL);
966   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
967     sigaction (SIGSEGV, &act, NULL);
968   if (__gnat_get_interrupt_state (SIGBUS) != 's')
969     sigaction (SIGBUS,  &act, NULL);
970
971   __gnat_handler_installed = 1;
972 }
973
974 /*******************/
975 /* Solaris Section */
976 /*******************/
977
978 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
979
980 #include <signal.h>
981 #include <siginfo.h>
982 #include <sys/ucontext.h>
983 #include <sys/regset.h>
984
985 /* The code below is common to SPARC and x86.  Beware of the delay slot
986    differences for signal context adjustments.  */
987
988 #if defined (__sparc)
989 #define RETURN_ADDR_OFFSET 8
990 #else
991 #define RETURN_ADDR_OFFSET 0
992 #endif
993
994 /* Likewise regarding how the "instruction pointer" register slot can
995    be identified in signal machine contexts.  We have either "REG_PC"
996    or "PC" at hand, depending on the target CPU and Solaris version.  */
997
998 #if !defined (REG_PC)
999 #define REG_PC PC
1000 #endif
1001
1002 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1003
1004 static void
1005 __gnat_error_handler (int sig, siginfo_t *sip, ucontext_t *uctx)
1006 {
1007   struct Exception_Data *exception;
1008   static int recurse = 0;
1009   const char *msg;
1010
1011   /* If this was an explicit signal from a "kill", just resignal it.  */
1012   if (SI_FROMUSER (sip))
1013     {
1014       signal (sig, SIG_DFL);
1015       kill (getpid(), sig);
1016     }
1017
1018   /* Otherwise, treat it as something we handle.  */
1019   switch (sig)
1020     {
1021     case SIGSEGV:
1022       /* If the problem was permissions, this is a constraint error.
1023          Likewise if the failing address isn't maximally aligned or if
1024          we've recursed.
1025
1026          ??? Using a static variable here isn't task-safe, but it's
1027          much too hard to do anything else and we're just determining
1028          which exception to raise.  */
1029       if (sip->si_code == SEGV_ACCERR
1030           || (((long) sip->si_addr) & 3) != 0
1031           || recurse)
1032         {
1033           exception = &constraint_error;
1034           msg = "SIGSEGV";
1035         }
1036       else
1037         {
1038           /* See if the page before the faulting page is accessible.  Do that
1039              by trying to access it.  We'd like to simply try to access
1040              4096 + the faulting address, but it's not guaranteed to be
1041              the actual address, just to be on the same page.  */
1042           recurse++;
1043           ((volatile char *)
1044            ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1045           exception = &storage_error;
1046           msg = "stack overflow (or erroneous memory access)";
1047         }
1048       break;
1049
1050     case SIGBUS:
1051       exception = &program_error;
1052       msg = "SIGBUS";
1053       break;
1054
1055     case SIGFPE:
1056       exception = &constraint_error;
1057       msg = "SIGFPE";
1058       break;
1059
1060     default:
1061       exception = &program_error;
1062       msg = "unhandled signal";
1063     }
1064
1065   recurse = 0;
1066
1067   Raise_From_Signal_Handler (exception, msg);
1068 }
1069
1070 void
1071 __gnat_install_handler (void)
1072 {
1073   struct sigaction act;
1074
1075   /* Set up signal handler to map synchronous signals to appropriate
1076      exceptions.  Make sure that the handler isn't interrupted by another
1077      signal that might cause a scheduling event!  */
1078
1079   act.sa_handler = __gnat_error_handler;
1080   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1081   sigemptyset (&act.sa_mask);
1082
1083   /* Do not install handlers if interrupt state is "System".  */
1084   if (__gnat_get_interrupt_state (SIGABRT) != 's')
1085     sigaction (SIGABRT, &act, NULL);
1086   if (__gnat_get_interrupt_state (SIGFPE) != 's')
1087     sigaction (SIGFPE,  &act, NULL);
1088   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1089     sigaction (SIGSEGV, &act, NULL);
1090   if (__gnat_get_interrupt_state (SIGBUS) != 's')
1091     sigaction (SIGBUS,  &act, NULL);
1092
1093   __gnat_handler_installed = 1;
1094 }
1095
1096 /***************/
1097 /* VMS Section */
1098 /***************/
1099
1100 #elif defined (VMS)
1101
1102 /* Routine called from binder to override default feature values. */
1103 void __gnat_set_features ();
1104 int __gnat_features_set = 0;
1105
1106 long __gnat_error_handler (int *, void *);
1107
1108 #ifdef __IA64
1109 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1110 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1111 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1112 #else
1113 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1114 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1115 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
1116 #endif
1117
1118 #if defined (IN_RTS) && !defined (__IA64)
1119
1120 /* The prehandler actually gets control first on a condition.  It swaps the
1121    stack pointer and calls the handler (__gnat_error_handler).  */
1122 extern long __gnat_error_prehandler (void);
1123
1124 extern char *__gnat_error_prehandler_stack;   /* Alternate signal stack */
1125 #endif
1126
1127 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1128    Most of these are also defined in the header file ssdef.h which has not
1129    yet been converted to be recognized by GNU C.  */
1130
1131 /* Defining these as macros, as opposed to external addresses, allows
1132    them to be used in a case statement below.  */
1133 #define SS$_ACCVIO            12
1134 #define SS$_HPARITH         1284
1135 #define SS$_STKOVF          1364
1136 #define SS$_RESIGNAL        2328
1137
1138 /* These codes are in standard message libraries.  */
1139 extern int CMA$_EXIT_THREAD;
1140 extern int SS$_DEBUG;
1141 extern int SS$_INTDIV;
1142 extern int LIB$_KEYNOTFOU;
1143 extern int LIB$_ACTIMAGE;
1144 extern int MTH$_FLOOVEMAT;       /* Some ACVC_21 CXA tests */
1145
1146 /* These codes are non standard, which is to say the author is
1147    not sure if they are defined in the standard message libraries
1148    so keep them as macros for now.  */
1149 #define RDB$_STREAM_EOF 20480426
1150 #define FDL$_UNPRIKW 11829410
1151
1152 struct cond_except {
1153   const int *cond;
1154   const struct Exception_Data *except;
1155 };
1156
1157 struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1158
1159 /* Conditions that don't have an Ada exception counterpart must raise
1160    Non_Ada_Error.  Since this is defined in s-auxdec, it should only be
1161    referenced by user programs, not the compiler or tools.  Hence the
1162    #ifdef IN_RTS.  */
1163
1164 #ifdef IN_RTS
1165
1166 #define Status_Error ada__io_exceptions__status_error
1167 extern struct Exception_Data Status_Error;
1168
1169 #define Mode_Error ada__io_exceptions__mode_error
1170 extern struct Exception_Data Mode_Error;
1171
1172 #define Name_Error ada__io_exceptions__name_error
1173 extern struct Exception_Data Name_Error;
1174
1175 #define Use_Error ada__io_exceptions__use_error
1176 extern struct Exception_Data Use_Error;
1177
1178 #define Device_Error ada__io_exceptions__device_error
1179 extern struct Exception_Data Device_Error;
1180
1181 #define End_Error ada__io_exceptions__end_error
1182 extern struct Exception_Data End_Error;
1183
1184 #define Data_Error ada__io_exceptions__data_error
1185 extern struct Exception_Data Data_Error;
1186
1187 #define Layout_Error ada__io_exceptions__layout_error
1188 extern struct Exception_Data Layout_Error;
1189
1190 #define Non_Ada_Error system__aux_dec__non_ada_error
1191 extern struct Exception_Data Non_Ada_Error;
1192
1193 #define Coded_Exception system__vms_exception_table__coded_exception
1194 extern struct Exception_Data *Coded_Exception (Exception_Code);
1195
1196 #define Base_Code_In system__vms_exception_table__base_code_in
1197 extern Exception_Code Base_Code_In (Exception_Code);
1198
1199 /* DEC Ada exceptions are not defined in a header file, so they
1200    must be declared as external addresses.  */
1201
1202 extern int ADA$_PROGRAM_ERROR;
1203 extern int ADA$_LOCK_ERROR;
1204 extern int ADA$_EXISTENCE_ERROR;
1205 extern int ADA$_KEY_ERROR;
1206 extern int ADA$_KEYSIZERR;
1207 extern int ADA$_STAOVF;
1208 extern int ADA$_CONSTRAINT_ERRO;
1209 extern int ADA$_IOSYSFAILED;
1210 extern int ADA$_LAYOUT_ERROR;
1211 extern int ADA$_STORAGE_ERROR;
1212 extern int ADA$_DATA_ERROR;
1213 extern int ADA$_DEVICE_ERROR;
1214 extern int ADA$_END_ERROR;
1215 extern int ADA$_MODE_ERROR;
1216 extern int ADA$_NAME_ERROR;
1217 extern int ADA$_STATUS_ERROR;
1218 extern int ADA$_NOT_OPEN;
1219 extern int ADA$_ALREADY_OPEN;
1220 extern int ADA$_USE_ERROR;
1221 extern int ADA$_UNSUPPORTED;
1222 extern int ADA$_FAC_MODE_MISMAT;
1223 extern int ADA$_ORG_MISMATCH;
1224 extern int ADA$_RFM_MISMATCH;
1225 extern int ADA$_RAT_MISMATCH;
1226 extern int ADA$_MRS_MISMATCH;
1227 extern int ADA$_MRN_MISMATCH;
1228 extern int ADA$_KEY_MISMATCH;
1229 extern int ADA$_MAXLINEXC;
1230 extern int ADA$_LINEXCMRS;
1231
1232 /* DEC Ada specific conditions.  */
1233 static const struct cond_except dec_ada_cond_except_table [] = {
1234   {&ADA$_PROGRAM_ERROR,   &program_error},
1235   {&ADA$_USE_ERROR,       &Use_Error},
1236   {&ADA$_KEYSIZERR,       &program_error},
1237   {&ADA$_STAOVF,          &storage_error},
1238   {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1239   {&ADA$_IOSYSFAILED,     &Device_Error},
1240   {&ADA$_LAYOUT_ERROR,    &Layout_Error},
1241   {&ADA$_STORAGE_ERROR,   &storage_error},
1242   {&ADA$_DATA_ERROR,      &Data_Error},
1243   {&ADA$_DEVICE_ERROR,    &Device_Error},
1244   {&ADA$_END_ERROR,       &End_Error},
1245   {&ADA$_MODE_ERROR,      &Mode_Error},
1246   {&ADA$_NAME_ERROR,      &Name_Error},
1247   {&ADA$_STATUS_ERROR,    &Status_Error},
1248   {&ADA$_NOT_OPEN,        &Use_Error},
1249   {&ADA$_ALREADY_OPEN,    &Use_Error},
1250   {&ADA$_USE_ERROR,       &Use_Error},
1251   {&ADA$_UNSUPPORTED,     &Use_Error},
1252   {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1253   {&ADA$_ORG_MISMATCH,    &Use_Error},
1254   {&ADA$_RFM_MISMATCH,    &Use_Error},
1255   {&ADA$_RAT_MISMATCH,    &Use_Error},
1256   {&ADA$_MRS_MISMATCH,    &Use_Error},
1257   {&ADA$_MRN_MISMATCH,    &Use_Error},
1258   {&ADA$_KEY_MISMATCH,    &Use_Error},
1259   {&ADA$_MAXLINEXC,       &constraint_error},
1260   {&ADA$_LINEXCMRS,       &constraint_error},
1261   {0,                     0}
1262 };
1263
1264 #if 0
1265    /* Already handled by a pragma Import_Exception
1266       in Aux_IO_Exceptions */
1267   {&ADA$_LOCK_ERROR,      &Lock_Error},
1268   {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1269   {&ADA$_KEY_ERROR,       &Key_Error},
1270 #endif
1271
1272 #endif /* IN_RTS */
1273
1274 /* Non-DEC Ada specific conditions.  We could probably also put
1275    SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF.  */
1276 static const struct cond_except cond_except_table [] = {
1277   {&MTH$_FLOOVEMAT, &constraint_error},
1278   {&SS$_INTDIV,     &constraint_error},
1279   {0,               0}
1280 };
1281
1282 /* To deal with VMS conditions and their mapping to Ada exceptions,
1283    the __gnat_error_handler routine below is installed as an exception
1284    vector having precedence over DEC frame handlers.  Some conditions
1285    still need to be handled by such handlers, however, in which case
1286    __gnat_error_handler needs to return SS$_RESIGNAL.  Consider for
1287    instance the use of a third party library compiled with DECAda and
1288    performing its own exception handling internally.
1289
1290    To allow some user-level flexibility, which conditions should be
1291    resignaled is controlled by a predicate function, provided with the
1292    condition value and returning a boolean indication stating whether
1293    this condition should be resignaled or not.
1294
1295    That predicate function is called indirectly, via a function pointer,
1296    by __gnat_error_handler, and changing that pointer is allowed to the
1297    the user code by way of the __gnat_set_resignal_predicate interface.
1298
1299    The user level function may then implement what it likes, including
1300    for instance the maintenance of a dynamic data structure if the set
1301    of to be resignalled conditions has to change over the program's
1302    lifetime.
1303
1304    ??? This is not a perfect solution to deal with the possible
1305    interactions between the GNAT and the DECAda exception handling
1306    models and better (more general) schemes are studied.  This is so
1307    just provided as a convenient workaround in the meantime, and
1308    should be use with caution since the implementation has been kept
1309    very simple.  */
1310
1311 typedef int
1312 resignal_predicate (int code);
1313
1314 const int *cond_resignal_table [] = {
1315   &CMA$_EXIT_THREAD,
1316   &SS$_DEBUG,
1317   &LIB$_KEYNOTFOU,
1318   &LIB$_ACTIMAGE,
1319   (int *) RDB$_STREAM_EOF,
1320   (int *) FDL$_UNPRIKW,
1321   0
1322 };
1323
1324 const int facility_resignal_table [] = {
1325   0x1380000, /* RDB */
1326   0x2220000, /* SQL */
1327   0
1328 };
1329
1330 /* Default GNAT predicate for resignaling conditions.  */
1331
1332 static int
1333 __gnat_default_resignal_p (int code)
1334 {
1335   int i, iexcept;
1336
1337   for (i = 0; facility_resignal_table [i]; i++)
1338     if ((code & 0xfff0000) == facility_resignal_table [i])
1339       return 1;
1340
1341   for (i = 0, iexcept = 0;
1342        cond_resignal_table [i] &&
1343        !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1344        i++);
1345
1346   return iexcept;
1347 }
1348
1349 /* Static pointer to predicate that the __gnat_error_handler exception
1350    vector invokes to determine if it should resignal a condition.  */
1351
1352 static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1353
1354 /* User interface to change the predicate pointer to PREDICATE. Reset to
1355    the default if PREDICATE is null.  */
1356
1357 void
1358 __gnat_set_resignal_predicate (resignal_predicate * predicate)
1359 {
1360   if (predicate == 0)
1361     __gnat_resignal_p = __gnat_default_resignal_p;
1362   else
1363     __gnat_resignal_p = predicate;
1364 }
1365
1366 /* Should match System.Parameters.Default_Exception_Msg_Max_Length.  */
1367 #define Default_Exception_Msg_Max_Length 512
1368
1369 /* Action routine for SYS$PUTMSG. There may be multiple
1370    conditions, each with text to be appended to MESSAGE
1371    and separated by line termination.  */
1372
1373 static int
1374 copy_msg (msgdesc, message)
1375      struct descriptor_s *msgdesc;
1376      char *message;
1377 {
1378   int len = strlen (message);
1379   int copy_len;
1380
1381   /* Check for buffer overflow and skip.  */
1382   if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1383     {
1384       strcat (message, "\r\n");
1385       len += 2;
1386     }
1387
1388   /* Check for buffer overflow and truncate if necessary.  */
1389   copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1390               msgdesc->len :
1391               Default_Exception_Msg_Max_Length - 1 - len);
1392   strncpy (&message [len], msgdesc->adr, copy_len);
1393   message [len + copy_len] = 0;
1394
1395   return 0;
1396 }
1397
1398 long
1399 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1400 {
1401   struct Exception_Data *exception = 0;
1402   Exception_Code base_code;
1403   struct descriptor_s gnat_facility = {4,0,"GNAT"};
1404   char message [Default_Exception_Msg_Max_Length];
1405
1406   const char *msg = "";
1407
1408   /* Check for conditions to resignal which aren't effected by pragma
1409      Import_Exception.  */
1410   if (__gnat_resignal_p (sigargs [1]))
1411     return SS$_RESIGNAL;
1412
1413 #ifdef IN_RTS
1414   /* See if it's an imported exception.  Beware that registered exceptions
1415      are bound to their base code, with the severity bits masked off.  */
1416   base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1417   exception = Coded_Exception (base_code);
1418
1419   if (exception)
1420     {
1421       message [0] = 0;
1422
1423       /* Subtract PC & PSL fields which messes with PUTMSG.  */
1424       sigargs [0] -= 2;
1425       SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1426       sigargs [0] += 2;
1427       msg = message;
1428
1429       exception->Name_Length = 19;
1430       /* ??? The full name really should be get sys$getmsg returns.  */
1431       exception->Full_Name = "IMPORTED_EXCEPTION";
1432       exception->Import_Code = base_code;
1433
1434 #ifdef __IA64
1435       /* Do not adjust the program counter as already points to the next
1436          instruction (just after the call to LIB$STOP).  */
1437       Raise_From_Signal_Handler (exception, msg);
1438 #endif
1439     }
1440 #endif
1441
1442   if (exception == 0)
1443     switch (sigargs[1])
1444       {
1445       case SS$_ACCVIO:
1446         if (sigargs[3] == 0)
1447           {
1448             exception = &constraint_error;
1449             msg = "access zero";
1450           }
1451         else
1452           {
1453             exception = &storage_error;
1454             msg = "stack overflow (or erroneous memory access)";
1455           }
1456         __gnat_adjust_context_for_raise (0, (void *)mechargs);
1457         break;
1458
1459       case SS$_STKOVF:
1460         exception = &storage_error;
1461         msg = "stack overflow";
1462         __gnat_adjust_context_for_raise (0, (void *)mechargs);
1463         break;
1464
1465       case SS$_HPARITH:
1466 #ifndef IN_RTS
1467         return SS$_RESIGNAL; /* toplev.c handles for compiler */
1468 #else
1469         exception = &constraint_error;
1470         msg = "arithmetic error";
1471 #ifndef __alpha__
1472         /* No need to adjust pc on Alpha: the pc is already on the instruction
1473            after the trapping one.  */
1474         __gnat_adjust_context_for_raise (0, (void *)mechargs);
1475 #endif
1476 #endif
1477         break;
1478
1479       default:
1480 #ifdef IN_RTS
1481         {
1482           int i;
1483
1484           /* Scan the DEC Ada exception condition table for a match and fetch
1485              the associated GNAT exception pointer.  */
1486           for (i = 0;
1487                dec_ada_cond_except_table [i].cond &&
1488                !LIB$MATCH_COND (&sigargs [1],
1489                                 &dec_ada_cond_except_table [i].cond);
1490                i++);
1491           exception = (struct Exception_Data *)
1492             dec_ada_cond_except_table [i].except;
1493
1494           if (!exception)
1495             {
1496               /* Scan the VMS standard condition table for a match and fetch
1497                  the associated GNAT exception pointer.  */
1498               for (i = 0;
1499                    cond_except_table [i].cond &&
1500                    !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1501                    i++);
1502               exception = (struct Exception_Data *)
1503                 cond_except_table [i].except;
1504
1505               if (!exception)
1506                 /* User programs expect Non_Ada_Error to be raised, reference
1507                    DEC Ada test CXCONDHAN.  */
1508                 exception = &Non_Ada_Error;
1509             }
1510         }
1511 #else
1512         exception = &program_error;
1513 #endif
1514         message [0] = 0;
1515         /* Subtract PC & PSL fields which messes with PUTMSG.  */
1516         sigargs [0] -= 2;
1517         SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1518         sigargs [0] += 2;
1519         msg = message;
1520         break;
1521       }
1522
1523   Raise_From_Signal_Handler (exception, msg);
1524 }
1525
1526 long
1527 __gnat_error_handler (int *sigargs, void *mechargs)
1528 {
1529   return __gnat_handle_vms_condition (sigargs, mechargs);
1530 }
1531
1532 void
1533 __gnat_install_handler (void)
1534 {
1535   long prvhnd ATTRIBUTE_UNUSED;
1536
1537 #if !defined (IN_RTS)
1538   SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1539 #endif
1540
1541   /* On alpha-vms, we avoid the global vector annoyance thanks to frame based
1542      handlers to turn conditions into exceptions since GCC 3.4.  The global
1543      vector is still required for earlier GCC versions.  We're resorting to
1544      the __gnat_error_prehandler assembly function in this case.  */
1545
1546 #if defined (IN_RTS) && defined (__alpha__)
1547   if ((__GNUC__ * 10 + __GNUC_MINOR__) < 34)
1548     {
1549       char * c = (char *) xmalloc (2049);
1550
1551       __gnat_error_prehandler_stack = &c[2048];
1552       SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1553     }
1554 #endif
1555
1556   __gnat_handler_installed = 1;
1557 }
1558
1559 /* __gnat_adjust_context_for_raise for Alpha - see comments along with the
1560    default version later in this file.  */
1561
1562 #if defined (IN_RTS) && defined (__alpha__)
1563
1564 #include <vms/chfctxdef.h>
1565 #include <vms/chfdef.h>
1566
1567 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1568
1569 void
1570 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1571 {
1572   /* Add one to the address of the instruction signaling the condition,
1573      located in the sigargs array.  */
1574
1575   CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1576   CHF$SIGNAL_ARRAY * sigargs
1577     = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1578
1579   int vcount = sigargs->chf$is_sig_args;
1580   int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1581
1582   (*pc_slot) ++;
1583 }
1584
1585 #endif
1586
1587 /* __gnat_adjust_context_for_raise for ia64.  */
1588
1589 #if defined (IN_RTS) && defined (__IA64)
1590
1591 #include <vms/chfctxdef.h>
1592 #include <vms/chfdef.h>
1593
1594 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1595
1596 typedef unsigned long long u64;
1597
1598 void
1599 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1600 {
1601   /* Add one to the address of the instruction signaling the condition,
1602      located in the 64bits sigargs array.  */
1603
1604   CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1605
1606   CHF64$SIGNAL_ARRAY *chfsig64
1607     = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1608
1609   u64 * post_sigarray
1610     = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1611
1612   u64 * ih_pc_loc = post_sigarray - 2;
1613
1614   (*ih_pc_loc) ++;
1615 }
1616
1617 #endif
1618
1619 /* Feature logical name and global variable address pair */
1620 struct feature {char *name; int* gl_addr;};
1621
1622 /* Default values for GNAT features set by environment. */
1623 int __gl_no_malloc_64 = 0;
1624
1625 /* Array feature logical names and global variable addresses */
1626 static struct feature features[] = {
1627   {"GNAT$NO_MALLOC_64", &__gl_no_malloc_64},
1628   {0, 0}
1629 };
1630
1631 void __gnat_set_features ()
1632 {
1633   struct descriptor_s name_desc, result_desc;
1634   int i, status;
1635   unsigned short rlen;
1636
1637 #define MAXEQUIV 10
1638   char buff [MAXEQUIV];
1639
1640   /* Loop through features array and test name for enable/disable */
1641   for (i=0; features [i].name; i++)
1642     {
1643        name_desc.len = strlen (features [i].name);
1644        name_desc.mbz = 0;
1645        name_desc.adr = features [i].name;
1646
1647        result_desc.len = MAXEQUIV - 1;
1648        result_desc.mbz = 0;
1649        result_desc.adr = buff;
1650
1651        status = LIB$GET_LOGICAL (&name_desc, &result_desc, &rlen);
1652
1653        if (((status & 1) == 1) && (rlen < MAXEQUIV))
1654          buff [rlen] = 0;
1655        else
1656          strcpy (buff, "");
1657
1658        if (strcmp (buff, "ENABLE") == 0)
1659           *features [i].gl_addr = 1;
1660        else if (strcmp (buff, "DISABLE") == 0)
1661           *features [i].gl_addr = 0;
1662     }
1663
1664     __gnat_features_set = 1;
1665 }
1666
1667 /*******************/
1668 /* FreeBSD Section */
1669 /*******************/
1670
1671 #elif defined (__FreeBSD__)
1672
1673 #include <signal.h>
1674 #include <sys/ucontext.h>
1675 #include <unistd.h>
1676
1677 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1678
1679 static void
1680 __gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
1681                       ucontext_t *ucontext)
1682 {
1683   struct Exception_Data *exception;
1684   const char *msg;
1685
1686   switch (sig)
1687     {
1688     case SIGFPE:
1689       exception = &constraint_error;
1690       msg = "SIGFPE";
1691       break;
1692
1693     case SIGILL:
1694       exception = &constraint_error;
1695       msg = "SIGILL";
1696       break;
1697
1698     case SIGSEGV:
1699       exception = &storage_error;
1700       msg = "stack overflow or erroneous memory access";
1701       break;
1702
1703     case SIGBUS:
1704       exception = &constraint_error;
1705       msg = "SIGBUS";
1706       break;
1707
1708     default:
1709       exception = &program_error;
1710       msg = "unhandled signal";
1711     }
1712
1713   Raise_From_Signal_Handler (exception, msg);
1714 }
1715
1716 void
1717 __gnat_install_handler ()
1718 {
1719   struct sigaction act;
1720
1721   /* Set up signal handler to map synchronous signals to appropriate
1722      exceptions.  Make sure that the handler isn't interrupted by another
1723      signal that might cause a scheduling event!  */
1724
1725   act.sa_sigaction
1726     = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1727   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1728   (void) sigemptyset (&act.sa_mask);
1729
1730   (void) sigaction (SIGILL,  &act, NULL);
1731   (void) sigaction (SIGFPE,  &act, NULL);
1732   (void) sigaction (SIGSEGV, &act, NULL);
1733   (void) sigaction (SIGBUS,  &act, NULL);
1734
1735   __gnat_handler_installed = 1;
1736 }
1737
1738 /*******************/
1739 /* VxWorks Section */
1740 /*******************/
1741
1742 #elif defined(__vxworks)
1743
1744 #include <signal.h>
1745 #include <taskLib.h>
1746
1747 #ifndef __RTP__
1748 #include <intLib.h>
1749 #include <iv.h>
1750 #endif
1751
1752 #ifdef VTHREADS
1753 #include "private/vThreadsP.h"
1754 #endif
1755
1756 void __gnat_error_handler (int, void *, struct sigcontext *);
1757
1758 #ifndef __RTP__
1759
1760 /* Directly vectored Interrupt routines are not supported when using RTPs.  */
1761
1762 extern int __gnat_inum_to_ivec (int);
1763
1764 /* This is needed by the GNAT run time to handle Vxworks interrupts.  */
1765 int
1766 __gnat_inum_to_ivec (int num)
1767 {
1768   return INUM_TO_IVEC (num);
1769 }
1770 #endif
1771
1772 #if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1773
1774 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1775    on Alpha VxWorks and VxWorks 6.x (including RTPs).  */
1776
1777 extern long getpid (void);
1778
1779 long
1780 getpid (void)
1781 {
1782   return taskIdSelf ();
1783 }
1784 #endif
1785
1786 /* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
1787    handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
1788    doesn't.  */
1789 void
1790 __gnat_clear_exception_count (void)
1791 {
1792 #ifdef VTHREADS
1793   WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1794
1795   currentTask->vThreads.excCnt = 0;
1796 #endif
1797 }
1798
1799 /* Handle different SIGnal to exception mappings in different VxWorks
1800    versions.   */
1801 static void
1802 __gnat_map_signal (int sig)
1803 {
1804   struct Exception_Data *exception;
1805   const char *msg;
1806
1807   switch (sig)
1808     {
1809     case SIGFPE:
1810       exception = &constraint_error;
1811       msg = "SIGFPE";
1812       break;
1813 #ifdef VTHREADS
1814     case SIGILL:
1815       exception = &constraint_error;
1816       msg = "Floating point exception or SIGILL";
1817       break;
1818     case SIGSEGV:
1819       exception = &storage_error;
1820       msg = "SIGSEGV";
1821       break;
1822     case SIGBUS:
1823       exception = &storage_error;
1824       msg = "SIGBUS: possible stack overflow";
1825       break;
1826 #elif (_WRS_VXWORKS_MAJOR == 6)
1827     case SIGILL:
1828       exception = &constraint_error;
1829       msg = "SIGILL";
1830       break;
1831 #ifdef __RTP__
1832     /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
1833        since stack checking uses the probing mechanism.  */
1834     case SIGSEGV:
1835       exception = &storage_error;
1836       msg = "SIGSEGV: possible stack overflow";
1837       break;
1838     case SIGBUS:
1839       exception = &program_error;
1840       msg = "SIGBUS";
1841       break;
1842 #else
1843       /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
1844     case SIGSEGV:
1845       exception = &storage_error;
1846       msg = "SIGSEGV";
1847       break;
1848     case SIGBUS:
1849       exception = &storage_error;
1850       msg = "SIGBUS: possible stack overflow";
1851       break;
1852 #endif
1853 #else
1854     /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
1855        since stack checking uses the stack limit mechanism.  */
1856     case SIGILL:
1857       exception = &storage_error;
1858       msg = "SIGILL: possible stack overflow";
1859       break;
1860     case SIGSEGV:
1861       exception = &storage_error;
1862       msg = "SIGSEGV";
1863       break;
1864     case SIGBUS:
1865       exception = &program_error;
1866       msg = "SIGBUS";
1867       break;
1868 #endif
1869     default:
1870       exception = &program_error;
1871       msg = "unhandled signal";
1872     }
1873
1874   __gnat_clear_exception_count ();
1875   Raise_From_Signal_Handler (exception, msg);
1876 }
1877
1878 /* Tasking and Non-tasking signal handler.  Map SIGnal to Ada exception
1879    propagation after the required low level adjustments.  */
1880
1881 void
1882 __gnat_error_handler (int sig, void * si ATTRIBUTE_UNUSED,
1883                       struct sigcontext * sc)
1884 {
1885   sigset_t mask;
1886
1887   /* VxWorks will always mask out the signal during the signal handler and
1888      will reenable it on a longjmp.  GNAT does not generate a longjmp to
1889      return from a signal handler so the signal will still be masked unless
1890      we unmask it.  */
1891   sigprocmask (SIG_SETMASK, NULL, &mask);
1892   sigdelset (&mask, sig);
1893   sigprocmask (SIG_SETMASK, &mask, NULL);
1894
1895   __gnat_map_signal (sig);
1896 }
1897
1898 void
1899 __gnat_install_handler (void)
1900 {
1901   struct sigaction act;
1902
1903   /* Setup signal handler to map synchronous signals to appropriate
1904      exceptions.  Make sure that the handler isn't interrupted by another
1905      signal that might cause a scheduling event!  */
1906
1907   act.sa_handler = __gnat_error_handler;
1908   act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1909   sigemptyset (&act.sa_mask);
1910
1911   /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1912      applies to vectored hardware interrupts, not signals.  */
1913   sigaction (SIGFPE,  &act, NULL);
1914   sigaction (SIGILL,  &act, NULL);
1915   sigaction (SIGSEGV, &act, NULL);
1916   sigaction (SIGBUS,  &act, NULL);
1917
1918   __gnat_handler_installed = 1;
1919 }
1920
1921 #define HAVE_GNAT_INIT_FLOAT
1922
1923 void
1924 __gnat_init_float (void)
1925 {
1926   /* Disable overflow/underflow exceptions on the PPC processor, needed
1927      to get correct Ada semantics.  Note that for AE653 vThreads, the HW
1928      overflow settings are an OS configuration issue.  The instructions
1929      below have no effect.  */
1930 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1931   asm ("mtfsb0 25");
1932   asm ("mtfsb0 26");
1933 #endif
1934
1935 #if (defined (__i386__) || defined (i386)) && !defined (VTHREADS)
1936   /* This is used to properly initialize the FPU on an x86 for each
1937      process thread.  */
1938   asm ("finit");
1939 #endif
1940
1941   /* Similarly for SPARC64.  Achieved by masking bits in the Trap Enable Mask
1942      field of the Floating-point Status Register (see the SPARC Architecture
1943      Manual Version 9, p 48).  */
1944 #if defined (sparc64)
1945
1946 #define FSR_TEM_NVM (1 << 27)  /* Invalid operand  */
1947 #define FSR_TEM_OFM (1 << 26)  /* Overflow  */
1948 #define FSR_TEM_UFM (1 << 25)  /* Underflow  */
1949 #define FSR_TEM_DZM (1 << 24)  /* Division by Zero  */
1950 #define FSR_TEM_NXM (1 << 23)  /* Inexact result  */
1951   {
1952     unsigned int fsr;
1953
1954     __asm__("st %%fsr, %0" : "=m" (fsr));
1955     fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1956     __asm__("ld %0, %%fsr" : : "m" (fsr));
1957   }
1958 #endif
1959 }
1960
1961 /* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
1962    (if not null) when a new task is created.  It is initialized by
1963    System.Stack_Checking.Operations.Initialize_Stack_Limit.
1964    The use of a hook avoids to drag stack checking subprograms if stack
1965    checking is not used.  */
1966 void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
1967
1968 /******************/
1969 /* NetBSD Section */
1970 /******************/
1971
1972 #elif defined(__NetBSD__)
1973
1974 #include <signal.h>
1975 #include <unistd.h>
1976
1977 static void
1978 __gnat_error_handler (int sig)
1979 {
1980   struct Exception_Data *exception;
1981   const char *msg;
1982
1983   switch(sig)
1984   {
1985     case SIGFPE:
1986       exception = &constraint_error;
1987       msg = "SIGFPE";
1988       break;
1989     case SIGILL:
1990       exception = &constraint_error;
1991       msg = "SIGILL";
1992       break;
1993     case SIGSEGV:
1994       exception = &storage_error;
1995       msg = "stack overflow or erroneous memory access";
1996       break;
1997     case SIGBUS:
1998       exception = &constraint_error;
1999       msg = "SIGBUS";
2000       break;
2001     default:
2002       exception = &program_error;
2003       msg = "unhandled signal";
2004     }
2005
2006     Raise_From_Signal_Handler(exception, msg);
2007 }
2008
2009 void
2010 __gnat_install_handler(void)
2011 {
2012   struct sigaction act;
2013
2014   act.sa_handler = __gnat_error_handler;
2015   act.sa_flags = SA_NODEFER | SA_RESTART;
2016   sigemptyset (&act.sa_mask);
2017
2018   /* Do not install handlers if interrupt state is "System".  */
2019   if (__gnat_get_interrupt_state (SIGFPE) != 's')
2020     sigaction (SIGFPE,  &act, NULL);
2021   if (__gnat_get_interrupt_state (SIGILL) != 's')
2022     sigaction (SIGILL,  &act, NULL);
2023   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2024     sigaction (SIGSEGV, &act, NULL);
2025   if (__gnat_get_interrupt_state (SIGBUS) != 's')
2026     sigaction (SIGBUS,  &act, NULL);
2027
2028   __gnat_handler_installed = 1;
2029 }
2030
2031 /*******************/
2032 /* OpenBSD Section */
2033 /*******************/
2034
2035 #elif defined(__OpenBSD__)
2036
2037 #include <signal.h>
2038 #include <unistd.h>
2039
2040 static void
2041 __gnat_error_handler (int sig)
2042 {
2043   struct Exception_Data *exception;
2044   const char *msg;
2045
2046   switch(sig)
2047   {
2048     case SIGFPE:
2049       exception = &constraint_error;
2050       msg = "SIGFPE";
2051       break;
2052     case SIGILL:
2053       exception = &constraint_error;
2054       msg = "SIGILL";
2055       break;
2056     case SIGSEGV:
2057       exception = &storage_error;
2058       msg = "stack overflow or erroneous memory access";
2059       break;
2060     case SIGBUS:
2061       exception = &constraint_error;
2062       msg = "SIGBUS";
2063       break;
2064     default:
2065       exception = &program_error;
2066       msg = "unhandled signal";
2067     }
2068
2069     Raise_From_Signal_Handler(exception, msg);
2070 }
2071
2072 void
2073 __gnat_install_handler(void)
2074 {
2075   struct sigaction act;
2076
2077   act.sa_handler = __gnat_error_handler;
2078   act.sa_flags = SA_NODEFER | SA_RESTART;
2079   sigemptyset (&act.sa_mask);
2080
2081   /* Do not install handlers if interrupt state is "System" */
2082   if (__gnat_get_interrupt_state (SIGFPE) != 's')
2083     sigaction (SIGFPE,  &act, NULL);
2084   if (__gnat_get_interrupt_state (SIGILL) != 's')
2085     sigaction (SIGILL,  &act, NULL);
2086   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2087     sigaction (SIGSEGV, &act, NULL);
2088   if (__gnat_get_interrupt_state (SIGBUS) != 's')
2089     sigaction (SIGBUS,  &act, NULL);
2090
2091   __gnat_handler_installed = 1;
2092 }
2093
2094 /******************/
2095 /* Darwin Section */
2096 /******************/
2097
2098 #elif defined(__APPLE__)
2099
2100 #include <signal.h>
2101 #include <mach/mach_vm.h>
2102 #include <mach/vm_statistics.h>
2103
2104 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
2105 char __gnat_alternate_stack[64 * 1024]; /* 2 * MINSIGSTKSZ */
2106
2107 static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
2108
2109 /* Defined in xnu unix_signal.c  */
2110 #define UC_RESET_ALT_STACK      0x80000000
2111 extern int sigreturn (void *uc, int flavour);
2112
2113 /* Return true if ADDR is within a stack guard area.  */
2114 static int
2115 __gnat_is_stack_guard (mach_vm_address_t addr)
2116 {
2117   kern_return_t kret;
2118   vm_region_submap_info_data_64_t info;
2119   mach_vm_address_t start;
2120   mach_vm_size_t size;
2121   natural_t depth;
2122   mach_msg_type_number_t count;
2123
2124   count = VM_REGION_SUBMAP_INFO_COUNT_64;
2125   start = addr;
2126   size = -1;
2127   depth = 9999;
2128   kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
2129                                  (vm_region_recurse_info_t) &info, &count);
2130   if (kret == KERN_SUCCESS
2131       && addr >= start && addr < (start + size)
2132       && info.protection == VM_PROT_NONE
2133       && info.user_tag == VM_MEMORY_STACK)
2134     return 1;
2135   return 0;
2136 }
2137
2138 static void
2139 __gnat_error_handler (int sig, siginfo_t * si, void * uc)
2140 {
2141   struct Exception_Data *exception;
2142   const char *msg;
2143
2144   switch (sig)
2145     {
2146     case SIGSEGV:
2147     case SIGBUS:
2148       if (__gnat_is_stack_guard ((unsigned long)si->si_addr))
2149         {
2150           exception = &storage_error;
2151           msg = "stack overflow";
2152         }
2153       else
2154         {
2155           exception = &constraint_error;
2156           msg = "erroneous memory access";
2157         }
2158       /* Reset the use of alt stack, so that the alt stack will be used
2159          for the next signal delivery.  */
2160       sigreturn (NULL, UC_RESET_ALT_STACK);
2161       break;
2162
2163     case SIGFPE:
2164       exception = &constraint_error;
2165       msg = "SIGFPE";
2166       break;
2167
2168     default:
2169       exception = &program_error;
2170       msg = "unhandled signal";
2171     }
2172
2173   Raise_From_Signal_Handler (exception, msg);
2174 }
2175
2176 void
2177 __gnat_install_handler (void)
2178 {
2179   struct sigaction act;
2180
2181   /* Set up signal handler to map synchronous signals to appropriate
2182      exceptions.  Make sure that the handler isn't interrupted by another
2183      signal that might cause a scheduling event!  Also setup an alternate
2184      stack region for the handler execution so that stack overflows can be
2185      handled properly, avoiding a SEGV generation from stack usage by the
2186      handler itself (and it is required by Darwin).  */
2187
2188   stack_t stack;
2189   stack.ss_sp = __gnat_alternate_stack;
2190   stack.ss_size = sizeof (__gnat_alternate_stack);
2191   stack.ss_flags = 0;
2192   sigaltstack (&stack, NULL);
2193
2194   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2195   act.sa_sigaction = __gnat_error_handler;
2196   sigemptyset (&act.sa_mask);
2197
2198   /* Do not install handlers if interrupt state is "System".  */
2199   if (__gnat_get_interrupt_state (SIGABRT) != 's')
2200     sigaction (SIGABRT, &act, NULL);
2201   if (__gnat_get_interrupt_state (SIGFPE) != 's')
2202     sigaction (SIGFPE,  &act, NULL);
2203   if (__gnat_get_interrupt_state (SIGILL) != 's')
2204     sigaction (SIGILL,  &act, NULL);
2205
2206   act.sa_flags |= SA_ONSTACK;
2207   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2208     sigaction (SIGSEGV, &act, NULL);
2209   if (__gnat_get_interrupt_state (SIGBUS) != 's')
2210     sigaction (SIGBUS,  &act, NULL);
2211
2212   __gnat_handler_installed = 1;
2213 }
2214
2215 #else
2216
2217 /* For all other versions of GNAT, the handler does nothing.  */
2218
2219 /*******************/
2220 /* Default Section */
2221 /*******************/
2222
2223 void
2224 __gnat_install_handler (void)
2225 {
2226   __gnat_handler_installed = 1;
2227 }
2228
2229 #endif
2230
2231 /*********************/
2232 /* __gnat_init_float */
2233 /*********************/
2234
2235 /* This routine is called as each process thread is created, for possible
2236    initialization of the FP processor.  This version is used under INTERIX,
2237    WIN32 and could be used under OS/2.  */
2238
2239 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
2240   || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
2241   || defined (__OpenBSD__)
2242
2243 #define HAVE_GNAT_INIT_FLOAT
2244
2245 void
2246 __gnat_init_float (void)
2247 {
2248 #if defined (__i386__) || defined (i386) || defined (__x86_64)
2249
2250   /* This is used to properly initialize the FPU on an x86 for each
2251      process thread.  */
2252
2253   asm ("finit");
2254
2255 #endif  /* Defined __i386__ */
2256 }
2257 #endif
2258
2259 #ifndef HAVE_GNAT_INIT_FLOAT
2260
2261 /* All targets without a specific __gnat_init_float will use an empty one.  */
2262 void
2263 __gnat_init_float (void)
2264 {
2265 }
2266 #endif
2267
2268 /***********************************/
2269 /* __gnat_adjust_context_for_raise */
2270 /***********************************/
2271
2272 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2273
2274 /* All targets without a specific version will use an empty one.  */
2275
2276 /* Given UCONTEXT a pointer to a context structure received by a signal
2277    handler for SIGNO, perform the necessary adjustments to let the handler
2278    raise an exception.  Calls to this routine are not conditioned by the
2279    propagation scheme in use.  */
2280
2281 void
2282 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2283                                  void *ucontext ATTRIBUTE_UNUSED)
2284 {
2285   /* We used to compensate here for the raised from call vs raised from signal
2286      exception discrepancy with the GCC ZCX scheme, but this now can be dealt
2287      with generically in the unwinder (see GCC PR other/26208).  Only the VMS
2288      ports still do the compensation described in the few lines below.
2289
2290      *** Call vs signal exception discrepancy with GCC ZCX scheme ***
2291
2292      The GCC unwinder expects to be dealing with call return addresses, since
2293      this is the "nominal" case of what we retrieve while unwinding a regular
2294      call chain.
2295
2296      To evaluate if a handler applies at some point identified by a return
2297      address, the propagation engine needs to determine what region the
2298      corresponding call instruction pertains to.  Because the return address
2299      may not be attached to the same region as the call, the unwinder always
2300      subtracts "some" amount from a return address to search the region
2301      tables, amount chosen to ensure that the resulting address is inside the
2302      call instruction.
2303
2304      When we raise an exception from a signal handler, e.g. to transform a
2305      SIGSEGV into Storage_Error, things need to appear as if the signal
2306      handler had been "called" by the instruction which triggered the signal,
2307      so that exception handlers that apply there are considered.  What the
2308      unwinder will retrieve as the return address from the signal handler is
2309      what it will find as the faulting instruction address in the signal
2310      context pushed by the kernel.  Leaving this address untouched looses, if
2311      the triggering instruction happens to be the very first of a region, as
2312      the later adjustments performed by the unwinder would yield an address
2313      outside that region.  We need to compensate for the unwinder adjustments
2314      at some point, and this is what this routine is expected to do.
2315
2316      signo is passed because on some targets for some signals the PC in
2317      context points to the instruction after the faulting one, in which case
2318      the unwinder adjustment is still desired.  */
2319 }
2320
2321 #endif