OSDN Git Service

2010-01-27 Vincent Celier <celier@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / init.c
index d2c22ea..28498c4 100644 (file)
@@ -6,24 +6,23 @@
  *                                                                          *
  *                          C Implementation File                           *
  *                                                                          *
- *          Copyright (C) 1992-2008, Free Software Foundation, Inc.         *
+ *          Copyright (C) 1992-2009, 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- *
+ * ware  Foundation;  either version 3,  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,  51  Franklin  Street,  Fifth  Floor, *
- * Boston, MA 02110-1301, USA.                                              *
+ * or FITNESS FOR A PARTICULAR PURPOSE.                                     *
  *                                                                          *
- * 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.                        *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception,   *
+ * version 3.1, as published by the Free Software Foundation.               *
+ *                                                                          *
+ * You should have received a copy of the GNU General Public License and    *
+ * a copy of the GCC Runtime Library Exception along with this program;     *
+ * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
+ * <http://www.gnu.org/licenses/>.                                          *
  *                                                                          *
  * GNAT was originally developed  by the GNAT team at  New York University. *
  * Extensive contributions were provided by Ada Core Technologies Inc.      *
@@ -54,7 +53,7 @@
 #include "tsystem.h"
 #include <sys/stat.h>
 
-/* We don't have libiberty, so us malloc.  */
+/* We don't have libiberty, so use malloc.  */
 #define xmalloc(S) malloc (S)
 #else
 #include "config.h"
@@ -179,7 +178,7 @@ __gnat_get_specific_dispatching (int priority)
    file now sets the __gl_* variables directly.  */
 
 void
-__gnat_set_globals ()
+__gnat_set_globals (void)
 {
 }
 
@@ -217,24 +216,10 @@ nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
 
 static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
 
-/* __gnat_adjust_context_for_raise - see comments along with the default
-   version later in this file.  */
-
-void
-__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
-{
-  /* We need to adjust the "Instruction Address Register" value, part of a
-     'struct mstsave' wrapped as a jumpbuf in the mcontext field designated by
-     the signal data pointer we get.  See sys/context.h + sys/mstsave.h  */
-
-  mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
-  mcontext->jmp_context.iar++;
-}
-
-#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
-
 static void
-__gnat_error_handler (int sig, siginfo_t * si, void * uc)
+__gnat_error_handler (int sig,
+                     siginfo_t * si ATTRIBUTE_UNUSED,
+                     void * uc ATTRIBUTE_UNUSED)
 {
   struct Exception_Data *exception;
   const char *msg;
@@ -262,7 +247,6 @@ __gnat_error_handler (int sig, siginfo_t * si, void * uc)
       msg = "unhandled signal";
     }
 
-  __gnat_adjust_context_for_raise (sig, uc);
   Raise_From_Signal_Handler (exception, msg);
 }
 
@@ -308,33 +292,25 @@ 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);
 
-/* __gnat_adjust_context_for_raise - see comments along with the default
-   version later in this file.  */
-
 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
 
 void
-__gnat_adjust_context_for_raise (int signo, void *context)
+__gnat_adjust_context_for_raise (int signo, void *ucontext)
 {
-  struct sigcontext * sigcontext = (struct sigcontext *) context;
-
-  /* The fallback code fetches the faulting insn address from sc_pc, so
-     adjust that when need be.  For SIGFPE, the required adjustment depends
-     on the trap shadow situation (see man ieee).  */
+  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)
-    {
-      /* ??? We never adjust here, considering that sc_pc always
-        designates the instruction following the one which trapped.
-        This is not necessarily true but corresponds to what we have
-        always observed.  */
-    }
-  else
-    sigcontext->sc_pc ++;
+    sigcontext->sc_pc--;
 }
 
 static void
-__gnat_error_handler
-  (int sig, siginfo_t *sip, struct sigcontext *context)
+__gnat_error_handler (int sig, siginfo_t *sip, struct sigcontext *context)
 {
   struct Exception_Data *exception;
   static int recurse = 0;
@@ -399,7 +375,7 @@ __gnat_error_handler
     }
 
   recurse = 0;
-  Raise_From_Signal_Handler (exception, (char *) msg);
+  Raise_From_Signal_Handler (exception, (const char *) msg);
 }
 
 void
@@ -464,29 +440,11 @@ __gnat_machine_state_length (void)
 static void
 __gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext);
 
