OSDN Git Service

2010-04-27 Jonathan Wakely <jwakely.gcc@gmail.com>
[pf3gnuchains/gcc-fork.git] / gcc / unwind-c.c
index 8f2f5c4..86b9f55 100644 (file)
@@ -1,5 +1,5 @@
 /* Supporting functions for C exception handling.
 /* Supporting functions for C exception handling.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc.
    Contributed by Aldy Hernandez <aldy@quesejoda.com>.
    Shamelessly stolen from the Java front end.
 
    Contributed by Aldy Hernandez <aldy@quesejoda.com>.
    Shamelessly stolen from the Java front end.
 
@@ -7,7 +7,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,10 +15,14 @@ WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 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
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+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/>.  */
 
 #include "tconfig.h"
 #include "tsystem.h"
 
 #include "tconfig.h"
 #include "tsystem.h"
@@ -41,7 +45,7 @@ static const unsigned char *
 parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
                   lsda_header_info *info)
 {
 parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
                   lsda_header_info *info)
 {
-  _Unwind_Word tmp;
+  _uleb128_t tmp;
   unsigned char lpstart_encoding;
 
   info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
   unsigned char lpstart_encoding;
 
   info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
@@ -72,14 +76,37 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
   return p;
 }
 
   return p;
 }
 
+#ifdef __ARM_EABI_UNWINDER__
+/* ARM EABI personality routines must also unwind the stack.  */
+#define CONTINUE_UNWINDING \
+  do                                                           \
+    {                                                          \
+      if (__gnu_unwind_frame (ue_header, context) != _URC_OK)  \
+       return _URC_FAILURE;                                    \
+      return _URC_CONTINUE_UNWIND;                             \
+    }                                                          \
+  while (0)
+#else
+#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
+#endif
+
 #ifdef __USING_SJLJ_EXCEPTIONS__
 #define PERSONALITY_FUNCTION    __gcc_personality_sj0
 #define __builtin_eh_return_data_regno(x) x
 #else
 #define PERSONALITY_FUNCTION    __gcc_personality_v0
 #endif
 #ifdef __USING_SJLJ_EXCEPTIONS__
 #define PERSONALITY_FUNCTION    __gcc_personality_sj0
 #define __builtin_eh_return_data_regno(x) x
 #else
 #define PERSONALITY_FUNCTION    __gcc_personality_v0
 #endif
-#define PERSONALITY_FUNCTION    __gcc_personality_v0
 
 
+#ifdef __ARM_EABI_UNWINDER__
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *,
+                     struct _Unwind_Context *);
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (_Unwind_State state,
+                     struct _Unwind_Exception * ue_header,
+                     struct _Unwind_Context * context)
+#else
 _Unwind_Reason_Code
 PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
                      struct _Unwind_Exception *, struct _Unwind_Context *);
 _Unwind_Reason_Code
 PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
                      struct _Unwind_Exception *, struct _Unwind_Context *);
@@ -90,28 +117,48 @@ PERSONALITY_FUNCTION (int version,
                      _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
                      struct _Unwind_Exception *ue_header,
                      struct _Unwind_Context *context)
                      _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
                      struct _Unwind_Exception *ue_header,
                      struct _Unwind_Context *context)
