OSDN Git Service

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