1 /****************************************************************************
2  *                                                                          *
3  *                         GNAT COMPILER COMPONENTS                         *
4  *                                                                          *
5  *                                 I N I T                                  *
6  *                                                                          *
7  *                          C Implementation File                           *
8  *                                                                          *
9  *          Copyright (C) 1992-2003 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 2,  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.  See the GNU General Public License *
17  * for  more details.  You should have  received  a copy of the GNU General *
18  * Public License  distributed with GNAT;  see file COPYING.  If not, write *
19  * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
20  * MA 02111-1307, USA.                                                      *
21  *                                                                          *
22  * As a  special  exception,  if you  link  this file  with other  files to *
23  * produce an executable,  this file does not by itself cause the resulting *
24  * executable to be covered by the GNU General Public License. This except- *
25  * ion does not  however invalidate  any other reasons  why the  executable *
26  * file might be covered by the  GNU Public License.                        *
27  *                                                                          *
28  * GNAT was originally developed  by the GNAT team at  New York University. *
29  * Extensive contributions were provided by Ada Core Technologies Inc.      *
30  *                                                                          *
31  ****************************************************************************/
32 
33 /*  This unit contains initialization circuits that are system dependent. A
34     major part of the functionality involved involves stack overflow checking.
35     The GCC backend generates probe instructions to test for stack overflow.
36     For details on the exact approach used to generate these probes, see the
37     "Using and Porting GCC" manual, in particular the "Stack Checking" section
38     and the subsection "Specifying How Stack Checking is Done". The handlers
39     installed by this file are used to handle resulting signals that come
40     from these probes failing (i.e. touching protected pages) */
41 
42 /* The following include is here to meet the published VxWorks requirement
43    that the __vxworks header appear before any other include. */
44 #ifdef __vxworks
45 #include "vxWorks.h"
46 #endif
47 
48 #ifdef IN_RTS
49 #include "tconfig.h"
50 #include "tsystem.h"
51 #include <sys/stat.h>
52 
53 /* We don't have libiberty, so us malloc.  */
54 #define xmalloc(S) malloc (S)
55 #else
56 #include "config.h"
57 #include "system.h"
58 #endif
59 
60 #include "adaint.h"
61 #include "raise.h"
62 
63 extern void __gnat_raise_program_error (const char *, int);
64 
65 /* Addresses of exception data blocks for predefined exceptions. */
66 extern struct Exception_Data constraint_error;
67 extern struct Exception_Data numeric_error;
68 extern struct Exception_Data program_error;
69 extern struct Exception_Data storage_error;
70 extern struct Exception_Data tasking_error;
71 extern struct Exception_Data _abort_signal;
72 
73 #define Lock_Task system__soft_links__lock_task
74 extern void (*Lock_Task) (void);
75 
76 #define Unlock_Task system__soft_links__unlock_task
77 extern void (*Unlock_Task) (void);
78 
79 #define Get_Machine_State_Addr \
80                       system__soft_links__get_machine_state_addr
81 extern struct Machine_State *(*Get_Machine_State_Addr) (void);
82 
83 #define Check_Abort_Status     \
84                       system__soft_links__check_abort_status
85 extern int (*Check_Abort_Status) (void);
86 
87 #define Raise_From_Signal_Handler \
88                       ada__exceptions__raise_from_signal_handler
89 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
90 
91 #define Propagate_Signal_Exception \
92                       __gnat_propagate_sig_exc
93 extern void Propagate_Signal_Exception (struct Machine_State *,
94                                         struct Exception_Data *,
95                                         const char *);
96 
97 /* Copies of global values computed by the binder */
98 int   __gl_main_priority            = -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_restrictions             = 0;
105 char *__gl_interrupt_states         = 0;
106 int   __gl_num_interrupt_states     = 0;
107 int   __gl_unreserve_all_interrupts = 0;
108 int   __gl_exception_tracebacks     = 0;
109 int   __gl_zero_cost_exceptions     = 0;
110 
111 /* Indication of whether synchronous signal handler has already been
112    installed by a previous call to adainit */
113 int  __gnat_handler_installed      = 0;
114 
115 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
116    is defined. If this is not set them a void implementation will be defined
117    at the end of this unit. */
118 #undef HAVE_GNAT_INIT_FLOAT
119 
120 /******************************/
121 /* __gnat_get_interrupt_state */
122 /******************************/
123 
124 char __gnat_get_interrupt_state (int);
125 
126 /* This routine is called from the runtime as needed to determine the state
127    of an interrupt, as set by an Interrupt_State pragma appearing anywhere
128    in the current partition. The input argument is the interrupt number,
129    and the result is one of the following:
130 
131        'n'   this interrupt not set by any Interrupt_State pragma
132        'u'   Interrupt_State pragma set state to User
133        'r'   Interrupt_State pragma set state to Runtime
134        's'   Interrupt_State pragma set state to System */
135 
136 char
__gnat_get_interrupt_state(int intrup)137 __gnat_get_interrupt_state (int intrup)
138 {
139   if (intrup >= __gl_num_interrupt_states)
140     return 'n';
141   else
142     return __gl_interrupt_states [intrup];
143 }
144 
145 /**********************/
146 /* __gnat_set_globals */
147 /**********************/
148 
149 /* This routine is called from the binder generated main program.  It copies
150    the values for global quantities computed by the binder into the following
151    global locations. The reason that we go through this copy, rather than just
152    define the global locations in the binder generated file, is that they are
153    referenced from the runtime, which may be in a shared library, and the
154    binder file is not in the shared library. Global references across library
155    boundaries like this are not handled correctly in all systems.  */
156 
157 void
__gnat_set_globals(int main_priority,int time_slice_val,char wc_encoding,char locking_policy,char queuing_policy,char task_dispatching_policy,char * restrictions,char * interrupt_states,int num_interrupt_states,int unreserve_all_interrupts,int exception_tracebacks,int zero_cost_exceptions)158 __gnat_set_globals (int main_priority,
159                     int time_slice_val,
160                     char wc_encoding,
161                     char locking_policy,
162                     char queuing_policy,
163                     char task_dispatching_policy,
164                     char *restrictions,
165                     char *interrupt_states,
166                     int num_interrupt_states,
167                     int unreserve_all_interrupts,
168                     int exception_tracebacks,
169                     int zero_cost_exceptions)
170 {
171   static int already_called = 0;
172 
173   /* If this procedure has been already called once, check that the
174      arguments in this call are consistent with the ones in the previous
175      calls. Otherwise, raise a Program_Error exception.
176 
177      We do not check for consistency of the wide character encoding
178      method. This default affects only Wide_Text_IO where no explicit
179      coding method is given, and there is no particular reason to let
180      this default be affected by the source representation of a library
181      in any case.
182 
183      We do not check either for the consistency of exception tracebacks,
184      because exception tracebacks are not normally set in Stand-Alone
185      libraries. If a library or the main program set the exception
186      tracebacks, then they are never reset afterwards (see below).
187 
188      The value of main_priority is meaningful only when we are invoked
189      from the main program elaboration routine of an Ada application.
190      Checking the consistency of this parameter should therefore not be
191      done. Since it is assured that the main program elaboration will
192      always invoke this procedure before any library elaboration
193      routine, only the value of main_priority during the first call
194      should be taken into account and all the subsequent ones should be
195      ignored. Note that the case where the main program is not written
196      in Ada is also properly handled, since the default value will then
197      be used for this parameter.
198 
199      For identical reasons, the consistency of time_slice_val should not
200      be checked. */
201 
202   if (already_called)
203     {
204       if (__gl_locking_policy		   != locking_policy
205 	  || __gl_queuing_policy           != queuing_policy
206 	  || __gl_task_dispatching_policy  != task_dispatching_policy
207 	  || __gl_unreserve_all_interrupts != unreserve_all_interrupts
208 	  || __gl_zero_cost_exceptions     != zero_cost_exceptions)
209 	__gnat_raise_program_error (__FILE__, __LINE__);
210 
211       /* If either a library or the main program set the exception traceback
212          flag, it is never reset later */
213 
214       if (exception_tracebacks != 0)
215          __gl_exception_tracebacks = exception_tracebacks;
216 
217       return;
218     }
219   already_called = 1;
220 
221   __gl_main_priority            = main_priority;
222   __gl_time_slice_val           = time_slice_val;
223   __gl_wc_encoding              = wc_encoding;
224   __gl_locking_policy           = locking_policy;
225   __gl_queuing_policy           = queuing_policy;
226   __gl_restrictions             = restrictions;
227   __gl_interrupt_states         = interrupt_states;
228   __gl_num_interrupt_states     = num_interrupt_states;
229   __gl_task_dispatching_policy  = task_dispatching_policy;
230   __gl_unreserve_all_interrupts = unreserve_all_interrupts;
231   __gl_exception_tracebacks     = exception_tracebacks;
232 
233   /* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
234      a-except.adb, which is also part of the compiler sources. Since the
235      compiler is built with an older release of GNAT, the call generated by
236      the old binder to this function does not provide any value for the
237      corresponding argument, so the global has to be initialized in some
238      reasonable other way. This could be removed as soon as the next major
239      release is out.  */
240 
241 #ifdef IN_RTS
242   __gl_zero_cost_exceptions = zero_cost_exceptions;
243 #else
244   __gl_zero_cost_exceptions = 0;
245   /* We never build the compiler to run in ZCX mode currently anyway.  */
246 #endif
247 }
248 
249 /*********************/
250 /* __gnat_initialize */
251 /*********************/
252 
253 /* __gnat_initialize is called at the start of execution of an Ada program
254    (the call is generated by the binder). The standard routine does nothing
255    at all; the intention is that this be replaced by system specific
256    code where initialization is required. */
257 
258 /***********************************/
259 /* __gnat_initialize (AIX Version) */
260 /***********************************/
261 
262 #if defined (_AIX)
263 
264 #include <signal.h>
265 #include <sys/time.h>
266 
267 /* Some versions of AIX don't define SA_NODEFER. */
268 
269 #ifndef SA_NODEFER
270 #define SA_NODEFER 0
271 #endif /* SA_NODEFER */
272 
273 /* Versions of AIX before 4.3 don't have nanosleep but provide
274    nsleep instead. */
275 
276 #ifndef _AIXVERSION_430
277 
278 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
279 
280 int
nanosleep(struct timestruc_t * Rqtp,struct timestruc_t * Rmtp)281 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
282 {
283   return nsleep (Rqtp, Rmtp);
284 }
285 
286 #endif /* _AIXVERSION_430 */
287 
288 static void __gnat_error_handler (int);
289 
290 static void
__gnat_error_handler(int sig)291 __gnat_error_handler (int sig)
292 {
293   struct Exception_Data *exception;
294   const char *msg;
295 
296   switch (sig)
297     {
298     case SIGSEGV:
299       /* FIXME: we need to detect the case of a *real* SIGSEGV */
300       exception = &storage_error;
301       msg = "stack overflow or erroneous memory access";
302       break;
303 
304     case SIGBUS:
305       exception = &constraint_error;
306       msg = "SIGBUS";
307       break;
308 
309     case SIGFPE:
310       exception = &constraint_error;
311       msg = "SIGFPE";
312       break;
313 
314     default:
315       exception = &program_error;
316       msg = "unhandled signal";
317     }
318 
319   Raise_From_Signal_Handler (exception, msg);
320 }
321 
322 void
__gnat_install_handler(void)323 __gnat_install_handler (void)
324 {
325   struct sigaction act;
326 
327   /* Set up signal handler to map synchronous signals to appropriate
328      exceptions.  Make sure that the handler isn't interrupted by another
329      signal that might cause a scheduling event! */
330 
331   act.sa_handler = __gnat_error_handler;
332   act.sa_flags = SA_NODEFER | SA_RESTART;
333   sigemptyset (&act.sa_mask);
334 
335   /* Do not install handlers if interrupt state is "System" */
336   if (__gnat_get_interrupt_state (SIGABRT) != 's')
337     sigaction (SIGABRT, &act, NULL);
338   if (__gnat_get_interrupt_state (SIGFPE) != 's')
339     sigaction (SIGFPE,  &act, NULL);
340   if (__gnat_get_interrupt_state (SIGILL) != 's')
341     sigaction (SIGILL,  &act, NULL);
342   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
343     sigaction (SIGSEGV, &act, NULL);
344   if (__gnat_get_interrupt_state (SIGBUS) != 's')
345     sigaction (SIGBUS,  &act, NULL);
346 
347   __gnat_handler_installed = 1;
348 }
349 
350 void
__gnat_initialize(void)351 __gnat_initialize (void)
352 {
353 }
354 
355 /***************************************/
356 /* __gnat_initialize (RTEMS version) */
357 /***************************************/
358 
359 #elif defined(__rtems__)
360 
361 extern void __gnat_install_handler (void);
362 
363 /* For RTEMS, each bsp will provide a custom __gnat_install_handler (). */
364 
365 void
__gnat_initialize(void)366 __gnat_initialize (void)
367 {
368    __gnat_install_handler ();
369 }
370 
371 /****************************************/
372 /* __gnat_initialize (Dec Unix Version) */
373 /****************************************/
374 
375 #elif defined(__alpha__) && defined(__osf__) && ! defined(__alpha_vxworks)
376 
377 /* Note: it seems that __osf__ is defined for the Alpha VXWorks case. Not
378    clear that this is reasonable, but in any case we have to be sure to
379    exclude this case in the above test.  */
380 
381 #include <signal.h>
382 #include <sys/siginfo.h>
383 
384 static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
385 extern char *__gnat_get_code_loc (struct sigcontext *);
386 extern void __gnat_enter_handler (struct sigcontext *, char *);
387 extern size_t __gnat_machine_state_length (void);
388 
389 extern long exc_lookup_gp (char *);
390 extern void exc_resume (struct sigcontext *);
391 
392 static void
__gnat_error_handler(int sig,siginfo_t * sip,struct sigcontext * context)393 __gnat_error_handler (int sig, siginfo_t *sip, struct sigcontext *context)
394 {
395   struct Exception_Data *exception;
396   static int recurse = 0;
397   struct sigcontext *mstate;
398   const char *msg;
399 
400   /* If this was an explicit signal from a "kill", just resignal it.  */
401   if (SI_FROMUSER (sip))
402     {
403       signal (sig, SIG_DFL);
404       kill (getpid(), sig);
405     }
406 
407   /* Otherwise, treat it as something we handle.  */
408   switch (sig)
409     {
410     case SIGSEGV:
411       /* If the problem was permissions, this is a constraint error.
412 	 Likewise if the failing address isn't maximally aligned or if
413 	 we've recursed.
414 
415 	 ??? Using a static variable here isn't task-safe, but it's
416 	 much too hard to do anything else and we're just determining
417 	 which exception to raise.  */
418       if (sip->si_code == SEGV_ACCERR
419 	  || (((long) sip->si_addr) & 3) != 0
420 	  || recurse)
421 	{
422 	  exception = &constraint_error;
423 	  msg = "SIGSEGV";
424 	}
425       else
426 	{
427 	  /* See if the page before the faulting page is accessible.  Do that
428 	     by trying to access it.  We'd like to simply try to access
429 	     4096 + the faulting address, but it's not guaranteed to be
430 	     the actual address, just to be on the same page.  */
431 	  recurse++;
432 	  ((volatile char *)
433 	   ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
434 	  msg = "stack overflow (or erroneous memory access)";
435 	  exception = &storage_error;
436 	}
437       break;
438 
439     case SIGBUS:
440       exception = &program_error;
441       msg = "SIGBUS";
442       break;
443 
444     case SIGFPE:
445       exception = &constraint_error;
446       msg = "SIGFPE";
447       break;
448 
449     default:
450       exception = &program_error;
451       msg = "unhandled signal";
452     }
453 
454   recurse = 0;
455   mstate = (struct sigcontext *) (*Get_Machine_State_Addr) ();
456   if (mstate != 0)
457     *mstate = *context;
458 
459   Raise_From_Signal_Handler (exception, (char *) msg);
460 }
461 
462 void
__gnat_install_handler(void)463 __gnat_install_handler (void)
464 {
465   struct sigaction act;
466 
467   /* Setup signal handler to map synchronous signals to appropriate
468      exceptions. Make sure that the handler isn't interrupted by another
469      signal that might cause a scheduling event! */
470 
471   act.sa_handler = (void (*) (int)) __gnat_error_handler;
472   act.sa_flags = SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_SIGINFO;
473   sigemptyset (&act.sa_mask);
474 
475   /* Do not install handlers if interrupt state is "System" */
476   if (__gnat_get_interrupt_state (SIGABRT) != 's')
477     sigaction (SIGABRT, &act, NULL);
478   if (__gnat_get_interrupt_state (SIGFPE) != 's')
479     sigaction (SIGFPE,  &act, NULL);
480   if (__gnat_get_interrupt_state (SIGILL) != 's')
481     sigaction (SIGILL,  &act, NULL);
482   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
483     sigaction (SIGSEGV, &act, NULL);
484   if (__gnat_get_interrupt_state (SIGBUS) != 's')
485     sigaction (SIGBUS,  &act, NULL);
486 
487   __gnat_handler_installed = 1;
488 }
489 
490 void
__gnat_initialize(void)491 __gnat_initialize (void)
492 {
493 }
494 
495 /* Routines called by 5amastop.adb.  */
496 
497 #define SC_GP 29
498 
499 char *
__gnat_get_code_loc(struct sigcontext * context)500 __gnat_get_code_loc (struct sigcontext *context)
501 {
502   return (char *) context->sc_pc;
503 }
504 
505 void
__gnat_enter_handler(struct sigcontext * context,char * pc)506 __gnat_enter_handler ( struct sigcontext *context, char *pc)
507 {
508   context->sc_pc = (long) pc;
509   context->sc_regs[SC_GP] = exc_lookup_gp (pc);
510   exc_resume (context);
511 }
512 
513 size_t
__gnat_machine_state_length(void)514 __gnat_machine_state_length (void)
515 {
516   return sizeof (struct sigcontext);
517 }
518 
519 /************************************/
520 /* __gnat_initialize (HPUX Version) */
521 /************************************/
522 
523 #elif defined (hpux)
524 
525 #include <signal.h>
526 
527 static void __gnat_error_handler (int);
528 
529 static void
__gnat_error_handler(int sig)530 __gnat_error_handler (int sig)
531 {
532   struct Exception_Data *exception;
533   char *msg;
534 
535   switch (sig)
536     {
537     case SIGSEGV:
538       /* FIXME: we need to detect the case of a *real* SIGSEGV */
539       exception = &storage_error;
540       msg = "stack overflow or erroneous memory access";
541       break;
542 
543     case SIGBUS:
544       exception = &constraint_error;
545       msg = "SIGBUS";
546       break;
547 
548     case SIGFPE:
549       exception = &constraint_error;
550       msg = "SIGFPE";
551       break;
552 
553     default:
554       exception = &program_error;
555       msg = "unhandled signal";
556     }
557 
558   Raise_From_Signal_Handler (exception, msg);
559 }
560 
561 void
__gnat_install_handler(void)562 __gnat_install_handler (void)
563 {
564   struct sigaction act;
565 
566   /* Set up signal handler to map synchronous signals to appropriate
567      exceptions.  Make sure that the handler isn't interrupted by another
568      signal that might cause a scheduling event! Also setup an alternate
569      stack region for the handler execution so that stack overflows can be
570      handled properly, avoiding a SEGV generation from stack usage by the
571      handler itself. */
572 
573   static char handler_stack[SIGSTKSZ*2];
574   /* SIGSTKSZ appeared to be "short" for the needs in some contexts
575      (e.g. experiments with GCC ZCX exceptions).  */
576 
577   stack_t stack;
578 
579   stack.ss_sp    = handler_stack;
580   stack.ss_size  = sizeof (handler_stack);
581   stack.ss_flags = 0;
582 
583   sigaltstack (&stack, NULL);
584 
585   act.sa_handler = __gnat_error_handler;
586   act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK;
587   sigemptyset (&act.sa_mask);
588 
589   /* Do not install handlers if interrupt state is "System" */
590   if (__gnat_get_interrupt_state (SIGABRT) != 's')
591     sigaction (SIGABRT, &act, NULL);
592   if (__gnat_get_interrupt_state (SIGFPE) != 's')
593     sigaction (SIGFPE,  &act, NULL);
594   if (__gnat_get_interrupt_state (SIGILL) != 's')
595     sigaction (SIGILL,  &act, NULL);
596   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
597     sigaction (SIGSEGV, &act, NULL);
598   if (__gnat_get_interrupt_state (SIGBUS) != 's')
599     sigaction (SIGBUS,  &act, NULL);
600 
601   __gnat_handler_installed = 1;
602 }
603 
604 void
__gnat_initialize(void)605 __gnat_initialize (void)
606 {
607 }
608 
609 /*****************************************/
610 /* __gnat_initialize (GNU/Linux Version) */
611 /*****************************************/
612 
613 #elif defined (linux) && defined (i386) && !defined (__RT__)
614 
615 #include <signal.h>
616 #include <asm/sigcontext.h>
617 
618 /* GNU/Linux, which uses glibc, does not define NULL in included
619    header files */
620 
621 #if !defined (NULL)
622 #define NULL ((void *) 0)
623 #endif
624 
625 struct Machine_State
626 {
627   unsigned long eip;
628   unsigned long ebx;
629   unsigned long esp;
630   unsigned long ebp;
631   unsigned long esi;
632   unsigned long edi;
633 };
634 
635 static void __gnat_error_handler (int);
636 
637 static void
__gnat_error_handler(int sig)638 __gnat_error_handler (int sig)
639 {
640   struct Exception_Data *exception;
641   const char *msg;
642   static int recurse = 0;
643 
644   struct sigcontext *info
645     = (struct sigcontext *) (((char *) &sig) + sizeof (int));
646 
647   /* The Linux kernel does not document how to get the machine state in a
648      signal handler, but in fact the necessary data is in a sigcontext_struct
649      value that is on the stack immediately above the signal number
650      parameter, and the above messing accesses this value on the stack. */
651 
652   struct Machine_State *mstate;
653 
654   switch (sig)
655     {
656     case SIGSEGV:
657       /* If the problem was permissions, this is a constraint error.
658        Likewise if the failing address isn't maximally aligned or if
659        we've recursed.
660 
661        ??? Using a static variable here isn't task-safe, but it's
662        much too hard to do anything else and we're just determining
663        which exception to raise.  */
664       if (recurse)
665       {
666         exception = &constraint_error;
667         msg = "SIGSEGV";
668       }
669       else
670       {
671         /* Here we would like a discrimination test to see whether the
672            page before the faulting address is accessible. Unfortunately
673            Linux seems to have no way of giving us the faulting address.
674 
675            In versions of a-init.c before 1.95, we had a test of the page
676            before the stack pointer using:
677 
678             recurse++;
679              ((volatile char *)
680               ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
681 
682            but that's wrong, since it tests the stack pointer location, and
683            the current stack probe code does not move the stack pointer
684            until all probes succeed.
685 
686            For now we simply do not attempt any discrimination at all. Note
687            that this is quite acceptable, since a "real" SIGSEGV can only
688            occur as the result of an erroneous program */
689 
690         msg = "stack overflow (or erroneous memory access)";
691         exception = &storage_error;
692       }
693       break;
694 
695     case SIGBUS:
696       exception = &constraint_error;
697       msg = "SIGBUS";
698       break;
699 
700     case SIGFPE:
701       exception = &constraint_error;
702       msg = "SIGFPE";
703       break;
704 
705     default:
706       exception = &program_error;
707       msg = "unhandled signal";
708     }
709 
710   mstate = (*Get_Machine_State_Addr) ();
711   if (mstate)
712     {
713       mstate->eip = info->eip;
714       mstate->ebx = info->ebx;
715       mstate->esp = info->esp_at_signal;
716       mstate->ebp = info->ebp;
717       mstate->esi = info->esi;
718       mstate->edi = info->edi;
719     }
720 
721   recurse = 0;
722   Raise_From_Signal_Handler (exception, msg);
723 }
724 
725 void
__gnat_install_handler(void)726 __gnat_install_handler (void)
727 {
728   struct sigaction act;
729 
730   /* Set up signal handler to map synchronous signals to appropriate
731      exceptions.  Make sure that the handler isn't interrupted by another
732      signal that might cause a scheduling event! */
733 
734   act.sa_handler = __gnat_error_handler;
735   act.sa_flags = SA_NODEFER | SA_RESTART;
736   sigemptyset (&act.sa_mask);
737 
738   /* Do not install handlers if interrupt state is "System" */
739   if (__gnat_get_interrupt_state (SIGABRT) != 's')
740     sigaction (SIGABRT, &act, NULL);
741   if (__gnat_get_interrupt_state (SIGFPE) != 's')
742     sigaction (SIGFPE,  &act, NULL);
743   if (__gnat_get_interrupt_state (SIGILL) != 's')
744     sigaction (SIGILL,  &act, NULL);
745   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
746     sigaction (SIGSEGV, &act, NULL);
747   if (__gnat_get_interrupt_state (SIGBUS) != 's')
748     sigaction (SIGBUS,  &act, NULL);
749 
750   __gnat_handler_installed = 1;
751 }
752 
753 void
__gnat_initialize(void)754 __gnat_initialize (void)
755 {
756 }
757 
758 /******************************************/
759 /* __gnat_initialize (NT-mingw32 Version) */
760 /******************************************/
761 
762 #elif defined (__MINGW32__)
763 #include <windows.h>
764 
765 static LONG WINAPI __gnat_error_handler (PEXCEPTION_POINTERS);
766 
767 /* __gnat_initialize (mingw32).  */
768 
769 static LONG WINAPI
__gnat_error_handler(PEXCEPTION_POINTERS info)770 __gnat_error_handler (PEXCEPTION_POINTERS info)
771 {
772   static int recurse;
773   struct Exception_Data *exception;
774   const char *msg;
775 
776   switch (info->ExceptionRecord->ExceptionCode)
777     {
778     case EXCEPTION_ACCESS_VIOLATION:
779       /* If the failing address isn't maximally-aligned or if we've
780 	 recursed, this is a program error.  */
781       if ((info->ExceptionRecord->ExceptionInformation[1] & 3) != 0
782 	  || recurse)
783 	{
784 	  exception = &program_error;
785 	  msg = "EXCEPTION_ACCESS_VIOLATION";
786 	}
787       else
788 	{
789 	  /* See if the page before the faulting page is accessible.  Do that
790 	     by trying to access it. */
791 	  recurse++;
792 	  * ((volatile char *) (info->ExceptionRecord->ExceptionInformation[1]
793 				+ 4096));
794 	  exception = &storage_error;
795 	  msg = "stack overflow (or erroneous memory access)";
796 	}
797       break;
798 
799     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
800       exception = &constraint_error;
801       msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
802       break;
803 
804     case EXCEPTION_DATATYPE_MISALIGNMENT:
805       exception = &constraint_error;
806       msg = "EXCEPTION_DATATYPE_MISALIGNMENT";
807       break;
808 
809     case EXCEPTION_FLT_DENORMAL_OPERAND:
810       exception = &constraint_error;
811       msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
812       break;
813 
814     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
815       exception = &constraint_error;
816       msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
817       break;
818 
819     case EXCEPTION_FLT_INVALID_OPERATION:
820       exception = &constraint_error;
821       msg = "EXCEPTION_FLT_INVALID_OPERATION";
822       break;
823 
824     case EXCEPTION_FLT_OVERFLOW:
825       exception = &constraint_error;
826       msg = "EXCEPTION_FLT_OVERFLOW";
827       break;
828 
829     case EXCEPTION_FLT_STACK_CHECK:
830       exception = &program_error;
831       msg = "EXCEPTION_FLT_STACK_CHECK";
832       break;
833 
834     case EXCEPTION_FLT_UNDERFLOW:
835       exception = &constraint_error;
836       msg = "EXCEPTION_FLT_UNDERFLOW";
837       break;
838 
839     case EXCEPTION_INT_DIVIDE_BY_ZERO:
840       exception = &constraint_error;
841       msg = "EXCEPTION_INT_DIVIDE_BY_ZERO";
842       break;
843 
844     case EXCEPTION_INT_OVERFLOW:
845       exception = &constraint_error;
846       msg = "EXCEPTION_INT_OVERFLOW";
847       break;
848 
849     case EXCEPTION_INVALID_DISPOSITION:
850       exception = &program_error;
851       msg = "EXCEPTION_INVALID_DISPOSITION";
852       break;
853 
854     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
855       exception = &program_error;
856       msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
857       break;
858 
859     case EXCEPTION_PRIV_INSTRUCTION:
860       exception = &program_error;
861       msg = "EXCEPTION_PRIV_INSTRUCTION";
862       break;
863 
864     case EXCEPTION_SINGLE_STEP:
865       exception = &program_error;
866       msg = "EXCEPTION_SINGLE_STEP";
867       break;
868 
869     case EXCEPTION_STACK_OVERFLOW:
870       exception = &storage_error;
871       msg = "EXCEPTION_STACK_OVERFLOW";
872       break;
873 
874    default:
875       exception = &program_error;
876       msg = "unhandled signal";
877     }
878 
879   recurse = 0;
880   Raise_From_Signal_Handler (exception, msg);
881   return 0; /* This is never reached, avoid compiler warning */
882 }
883 
884 void
__gnat_install_handler(void)885 __gnat_install_handler (void)
886 {
887   SetUnhandledExceptionFilter (__gnat_error_handler);
888   __gnat_handler_installed = 1;
889 }
890 
891 void
__gnat_initialize(void)892 __gnat_initialize (void)
893 {
894 
895    /* Initialize floating-point coprocessor. This call is needed because
896       the MS libraries default to 64-bit precision instead of 80-bit
897       precision, and we require the full precision for proper operation,
898       given that we have set Max_Digits etc with this in mind */
899 
900    __gnat_init_float ();
901 
902    /* initialize a lock for a process handle list - see a-adaint.c for the
903       implementation of __gnat_portable_no_block_spawn, __gnat_portable_wait */
904    __gnat_plist_init();
905 }
906 
907 /***************************************/
908 /* __gnat_initialize (Interix Version) */
909 /***************************************/
910 
911 #elif defined (__INTERIX)
912 
913 #include <signal.h>
914 
915 static void __gnat_error_handler (int);
916 
917 static void
__gnat_error_handler(int sig)918 __gnat_error_handler (int sig)
919 {
920   struct Exception_Data *exception;
921   char *msg;
922 
923   switch (sig)
924     {
925     case SIGSEGV:
926       exception = &storage_error;
927       msg = "stack overflow or erroneous memory access";
928       break;
929 
930     case SIGBUS:
931       exception = &constraint_error;
932       msg = "SIGBUS";
933       break;
934 
935     case SIGFPE:
936       exception = &constraint_error;
937       msg = "SIGFPE";
938       break;
939 
940     default:
941       exception = &program_error;
942       msg = "unhandled signal";
943     }
944 
945   Raise_From_Signal_Handler (exception, msg);
946 }
947 
948 void
__gnat_install_handler(void)949 __gnat_install_handler (void)
950 {
951   struct sigaction act;
952 
953   /* Set up signal handler to map synchronous signals to appropriate
954      exceptions.  Make sure that the handler isn't interrupted by another
955      signal that might cause a scheduling event! */
956 
957   act.sa_handler = __gnat_error_handler;
958   act.sa_flags = 0;
959   sigemptyset (&act.sa_mask);
960 
961   /* Handlers for signals besides SIGSEGV cause c974013 to hang */
962 /*  sigaction (SIGILL,  &act, NULL); */
963 /*  sigaction (SIGABRT, &act, NULL); */
964 /*  sigaction (SIGFPE,  &act, NULL); */
965 /*  sigaction (SIGBUS,  &act, NULL); */
966 
967   /* Do not install handlers if interrupt state is "System" */
968   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
969     sigaction (SIGSEGV, &act, NULL);
970 
971   __gnat_handler_installed = 1;
972 }
973 
974 void
__gnat_initialize(void)975 __gnat_initialize (void)
976 {
977    __gnat_init_float ();
978 }
979 
980 /**************************************/
981 /* __gnat_initialize (LynxOS Version) */
982 /**************************************/
983 
984 #elif defined (__Lynx__)
985 
986 void
__gnat_initialize(void)987 __gnat_initialize (void)
988 {
989    __gnat_init_float ();
990 }
991 
992 /*********************************/
993 /* __gnat_install_handler (Lynx) */
994 /*********************************/
995 
996 void
__gnat_install_handler(void)997 __gnat_install_handler (void)
998 {
999   __gnat_handler_installed = 1;
1000 }
1001 
1002 /****************************/
1003 /* __gnat_initialize (OS/2) */
1004 /****************************/
1005 
1006 #elif defined (__EMX__) /* OS/2 dependent initialization */
1007 
1008 void
__gnat_initialize(void)1009 __gnat_initialize (void)
1010 {
1011 }
1012 
1013 /*********************************/
1014 /* __gnat_install_handler (OS/2) */
1015 /*********************************/
1016 
1017 void
__gnat_install_handler(void)1018 __gnat_install_handler (void)
1019 {
1020   __gnat_handler_installed = 1;
1021 }
1022 
1023 /***********************************/
1024 /* __gnat_initialize (SGI Version) */
1025 /***********************************/
1026 
1027 #elif defined (sgi)
1028 
1029 #include <signal.h>
1030 #include <siginfo.h>
1031 
1032 #ifndef NULL
1033 #define NULL 0
1034 #endif
1035 
1036 #define SIGADAABORT 48
1037 #define SIGNAL_STACK_SIZE 4096
1038 #define SIGNAL_STACK_ALIGNMENT 64
1039 
1040 struct Machine_State
1041 {
1042   sigcontext_t context;
1043 };
1044 
1045 static void __gnat_error_handler (int, int, sigcontext_t *);
1046 
1047 static void
__gnat_error_handler(int sig,int code,sigcontext_t * sc)1048 __gnat_error_handler (int sig, int code, sigcontext_t *sc)
1049 {
1050   struct Machine_State  *mstate;
1051   struct Exception_Data *exception;
1052   const char *msg;
1053 
1054   switch (sig)
1055     {
1056     case SIGSEGV:
1057       if (code == EFAULT)
1058 	{
1059 	  exception = &program_error;
1060 	  msg = "SIGSEGV: (Invalid virtual address)";
1061 	}
1062       else if (code == ENXIO)
1063 	{
1064 	  exception = &program_error;
1065 	  msg = "SIGSEGV: (Read beyond mapped object)";
1066 	}
1067       else if (code == ENOSPC)
1068 	{
1069 	  exception = &program_error; /* ??? storage_error ??? */
1070 	  msg = "SIGSEGV: (Autogrow for file failed)";
1071 	}
1072       else if (code == EACCES)
1073 	{
1074 	  /* ??? Re-add smarts to further verify that we launched
1075 		 the stack into a guard page, not an attempt to
1076 		 write to .text or something */
1077 	  exception = &storage_error;
1078 	  msg = "SIGSEGV: (stack overflow or erroneous memory access)";
1079 	}
1080       else
1081 	{
1082 	  /* Just in case the OS guys did it to us again.  Sometimes
1083 	     they fail to document all of the valid codes that are
1084 	     passed to signal handlers, just in case someone depends
1085 	     on knowing all the codes */
1086 	  exception = &program_error;
1087 	  msg = "SIGSEGV: (Undocumented reason)";
1088 	}
1089       break;
1090 
1091     case SIGBUS:
1092       /* Map all bus errors to Program_Error.  */
1093       exception = &program_error;
1094       msg = "SIGBUS";
1095       break;
1096 
1097     case SIGFPE:
1098       /* Map all fpe errors to Constraint_Error.  */
1099       exception = &constraint_error;
1100       msg = "SIGFPE";
1101       break;
1102 
1103     case SIGADAABORT:
1104       if ((*Check_Abort_Status) ())
1105 	{
1106 	  exception = &_abort_signal;
1107 	  msg = "";
1108 	}
1109       else
1110 	return;
1111 
1112       break;
1113 
1114     default:
1115       /* Everything else is a Program_Error. */
1116       exception = &program_error;
1117       msg = "unhandled signal";
1118     }
1119 
1120   mstate = (*Get_Machine_State_Addr) ();
1121   if (mstate != 0)
1122     memcpy ((void *) mstate, (const void *) sc, sizeof (sigcontext_t));
1123 
1124   Raise_From_Signal_Handler (exception, msg);
1125 }
1126 
1127 void
__gnat_install_handler(void)1128 __gnat_install_handler (void)
1129 {
1130   struct sigaction act;
1131 
1132   /* Setup signal handler to map synchronous signals to appropriate
1133      exceptions.  Make sure that the handler isn't interrupted by another
1134      signal that might cause a scheduling event! */
1135 
1136   act.sa_handler = __gnat_error_handler;
1137   act.sa_flags = SA_NODEFER + SA_RESTART;
1138   sigfillset (&act.sa_mask);
1139   sigemptyset (&act.sa_mask);
1140 
1141   /* Do not install handlers if interrupt state is "System" */
1142   if (__gnat_get_interrupt_state (SIGABRT) != 's')
1143     sigaction (SIGABRT, &act, NULL);
1144   if (__gnat_get_interrupt_state (SIGFPE) != 's')
1145     sigaction (SIGFPE,  &act, NULL);
1146   if (__gnat_get_interrupt_state (SIGILL) != 's')
1147     sigaction (SIGILL,  &act, NULL);
1148   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1149     sigaction (SIGSEGV, &act, NULL);
1150   if (__gnat_get_interrupt_state (SIGBUS) != 's')
1151     sigaction (SIGBUS,  &act, NULL);
1152   if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
1153     sigaction (SIGADAABORT,  &act, NULL);
1154 
1155   __gnat_handler_installed = 1;
1156 }
1157 
1158 void
__gnat_initialize(void)1159 __gnat_initialize (void)
1160 {
1161 }
1162 
1163 /*************************************************/
1164 /* __gnat_initialize (Solaris and SunOS Version) */
1165 /*************************************************/
1166 
1167 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
1168 
1169 #include <signal.h>
1170 #include <siginfo.h>
1171 
1172 static void __gnat_error_handler (int, siginfo_t *);
1173 
1174 static void
__gnat_error_handler(int sig,siginfo_t * sip)1175 __gnat_error_handler (int sig, siginfo_t *sip)
1176 {
1177   struct Exception_Data *exception;
1178   static int recurse = 0;
1179   const char *msg;
1180 
1181   /* If this was an explicit signal from a "kill", just resignal it.  */
1182   if (SI_FROMUSER (sip))
1183     {
1184       signal (sig, SIG_DFL);
1185       kill (getpid(), sig);
1186     }
1187 
1188   /* Otherwise, treat it as something we handle.  */
1189   switch (sig)
1190     {
1191     case SIGSEGV:
1192       /* If the problem was permissions, this is a constraint error.
1193 	 Likewise if the failing address isn't maximally aligned or if
1194 	 we've recursed.
1195 
1196 	 ??? Using a static variable here isn't task-safe, but it's
1197 	 much too hard to do anything else and we're just determining
1198 	 which exception to raise.  */
1199       if (sip->si_code == SEGV_ACCERR
1200 	  || (((long) sip->si_addr) & 3) != 0
1201 	  || recurse)
1202 	{
1203 	  exception = &constraint_error;
1204 	  msg = "SIGSEGV";
1205 	}
1206       else
1207 	{
1208 	  /* See if the page before the faulting page is accessible.  Do that
1209 	     by trying to access it.  We'd like to simply try to access
1210 	     4096 + the faulting address, but it's not guaranteed to be
1211 	     the actual address, just to be on the same page.  */
1212 	  recurse++;
1213 	  ((volatile char *)
1214 	   ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1215 	  exception = &storage_error;
1216 	  msg = "stack overflow (or erroneous memory access)";
1217 	}
1218       break;
1219 
1220     case SIGBUS:
1221       exception = &program_error;
1222       msg = "SIGBUS";
1223       break;
1224 
1225     case SIGFPE:
1226       exception = &constraint_error;
1227       msg = "SIGFPE";
1228       break;
1229 
1230     default:
1231       exception = &program_error;
1232       msg = "unhandled signal";
1233     }
1234 
1235   recurse = 0;
1236 
1237   Raise_From_Signal_Handler (exception, msg);
1238 }
1239 
1240 void
__gnat_install_handler(void)1241 __gnat_install_handler (void)
1242 {
1243   struct sigaction act;
1244 
1245   /* Set up signal handler to map synchronous signals to appropriate
1246      exceptions.  Make sure that the handler isn't interrupted by another
1247      signal that might cause a scheduling event! */
1248 
1249   act.sa_handler = __gnat_error_handler;
1250   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1251   sigemptyset (&act.sa_mask);
1252 
1253   /* Do not install handlers if interrupt state is "System" */
1254   if (__gnat_get_interrupt_state (SIGABRT) != 's')
1255     sigaction (SIGABRT, &act, NULL);
1256   if (__gnat_get_interrupt_state (SIGFPE) != 's')
1257     sigaction (SIGFPE,  &act, NULL);
1258   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1259     sigaction (SIGSEGV, &act, NULL);
1260   if (__gnat_get_interrupt_state (SIGBUS) != 's')
1261     sigaction (SIGBUS,  &act, NULL);
1262 
1263   __gnat_handler_installed = 1;
1264 }
1265 
1266 void
__gnat_initialize(void)1267 __gnat_initialize (void)
1268 {
1269 }
1270 
1271 /***********************************/
1272 /* __gnat_initialize (VMS Version) */
1273 /***********************************/
1274 
1275 #elif defined (VMS)
1276 
1277 /* The prehandler actually gets control first on a condition. It swaps the
1278    stack pointer and calls the handler (__gnat_error_handler). */
1279 extern long __gnat_error_prehandler (void);
1280 
1281 extern char *__gnat_error_prehandler_stack;   /* Alternate signal stack */
1282 
1283 /* Conditions that don't have an Ada exception counterpart must raise
1284    Non_Ada_Error.  Since this is defined in s-auxdec, it should only be
1285    referenced by user programs, not the compiler or tools. Hence the
1286    #ifdef IN_RTS. */
1287 
1288 #ifdef IN_RTS
1289 #define Non_Ada_Error system__aux_dec__non_ada_error
1290 extern struct Exception_Data Non_Ada_Error;
1291 
1292 #define Coded_Exception system__vms_exception_table__coded_exception
1293 extern struct Exception_Data *Coded_Exception (int);
1294 #endif
1295 
1296 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1297    Most of these are also defined in the header file ssdef.h which has not
1298    yet been converted to be recoginized by Gnu C. Some, which couldn't be
1299    located, are assigned names based on the DEC test suite tests which
1300    raise them. */
1301 
1302 #define SS$_ACCVIO            12
1303 #define SS$_DEBUG           1132
1304 #define SS$_INTDIV          1156
1305 #define SS$_HPARITH         1284
1306 #define SS$_STKOVF          1364
1307 #define SS$_RESIGNAL        2328
1308 #define MTH$_FLOOVEMAT   1475268       /* Some ACVC_21 CXA tests */
1309 #define SS$_CE24VRU      3253636       /* Write to unopened file */
1310 #define SS$_C980VTE      3246436       /* AST requests time slice */
1311 #define CMA$_EXIT_THREAD 4227492
1312 #define CMA$_EXCCOPLOS   4228108
1313 #define CMA$_ALERTED     4227460
1314 
1315 struct descriptor_s {unsigned short len, mbz; char *adr; };
1316 
1317 long __gnat_error_handler (int *, void *);
1318 
1319 long
__gnat_error_handler(int * sigargs,void * mechargs)1320 __gnat_error_handler (int *sigargs, void *mechargs)
1321 {
1322   struct Exception_Data *exception = 0;
1323   char *msg = "";
1324   char message[256];
1325   long prvhnd;
1326   struct descriptor_s msgdesc;
1327   int msg_flag = 0x000f; /* 1 bit for each of the four message parts */
1328   unsigned short outlen;
1329   char curr_icb[544];
1330   long curr_invo_handle;
1331   long *mstate;
1332 
1333   /* Resignaled condtions aren't effected by by pragma Import_Exception */
1334 
1335   switch (sigargs[1])
1336   {
1337 
1338     case CMA$_EXIT_THREAD:
1339       return SS$_RESIGNAL;
1340 
1341     case SS$_DEBUG: /* Gdb attach, resignal to merge activate gdbstub. */
1342       return SS$_RESIGNAL;
1343 
1344     case 1409786: /* Nickerson bug #33 ??? */
1345       return SS$_RESIGNAL;
1346 
1347     case 1381050: /* Nickerson bug #33 ??? */
1348       return SS$_RESIGNAL;
1349 
1350     case 11829410: /* Resignalled as Use_Error for CE10VRC */
1351       return SS$_RESIGNAL;
1352 
1353   }
1354 
1355 #ifdef IN_RTS
1356   /* See if it's an imported exception. Mask off severity bits. */
1357   exception = Coded_Exception (sigargs[1] & 0xfffffff8);
1358   if (exception)
1359     {
1360       msgdesc.len = 256;
1361       msgdesc.mbz = 0;
1362       msgdesc.adr = message;
1363       SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1364       message[outlen] = 0;
1365       msg = message;
1366 
1367       exception->Name_Length = 19;
1368       /* The full name really should be get sys$getmsg returns. ??? */
1369       exception->Full_Name = "IMPORTED_EXCEPTION";
1370       exception->Import_Code = sigargs[1] & 0xfffffff8;
1371     }
1372 #endif
1373 
1374   if (exception == 0)
1375     switch (sigargs[1])
1376       {
1377       case SS$_ACCVIO:
1378         if (sigargs[3] == 0)
1379 	  {
1380 	    exception = &constraint_error;
1381 	    msg = "access zero";
1382 	  }
1383 	else
1384 	  {
1385 	    exception = &storage_error;
1386 	    msg = "stack overflow (or erroneous memory access)";
1387 	  }
1388 	break;
1389 
1390       case SS$_STKOVF:
1391 	exception = &storage_error;
1392 	msg = "stack overflow";
1393 	break;
1394 
1395       case SS$_INTDIV:
1396 	exception = &constraint_error;
1397 	msg = "division by zero";
1398 	break;
1399 
1400       case SS$_HPARITH:
1401 #ifndef IN_RTS
1402 	return SS$_RESIGNAL; /* toplev.c handles for compiler */
1403 #else
1404 	{
1405 	  exception = &constraint_error;
1406 	  msg = "arithmetic error";
1407 	}
1408 #endif
1409 	break;
1410 
1411       case MTH$_FLOOVEMAT:
1412 	exception = &constraint_error;
1413 	msg = "floating overflow in math library";
1414 	break;
1415 
1416       case SS$_CE24VRU:
1417 	exception = &constraint_error;
1418 	msg = "";
1419 	break;
1420 
1421       case SS$_C980VTE:
1422 	exception = &program_error;
1423 	msg = "";
1424 	break;
1425 
1426       default:
1427 #ifndef IN_RTS
1428 	exception = &program_error;
1429 #else
1430 	/* User programs expect Non_Ada_Error to be raised, reference
1431 	   DEC Ada test CXCONDHAN. */
1432 	exception = &Non_Ada_Error;
1433 #endif
1434 	msgdesc.len = 256;
1435 	msgdesc.mbz = 0;
1436 	msgdesc.adr = message;
1437 	SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1438 	message[outlen] = 0;
1439 	msg = message;
1440 	break;
1441       }
1442 
1443   mstate = (long *) (*Get_Machine_State_Addr) ();
1444   if (mstate != 0)
1445     {
1446       LIB$GET_CURR_INVO_CONTEXT (&curr_icb);
1447       LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
1448       LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
1449       curr_invo_handle = LIB$GET_INVO_HANDLE (&curr_icb);
1450       *mstate = curr_invo_handle;
1451     }
1452   Raise_From_Signal_Handler (exception, msg);
1453 }
1454 
1455 void
__gnat_install_handler(void)1456 __gnat_install_handler (void)
1457 {
1458   long prvhnd;
1459   char *c;
1460 
1461   c = (char *) xmalloc (2049);
1462 
1463   __gnat_error_prehandler_stack = &c[2048];
1464 
1465   /* __gnat_error_prehandler is an assembly function.  */
1466   SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1467   __gnat_handler_installed = 1;
1468 }
1469 
1470 void
__gnat_initialize(void)1471 __gnat_initialize(void)
1472 {
1473 }
1474 
1475 /*************************************************/
1476 /* __gnat_initialize (FreeBSD version) */
1477 /*************************************************/
1478 
1479 #elif defined (__FreeBSD__)
1480 
1481 #include <signal.h>
1482 #include <unistd.h>
1483 
1484 static void
__gnat_error_handler(sig,code,sc)1485 __gnat_error_handler (sig, code, sc)
1486      int sig;
1487      int code;
1488      struct sigcontext *sc;
1489 {
1490   struct Exception_Data *exception;
1491   char *msg;
1492 
1493   switch (sig)
1494     {
1495     case SIGFPE:
1496       exception = &constraint_error;
1497       msg = "SIGFPE";
1498       break;
1499 
1500     case SIGILL:
1501       exception = &constraint_error;
1502       msg = "SIGILL";
1503       break;
1504 
1505     case SIGSEGV:
1506       exception = &storage_error;
1507       msg = "stack overflow or erroneous memory access";
1508       break;
1509 
1510     case SIGBUS:
1511       exception = &constraint_error;
1512       msg = "SIGBUS";
1513       break;
1514 
1515     default:
1516       exception = &program_error;
1517       msg = "unhandled signal";
1518     }
1519 
1520   Raise_From_Signal_Handler (exception, msg);
1521 }
1522 
1523 void
__gnat_install_handler()1524 __gnat_install_handler ()
1525 {
1526   struct sigaction act;
1527 
1528   /* Set up signal handler to map synchronous signals to appropriate
1529      exceptions.  Make sure that the handler isn't interrupted by another
1530      signal that might cause a scheduling event! */
1531 
1532   act.sa_handler = __gnat_error_handler;
1533   act.sa_flags = SA_NODEFER | SA_RESTART;
1534   (void) sigemptyset (&act.sa_mask);
1535 
1536   (void) sigaction (SIGILL,  &act, NULL);
1537   (void) sigaction (SIGFPE,  &act, NULL);
1538   (void) sigaction (SIGSEGV, &act, NULL);
1539   (void) sigaction (SIGBUS,  &act, NULL);
1540 }
1541 
1542 void __gnat_init_float ();
1543 
1544 void
__gnat_initialize()1545 __gnat_initialize ()
1546 {
1547    __gnat_install_handler ();
1548 
1549    /* XXX - Initialize floating-point coprocessor. This call is
1550       needed because FreeBSD defaults to 64-bit precision instead
1551       of 80-bit precision?  We require the full precision for
1552       proper operation, given that we have set Max_Digits etc
1553       with this in mind */
1554    __gnat_init_float ();
1555 }
1556 
1557 /***************************************/
1558 /* __gnat_initialize (VXWorks Version) */
1559 /***************************************/
1560 
1561 #elif defined(__vxworks)
1562 
1563 #include <signal.h>
1564 #include <taskLib.h>
1565 #include <intLib.h>
1566 #include <iv.h>
1567 
1568 extern int __gnat_inum_to_ivec (int);
1569 static void __gnat_error_handler (int, int, struct sigcontext *);
1570 void __gnat_map_signal (int);
1571 
1572 #ifndef __alpha_vxworks
1573 
1574 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1575    on Alpha VxWorks */
1576 
1577 extern long getpid (void);
1578 
1579 long
getpid(void)1580 getpid (void)
1581 {
1582   return taskIdSelf ();
1583 }
1584 #endif
1585 
1586 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1587 int
__gnat_inum_to_ivec(int num)1588 __gnat_inum_to_ivec (int num)
1589 {
1590   return INUM_TO_IVEC (num);
1591 }
1592 
1593 /* Exported to 5zintman.adb in order to handle different signal
1594    to exception mappings in different VxWorks versions */
1595 void
__gnat_map_signal(int sig)1596 __gnat_map_signal (int sig)
1597 {
1598   struct Exception_Data *exception;
1599   char *msg;
1600 
1601   switch (sig)
1602     {
1603     case SIGFPE:
1604       exception = &constraint_error;
1605       msg = "SIGFPE";
1606       break;
1607     case SIGILL:
1608       exception = &constraint_error;
1609       msg = "SIGILL";
1610       break;
1611     case SIGSEGV:
1612       exception = &program_error;
1613       msg = "SIGSEGV";
1614       break;
1615     case SIGBUS:
1616 #ifdef VTHREADS
1617       exception = &storage_error;
1618       msg = "SIGBUS: possible stack overflow";
1619 #else
1620       exception = &program_error;
1621       msg = "SIGBUS";
1622 #endif
1623       break;
1624     default:
1625       exception = &program_error;
1626       msg = "unhandled signal";
1627     }
1628 
1629   Raise_From_Signal_Handler (exception, msg);
1630 }
1631 
1632 static void
__gnat_error_handler(int sig,int code,struct sigcontext * sc)1633 __gnat_error_handler (int sig, int code, struct sigcontext *sc)
1634 {
1635   sigset_t mask;
1636   int result;
1637 
1638   /* VxWorks will always mask out the signal during the signal handler and
1639      will reenable it on a longjmp.  GNAT does not generate a longjmp to
1640      return from a signal handler so the signal will still be masked unless
1641      we unmask it. */
1642   sigprocmask (SIG_SETMASK, NULL, &mask);
1643   sigdelset (&mask, sig);
1644   sigprocmask (SIG_SETMASK, &mask, NULL);
1645 
1646   /* VxWorks will suspend the task when it gets a hardware exception.  We
1647      take the liberty of resuming the task for the application. */
1648   if (taskIsSuspended (taskIdSelf ()) != 0)
1649     taskResume (taskIdSelf ());
1650 
1651   __gnat_map_signal (sig);
1652 
1653 }
1654 
1655 void
__gnat_install_handler(void)1656 __gnat_install_handler (void)
1657 {
1658   struct sigaction act;
1659 
1660   /* Setup signal handler to map synchronous signals to appropriate
1661      exceptions.  Make sure that the handler isn't interrupted by another
1662      signal that might cause a scheduling event! */
1663 
1664   act.sa_handler = __gnat_error_handler;
1665   act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1666   sigemptyset (&act.sa_mask);
1667 
1668   /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1669      applies to vectored hardware interrupts, not signals */
1670   sigaction (SIGFPE,  &act, NULL);
1671   sigaction (SIGILL,  &act, NULL);
1672   sigaction (SIGSEGV, &act, NULL);
1673   sigaction (SIGBUS,  &act, NULL);
1674 
1675   __gnat_handler_installed = 1;
1676 }
1677 
1678 #define HAVE_GNAT_INIT_FLOAT
1679 
1680 void
__gnat_init_float(void)1681 __gnat_init_float (void)
1682 {
1683   /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1684      to get correct Ada semantic.  */
1685 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT)
1686   asm ("mtfsb0 25");
1687   asm ("mtfsb0 26");
1688 #endif
1689 
1690   /* Similarily for sparc64. Achieved by masking bits in the Trap Enable Mask
1691      field of the Floating-point Status Register (see the Sparc Architecture
1692      Manual Version 9, p 48).  */
1693 #if defined (sparc64)
1694 
1695 #define FSR_TEM_NVM (1 << 27)  /* Invalid operand  */
1696 #define FSR_TEM_OFM (1 << 26)  /* Overflow  */
1697 #define FSR_TEM_UFM (1 << 25)  /* Underflow  */
1698 #define FSR_TEM_DZM (1 << 24)  /* Division by Zero  */
1699 #define FSR_TEM_NXM (1 << 23)  /* Inexact result  */
1700   {
1701     unsigned int fsr;
1702 
1703     __asm__("st %%fsr, %0" : "=m" (fsr));
1704     fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1705     __asm__("ld %0, %%fsr" : : "m" (fsr));
1706   }
1707 #endif
1708 }
1709 
1710 void
__gnat_initialize(void)1711 __gnat_initialize (void)
1712 {
1713   __gnat_init_float ();
1714 
1715   /* Assume an environment task stack size of 20kB.
1716 
1717      Using a constant is necessary because we do not want each Ada application
1718      to depend on the optional taskShow library,
1719      which is required to get the actual stack information.
1720 
1721      The consequence of this is that with -fstack-check
1722      the environment task must have an actual stack size
1723      of at least 20kB and the usable size will be about 14kB.
1724   */
1725 
1726   __gnat_set_stack_size (14336);
1727   /* Allow some head room for the stack checking code, and for
1728      stack space consumed during initialization */
1729 }
1730 
1731 /********************************/
1732 /* __gnat_initialize for NetBSD */
1733 /********************************/
1734 
1735 #elif defined(__NetBSD__)
1736 
1737 #include <signal.h>
1738 #include <unistd.h>
1739 
1740 static void
__gnat_error_handler(int sig)1741 __gnat_error_handler (int sig)
1742 {
1743   struct Exception_Data *exception;
1744   const char *msg;
1745 
1746   switch(sig)
1747   {
1748     case SIGFPE:
1749       exception = &constraint_error;
1750       msg = "SIGFPE";
1751       break;
1752     case SIGILL:
1753       exception = &constraint_error;
1754       msg = "SIGILL";
1755       break;
1756     case SIGSEGV:
1757       exception = &storage_error;
1758       msg = "stack overflow or erroneous memory access";
1759       break;
1760     case SIGBUS:
1761       exception = &constraint_error;
1762       msg = "SIGBUS";
1763       break;
1764     default:
1765       exception = &program_error;
1766       msg = "unhandled signal";
1767     }
1768 
1769     Raise_From_Signal_Handler(exception, msg);
1770 }
1771 
1772 void
__gnat_install_handler(void)1773 __gnat_install_handler(void)
1774 {
1775   struct sigaction act;
1776 
1777   act.sa_handler = __gnat_error_handler;
1778   act.sa_flags = SA_NODEFER | SA_RESTART;
1779   sigemptyset (&act.sa_mask);
1780 
1781   /* Do not install handlers if interrupt state is "System" */
1782   if (__gnat_get_interrupt_state (SIGFPE) != 's')
1783     sigaction (SIGFPE,  &act, NULL);
1784   if (__gnat_get_interrupt_state (SIGILL) != 's')
1785     sigaction (SIGILL,  &act, NULL);
1786   if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1787     sigaction (SIGSEGV, &act, NULL);
1788   if (__gnat_get_interrupt_state (SIGBUS) != 's')
1789     sigaction (SIGBUS,  &act, NULL);
1790 
1791   __gnat_handler_installed = 1;
1792 }
1793 
1794 void
__gnat_initialize(void)1795 __gnat_initialize (void)
1796 {
1797   __gnat_install_handler ();
1798   __gnat_init_float ();
1799 }
1800 
1801 #else
1802 
1803 /* For all other versions of GNAT, the initialize routine and handler
1804    installation do nothing */
1805 
1806 /***************************************/
1807 /* __gnat_initialize (Default Version) */
1808 /***************************************/
1809 
1810 void
__gnat_initialize(void)1811 __gnat_initialize (void)
1812 {
1813 }
1814 
1815 /********************************************/
1816 /* __gnat_install_handler (Default Version) */
1817 /********************************************/
1818 
1819 void
__gnat_install_handler(void)1820 __gnat_install_handler (void)
1821 {
1822   __gnat_handler_installed = 1;
1823 }
1824 
1825 #endif
1826 
1827 /*********************/
1828 /* __gnat_init_float */
1829 /*********************/
1830 
1831 /* This routine is called as each process thread is created, for possible
1832    initialization of the FP processor. This version is used under INTERIX,
1833    WIN32 and could be used under OS/2 */
1834 
1835 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1836   || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1837 
1838 #define HAVE_GNAT_INIT_FLOAT
1839 
1840 void
__gnat_init_float(void)1841 __gnat_init_float (void)
1842 {
1843 #if defined (__i386__) || defined (i386)
1844 
1845   /* This is used to properly initialize the FPU on an x86 for each
1846      process thread. */
1847 
1848   asm ("finit");
1849 
1850 #endif  /* Defined __i386__ */
1851 }
1852 #endif
1853 
1854 #ifndef HAVE_GNAT_INIT_FLOAT
1855 
1856 /* All targets without a specific __gnat_init_float will use an empty one */
1857 void
__gnat_init_float(void)1858 __gnat_init_float (void)
1859 {
1860 }
1861 #endif
1862