-#if defined (__hppa__)
-
-/* __gnat_adjust_context_for_raise - see comments along with the default
-   version later in this file.  */
-
-#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
-
-void
-__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
-{
-  mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
-
-  if (UseWideRegs (mcontext))
-    mcontext->ss_wide.ss_32.ss_pcoq_head_lo ++;
-  else
-    mcontext->ss_narrow.ss_pcoq_head ++;
-}
-
-#endif
-
 static void
 __gnat_error_handler
-  (int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED, void *ucontext)
+  (int sig,
+   siginfo_t *siginfo ATTRIBUTE_UNUSED,
+   void *ucontext ATTRIBUTE_UNUSED)
 {
   struct Exception_Data *exception;
   const char *msg;
@@ -514,8 +472,6 @@ __gnat_error_handler
       msg = "unhandled signal";
     }
 
-  __gnat_adjust_context_for_raise (sig, ucontext);
-
   Raise_From_Signal_Handler (exception, msg);
 }
 
@@ -568,8 +524,7 @@ __gnat_install_handler (void)
 /* GNU/Linux Section */
 /*********************/
 
-#elif defined (linux) && (defined (i386) || defined (__x86_64__) \
-                          || defined (__ia64__) || defined (__powerpc__))
+#elif defined (linux)
 
 #include <signal.h>
 
@@ -617,19 +572,20 @@ void fake_linux_sigemptyset (sigset_t *set) {
 
 static void __gnat_error_handler (int, siginfo_t *siginfo, void *ucontext);
 
-/* __gnat_adjust_context_for_raise - see comments along with the default
-   version later in this file.  */
+#if defined (i386) || defined (__x86_64__) || defined (__ia64__)
 
 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
 
 void
 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
 {
-#ifndef __powerpc__
   mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
-#endif
 
-  /* On the i386 and x86-64 architectures, stack checking is performed by
+  /* On the i386 and x86-64 architectures, we specifically detect calls to
+     the null address and entirely fold the not-yet-fully-established frame
+     to prevent it from stopping the unwinding.
+
+     On the i386 and x86-64 architectures, stack checking is performed by
      means of probes with moving stack pointer, that is to say the probed
      address is always the value of the stack pointer.  Upon hitting the
      guard page, the stack pointer therefore points to an inaccessible
@@ -642,37 +598,53 @@ __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
      by the time the EH return is executed.
 
      We therefore adjust the saved value of the stack pointer by the size
-     of one page, in order to make sure that it points to an accessible
-     address in case it's used as the target CFA.  The stack checking code
-     guarantees that this page is unused by the time this happens.  */
+     of one page + a small dope of 4 words, in order to make sure that it
+     points to an accessible address in case it's used as the target CFA.
+     The stack checking code guarantees that this address is unused by the
+     time this happens.  */
 
 #if defined (i386)
-  unsigned long pattern = *(unsigned long *)mcontext->gregs[REG_EIP];
+  unsigned long *pc = (unsigned long *)mcontext->gregs[REG_EIP];
+  /* The call insn pushes the return address onto the stack.  Pop it.  */
+  if (pc == NULL)
+    {
+      mcontext->gregs[REG_EIP] = *(unsigned long *)mcontext->gregs[REG_ESP];
+      mcontext->gregs[REG_ESP] += 4;
+    }
   /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode.  */
-  if (signo == SIGSEGV && pattern == 0x00240c83)
-    mcontext->gregs[REG_ESP] += 4096;
-  mcontext->gregs[REG_EIP]++;
+  else if (signo == SIGSEGV && *pc == 0x00240c83)
+    mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
 #elif defined (__x86_64__)
-  unsigned long pattern = *(unsigned long *)mcontext->gregs[REG_RIP];
+  unsigned long *pc = (unsigned long *)mcontext->gregs[REG_RIP];
+  /* The call insn pushes the return address onto the stack.  Pop it.  */
+  if (pc == NULL)
+    {
+      mcontext->gregs[REG_RIP] = *(unsigned long *)mcontext->gregs[REG_RSP];
+      mcontext->gregs[REG_RSP] += 8;
+    }
   /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode.  */
-  if (signo == SIGSEGV && (pattern & 0xffffffffff) == 0x00240c8348)
-    mcontext->gregs[REG_RSP] += 4096;
-  mcontext->gregs[REG_RIP]++;
+  else if (signo == SIGSEGV && (*pc & 0xffffffffff) == 0x00240c8348)
+    mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
 #elif defined (__ia64__)
+  /* ??? The IA-64 unwinder doesn't compensate for signals.  */
   mcontext->sc_ip++;
-#elif defined (__powerpc__)
-  ((ucontext_t *) ucontext)->uc_mcontext.regs->nip++;
 #endif
 }
 
+#endif
+
 static void
 __gnat_error_handler (int sig,
                       siginfo_t *siginfo ATTRIBUTE_UNUSED,
                       void *ucontext)
 {
   struct Exception_Data *exception;
-  const char *msg;
   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);
 
   switch (sig)
     {
@@ -729,15 +701,8 @@ __gnat_error_handler (int sig,
       exception = &program_error;
       msg = "unhandled signal";
     }
-  recurse = 0;
-
-  /* We adjust the interrupted context here (and not in the
-     MD_FALLBACK_FRAME_STATE_FOR macro) because recent versions of the Native
-     POSIX Thread Library (NPTL) are compiled with DWARF-2 unwind information,
-     and hence the later macro is never executed for signal frames.  */
-
-  __gnat_adjust_context_for_raise (sig, ucontext);
 
+  recurse = 0;
   Raise_From_Signal_Handler (exception, msg);
 }
 
@@ -1045,28 +1010,46 @@ __gnat_install_handler(void)
 /* Likewise regarding how the "instruction pointer" register slot can
    be identified in signal machine contexts.  We have either "REG_PC"
    or "PC" at hand, depending on the target CPU and Solaris version.  */
-
 #if !defined (REG_PC)
 #define REG_PC PC
 #endif
 
-static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
-
-/* __gnat_adjust_context_for_raise - see comments along with the default
-   version later in this file.  */
+static void __gnat_error_handler (int, siginfo_t *, void *);
 
 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
 
 void
-__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
-                                void * ucontext)
+__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
 {
-  mcontext_t *mcontext = & ((ucontext_t *)ucontext)->uc_mcontext;
-  mcontext->gregs[REG_PC] += (1 - RETURN_ADDR_OFFSET);
+  mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
+  unsigned long *pc = (unsigned long *)mcontext->gregs[REG_PC];
+
+  /* We specifically detect calls to the null address and entirely fold
+     the not-yet-fully-established frame to prevent it from stopping the
+     unwinding.  */
+  if (pc == NULL)
+#if defined (__sparc)
+    /* The call insn moves the return address into %o7.  Move it back.  */
+    mcontext->gregs[REG_PC] = mcontext->gregs[REG_O7];
+#elif defined (i386)
+    {
+      /* The call insn pushes the return address onto the stack.  Pop it.  */
+      mcontext->gregs[REG_PC] = *(unsigned long *)mcontext->gregs[UESP];
+      mcontext->gregs[UESP] += 4;
+    }
+#elif defined (__x86_64__)
+    {
+      /* The call insn pushes the return address onto the stack.  Pop it.  */
+      mcontext->gregs[REG_PC] = *(unsigned long *)mcontext->gregs[REG_RSP];
+      mcontext->gregs[REG_RSP] += 8;
+    }
+#else
+#error architecture not supported on Solaris
+#endif
 }
 
 static void
