OSDN Git Service

2007-04-06 Ed Schonberg <schonberg@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / unwind-c.c
index fc76edb..f287ea2 100644 (file)
@@ -50,7 +50,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);
@@ -81,6 +81,20 @@ 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
@@ -88,6 +102,16 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
 #define PERSONALITY_FUNCTION    __gcc_personality_v0
 #endif
 
+#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 *);
@@ -98,28 +122,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;
   _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__
@@ -131,7 +175,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);
@@ -141,7 +185,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;
+      landing_pad = (_Unwind_Ptr)cs_lp + 1;
       if (cs_action)
        action_record = info.action_table + cs_action - 1;
       goto found_something;
@@ -151,7 +195,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);
@@ -171,20 +215,19 @@ PERSONALITY_FUNCTION (int version,
          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),