about summary refs log tree commit diff
path: root/sysdeps/generic/unwind-dw2-fde.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/generic/unwind-dw2-fde.c')
-rw-r--r--sysdeps/generic/unwind-dw2-fde.c228
1 files changed, 126 insertions, 102 deletions
diff --git a/sysdeps/generic/unwind-dw2-fde.c b/sysdeps/generic/unwind-dw2-fde.c
index 6c51c6f730..64c0846ccb 100644
--- a/sysdeps/generic/unwind-dw2-fde.c
+++ b/sysdeps/generic/unwind-dw2-fde.c
@@ -1,13 +1,13 @@
 /* Subroutines needed for unwinding stack frames for exception handling.  */
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by Jason Merrill <jason@cygnus.com>.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC 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 version.
+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
+version.
 
 In addition to the permissions in the GNU General Public License, the
 Free Software Foundation gives you unlimited permission to link the
@@ -18,15 +18,15 @@ do apply in other respects; for example, they cover modification of
 the file, and distribution when not linked into a combine
 executable.)
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT 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
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+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.  */
 
 #ifdef _LIBC
 # include <shlib-compat.h>
@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA.  */
 #include <unwind-pe.h>
 #include <unwind-dw2-fde.h>
 #else
+#ifndef _Unwind_Find_FDE
 #include "tconfig.h"
 #include "tsystem.h"
 #include "dwarf2.h"
@@ -53,6 +54,7 @@ Boston, MA 02111-1307, USA.  */
 #include "unwind-dw2-fde.h"
 #include "gthr.h"
 #endif
+#endif
 
 /* The unseen_objects list contains objects that have been registered
    but not yet categorized in any way.  The seen_objects list has had
@@ -109,7 +111,7 @@ __register_frame_info_bases (void *begin, struct object *ob,
 			     void *tbase, void *dbase)
 {
   /* If .eh_frame is empty, don't register at all.  */
-  if (*(uword *)begin == 0)
+  if (*(uword *) begin == 0)
     return;
 
   ob->pc_begin = (void *)-1;
