installed by this file are used to catch the resulting signals that come
from these probes failing (i.e. touching protected pages). */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* This file should be kept synchronized with 2sinit.ads, 2sinit.adb,
s-init-ae653-cert.adb and s-init-xi-sparc.adb. All these files implement
the required functionality for different targets. */
#include "vxWorks.h"
#endif
+#ifdef __ANDROID__
+#undef linux
+#endif
+
#ifdef IN_RTS
#include "tconfig.h"
#include "tsystem.h"
#include "adaint.h"
#include "raise.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern void __gnat_raise_program_error (const char *, int);
/* Addresses of exception data blocks for predefined exceptions. Tasking_Error
- is not used in this unit, and the abort signal is only used on IRIX. */
+ is not used in this unit, and the abort signal is only used on IRIX.
+ ??? Revisit this part since IRIX is no longer supported. */
extern struct Exception_Data constraint_error;
extern struct Exception_Data numeric_error;
extern struct Exception_Data program_error;
int __gl_num_interrupt_states = 0;
int __gl_unreserve_all_interrupts = 0;
int __gl_exception_tracebacks = 0;
-int __gl_zero_cost_exceptions = 0;
int __gl_detect_blocking = 0;
int __gl_default_stack_size = -1;
int __gl_leap_seconds_support = 0;
int __gl_canonical_streams = 0;
+/* This value is not used anymore, but kept for bootstrapping purpose. */
+int __gl_zero_cost_exceptions = 0;
+
/* Indication of whether synchronous signal handler has already been
installed by a previous call to adainit. */
int __gnat_handler_installed = 0;
}
/*****************/
-/* Tru64 section */
+/* HP-UX section */
/*****************/
-#elif defined(__alpha__) && defined(__osf__)
+#elif defined (__hpux__)
#include <signal.h>
-#include <sys/siginfo.h>
-
-extern char *__gnat_get_code_loc (struct sigcontext *);
-extern void __gnat_set_code_loc (struct sigcontext *, char *);
-extern size_t __gnat_machine_state_length (void);
-
-#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
-
-void
-__gnat_adjust_context_for_raise (int signo, void *ucontext)
-{
- struct sigcontext *sigcontext = (struct sigcontext *) ucontext;
-
- /* The unwinder expects the signal context to contain the address of the
- faulting instruction. For SIGFPE, this depends on the trap shadow
- situation (see man ieee). We nonetheless always compensate for it,
- considering that PC designates the instruction following the one that
- trapped. This is not necessarily true but corresponds to what we have
- always observed. */
- if (signo == SIGFPE)
- sigcontext->sc_pc--;
-}
-
-static void
-__gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
-{
- struct Exception_Data *exception;
- static int recurse = 0;
- const char *msg;
-
- /* Adjusting is required for every fault context, so adjust for this one
- now, before we possibly trigger a recursive fault below. */
- __gnat_adjust_context_for_raise (sig, ucontext);
-
- /* If this was an explicit signal from a "kill", just resignal it. */
- if (SI_FROMUSER (si))
- {
- 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 (si->si_code == SEGV_ACCERR
- || (long) si->si_addr == 0
- || (((long) si->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) si->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, CONST_CAST (char *, msg));
-}
-
-void
-__gnat_install_handler (void)
-{
- 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 (*) (int)) __gnat_error_handler;
- act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
- sigemptyset (&act.sa_mask);
-
- /* Do not install handlers if interrupt state is "System". */
- if (__gnat_get_interrupt_state (SIGABRT) != 's')
- sigaction (SIGABRT, &act, NULL);
- if (__gnat_get_interrupt_state (SIGFPE) != 's')
- sigaction (SIGFPE, &act, NULL);
- if (__gnat_get_interrupt_state (SIGILL) != 's')
- sigaction (SIGILL, &act, NULL);
- if (__gnat_get_interrupt_state (SIGSEGV) != 's')
- sigaction (SIGSEGV, &act, NULL);
- if (__gnat_get_interrupt_state (SIGBUS) != 's')
- sigaction (SIGBUS, &act, NULL);
-
- __gnat_handler_installed = 1;
-}
+#include <sys/ucontext.h>
-/* Routines called by s-mastop-tru64.adb. */
+#if defined (IN_RTS) && defined (__ia64__)
-#define SC_GP 29
+#include <sys/uc_access.h>
-char *
-__gnat_get_code_loc (struct sigcontext *context)
-{
- return (char *) context->sc_pc;
-}
+#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
void
-__gnat_set_code_loc (struct sigcontext *context, char *pc)
+__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
{
- context->sc_pc = (long) pc;
-}
+ ucontext_t *uc = (ucontext_t *) ucontext;
+ uint64_t ip;
-size_t
-__gnat_machine_state_length (void)
-{
- return sizeof (struct sigcontext);
+ /* Adjust on itanium, as GetIPInfo is not supported. */
+ __uc_get_ip (uc, &ip);
+ __uc_set_ip (uc, ip + 1);
}
+#endif /* IN_RTS && __ia64__ */
-/*****************/
-/* HP-UX section */
-/*****************/
-
-#elif defined (__hpux__)
-
-#include <signal.h>
-#include <sys/ucontext.h>
+/* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
+ propagation after the required low level adjustments. */
static void
__gnat_error_handler (int sig,
struct Exception_Data *exception;
const char *msg;
+ __gnat_adjust_context_for_raise (sig, ucontext);
+
switch (sig)
{
case SIGSEGV:
if (signo == SIGSEGV && pc && *pc == 0x00240c83)
mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
#elif defined (__x86_64__)
- unsigned long *pc = (unsigned long *)mcontext->gregs[REG_RIP];
- /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode. */
- if (signo == SIGSEGV && pc && (*pc & 0xffffffffff) == 0x00240c8348)
+ unsigned long long *pc = (unsigned long long *)mcontext->gregs[REG_RIP];
+ if (signo == SIGSEGV && pc
+ /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode. */
+ && ((*pc & 0xffffffffffLL) == 0x00240c8348LL
+ /* The pattern may also be "orl $0x0,(%esp)" for a probe in
+ x32 mode. */
+ || (*pc & 0xffffffffLL) == 0x00240c83LL))
mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
#elif defined (__ia64__)
/* ??? The IA-64 unwinder doesn't compensate for signals. */
__gnat_handler_installed = 1;
}
-/****************/
-/* IRIX Section */
-/****************/
-
-#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
-
-#define Check_Abort_Status \
- system__soft_links__check_abort_status
-extern int (*Check_Abort_Status) (void);
-
-extern struct Exception_Data _abort_signal;
-
-/* We are not setting the SA_SIGINFO bit in the sigaction flags when
- connecting that handler, with the effects described in the sigaction
- man page:
-
- SA_SIGINFO If set and the signal is caught, sig is passed as the
- first argument to the signal-catching function. If the
- second argument is not equal to NULL, it points to a
- siginfo_t structure containing the reason why the
- signal was generated [see siginfo(5)]; the third
- argument points to a ucontext_t structure containing
- the receiving process's context when the signal was
- delivered [see ucontext(5)]. If cleared and the signal
- is caught, the first argument is also the signal number
- but the second argument is the signal code identifying
- the cause of the signal. The third argument points to a
- sigcontext_t structure containing the receiving
- process's context when the signal was delivered. This
- is the default behavior (see signal(5) for more
- details). Additionally, when SA_SIGINFO is set for a
- signal, multiple occurrences of that signal will be
- queued for delivery in FIFO order (see sigqueue(3) for
- a more detailed explanation of this concept), if those
- occurrences of that signal were generated using
- sigqueue(3). */
-
-static void
-__gnat_error_handler (int sig, siginfo_t *reason, void *uc ATTRIBUTE_UNUSED)
-{
- /* This handler is installed with SA_SIGINFO cleared, but there's no
- prototype for the resulting alternative three-argument form, so we
- have to hack around this by casting reason to the int actually
- passed. */
- int code = (int) reason;
- struct Exception_Data *exception;
- const char *msg;
-
- 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 || code == EEXIST)
- {
- /* ??? We handle stack overflows here, some of which do trigger
- SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
- the documented valid codes for SEGV in the signal(5) man
- page. */
-
- /* ??? 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";
- }
-
- Raise_From_Signal_Handler (exception, msg);
-}
-
-void
-__gnat_install_handler (void)
-{
- 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!
-
- The handler is installed with SA_SIGINFO cleared, but there's no
- C++ prototype for the three-argument form, so fake it by using
- sa_sigaction and casting the arguments instead. */
-
- act.sa_sigaction = __gnat_error_handler;
- act.sa_flags = SA_NODEFER + SA_RESTART;
- sigfillset (&act.sa_mask);
- sigemptyset (&act.sa_mask);
-
- /* Do not install handlers if interrupt state is "System". */
- if (__gnat_get_interrupt_state (SIGABRT) != 's')
- sigaction (SIGABRT, &act, NULL);
- if (__gnat_get_interrupt_state (SIGFPE) != 's')
- sigaction (SIGFPE, &act, NULL);
- if (__gnat_get_interrupt_state (SIGILL) != 's')
- sigaction (SIGILL, &act, NULL);
- if (__gnat_get_interrupt_state (SIGSEGV) != 's')
- sigaction (SIGSEGV, &act, NULL);
- if (__gnat_get_interrupt_state (SIGBUS) != 's')
- sigaction (SIGBUS, &act, NULL);
- if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
- sigaction (SIGADAABORT, &act, NULL);
-
- __gnat_handler_installed = 1;
-}
-
/*******************/
/* LynxOS Section */
/*******************/
#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 recognized by GNU C. */
+ It would be better to just include <ssdef.h> */
-/* Defining these as macros, as opposed to external addresses, allows
- them to be used in a case statement below. */
#define SS$_ACCVIO 12
#define SS$_HPARITH 1284
+#define SS$_INTDIV 1156
#define SS$_STKOVF 1364
#define SS$_RESIGNAL 2328
+#define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
+
+/* The following codes must be resignalled, and not handled here. */
+
/* These codes are in standard message libraries. */
extern int C$_SIGKILL;
extern int SS$_DEBUG;
extern int LIB$_KEYNOTFOU;
extern int LIB$_ACTIMAGE;
-#define CMA$_EXIT_THREAD 4227492
-#define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
-#define SS$_INTDIV 1156
/* These codes are non standard, which is to say the author is
not sure if they are defined in the standard message libraries
so keep them as macros for now. */
#define RDB$_STREAM_EOF 20480426
#define FDL$_UNPRIKW 11829410
+#define CMA$_EXIT_THREAD 4227492
+
+struct cond_sigargs {
+ unsigned int sigarg;
+ unsigned int sigargval;
+};
+
+struct cond_subtests {
+ unsigned int num;
+ const struct cond_sigargs sigargs[];
+};
struct cond_except {
unsigned int cond;
const struct Exception_Data *except;
+ unsigned int needs_adjust; /* 1 = adjust PC, 0 = no adjust */
+ const struct cond_subtests *subtests;
};
struct descriptor_s {
/* DEC Ada specific conditions. */
static const struct cond_except dec_ada_cond_except_table [] = {
- {ADA$_PROGRAM_ERROR, &program_error},
- {ADA$_USE_ERROR, &Use_Error},
- {ADA$_KEYSIZERR, &program_error},
- {ADA$_STAOVF, &storage_error},
- {ADA$_CONSTRAINT_ERRO, &constraint_error},
- {ADA$_IOSYSFAILED, &Device_Error},
- {ADA$_LAYOUT_ERROR, &Layout_Error},
- {ADA$_STORAGE_ERROR, &storage_error},
- {ADA$_DATA_ERROR, &Data_Error},
- {ADA$_DEVICE_ERROR, &Device_Error},
- {ADA$_END_ERROR, &End_Error},
- {ADA$_MODE_ERROR, &Mode_Error},
- {ADA$_NAME_ERROR, &Name_Error},
- {ADA$_STATUS_ERROR, &Status_Error},
- {ADA$_NOT_OPEN, &Use_Error},
- {ADA$_ALREADY_OPEN, &Use_Error},
- {ADA$_USE_ERROR, &Use_Error},
- {ADA$_UNSUPPORTED, &Use_Error},
- {ADA$_FAC_MODE_MISMAT, &Use_Error},
- {ADA$_ORG_MISMATCH, &Use_Error},
- {ADA$_RFM_MISMATCH, &Use_Error},
- {ADA$_RAT_MISMATCH, &Use_Error},
- {ADA$_MRS_MISMATCH, &Use_Error},
- {ADA$_MRN_MISMATCH, &Use_Error},
- {ADA$_KEY_MISMATCH, &Use_Error},
- {ADA$_MAXLINEXC, &constraint_error},
- {ADA$_LINEXCMRS, &constraint_error},
+ {ADA$_PROGRAM_ERROR, &program_error, 0, 0},
+ {ADA$_USE_ERROR, &Use_Error, 0, 0},
+ {ADA$_KEYSIZERR, &program_error, 0, 0},
+ {ADA$_STAOVF, &storage_error, 0, 0},
+ {ADA$_CONSTRAINT_ERRO, &constraint_error, 0, 0},
+ {ADA$_IOSYSFAILED, &Device_Error, 0, 0},
+ {ADA$_LAYOUT_ERROR, &Layout_Error, 0, 0},
+ {ADA$_STORAGE_ERROR, &storage_error, 0, 0},
+ {ADA$_DATA_ERROR, &Data_Error, 0, 0},
+ {ADA$_DEVICE_ERROR, &Device_Error, 0, 0},
+ {ADA$_END_ERROR, &End_Error, 0, 0},
+ {ADA$_MODE_ERROR, &Mode_Error, 0, 0},
+ {ADA$_NAME_ERROR, &Name_Error, 0, 0},
+ {ADA$_STATUS_ERROR, &Status_Error, 0, 0},
+ {ADA$_NOT_OPEN, &Use_Error, 0, 0},
+ {ADA$_ALREADY_OPEN, &Use_Error, 0, 0},
+ {ADA$_USE_ERROR, &Use_Error, 0, 0},
+ {ADA$_UNSUPPORTED, &Use_Error, 0, 0},
+ {ADA$_FAC_MODE_MISMAT, &Use_Error, 0, 0},
+ {ADA$_ORG_MISMATCH, &Use_Error, 0, 0},
+ {ADA$_RFM_MISMATCH, &Use_Error, 0, 0},
+ {ADA$_RAT_MISMATCH, &Use_Error, 0, 0},
+ {ADA$_MRS_MISMATCH, &Use_Error, 0, 0},
+ {ADA$_MRN_MISMATCH, &Use_Error, 0, 0},
+ {ADA$_KEY_MISMATCH, &Use_Error, 0, 0},
+ {ADA$_MAXLINEXC, &constraint_error, 0, 0},
+ {ADA$_LINEXCMRS, &constraint_error, 0, 0},
#if 0
/* Already handled by a pragma Import_Exception
in Aux_IO_Exceptions */
- {ADA$_LOCK_ERROR, &Lock_Error},
- {ADA$_EXISTENCE_ERROR, &Existence_Error},
- {ADA$_KEY_ERROR, &Key_Error},
+ {ADA$_LOCK_ERROR, &Lock_Error, 0, 0},
+ {ADA$_EXISTENCE_ERROR, &Existence_Error, 0, 0},
+ {ADA$_KEY_ERROR, &Key_Error, 0, 0},
#endif
- {0, 0}
+ {0, 0, 0, 0}
};
#endif /* IN_RTS */
-/* Non-DEC Ada specific conditions. We could probably also put
- SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
-static const struct cond_except cond_except_table [] = {
- {MTH$_FLOOVEMAT, &constraint_error},
- {SS$_INTDIV, &constraint_error},
- {0, 0}
+/* Non-DEC Ada specific conditions that map to Ada exceptions. */
+
+/* Subtest for ACCVIO Constraint_Error, kept for compatibility,
+ in hindsight should have just made ACCVIO == Storage_Error. */
+#define ACCVIO_VIRTUAL_ADDR 3
+static const struct cond_subtests accvio_c_e =
+ {1, /* number of subtests below */
+ {
+ {ACCVIO_VIRTUAL_ADDR, 0}
+ }
+ };
+
+/* Macro flag to adjust PC which gets off by one for some conditions,
+ not sure if this is reliably true, PC could be off by more for
+ HPARITH for example, unless a trapb is inserted. */
+#define NEEDS_ADJUST 1
+
+static const struct cond_except system_cond_except_table [] = {
+ {MTH$_FLOOVEMAT, &constraint_error, 0, 0},
+ {SS$_INTDIV, &constraint_error, 0, 0},
+ {SS$_HPARITH, &constraint_error, NEEDS_ADJUST, 0},
+ {SS$_ACCVIO, &constraint_error, NEEDS_ADJUST, &accvio_c_e},
+ {SS$_ACCVIO, &storage_error, NEEDS_ADJUST, 0},
+ {SS$_STKOVF, &storage_error, NEEDS_ADJUST, 0},
+ {0, 0, 0, 0}
};
/* To deal with VMS conditions and their mapping to Ada exceptions,
for (i = 0, iexcept = 0;
cond_resignal_table [i]
- && !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
+ && !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
i++);
return iexcept;
return 0;
}
+/* Scan TABLE for a match for the condition contained in SIGARGS,
+ and return the entry, or the empty entry if no match found. */
+
+static const struct cond_except *
+ scan_conditions ( int *sigargs, const struct cond_except *table [])
+{
+ int i;
+ struct cond_except entry;
+
+ /* Scan the exception condition table for a match and fetch
+ the associated GNAT exception pointer. */
+ for (i = 0; (*table) [i].cond; i++)
+ {
+ unsigned int match = LIB$MATCH_COND (&sigargs [1], &(*table) [i].cond);
+ const struct cond_subtests *subtests = (*table) [i].subtests;
+
+ if (match)
+ {
+ if (!subtests)
+ {
+ return &(*table) [i];
+ }
+ else
+ {
+ unsigned int ii;
+ int num = (*subtests).num;
+
+ /* Perform subtests to differentiate exception. */
+ for (ii = 0; ii < num; ii++)
+ {
+ unsigned int arg = (*subtests).sigargs [ii].sigarg;
+ unsigned int argval = (*subtests).sigargs [ii].sigargval;
+
+ if (sigargs [arg] != argval)
+ {
+ num = 0;
+ break;
+ }
+ }
+
+ /* All subtests passed. */
+ if (num == (*subtests).num)
+ return &(*table) [i];
+ }
+ }
+ }
+
+ /* No match, return the null terminating entry. */
+ return &(*table) [i];
+}
+
long
__gnat_handle_vms_condition (int *sigargs, void *mechargs)
{
struct Exception_Data *exception = 0;
+ unsigned int needs_adjust = 0;
Exception_Code base_code;
struct descriptor_s gnat_facility = {4, 0, "GNAT"};
char message [Default_Exception_Msg_Max_Length];
Import_Exception. */
if (__gnat_resignal_p (sigargs [1]))
return SS$_RESIGNAL;
+#ifndef IN_RTS
+ /* toplev.c handles this for compiler. */
+ if (sigargs [1] == SS$_HPARITH)
+ return SS$_RESIGNAL;
+#endif
#ifdef IN_RTS
/* See if it's an imported exception. Beware that registered exceptions
are bound to their base code, with the severity bits masked off. */
base_code = Base_Code_In ((Exception_Code) sigargs[1]);
exception = Coded_Exception (base_code);
-
- if (exception)
- {
- message[0] = 0;
-
- /* Subtract PC & PSL fields which messes with PUTMSG. */
- sigargs[0] -= 2;
- SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
- sigargs[0] += 2;
- msg = message;
-
- exception->Name_Length = 19;
- /* ??? The full name really should be get SYS$GETMSG returns. */
- exception->Full_Name = "IMPORTED_EXCEPTION";
- exception->Import_Code = base_code;
-
-#ifdef __IA64
- /* Do not adjust the program counter as already points to the next
- instruction (just after the call to LIB$STOP). */
- Raise_From_Signal_Handler (exception, msg);
-#endif
- }
#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";
- }
- __gnat_adjust_context_for_raise (SS$_ACCVIO, (void *)mechargs);
- break;
-
- case SS$_STKOVF:
- exception = &storage_error;
- msg = "stack overflow";
- __gnat_adjust_context_for_raise (SS$_STKOVF, (void *)mechargs);
- break;
-
- case SS$_HPARITH:
-#ifndef IN_RTS
- return SS$_RESIGNAL; /* toplev.c handles for compiler */
-#else
- exception = &constraint_error;
- msg = "arithmetic error";
- __gnat_adjust_context_for_raise (SS$_HPARITH, (void *)mechargs);
-#endif
- break;
-
- default:
#ifdef IN_RTS
+ {
+ int i;
+ struct cond_except cond;
+ const struct cond_except *cond_table;
+ const struct cond_except *cond_tables [] = {dec_ada_cond_except_table,
+ system_cond_except_table,
+ 0};
+
+ i = 0;
+ while ((cond_table = cond_tables[i++]) && !exception)
{
- int i;
-
- /* Scan the DEC Ada exception condition table for a match and fetch
- the associated GNAT exception pointer. */
- for (i = 0;
- dec_ada_cond_except_table [i].cond &&
- !LIB$MATCH_COND (&sigargs [1],
- &dec_ada_cond_except_table [i].cond);
- i++);
- exception = (struct Exception_Data *)
- dec_ada_cond_except_table [i].except;
-
- if (!exception)
- {
- /* Scan the VMS standard condition table for a match and fetch
- the associated GNAT exception pointer. */
- for (i = 0;
- cond_except_table[i].cond &&
- !LIB$MATCH_COND (&sigargs[1], &cond_except_table[i].cond);
- i++);
- exception = (struct Exception_Data *)
- cond_except_table [i].except;
-
- if (!exception)
- /* User programs expect Non_Ada_Error to be raised, reference
- DEC Ada test CXCONDHAN. */
- exception = &Non_Ada_Error;
- }
+ cond = *scan_conditions (sigargs, &cond_table);
+ exception = (struct Exception_Data *) cond.except;
}
+
+ if (exception)
+ needs_adjust = cond.needs_adjust;
+ else
+ /* User programs expect Non_Ada_Error to be raised if no match,
+ reference DEC Ada test CXCONDHAN. */
+ exception = &Non_Ada_Error;
+ }
#else
- exception = &program_error;
+ {
+ /* Pretty much everything is just a program error in the compiler */
+ exception = &program_error;
+ }
#endif
- message[0] = 0;
- /* Subtract PC & PSL fields which messes with PUTMSG. */
- sigargs[0] -= 2;
- SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
- sigargs[0] += 2;
- msg = message;
- break;
- }
+
+ message[0] = 0;
+ /* Subtract PC & PSL fields as per ABI for SYS$PUTMSG. */
+ sigargs[0] -= 2;
+ SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
+ /* Add back PC & PSL fields as per ABI for SYS$PUTMSG. */
+ sigargs[0] += 2;
+ msg = message;
+
+ if (needs_adjust)
+ __gnat_adjust_context_for_raise (sigargs [1], (void *)mechargs);
Raise_From_Signal_Handler (exception, msg);
}
if (signo == SS$_HPARITH)
{
/* Sub one to the address of the instruction signaling the condition,
- located in the sigargs array. */
+ located in the sigargs array. */
CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
CHF$SIGNAL_ARRAY * sigargs
- = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
+ = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
int vcount = sigargs->chf$is_sig_args;
int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
#endif
}
+#if defined(__leon__) && defined(_WRS_KERNEL)
+/* For LEON VxWorks we need to install a trap handler for stack overflow */
+
+extern void excEnt (void);
+/* VxWorks exception handler entry */
+
+struct trap_entry {
+ unsigned long inst_first;
+ unsigned long inst_second;
+ unsigned long inst_third;
+ unsigned long inst_fourth;
+};
+/* Four instructions representing entries in the trap table */
+
+struct trap_entry *trap_0_entry;
+/* We will set the location of the entry for software trap 0 in the trap
+ table. */
+#endif
+
void
__gnat_install_handler (void)
{
sigaction (SIGSEGV, &act, NULL);
sigaction (SIGBUS, &act, NULL);
+#if defined(__leon__) && defined(_WRS_KERNEL)
+ /* Specific to the LEON VxWorks kernel run-time library */
+
+ /* For stack checking the compiler triggers a software trap 0 (ta 0) in
+ case of overflow (we use the stack limit mechanism). We need to install
+ the trap handler here for this software trap (the OS does not handle
+ it) as if it were a data_access_exception (trap 9). We do the same as
+ if we put in the trap table a VXSPARC_BAD_TRAP(9). Software trap 0 is
+ located at vector 0x80, and each entry takes 4 words. */
+
+ trap_0_entry = (struct trap_entry *)(intVecBaseGet () + 0x80 * 4);
+
+ /* mov 0x9, %l7 */
+
+ trap_0_entry->inst_first = 0xae102000 + 9;
+
+ /* sethi %hi(excEnt), %l6 */
+
+ /* The 22 most significant bits of excEnt are obtained shifting 10 times
+ to the right. */
+
+ trap_0_entry->inst_second = 0x2d000000 + ((unsigned long)excEnt >> 10);
+
+ /* jmp %l6+%lo(excEnt) */
+
+ /* The 10 least significant bits of excEnt are obtained by masking */
+
+ trap_0_entry->inst_third = 0x81c5a000 + ((unsigned long)excEnt & 0x3ff);
+
+ /* rd %psr, %l0 */
+
+ trap_0_entry->inst_fourth = 0xa1480000;
+#endif
+
__gnat_handler_installed = 1;
}