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.
-   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.
 
@@ -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
-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
@@ -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.
 
-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"
@@ -41,7 +45,7 @@ static const unsigned char *
 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);
@@ -72,14 +76,37 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *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
-#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 *);
@@ -90,28 +117,48 @@ PERSONALITY_FUNCTION (int version,
                      _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
                      struct _Unwind_Exception *ue_header,
                      struct _Unwind_Context *context)
+#endif
 {
   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;
-
+  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)
-    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)
-    return _URC_CONTINUE_UNWIND;
+    CONTINUE_UNWINDING;
 
   /* 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__
@@ -123,7 +170,7 @@ PERSONALITY_FUNCTION (int version,
     return _URC_CONTINUE_UNWIND;
   else
     {
-      _Unwind_Word cs_lp, cs_action;
+      _uleb128_t cs_lp, cs_action;
       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.  */
-      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
@@ -143,7 +188,7 @@ PERSONALITY_FUNCTION (int version,
   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);
@@ -158,25 +203,22 @@ PERSONALITY_FUNCTION (int version,
        {
          if (cs_lp)
            landing_pad = info.LPStart + cs_lp;
-         if (cs_action)
-           action_record = info.action_table + cs_action - 1;
          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.  */
-  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.  */
-      return _URC_CONTINUE_UNWIND;
+      CONTINUE_UNWINDING;
     }
 
   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),