1 /****************************************************************************
2  *                                                                          *
3  *                         GNAT COMPILER COMPONENTS                         *
4  *                                                                          *
5  *                                 I N I T                                  *
6  *                                                                          *
7  *                          C Implementation File                           *
8  *                                                                          *
9  *          Copyright (C) 1992-2019, 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 s-init.ads, s-init.adb and the
42    s-init-*.adb variants. All these files implement the required functionality
43    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 #include "version.h" /* for _WRS_VXWORKS_MAJOR */
50 #endif
51 
52 #ifdef __ANDROID__
53 #undef __linux__
54 #endif
55 
56 #ifdef IN_RTS
57 
58 #ifdef STANDALONE
59 #include "runtime.h"
60 #else
61 #include "tconfig.h"
62 #include "tsystem.h"
63 #endif
64 
65 #include <sys/stat.h>
66 
67 /* We don't have libiberty, so use malloc.  */
68 #define xmalloc(S) malloc (S)
69 #else
70 #include "config.h"
71 #include "system.h"
72 #endif
73 
74 #include "adaint.h"
75 #include "raise.h"
76 
77 #ifdef __cplusplus
78 extern "C" {
79 #endif
80 
81 extern void __gnat_raise_program_error (const char *, int);
82 
83 /* Addresses of exception data blocks for predefined exceptions.  Tasking_Error
84    is not used in this unit, and the abort signal is only used on IRIX.
85    ??? Revisit this part since IRIX is no longer supported.  */
86 extern struct Exception_Data constraint_error;
87 extern struct Exception_Data numeric_error;
88 extern struct Exception_Data program_error;
89 extern struct Exception_Data storage_error;
90 
91 /* For the Cert run time we use the regular raise exception routine because
92    Raise_From_Signal_Handler is not available.  */
93 #ifdef CERT
94 #define Raise_From_Signal_Handler \
95                       __gnat_raise_exception
96 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
97 #else
98 #define Raise_From_Signal_Handler \
99                       ada__exceptions__raise_from_signal_handler
100 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
101 #endif
102 
103 /* Global values computed by the binder.  Note that these variables are
104    declared here, not in the binder file, to avoid having unresolved
105    references in the shared libgnat.  */
106 int   __gl_main_priority                 = -1;
107 int   __gl_main_cpu                      = -1;
108 int   __gl_time_slice_val                = -1;
109 char  __gl_wc_encoding                   = 'n';
110 char  __gl_locking_policy                = ' ';
111 char  __gl_queuing_policy                = ' ';
112 char  __gl_task_dispatching_policy       = ' ';
113 char *__gl_priority_specific_dispatching = 0;
114 int   __gl_num_specific_dispatching      = 0;
115 char *__gl_interrupt_states              = 0;
116 int   __gl_num_interrupt_states          = 0;
117 int   __gl_unreserve_all_interrupts      = 0;
118 int   __gl_exception_tracebacks          = 0;
119 int   __gl_exception_tracebacks_symbolic = 0;
120 int   __gl_detect_blocking               = 0;
121 int   __gl_default_stack_size            = -1;
122 int   __gl_leap_seconds_support          = 0;
123 int   __gl_canonical_streams             = 0;
124 char *__gl_bind_env_addr                 = NULL;
125 
126 /* This value is not used anymore, but kept for bootstrapping purpose.  */
127 int   __gl_zero_cost_exceptions          = 0;
128 
129 /* Indication of whether synchronous signal handler has already been
130    installed by a previous call to adainit.  */
131 int  __gnat_handler_installed      = 0;
132 
133 #ifndef IN_RTS
134 int __gnat_inside_elab_final_code = 0;
135 /* ??? This variable is obsolete since 2001-08-29 but is kept to allow
136    bootstrap from old GNAT versions (< 3.15).  */
137 #endif
138 
139 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
140    is defined.  If this is not set then a void implementation will be defined
141    at the end of this unit.  */
142 #undef HAVE_GNAT_INIT_FLOAT
143 
144 /******************************/
145 /* __gnat_get_interrupt_state */
146 /******************************/
147 
148 char __gnat_get_interrupt_state (int);
149 
150 /* This routine is called from the runtime as needed to determine the state
151    of an interrupt, as set by an Interrupt_State pragma appearing anywhere
152    in the current partition.  The input argument is the interrupt number,
153    and the result is one of the following:
154 
155        'n'   this interrupt not set by any Interrupt_State pragma
156        'u'   Interrupt_State pragma set state to User
157        'r'   Interrupt_State pragma set state to Runtime
158        's'   Interrupt_State pragma set state to System  */
159 
160 char
__gnat_get_interrupt_state(int intrup)161 __gnat_get_interrupt_state (int intrup)
162 {
163   if (intrup >= __gl_num_interrupt_states)
164     return 'n';
165   else
166     return __gl_interrupt_states [intrup];
167 }
168 
169 /***********************************/
170 /* __gnat_get_specific_dispatching */
171 /***********************************/
172 
173 char __gnat_get_specific_dispatching (int);
174 
175 /* This routine is called from the runtime as needed to determine the
176    priority specific dispatching policy, as set by a
177    Priority_Specific_Dispatching pragma appearing anywhere in the current
178    partition.  The input argument is the priority number, and the result
179    is the upper case first character of the policy name, e.g. 'F' for
180    FIFO_Within_Priorities. A space ' ' is returned if no
181    Priority_Specific_Dispatching pragma is used in the partition.  */
182 
183 char
__gnat_get_specific_dispatching(int priority)184 __gnat_get_specific_dispatching (int priority)
185 {
186   if (__gl_num_specific_dispatching == 0)
187     return ' ';
188   else if (priority >= __gl_num_specific_dispatching)
189     return 'F';
190   else
191     return __gl_priority_specific_dispatching [priority];
192 }
193 
194 #ifndef IN_RTS
195 
196 /**********************/
197 /* __gnat_set_globals */
198 /**********************/
199 
200 /* This routine is kept for bootstrapping purposes, since the binder generated
201    file now sets the __gl_* variables directly.  */
202 
203 void
__gnat_set_globals(void)204 __gnat_set_globals (void)
205 {
206 }
207 
208 #endif
209 
210 /***************/
211 /* AIX Section */
212 /***************/
213 
214 #if defined (_AIX)
215 
216 #include <signal.h>
217 #include <sys/time.h>
218 
219 /* Some versions of AIX don't define SA_NODEFER.  */
220 
221 #ifndef SA_NODEFER
222 #define SA_NODEFER 0
223 #endif /* SA_NODEFER */
224 
225 /* Versions of AIX before 4.3 don't have nanosleep but provide
226    nsleep instead.  */
227 
228 #ifndef _AIXVERSION_430
229 
230 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
231 
232 int
nanosleep(struct timestruc_t * Rqtp,struct timestruc_t * Rmtp)233 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
234 {
235   return nsleep (Rqtp, Rmtp);
236 }
237 
238 #endif /* _AIXVERSION_430 */
239 
240 static void
__gnat_error_handler(int sig,siginfo_t * si ATTRIBUTE_UNUSED,void * ucontext ATTRIBUTE_UNUSED)241 __gnat_error_handler (int sig,
242 		      siginfo_t *si ATTRIBUTE_UNUSED,
243 		      void *ucontext ATTRIBUTE_UNUSED)
244 {
245   struct Exception_Data *exception;
246   const char *msg;
247 
248   switch (sig)
249     {
250     case SIGSEGV:
251       /* FIXME: we need to detect the case of a *real* SIGSEGV.  */
252       exception = &storage_error;
253       msg = "stack overflow or erroneous memory access";
254       break;
255 
256     case SIGBUS:
257       exception = &constraint_error;
258       msg = "SIGBUS";
259       break;
260 
261     case SIGFPE:
262       exception = &constraint_error;
263       msg = "SIGFPE";
264       break;
265 
266     default:
267       exception = &program_error;
268       msg = "unhandled signal";
269     }
270 
271   Raise_From_Signal_Handler (exception, msg);
272 }
273 
274 void
__gnat_install_handler(void)275 __gnat_install_handler (void)
276 {
277   struct sigaction act;
278 
279   /* Set up signal handler to map synchronous signals to appropriate
280      exceptions.  Make sure that the handler isn't interrupted by another
281      signal that might cause a scheduling event!  */
282 
283   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
284   act.sa_sigaction = __gnat_error_handler;
285   sigemptyset (&act.sa_mask);
286 
287   /* Do not install handlers if interrupt state is "System".  */
288   if (__gnat_get_interrupt_state (SIGABRT) != 's')
289     sigaction (SIGABRT, &act, NULL);
290   if (__gnat_get_interrupt_state (SIGFPE) != 's')
291     sigaction (SIGFPE,  &act, NULL);
292   if (__gnat_get_interrupt_state (SIGILL) != 's')
293     sigaction (SIGILL,  &act, NULL);
294   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
295     sigaction (SIGSEGV, &act, NULL);
296   if (__gnat_get_interrupt_state (SIGBUS) != 's')
297     sigaction (SIGBUS,  &act, NULL);
298 
299   __gnat_handler_installed = 1;
300 }
301 
302 /*****************/
303 /* HP-UX section */
304 /*****************/
305 
306 #elif defined (__hpux__)
307 
308 #include <signal.h>
309 #include <sys/ucontext.h>
310 
311 #if defined (IN_RTS) && defined (__ia64__)
312 
313 #include <sys/uc_access.h>
314 
315 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
316 
317 void
__gnat_adjust_context_for_raise(int signo ATTRIBUTE_UNUSED,void * ucontext)318 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
319 {
320   ucontext_t *uc = (ucontext_t *) ucontext;
321   uint64_t ip;
322 
323   /* Adjust on itanium, as GetIPInfo is not supported.  */
324   __uc_get_ip (uc, &ip);
325   __uc_set_ip (uc, ip + 1);
326 }
327 #endif /* IN_RTS && __ia64__ */
328 
329 /* Tasking and Non-tasking signal handler.  Map SIGnal to Ada exception
330    propagation after the required low level adjustments.  */
331 
332 static void
__gnat_error_handler(int sig,siginfo_t * si ATTRIBUTE_UNUSED,void * ucontext)333 __gnat_error_handler (int sig, siginfo_t *si ATTRIBUTE_UNUSED, void *ucontext)
334 {
335   struct Exception_Data *exception;
336   const char *msg;
337 
338   __gnat_adjust_context_for_raise (sig, ucontext);
339 
340   switch (sig)
341     {
342     case SIGSEGV:
343       /* FIXME: we need to detect the case of a *real* SIGSEGV.  */
344       exception = &storage_error;
345       msg = "stack overflow or erroneous memory access";
346       break;
347 
348     case SIGBUS:
349       exception = &constraint_error;
350       msg = "SIGBUS";
351       break;
352 
353     case SIGFPE:
354       exception = &constraint_error;
355       msg = "SIGFPE";
356       break;
357 
358     default:
359       exception = &program_error;
360       msg = "unhandled signal";
361     }
362 
363   Raise_From_Signal_Handler (exception, msg);
364 }
365 
366 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
367 #if defined (__hppa__)
368 char __gnat_alternate_stack[16 * 1024]; /* 2 * SIGSTKSZ */
369 #else
370 char __gnat_alternate_stack[128 * 1024]; /* MINSIGSTKSZ */
371 #endif
372 
373 void
__gnat_install_handler(void)374 __gnat_install_handler (void)
375 {
376   struct sigaction act;
377 
378   /* Set up signal handler to map synchronous signals to appropriate
379      exceptions.  Make sure that the handler isn't interrupted by another
380      signal that might cause a scheduling event!  Also setup an alternate
381      stack region for the handler execution so that stack overflows can be
382      handled properly, avoiding a SEGV generation from stack usage by the
383      handler itself.  */
384 
385   stack_t stack;
386   stack.ss_sp = __gnat_alternate_stack;
387   stack.ss_size = sizeof (__gnat_alternate_stack);
388   stack.ss_flags = 0;
389   sigaltstack (&stack, NULL);
390 
391   act.sa_sigaction = __gnat_error_handler;
392   act.sa_flags = SA_NODEFER | SA_RESTART | 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 (SIGBUS) != 's')
403     sigaction (SIGBUS,  &act, NULL);
404   act.sa_flags |= SA_ONSTACK;
405   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
406     sigaction (SIGSEGV, &act, NULL);
407 
408   __gnat_handler_installed = 1;
409 }
410 
411 /*********************/
412 /* GNU/Linux Section */
413 /*********************/
414 
415 #elif defined (__linux__)
416 
417 #include <signal.h>
418 
419 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
420 #include <sys/ucontext.h>
421 
422 /* GNU/Linux, which uses glibc, does not define NULL in included
423    header files.  */
424 
425 #if !defined (NULL)
426 #define NULL ((void *) 0)
427 #endif
428 
429 #if defined (MaRTE)
430 
431 /* MaRTE OS provides its own version of sigaction, sigfillset, and
432    sigemptyset (overriding these symbol names).  We want to make sure that
433    the versions provided by the underlying C library are used here (these
434    versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
435    and fake_linux_sigemptyset, respectively).  The MaRTE library will not
436    always be present (it will not be linked if no tasking constructs are
437    used), so we use the weak symbol mechanism to point always to the symbols
438    defined within the C library.  */
439 
440 #pragma weak linux_sigaction
linux_sigaction(int signum,const struct sigaction * act,struct sigaction * oldact)441 int linux_sigaction (int signum, const struct sigaction *act,
442 		     struct sigaction *oldact)
443 {
444   return sigaction (signum, act, oldact);
445 }
446 #define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
447 
448 #pragma weak fake_linux_sigfillset
fake_linux_sigfillset(sigset_t * set)449 void fake_linux_sigfillset (sigset_t *set)
450 {
451   sigfillset (set);
452 }
453 #define sigfillset(set) fake_linux_sigfillset (set)
454 
455 #pragma weak fake_linux_sigemptyset
fake_linux_sigemptyset(sigset_t * set)456 void fake_linux_sigemptyset (sigset_t *set)
457 {
458   sigemptyset (set);
459 }
460 #define sigemptyset(set) fake_linux_sigemptyset (set)
461 
462 #endif
463 
464 #if defined (__i386__) || defined (__x86_64__) || defined (__ia64__) \
465     || defined (__ARMEL__)
466 
467 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
468 
469 void
__gnat_adjust_context_for_raise(int signo ATTRIBUTE_UNUSED,void * ucontext)470 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
471 {
472 #ifndef STANDALONE
473   mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
474 
475   /* On the i386 and x86-64 architectures, stack checking is performed by
476      means of probes with moving stack pointer, that is to say the probed
477      address is always the value of the stack pointer.  Upon hitting the
478      guard page, the stack pointer therefore points to an inaccessible
479      address and an alternate signal stack is needed to run the handler.
480      But there is an additional twist: on these architectures, the EH
481      return code writes the address of the handler at the target CFA's
482      value on the stack before doing the jump.  As a consequence, if
483      there is an active handler in the frame whose stack has overflowed,
484      the stack pointer must nevertheless point to an accessible address
485      by the time the EH return is executed.
486 
487      We therefore adjust the saved value of the stack pointer by the size
488      of one page + a small dope of 4 words, in order to make sure that it
489      points to an accessible address in case it's used as the target CFA.
490      The stack checking code guarantees that this address is unused by the
491      time this happens.  */
492 
493 #if defined (__i386__)
494   unsigned long *pc = (unsigned long *)mcontext->gregs[REG_EIP];
495   /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode.  */
496   if (signo == SIGSEGV && pc && *pc == 0x00240c83)
497     mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
498 #elif defined (__x86_64__)
499   unsigned long long *pc = (unsigned long long *)mcontext->gregs[REG_RIP];
500   if (signo == SIGSEGV && pc
501       /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode.  */
502       && ((*pc & 0xffffffffffLL) == 0x00240c8348LL
503 	  /* The pattern may also be "orl $0x0,(%esp)" for a probe in
504 	     x32 mode.  */
505 	  || (*pc & 0xffffffffLL) == 0x00240c83LL))
506     mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
507 #elif defined (__ia64__)
508   /* ??? The IA-64 unwinder doesn't compensate for signals.  */
509   mcontext->sc_ip++;
510 #elif defined (__ARMEL__)
511   /* ARM Bump has to be an even number because of odd/even architecture.  */
512   mcontext->arm_pc+=2;
513 #ifdef __thumb2__
514 #define CPSR_THUMB_BIT 5
515   /* For thumb, the return address much have the low order bit set, otherwise
516      the unwinder will reset to "arm" mode upon return.  As long as the
517      compilation unit containing the landing pad is compiled with the same
518      mode (arm vs thumb) as the signaling compilation unit, this works.  */
519   if (mcontext->arm_cpsr & (1<<CPSR_THUMB_BIT))
520     mcontext->arm_pc+=1;
521 #endif
522 #endif
523 #endif
524 }
525 
526 #endif
527 
528 static void
__gnat_error_handler(int sig,siginfo_t * si ATTRIBUTE_UNUSED,void * ucontext)529 __gnat_error_handler (int sig, siginfo_t *si ATTRIBUTE_UNUSED, void *ucontext)
530 {
531   struct Exception_Data *exception;
532   const char *msg;
533 
534   /* Adjusting is required for every fault context, so adjust for this one
535      now, before we possibly trigger a recursive fault below.  */
536   __gnat_adjust_context_for_raise (sig, ucontext);
537 
538   switch (sig)
539     {
540     case SIGSEGV:
541       /* Here we would like a discrimination test to see whether the page
542 	 before the faulting address is accessible.  Unfortunately, Linux
543 	 seems to have no way of giving us the faulting address.
544 
545 	 In old versions of init.c, we had a test of the page before the
546 	 stack pointer:
547 
548 	   ((volatile char *)
549 	    ((long) si->esp_at_signal & - getpagesize ()))[getpagesize ()];
550 
551 	 but that's wrong since it tests the stack pointer location and the
552 	 stack probing code may not move it until all probes succeed.
553 
554 	 For now we simply do not attempt any discrimination at all. Note
555 	 that this is quite acceptable, since a "real" SIGSEGV can only
556 	 occur as the result of an erroneous program.  */
557       exception = &storage_error;
558       msg = "stack overflow or erroneous memory access";
559       break;
560 
561     case SIGBUS:
562       exception = &storage_error;
563       msg = "SIGBUS: possible stack overflow";
564       break;
565 
566     case SIGFPE:
567       exception = &constraint_error;
568       msg = "SIGFPE";
569       break;
570 
571     default:
572       exception = &program_error;
573       msg = "unhandled signal";
574     }
575 
576   Raise_From_Signal_Handler (exception, msg);
577 }
578 
579 #ifndef __ia64__
580 #define HAVE_GNAT_ALTERNATE_STACK 1
581 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.
582    It must be larger than MINSIGSTKSZ and hopefully near 2 * SIGSTKSZ.  */
583 # if 16 * 1024 < MINSIGSTKSZ
584 #  error "__gnat_alternate_stack too small"
585 # endif
586 char __gnat_alternate_stack[16 * 1024];
587 #endif
588 
589 #ifdef __XENO__
590 #include <sys/mman.h>
591 #include <native/task.h>
592 
593 RT_TASK main_task;
594 #endif
595 
596 void
__gnat_install_handler(void)597 __gnat_install_handler (void)
598 {
599   struct sigaction act;
600 
601 #ifdef __XENO__
602   int prio;
603 
604   if (__gl_main_priority == -1)
605     prio = 49;
606   else
607     prio = __gl_main_priority;
608 
609   /* Avoid memory swapping for this program */
610 
611   mlockall (MCL_CURRENT|MCL_FUTURE);
612 
613   /* Turn the current Linux task into a native Xenomai task */
614 
615   rt_task_shadow (&main_task, "environment_task", prio, T_FPU);
616 #endif
617 
618   /* Set up signal handler to map synchronous signals to appropriate
619      exceptions.  Make sure that the handler isn't interrupted by another
620      signal that might cause a scheduling event!  Also setup an alternate
621      stack region for the handler execution so that stack overflows can be
622      handled properly, avoiding a SEGV generation from stack usage by the
623      handler itself.  */
624 
625   act.sa_sigaction = __gnat_error_handler;
626   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
627   sigemptyset (&act.sa_mask);
628 
629   /* Do not install handlers if interrupt state is "System".  */
630   if (__gnat_get_interrupt_state (SIGABRT) != 's')
631     sigaction (SIGABRT, &act, NULL);
632   if (__gnat_get_interrupt_state (SIGFPE) != 's')
633     sigaction (SIGFPE,  &act, NULL);
634   if (__gnat_get_interrupt_state (SIGILL) != 's')
635     sigaction (SIGILL,  &act, NULL);
636   if (__gnat_get_interrupt_state (SIGBUS) != 's')
637     sigaction (SIGBUS,  &act, NULL);
638   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
639     {
640 #ifdef HAVE_GNAT_ALTERNATE_STACK
641       /* Setup an alternate stack region for the handler execution so that
642 	 stack overflows can be handled properly, avoiding a SEGV generation
643 	 from stack usage by the handler itself.  */
644       stack_t stack;
645 
646       stack.ss_sp = __gnat_alternate_stack;
647       stack.ss_size = sizeof (__gnat_alternate_stack);
648       stack.ss_flags = 0;
649       sigaltstack (&stack, NULL);
650 
651       act.sa_flags |= SA_ONSTACK;
652 #endif
653       sigaction (SIGSEGV, &act, NULL);
654     }
655 
656   __gnat_handler_installed = 1;
657 }
658 
659 /*******************/
660 /* LynxOS Section */
661 /*******************/
662 
663 #elif defined (__Lynx__)
664 
665 #include <signal.h>
666 #include <unistd.h>
667 
668 static void
__gnat_error_handler(int sig)669 __gnat_error_handler (int sig)
670 {
671   struct Exception_Data *exception;
672   const char *msg;
673 
674   switch(sig)
675   {
676     case SIGFPE:
677       exception = &constraint_error;
678       msg = "SIGFPE";
679       break;
680     case SIGILL:
681       exception = &constraint_error;
682       msg = "SIGILL";
683       break;
684     case SIGSEGV:
685       exception = &storage_error;
686       msg = "stack overflow or erroneous memory access";
687       break;
688     case SIGBUS:
689       exception = &constraint_error;
690       msg = "SIGBUS";
691       break;
692     default:
693       exception = &program_error;
694       msg = "unhandled signal";
695     }
696 
697     Raise_From_Signal_Handler (exception, msg);
698 }
699 
700 void
__gnat_install_handler(void)701 __gnat_install_handler (void)
702 {
703   struct sigaction act;
704 
705   act.sa_handler = __gnat_error_handler;
706   act.sa_flags = 0x0;
707   sigemptyset (&act.sa_mask);
708 
709   /* Do not install handlers if interrupt state is "System".  */
710   if (__gnat_get_interrupt_state (SIGFPE) != 's')
711     sigaction (SIGFPE,  &act, NULL);
712   if (__gnat_get_interrupt_state (SIGILL) != 's')
713     sigaction (SIGILL,  &act, NULL);
714   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
715     sigaction (SIGSEGV, &act, NULL);
716   if (__gnat_get_interrupt_state (SIGBUS) != 's')
717     sigaction (SIGBUS,  &act, NULL);
718 
719   __gnat_handler_installed = 1;
720 }
721 
722 /*******************/
723 /* Solaris Section */
724 /*******************/
725 
726 #elif defined (__sun__) && !defined (__vxworks)
727 
728 #include <signal.h>
729 #include <siginfo.h>
730 #include <sys/ucontext.h>
731 #include <sys/regset.h>
732 
733 static void
__gnat_error_handler(int sig,siginfo_t * si,void * ucontext ATTRIBUTE_UNUSED)734 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext ATTRIBUTE_UNUSED)
735 {
736   struct Exception_Data *exception;
737   static int recurse = 0;
738   const char *msg;
739 
740   switch (sig)
741     {
742     case SIGSEGV:
743       /* If the problem was permissions, this is a constraint error.
744 	 Likewise if the failing address isn't maximally aligned or if
745 	 we've recursed.
746 
747 	 ??? Using a static variable here isn't task-safe, but it's
748 	 much too hard to do anything else and we're just determining
749 	 which exception to raise.  */
750       if (si->si_code == SEGV_ACCERR
751 	  || (long) si->si_addr == 0
752 	  || (((long) si->si_addr) & 3) != 0
753 	  || recurse)
754 	{
755 	  exception = &constraint_error;
756 	  msg = "SIGSEGV";
757 	}
758       else
759 	{
760 	  /* See if the page before the faulting page is accessible.  Do that
761 	     by trying to access it.  We'd like to simply try to access
762 	     4096 + the faulting address, but it's not guaranteed to be
763 	     the actual address, just to be on the same page.  */
764 	  recurse++;
765 	  ((volatile char *)
766 	   ((long) si->si_addr & - getpagesize ()))[getpagesize ()];
767 	  exception = &storage_error;
768 	  msg = "stack overflow or erroneous memory access";
769 	}
770       break;
771 
772     case SIGBUS:
773       exception = &program_error;
774       msg = "SIGBUS";
775       break;
776 
777     case SIGFPE:
778       exception = &constraint_error;
779       msg = "SIGFPE";
780       break;
781 
782     default:
783       exception = &program_error;
784       msg = "unhandled signal";
785     }
786 
787   recurse = 0;
788   Raise_From_Signal_Handler (exception, msg);
789 }
790 
791 void
__gnat_install_handler(void)792 __gnat_install_handler (void)
793 {
794   struct sigaction act;
795 
796   /* Set up signal handler to map synchronous signals to appropriate
797      exceptions.  Make sure that the handler isn't interrupted by another
798      signal that might cause a scheduling event!  */
799 
800   act.sa_sigaction = __gnat_error_handler;
801   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
802   sigemptyset (&act.sa_mask);
803 
804   /* Do not install handlers if interrupt state is "System".  */
805   if (__gnat_get_interrupt_state (SIGABRT) != 's')
806     sigaction (SIGABRT, &act, NULL);
807   if (__gnat_get_interrupt_state (SIGFPE) != 's')
808     sigaction (SIGFPE,  &act, NULL);
809   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
810     sigaction (SIGSEGV, &act, NULL);
811   if (__gnat_get_interrupt_state (SIGBUS) != 's')
812     sigaction (SIGBUS,  &act, NULL);
813 
814   __gnat_handler_installed = 1;
815 }
816 
817 /***************/
818 /* VMS Section */
819 /***************/
820 
821 #elif defined (VMS)
822 
823 /* Routine called from binder to override default feature values. */
824 void __gnat_set_features (void);
825 int __gnat_features_set = 0;
826 void (*__gnat_ctrl_c_handler) (void) = 0;
827 
828 #ifdef __IA64
829 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
830 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
831 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
832 #else
833 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
834 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
835 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
836 #endif
837 
838 /* Masks for facility identification. */
839 #define FAC_MASK  		0x0fff0000
840 #define DECADA_M_FACILITY	0x00310000
841 
842 /* Define macro symbols for the VMS conditions that become Ada exceptions.
843    It would be better to just include <ssdef.h> */
844 
845 #define SS$_CONTINUE           1
846 #define SS$_ACCVIO            12
847 #define SS$_HPARITH         1284
848 #define SS$_INTDIV          1156
849 #define SS$_STKOVF          1364
850 #define SS$_CONTROLC        1617
851 #define SS$_RESIGNAL        2328
852 
853 #define MTH$_FLOOVEMAT   1475268       /* Some ACVC_21 CXA tests */
854 
855 /* The following codes must be resignalled, and not handled here. */
856 
857 /* These codes are in standard message libraries.  */
858 extern int C$_SIGKILL;
859 extern int C$_SIGINT;
860 extern int SS$_DEBUG;
861 extern int LIB$_KEYNOTFOU;
862 extern int LIB$_ACTIMAGE;
863 
864 /* These codes are non standard, which is to say the author is
865    not sure if they are defined in the standard message libraries
866    so keep them as macros for now.  */
867 #define RDB$_STREAM_EOF 20480426
868 #define FDL$_UNPRIKW 11829410
869 #define CMA$_EXIT_THREAD 4227492
870 
871 struct cond_sigargs
872 {
873   unsigned int sigarg;
874   unsigned int sigargval;
875 };
876 
877 struct cond_subtests
878 {
879   unsigned int num;
880   const struct cond_sigargs sigargs[];
881 };
882 
883 struct cond_except
884 {
885   unsigned int cond;
886   const struct Exception_Data *except;
887   unsigned int needs_adjust;  /* 1 = adjust PC,  0 = no adjust */
888   const struct cond_subtests *subtests;
889 };
890 
891 struct descriptor_s
892 {
893   unsigned short len, mbz;
894   __char_ptr32 adr;
895 };
896 
897 /* Conditions that don't have an Ada exception counterpart must raise
898    Non_Ada_Error.  Since this is defined in s-auxdec, it should only be
899    referenced by user programs, not the compiler or tools.  Hence the
900    #ifdef IN_RTS.  */
901 
902 #ifdef IN_RTS
903 
904 #define Status_Error ada__io_exceptions__status_error
905 extern struct Exception_Data Status_Error;
906 
907 #define Mode_Error ada__io_exceptions__mode_error
908 extern struct Exception_Data Mode_Error;
909 
910 #define Name_Error ada__io_exceptions__name_error
911 extern struct Exception_Data Name_Error;
912 
913 #define Use_Error ada__io_exceptions__use_error
914 extern struct Exception_Data Use_Error;
915 
916 #define Device_Error ada__io_exceptions__device_error
917 extern struct Exception_Data Device_Error;
918 
919 #define End_Error ada__io_exceptions__end_error
920 extern struct Exception_Data End_Error;
921 
922 #define Data_Error ada__io_exceptions__data_error
923 extern struct Exception_Data Data_Error;
924 
925 #define Layout_Error ada__io_exceptions__layout_error
926 extern struct Exception_Data Layout_Error;
927 
928 #define Non_Ada_Error system__aux_dec__non_ada_error
929 extern struct Exception_Data Non_Ada_Error;
930 
931 #define Coded_Exception system__vms_exception_table__coded_exception
932 extern struct Exception_Data *Coded_Exception (void *);
933 
934 #define Base_Code_In system__vms_exception_table__base_code_in
935 extern void *Base_Code_In (void *);
936 
937 /* DEC Ada exceptions are not defined in a header file, so they
938    must be declared.  */
939 
940 #define ADA$_ALREADY_OPEN	0x0031a594
941 #define ADA$_CONSTRAINT_ERRO	0x00318324
942 #define ADA$_DATA_ERROR		0x003192c4
943 #define ADA$_DEVICE_ERROR	0x003195e4
944 #define ADA$_END_ERROR		0x00319904
945 #define ADA$_FAC_MODE_MISMAT	0x0031a8b3
946 #define ADA$_IOSYSFAILED	0x0031af04
947 #define ADA$_KEYSIZERR		0x0031aa3c
948 #define ADA$_KEY_MISMATCH	0x0031a8e3
949 #define ADA$_LAYOUT_ERROR	0x00319c24
950 #define ADA$_LINEXCMRS		0x0031a8f3
951 #define ADA$_MAXLINEXC		0x0031a8eb
952 #define ADA$_MODE_ERROR		0x00319f44
953 #define ADA$_MRN_MISMATCH	0x0031a8db
954 #define ADA$_MRS_MISMATCH	0x0031a8d3
955 #define ADA$_NAME_ERROR		0x0031a264
956 #define ADA$_NOT_OPEN		0x0031a58c
957 #define ADA$_ORG_MISMATCH	0x0031a8bb
958 #define ADA$_PROGRAM_ERROR	0x00318964
959 #define ADA$_RAT_MISMATCH	0x0031a8cb
960 #define ADA$_RFM_MISMATCH	0x0031a8c3
961 #define ADA$_STAOVF		0x00318cac
962 #define ADA$_STATUS_ERROR	0x0031a584
963 #define ADA$_STORAGE_ERROR	0x00318c84
964 #define ADA$_UNSUPPORTED	0x0031a8ab
965 #define ADA$_USE_ERROR		0x0031a8a4
966 
967 /* DEC Ada specific conditions.  */
968 static const struct cond_except dec_ada_cond_except_table [] =
969 {
970   {ADA$_PROGRAM_ERROR,   &program_error, 0, 0},
971   {ADA$_USE_ERROR,       &Use_Error, 0, 0},
972   {ADA$_KEYSIZERR,       &program_error, 0, 0},
973   {ADA$_STAOVF,          &storage_error, 0, 0},
974   {ADA$_CONSTRAINT_ERRO, &constraint_error, 0, 0},
975   {ADA$_IOSYSFAILED,     &Device_Error, 0, 0},
976   {ADA$_LAYOUT_ERROR,    &Layout_Error, 0, 0},
977   {ADA$_STORAGE_ERROR,   &storage_error, 0, 0},
978   {ADA$_DATA_ERROR,      &Data_Error, 0, 0},
979   {ADA$_DEVICE_ERROR,    &Device_Error, 0, 0},
980   {ADA$_END_ERROR,       &End_Error, 0, 0},
981   {ADA$_MODE_ERROR,      &Mode_Error, 0, 0},
982   {ADA$_NAME_ERROR,      &Name_Error, 0, 0},
983   {ADA$_STATUS_ERROR,    &Status_Error, 0, 0},
984   {ADA$_NOT_OPEN,        &Use_Error, 0, 0},
985   {ADA$_ALREADY_OPEN,    &Use_Error, 0, 0},
986   {ADA$_USE_ERROR,       &Use_Error, 0, 0},
987   {ADA$_UNSUPPORTED,     &Use_Error, 0, 0},
988   {ADA$_FAC_MODE_MISMAT, &Use_Error, 0, 0},
989   {ADA$_ORG_MISMATCH,    &Use_Error, 0, 0},
990   {ADA$_RFM_MISMATCH,    &Use_Error, 0, 0},
991   {ADA$_RAT_MISMATCH,    &Use_Error, 0, 0},
992   {ADA$_MRS_MISMATCH,    &Use_Error, 0, 0},
993   {ADA$_MRN_MISMATCH,    &Use_Error, 0, 0},
994   {ADA$_KEY_MISMATCH,    &Use_Error, 0, 0},
995   {ADA$_MAXLINEXC,       &constraint_error, 0, 0},
996   {ADA$_LINEXCMRS,       &constraint_error, 0, 0},
997 
998 #if 0
999    /* Already handled by a pragma Import_Exception
1000       in Aux_IO_Exceptions */
1001   {ADA$_LOCK_ERROR,      &Lock_Error, 0, 0},
1002   {ADA$_EXISTENCE_ERROR, &Existence_Error, 0, 0},
1003   {ADA$_KEY_ERROR,       &Key_Error, 0, 0},
1004 #endif
1005 
1006   {0,                    0, 0, 0}
1007 };
1008 
1009 #endif /* IN_RTS */
1010 
1011 /* Non-DEC Ada specific conditions that map to Ada exceptions.  */
1012 
1013 /* Subtest for ACCVIO Constraint_Error, kept for compatibility,
1014    in hindsight should have just made ACCVIO == Storage_Error.  */
1015 #define ACCVIO_VIRTUAL_ADDR 3
1016 static const struct cond_subtests accvio_c_e =
1017 {1,  /* number of subtests below */
1018   {
1019      { ACCVIO_VIRTUAL_ADDR, 0 }
1020    }
1021 };
1022 
1023 /* Macro flag to adjust PC which gets off by one for some conditions,
1024    not sure if this is reliably true, PC could be off by more for
1025    HPARITH for example, unless a trapb is inserted. */
1026 #define NEEDS_ADJUST 1
1027 
1028 static const struct cond_except system_cond_except_table [] =
1029 {
1030   {MTH$_FLOOVEMAT, &constraint_error, 0, 0},
1031   {SS$_INTDIV,     &constraint_error, 0, 0},
1032   {SS$_HPARITH,    &constraint_error, NEEDS_ADJUST, 0},
1033   {SS$_ACCVIO,     &constraint_error, NEEDS_ADJUST, &accvio_c_e},
1034   {SS$_ACCVIO,     &storage_error,    NEEDS_ADJUST, 0},
1035   {SS$_STKOVF,     &storage_error,    NEEDS_ADJUST, 0},
1036   {0,               0, 0, 0}
1037 };
1038 
1039 /* To deal with VMS conditions and their mapping to Ada exceptions,
1040    the __gnat_error_handler routine below is installed as an exception
1041    vector having precedence over DEC frame handlers.  Some conditions
1042    still need to be handled by such handlers, however, in which case
1043    __gnat_error_handler needs to return SS$_RESIGNAL.  Consider for
1044    instance the use of a third party library compiled with DECAda and
1045    performing its own exception handling internally.
1046 
1047    To allow some user-level flexibility, which conditions should be
1048    resignaled is controlled by a predicate function, provided with the
1049    condition value and returning a boolean indication stating whether
1050    this condition should be resignaled or not.
1051 
1052    That predicate function is called indirectly, via a function pointer,
1053    by __gnat_error_handler, and changing that pointer is allowed to the
1054    user code by way of the __gnat_set_resignal_predicate interface.
1055 
1056    The user level function may then implement what it likes, including
1057    for instance the maintenance of a dynamic data structure if the set
1058    of to be resignalled conditions has to change over the program's
1059    lifetime.
1060 
1061    ??? This is not a perfect solution to deal with the possible
1062    interactions between the GNAT and the DECAda exception handling
1063    models and better (more general) schemes are studied.  This is so
1064    just provided as a convenient workaround in the meantime, and
1065    should be use with caution since the implementation has been kept
1066    very simple.  */
1067 
1068 typedef int resignal_predicate (int code);
1069 
1070 static const int * const cond_resignal_table [] =
1071 {
1072   &C$_SIGKILL,
1073   (int *)CMA$_EXIT_THREAD,
1074   &SS$_DEBUG,
1075   &LIB$_KEYNOTFOU,
1076   &LIB$_ACTIMAGE,
1077   (int *) RDB$_STREAM_EOF,
1078   (int *) FDL$_UNPRIKW,
1079   0
1080 };
1081 
1082 static const int facility_resignal_table [] =
1083 {
1084   0x1380000, /* RDB */
1085   0x2220000, /* SQL */
1086   0
1087 };
1088 
1089 /* Default GNAT predicate for resignaling conditions.  */
1090 
1091 static int
__gnat_default_resignal_p(int code)1092 __gnat_default_resignal_p (int code)
1093 {
1094   int i, iexcept;
1095 
1096   for (i = 0; facility_resignal_table [i]; i++)
1097     if ((code & FAC_MASK) == facility_resignal_table [i])
1098       return 1;
1099 
1100   for (i = 0, iexcept = 0;
1101        cond_resignal_table [i]
1102 	&& !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1103        i++);
1104 
1105   return iexcept;
1106 }
1107 
1108 /* Static pointer to predicate that the __gnat_error_handler exception
1109    vector invokes to determine if it should resignal a condition.  */
1110 
1111 static resignal_predicate *__gnat_resignal_p = __gnat_default_resignal_p;
1112 
1113 /* User interface to change the predicate pointer to PREDICATE. Reset to
1114    the default if PREDICATE is null.  */
1115 
1116 void
__gnat_set_resignal_predicate(resignal_predicate * predicate)1117 __gnat_set_resignal_predicate (resignal_predicate *predicate)
1118 {
1119   if (predicate == NULL)
1120     __gnat_resignal_p = __gnat_default_resignal_p;
1121   else
1122     __gnat_resignal_p = predicate;
1123 }
1124 
1125 /* Should match System.Parameters.Default_Exception_Msg_Max_Length.  */
1126 #define Default_Exception_Msg_Max_Length 512
1127 
1128 /* Action routine for SYS$PUTMSG. There may be multiple
1129    conditions, each with text to be appended to MESSAGE
1130    and separated by line termination.  */
1131 static int
copy_msg(struct descriptor_s * msgdesc,char * message)1132 copy_msg (struct descriptor_s *msgdesc, char *message)
1133 {
1134   int len = strlen (message);
1135   int copy_len;
1136 
1137   /* Check for buffer overflow and skip.  */
1138   if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1139     {
1140       strcat (message, "\r\n");
1141       len += 2;
1142     }
1143 
1144   /* Check for buffer overflow and truncate if necessary.  */
1145   copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1146 	      msgdesc->len :
1147 	      Default_Exception_Msg_Max_Length - 1 - len);
1148   strncpy (&message [len], msgdesc->adr, copy_len);
1149   message [len + copy_len] = 0;
1150 
1151   return 0;
1152 }
1153 
1154 /* Scan TABLE for a match for the condition contained in SIGARGS,
1155    and return the entry, or the empty entry if no match found.  */
1156 static const struct cond_except *
scan_conditions(int * sigargs,const struct cond_except * table[])1157 scan_conditions ( int *sigargs, const struct cond_except *table [])
1158 {
1159   int i;
1160   struct cond_except entry;
1161 
1162   /* Scan the exception condition table for a match and fetch
1163      the associated GNAT exception pointer.  */
1164   for (i = 0; (*table) [i].cond; i++)
1165     {
1166       unsigned int match = LIB$MATCH_COND (&sigargs [1], &(*table) [i].cond);
1167       const struct cond_subtests *subtests  = (*table) [i].subtests;
1168 
1169       if (match)
1170 	{
1171 	  if (!subtests)
1172 	    {
1173 	      return &(*table) [i];
1174 	    }
1175 	  else
1176 	    {
1177 	      unsigned int ii;
1178 	      int num = (*subtests).num;
1179 
1180 	      /* Perform subtests to differentiate exception.  */
1181 	      for (ii = 0; ii < num; ii++)
1182 		{
1183 		  unsigned int arg = (*subtests).sigargs [ii].sigarg;
1184 		  unsigned int argval = (*subtests).sigargs [ii].sigargval;
1185 
1186 		  if (sigargs [arg] != argval)
1187 		    {
1188 		      num = 0;
1189 		      break;
1190 		    }
1191 		}
1192 
1193 	      /* All subtests passed.  */
1194 	      if (num == (*subtests).num)
1195 	        return &(*table) [i];
1196 	    }
1197 	}
1198     }
1199 
1200     /* No match, return the null terminating entry.  */
1201     return &(*table) [i];
1202 }
1203 
1204 /* __gnat_handle_vms_condtition is both a frame based handler
1205    for the runtime, and an exception vector for the compiler.  */
1206 long
__gnat_handle_vms_condition(int * sigargs,void * mechargs)1207 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
1208 {
1209   struct Exception_Data *exception = 0;
1210   unsigned int needs_adjust = 0;
1211   void *base_code;
1212   struct descriptor_s gnat_facility = {4, 0, "GNAT"};
1213   char message [Default_Exception_Msg_Max_Length];
1214 
1215   const char *msg = "";
1216 
1217   /* Check for conditions to resignal which aren't effected by pragma
1218      Import_Exception.  */
1219   if (__gnat_resignal_p (sigargs [1]))
1220     return SS$_RESIGNAL;
1221 #ifndef IN_RTS
1222   /* toplev.c handles this for compiler.  */
1223   if (sigargs [1] == SS$_HPARITH)
1224     return SS$_RESIGNAL;
1225 #endif
1226 
1227 #ifdef IN_RTS
1228   /* See if it's an imported exception.  Beware that registered exceptions
1229      are bound to their base code, with the severity bits masked off.  */
1230   base_code = Base_Code_In ((void *) sigargs[1]);
1231   exception = Coded_Exception (base_code);
1232 #endif
1233 
1234   if (exception == 0)
1235 #ifdef IN_RTS
1236     {
1237       int i;
1238       struct cond_except cond;
1239       const struct cond_except *cond_table;
1240       const struct cond_except *cond_tables [] = {dec_ada_cond_except_table,
1241 					          system_cond_except_table,
1242 					          0};
1243       unsigned int ctrlc = SS$_CONTROLC;
1244       unsigned int *sigint = &C$_SIGINT;
1245       int ctrlc_match = LIB$MATCH_COND (&sigargs [1], &ctrlc);
1246       int sigint_match = LIB$MATCH_COND (&sigargs [1], &sigint);
1247 
1248       extern int SYS$DCLAST (void (*astadr)(), unsigned long long astprm,
1249 	                     unsigned int acmode);
1250 
1251       /* If SS$_CONTROLC has been imported as an exception, it will take
1252 	 priority over a Ctrl/C handler.  See above.  SIGINT has a
1253 	 different condition value due to it's DECCCRTL roots and it's
1254 	 the condition that gets raised for a "kill -INT".  */
1255       if ((ctrlc_match || sigint_match) && __gnat_ctrl_c_handler)
1256 	{
1257 	  SYS$DCLAST (__gnat_ctrl_c_handler, 0, 0);
1258 	  return SS$_CONTINUE;
1259 	}
1260 
1261       i = 0;
1262       while ((cond_table = cond_tables[i++]) && !exception)
1263 	{
1264 	  cond = *scan_conditions (sigargs, &cond_table);
1265 	  exception = (struct Exception_Data *) cond.except;
1266 	}
1267 
1268       if (exception)
1269 	needs_adjust = cond.needs_adjust;
1270       else
1271 	/* User programs expect Non_Ada_Error to be raised if no match,
1272 	   reference DEC Ada test CXCONDHAN.  */
1273 	exception = &Non_Ada_Error;
1274       }
1275 #else
1276     {
1277       /* Pretty much everything is just a program error in the compiler */
1278       exception = &program_error;
1279     }
1280 #endif
1281 
1282   message[0] = 0;
1283   /* Subtract PC & PSL fields as per ABI for SYS$PUTMSG.  */
1284   sigargs[0] -= 2;
1285 
1286   extern int SYS$PUTMSG (void *, int (*)(), void *, unsigned long long);
1287 
1288   /* If it was a DEC Ada specific condtiion, make it GNAT otherwise
1289      keep the old facility.  */
1290   if ((sigargs [1] & FAC_MASK) == DECADA_M_FACILITY)
1291     SYS$PUTMSG (sigargs, copy_msg, &gnat_facility,
1292 	        (unsigned long long ) message);
1293   else
1294     SYS$PUTMSG (sigargs, copy_msg, 0,
1295 	        (unsigned long long ) message);
1296 
1297   /* Add back PC & PSL fields as per ABI for SYS$PUTMSG.  */
1298   sigargs[0] += 2;
1299   msg = message;
1300 
1301   if (needs_adjust)
1302     __gnat_adjust_context_for_raise (sigargs [1], (void *)mechargs);
1303 
1304   Raise_From_Signal_Handler (exception, msg);
1305 }
1306 
1307 #if defined (IN_RTS) && defined (__IA64)
1308 /* Called only from adasigio.b32.  This is a band aid to avoid going
1309    through the VMS signal handling code which results in a 0x8000 per
1310    handled exception memory leak in P2 space (see VMS source listing
1311    sys/lis/exception.lis) due to the allocation of working space that
1312    is expected to be deallocated upon return from the condition handler,
1313    which doesn't return in GNAT compiled code.  */
1314 void
GNAT$STOP(int * sigargs)1315 GNAT$STOP (int *sigargs)
1316 {
1317    /* Note that there are no mechargs. We rely on the fact that condtions
1318       raised from DEClib I/O do not require an "adjust".  Also the count
1319       will be off by 2, since LIB$STOP didn't get a chance to add the
1320       PC and PSL fields, so we bump it so PUTMSG comes out right.  */
1321    sigargs [0] += 2;
1322    __gnat_handle_vms_condition (sigargs, 0);
1323 }
1324 #endif
1325 
1326 void
__gnat_install_handler(void)1327 __gnat_install_handler (void)
1328 {
1329   long prvhnd ATTRIBUTE_UNUSED;
1330 
1331 #if !defined (IN_RTS)
1332   extern int SYS$SETEXV (unsigned int vector, int (*addres)(),
1333 	                 unsigned int accmode, void *(*(prvhnd)));
1334   SYS$SETEXV (1, __gnat_handle_vms_condition, 3, &prvhnd);
1335 #endif
1336 
1337   __gnat_handler_installed = 1;
1338 }
1339 
1340 /* __gnat_adjust_context_for_raise for Alpha - see comments along with the
1341    default version later in this file.  */
1342 
1343 #if defined (IN_RTS) && defined (__alpha__)
1344 
1345 #include <vms/chfctxdef.h>
1346 #include <vms/chfdef.h>
1347 
1348 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1349 
1350 void
__gnat_adjust_context_for_raise(int signo ATTRIBUTE_UNUSED,void * ucontext)1351 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1352 {
1353   if (signo == SS$_HPARITH)
1354     {
1355       /* Sub one to the address of the instruction signaling the condition,
1356 	 located in the sigargs array.  */
1357 
1358       CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1359       CHF$SIGNAL_ARRAY * sigargs
1360 	= (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1361 
1362       int vcount = sigargs->chf$is_sig_args;
1363       int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1364 
1365       (*pc_slot)--;
1366     }
1367 }
1368 
1369 #endif
1370 
1371 /* __gnat_adjust_context_for_raise for ia64.  */
1372 
1373 #if defined (IN_RTS) && defined (__IA64)
1374 
1375 #include <vms/chfctxdef.h>
1376 #include <vms/chfdef.h>
1377 
1378 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1379 
1380 typedef unsigned long long u64;
1381 
1382 void
__gnat_adjust_context_for_raise(int signo ATTRIBUTE_UNUSED,void * ucontext)1383 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1384 {
1385   /* Add one to the address of the instruction signaling the condition,
1386      located in the 64bits sigargs array.  */
1387 
1388   CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1389 
1390   CHF64$SIGNAL_ARRAY *chfsig64
1391     = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1392 
1393   u64 * post_sigarray
1394     = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1395 
1396   u64 * ih_pc_loc = post_sigarray - 2;
1397 
1398   (*ih_pc_loc) ++;
1399 }
1400 
1401 #endif
1402 
1403 /* Easier interface for LIB$GET_LOGICAL: put the equivalence of NAME into BUF,
1404    always NUL terminated.  In case of error or if the result is longer than
1405    LEN (length of BUF) an empty string is written info BUF.  */
1406 
1407 static void
__gnat_vms_get_logical(const char * name,char * buf,int len)1408 __gnat_vms_get_logical (const char *name, char *buf, int len)
1409 {
1410   struct descriptor_s name_desc, result_desc;
1411   int status;
1412   unsigned short rlen;
1413 
1414   /* Build the descriptor for NAME.  */
1415   name_desc.len = strlen (name);
1416   name_desc.mbz = 0;
1417   name_desc.adr = (char *)name;
1418 
1419   /* Build the descriptor for the result.  */
1420   result_desc.len = len;
1421   result_desc.mbz = 0;
1422   result_desc.adr = buf;
1423 
1424   status = LIB$GET_LOGICAL (&name_desc, &result_desc, &rlen);
1425 
1426   if ((status & 1) == 1 && rlen < len)
1427     buf[rlen] = 0;
1428   else
1429     buf[0] = 0;
1430 }
1431 
1432 /* Size of a page on ia64 and alpha VMS.  */
1433 #define VMS_PAGESIZE 8192
1434 
1435 /* User mode.  */
1436 #define PSL__C_USER 3
1437 
1438 /* No access.  */
1439 #define PRT__C_NA 0
1440 
1441 /* Descending region.  */
1442 #define VA__M_DESCEND 1
1443 
1444 /* Get by virtual address.  */
1445 #define VA___REGSUM_BY_VA 1
1446 
1447 /* Memory region summary.  */
1448 struct regsum
1449 {
1450   unsigned long long q_region_id;
1451   unsigned int l_flags;
1452   unsigned int l_region_protection;
1453   void *pq_start_va;
1454   unsigned long long q_region_size;
1455   void *pq_first_free_va;
1456 };
1457 
1458 extern int SYS$GET_REGION_INFO (unsigned int, unsigned long long *,
1459 	                        void *, void *, unsigned int,
1460 	                        void *, unsigned int *);
1461 extern int SYS$EXPREG_64 (unsigned long long *, unsigned long long,
1462 	                  unsigned int, unsigned int, void **,
1463 	                  unsigned long long *);
1464 extern int SYS$SETPRT_64 (void *, unsigned long long, unsigned int,
1465 	                  unsigned int, void **, unsigned long long *,
1466 	                  unsigned int *);
1467 
1468 /* Add a guard page in the memory region containing ADDR at ADDR +/- SIZE.
1469    (The sign depends on the kind of the memory region).  */
1470 
1471 static int
__gnat_set_stack_guard_page(void * addr,unsigned long size)1472 __gnat_set_stack_guard_page (void *addr, unsigned long size)
1473 {
1474   int status;
1475   void *ret_va;
1476   unsigned long long ret_len;
1477   unsigned int ret_prot;
1478   void *start_va;
1479   unsigned long long length;
1480   unsigned int retlen;
1481   struct regsum buffer;
1482 
1483   /* Get the region for ADDR.  */
1484   status = SYS$GET_REGION_INFO
1485     (VA___REGSUM_BY_VA, NULL, addr, NULL, sizeof (buffer), &buffer, &retlen);
1486 
1487   if ((status & 1) != 1)
1488     return -1;
1489 
1490   /* Extend the region.  */
1491   status = SYS$EXPREG_64 (&buffer.q_region_id,
1492 	                  size, 0, 0, &start_va, &length);
1493 
1494   if ((status & 1) != 1)
1495     return -1;
1496 
1497   /* Create a guard page.  */
1498   if (!(buffer.l_flags & VA__M_DESCEND))
1499     start_va = (void *)((unsigned long long)start_va + length - VMS_PAGESIZE);
1500 
1501   status = SYS$SETPRT_64 (start_va, VMS_PAGESIZE, PSL__C_USER, PRT__C_NA,
1502 	                  &ret_va, &ret_len, &ret_prot);
1503 
1504   if ((status & 1) != 1)
1505     return -1;
1506   return 0;
1507 }
1508 
1509 /* Read logicals to limit the stack(s) size.  */
1510 
1511 static void
__gnat_set_stack_limit(void)1512 __gnat_set_stack_limit (void)
1513 {
1514 #ifdef __ia64__
1515   void *sp;
1516   unsigned long size;
1517   char value[16];
1518   char *e;
1519 
1520   /* The main stack.  */
1521   __gnat_vms_get_logical ("GNAT_STACK_SIZE", value, sizeof (value));
1522   size = strtoul (value, &e, 0);
1523   if (e > value && *e == 0)
1524     {
1525       asm ("mov %0=sp" : "=r" (sp));
1526       __gnat_set_stack_guard_page (sp, size * 1024);
1527     }
1528 
1529   /* The register stack.  */
1530   __gnat_vms_get_logical ("GNAT_RBS_SIZE", value, sizeof (value));
1531   size = strtoul (value, &e, 0);
1532   if (e > value && *e == 0)
1533     {
1534       asm ("mov %0=ar.bsp" : "=r" (sp));
1535       __gnat_set_stack_guard_page (sp, size * 1024);
1536     }
1537 #endif
1538 }
1539 
1540 #ifdef IN_RTS
1541 extern int SYS$IEEE_SET_FP_CONTROL (void *, void *, void *);
1542 #define K_TRUE 1
1543 #define __int64 long long
1544 #define __NEW_STARLET
1545 #include <vms/ieeedef.h>
1546 #endif
1547 
1548 /* Feature logical name and global variable address pair.
1549    If we ever add another feature logical to this list, the
1550    feature struct will need to be enhanced to take into account
1551    possible values for *gl_addr.  */
1552 struct feature {
1553   const char *name;
1554   int *gl_addr;
1555 };
1556 
1557 /* Default values for GNAT features set by environment or binder.  */
1558 int __gl_heap_size = 64;
1559 
1560 /* Default float format is 'I' meaning IEEE.  If gnatbind detetcts that a
1561    VAX Float format is specified, it will set this global variable to 'V'.
1562    Subsequently __gnat_set_features will test the variable and if set for
1563    VAX Float will call a Starlet function to enable trapping for invalid
1564    operation, drivide by zero, and overflow. This will prevent the VMS runtime
1565    (specifically OTS$CHECK_FP_MODE) from complaining about inconsistent
1566    floating point settings in a mixed language program. Ideally the setting
1567    would be determined at link time based on settings in the object files,
1568    however the VMS linker seems to take the setting from the first object
1569    in the link, e.g. pcrt0.o which is float representation neutral.  */
1570 char __gl_float_format = 'I';
1571 
1572 /* Array feature logical names and global variable addresses.  */
1573 static const struct feature features[] =
1574 {
1575   {"GNAT$NO_MALLOC_64", &__gl_heap_size},
1576   {0, 0}
1577 };
1578 
1579 void
__gnat_set_features(void)1580 __gnat_set_features (void)
1581 {
1582   int i;
1583   char buff[16];
1584 #ifdef IN_RTS
1585   IEEE clrmsk, setmsk, prvmsk;
1586 
1587   clrmsk.ieee$q_flags = 0LL;
1588   setmsk.ieee$q_flags = 0LL;
1589 #endif
1590 
1591   /* Loop through features array and test name for enable/disable.  */
1592   for (i = 0; features[i].name; i++)
1593     {
1594       __gnat_vms_get_logical (features[i].name, buff, sizeof (buff));
1595 
1596       if (strcmp (buff, "ENABLE") == 0
1597 	  || strcmp (buff, "TRUE") == 0
1598 	  || strcmp (buff, "1") == 0)
1599 	*features[i].gl_addr = 32;
1600       else if (strcmp (buff, "DISABLE") == 0
1601 	       || strcmp (buff, "FALSE") == 0
1602 	       || strcmp (buff, "0") == 0)
1603 	*features[i].gl_addr = 64;
1604     }
1605 
1606   /* Features to artificially limit the stack size.  */
1607   __gnat_set_stack_limit ();
1608 
1609 #ifdef IN_RTS
1610   if (__gl_float_format == 'V')
1611     {
1612       setmsk.ieee$v_trap_enable_inv = K_TRUE;
1613       setmsk.ieee$v_trap_enable_dze = K_TRUE;
1614       setmsk.ieee$v_trap_enable_ovf = K_TRUE;
1615       SYS$IEEE_SET_FP_CONTROL (&clrmsk, &setmsk, &prvmsk);
1616     }
1617 #endif
1618 
1619   __gnat_features_set = 1;
1620 }
1621 
1622 /* Return true if the VMS version is 7.x.  */
1623 
1624 extern unsigned int LIB$GETSYI (int *, ...);
1625 
1626 #define SYI$_VERSION 0x1000
1627 
1628 int
__gnat_is_vms_v7(void)1629 __gnat_is_vms_v7 (void)
1630 {
1631   struct descriptor_s desc;
1632   char version[8];
1633   int status;
1634   int code = SYI$_VERSION;
1635 
1636   desc.len = sizeof (version);
1637   desc.mbz = 0;
1638   desc.adr = version;
1639 
1640   status = LIB$GETSYI (&code, 0, &desc);
1641   if ((status & 1) == 1 && version[1] == '7' && version[2] == '.')
1642     return 1;
1643   else
1644     return 0;
1645 }
1646 
1647 /*******************/
1648 /* FreeBSD Section */
1649 /*******************/
1650 
1651 #elif defined (__FreeBSD__) || defined (__DragonFly__)
1652 
1653 #include <signal.h>
1654 #include <sys/ucontext.h>
1655 #include <unistd.h>
1656 
1657 static void
__gnat_error_handler(int sig,siginfo_t * si ATTRIBUTE_UNUSED,void * ucontext ATTRIBUTE_UNUSED)1658 __gnat_error_handler (int sig,
1659 		      siginfo_t *si ATTRIBUTE_UNUSED,
1660 		      void *ucontext ATTRIBUTE_UNUSED)
1661 {
1662   struct Exception_Data *exception;
1663   const char *msg;
1664 
1665   switch (sig)
1666     {
1667     case SIGFPE:
1668       exception = &constraint_error;
1669       msg = "SIGFPE";
1670       break;
1671 
1672     case SIGILL:
1673       exception = &constraint_error;
1674       msg = "SIGILL";
1675       break;
1676 
1677     case SIGSEGV:
1678       exception = &storage_error;
1679       msg = "stack overflow or erroneous memory access";
1680       break;
1681 
1682     case SIGBUS:
1683       exception = &storage_error;
1684       msg = "SIGBUS: possible stack overflow";
1685       break;
1686 
1687     default:
1688       exception = &program_error;
1689       msg = "unhandled signal";
1690     }
1691 
1692   Raise_From_Signal_Handler (exception, msg);
1693 }
1694 
1695 void
__gnat_install_handler(void)1696 __gnat_install_handler (void)
1697 {
1698   struct sigaction act;
1699 
1700   /* Set up signal handler to map synchronous signals to appropriate
1701      exceptions.  Make sure that the handler isn't interrupted by another
1702      signal that might cause a scheduling event!  */
1703 
1704   act.sa_sigaction
1705     = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1706   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1707   (void) sigemptyset (&act.sa_mask);
1708 
1709   (void) sigaction (SIGILL,  &act, NULL);
1710   (void) sigaction (SIGFPE,  &act, NULL);
1711   (void) sigaction (SIGSEGV, &act, NULL);
1712   (void) sigaction (SIGBUS,  &act, NULL);
1713 
1714   __gnat_handler_installed = 1;
1715 }
1716 
1717 /*************************************/
1718 /* VxWorks Section (including Vx653) */
1719 /*************************************/
1720 
1721 #elif defined(__vxworks)
1722 
1723 #include <signal.h>
1724 #include <taskLib.h>
1725 #if (defined (__i386__) || defined (__x86_64__)) && !defined (VTHREADS)
1726 #include <sysLib.h>
1727 #endif
1728 
1729 #include "sigtramp.h"
1730 
1731 #ifndef __RTP__
1732 #include <intLib.h>
1733 #include <iv.h>
1734 #endif
1735 
1736 #if ((defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6))) && !defined(__RTP__)
1737 #define VXWORKS_FORCE_GUARD_PAGE 1
1738 #include <vmLib.h>
1739 extern size_t vxIntStackOverflowSize;
1740 #define INT_OVERFLOW_SIZE vxIntStackOverflowSize
1741 #endif
1742 
1743 #ifdef VTHREADS
1744 #include "private/vThreadsP.h"
1745 #endif
1746 
1747 #ifndef __RTP__
1748 
1749 /* Directly vectored Interrupt routines are not supported when using RTPs.  */
1750 
1751 extern void * __gnat_inum_to_ivec (int);
1752 
1753 /* This is needed by the GNAT run time to handle Vxworks interrupts.  */
1754 void *
__gnat_inum_to_ivec(int num)1755 __gnat_inum_to_ivec (int num)
1756 {
1757   return (void *) INUM_TO_IVEC (num);
1758 }
1759 #endif
1760 
1761 #if !defined(__alpha_vxworks) && ((_WRS_VXWORKS_MAJOR != 6) && (_WRS_VXWORKS_MAJOR != 7)) && !defined(__RTP__)
1762 
1763 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1764    on Alpha VxWorks and VxWorks 6.x (including RTPs).  */
1765 
1766 extern long getpid (void);
1767 
1768 long
getpid(void)1769 getpid (void)
1770 {
1771   return taskIdSelf ();
1772 }
1773 #endif
1774 
1775 /* When stack checking is performed by probing a guard page on the stack,
1776    sometimes this guard page is not properly reset on VxWorks. We need to
1777    manually reset it in this case.
1778    This function returns TRUE in case the guard page was hit by the
1779    signal. */
1780 static int
__gnat_reset_guard_page(int sig)1781 __gnat_reset_guard_page (int sig)
1782 {
1783   /* On ARM VxWorks 6.x and x86_64 VxWorks 7, the guard page is left un-armed
1784      by the kernel after being violated, so subsequent violations aren't
1785      detected.
1786      So we retrieve the address of the guard page from the TCB and compare it
1787      with the page that is violated and re-arm that page if there's a match. */
1788 #if defined (VXWORKS_FORCE_GUARD_PAGE)
1789 
1790   /* Ignore signals that are not stack overflow signals */
1791   if (sig != SIGSEGV && sig != SIGBUS && sig != SIGILL) return FALSE;
1792 
1793   /* If the target does not support guard pages, INT_OVERFLOW_SIZE will be 0 */
1794   if (INT_OVERFLOW_SIZE == 0) return FALSE;
1795 
1796   TASK_ID tid           = taskIdSelf ();
1797   WIND_TCB *pTcb        = taskTcb (tid);
1798   VIRT_ADDR guardPage   = (VIRT_ADDR) pTcb->pStackEnd - INT_OVERFLOW_SIZE;
1799   UINT stateMask        = VM_STATE_MASK_VALID;
1800   UINT guardState       = VM_STATE_VALID_NOT;
1801 
1802 #if (_WRS_VXWORKS_MAJOR >= 7)
1803   stateMask  |= MMU_ATTR_SPL_MSK;
1804   guardState |= MMU_ATTR_NO_BLOCK;
1805 #endif
1806 
1807   UINT nState;
1808   vmStateGet (NULL, guardPage, &nState);
1809   if ((nState & VM_STATE_MASK_VALID) != VM_STATE_VALID_NOT)
1810     {
1811       /* If the guard page has a valid state, we need to reset to
1812          invalid state here */
1813       vmStateSet (NULL, guardPage, INT_OVERFLOW_SIZE, stateMask, guardState);
1814       return TRUE;
1815     }
1816 #endif /* VXWORKS_FORCE_GUARD_PAGE */
1817   return FALSE;
1818 }
1819 
1820 /* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
1821    handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
1822    doesn't.  */
1823 void
__gnat_clear_exception_count(void)1824 __gnat_clear_exception_count (void)
1825 {
1826 #ifdef VTHREADS
1827   WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1828 
1829   currentTask->vThreads.excCnt = 0;
1830 #endif
1831 }
1832 
1833 /* Handle different SIGnal to exception mappings in different VxWorks
1834    versions.  */
1835 void
__gnat_map_signal(int sig,siginfo_t * si ATTRIBUTE_UNUSED,void * sc ATTRIBUTE_UNUSED)1836 __gnat_map_signal (int sig,
1837                    siginfo_t *si ATTRIBUTE_UNUSED,
1838                    void *sc ATTRIBUTE_UNUSED)
1839 {
1840   struct Exception_Data *exception;
1841   const char *msg;
1842 
1843   switch (sig)
1844     {
1845     case SIGFPE:
1846       exception = &constraint_error;
1847       msg = "SIGFPE";
1848       break;
1849 #ifdef VTHREADS
1850 #ifdef __VXWORKSMILS__
1851     case SIGILL:
1852       exception = &storage_error;
1853       msg = "SIGILL: possible stack overflow";
1854       break;
1855     case SIGSEGV:
1856       exception = &storage_error;
1857       msg = "SIGSEGV";
1858       break;
1859     case SIGBUS:
1860       exception = &program_error;
1861       msg = "SIGBUS";
1862       break;
1863 #else
1864     case SIGILL:
1865       exception = &constraint_error;
1866       msg = "Floating point exception or SIGILL";
1867       break;
1868     case SIGSEGV:
1869       exception = &storage_error;
1870       msg = "SIGSEGV";
1871       break;
1872     case SIGBUS:
1873       exception = &storage_error;
1874       msg = "SIGBUS: possible stack overflow";
1875       break;
1876 #endif
1877 #elif (_WRS_VXWORKS_MAJOR >= 6)
1878     case SIGILL:
1879       exception = &constraint_error;
1880       msg = "SIGILL";
1881       break;
1882 #ifdef __RTP__
1883     /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
1884        since stack checking uses the probing mechanism.  */
1885     case SIGSEGV:
1886       exception = &storage_error;
1887       msg = "SIGSEGV: possible stack overflow";
1888       break;
1889     case SIGBUS:
1890       exception = &program_error;
1891       msg = "SIGBUS";
1892       break;
1893 #else
1894       /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
1895     case SIGSEGV:
1896       exception = &storage_error;
1897       msg = "SIGSEGV";
1898       break;
1899     case SIGBUS:
1900       exception = &storage_error;
1901       msg = "SIGBUS: possible stack overflow";
1902       break;
1903 #endif
1904 #else
1905     /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
1906        since stack checking uses the stack limit mechanism.  */
1907     case SIGILL:
1908       exception = &storage_error;
1909       msg = "SIGILL: possible stack overflow";
1910       break;
1911     case SIGSEGV:
1912       exception = &storage_error;
1913       msg = "SIGSEGV";
1914       break;
1915     case SIGBUS:
1916       exception = &program_error;
1917       msg = "SIGBUS";
1918       break;
1919 #endif
1920     default:
1921       exception = &program_error;
1922       msg = "unhandled signal";
1923     }
1924 
1925   if (__gnat_reset_guard_page (sig))
1926     {
1927       /* Set the exception message: we know for sure that we have a
1928          stack overflow here */
1929       exception = &storage_error;
1930 
1931       switch (sig)
1932         {
1933         case SIGSEGV:
1934           msg = "SIGSEGV: stack overflow";
1935           break;
1936         case SIGBUS:
1937           msg = "SIGBUS: stack overflow";
1938           break;
1939         case SIGILL:
1940           msg = "SIGILL: stack overflow";
1941           break;
1942         }
1943     }
1944   __gnat_clear_exception_count ();
1945   Raise_From_Signal_Handler (exception, msg);
1946 }
1947 
1948 #if defined (ARMEL) && (_WRS_VXWORKS_MAJOR >= 7) && !defined (__aarch64__)
1949 
1950 /* ARM-vx7 case with arm unwinding exceptions */
1951 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1952 
1953 #include <arch/../regs.h>
1954 #ifndef __RTP__
1955 #include <sigLib.h>
1956 #else
1957 #include <signal.h>
1958 #include <regs.h>
1959 #include <ucontext.h>
1960 #endif /* __RTP__ */
1961 
1962 void
__gnat_adjust_context_for_raise(int signo ATTRIBUTE_UNUSED,void * sc ATTRIBUTE_UNUSED)1963 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
1964 				 void *sc ATTRIBUTE_UNUSED)
1965 {
1966   /* In case of ARM exceptions, the registers context have the PC pointing
1967      to the instruction that raised the signal.  However the unwinder expects
1968      the instruction to be in the range ]PC,PC+1].  */
1969   uintptr_t *pc_addr;
1970 #ifdef __RTP__
1971   mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext;
1972   pc_addr = (uintptr_t*)&mcontext->regs.pc;
1973 #else
1974   struct sigcontext * sctx = (struct sigcontext *) sc;
1975   pc_addr = (uintptr_t*)&sctx->sc_pregs->pc;
1976 #endif
1977   /* ARM Bump has to be an even number because of odd/even architecture.  */
1978   *pc_addr += 2;
1979 }
1980 #endif /* ARMEL && _WRS_VXWORKS_MAJOR >= 7 */
1981 
1982 /* Tasking and Non-tasking signal handler.  Map SIGnal to Ada exception
1983    propagation after the required low level adjustments.  */
1984 
1985 static void
__gnat_error_handler(int sig,siginfo_t * si,void * sc)1986 __gnat_error_handler (int sig, siginfo_t *si, void *sc)
1987 {
1988   sigset_t mask;
1989 
1990   /* VxWorks on e500v2 clears the SPE bit of the MSR when entering CPU
1991      exception state. To allow the handler and exception to work properly
1992      when they contain SPE instructions, we need to set it back before doing
1993      anything else.
1994      This mechanism is only need in kernel mode. */
1995 #if !(defined (__RTP__) || defined (VTHREADS)) && ((CPU == PPCE500V2) || (CPU == PPC85XX))
1996   register unsigned msr;
1997   /* Read the MSR value */
1998   asm volatile ("mfmsr %0" : "=r" (msr));
1999   /* Force the SPE bit if not set.  */
2000   if ((msr & 0x02000000) == 0)
2001     {
2002       msr |= 0x02000000;
2003       /* Store to MSR */
2004       asm volatile ("mtmsr %0" : : "r" (msr));
2005     }
2006 #endif
2007 
2008   /* VxWorks will always mask out the signal during the signal handler and
2009      will reenable it on a longjmp.  GNAT does not generate a longjmp to
2010      return from a signal handler so the signal will still be masked unless
2011      we unmask it.  */
2012   sigprocmask (SIG_SETMASK, NULL, &mask);
2013   sigdelset (&mask, sig);
2014   sigprocmask (SIG_SETMASK, &mask, NULL);
2015 
2016 #if defined (__ARMEL__) || defined (__PPC__) || defined (__i386__) || defined (__x86_64__) || defined (__aarch64__)
2017   /* On certain targets, kernel mode, we process signals through a Call Frame
2018      Info trampoline, voiding the need for myriads of fallback_frame_state
2019      variants in the ZCX runtime.  We have no simple way to distinguish ZCX
2020      from SJLJ here, so we do this for SJLJ as well even though this is not
2021      necessary.  This only incurs a few extra instructions and a tiny
2022      amount of extra stack usage.  */
2023 
2024 #ifdef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2025   /* We need to sometimes to adjust the PC in case of signals so that it
2026      doesn't reference the exception that actually raised the signal but the
2027      instruction before it.  */
2028   __gnat_adjust_context_for_raise (sig, sc);
2029 #endif
2030 
2031   __gnat_sigtramp (sig, (void *)si, (void *)sc,
2032                    (__sigtramphandler_t *)&__gnat_map_signal);
2033 
2034 #else
2035   __gnat_map_signal (sig, si, sc);
2036 #endif
2037 }
2038 
2039 #if defined(__leon__) && defined(_WRS_KERNEL)
2040 /* For LEON VxWorks we need to install a trap handler for stack overflow */
2041 
2042 extern void excEnt (void);
2043 /* VxWorks exception handler entry */
2044 
2045 struct trap_entry {
2046    unsigned long inst_first;
2047    unsigned long inst_second;
2048    unsigned long inst_third;
2049    unsigned long inst_fourth;
2050 };
2051 /* Four instructions representing entries in the trap table */
2052 
2053 struct trap_entry *trap_0_entry;
2054 /* We will set the location of the entry for software trap 0 in the trap
2055    table. */
2056 #endif
2057 
2058 void
__gnat_install_handler(void)2059 __gnat_install_handler (void)
2060 {
2061   struct sigaction act;
2062 
2063   /* Setup signal handler to map synchronous signals to appropriate
2064      exceptions.  Make sure that the handler isn't interrupted by another
2065      signal that might cause a scheduling event!  */
2066 
2067   act.sa_sigaction = __gnat_error_handler;
2068   act.sa_flags = SA_SIGINFO | SA_ONSTACK;
2069   sigemptyset (&act.sa_mask);
2070 
2071   /* For VxWorks, install all signal handlers, since pragma Interrupt_State
2072      applies to vectored hardware interrupts, not signals.  */
2073   sigaction (SIGFPE,  &act, NULL);
2074   sigaction (SIGILL,  &act, NULL);
2075   sigaction (SIGSEGV, &act, NULL);
2076   sigaction (SIGBUS,  &act, NULL);
2077 
2078 #if defined(__leon__) && defined(_WRS_KERNEL)
2079   /* Specific to the LEON VxWorks kernel run-time library */
2080 
2081   /* For stack checking the compiler triggers a software trap 0 (ta 0) in
2082      case of overflow (we use the stack limit mechanism). We need to install
2083      the trap handler here for this software trap (the OS does not handle
2084      it) as if it were a data_access_exception (trap 9). We do the same as
2085      if we put in the trap table a VXSPARC_BAD_TRAP(9). Software trap 0 is
2086      located at vector 0x80, and each entry takes 4 words. */
2087 
2088   trap_0_entry = (struct trap_entry *)(intVecBaseGet () + 0x80 * 4);
2089 
2090   /* mov 0x9, %l7 */
2091 
2092   trap_0_entry->inst_first = 0xae102000 + 9;
2093 
2094   /* sethi %hi(excEnt), %l6 */
2095 
2096   /* The 22 most significant bits of excEnt are obtained shifting 10 times
2097      to the right.  */
2098 
2099   trap_0_entry->inst_second = 0x2d000000 + ((unsigned long)excEnt >> 10);
2100 
2101   /* jmp %l6+%lo(excEnt) */
2102 
2103   /* The 10 least significant bits of excEnt are obtained by masking */
2104 
2105   trap_0_entry->inst_third = 0x81c5a000 + ((unsigned long)excEnt & 0x3ff);
2106 
2107   /* rd %psr, %l0 */
2108 
2109   trap_0_entry->inst_fourth = 0xa1480000;
2110 #endif
2111 
2112 #ifdef __HANDLE_VXSIM_SC
2113   /*  By experiment, found that sysModel () returns the following string
2114       prefix for vxsim when running on Linux and Windows.  */
2115   {
2116     char *model = sysModel ();
2117     if ((strncmp (model, "Linux", 5) == 0)
2118         || (strncmp (model, "Windows", 7) == 0)
2119         || (strncmp (model, "SIMLINUX", 8) == 0) /* vx7 */
2120         || (strncmp (model, "SIMNT", 5) == 0)) /* ditto */
2121       __gnat_set_is_vxsim (TRUE);
2122   }
2123 #endif
2124 
2125   __gnat_handler_installed = 1;
2126 }
2127 
2128 #define HAVE_GNAT_INIT_FLOAT
2129 
2130 void
__gnat_init_float(void)2131 __gnat_init_float (void)
2132 {
2133   /* Disable overflow/underflow exceptions on the PPC processor, needed
2134      to get correct Ada semantics.  Note that for AE653 vThreads, the HW
2135      overflow settings are an OS configuration issue.  The instructions
2136      below have no effect.  */
2137 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && (!defined (VTHREADS) || defined (__VXWORKSMILS__))
2138 #if defined (__SPE__)
2139   {
2140     /* For e500v2, do nothing and leave the responsibility to install the
2141        handler and enable the exceptions to the BSP.  */
2142   }
2143 #else
2144   asm ("mtfsb0 25");
2145   asm ("mtfsb0 26");
2146 #endif
2147 #endif
2148 
2149 #if (defined (__i386__) || defined (__x86_64__)) && !defined (VTHREADS)
2150   /* This is used to properly initialize the FPU on an x86 for each
2151      process thread. */
2152   asm ("finit");
2153 #endif
2154 
2155   /* Similarly for SPARC64.  Achieved by masking bits in the Trap Enable Mask
2156      field of the Floating-point Status Register (see the SPARC Architecture
2157      Manual Version 9, p 48).  */
2158 #if defined (sparc64)
2159 
2160 #define FSR_TEM_NVM (1 << 27)  /* Invalid operand  */
2161 #define FSR_TEM_OFM (1 << 26)  /* Overflow  */
2162 #define FSR_TEM_UFM (1 << 25)  /* Underflow  */
2163 #define FSR_TEM_DZM (1 << 24)  /* Division by Zero  */
2164 #define FSR_TEM_NXM (1 << 23)  /* Inexact result  */
2165   {
2166     unsigned int fsr;
2167 
2168     __asm__("st %%fsr, %0" : "=m" (fsr));
2169     fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
2170     __asm__("ld %0, %%fsr" : : "m" (fsr));
2171   }
2172 #endif
2173 }
2174 
2175 /* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
2176    (if not null) when a new task is created.  It is initialized by
2177    System.Stack_Checking.Operations.Initialize_Stack_Limit.
2178    The use of a hook avoids to drag stack checking subprograms if stack
2179    checking is not used.  */
2180 void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
2181 
2182 /******************/
2183 /* NetBSD Section */
2184 /******************/
2185 
2186 #elif defined(__NetBSD__)
2187 
2188 #include <signal.h>
2189 #include <unistd.h>
2190 
2191 static void
__gnat_error_handler(int sig)2192 __gnat_error_handler (int sig)
2193 {
2194   struct Exception_Data *exception;
2195   const char *msg;
2196 
2197   switch(sig)
2198   {
2199     case SIGFPE:
2200       exception = &constraint_error;
2201       msg = "SIGFPE";
2202       break;
2203     case SIGILL:
2204       exception = &constraint_error;
2205       msg = "SIGILL";
2206       break;
2207     case SIGSEGV:
2208       exception = &storage_error;
2209       msg = "stack overflow or erroneous memory access";
2210       break;
2211     case SIGBUS:
2212       exception = &constraint_error;
2213       msg = "SIGBUS";
2214       break;
2215     default:
2216       exception = &program_error;
2217       msg = "unhandled signal";
2218     }
2219 
2220     Raise_From_Signal_Handler (exception, msg);
2221 }
2222 
2223 void
__gnat_install_handler(void)2224 __gnat_install_handler (void)
2225 {
2226   struct sigaction act;
2227 
2228   act.sa_handler = __gnat_error_handler;
2229   act.sa_flags = SA_NODEFER | SA_RESTART;
2230   sigemptyset (&act.sa_mask);
2231 
2232   /* Do not install handlers if interrupt state is "System".  */
2233   if (__gnat_get_interrupt_state (SIGFPE) != 's')
2234     sigaction (SIGFPE,  &act, NULL);
2235   if (__gnat_get_interrupt_state (SIGILL) != 's')
2236     sigaction (SIGILL,  &act, NULL);
2237   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2238     sigaction (SIGSEGV, &act, NULL);
2239   if (__gnat_get_interrupt_state (SIGBUS) != 's')
2240     sigaction (SIGBUS,  &act, NULL);
2241 
2242   __gnat_handler_installed = 1;
2243 }
2244 
2245 /*******************/
2246 /* OpenBSD Section */
2247 /*******************/
2248 
2249 #elif defined(__OpenBSD__)
2250 
2251 #include <signal.h>
2252 #include <unistd.h>
2253 
2254 static void
__gnat_error_handler(int sig)2255 __gnat_error_handler (int sig)
2256 {
2257   struct Exception_Data *exception;
2258   const char *msg;
2259 
2260   switch(sig)
2261   {
2262     case SIGFPE:
2263       exception = &constraint_error;
2264       msg = "SIGFPE";
2265       break;
2266     case SIGILL:
2267       exception = &constraint_error;
2268       msg = "SIGILL";
2269       break;
2270     case SIGSEGV:
2271       exception = &storage_error;
2272       msg = "stack overflow or erroneous memory access";
2273       break;
2274     case SIGBUS:
2275       exception = &constraint_error;
2276       msg = "SIGBUS";
2277       break;
2278     default:
2279       exception = &program_error;
2280       msg = "unhandled signal";
2281     }
2282 
2283     Raise_From_Signal_Handler (exception, msg);
2284 }
2285 
2286 void
__gnat_install_handler(void)2287 __gnat_install_handler (void)
2288 {
2289   struct sigaction act;
2290 
2291   act.sa_handler = __gnat_error_handler;
2292   act.sa_flags = SA_NODEFER | SA_RESTART;
2293   sigemptyset (&act.sa_mask);
2294 
2295   /* Do not install handlers if interrupt state is "System" */
2296   if (__gnat_get_interrupt_state (SIGFPE) != 's')
2297     sigaction (SIGFPE,  &act, NULL);
2298   if (__gnat_get_interrupt_state (SIGILL) != 's')
2299     sigaction (SIGILL,  &act, NULL);
2300   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2301     sigaction (SIGSEGV, &act, NULL);
2302   if (__gnat_get_interrupt_state (SIGBUS) != 's')
2303     sigaction (SIGBUS,  &act, NULL);
2304 
2305   __gnat_handler_installed = 1;
2306 }
2307 
2308 /******************/
2309 /* Darwin Section */
2310 /******************/
2311 
2312 #elif defined(__APPLE__)
2313 
2314 #include <TargetConditionals.h>
2315 #include <signal.h>
2316 #include <stdlib.h>
2317 #include <sys/syscall.h>
2318 #include <sys/sysctl.h>
2319 
2320 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
2321 char __gnat_alternate_stack[32 * 1024]; /* 1 * MINSIGSTKSZ */
2322 
2323 /* Defined in xnu unix_signal.c.
2324    Tell the kernel to re-use alt stack when delivering a signal.  */
2325 #define	UC_RESET_ALT_STACK	0x80000000
2326 
2327 #if !(defined (__arm__) || defined (__arm64__) || TARGET_IPHONE_SIMULATOR)
2328 #include <mach/mach_vm.h>
2329 #include <mach/mach_init.h>
2330 #include <mach/vm_statistics.h>
2331 #endif
2332 
2333 #ifdef __arm64__
2334 #include <sys/ucontext.h>
2335 #include "sigtramp.h"
2336 #endif
2337 
2338 /* Return true if ADDR is within a stack guard area.  */
2339 static int
__gnat_is_stack_guard(mach_vm_address_t addr)2340 __gnat_is_stack_guard (mach_vm_address_t addr)
2341 {
2342 #if !(defined (__arm__) || defined (__arm64__) || TARGET_IPHONE_SIMULATOR)
2343   kern_return_t kret;
2344   vm_region_submap_info_data_64_t info;
2345   mach_vm_address_t start;
2346   mach_vm_size_t size;
2347   natural_t depth;
2348   mach_msg_type_number_t count;
2349 
2350   count = VM_REGION_SUBMAP_INFO_COUNT_64;
2351   start = addr;
2352   size = -1;
2353   depth = 9999;
2354   kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
2355 				 (vm_region_recurse_info_t) &info, &count);
2356   if (kret == KERN_SUCCESS
2357       && addr >= start && addr < (start + size)
2358       && info.protection == VM_PROT_NONE
2359       && info.user_tag == VM_MEMORY_STACK)
2360     return 1;
2361   return 0;
2362 #else
2363   /* Pagezero for arm.  */
2364   return addr >= 4096;
2365 #endif
2366 }
2367 
2368 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2369 
2370 #if defined (__x86_64__)
2371 static int
__darwin_major_version(void)2372 __darwin_major_version (void)
2373 {
2374   static int cache = -1;
2375   if (cache < 0)
2376     {
2377       int mib[2] = {CTL_KERN, KERN_OSRELEASE};
2378       size_t len;
2379 
2380       /* Find out how big the buffer needs to be (and set cache to 0
2381          on failure).  */
2382       if (sysctl (mib, 2, NULL, &len, NULL, 0) == 0)
2383         {
2384           char release[len];
2385           sysctl (mib, 2, release, &len, NULL, 0);
2386           /* Darwin releases are of the form L.M.N where L is the major
2387              version, so strtol will return L.  */
2388           cache = (int) strtol (release, NULL, 10);
2389         }
2390       else
2391         {
2392           cache = 0;
2393         }
2394     }
2395   return cache;
2396 }
2397 #endif
2398 
2399 void
__gnat_adjust_context_for_raise(int signo ATTRIBUTE_UNUSED,void * ucontext ATTRIBUTE_UNUSED)2400 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2401 				 void *ucontext ATTRIBUTE_UNUSED)
2402 {
2403 #if defined (__x86_64__)
2404   if (__darwin_major_version () < 12)
2405     {
2406       /* Work around radar #10302855, where the unwinders (libunwind or
2407 	 libgcc_s depending on the system revision) and the DWARF unwind
2408 	 data for sigtramp have different ideas about register numbering,
2409 	 causing rbx and rdx to be transposed.  */
2410       ucontext_t *uc = (ucontext_t *)ucontext;
2411       unsigned long t = uc->uc_mcontext->__ss.__rbx;
2412 
2413       uc->uc_mcontext->__ss.__rbx = uc->uc_mcontext->__ss.__rdx;
2414       uc->uc_mcontext->__ss.__rdx = t;
2415     }
2416 #elif defined(__arm64__)
2417   /* Even though the CFI is marked as a signal frame, we need this.  */
2418   ucontext_t *uc = (ucontext_t *)ucontext;
2419   uc->uc_mcontext->__ss.__pc++;
2420 #endif
2421 }
2422 
2423 static void
__gnat_map_signal(int sig,siginfo_t * si,void * mcontext ATTRIBUTE_UNUSED)2424 __gnat_map_signal (int sig, siginfo_t *si, void *mcontext ATTRIBUTE_UNUSED)
2425 {
2426   struct Exception_Data *exception;
2427   const char *msg;
2428 
2429   switch (sig)
2430     {
2431     case SIGSEGV:
2432     case SIGBUS:
2433       if (__gnat_is_stack_guard ((unsigned long)si->si_addr))
2434 	{
2435 #ifdef __arm64__
2436 	  /* ??? This is a kludge to make stack checking work.  The problem is
2437 	     that the trampoline doesn't restore LR and, consequently, doesn't
2438 	     make it possible to unwind past an interrupted frame which hasn"t
2439 	     saved LR on the stack yet.  Therefore, for probes in the prologue
2440 	     (32-bit probes as opposed to standard 64-bit probes), we make the
2441 	     unwinder skip the not-yet-established frame altogether.  */
2442 	  mcontext_t mc = (mcontext_t)mcontext;
2443 	  if (!(*(unsigned int *)(mc->__ss.__pc-1) & ((unsigned int)1 << 30)))
2444 	    mc->__ss.__pc = mc->__ss.__lr;
2445 #endif
2446 	  exception = &storage_error;
2447 	  msg = "stack overflow";
2448 	}
2449       else
2450 	{
2451 	  exception = &constraint_error;
2452 	  msg = "erroneous memory access";
2453 	}
2454 
2455       /* Reset the use of alt stack, so that the alt stack will be used
2456 	 for the next signal delivery.
2457 	 The stack can't be used in case of stack checking.  */
2458       syscall (SYS_sigreturn, NULL, UC_RESET_ALT_STACK);
2459       break;
2460 
2461     case SIGFPE:
2462       exception = &constraint_error;
2463       msg = "SIGFPE";
2464       break;
2465 
2466     default:
2467       exception = &program_error;
2468       msg = "unhandled signal";
2469     }
2470 
2471   Raise_From_Signal_Handler (exception, msg);
2472 }
2473 
2474 static void
__gnat_error_handler(int sig,siginfo_t * si,void * ucontext)2475 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
2476 {
2477   __gnat_adjust_context_for_raise (sig, ucontext);
2478 
2479   /* The Darwin libc comes with a signal trampoline, except for ARM64.  */
2480 #ifdef __arm64__
2481   __gnat_sigtramp (sig, (void *)si, ucontext,
2482 		   (__sigtramphandler_t *)&__gnat_map_signal);
2483 #else
2484   __gnat_map_signal (sig, si, ucontext);
2485 #endif
2486 }
2487 
2488 void
__gnat_install_handler(void)2489 __gnat_install_handler (void)
2490 {
2491   struct sigaction act;
2492 
2493   /* Set up signal handler to map synchronous signals to appropriate
2494      exceptions.  Make sure that the handler isn't interrupted by another
2495      signal that might cause a scheduling event!  Also setup an alternate
2496      stack region for the handler execution so that stack overflows can be
2497      handled properly, avoiding a SEGV generation from stack usage by the
2498      handler itself (and it is required by Darwin).  */
2499 
2500   stack_t stack;
2501   stack.ss_sp = __gnat_alternate_stack;
2502   stack.ss_size = sizeof (__gnat_alternate_stack);
2503   stack.ss_flags = 0;
2504   sigaltstack (&stack, NULL);
2505 
2506   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2507   act.sa_sigaction = __gnat_error_handler;
2508   sigemptyset (&act.sa_mask);
2509 
2510   /* Do not install handlers if interrupt state is "System".  */
2511   if (__gnat_get_interrupt_state (SIGABRT) != 's')
2512     sigaction (SIGABRT, &act, NULL);
2513   if (__gnat_get_interrupt_state (SIGFPE) != 's')
2514     sigaction (SIGFPE,  &act, NULL);
2515   if (__gnat_get_interrupt_state (SIGILL) != 's')
2516     sigaction (SIGILL,  &act, NULL);
2517 
2518   act.sa_flags |= SA_ONSTACK;
2519   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2520     sigaction (SIGSEGV, &act, NULL);
2521   if (__gnat_get_interrupt_state (SIGBUS) != 's')
2522     sigaction (SIGBUS,  &act, NULL);
2523 
2524   __gnat_handler_installed = 1;
2525 }
2526 
2527 #elif defined(__QNX__)
2528 
2529 /***************/
2530 /* QNX Section */
2531 /***************/
2532 
2533 #include <signal.h>
2534 #include <unistd.h>
2535 #include <string.h>
2536 #include "sigtramp.h"
2537 
2538 void
__gnat_map_signal(int sig,siginfo_t * si ATTRIBUTE_UNUSED,void * mcontext ATTRIBUTE_UNUSED)2539 __gnat_map_signal (int sig,
2540 		   siginfo_t *si ATTRIBUTE_UNUSED,
2541 		   void *mcontext ATTRIBUTE_UNUSED)
2542 {
2543   struct Exception_Data *exception;
2544   const char *msg;
2545 
2546   switch(sig)
2547   {
2548     case SIGFPE:
2549       exception = &constraint_error;
2550       msg = "SIGFPE";
2551       break;
2552     case SIGILL:
2553       exception = &constraint_error;
2554       msg = "SIGILL";
2555       break;
2556     case SIGSEGV:
2557       exception = &storage_error;
2558       msg = "stack overflow or erroneous memory access";
2559       break;
2560     case SIGBUS:
2561       exception = &constraint_error;
2562       msg = "SIGBUS";
2563       break;
2564     default:
2565       exception = &program_error;
2566       msg = "unhandled signal";
2567     }
2568 
2569     Raise_From_Signal_Handler (exception, msg);
2570 }
2571 
2572 static void
__gnat_error_handler(int sig,siginfo_t * si,void * ucontext)2573 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
2574 {
2575   __gnat_sigtramp (sig, (void *) si, (void *) ucontext,
2576 		   (__sigtramphandler_t *)&__gnat_map_signal);
2577 }
2578 
2579 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
2580 /* sigaltstack is currently not supported by QNX7 */
2581 char __gnat_alternate_stack[0];
2582 
2583 void
__gnat_install_handler(void)2584 __gnat_install_handler (void)
2585 {
2586   struct sigaction act;
2587   int err;
2588 
2589   act.sa_handler = __gnat_error_handler;
2590   act.sa_flags = SA_NODEFER | SA_SIGINFO;
2591   sigemptyset (&act.sa_mask);
2592 
2593   /* Do not install handlers if interrupt state is "System" */
2594   if (__gnat_get_interrupt_state (SIGFPE) != 's') {
2595     err = sigaction (SIGFPE,  &act, NULL);
2596     if (err == -1) {
2597       err = errno;
2598       perror ("error while attaching SIGFPE");
2599       perror (strerror (err));
2600     }
2601   }
2602   if (__gnat_get_interrupt_state (SIGILL) != 's') {
2603     sigaction (SIGILL,  &act, NULL);
2604     if (err == -1) {
2605       err = errno;
2606       perror ("error while attaching SIGFPE");
2607       perror (strerror (err));
2608     }
2609   }
2610   if (__gnat_get_interrupt_state (SIGSEGV) != 's') {
2611     sigaction (SIGSEGV, &act, NULL);
2612     if (err == -1) {
2613       err = errno;
2614       perror ("error while attaching SIGFPE");
2615       perror (strerror (err));
2616     }
2617   }
2618   if (__gnat_get_interrupt_state (SIGBUS) != 's') {
2619     sigaction (SIGBUS,  &act, NULL);
2620     if (err == -1) {
2621       err = errno;
2622       perror ("error while attaching SIGFPE");
2623       perror (strerror (err));
2624     }
2625   }
2626   __gnat_handler_installed = 1;
2627 }
2628 
2629 #elif defined (__DJGPP__)
2630 
2631 void
__gnat_install_handler()2632 __gnat_install_handler ()
2633 {
2634   __gnat_handler_installed = 1;
2635 }
2636 
2637 #elif defined(__ANDROID__)
2638 
2639 /*******************/
2640 /* Android Section */
2641 /*******************/
2642 
2643 #include <signal.h>
2644 #include <sys/ucontext.h>
2645 #include "sigtramp.h"
2646 
2647 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2648 
2649 void
__gnat_adjust_context_for_raise(int signo ATTRIBUTE_UNUSED,void * ucontext)2650 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
2651 {
2652   mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
2653 
2654   /* ARM Bump has to be an even number because of odd/even architecture.  */
2655   ((mcontext_t *) mcontext)->arm_pc += 2;
2656 }
2657 
2658 static void
__gnat_map_signal(int sig,siginfo_t * si ATTRIBUTE_UNUSED,void * mcontext ATTRIBUTE_UNUSED)2659 __gnat_map_signal (int sig,
2660 		   siginfo_t *si ATTRIBUTE_UNUSED,
2661 		   void *mcontext ATTRIBUTE_UNUSED)
2662 {
2663   struct Exception_Data *exception;
2664   const char *msg;
2665 
2666   switch (sig)
2667     {
2668     case SIGSEGV:
2669       exception = &storage_error;
2670       msg = "stack overflow or erroneous memory access";
2671       break;
2672 
2673     case SIGBUS:
2674       exception = &constraint_error;
2675       msg = "SIGBUS";
2676       break;
2677 
2678     case SIGFPE:
2679       exception = &constraint_error;
2680       msg = "SIGFPE";
2681       break;
2682 
2683     default:
2684       exception = &program_error;
2685       msg = "unhandled signal";
2686     }
2687 
2688   Raise_From_Signal_Handler (exception, msg);
2689 }
2690 
2691 static void
__gnat_error_handler(int sig,siginfo_t * si,void * ucontext)2692 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
2693 {
2694   __gnat_adjust_context_for_raise (sig, ucontext);
2695 
2696   __gnat_sigtramp (sig, (void *) si, (void *) ucontext,
2697 		   (__sigtramphandler_t *)&__gnat_map_signal);
2698 }
2699 
2700 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
2701 char __gnat_alternate_stack[16 * 1024];
2702 
2703 void
__gnat_install_handler(void)2704 __gnat_install_handler (void)
2705 {
2706   struct sigaction act;
2707 
2708   /* Set up signal handler to map synchronous signals to appropriate
2709      exceptions.  Make sure that the handler isn't interrupted by another
2710      signal that might cause a scheduling event!  Also setup an alternate
2711      stack region for the handler execution so that stack overflows can be
2712      handled properly, avoiding a SEGV generation from stack usage by the
2713      handler itself.  */
2714 
2715   stack_t stack;
2716   stack.ss_sp = __gnat_alternate_stack;
2717   stack.ss_size = sizeof (__gnat_alternate_stack);
2718   stack.ss_flags = 0;
2719   sigaltstack (&stack, NULL);
2720 
2721   act.sa_sigaction = __gnat_error_handler;
2722   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2723   sigemptyset (&act.sa_mask);
2724 
2725   sigaction (SIGABRT, &act, NULL);
2726   sigaction (SIGFPE,  &act, NULL);
2727   sigaction (SIGILL,  &act, NULL);
2728   sigaction (SIGBUS,  &act, NULL);
2729   act.sa_flags |= SA_ONSTACK;
2730   sigaction (SIGSEGV, &act, NULL);
2731 
2732   __gnat_handler_installed = 1;
2733 }
2734 
2735 #else
2736 
2737 /* For all other versions of GNAT, the handler does nothing.  */
2738 
2739 /*******************/
2740 /* Default Section */
2741 /*******************/
2742 
2743 void
__gnat_install_handler(void)2744 __gnat_install_handler (void)
2745 {
2746   __gnat_handler_installed = 1;
2747 }
2748 
2749 #endif
2750 
2751 /*********************/
2752 /* __gnat_init_float */
2753 /*********************/
2754 
2755 /* This routine is called as each process thread is created, for possible
2756    initialization of the FP processor.  This version is used under INTERIX
2757    and WIN32.  */
2758 
2759 #if defined (_WIN32) || defined (__INTERIX) \
2760   || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
2761   || defined (__OpenBSD__) || defined (__DragonFly__) || defined(__QNX__)
2762 
2763 #define HAVE_GNAT_INIT_FLOAT
2764 
2765 void
__gnat_init_float(void)2766 __gnat_init_float (void)
2767 {
2768 #if defined (__i386__) || defined (__x86_64__)
2769 
2770   /* This is used to properly initialize the FPU on an x86 for each
2771      process thread.  */
2772 
2773   asm ("finit");
2774 
2775 #endif  /* Defined __i386__ */
2776 }
2777 #endif
2778 
2779 #ifndef HAVE_GNAT_INIT_FLOAT
2780 
2781 /* All targets without a specific __gnat_init_float will use an empty one.  */
2782 void
__gnat_init_float(void)2783 __gnat_init_float (void)
2784 {
2785 }
2786 #endif
2787 
2788 /***********************************/
2789 /* __gnat_adjust_context_for_raise */
2790 /***********************************/
2791 
2792 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2793 
2794 /* All targets without a specific version will use an empty one.  */
2795 
2796 /* Given UCONTEXT a pointer to a context structure received by a signal
2797    handler for SIGNO, perform the necessary adjustments to let the handler
2798    raise an exception.  Calls to this routine are not conditioned by the
2799    propagation scheme in use.  */
2800 
2801 void
__gnat_adjust_context_for_raise(int signo ATTRIBUTE_UNUSED,void * ucontext ATTRIBUTE_UNUSED)2802 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2803 				 void *ucontext ATTRIBUTE_UNUSED)
2804 {
2805   /* We used to compensate here for the raised from call vs raised from signal
2806      exception discrepancy with the GCC ZCX scheme, but this now can be dealt
2807      with generically in the unwinder (see GCC PR other/26208).  This however
2808      requires the use of the _Unwind_GetIPInfo routine in raise-gcc.c, which
2809      is predicated on the definition of HAVE_GETIPINFO at compile time.  Only
2810      the VMS ports still do the compensation described in the few lines below.
2811 
2812      *** Call vs signal exception discrepancy with GCC ZCX scheme ***
2813 
2814      The GCC unwinder expects to be dealing with call return addresses, since
2815      this is the "nominal" case of what we retrieve while unwinding a regular
2816      call chain.
2817 
2818      To evaluate if a handler applies at some point identified by a return
2819      address, the propagation engine needs to determine what region the
2820      corresponding call instruction pertains to.  Because the return address
2821      may not be attached to the same region as the call, the unwinder always
2822      subtracts "some" amount from a return address to search the region
2823      tables, amount chosen to ensure that the resulting address is inside the
2824      call instruction.
2825 
2826      When we raise an exception from a signal handler, e.g. to transform a
2827      SIGSEGV into Storage_Error, things need to appear as if the signal
2828      handler had been "called" by the instruction which triggered the signal,
2829      so that exception handlers that apply there are considered.  What the
2830      unwinder will retrieve as the return address from the signal handler is
2831      what it will find as the faulting instruction address in the signal
2832      context pushed by the kernel.  Leaving this address untouched looses, if
2833      the triggering instruction happens to be the very first of a region, as
2834      the later adjustments performed by the unwinder would yield an address
2835      outside that region.  We need to compensate for the unwinder adjustments
2836      at some point, and this is what this routine is expected to do.
2837 
2838      signo is passed because on some targets for some signals the PC in
2839      context points to the instruction after the faulting one, in which case
2840      the unwinder adjustment is still desired.  */
2841 }
2842 
2843 #endif
2844 
2845 #ifdef __cplusplus
2846 }
2847 #endif
2848