+#endif
 {
   lsda_header_info info;
 {
   lsda_header_info info;
-  const unsigned char *language_specific_data, *p, *action_record;
+  const unsigned char *language_specific_data, *p;
   _Unwind_Ptr landing_pad, ip;
   _Unwind_Ptr landing_pad, ip;
-
+  int ip_before_insn = 0;
+
+#ifdef __ARM_EABI_UNWINDER__
+  if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING)
+    CONTINUE_UNWINDING;
+
+  /* The dwarf unwinder assumes the context structure holds things like the
+     function and LSDA pointers.  The ARM implementation caches these in
+     the exception header (UCB).  To avoid rewriting everything we make the
+     virtual IP register point at the UCB.  */
+  ip = (_Unwind_Ptr) ue_header;
+  _Unwind_SetGR (context, 12, ip);
+#else
   if (version != 1)
     return _URC_FATAL_PHASE1_ERROR;
 
   /* Currently we only support cleanups for C.  */
   if ((actions & _UA_CLEANUP_PHASE) == 0)
   if (version != 1)
     return _URC_FATAL_PHASE1_ERROR;
 
   /* Currently we only support cleanups for C.  */
   if ((actions & _UA_CLEANUP_PHASE) == 0)
-    return _URC_CONTINUE_UNWIND;
+    CONTINUE_UNWINDING;
+#endif
 
   language_specific_data = (const unsigned char *)
     _Unwind_GetLanguageSpecificData (context);
 
   /* If no LSDA, then there are no handlers or cleanups.  */
   if (! language_specific_data)
 
   language_specific_data = (const unsigned char *)
     _Unwind_GetLanguageSpecificData (context);
 
   /* If no LSDA, then there are no handlers or cleanups.  */
   if (! language_specific_data)
-    return _URC_CONTINUE_UNWIND;
+    CONTINUE_UNWINDING;
 
   /* Parse the LSDA header.  */
   p = parse_lsda_header (context, language_specific_data, &info);
 
   /* Parse the LSDA header.  */
   p = parse_lsda_header (context, language_specific_data, &info);
-  ip = _Unwind_GetIP (context) - 1;
+#ifdef HAVE_GETIPINFO
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
+#else
+  ip = _Unwind_GetIP (context);
+#endif
+  if (! ip_before_insn)
+    --ip;
   landing_pad = 0;
 
 #ifdef __USING_SJLJ_EXCEPTIONS__
   landing_pad = 0;
 
 #ifdef __USING_SJLJ_EXCEPTIONS__
@@ -123,7 +170,7 @@ PERSONALITY_FUNCTION (int version,
     return _URC_CONTINUE_UNWIND;
   else
     {
     return _URC_CONTINUE_UNWIND;
   else
     {
-      _Unwind_Word cs_lp, cs_action;
+      _uleb128_t cs_lp, cs_action;
       do
        {
          p = read_uleb128 (p, &cs_lp);
       do
        {
          p = read_uleb128 (p, &cs_lp);
@@ -133,9 +180,7 @@ PERSONALITY_FUNCTION (int version,
 
       /* Can never have null landing pad for sjlj -- that would have
         been indicated by a -1 call site index.  */
 
       /* Can never have null landing pad for sjlj -- that would have
         been indicated by a -1 call site index.  */
-      landing_pad = cs_lp + 1;
-      if (cs_action)
-       action_record = info.action_table + cs_action - 1;
+      landing_pad = (_Unwind_Ptr)cs_lp + 1;
       goto found_something;
     }
 #else
       goto found_something;
     }
 #else
@@ -143,7 +188,7 @@ PERSONALITY_FUNCTION (int version,
   while (p < info.action_table)
     {
       _Unwind_Ptr cs_start, cs_len, cs_lp;
   while (p < info.action_table)
     {
       _Unwind_Ptr cs_start, cs_len, cs_lp;
-      _Unwind_Word cs_action;
+      _uleb128_t cs_action;
 
       /* Note that all call-site encodings are "absolute" displacements.  */
       p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
 
       /* Note that all call-site encodings are "absolute" displacements.  */
       p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
@@ -158,25 +203,22 @@ PERSONALITY_FUNCTION (int version,
        {
          if (cs_lp)
            landing_pad = info.LPStart + cs_lp;
        {
          if (cs_lp)
            landing_pad = info.LPStart + cs_lp;
-         if (cs_action)
-           action_record = info.action_table + cs_action - 1;
          goto found_something;
        }
     }
          goto found_something;
        }
     }
-  
 #endif
 
   /* IP is not in table.  No associated cleanups.  */
   /* ??? This is where C++ calls std::terminate to catch throw
      from a destructor.  */
 #endif
 
   /* IP is not in table.  No associated cleanups.  */
   /* ??? This is where C++ calls std::terminate to catch throw
      from a destructor.  */
-  return _URC_CONTINUE_UNWIND;
+  CONTINUE_UNWINDING;
 
  found_something:
   if (landing_pad == 0)
     {
       /* IP is present, but has a null landing pad.
         No handler to be run.  */
 
  found_something:
   if (landing_pad == 0)
     {
       /* IP is present, but has a null landing pad.
         No handler to be run.  */
-      return _URC_CONTINUE_UNWIND;
+      CONTINUE_UNWINDING;
     }
 
   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
     }
 
   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),