-__gnat_error_handler (int sig, siginfo_t *sip, ucontext_t *uctx)
+__gnat_error_handler (int sig, siginfo_t *sip, void *ucontext)
 {
   struct Exception_Data *exception;
   static int recurse = 0;
@@ -1074,16 +1057,8 @@ __gnat_error_handler (int sig, siginfo_t *sip, ucontext_t *uctx)
 
   /* 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, (void *)uctx);
-
-  /* If this was an explicit signal from a "kill", just resignal it.  */
-  if (SI_FROMUSER (sip))
-    {
-      signal (sig, SIG_DFL);
-      kill (getpid(), sig);
-    }
+  __gnat_adjust_context_for_raise (sig, ucontext);
 
-  /* Otherwise, treat it as something we handle.  */
   switch (sig)
     {
     case SIGSEGV:
@@ -1095,6 +1070,7 @@ __gnat_error_handler (int sig, siginfo_t *sip, ucontext_t *uctx)
         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 == 0
          || (((long) sip->si_addr) & 3) != 0
          || recurse)
        {
@@ -1131,7 +1107,6 @@ __gnat_error_handler (int sig, siginfo_t *sip, ucontext_t *uctx)
     }
 
   recurse = 0;
-
   Raise_From_Signal_Handler (exception, msg);
 }
 
@@ -1167,6 +1142,10 @@ __gnat_install_handler (void)
 
 #elif defined (VMS)
 