@@ -118,6 +120,9 @@ __register_frame_info_bases (void *begin, struct object *ob,
   ob->u.single = begin;
   ob->s.i = 0;
   ob->s.b.encoding = DW_EH_PE_omit;
+#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
+  ob->fde_end = NULL;
+#endif
 
   init_object_mutex_once ();
   __gthread_mutex_lock (&object_mutex);
@@ -141,7 +146,7 @@ __register_frame (void *begin)
   struct object *ob;
 
   /* If .eh_frame is empty, don't register at all.  */
-  if (*(uword *)begin == 0)
+  if (*(uword *) begin == 0)
     return;
 
   ob = (struct object *) malloc (sizeof (struct object));
@@ -206,7 +211,7 @@ __deregister_frame_info_bases (void *begin)
   struct object *ob = 0;
 
   /* If .eh_frame is empty, we haven't registered.  */
-  if (*(uword *)begin == 0)
+  if (*(uword *) begin == 0)
     return ob;
 
   init_object_mutex_once ();
@@ -260,7 +265,7 @@ void
 __deregister_frame (void *begin)
 {
   /* If .eh_frame is empty, we haven't registered.  */
-  if (*(uword *)begin != 0)
+  if (*(uword *) begin != 0)
     free (INTUSE(__deregister_frame_info_bases) (begin));
 }
 
@@ -297,18 +302,20 @@ get_cie_encoding (struct dwarf_cie *cie)
 {
   const unsigned char *aug, *p;
   _Unwind_Ptr dummy;
+  _Unwind_Word utmp;
+  _Unwind_Sword stmp;
 
   aug = cie->augmentation;
   if (aug[0] != 'z')
     return DW_EH_PE_absptr;
 
   p = aug + strlen (aug) + 1;		/* Skip the augmentation string.  */
-  p = read_uleb128 (p, &dummy);		/* Skip code alignment.  */
-  p = read_sleb128 (p, &dummy);		/* Skip data alignment.  */
+  p = read_uleb128 (p, &utmp);		/* Skip code alignment.  */
+  p = read_sleb128 (p, &stmp);		/* Skip data alignment.  */
   p++;					/* Skip return address column.  */
 
   aug++;				/* Skip 'z' */
-  p = read_uleb128 (p, &dummy);		/* Skip augmentation length.  */
+  p = read_uleb128 (p, &utmp);		/* Skip augmentation length.  */
   while (1)
     {
       /* This is what we're looking for.  */
@@ -345,14 +352,21 @@ get_fde_encoding (struct dwarf_fde *f)
 
 /* Comparison routines.  Three variants of increasing complexity.  */
 
-static saddr
+static int
 fde_unencoded_compare (struct object *ob __attribute__((unused)),
 		       fde *x, fde *y)
 {
-  return *(saddr *)x->pc_begin - *(saddr *)y->pc_begin;
+  _Unwind_Ptr x_ptr = *(_Unwind_Ptr *) x->pc_begin;
+  _Unwind_Ptr y_ptr = *(_Unwind_Ptr *) y->pc_begin;
+
+  if (x_ptr > y_ptr)
+    return 1;
+  if (x_ptr < y_ptr)
+    return -1;
+  return 0;
 }
 
-static saddr
+static int
 fde_single_encoding_compare (struct object *ob, fde *x, fde *y)
 {
   _Unwind_Ptr base, x_ptr, y_ptr;
@@ -361,10 +375,14 @@ fde_single_encoding_compare (struct object *ob, fde *x, fde *y)
   read_encoded_value_with_base (ob->s.b.encoding, base, x->pc_begin, &x_ptr);
   read_encoded_value_with_base (ob->s.b.encoding, base, y->pc_begin, &y_ptr);
 
-  return x_ptr - y_ptr;
+  if (x_ptr > y_ptr)
+    return 1;
+  if (x_ptr < y_ptr)
+    return -1;
+  return 0;
 }
 
-static saddr
+static int
 fde_mixed_encoding_compare (struct object *ob, fde *x, fde *y)
 {
   int x_encoding, y_encoding;
@@ -378,10 +396,14 @@ fde_mixed_encoding_compare (struct object *ob, fde *x, fde *y)
   read_encoded_value_with_base (y_encoding, base_from_object (y_encoding, ob),
 				y->pc_begin, &y_ptr);
 
-  return x_ptr - y_ptr;
+  if (x_ptr > y_ptr)
+    return 1;
+  if (x_ptr < y_ptr)
+    return -1;
+  return 0;
 }
 
-typedef saddr (*fde_compare_t) (struct object *, fde *, fde *);
+typedef int (*fde_compare_t) (struct object *, fde *, fde *);
 
 
 /* This is a special mix of insertion sort and heap sort, optimized for
@@ -459,13 +481,13 @@ fde_split (struct object *ob, fde_compare_t fde_compare,
       fde **probe;
 
       for (probe = chain_end;
-           probe != &marker && fde_compare (ob, linear->array[i], *probe) < 0;
-           probe = chain_end)
-        {
-          chain_end = (fde **)erratic->array[probe - linear->array];
-          erratic->array[probe - linear->array] = NULL;
-        }
-      erratic->array[i] = (fde *)chain_end;
+	   probe != &marker && fde_compare (ob, linear->array[i], *probe) < 0;
+	   probe = chain_end)
+	{
+	  chain_end = (fde **) erratic->array[probe - linear->array];
+	  erratic->array[probe - linear->array] = NULL;
+	}
+      erratic->array[i] = (fde *) chain_end;
       chain_end = &linear->array[i];
     }
 
@@ -490,11 +512,11 @@ frame_heapsort (struct object *ob, fde_compare_t fde_compare,
 {
   /* For a description of this algorithm, see:
      Samuel P. Harbison, Guy L. Steele Jr.: C, a reference manual, 2nd ed.,
-     p. 60-61. */
+     p. 60-61.  */
   fde ** a = erratic->array;
   /* A portion of the array is called a "heap" if for all i>=0:
      If i and 2i+1 are valid indices, then a[i] >= a[2i+1].
-     If i and 2i+2 are valid indices, then a[i] >= a[2i+2]. */
+     If i and 2i+2 are valid indices, then a[i] >= a[2i+2].  */
 #define SWAP(x,y) do { fde * tmp = x; x = y; y = tmp; } while (0)
   size_t n = erratic->count;
   size_t m = n;
@@ -502,53 +524,53 @@ frame_heapsort (struct object *ob, fde_compare_t fde_compare,
 
   while (m > 0)
     {
-      /* Invariant: a[m..n-1] is a heap. */
+      /* Invariant: a[m..n-1] is a heap.  */
       m--;
       for (i = m; 2*i+1 < n; )
-        {
-          if (2*i+2 < n
-              && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
-              && fde_compare (ob, a[2*i+2], a[i]) > 0)
-            {
-              SWAP (a[i], a[2*i+2]);
-              i = 2*i+2;
-            }
-          else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
-            {
-              SWAP (a[i], a[2*i+1]);
-              i = 2*i+1;
-            }
-          else
-            break;
-        }
+	{
+	  if (2*i+2 < n
+	      && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
+	      && fde_compare (ob, a[2*i+2], a[i]) > 0)
+	    {
+	      SWAP (a[i], a[2*i+2]);
+	      i = 2*i+2;
+	    }
+	  else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
+	    {
+	      SWAP (a[i], a[2*i+1]);
+	      i = 2*i+1;
+	    }
+	  else
+	    break;
+	}
     }
   while (n > 1)
     {
-      /* Invariant: a[0..n-1] is a heap. */
+      /* Invariant: a[0..n-1] is a heap.  */
       n--;
       SWAP (a[0], a[n]);
       for (i = 0; 2*i+1 < n; )
-        {
-          if (2*i+2 < n
-              && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
-              && fde_compare (ob, a[2*i+2], a[i]) > 0)
-            {
-              SWAP (a[i], a[2*i+2]);
-              i = 2*i+2;
-            }
-          else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
-            {
-              SWAP (a[i], a[2*i+1]);
-              i = 2*i+1;
-            }
-          else
-            break;
-        }
+	{
+	  if (2*i+2 < n
+	      && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
+	      && fde_compare (ob, a[2*i+2], a[i]) > 0)
+	    {
+	      SWAP (a[i], a[2*i+2]);
+	      i = 2*i+2;
+	    }
+	  else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
+	    {
+	      SWAP (a[i], a[2*i+1]);
+	      i = 2*i+1;
+	    }
+	  else
+	    break;
+	}
     }
 #undef SWAP
 }
 
-/* Merge V1 and V2, both sorted, and put the result into V1. */
+/* Merge V1 and V2, both sorted, and put the result into V1.  */
 static inline void
 fde_merge (struct object *ob, fde_compare_t fde_compare,
 	   struct fde_vector *v1, struct fde_vector *v2)
@@ -560,16 +582,18 @@ fde_merge (struct object *ob, fde_compare_t fde_compare,
   if (i2 > 0)
     {
       i1 = v1->count;
-      do {
-        i2--;
-        fde2 = v2->array[i2];
-        while (i1 > 0 && fde_compare (ob, v1->array[i1-1], fde2) > 0)
-          {
-            v1->array[i1+i2] = v1->array[i1-1];
-            i1--;
-          }
-        v1->array[i1+i2] = fde2;
-      } while (i2 > 0);
+      do
+	{
+	  i2--;
+	  fde2 = v2->array[i2];
+	  while (i1 > 0 && fde_compare (ob, v1->array[i1-1], fde2) > 0)
+	    {
+	      v1->array[i1+i2] = v1->array[i1-1];
+	      i1--;
+	    }
+	  v1->array[i1+i2] = fde2;
+	}
+      while (i2 > 0);
       v1->count += v2->count;
     }
 }
@@ -619,7 +643,7 @@ classify_object_over_fdes (struct object *ob, fde *this_fde)
   int encoding = DW_EH_PE_absptr;
   _Unwind_Ptr base = 0;
 
-  for (; this_fde->length != 0; this_fde = next_fde (this_fde))
+  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
     {
       struct dwarf_cie *this_cie;
       _Unwind_Ptr mask, pc_begin;
@@ -659,8 +683,8 @@ classify_object_over_fdes (struct object *ob, fde *this_fde)
 	continue;
 
       count += 1;
-      if ((void *)pc_begin < ob->pc_begin)
-	ob->pc_begin = (void *)pc_begin;
+      if ((void *) pc_begin < ob->pc_begin)
+	ob->pc_begin = (void *) pc_begin;
     }
 
   return count;
@@ -673,7 +697,7 @@ add_fdes (struct object *ob, struct fde_accumulator *accu, fde *this_fde)
   int encoding = ob->s.b.encoding;
   _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
 
-  for (; this_fde->length != 0; this_fde = next_fde (this_fde))
+  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
     {
       struct dwarf_cie *this_cie;
 
@@ -696,7 +720,7 @@ add_fdes (struct object *ob, struct fde_accumulator *accu, fde *this_fde)
 
       if (encoding == DW_EH_PE_absptr)
 	{
-	  if (*(_Unwind_Ptr *)this_fde->pc_begin == 0)
+	  if (*(_Unwind_Ptr *) this_fde->pc_begin == 0)
 	    continue;
 	}
       else
@@ -764,7 +788,7 @@ init_object (struct object* ob)
     {
       fde **p;
       for (p = ob->u.array; *p; ++p)
-        add_fdes (ob, &accu, *p);
+	add_fdes (ob, &accu, *p);
     }
   else
     add_fdes (ob, &accu, ob->u.single);
@@ -790,7 +814,7 @@ linear_search_fdes (struct object *ob, fde *this_fde, void *pc)
   int encoding = ob->s.b.encoding;
   _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
 
-  for (; this_fde->length != 0; this_fde = next_fde (this_fde))
+  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
     {
       struct dwarf_cie *this_cie;
       _Unwind_Ptr pc_begin, pc_range;
@@ -814,8 +838,8 @@ linear_search_fdes (struct object *ob, fde *this_fde, void *pc)
 
       if (encoding == DW_EH_PE_absptr)
 	{
-	  pc_begin = ((_Unwind_Ptr *)this_fde->pc_begin)[0];
-	  pc_range = ((_Unwind_Ptr *)this_fde->pc_begin)[1];
+	  pc_begin = ((_Unwind_Ptr *) this_fde->pc_begin)[0];
+	  pc_range = ((_Unwind_Ptr *) this_fde->pc_begin)[1];
 	  if (pc_begin == 0)
 	    continue;
 	}
@@ -842,8 +866,8 @@ linear_search_fdes (struct object *ob, fde *this_fde, void *pc)
 	    continue;
 	}
 
-      if ((_Unwind_Ptr)pc - pc_begin < pc_range)
-        return this_fde;
+      if ((_Unwind_Ptr) pc - pc_begin < pc_range)
+	return this_fde;
     }
 
   return NULL;
@@ -865,8 +889,8 @@ binary_search_unencoded_fdes (struct object *ob, void *pc)
       void *pc_begin;
       uaddr pc_range;
 
-      pc_begin = ((void **)f->pc_begin)[0];
-      pc_range = ((uaddr *)f->pc_begin)[1];
+      pc_begin = ((void **) f->pc_begin)[0];
+      pc_range = ((uaddr *) f->pc_begin)[1];
 
       if (pc < pc_begin)
 	hi = i;
@@ -898,9 +922,9 @@ binary_search_single_encoding_fdes (struct object *ob, void *pc)
 					&pc_begin);
       read_encoded_value_with_base (encoding & 0x0F, 0, p, &pc_range);
 
-      if ((_Unwind_Ptr)pc < pc_begin)
+      if ((_Unwind_Ptr) pc < pc_begin)
 	hi = i;
-      else if ((_Unwind_Ptr)pc >= pc_begin + pc_range)
+      else if ((_Unwind_Ptr) pc >= pc_begin + pc_range)
 	lo = i + 1;
       else
 	return f;
@@ -929,9 +953,9 @@ binary_search_mixed_encoding_fdes (struct object *ob, void *pc)
 					f->pc_begin, &pc_begin);
       read_encoded_value_with_base (encoding & 0x0F, 0, p, &pc_range);
 
-      if ((_Unwind_Ptr)pc < pc_begin)
+      if ((_Unwind_Ptr) pc < pc_begin)
 	hi = i;
-      else if ((_Unwind_Ptr)pc >= pc_begin + pc_range)
+      else if ((_Unwind_Ptr) pc >= pc_begin + pc_range)
 	lo = i + 1;
       else
 	return f;
@@ -969,14 +993,14 @@ search_object (struct object* ob, void *pc)
     {
       /* Long slow labourious linear search, cos we've no memory.  */
       if (ob->s.b.from_array)
-        {
-          fde **p;
+	{
+	  fde **p;
 	  for (p = ob->u.array; *p ; p++)
 	    {
 	      fde *f = linear_search_fdes (ob, *p, pc);
-              if (f)
+	      if (f)
 		return f;
-            }
+	    }
 	  return NULL;
 	}
       else