+++ /dev/null
-/****************************************************************************
- * *
- * GNAT COMPILER COMPONENTS *
- * *
- * I N I T *
- * *
- * $Revision: 1.8.10.1.4.1 $
- * *
- * C Implementation File *
- * *
- * Copyright (C) 1992-2001 Free Software Foundation, Inc. *
- * *
- * GNAT is free software; you can redistribute it and/or modify it under *
- * terms of the GNU General Public License as published by the Free Soft- *
- * ware Foundation; either version 2, or (at your option) any later ver- *
- * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
- * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
- * for more details. You should have received a copy of the GNU General *
- * Public License distributed with GNAT; see file COPYING. If not, write *
- * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, *
- * MA 02111-1307, USA. *
- * *
- * As a special exception, if you link this file with other files to *
- * produce an executable, this file does not by itself cause the resulting *
- * executable to be covered by the GNU General Public License. This except- *
- * ion does not however invalidate any other reasons why the executable *
- * file might be covered by the GNU Public License. *
- * *
- * GNAT was originally developed by the GNAT team at New York University. *
- * Extensive contributions were provided by Ada Core Technologies Inc. *
- * *
- ****************************************************************************/
-
-/* This unit contains initialization circuits that are system dependent. A
- major part of the functionality involved involves stack overflow checking.
- The GCC backend generates probe instructions to test for stack overflow.
- For details on the exact approach used to generate these probes, see the
- "Using and Porting GCC" manual, in particular the "Stack Checking" section
- and the subsection "Specifying How Stack Checking is Done". The handlers
- installed by this file are used to handle resulting signals that come
- from these probes failing (i.e. touching protected pages) */
-
-/* The following include is here to meet the published VxWorks requirement
- that the __vxworks header appear before any other include. */
-#ifdef __vxworks
-#include "vxWorks.h"
-#endif
-
-#ifdef IN_RTS
-#include "tconfig.h"
-#include "tsystem.h"
-#include <sys/stat.h>
-#else
-#include "config.h"
-#include "system.h"
-#endif
-
-#include "adaint.h"
-#include "raise.h"
-
-extern void __gnat_raise_program_error (const char *, int);
-
-/* Addresses of exception data blocks for predefined exceptions. */
-extern struct Exception_Data constraint_error;
-extern struct Exception_Data numeric_error;
-extern struct Exception_Data program_error;
-extern struct Exception_Data storage_error;
-extern struct Exception_Data tasking_error;
-extern struct Exception_Data _abort_signal;
-
-#define Lock_Task system__soft_links__lock_task
-extern void (*Lock_Task) PARAMS ((void));
-
-#define Unlock_Task system__soft_links__unlock_task
-extern void (*Unlock_Task) PARAMS ((void));
-
-#define Get_Machine_State_Addr \
- system__soft_links__get_machine_state_addr
-extern struct Machine_State *(*Get_Machine_State_Addr) PARAMS ((void));
-
-#define Check_Abort_Status \
- system__soft_links__check_abort_status
-extern int (*Check_Abort_Status) PARAMS ((void));
-
-#define Raise_From_Signal_Handler \
- ada__exceptions__raise_from_signal_handler
-extern void Raise_From_Signal_Handler PARAMS ((struct Exception_Data *,
- const char *));
-
-#define Propagate_Signal_Exception \
- __gnat_propagate_sig_exc
-extern void Propagate_Signal_Exception
- PARAMS ((struct Machine_State *, struct Exception_Data *, const char *));
-
-/* Copies of global values computed by the binder */
-int __gl_main_priority = -1;
-int __gl_time_slice_val = -1;
-char __gl_wc_encoding = 'n';
-char __gl_locking_policy = ' ';
-char __gl_queuing_policy = ' ';
-char __gl_task_dispatching_policy = ' ';
-int __gl_unreserve_all_interrupts = 0;
-int __gl_exception_tracebacks = 0;
-
-/* Indication of whether synchronous signal handler has already been
- installed by a previous call to adainit */
-int __gnat_handler_installed = 0;
-
-/* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
- is defined. If this is not set them a void implementation will be defined
- at the end of this unit. */
-#undef HAVE_GNAT_INIT_FLOAT
-
-/**********************/
-/* __gnat_set_globals */
-/**********************/
-
-/* This routine is called from the binder generated main program. It copies
- the values for global quantities computed by the binder into the following
- global locations. The reason that we go through this copy, rather than just
- define the global locations in the binder generated file, is that they are
- referenced from the runtime, which may be in a shared library, and the
- binder file is not in the shared library. Global references across library
- boundaries like this are not handled correctly in all systems. */
-
-void
-__gnat_set_globals (main_priority, time_slice_val, wc_encoding, locking_policy,
- queuing_policy, task_dispatching_policy, adafinal_ptr,
- unreserve_all_interrupts, exception_tracebacks)
- int main_priority;
- int time_slice_val;
- int wc_encoding;
- int locking_policy, queuing_policy, task_dispatching_policy;
- void (*adafinal_ptr) PARAMS ((void)) ATTRIBUTE_UNUSED;
- int unreserve_all_interrupts, exception_tracebacks;
-{
- static int already_called = 0;
-
- /* If this procedure has been already called once, check that the
- arguments in this call are consistent with the ones in the previous
- calls. Otherwise, raise a Program_Error exception.
-
- We do not check for consistency of the wide character encoding
- method. This default affects only Wide_Text_IO where no explicit
- coding method is given, and there is no particular reason to let
- this default be affected by the source representation of a library
- in any case.
-
- The value of main_priority is meaningful only when we are invoked
- from the main program elaboration routine of an Ada application.
- Checking the consistency of this parameter should therefore not be
- done. Since it is assured that the main program elaboration will
- always invoke this procedure before any library elaboration
- routine, only the value of main_priority during the first call
- should be taken into account and all the subsequent ones should be
- ignored. Note that the case where the main program is not written
- in Ada is also properly handled, since the default value will then
- be used for this parameter.
-
- For identical reasons, the consistency of time_slice_val should not
- be checked. */
-
- if (already_called)
- {
- if (__gl_locking_policy != locking_policy ||
- __gl_queuing_policy != queuing_policy ||
- __gl_task_dispatching_policy != task_dispatching_policy ||
- __gl_unreserve_all_interrupts != unreserve_all_interrupts ||
- __gl_exception_tracebacks != exception_tracebacks)
- {
- __gnat_raise_program_error (__FILE__, __LINE__);
- }
- return;
- }
- already_called = 1;
-
- __gl_main_priority = main_priority;
- __gl_time_slice_val = time_slice_val;
- __gl_wc_encoding = wc_encoding;
- __gl_locking_policy = locking_policy;
- __gl_queuing_policy = queuing_policy;
- __gl_task_dispatching_policy = task_dispatching_policy;
- __gl_unreserve_all_interrupts = unreserve_all_interrupts;
- __gl_exception_tracebacks = exception_tracebacks;
-}
-
-/*********************/
-/* __gnat_initialize */
-/*********************/
-
-/* __gnat_initialize is called at the start of execution of an Ada program
- (the call is generated by the binder). The standard routine does nothing
- at all; the intention is that this be replaced by system specific
- code where initialization is required. */
-
-/***********************************/
-/* __gnat_initialize (AIX version) */
-/***********************************/
-
-#if defined (_AIX)
-
-/* AiX doesn't have SA_NODEFER */
-
-#define SA_NODEFER 0
-
-#include <sys/time.h>
-
-/* AiX doesn't have nanosleep, but provides nsleep instead */
-
-extern int nanosleep PARAMS ((struct timestruc_t *, struct timestruc_t *));
-static void __gnat_error_handler PARAMS ((int));
-
-int
-nanosleep (Rqtp, Rmtp)
- struct timestruc_t *Rqtp, *Rmtp;
-{
- return nsleep (Rqtp, Rmtp);
-}
-
-#include <signal.h>
-
-static void
-__gnat_error_handler (sig)
- int sig;
-{
- struct Exception_Data *exception;
- const char *msg;
-
- switch (sig)
- {
- case SIGSEGV:
- /* FIXME: we need to detect the case of a *real* SIGSEGV */
- exception = &storage_error;
- msg = "stack overflow or erroneous memory access";
- break;
-
- case SIGBUS:
- exception = &constraint_error;
- msg = "SIGBUS";
- break;
-
- case SIGFPE:
- exception = &constraint_error;
- msg = "SIGFPE";
- break;
-
- default:
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler ()
-{
- struct sigaction act;
-
- /* Set up signal handler to map synchronous signals to appropriate
- exceptions. Make sure that the handler isn't interrupted by another
- signal that might cause a scheduling event! */
-
- act.sa_handler = __gnat_error_handler;
- act.sa_flags = SA_NODEFER | SA_RESTART;
- (void) sigemptyset (&act.sa_mask);
-
- (void) sigaction (SIGABRT, &act, NULL);
- (void) sigaction (SIGFPE, &act, NULL);
-
- if (__gl_unreserve_all_interrupts == 0)
- {
- (void) sigaction (SIGILL, &act, NULL);
- (void) sigaction (SIGSEGV, &act, NULL);
- (void) sigaction (SIGBUS, &act, NULL);
- }
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize ()
-{
-}
-
-/****************************************/
-/* __gnat_initialize (Dec Unix version) */
-/****************************************/
-
-#elif defined(__alpha__) && defined(__osf__) && ! defined(__alpha_vxworks)
-
-/* Note: it seems that __osf__ is defined for the Alpha VXWorks case. Not
- clear that this is reasonable, but in any case we have to be sure to
- exclude this case in the above test. */
-
-#include <signal.h>
-#include <sys/siginfo.h>
-
-static void __gnat_error_handler PARAMS ((int, siginfo_t *,
- struct sigcontext *));
-extern char *__gnat_get_code_loc PARAMS ((struct sigcontext *));
-extern void __gnat_enter_handler PARAMS ((struct sigcontext *, char *));
-extern size_t __gnat_machine_state_length PARAMS ((void));
-
-extern long exc_lookup_gp PARAMS ((char *));
-extern void exc_resume PARAMS ((struct sigcontext *));
-
-static void
-__gnat_error_handler (sig, sip, context)
- int sig;
- siginfo_t *sip;
- struct sigcontext *context;
-{
- struct Exception_Data *exception;
- static int recurse = 0;
- struct sigcontext *mstate;
- const char *msg;
-
- /* If this was an explicit signal from a "kill", just resignal it. */
- if (SI_FROMUSER (sip))
- {
- signal (sig, SIG_DFL);
- kill (getpid(), sig);
- }
-
- /* Otherwise, treat it as something we handle. */
- switch (sig)
- {
- case SIGSEGV:
- /* If the problem was permissions, this is a constraint error.
- Likewise if the failing address isn't maximally aligned or if
- we've recursed.
-
- ??? Using a static variable here isn't task-safe, but it's
- much too hard to do anything else and we're just determining
- which exception to raise. */
- if (sip->si_code == SEGV_ACCERR
- || (((long) sip->si_addr) & 3) != 0
- || recurse)
- {
- exception = &constraint_error;
- msg = "SIGSEGV";
- }
- else
- {
- /* See if the page before the faulting page is accessible. Do that
- by trying to access it. We'd like to simply try to access
- 4096 + the faulting address, but it's not guaranteed to be
- the actual address, just to be on the same page. */
- recurse++;
- ((volatile char *)
- ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
- msg = "stack overflow (or erroneous memory access)";
- exception = &storage_error;
- }
- break;
-
- case SIGBUS:
- exception = &program_error;
- msg = "SIGBUS";
- break;
-
- case SIGFPE:
- exception = &constraint_error;
- msg = "SIGFPE";
- break;
-
- default:
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- recurse = 0;
- mstate = (struct sigcontext *) (*Get_Machine_State_Addr) ();
- if (mstate != 0)
- *mstate = *context;
-
- Raise_From_Signal_Handler (exception, (char *) msg);
-}
-
-void
-__gnat_install_handler ()
-{
- struct sigaction act;
-
- /* Setup signal handler to map synchronous signals to appropriate
- exceptions. Make sure that the handler isn't interrupted by another
- signal that might cause a scheduling event! */
-
- act.sa_handler = (void (*) PARAMS ((int))) __gnat_error_handler;
- act.sa_flags = SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_SIGINFO;
- (void) sigemptyset (&act.sa_mask);
-
- (void) sigaction (SIGABRT, &act, NULL);
- (void) sigaction (SIGFPE, &act, NULL);
-
- if (__gl_unreserve_all_interrupts == 0)
- {
- (void) sigaction (SIGILL, &act, NULL);
- (void) sigaction (SIGSEGV, &act, NULL);
- (void) sigaction (SIGBUS, &act, NULL);
- }
-
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize ()
-{
-}
-
-/* Routines called by 5amastop.adb. */
-
-#define SC_GP 29
-
-char *
-__gnat_get_code_loc (context)
- struct sigcontext *context;
-{
- return (char *) context->sc_pc;
-}
-
-void
-__gnat_enter_handler (context, pc)
- struct sigcontext *context;
- char *pc;
-{
- context->sc_pc = (long) pc;
- context->sc_regs[SC_GP] = exc_lookup_gp (pc);
- exc_resume (context);
-}
-
-size_t
-__gnat_machine_state_length ()
-{
- return sizeof (struct sigcontext);
-}
-
-/***********************************/
-/* __gnat_initialize (HPUX version) */
-/***********************************/
-
-#elif defined (hpux)
-
-#include <signal.h>
-
-static void __gnat_error_handler PARAMS ((int));
-
-static void
-__gnat_error_handler (sig)
- int sig;
-{
- struct Exception_Data *exception;
- char *msg;
-
- switch (sig)
- {
- case SIGSEGV:
- /* FIXME: we need to detect the case of a *real* SIGSEGV */
- exception = &storage_error;
- msg = "stack overflow or erroneous memory access";
- break;
-
- case SIGBUS:
- exception = &constraint_error;
- msg = "SIGBUS";
- break;
-
- case SIGFPE:
- exception = &constraint_error;
- msg = "SIGFPE";
- break;
-
- default:
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler ()
-{
- struct sigaction act;
-
- /* Set up signal handler to map synchronous signals to appropriate
- exceptions. Make sure that the handler isn't interrupted by another
- signal that might cause a scheduling event! Also setup an alternate
- stack region for the handler execution so that stack overflows can be
- handled properly, avoiding a SEGV generation from stack usage by the
- handler itself. */
-
- static char handler_stack [SIGSTKSZ];
-
- stack_t stack;
-
- stack.ss_sp = handler_stack;
- stack.ss_size = SIGSTKSZ;
- stack.ss_flags = 0;
-
- (void) sigaltstack (&stack, NULL);
-
- act.sa_handler = __gnat_error_handler;
- act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK;
- (void) sigemptyset (&act.sa_mask);
-
- (void) sigaction (SIGABRT, &act, NULL);
- (void) sigaction (SIGFPE, &act, NULL);
-
- if (__gl_unreserve_all_interrupts == 0)
- {
- (void) sigaction (SIGILL, &act, NULL);
- (void) sigaction (SIGSEGV, &act, NULL);
- (void) sigaction (SIGBUS, &act, NULL);
- }
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize ()
-{
-}
-
-/*************************************/
-/* __gnat_initialize (GNU/Linux version) */
-/*************************************/
-
-#elif defined (linux) && defined (i386) && !defined (__RT__)
-
-#include <signal.h>
-#include <asm/sigcontext.h>
-
-/* GNU/Linux, which uses glibc, does not define NULL in included
- header files */
-
-#if !defined (NULL)
-#define NULL ((void *) 0)
-#endif
-
-struct Machine_State
-{
- unsigned long eip;
- unsigned long ebx;
- unsigned long esp;
- unsigned long ebp;
- unsigned long esi;
- unsigned long edi;
-};
-
-static void __gnat_error_handler PARAMS ((int));
-
-static void
-__gnat_error_handler (sig)
- int sig;
-{
- struct Exception_Data *exception;
- const char *msg;
- static int recurse = 0;
-
- struct sigcontext *info
- = (struct sigcontext *) (((char *) &sig) + sizeof (int));
-
- /* The Linux kernel does not document how to get the machine state in a
- signal handler, but in fact the necessary data is in a sigcontext_struct
- value that is on the stack immediately above the signal number
- parameter, and the above messing accesses this value on the stack. */
-
- struct Machine_State *mstate;
-
- switch (sig)
- {
- case SIGSEGV:
- /* If the problem was permissions, this is a constraint error.
- Likewise if the failing address isn't maximally aligned or if
- we've recursed.
-
- ??? Using a static variable here isn't task-safe, but it's
- much too hard to do anything else and we're just determining
- which exception to raise. */
- if (recurse)
- {
- exception = &constraint_error;
- msg = "SIGSEGV";
- }
- else
- {
- /* Here we would like a discrimination test to see whether the
- page before the faulting address is accessible. Unfortunately
- Linux seems to have no way of giving us the faulting address.
-
- In versions of a-init.c before 1.95, we had a test of the page
- before the stack pointer using:
-
- recurse++;
- ((volatile char *)
- ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
-
- but that's wrong, since it tests the stack pointer location, and
- the current stack probe code does not move the stack pointer
- until all probes succeed.
-
- For now we simply do not attempt any discrimination at all. Note
- that this is quite acceptable, since a "real" SIGSEGV can only
- occur as the result of an erroneous program */
-
- msg = "stack overflow (or erroneous memory access)";
- exception = &storage_error;
- }
- break;
-
- case SIGBUS:
- exception = &constraint_error;
- msg = "SIGBUS";
- break;
-
- case SIGFPE:
- exception = &constraint_error;
- msg = "SIGFPE";
- break;
-
- default:
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- mstate = (*Get_Machine_State_Addr)();
- if (mstate)
- {
- mstate->eip = info->eip;
- mstate->ebx = info->ebx;
- mstate->esp = info->esp_at_signal;
- mstate->ebp = info->ebp;
- mstate->esi = info->esi;
- mstate->edi = info->edi;
- }
-
- recurse = 0;
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler ()
-{
- struct sigaction act;
-
- /* Set up signal handler to map synchronous signals to appropriate
- exceptions. Make sure that the handler isn't interrupted by another
- signal that might cause a scheduling event! */
-
- act.sa_handler = __gnat_error_handler;
- act.sa_flags = SA_NODEFER | SA_RESTART;
- (void) sigemptyset (&act.sa_mask);
-
- (void) sigaction (SIGABRT, &act, NULL);
- (void) sigaction (SIGFPE, &act, NULL);
-
- if (__gl_unreserve_all_interrupts == 0)
- {
- (void) sigaction (SIGILL, &act, NULL);
- (void) sigaction (SIGSEGV, &act, NULL);
- (void) sigaction (SIGBUS, &act, NULL);
- }
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize ()
-{
-}
-
-/******************************************/
-/* __gnat_initialize (NT-mingw32 version) */
-/******************************************/
-
-#elif defined (__MINGW32__)
-#include <windows.h>
-
-static LONG __gnat_error_handler PARAMS ((PEXCEPTION_POINTERS));
-
-/* __gnat_initialize (mingw32). */
-
-static LONG
-__gnat_error_handler (info)
- PEXCEPTION_POINTERS info;
-{
- static int recurse;
- struct Exception_Data *exception;
- char *msg;
-
- switch (info->ExceptionRecord->ExceptionCode)
- {
- case EXCEPTION_ACCESS_VIOLATION:
- /* If the failing address isn't maximally-aligned or if we've
- recursed, this is a program error. */
- if ((info->ExceptionRecord->ExceptionInformation[1] & 3) != 0
- || recurse)
- {
- exception = &program_error;
- msg = "EXCEPTION_ACCESS_VIOLATION";
- }
- else
- {
- /* See if the page before the faulting page is accessible. Do that
- by trying to access it. */
- recurse++;
- * ((volatile char *) (info->ExceptionRecord->ExceptionInformation[1]
- + 4096));
- exception = &storage_error;
- msg = "stack overflow (or erroneous memory access)";
- }
- break;
-
- case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
- exception = &constraint_error;
- msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
- break;
-
- case EXCEPTION_DATATYPE_MISALIGNMENT:
- exception = &constraint_error;
- msg = "EXCEPTION_DATATYPE_MISALIGNMENT";
- break;
-
- case EXCEPTION_FLT_DENORMAL_OPERAND:
- exception = &constraint_error;
- msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
- break;
-
- case EXCEPTION_FLT_DIVIDE_BY_ZERO:
- exception = &constraint_error;
- msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
- break;
-
- case EXCEPTION_FLT_INVALID_OPERATION:
- exception = &constraint_error;
- msg = "EXCEPTION_FLT_INVALID_OPERATION";
- break;
-
- case EXCEPTION_FLT_OVERFLOW:
- exception = &constraint_error;
- msg = "EXCEPTION_FLT_OVERFLOW";
- break;
-
- case EXCEPTION_FLT_STACK_CHECK:
- exception = &program_error;
- msg = "EXCEPTION_FLT_STACK_CHECK";
- break;
-
- case EXCEPTION_FLT_UNDERFLOW:
- exception = &constraint_error;
- msg = "EXCEPTION_FLT_UNDERFLOW";
- break;
-
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- exception = &constraint_error;
- msg = "EXCEPTION_INT_DIVIDE_BY_ZERO";
- break;
-
- case EXCEPTION_INT_OVERFLOW:
- exception = &constraint_error;
- msg = "EXCEPTION_INT_OVERFLOW";
- break;
-
- case EXCEPTION_INVALID_DISPOSITION:
- exception = &program_error;
- msg = "EXCEPTION_INVALID_DISPOSITION";
- break;
-
- case EXCEPTION_NONCONTINUABLE_EXCEPTION:
- exception = &program_error;
- msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
- break;
-
- case EXCEPTION_PRIV_INSTRUCTION:
- exception = &program_error;
- msg = "EXCEPTION_PRIV_INSTRUCTION";
- break;
-
- case EXCEPTION_SINGLE_STEP:
- exception = &program_error;
- msg = "EXCEPTION_SINGLE_STEP";
- break;
-
- case EXCEPTION_STACK_OVERFLOW:
- exception = &storage_error;
- msg = "EXCEPTION_STACK_OVERFLOW";
- break;
-
- default:
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- recurse = 0;
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler ()
-{
- SetUnhandledExceptionFilter (__gnat_error_handler);
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize ()
-{
-
- /* Initialize floating-point coprocessor. This call is needed because
- the MS libraries default to 64-bit precision instead of 80-bit
- precision, and we require the full precision for proper operation,
- given that we have set Max_Digits etc with this in mind */
-
- __gnat_init_float ();
-
- /* initialize a lock for a process handle list - see a-adaint.c for the
- implementation of __gnat_portable_no_block_spawn, __gnat_portable_wait */
- __gnat_plist_init();
-}
-
-/**************************************/
-/* __gnat_initialize (Interix version) */
-/**************************************/
-
-#elif defined (__INTERIX)
-
-#include <signal.h>
-
-static void __gnat_error_handler PARAMS ((int));
-
-static void
-__gnat_error_handler (sig)
- int sig;
-{
- struct Exception_Data *exception;
- char *msg;
-
- switch (sig)
- {
- case SIGSEGV:
- exception = &storage_error;
- msg = "stack overflow or erroneous memory access";
- break;
-
- case SIGBUS:
- exception = &constraint_error;
- msg = "SIGBUS";
- break;
-
- case SIGFPE:
- exception = &constraint_error;
- msg = "SIGFPE";
- break;
-
- default:
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler ()
-{
- struct sigaction act;
-
- /* Set up signal handler to map synchronous signals to appropriate
- exceptions. Make sure that the handler isn't interrupted by another
- signal that might cause a scheduling event! */
-
- act.sa_handler = __gnat_error_handler;
- act.sa_flags = 0;
- (void) sigemptyset (&act.sa_mask);
-
- /* Handlers for signals besides SIGSEGV cause c974013 to hang */
-/* (void) sigaction (SIGILL, &act, NULL); */
-/* (void) sigaction (SIGABRT, &act, NULL); */
-/* (void) sigaction (SIGFPE, &act, NULL); */
-/* (void) sigaction (SIGBUS, &act, NULL); */
- if (__gl_unreserve_all_interrupts == 0)
- {
- (void) sigaction (SIGSEGV, &act, NULL);
- }
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize ()
-{
- __gnat_init_float ();
-}
-
-/**************************************/
-/* __gnat_initialize (LynxOS version) */
-/**************************************/
-
-#elif defined (__Lynx__)
-
-void
-__gnat_initialize ()
-{
- __gnat_init_float ();
-}
-
-/*********************************/
-/* __gnat_install_handler (Lynx) */
-/*********************************/
-
-void
-__gnat_install_handler ()
-{
- __gnat_handler_installed = 1;
-}
-
-/****************************/
-/* __gnat_initialize (OS/2) */
-/****************************/
-
-#elif defined (__EMX__) /* OS/2 dependent initialization */
-
-void
-__gnat_initialize ()
-{
-}
-
-/*********************************/
-/* __gnat_install_handler (OS/2) */
-/*********************************/
-
-void
-__gnat_install_handler ()
-{
- __gnat_handler_installed = 1;
-}
-
-/***********************************/
-/* __gnat_initialize (SGI version) */
-/***********************************/
-
-#elif defined (sgi)
-
-#include <signal.h>
-#include <siginfo.h>
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#define SIGADAABORT 48
-#define SIGNAL_STACK_SIZE 4096
-#define SIGNAL_STACK_ALIGNMENT 64
-
-struct Machine_State
-{
- sigcontext_t context;
-};
-
-static void __gnat_error_handler PARAMS ((int, int, sigcontext_t *));
-
-static void
-__gnat_error_handler (sig, code, sc)
- int sig;
- int code;
- sigcontext_t *sc;
-{
- struct Machine_State *mstate;
- struct Exception_Data *exception;
- char *msg;
-
- int i;
-
- switch (sig)
- {
- case SIGSEGV:
- if (code == EFAULT)
- {
- exception = &program_error;
- msg = "SIGSEGV: (Invalid virtual address)";
- }
- else if (code == ENXIO)
- {
- exception = &program_error;
- msg = "SIGSEGV: (Read beyond mapped object)";
- }
- else if (code == ENOSPC)
- {
- exception = &program_error; /* ??? storage_error ??? */
- msg = "SIGSEGV: (Autogrow for file failed)";
- }
- else if (code == EACCES)
- {
- /* ??? Re-add smarts to further verify that we launched
- the stack into a guard page, not an attempt to
- write to .text or something */
- exception = &storage_error;
- msg = "SIGSEGV: (stack overflow or erroneous memory access)";
- }
- else
- {
- /* Just in case the OS guys did it to us again. Sometimes
- they fail to document all of the valid codes that are
- passed to signal handlers, just in case someone depends
- on knowing all the codes */
- exception = &program_error;
- msg = "SIGSEGV: (Undocumented reason)";
- }
- break;
-
- case SIGBUS:
- /* Map all bus errors to Program_Error. */
- exception = &program_error;
- msg = "SIGBUS";
- break;
-
- case SIGFPE:
- /* Map all fpe errors to Constraint_Error. */
- exception = &constraint_error;
- msg = "SIGFPE";
- break;
-
- case SIGADAABORT:
- if ((*Check_Abort_Status) ())
- {
- exception = &_abort_signal;
- msg = "";
- }
- else
- return;
-
- break;
-
- default:
- /* Everything else is a Program_Error. */
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- mstate = (*Get_Machine_State_Addr)();
- if (mstate != 0)
- memcpy ((void *) mstate, (const void *) sc, sizeof (sigcontext_t));
-
- Raise_From_Signal_Handler (exception, msg);
-
-}
-
-void
-__gnat_install_handler ()
-{
- stack_t ss;
- struct sigaction act;
-
- /* Setup signal handler to map synchronous signals to appropriate
- exceptions. Make sure that the handler isn't interrupted by another
- signal that might cause a scheduling event! */
-
- act.sa_handler = __gnat_error_handler;
- act.sa_flags = SA_NODEFER + SA_RESTART;
- (void) sigfillset (&act.sa_mask);
- (void) sigemptyset (&act.sa_mask);
-
- (void) sigaction (SIGABRT, &act, NULL);
- (void) sigaction (SIGFPE, &act, NULL);
-
- if (__gl_unreserve_all_interrupts == 0)
- {
- (void) sigaction (SIGILL, &act, NULL);
- (void) sigaction (SIGSEGV, &act, NULL);
- (void) sigaction (SIGBUS, &act, NULL);
- }
- (void) sigaction (SIGADAABORT, &act, NULL);
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize ()
-{
-}
-
-/*************************************************/
-/* __gnat_initialize (Solaris and SunOS version) */
-/*************************************************/
-
-#elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
-
-#include <signal.h>
-#include <siginfo.h>
-
-static void __gnat_error_handler PARAMS ((int, siginfo_t *));
-
-static void
-__gnat_error_handler (sig, sip)
- int sig;
- siginfo_t *sip;
-{
- struct Exception_Data *exception;
- static int recurse = 0;
- char *msg;
-
- /* If this was an explicit signal from a "kill", just resignal it. */
- if (SI_FROMUSER (sip))
- {
- signal (sig, SIG_DFL);
- kill (getpid(), sig);
- }
-
- /* Otherwise, treat it as something we handle. */
- switch (sig)
- {
- case SIGSEGV:
- /* If the problem was permissions, this is a constraint error.
- Likewise if the failing address isn't maximally aligned or if
- we've recursed.
-
- ??? Using a static variable here isn't task-safe, but it's
- much too hard to do anything else and we're just determining
- which exception to raise. */
- if (sip->si_code == SEGV_ACCERR
- || (((long) sip->si_addr) & 3) != 0
- || recurse)
- {
- exception = &constraint_error;
- msg = "SIGSEGV";
- }
- else
- {
- /* See if the page before the faulting page is accessible. Do that
- by trying to access it. We'd like to simply try to access
- 4096 + the faulting address, but it's not guaranteed to be
- the actual address, just to be on the same page. */
- recurse++;
- ((volatile char *)
- ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
- exception = &storage_error;
- msg = "stack overflow (or erroneous memory access)";
- }
- break;
-
- case SIGBUS:
- exception = &program_error;
- msg = "SIGBUS";
- break;
-
- case SIGFPE:
- exception = &constraint_error;
- msg = "SIGFPE";
- break;
-
- default:
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- recurse = 0;
-
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler ()
-{
- struct sigaction act;
-
- /* Set up signal handler to map synchronous signals to appropriate
- exceptions. Make sure that the handler isn't interrupted by another
- signal that might cause a scheduling event! */
-
- act.sa_handler = __gnat_error_handler;
- act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
- (void) sigemptyset (&act.sa_mask);
-
- (void) sigaction (SIGABRT, &act, NULL);
-
- if (__gl_unreserve_all_interrupts == 0)
- {
- (void) sigaction (SIGFPE, &act, NULL);
- (void) sigaction (SIGSEGV, &act, NULL);
- (void) sigaction (SIGBUS, &act, NULL);
- }
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize ()
-{
-}
-
-/***********************************/
-/* __gnat_initialize (SNI version) */
-/***********************************/
-
-#elif defined (__sni__)
-
-/* SNI needs special defines and includes */
-
-#define _XOPEN_SOURCE
-#define _POSIX_SOURCE
-#include <signal.h>
-
-extern size_t __gnat_getpagesize PARAMS ((void));
-static void __gnat_error_handler PARAMS ((int));
-
-/* The run time needs this function which is a #define in SNI */
-
-size_t
-__gnat_getpagesize ()
-{
- return getpagesize ();
-}
-
-static void
-__gnat_error_handler (sig)
- int sig;
-{
- struct Exception_Data *exception;
- char *msg;
-
- switch (sig)
- {
- case SIGSEGV:
- /* FIXME: we need to detect the case of a *real* SIGSEGV */
- exception = &storage_error;
- msg = "stack overflow or erroneous memory access";
- break;
-
- case SIGBUS:
- exception = &constraint_error;
- msg = "SIGBUS";
- break;
-
- case SIGFPE:
- exception = &constraint_error;
- msg = "SIGFPE";
- break;
-
- default:
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler ()
-{
- struct sigaction act;
-
- /* Set up signal handler to map synchronous signals to appropriate
- exceptions. Make sure that the handler isn't interrupted by another
- signal that might cause a scheduling event! */
-
- act.sa_handler = __gnat_error_handler;
- act.sa_flags = SA_NODEFER | SA_RESTART;
- (void) sigemptyset (&act.sa_mask);
-
- (void) sigaction (SIGABRT, &act, NULL);
- (void) sigaction (SIGFPE, &act, NULL);
-
- if (__gl_unreserve_all_interrupts == 0)
- {
- (void) sigaction (SIGILL, &act, NULL);
- (void) sigaction (SIGSEGV, &act, NULL);
- (void) sigaction (SIGBUS, &act, NULL);
- }
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize ()
-{
-}
-
-/***********************************/
-/* __gnat_initialize (VMS version) */
-/***********************************/
-
-#elif defined (VMS)
-
-/* The prehandler actually gets control first on a condition. It swaps the
- stack pointer and calls the handler (__gnat_error_handler). */
-extern long __gnat_error_prehandler ();
-
-extern char *__gnat_error_prehandler_stack; /* Alternate signal stack */
-
-/* Conditions that don't have an Ada exception counterpart must raise
- Non_Ada_Error. Since this is defined in s-auxdec, it should only be
- referenced by user programs, not the compiler or tools. Hence the
- #ifdef IN_RTS. */
-
-#ifdef IN_RTS
-#define Non_Ada_Error system__aux_dec__non_ada_error
-extern struct Exception_Data Non_Ada_Error;
-
-#define Coded_Exception system__vms_exception_table__coded_exception
-extern struct Exception_Data *Coded_Exception (int);
-#endif
-
-/* Define macro symbols for the VMS conditions that become Ada exceptions.
- Most of these are also defined in the header file ssdef.h which has not
- yet been converted to be recoginized by Gnu C. Some, which couldn't be
- located, are assigned names based on the DEC test suite tests which
- raise them. */
-
-#define SS$_ACCVIO 12
-#define SS$_DEBUG 1132
-#define SS$_INTDIV 1156
-#define SS$_HPARITH 1284
-#define SS$_STKOVF 1364
-#define SS$_RESIGNAL 2328
-#define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
-#define SS$_CE24VRU 3253636 /* Write to unopened file */
-#define SS$_C980VTE 3246436 /* AST requests time slice */
-#define CMA$_EXIT_THREAD 4227492
-#define CMA$_EXCCOPLOS 4228108
-#define CMA$_ALERTED 4227460
-
-struct descriptor_s {unsigned short len, mbz; char *adr; };
-
-static long __gnat_error_handler PARAMS ((int *, void *));
-
-static long
-__gnat_error_handler (sigargs, mechargs)
- int *sigargs;
- void *mechargs;
-{
- struct Exception_Data *exception = 0;
- char *msg = "";
- char message [256];
- long prvhnd;
- struct descriptor_s msgdesc;
- int msg_flag = 0x000f; /* 1 bit for each of the four message parts */
- unsigned short outlen;
- char curr_icb [544];
- long curr_invo_handle;
- long *mstate;
-
- /* Resignaled conditions aren't effected by by pragma Import_Exception */
-
- switch (sigargs[1])
- {
-
- case CMA$_EXIT_THREAD:
- return SS$_RESIGNAL;
-
- case SS$_DEBUG: /* Gdb attach, resignal to merge activate gdbstub. */
- return SS$_RESIGNAL;
-
- case 1409786: /* Nickerson bug #33 ??? */
- return SS$_RESIGNAL;
-
- case 1381050: /* Nickerson bug #33 ??? */
- return SS$_RESIGNAL;
-
- case 11829410: /* Resignalled as Use_Error for CE10VRC */
- return SS$_RESIGNAL;
-
- }
-
-#ifdef IN_RTS
- /* See if it's an imported exception. Mask off severity bits. */
- exception = Coded_Exception (sigargs [1] & 0xfffffff8);
- if (exception)
- {
- msgdesc.len = 256;
- msgdesc.mbz = 0;
- msgdesc.adr = message;
- SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
- message [outlen] = 0;
- msg = message;
-
- exception->Name_Length = 19;
- /* The full name really should be get sys$getmsg returns. ??? */
- exception->Full_Name = "IMPORTED_EXCEPTION";
- exception->Import_Code = sigargs [1] & 0xfffffff8;
- }
-#endif
-
- if (exception == 0)
- switch (sigargs[1])
- {
- case SS$_ACCVIO:
- if (sigargs[3] == 0)
- {
- exception = &constraint_error;
- msg = "access zero";
- }
- else
- {
- exception = &storage_error;
- msg = "stack overflow (or erroneous memory access)";
- }
- break;
-
- case SS$_STKOVF:
- exception = &storage_error;
- msg = "stack overflow";
- break;
-
- case SS$_INTDIV:
- exception = &constraint_error;
- msg = "division by zero";
- break;
-
- case SS$_HPARITH:
-#ifndef IN_RTS
- return SS$_RESIGNAL; /* toplev.c handles for compiler */
-#else
- {
- exception = &constraint_error;
- msg = "arithmetic error";
- }
-#endif
- break;
-
- case MTH$_FLOOVEMAT:
- exception = &constraint_error;
- msg = "floating overflow in math library";
- break;
-
- case SS$_CE24VRU:
- exception = &constraint_error;
- msg = "";
- break;
-
- case SS$_C980VTE:
- exception = &program_error;
- msg = "";
- break;
-
- default:
-#ifndef IN_RTS
- exception = &program_error;
-#else
- /* User programs expect Non_Ada_Error to be raised, reference
- DEC Ada test CXCONDHAN. */
- exception = &Non_Ada_Error;
-#endif
- msgdesc.len = 256;
- msgdesc.mbz = 0;
- msgdesc.adr = message;
- SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
- message [outlen] = 0;
- msg = message;
- break;
- }
-
- mstate = (long *) (*Get_Machine_State_Addr) ();
- if (mstate != 0)
- {
- LIB$GET_CURR_INVO_CONTEXT (&curr_icb);
- LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
- LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
- curr_invo_handle = LIB$GET_INVO_HANDLE (&curr_icb);
- *mstate = curr_invo_handle;
- }
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler ()
-{
- long prvhnd;
- char *c;
-
- c = (char *) malloc (2049);
-
- __gnat_error_prehandler_stack = &c[2048];
-
- /* __gnat_error_prehandler is an assembly function. */
- SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
- __gnat_handler_installed = 1;
-}
-
-void
-__gnat_initialize()
-{
-}
-
-/***************************************/
-/* __gnat_initialize (VXWorks version) */
-/***************************************/
-
-#elif defined(__vxworks)
-
-#include <signal.h>
-#include <taskLib.h>
-#include <intLib.h>
-#include <iv.h>
-
-static void __gnat_init_handler PARAMS ((int));
-extern int __gnat_inum_to_ivec PARAMS ((int));
-static void __gnat_error_handler PARAMS ((int, int, struct sigcontext *));
-
-static void
-__gnat_int_handler (interr)
- int interr;
-{
- /* Note that we should use something like Raise_From_Int_Handler here, but
- for now Raise_From_Signal_Handler will do the job. ??? */
-
- Raise_From_Signal_Handler (&storage_error, "stack overflow");
-}
-
-/* Used for stack-checking on VxWorks. Must be task-local in
- tasking programs */
-
-void *__gnat_stack_limit = NULL;
-
-#ifndef __alpha_vxworks
-
-/* getpid is used by s-parint.adb, but is not defined by VxWorks, except
- on Alpha VxWorks */
-
-extern long getpid PARAMS ((void));
-
-long
-getpid ()
-{
- return taskIdSelf ();
-}
-#endif
-
-/* This is needed by the GNAT run time to handle Vxworks interrupts */
-int
-__gnat_inum_to_ivec (num)
- int num;
-{
- return INUM_TO_IVEC (num);
-}
-
-static void
-__gnat_error_handler (sig, code, sc)
- int sig;
- int code;
- struct sigcontext *sc;
-{
- struct Exception_Data *exception;
- sigset_t mask;
- int result;
- char *msg;
-
- /* VxWorks will always mask out the signal during the signal handler and
- will reenable it on a longjmp. GNAT does not generate a longjmp to
- return from a signal handler so the signal will still be masked unless
- we unmask it. */
- (void) sigprocmask (SIG_SETMASK, NULL, &mask);
- sigdelset (&mask, sig);
- (void) sigprocmask (SIG_SETMASK, &mask, NULL);
-
- /* VxWorks will suspend the task when it gets a hardware exception. We
- take the liberty of resuming the task for the application. */
- if (taskIsSuspended (taskIdSelf ()) != 0)
- (void) taskResume (taskIdSelf ());
-
- switch (sig)
- {
- case SIGFPE:
- exception = &constraint_error;
- msg = "SIGFPE";
- break;
- case SIGILL:
- exception = &constraint_error;
- msg = "SIGILL";
- break;
- case SIGSEGV:
- exception = &program_error;
- msg = "SIGSEGV";
- break;
- case SIGBUS:
- exception = &program_error;
- msg = "SIGBUS";
- break;
- default:
- exception = &program_error;
- msg = "unhandled signal";
- }
-
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler ()
-{
- struct sigaction act;
-
- /* Setup signal handler to map synchronous signals to appropriate
- exceptions. Make sure that the handler isn't interrupted by another
- signal that might cause a scheduling event! */
-
- act.sa_handler = __gnat_error_handler;
- act.sa_flags = SA_SIGINFO | SA_ONSTACK;
- (void) sigemptyset (&act.sa_mask);
-
- (void) sigaction (SIGFPE, &act, NULL);
-
- if (__gl_unreserve_all_interrupts == 0)
- {
- (void) sigaction (SIGILL, &act, NULL);
- (void) sigaction (SIGSEGV, &act, NULL);
- (void) sigaction (SIGBUS, &act, NULL);
- }
- __gnat_handler_installed = 1;
-}
-
-#define HAVE_GNAT_INIT_FLOAT
-
-void
-__gnat_init_float ()
-{
-#if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT)
- /* Disable overflow/underflow exceptions on the PPC processor, this is needed
- to get correct Ada semantic */
- asm ("mtfsb0 25");
- asm ("mtfsb0 26");
-#endif
-}
-
-void
-__gnat_initialize ()
-{
- TASK_DESC pTaskDesc;
-
- if (taskInfoGet (taskIdSelf (), &pTaskDesc) != OK)
- printErr ("Cannot get task info");
-
- __gnat_stack_limit = (void *) pTaskDesc.td_pStackLimit;
-
- __gnat_init_float ();
-
-#ifdef __mips_vxworks
-#if 0
- /* For now remove this handler, since it is causing interferences with gdb */
-
- /* Connect the overflow trap directly to the __gnat_int_handler routine
- as it is not converted to a signal by VxWorks. */
-
- intConnect (INUM_TO_IVEC (IV_TRAP_VEC), &__gnat_int_handler, IV_TRAP_VEC);
-#endif
-#endif
-}
-
-/***************************************/
-/* __gnat_initialize (RTEMS version) */
-/***************************************/
-
-#elif defined(__rtems__)
-
-extern void __gnat_install_handler ();
-
-/* For RTEMS, each bsp will provide a custom __gnat_install_handler (). */
-
-void
-__gnat_initialize ()
-{
- __gnat_install_handler ();
-}
-
-#else
-
-/* For all other versions of GNAT, the initialize routine and handler
- installation do nothing */
-
-/***************************************/
-/* __gnat_initialize (default version) */
-/***************************************/
-
-void
-__gnat_initialize ()
-{
-}
-
-/********************************************/
-/* __gnat_install_handler (default version) */
-/********************************************/
-
-void
-__gnat_install_handler ()
-{
- __gnat_handler_installed = 1;
-}
-
-#endif
-
-/*********************/
-/* __gnat_init_float */
-/*********************/
-
-/* This routine is called as each process thread is created, for possible
- initialization of the FP processor. This version is used under INTERIX,
- WIN32 and could be used under OS/2 */
-
-#if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
- || defined (__Lynx__)
-
-#define HAVE_GNAT_INIT_FLOAT
-
-void
-__gnat_init_float ()
-{
-#if defined (__i386__) || defined (i386)
-
- /* This is used to properly initialize the FPU on an x86 for each
- process thread. */
-
- asm ("finit");
-
-#endif /* Defined __i386__ */
-}
-#endif
-
-#ifndef HAVE_GNAT_INIT_FLOAT
-
-/* All targets without a specific __gnat_init_float will use an empty one */
-void
-__gnat_init_float ()
-{
-}
-#endif