+/* Routine called from binder to override default feature values. */
+void __gnat_set_features ();
+int __gnat_features_set = 0;
+
 long __gnat_error_handler (int *, void *);
 
 #ifdef __IA64
@@ -1200,6 +1179,7 @@ extern char *__gnat_error_prehandler_stack;   /* Alternate signal stack */
 #define SS$_RESIGNAL        2328
 
 /* These codes are in standard message libraries.  */
+extern int C$_SIGKILL;
 extern int CMA$_EXIT_THREAD;
 extern int SS$_DEBUG;
 extern int SS$_INTDIV;
@@ -1376,6 +1356,7 @@ typedef int
 resignal_predicate (int code);
 
 const int *cond_resignal_table [] = {
+  &C$_SIGKILL,
   &CMA$_EXIT_THREAD,
   &SS$_DEBUG,
   &LIB$_KEYNOTFOU,
@@ -1680,6 +1661,54 @@ __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
 
 #endif
 
+/* Feature logical name and global variable address pair */
+struct feature {char *name; int* gl_addr;};
+
+/* Default values for GNAT features set by environment. */
+int __gl_no_malloc_64 = 0;
+
+/* Array feature logical names and global variable addresses */
+static struct feature features[] = {
+  {"GNAT$NO_MALLOC_64", &__gl_no_malloc_64},
+  {0, 0}
+};
+
+void __gnat_set_features ()
+{
+  struct descriptor_s name_desc, result_desc;
+  int i, status;
+  unsigned short rlen;
+
+#define MAXEQUIV 10
+  char buff [MAXEQUIV];
+
+  /* Loop through features array and test name for enable/disable */
+  for (i=0; features [i].name; i++)
+    {
+       name_desc.len = strlen (features [i].name);
+       name_desc.mbz = 0;
+       name_desc.adr = features [i].name;
+
+       result_desc.len = MAXEQUIV - 1;
+       result_desc.mbz = 0;
+       result_desc.adr = buff;
+
+       status = LIB$GET_LOGICAL (&name_desc, &result_desc, &rlen);
+
+       if (((status & 1) == 1) && (rlen < MAXEQUIV))
+         buff [rlen] = 0;
+       else
+         strcpy (buff, "");
+
+       if (strcmp (buff, "ENABLE") == 0)
+          *features [i].gl_addr = 1;
+       else if (strcmp (buff, "DISABLE") == 0)
+          *features [i].gl_addr = 0;
+    }
+
+    __gnat_features_set = 1;
+}
+
 /*******************/
 /* FreeBSD Section */
 /*******************/
@@ -1691,19 +1720,6 @@ __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
 #include <unistd.h>
 
 static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
-void __gnat_adjust_context_for_raise (int, void*);
-
-/* __gnat_adjust_context_for_raise - see comments along with the default
-   version later in this file.  */
-
-#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
-
-void
-__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
-{
-  mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
-  mcontext->mc_eip++;
-}
 
 static void
 __gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
@@ -1739,7 +1755,6 @@ __gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
       msg = "unhandled signal";
     }
 
-  __gnat_adjust_context_for_raise (sig, ucontext);
   Raise_From_Signal_Handler (exception, msg);
 }
 
@@ -1813,8 +1828,9 @@ getpid (void)
 }
 #endif
 
-/* VxWorks expects the field excCnt to be zeroed when a signal is handled.
-   The VxWorks version of longjmp does this; GCC's builtin_longjmp doesn't.  */
+/* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
+   handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
+   doesn't.  */
 void
 __gnat_clear_exception_count (void)
 {
@@ -1825,34 +1841,6 @@ __gnat_clear_exception_count (void)
 #endif
 }
 
-
-/* VxWorks context adjustment for targets that need/support it.  */
-
-void __gnat_adjust_context_for_raise (int, void*);
-
-#if defined (_ARCH_PPC) && !defined (VTHREADS) && !defined (__RTP__)
-
-#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
-
-/* We need the constant and structure definitions describing the machine
-   state.  Part of this is normally retrieved from the VxWorks "regs.h" but
-   #including it here gets the GCC internals instance of this file instead.
-   We need to #include the version we need directly here, and prevent the
-   possibly indirect inclusion of the GCC one, as its contents is useless to
-   us and it depends on several other headers that we don't have at hand.  */
-#include <arch/ppc/regsPpc.h>
-#define GCC_REGS_H
-#include <sigLib.h>
-
-void
-__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *sigcontext)
-{
-  REG_SET * mcontext = ((struct sigcontext *) sigcontext)->sc_pregs;
-  mcontext->pc++;
-}
-
-#endif
-
 /* Handle different SIGnal to exception mappings in different VxWorks
    versions.   */
 static void
