OSDN Git Service

* init.c (__gnat_error_handler, Solaris): Add ATTRIBUTE_UNUSED marker.
[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, 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 *cx ATTRIBUTE_UNUSED)
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 C$_SIGKILL;
1140 extern int CMA$_EXIT_THREAD;
1141 extern int SS$_DEBUG;
1142 extern int SS$_INTDIV;
1143 extern int LIB$_KEYNOTFOU;
1144 extern int LIB$_ACTIMAGE;
1145 extern int MTH$_FLOOVEMAT;       /* Some ACVC_21 CXA tests */
1146
1147 /* These codes are non standard, which is to say the author is
1148    not sure if they are defined in the standard message libraries
1149    so keep them as macros for now.  */
1150 #define RDB$_STREAM_EOF 20480426
1151 #define FDL$_UNPRIKW 11829410
1152
1153 struct cond_except {
1154   const int *cond;
1155   const struct Exception_Data *except;
1156 };
1157
1158 struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1159
1160 /* Conditions that don't have an Ada exception counterpart must raise
1161    Non_Ada_Error.  Since this is defined in s-auxdec, it should only be
1162    referenced by user programs, not the compiler or tools.  Hence the
1163    #ifdef IN_RTS.  */
1164
1165 #ifdef IN_RTS
1166
1167 #define Status_Error ada__io_exceptions__status_error
1168 extern struct Exception_Data Status_Error;
1169
1170 #define Mode_Error ada__io_exceptions__mode_error
1171 extern struct Exception_Data Mode_Error;
1172
1173 #define Name_Error ada__io_exceptions__name_error
1174 extern struct Exception_Data Name_Error;
1175
1176 #define Use_Error ada__io_exceptions__use_error
1177 extern struct Exception_Data Use_Error;
1178
1179 #define Device_Error ada__io_exceptions__device_error
1180 extern struct Exception_Data Device_Error;
1181
1182 #define End_Error ada__io_exceptions__end_error
1183 extern struct Exception_Data End_Error;
1184
1185 #define Data_Error ada__io_exceptions__data_error
1186 extern struct Exception_Data Data_Error;
1187
1188 #define Layout_Error ada__io_exceptions__layout_error
1189 extern struct Exception_Data Layout_Error;
1190
1191 #define Non_Ada_Error system__aux_dec__non_ada_error
1192 extern struct Exception_Data Non_Ada_Error;
1193
1194 #define Coded_Exception system__vms_exception_table__coded_exception
1195 extern struct Exception_Data *Coded_Exception (Exception_Code);
1196
1197 #define Base_Code_In system__vms_exception_table__base_code_in
1198 extern Exception_Code Base_Code_In (Exception_Code);
1199
1200 /* DEC Ada exceptions are not defined in a header file, so they
1201    must be declared as external addresses.  */
1202
1203 extern int ADA$_PROGRAM_ERROR;
1204 extern int ADA$_LOCK_ERROR;
1205 extern int ADA$_EXISTENCE_ERROR;
1206 extern int ADA$_KEY_ERROR;
1207 extern int ADA$_KEYSIZERR;
1208 extern int ADA$_STAOVF;
1209 extern int ADA$_CONSTRAINT_ERRO;
1210 extern int ADA$_IOSYSFAILED;
1211 extern int ADA$_LAYOUT_ERROR;
1212 extern int ADA$_STORAGE_ERROR;
1213 extern int ADA$_DATA_ERROR;
1214 extern int ADA$_DEVICE_ERROR;
1215 extern int ADA$_END_ERROR;
1216 extern int ADA$_MODE_ERROR;
1217 extern int ADA$_NAME_ERROR;
1218 extern int ADA$_STATUS_ERROR;
1219 extern int ADA$_NOT_OPEN;
1220 extern int ADA$_ALREADY_OPEN;
1221 extern int ADA$_USE_ERROR;
1222 extern int ADA$_UNSUPPORTED;
1223 extern int ADA$_FAC_MODE_MISMAT;
1224 extern int ADA$_ORG_MISMATCH;
1225 extern int ADA$_RFM_MISMATCH;
1226 extern int ADA$_RAT_MISMATCH;
1227 extern int ADA$_MRS_MISMATCH;
1228 extern int ADA$_MRN_MISMATCH;
1229 extern int ADA$_KEY_MISMATCH;
1230 extern int ADA$_MAXLINEXC;
1231 extern int ADA$_LINEXCMRS;
1232
1233 /* DEC Ada specific conditions.  */
1234 static const struct cond_except dec_ada_cond_except_table [] = {
1235   {&ADA$_PROGRAM_ERROR,   &program_error},
1236   {&ADA$_USE_ERROR,       &Use_Error},
1237   {&ADA$_KEYSIZERR,       &program_error},
1238   {&ADA$_STAOVF,          &storage_error},
1239   {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1240   {&ADA$_IOSYSFAILED,     &Device_Error},
1241   {&ADA$_LAYOUT_ERROR,    &Layout_Error},
1242   {&ADA$_STORAGE_ERROR,   &storage_error},
1243   {&ADA$_DATA_ERROR,      &Data_Error},
1244   {&ADA$_DEVICE_ERROR,    &Device_Error},
1245   {&ADA$_END_ERROR,       &End_Error},
1246   {&ADA$_MODE_ERROR,      &Mode_Error},
1247   {&ADA$_NAME_ERROR,      &Name_Error},
1248   {&ADA$_STATUS_ERROR,    &Status_Error},
1249   {&ADA$_NOT_OPEN,        &Use_Error},
1250   {&ADA$_ALREADY_OPEN,    &Use_Error},
1251   {&ADA$_USE_ERROR,       &Use_Error},
1252   {&ADA$_UNSUPPORTED,     &Use_Error},
1253   {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1254   {&ADA$_ORG_MISMATCH,    &Use_Error},
1255   {&ADA$_RFM_MISMATCH,    &Use_Error},
1256   {&ADA$_RAT_MISMATCH,    &Use_Error},
1257   {&ADA$_MRS_MISMATCH,    &Use_Error},
1258   {&ADA$_MRN_MISMATCH,    &Use_Error},
1259   {&ADA$_KEY_MISMATCH,    &Use_Error},
1260   {&ADA$_MAXLINEXC,       &constraint_error},
1261   {&ADA$_LINEXCMRS,       &constraint_error},
1262   {0,                     0}
1263 };
1264
1265 #if 0
1266    /* Already handled by a pragma Import_Exception
1267       in Aux_IO_Exceptions */
1268   {&ADA$_LOCK_ERROR,      &Lock_Error},
1269   {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1270   {&ADA$_KEY_ERROR,       &Key_Error},
1271 #endif
1272
1273 #endif /* IN_RTS */
1274
1275 /* Non-DEC Ada specific conditions.  We could probably also put
1276    SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF.  */
1277 static const struct cond_except cond_except_table [] = {
1278   {&MTH$_FLOOVEMAT, &constraint_error},
1279   {&SS$_INTDIV,     &constraint_error},
1280   {0,               0}
1281 };
1282
1283 /* To deal with VMS conditions and their mapping to Ada exceptions,
1284    the __gnat_error_handler routine below is installed as an exception
1285    vector having precedence over DEC frame handlers.  Some conditions
1286    still need to be handled by such handlers, however, in which case
1287    __gnat_error_handler needs to return SS$_RESIGNAL.  Consider for
1288    instance the use of a third party library compiled with DECAda and
1289    performing its own exception handling internally.
1290
1291    To allow some user-level flexibility, which conditions should be
1292    resignaled is controlled by a predicate function, provided with the
1293    condition value and returning a boolean indication stating whether
1294    this condition should be resignaled or not.
1295
1296    That predicate function is called indirectly, via a function pointer,
1297    by __gnat_error_handler, and changing that pointer is allowed to the
1298    the user code by way of the __gnat_set_resignal_predicate interface.
1299
1300    The user level function may then implement what it likes, including
1301    for instance the maintenance of a dynamic data structure if the set
1302    of to be resignalled conditions has to change over the program's
1303    lifetime.
1304
1305    ??? This is not a perfect solution to deal with the possible
1306    interactions between the GNAT and the DECAda exception handling
1307    models and better (more general) schemes are studied.  This is so
1308    just provided as a convenient workaround in the meantime, and
1309    should be use with caution since the implementation has been kept
1310    very simple.  */
1311
1312 typedef int
1313 resignal_predicate (int code);
1314
1315 const int *cond_resignal_table [] = {
1316   &C$_SIGKILL,
1317   &CMA$_EXIT_THREAD,
1318   &SS$_DEBUG,
1319   &LIB$_KEYNOTFOU,
1320   &LIB$_ACTIMAGE,
1321   (int *) RDB$_STREAM_EOF,
1322   (int *) FDL$_UNPRIKW,
1323   0
1324 };
1325
1326 const int facility_resignal_table [] = {
1327   0x1380000, /* RDB */
1328   0x2220000, /* SQL */
1329   0
1330 };
1331
1332 /* Default GNAT predicate for resignaling conditions.  */
1333
1334 static int
1335 __gnat_default_resignal_p (int code)
1336 {
1337   int i, iexcept;
1338
1339   for (i = 0; facility_resignal_table [i]; i++)
1340     if ((code & 0xfff0000) == facility_resignal_table [i])
1341       return 1;
1342
1343   for (i = 0, iexcept = 0;
1344        cond_resignal_table [i] &&
1345        !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1346        i++);
1347
1348   return iexcept;
1349 }
1350
1351 /* Static pointer to predicate that the __gnat_error_handler exception
1352    vector invokes to determine if it should resignal a condition.  */
1353
1354 static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1355
1356 /* User interface to change the predicate pointer to PREDICATE. Reset to
1357    the default if PREDICATE is null.  */
1358
1359 void
1360 __gnat_set_resignal_predicate (resignal_predicate * predicate)
1361 {
1362   if (predicate == 0)
1363     __gnat_resignal_p = __gnat_default_resignal_p;
1364   else
1365     __gnat_resignal_p = predicate;
1366 }
1367
1368 /* Should match System.Parameters.Default_Exception_Msg_Max_Length.  */
1369 #define Default_Exception_Msg_Max_Length 512
1370
1371 /* Action routine for SYS$PUTMSG. There may be multiple
1372    conditions, each with text to be appended to MESSAGE
1373    and separated by line termination.  */
1374
1375 static int
1376 copy_msg (msgdesc, message)
1377      struct descriptor_s *msgdesc;
1378      char *message;
1379 {
1380   int len = strlen (message);
1381   int copy_len;
1382
1383   /* Check for buffer overflow and skip.  */
1384   if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1385     {
1386       strcat (message, "\r\n");
1387       len += 2;
1388     }
1389
1390   /* Check for buffer overflow and truncate if necessary.  */
1391   copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1392               msgdesc->len :
1393               Default_Exception_Msg_Max_Length - 1 - len);
1394   strncpy (&message [len], msgdesc->adr, copy_len);
1395   message [len + copy_len] = 0;
1396
1397   return 0;
1398 }
1399
1400 long
1401 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1402 {
1403   struct Exception_Data *exception = 0;
1404   Exception_Code base_code;
1405   struct descriptor_s gnat_facility = {4,0,"GNAT"};
1406   char message [Default_Exception_Msg_Max_Length];
1407
1408   const char *msg = "";
1409
1410   /* Check for conditions to resignal which aren't effected by pragma
1411      Import_Exception.  */
1412   if (__gnat_resignal_p (sigargs [1]))
1413     return SS$_RESIGNAL;
1414
1415 #ifdef IN_RTS
1416   /* See if it's an imported exception.  Beware that registered exceptions
1417      are bound to their base code, with the severity bits masked off.  */
1418   base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1419   exception = Coded_Exception (base_code);
1420
1421   if (exception)
1422     {
1423       message [0] = 0;
1424
1425       /* Subtract PC & PSL fields which messes with PUTMSG.  */
1426       sigargs [0] -= 2;
1427       SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1428       sigargs [0] += 2;
1429       msg = message;
1430
1431       exception->Name_Length = 19;
1432       /* ??? The full name really should be get sys$getmsg returns.  */
1433       exception->Full_Name = "IMPORTED_EXCEPTION";
1434       exception->Import_Code = base_code;
1435
1436 #ifdef __IA64
1437       /* Do not adjust the program counter as already points to the next
1438          instruction (just after the call to LIB$STOP).  */
1439       Raise_From_Signal_Handler (exception, msg);
1440 #endif
1441     }
1442 #endif
1443
1444   if (exception == 0)
1445     switch (sigargs[1])
1446       {
1447       case SS$_ACCVIO:
1448         if (sigargs[3] == 0)
1449           {
1450             exception = &constraint_error;
1451             msg = "access zero";
1452           }
1453         else
1454           {
1455             exception = &storage_error;
1456             msg = "stack overflow (or erroneous memory access)";
1457           }
1458         __gnat_adjust_context_for_raise (0, (void *)mechargs);
1459         break;
1460
1461       case SS$_STKOVF:
1462         exception = &storage_error;
1463         msg = "stack overflow";
1464         __gnat_adjust_context_for_raise (0, (void *)mechargs);
1465         break;
1466
1467       case SS$_HPARITH:
1468 #ifndef IN_RTS
1469         return SS$_RESIGNAL; /* toplev.c handles for compiler */
1470 #else
1471         exception = &constraint_error;
1472         msg = "arithmetic error";
1473 #ifndef __alpha__
1474         /* No need to adjust pc on Alpha: the pc is already on the instruction
1475            after the trapping one.  */
1476         __gnat_adjust_context_for_raise (0, (void *)mechargs);
1477 #endif
1478 #endif
1479         break;
1480
1481       default:
1482 #ifdef IN_RTS
1483         {
1484           int i;
1485
1486           /* Scan the DEC Ada exception condition table for a match and fetch
1487              the associated GNAT exception pointer.  */
1488           for (i = 0;
1489                dec_ada_cond_except_table [i].cond &&
1490                !LIB$MATCH_COND (&sigargs [1],
1491                                 &dec_ada_cond_except_table [i].cond);
1492                i++);
1493           exception = (struct Exception_Data *)
1494             dec_ada_cond_except_table [i].except;
1495
1496           if (!exception)
1497             {
1498               /* Scan the VMS standard condition table for a match and fetch
1499                  the associated GNAT exception pointer.  */
1500               for (i = 0;
1501                    cond_except_table [i].cond &&
1502                    !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1503                    i++);
1504               exception = (struct Exception_Data *)
1505                 cond_except_table [i].except;
1506
1507               if (!exception)
1508                 /* User programs expect Non_Ada_Error to be raised, reference
1509                    DEC Ada test CXCONDHAN.  */
1510                 exception = &Non_Ada_Error;
1511             }
1512         }
1513 #else
1514         exception = &program_error;
1515 #endif
1516         message [0] = 0;
1517         /* Subtract PC & PSL fields which messes with PUTMSG.  */
1518         sigargs [0] -= 2;
1519         SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1520         sigargs [0] += 2;
1521         msg = message;
1522         break;
1523       }
1524
1525   Raise_From_Signal_Handler (exception, msg);
1526 }
1527
1528 long
1529 __gnat_error_handler (int *sigargs, void *mechargs)
1530 {
1531   return __gnat_handle_vms_condition (sigargs, mechargs);
1532 }
1533
1534 void
1535 __gnat_install_handler (void)
1536 {
1537   long prvhnd ATTRIBUTE_UNUSED;
1538
1539 #if !defined (IN_RTS)
1540   SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1541 #endif
1542
1543   /* On alpha-vms, we avoid the global vector annoyance thanks to frame based
1544      handlers to turn conditions into exceptions since GCC 3.4.  The global
1545      vector is still required for earlier GCC versions.  We're resorting to
1546      the __gnat_error_prehandler assembly function in this case.  */
1547
1548 #if defined (IN_RTS) && defined (__alpha__)
1549   if ((__GNUC__ * 10 + __GNUC_MINOR__) < 34)
1550     {
1551       char * c = (char *) xmalloc (2049);
1552
1553       __gnat_error_prehandler_stack = &c[2048];
1554       SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1555     }
1556 #endif
1557
1558   __gnat_handler_installed = 1;
1559 }
1560
1561 /* __gnat_adjust_context_for_raise for Alpha - see comments along with the
1562    default version later in this file.  */
1563
1564 #if defined (IN_RTS) && defined (__alpha__)
1565
1566 #include <vms/chfctxdef.h>
1567 #include <vms/chfdef.h>
1568
1569 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1570
1571 void
1572 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1573 {
1574   /* Add one to the address of the instruction signaling the condition,
1575      located in the sigargs array.  */
1576
1577   CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1578   CHF$SIGNAL_ARRAY * sigargs
1579     = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1580
1581   int vcount = sigargs->chf$is_sig_args;
1582   int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1583
1584   (*pc_slot) ++;
1585 }
1586
1587 #endif
1588
1589 /* __gnat_adjust_context_for_raise for ia64.  */
1590
1591 #if defined (IN_RTS) && defined (__IA64)
1592
1593 #include <vms/chfctxdef.h>
1594 #include <vms/chfdef.h>
1595
1596 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1597
1598 typedef unsigned long long u64;
1599
1600 void
1601 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1602 {
1603   /* Add one to the address of the instruction signaling the condition,
1604      located in the 64bits sigargs array.  */
1605
1606   CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1607
1608   CHF64$SIGNAL_ARRAY *chfsig64
1609     = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1610
1611   u64 * post_sigarray
1612     = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1613
1614   u64 * ih_pc_loc = post_sigarray - 2;
1615
1616   (*ih_pc_loc) ++;
1617 }
1618
1619 #endif
1620
1621 /* Feature logical name and global variable address pair */
1622 struct feature {char *name; int* gl_addr;};
1623
1624 /* Default values for GNAT features set by environment. */
1625 int __gl_no_malloc_64 = 0;
1626
1627 /* Array feature logical names and global variable addresses */
1628 static struct feature features[] = {
1629   {"GNAT$NO_MALLOC_64", &__gl_no_malloc_64},
1630   {0, 0}
1631 };
1632
1633 void __gnat_set_features ()
1634 {
1635   struct descriptor_s name_desc, result_desc;
1636   int i, status;
1637   unsigned short rlen;
1638
1639 #define MAXEQUIV 10
1640   char buff [MAXEQUIV];
1641
1642   /* Loop through features array and test name for enable/disable */
1643   for (i=0; features [i].name; i++)
1644     {
1645        name_desc.len = strlen (features [i].name);
1646        name_desc.mbz = 0;
1647        name_desc.adr = features [i].name;
1648
1649        result_desc.len = MAXEQUIV - 1;
1650        result_desc.mbz = 0;
1651        result_desc.adr = buff;
1652
1653        status = LIB$GET_LOGICAL (&name_desc, &result_desc, &rlen);
1654
1655        if (((status & 1) == 1) && (rlen < MAXEQUIV))
1656          buff [rlen] = 0;
1657        else
1658          strcpy (buff, "");
1659
1660        if (strcmp (buff, "ENABLE") == 0)
1661           *features [i].gl_addr = 1;
1662        else if (strcmp (buff, "DISABLE") == 0)
1663           *features [i].gl_addr = 0;
1664     }
1665
1666     __gnat_features_set = 1;
1667 }
1668
1669 /*******************/
1670 /* FreeBSD Section */
1671 /*******************/
1672
1673 #elif defined (__FreeBSD__)
1674
1675 #include <signal.h>
1676 #include <sys/ucontext.h>
1677 #include <unistd.h>
1678
1679 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1680
1681 static void
1682 __gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
1683                       ucontext_t *ucontext)
1684 {
1685   struct Exception_Data *exception;
1686   const char *msg;
1687
1688   switch (sig)
1689     {
1690     case SIGFPE:
1691       exception = &constraint_error;
1692       msg = "SIGFPE";
1693       break;
1694
1695     case SIGILL:
1696       exception = &constraint_error;
1697       msg = "SIGILL";
1698       break;
1699
1700     case SIGSEGV:
1701       exception = &storage_error;
1702       msg = "stack overflow or erroneous memory access";
1703       break;
1704
1705     case SIGBUS:
1706       exception = &constraint_error;
1707       msg = "SIGBUS";
1708       break;
1709
1710     default:
1711       exception = &program_error;
1712       msg = "unhandled signal";
1713     }
1714
1715   Raise_From_Signal_Handler (exception, msg);
1716 }
1717
1718 void
1719 __gnat_install_handler ()
1720 {
1721   struct sigaction act;
1722
1723   /* Set up signal handler to map synchronous signals to appropriate
1724      exceptions.  Make sure that the handler isn't interrupted by another
1725      signal that might cause a scheduling event!  */
1726
1727   act.sa_sigaction
1728     = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1729   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1730   (void) sigemptyset (&act.sa_mask);
1731
1732   (void) sigaction (SIGILL,  &act, NULL);
1733   (void) sigaction (SIGFPE,  &act, NULL);
1734   (void) sigaction (SIGSEGV, &act, NULL);
1735   (void) sigaction (SIGBUS,  &act, NULL);
1736
1737   __gnat_handler_installed = 1;
1738 }
1739
1740 /*******************/
1741 /* VxWorks Section */
1742 /*******************/
1743
1744 #elif defined(__vxworks)
1745
1746 #include <signal.h>
1747 #include <taskLib.h>
1748
1749 #ifndef __RTP__
1750 #include <intLib.h>
1751 #include <iv.h>
1752 #endif
1753
1754 #ifdef VTHREADS
1755 #include "private/vThreadsP.h"
1756 #endif
1757
1758 void __gnat_error_handler (int, void *, struct sigcontext *);
1759
1760 #ifndef __RTP__
1761
1762 /* Directly vectored Interrupt routines are not supported when using RTPs.  */
1763
1764 extern int __gnat_inum_to_ivec (int);
1765
1766 /* This is needed by the GNAT run time to handle Vxworks interrupts.  */
1767 int
1768 __gnat_inum_to_ivec (int num)
1769 {
1770   return INUM_TO_IVEC (num);
1771 }
1772 #endif
1773
1774 #if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1775
1776 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1777    on Alpha VxWorks and VxWorks 6.x (including RTPs).  */
1778
1779 extern long getpid (void);
1780
1781 long
1782 getpid (void)
1783 {
1784   return taskIdSelf ();
1785 }
1786 #endif
1787
1788 /* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
1789    handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
1790    doesn't.  */
1791 void
1792 __gnat_clear_exception_count (void)
1793 {
1794 #ifdef VTHREADS
1795   WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1796
1797   currentTask->vThreads.excCnt = 0;
1798 #endif
1799 }
1800
1801 /* Handle different SIGnal to exception mappings in different VxWorks
1802    versions.   */
1803 static void
1804 __gnat_map_signal (int sig)
1805 {
1806   struct Exception_Data *exception;
1807   const char *msg;
1808
1809   switch (sig)
1810     {
1811     case SIGFPE:
1812       exception = &constraint_error;
1813       msg = "SIGFPE";
1814       break;
1815 #ifdef VTHREADS
1816     case SIGILL:
1817       exception = &constraint_error;
1818       msg = "Floating point exception or SIGILL";
1819       break;
1820     case SIGSEGV:
1821       exception = &storage_error;
1822       msg = "SIGSEGV";
1823       break;
1824     case SIGBUS:
1825       exception = &storage_error;
1826       msg = "SIGBUS: possible stack overflow";
1827       break;
1828 #elif (_WRS_VXWORKS_MAJOR == 6)
1829     case SIGILL:
1830       exception = &constraint_error;
1831       msg = "SIGILL";
1832       break;
1833 #ifdef __RTP__
1834     /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
1835        since stack checking uses the probing mechanism.  */
1836     case SIGSEGV:
1837       exception = &storage_error;
1838       msg = "SIGSEGV: possible stack overflow";
1839       break;
1840     case SIGBUS:
1841       exception = &program_error;
1842       msg = "SIGBUS";
1843       break;
1844 #else
1845       /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
1846     case SIGSEGV:
1847       exception = &storage_error;
1848       msg = "SIGSEGV";
1849       break;
1850     case SIGBUS:
1851       exception = &storage_error;
1852       msg = "SIGBUS: possible stack overflow";
1853       break;
1854 #endif
1855 #else
1856     /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
1857        since stack checking uses the stack limit mechanism.  */
1858     case SIGILL:
1859       exception = &storage_error;
1860       msg = "SIGILL: possible stack overflow";
1861       break;
1862     case SIGSEGV:
1863       exception = &storage_error;
1864       msg = "SIGSEGV";
1865       break;
1866     case SIGBUS:
1867       exception = &program_error;
1868       msg = "SIGBUS";
1869       break;
1870 #endif
1871     default:
1872       exception = &program_error;
1873       msg = "unhandled signal";
1874     }
1875
1876   __gnat_clear_exception_count ();
1877   Raise_From_Signal_Handler (exception, msg);
1878 }
1879
1880 /* Tasking and Non-tasking signal handler.  Map SIGnal to Ada exception
1881    propagation after the required low level adjustments.  */
1882
1883 void
1884 __gnat_error_handler (int sig, void * si ATTRIBUTE_UNUSED,
1885                       struct sigcontext * sc)
1886 {
1887   sigset_t mask;
1888
1889   /* VxWorks will always mask out the signal during the signal handler and
1890      will reenable it on a longjmp.  GNAT does not generate a longjmp to
1891      return from a signal handler so the signal will still be masked unless
1892      we unmask it.  */
1893   sigprocmask (SIG_SETMASK, NULL, &mask);
1894   sigdelset (&mask, sig);
1895   sigprocmask (SIG_SETMASK, &mask, NULL);
1896
1897   __gnat_map_signal (sig);
1898 }
1899
1900 void
1901 __gnat_install_handler (void)
1902 {
1903   struct sigaction act;
1904
1905   /* Setup signal handler to map synchronous signals to appropriate
1906      exceptions.  Make sure that the handler isn't interrupted by another
1907      signal that might cause a scheduling event!  */
1908
1909   act.sa_handler = __gnat_error_handler;
1910   act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1911   sigemptyset (&act.sa_mask);
1912
1913   /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1914      applies to vectored hardware interrupts, not signals.  */
1915   sigaction (SIGFPE,  &act, NULL);
1916   sigaction (SIGILL,  &act, NULL);
1917   sigaction (SIGSEGV, &act, NULL);
1918   sigaction (SIGBUS,  &act, NULL);
1919
1920   __gnat_handler_installed = 1;
1921 }
1922
1923 #define HAVE_GNAT_INIT_FLOAT
1924
1925 void
1926 __gnat_init_float (void)
1927 {
1928   /* Disable overflow/underflow exceptions on the PPC processor, needed
1929      to get correct Ada semantics.  Note that for AE653 vThreads, the HW
1930      overflow settings are an OS configuration issue.  The instructions
1931      below have no effect.  */
1932 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1933   asm ("mtfsb0 25");
1934   asm ("mtfsb0 26");
1935 #endif
1936
1937 #if (defined (__i386__) || defined (i386)) && !defined (VTHREADS)
1938   /* This is used to properly initialize the FPU on an x86 for each
1939      process thread.  */
1940   asm ("finit");
1941 #endif
1942
1943   /* Similarly for SPARC64.  Achieved by masking bits in the Trap Enable Mask
1944      field of the Floating-point Status Register (see the SPARC Architecture
1945      Manual Version 9, p 48).  */
1946 #if defined (sparc64)
1947
1948 #define FSR_TEM_NVM (1 << 27)  /* Invalid operand  */
1949 #define FSR_TEM_OFM (1 << 26)  /* Overflow  */
1950 #define FSR_TEM_UFM (1 << 25)  /* Underflow  */
1951 #define FSR_TEM_DZM (1 << 24)  /* Division by Zero  */
1952 #define FSR_TEM_NXM (1 << 23)  /* Inexact result  */
1953   {
1954     unsigned int fsr;
1955
1956     __asm__("st %%fsr, %0" : "=m" (fsr));
1957     fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1958     __asm__("ld %0, %%fsr" : : "m" (fsr));
1959   }
1960 #endif
1961 }
1962
1963 /* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
1964    (if not null) when a new task is created.  It is initialized by
1965    System.Stack_Checking.Operations.Initialize_Stack_Limit.
1966    The use of a hook avoids to drag stack checking subprograms if stack
1967    checking is not used.  */
1968 void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
1969
1970 /******************/
1971 /* NetBSD Section */
1972 /******************/
1973
1974 #elif defined(__NetBSD__)
1975
1976 #include <signal.h>
1977 #include <unistd.h>
1978
1979 static void
1980 __gnat_error_handler (int sig)
1981 {
1982   struct Exception_Data *exception;
1983   const char *msg;
1984
1985   switch(sig)
1986   {
1987     case SIGFPE:
1988       exception = &constraint_error;
1989       msg = "SIGFPE";
1990       break;
1991     case SIGILL:
1992       exception = &constraint_error;
1993       msg = "SIGILL";
1994       break;
1995     case SIGSEGV:
1996       exception = &storage_error;
1997       msg = "stack overflow or erroneous memory access";
1998       break;
1999     case SIGBUS:
2000       exception = &constraint_error;
2001       msg = "SIGBUS";
2002       break;
2003     default:
2004       exception = &program_error;
2005       msg = "unhandled signal";
2006     }
2007
2008     Raise_From_Signal_Handler(exception, msg);
2009 }
2010
2011 void
2012 __gnat_install_handler(void)
2013 {
2014   struct sigaction act;
2015
2016   act.sa_handler = __gnat_error_handler;
2017   act.sa_flags = SA_NODEFER | SA_RESTART;
2018   sigemptyset (&act.sa_mask);
2019
2020   /* Do not install handlers if interrupt state is "System".  */
2021   if (__gnat_get_interrupt_state (SIGFPE) != 's')
2022     sigaction (SIGFPE,  &act, NULL);
2023   if (__gnat_get_interrupt_state (SIGILL) != 's')
2024     sigaction (SIGILL,  &act, NULL);
2025   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2026     sigaction (SIGSEGV, &act, NULL);
2027   if (__gnat_get_interrupt_state (SIGBUS) != 's')
2028     sigaction (SIGBUS,  &act, NULL);
2029
2030   __gnat_handler_installed = 1;
2031 }
2032
2033 /*******************/
2034 /* OpenBSD Section */
2035 /*******************/
2036
2037 #elif defined(__OpenBSD__)
2038
2039 #include <signal.h>
2040 #include <unistd.h>
2041
2042 static void
2043 __gnat_error_handler (int sig)
2044 {
2045   struct Exception_Data *exception;
2046   const char *msg;
2047
2048   switch(sig)
2049   {
2050     case SIGFPE:
2051       exception = &constraint_error;
2052       msg = "SIGFPE";
2053       break;
2054     case SIGILL:
2055       exception = &constraint_error;
2056       msg = "SIGILL";
2057       break;
2058     case SIGSEGV:
2059       exception = &storage_error;
2060       msg = "stack overflow or erroneous memory access";
2061       break;
2062     case SIGBUS:
2063       exception = &constraint_error;
2064       msg = "SIGBUS";
2065       break;
2066     default:
2067       exception = &program_error;
2068       msg = "unhandled signal";
2069     }
2070
2071     Raise_From_Signal_Handler(exception, msg);
2072 }
2073
2074 void
2075 __gnat_install_handler(void)
2076 {
2077   struct sigaction act;
2078
2079   act.sa_handler = __gnat_error_handler;
2080   act.sa_flags = SA_NODEFER | SA_RESTART;
2081   sigemptyset (&act.sa_mask);
2082
2083   /* Do not install handlers if interrupt state is "System" */
2084   if (__gnat_get_interrupt_state (SIGFPE) != 's')
2085     sigaction (SIGFPE,  &act, NULL);
2086   if (__gnat_get_interrupt_state (SIGILL) != 's')
2087     sigaction (SIGILL,  &act, NULL);
2088   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2089     sigaction (SIGSEGV, &act, NULL);
2090   if (__gnat_get_interrupt_state (SIGBUS) != 's')
2091     sigaction (SIGBUS,  &act, NULL);
2092
2093   __gnat_handler_installed = 1;
2094 }
2095
2096 /******************/
2097 /* Darwin Section */
2098 /******************/
2099
2100 #elif defined(__APPLE__)
2101
2102 #include <signal.h>
2103 #include <mach/mach_vm.h>
2104 #include <mach/vm_statistics.h>
2105
2106 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
2107 char __gnat_alternate_stack[32 * 1024]; /* 1 * MINSIGSTKSZ */
2108
2109 static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
2110
2111 /* Defined in xnu unix_signal.c  */
2112 #define UC_RESET_ALT_STACK      0x80000000
2113 extern int sigreturn (void *uc, int flavour);
2114
2115 /* Return true if ADDR is within a stack guard area.  */
2116 static int
2117 __gnat_is_stack_guard (mach_vm_address_t addr)
2118 {
2119   kern_return_t kret;
2120   vm_region_submap_info_data_64_t info;
2121   mach_vm_address_t start;
2122   mach_vm_size_t size;
2123   natural_t depth;
2124   mach_msg_type_number_t count;
2125
2126   count = VM_REGION_SUBMAP_INFO_COUNT_64;
2127   start = addr;
2128   size = -1;
2129   depth = 9999;
2130   kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
2131                                  (vm_region_recurse_info_t) &info, &count);
2132   if (kret == KERN_SUCCESS
2133       && addr >= start && addr < (start + size)
2134       && info.protection == VM_PROT_NONE
2135       && info.user_tag == VM_MEMORY_STACK)
2136     return 1;
2137   return 0;
2138 }
2139
2140 static void
2141 __gnat_error_handler (int sig, siginfo_t * si, void * uc)
2142 {
2143   struct Exception_Data *exception;
2144   const char *msg;
2145
2146   switch (sig)
2147     {
2148     case SIGSEGV:
2149     case SIGBUS:
2150       if (__gnat_is_stack_guard ((unsigned long)si->si_addr))
2151         {
2152           exception = &storage_error;
2153           msg = "stack overflow";
2154         }
2155       else
2156         {
2157           exception = &constraint_error;
2158           msg = "erroneous memory access";
2159         }
2160       /* Reset the use of alt stack, so that the alt stack will be used
2161          for the next signal delivery.  */
2162       sigreturn (NULL, UC_RESET_ALT_STACK);
2163       break;
2164
2165     case SIGFPE:
2166       exception = &constraint_error;
2167       msg = "SIGFPE";
2168       break;
2169
2170     default:
2171       exception = &program_error;
2172       msg = "unhandled signal";
2173     }
2174
2175   Raise_From_Signal_Handler (exception, msg);
2176 }
2177
2178 void
2179 __gnat_install_handler (void)
2180 {
2181   struct sigaction act;
2182
2183   /* Set up signal handler to map synchronous signals to appropriate
2184      exceptions.  Make sure that the handler isn't interrupted by another
2185      signal that might cause a scheduling event!  Also setup an alternate
2186      stack region for the handler execution so that stack overflows can be
2187      handled properly, avoiding a SEGV generation from stack usage by the
2188      handler itself (and it is required by Darwin).  */
2189
2190   stack_t stack;
2191   stack.ss_sp = __gnat_alternate_stack;
2192   stack.ss_size = sizeof (__gnat_alternate_stack);
2193   stack.ss_flags = 0;
2194   sigaltstack (&stack, NULL);
2195
2196   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2197   act.sa_sigaction = __gnat_error_handler;
2198   sigemptyset (&act.sa_mask);
2199
2200   /* Do not install handlers if interrupt state is "System".  */
2201   if (__gnat_get_interrupt_state (SIGABRT) != 's')
2202     sigaction (SIGABRT, &act, NULL);
2203   if (__gnat_get_interrupt_state (SIGFPE) != 's')
2204     sigaction (SIGFPE,  &act, NULL);
2205   if (__gnat_get_interrupt_state (SIGILL) != 's')
2206     sigaction (SIGILL,  &act, NULL);
2207
2208   act.sa_flags |= SA_ONSTACK;
2209   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2210     sigaction (SIGSEGV, &act, NULL);
2211   if (__gnat_get_interrupt_state (SIGBUS) != 's')
2212     sigaction (SIGBUS,  &act, NULL);
2213
2214   __gnat_handler_installed = 1;
2215 }
2216
2217 #else
2218
2219 /* For all other versions of GNAT, the handler does nothing.  */
2220
2221 /*******************/
2222 /* Default Section */
2223 /*******************/
2224
2225 void
2226 __gnat_install_handler (void)
2227 {
2228   __gnat_handler_installed = 1;
2229 }
2230
2231 #endif
2232
2233 /*********************/
2234 /* __gnat_init_float */
2235 /*********************/
2236
2237 /* This routine is called as each process thread is created, for possible
2238    initialization of the FP processor.  This version is used under INTERIX,
2239    WIN32 and could be used under OS/2.  */
2240
2241 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
2242   || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
2243   || defined (__OpenBSD__)
2244
2245 #define HAVE_GNAT_INIT_FLOAT
2246
2247 void
2248 __gnat_init_float (void)
2249 {
2250 #if defined (__i386__) || defined (i386) || defined (__x86_64)
2251
2252   /* This is used to properly initialize the FPU on an x86 for each
2253      process thread.  */
2254
2255   asm ("finit");
2256
2257 #endif  /* Defined __i386__ */
2258 }
2259 #endif
2260
2261 #ifndef HAVE_GNAT_INIT_FLOAT
2262
2263 /* All targets without a specific __gnat_init_float will use an empty one.  */
2264 void
2265 __gnat_init_float (void)
2266 {
2267 }
2268 #endif
2269
2270 /***********************************/
2271 /* __gnat_adjust_context_for_raise */
2272 /***********************************/
2273
2274 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2275
2276 /* All targets without a specific version will use an empty one.  */
2277
2278 /* Given UCONTEXT a pointer to a context structure received by a signal
2279    handler for SIGNO, perform the necessary adjustments to let the handler
2280    raise an exception.  Calls to this routine are not conditioned by the
2281    propagation scheme in use.  */
2282
2283 void
2284 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2285                                  void *ucontext ATTRIBUTE_UNUSED)
2286 {
2287   /* We used to compensate here for the raised from call vs raised from signal
2288      exception discrepancy with the GCC ZCX scheme, but this now can be dealt
2289      with generically in the unwinder (see GCC PR other/26208).  Only the VMS
2290      ports still do the compensation described in the few lines below.
2291
2292      *** Call vs signal exception discrepancy with GCC ZCX scheme ***
2293
2294      The GCC unwinder expects to be dealing with call return addresses, since
2295      this is the "nominal" case of what we retrieve while unwinding a regular
2296      call chain.
2297
2298      To evaluate if a handler applies at some point identified by a return
2299      address, the propagation engine needs to determine what region the
2300      corresponding call instruction pertains to.  Because the return address
2301      may not be attached to the same region as the call, the unwinder always
2302      subtracts "some" amount from a return address to search the region
2303      tables, amount chosen to ensure that the resulting address is inside the
2304      call instruction.
2305
2306      When we raise an exception from a signal handler, e.g. to transform a
2307      SIGSEGV into Storage_Error, things need to appear as if the signal
2308      handler had been "called" by the instruction which triggered the signal,
2309      so that exception handlers that apply there are considered.  What the
2310      unwinder will retrieve as the return address from the signal handler is
2311      what it will find as the faulting instruction address in the signal
2312      context pushed by the kernel.  Leaving this address untouched looses, if
2313      the triggering instruction happens to be the very first of a region, as
2314      the later adjustments performed by the unwinder would yield an address
2315      outside that region.  We need to compensate for the unwinder adjustments
2316      at some point, and this is what this routine is expected to do.
2317
2318      signo is passed because on some targets for some signals the PC in
2319      context points to the instruction after the faulting one, in which case
2320      the unwinder adjustment is still desired.  */
2321 }
2322
2323 #endif