aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/init.c')
-rw-r--r--gcc/ada/init.c64
1 files changed, 56 insertions, 8 deletions
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index c8de26b..d7653c7 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -1665,8 +1665,6 @@ __gnat_install_handler ()
#include "private/vThreadsP.h"
#endif
-void __gnat_error_handler (int, void *, struct sigcontext *);
-
#ifndef __RTP__
/* Directly vectored Interrupt routines are not supported when using RTPs. */
@@ -1677,7 +1675,7 @@ extern int __gnat_inum_to_ivec (int);
int
__gnat_inum_to_ivec (int num)
{
- return INUM_TO_IVEC (num);
+ return (int) INUM_TO_IVEC (num);
}
#endif
@@ -1711,8 +1709,8 @@ __gnat_clear_exception_count (void)
/* Handle different SIGnal to exception mappings in different VxWorks
versions. */
static void
-__gnat_map_signal (int sig, void *si ATTRIBUTE_UNUSED,
- struct sigcontext *sc ATTRIBUTE_UNUSED)
+__gnat_map_signal (int sig, siginfo_t *si ATTRIBUTE_UNUSED,
+ void *sc ATTRIBUTE_UNUSED)
{
struct Exception_Data *exception;
const char *msg;
@@ -1799,6 +1797,56 @@ __gnat_map_signal (int sig, void *si ATTRIBUTE_UNUSED,
msg = "unhandled signal";
}
+ /* On ARM VxWorks 6.x, the guard page is left in a RWX state by the kernel
+ after being violated, so subsequent violations aren't detected. Even if
+ this defect is fixed, it seems dubious to rely on the signal value alone,
+ so we retrieve the address of the guard page from the TCB and compare it
+ with the page that is violated (pREG 12 in the context) and re-arm that
+ page if there's a match. Additionally we're are assured this is a
+ genuine stack overflow condition and and set the message and exception
+ to that effect. */
+#if defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6)
+
+ /* We re-arm the guard page by re-setting it's attributes, however the
+ protection bits are just the low order seven (0x3f).
+ 0x00040 is the Valid Mask
+ 0x00f00 are Cache attributes
+ 0xff000 are Special attributes
+ We don't meddle with the 0xfff40 attributes. */
+
+#define PAGE_SIZE 4096
+#define MMU_ATTR_PROT_MSK 0x0000003f /* Protection Mask. */
+#define GUARD_PAGE_PROT 0x8101 /* Found by experiment. */
+
+ if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL)
+ {
+ TASK_ID tid = taskIdSelf ();
+ WIND_TCB *pTcb = taskTcb (tid);
+ unsigned long Violated_Page
+ = ((struct sigcontext *) sc)->sc_pregs->r[12] & ~(PAGE_SIZE - 1);
+
+ if ((unsigned long) (pTcb->pStackEnd - PAGE_SIZE) == Violated_Page)
+ {
+ vmStateSet (NULL, Violated_Page,
+ PAGE_SIZE, MMU_ATTR_PROT_MSK, GUARD_PAGE_PROT);
+ exception = &storage_error;
+
+ switch (sig)
+ {
+ case SIGSEGV:
+ msg = "SIGSEGV: stack overflow";
+ break;
+ case SIGBUS:
+ msg = "SIGBUS: stack overflow";
+ break;
+ case SIGILL:
+ msg = "SIGILL: stack overflow";
+ break;
+ }
+ }
+ }
+#endif /* defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6) */
+
__gnat_clear_exception_count ();
Raise_From_Signal_Handler (exception, msg);
}
@@ -1806,8 +1854,8 @@ __gnat_map_signal (int sig, void *si ATTRIBUTE_UNUSED,
/* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
propagation after the required low level adjustments. */
-void
-__gnat_error_handler (int sig, void *si, struct sigcontext *sc)
+static void
+__gnat_error_handler (int sig, siginfo_t *si, void *sc)
{
sigset_t mask;
@@ -1865,7 +1913,7 @@ __gnat_install_handler (void)
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_sigaction = __gnat_error_handler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigemptyset (&act.sa_mask);