@@ -1868,42 +1856,71 @@ __gnat_map_signal (int sig)
       msg = "SIGFPE";
       break;
 #ifdef VTHREADS
+#ifdef __VXWORKSMILS__
+    case SIGILL:
+      exception = &storage_error;
+      msg = "SIGILL: possible stack overflow";
+      break;
+    case SIGSEGV:
+      exception = &storage_error;
+      msg = "SIGSEGV";
+      break;
+    case SIGBUS:
+      exception = &program_error;
+      msg = "SIGBUS";
+      break;
+#else
     case SIGILL:
       exception = &constraint_error;
       msg = "Floating point exception or SIGILL";
       break;
     case SIGSEGV:
       exception = &storage_error;
-      msg = "SIGSEGV: possible stack overflow";
+      msg = "SIGSEGV";
       break;
     case SIGBUS:
       exception = &storage_error;
       msg = "SIGBUS: possible stack overflow";
       break;
-#else
-#ifdef __RTP__
-    /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
-       since stack checking uses the probing mechanism.  */
+#endif
+#elif (_WRS_VXWORKS_MAJOR == 6)
     case SIGILL:
       exception = &constraint_error;
       msg = "SIGILL";
       break;
+#ifdef __RTP__
+    /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
+       since stack checking uses the probing mechanism.  */
     case SIGSEGV:
       exception = &storage_error;
       msg = "SIGSEGV: possible stack overflow";
       break;
+    case SIGBUS:
+      exception = &program_error;
+      msg = "SIGBUS";
+      break;
+#else
+      /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
+    case SIGSEGV:
+      exception = &storage_error;
+      msg = "SIGSEGV";
+      break;
+    case SIGBUS:
+      exception = &storage_error;
+      msg = "SIGBUS: possible stack overflow";
+      break;
+#endif
 #else
-    /* In kernel mode a SIGILL is most likely due to a stack overflow,
+    /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
        since stack checking uses the stack limit mechanism.  */
     case SIGILL:
       exception = &storage_error;
       msg = "SIGILL: possible stack overflow";
       break;
     case SIGSEGV:
-      exception = &program_error;
+      exception = &storage_error;
       msg = "SIGSEGV";
       break;
-#endif
     case SIGBUS:
       exception = &program_error;
       msg = "SIGBUS";
@@ -1935,7 +1952,6 @@ __gnat_error_handler (int sig, void * si ATTRIBUTE_UNUSED,
   sigdelset (&mask, sig);
   sigprocmask (SIG_SETMASK, &mask, NULL);
 
-  __gnat_adjust_context_for_raise (sig, (void *)sc);
   __gnat_map_signal (sig);
 }
 
@@ -1972,9 +1988,19 @@ __gnat_init_float (void)
      overflow settings are an OS configuration issue.  The instructions
      below have no effect.  */
 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
+#if defined (__SPE__)
+  {
+     const unsigned long spefscr_mask = 0xfffffff3;
+     unsigned long spefscr;
+     asm ("mfspr  %0, 512" : "=r" (spefscr));
+     spefscr = spefscr & spefscr_mask;
+     asm ("mtspr 512, %0\n\tisync" : : "r" (spefscr));
+  }
+#else
   asm ("mtfsb0 25");
   asm ("mtfsb0 26");
 #endif
+#endif
 
 #if (defined (__i386__) || defined (i386)) && !defined (VTHREADS)
   /* This is used to properly initialize the FPU on an x86 for each
@@ -2009,7 +2035,6 @@ __gnat_init_float (void)
    checking is not used.  */
 void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
 
-
 /******************/
 /* NetBSD Section */
 /******************/
@@ -2136,6 +2161,130 @@ __gnat_install_handler(void)
   __gnat_handler_installed = 1;
 }
 
