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