+/******************/
+/* Darwin Section */
+/******************/
+
+#elif defined(__APPLE__)
+
+#include <signal.h>
+#include <sys/syscall.h>
+#include <mach/mach_vm.h>
+#include <mach/mach_init.h>
+#include <mach/vm_statistics.h>
+
+/* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
+char __gnat_alternate_stack[32 * 1024]; /* 1 * MINSIGSTKSZ */
+
+static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
+
+/* Defined in xnu unix_signal.c.
+   Tell the kernel to re-use alt stack when delivering a signal.  */
+#define        UC_RESET_ALT_STACK      0x80000000
+
+/* Return true if ADDR is within a stack guard area.  */
+static int
+__gnat_is_stack_guard (mach_vm_address_t addr)
+{
+  kern_return_t kret;
+  vm_region_submap_info_data_64_t info;
+  mach_vm_address_t start;
+  mach_vm_size_t size;
+  natural_t depth;
+  mach_msg_type_number_t count;
+
+  count = VM_REGION_SUBMAP_INFO_COUNT_64;
+  start = addr;
+  size = -1;
+  depth = 9999;
+  kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
+                                (vm_region_recurse_info_t) &info, &count);
+  if (kret == KERN_SUCCESS
+      && addr >= start && addr < (start + size)
+      && info.protection == VM_PROT_NONE
+      && info.user_tag == VM_MEMORY_STACK)
+    return 1;
+  return 0;
+}
+
+static void
+__gnat_error_handler (int sig, siginfo_t * si, void * uc ATTRIBUTE_UNUSED)
+{
+  struct Exception_Data *exception;
+  const char *msg;
+
+  switch (sig)
+    {
+    case SIGSEGV:
+    case SIGBUS:
+      if (__gnat_is_stack_guard ((unsigned long)si->si_addr))
+       {
+         exception = &storage_error;
+         msg = "stack overflow";
+       }
+      else
+       {
+         exception = &constraint_error;
+         msg = "erroneous memory access";
+       }
+      /* Reset the use of alt stack, so that the alt stack will be used
+        for the next signal delivery.
+         The stack can't be used in case of stack checking.  */
+      syscall (SYS_sigreturn, NULL, UC_RESET_ALT_STACK);
+      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 (void)
+{
+  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 (and it is required by Darwin).  */
+
+  stack_t stack;
+  stack.ss_sp = __gnat_alternate_stack;
+  stack.ss_size = sizeof (__gnat_alternate_stack);
+  stack.ss_flags = 0;
+  sigaltstack (&stack, NULL);
+
+  act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
+  act.sa_sigaction = __gnat_error_handler;
+  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);
+
+  act.sa_flags |= SA_ONSTACK;
+  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;
+}
+
 #else
 
 /* For all other versions of GNAT, the handler does nothing.  */
@@ -2169,7 +2318,7 @@ __gnat_install_handler (void)
 void
 __gnat_init_float (void)
 {
-#if defined (__i386__) || defined (i386)
+#if defined (__i386__) || defined (i386) || defined (__x86_64)
 
   /* This is used to properly initialize the FPU on an x86 for each
      process thread.  */
@@ -2206,12 +2355,14 @@ void
 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
                                 void *ucontext ATTRIBUTE_UNUSED)
 {
-  /* Adjustments are currently required for the GCC ZCX propagation scheme
-     only.  These adjustments (described below) are harmless for the other
-     schemes, so may be applied unconditionally.  */
+  /* We used to compensate here for the raised from call vs raised from signal
+     exception discrepancy with the GCC ZCX scheme, but this now can be dealt
+     with generically in the unwinder (see GCC PR other/26208).  This however
+     requires the use of the _Unwind_GetIPInfo routine in raise-gcc.c, which
+     is predicated on the definition of HAVE_GETIPINFO at compile time.  Only
+     the VMS ports still do the compensation described in the few lines below.
 
-  /* Adjustments required for a GCC ZCX propagation scheme:
-     ------------------------------------------------------
+     *** Call vs signal exception discrepancy with GCC ZCX scheme ***
 
      The GCC unwinder expects to be dealing with call return addresses, since
      this is the "nominal" case of what we retrieve while unwinding a regular
@@ -2239,15 +2390,7 @@ __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
 
      signo is passed because on some targets for some signals the PC in
      context points to the instruction after the faulting one, in which case
-     the unwinder adjustment is still desired.
-
-     We used to perform the compensation in the GCC unwinding fallback macro.
-     The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
-     describes a couple of issues with this approach.  First, on some targets
-     the adjustment to apply depends on the triggering signal, which is not
-     easily accessible from the macro.  Besides, other languages, e.g. Java,
-     deal with this by performing the adjustment in the signal handler before
-     the raise, so fallback adjustments just break those front-ends.  */
+     the unwinder adjustment is still desired.  */
 }
 
 #endif