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.c1079
1 files changed, 0 insertions, 1079 deletions
diff --git a/sysdeps/generic/unwind-dw2-fde.c b/sysdeps/generic/unwind-dw2-fde.c
deleted file mode 100644
index 104a2552b4..0000000000
--- a/sysdeps/generic/unwind-dw2-fde.c
+++ /dev/null
@@ -1,1079 +0,0 @@
-/* Subroutines needed for unwinding stack frames for exception handling.  */
-/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
-   Contributed by Jason Merrill <jason@cygnus.com>.
-
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifdef _LIBC
-# include <shlib-compat.h>
-#endif
-
-#if !defined _LIBC || SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2_5)
-
-#ifdef _LIBC
-#include <stdlib.h>
-#include <string.h>
-#include <libc-lock.h>
-#include <dwarf2.h>
-#include <unwind.h>
-#define NO_BASE_OF_ENCODED_VALUE
-#include <unwind-pe.h>
-#include <unwind-dw2-fde.h>
-#else
-#ifndef _Unwind_Find_FDE
-#include "tconfig.h"
-#include "tsystem.h"
-#include "dwarf2.h"
-#include "unwind.h"
-#define NO_BASE_OF_ENCODED_VALUE
-#include "unwind-pe.h"
-#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
-   it's pc_begin and count fields initialized at minimum, and is sorted
-   by decreasing value of pc_begin.  */
-static struct object *unseen_objects;
-static struct object *seen_objects;
-
-#ifdef _LIBC
-
-__libc_lock_define_initialized (static, object_mutex)
-#define init_object_mutex_once()
-#define __gthread_mutex_lock(m) __libc_lock_lock (*(m))
-#define __gthread_mutex_unlock(m) __libc_lock_unlock (*(m))
-
-void __register_frame_info_bases (void *begin, struct object *ob,
-				  void *tbase, void *dbase);
-hidden_proto (__register_frame_info_bases)
-void __register_frame_info_table_bases (void *begin,
-					struct object *ob,
-					void *tbase, void *dbase);
-hidden_proto (__register_frame_info_table_bases)
-void *__deregister_frame_info_bases (void *begin);
-hidden_proto (__deregister_frame_info_bases)
-
-#else
-
-#ifdef __GTHREAD_MUTEX_INIT
-static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
-#else
-static __gthread_mutex_t object_mutex;
-#endif
-
-#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
-static void
-init_object_mutex (void)
-{
-  __GTHREAD_MUTEX_INIT_FUNCTION (&object_mutex);
-}
-
-static void
-init_object_mutex_once (void)
-{
-  static __gthread_once_t once = __GTHREAD_ONCE_INIT;
-  __gthread_once (&once, init_object_mutex);
-}
-#else
-#define init_object_mutex_once()
-#endif
-
-#endif /* _LIBC */
-
-/* Called from crtbegin.o to register the unwind info for an object.  */
-
-void
-__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)
-    return;
-
-  ob->pc_begin = (void *)-1;
-  ob->tbase = tbase;
-  ob->dbase = dbase;
-  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);
-
-  ob->next = unseen_objects;
-  unseen_objects = ob;
-
-  __gthread_mutex_unlock (&object_mutex);
-}
-hidden_def (__register_frame_info_bases)
-
-void
-__register_frame_info (void *begin, struct object *ob)
-{
-  __register_frame_info_bases (begin, ob, 0, 0);
-}
-
-void
-__register_frame (void *begin)
-{
-  struct object *ob;
-
-  /* If .eh_frame is empty, don't register at all.  */
-  if (*(uword *) begin == 0)
-    return;
-
-  ob = (struct object *) malloc (sizeof (struct object));
-  __register_frame_info_bases (begin, ob, 0, 0);
-}
-
-/* Similar, but BEGIN is actually a pointer to a table of unwind entries
-   for different translation units.  Called from the file generated by
-   collect2.  */
-
-void
-__register_frame_info_table_bases (void *begin, struct object *ob,
-				   void *tbase, void *dbase)
-{
-  ob->pc_begin = (void *)-1;
-  ob->tbase = tbase;
-  ob->dbase = dbase;
-  ob->u.array = begin;
-  ob->s.i = 0;
-  ob->s.b.from_array = 1;
-  ob->s.b.encoding = DW_EH_PE_omit;
-
-  init_object_mutex_once ();
-  __gthread_mutex_lock (&object_mutex);
-
-  ob->next = unseen_objects;
-  unseen_objects = ob;
-
-  __gthread_mutex_unlock (&object_mutex);
-}
-hidden_def (__register_frame_info_table_bases)
-
-void
-__register_frame_info_table (void *begin, struct object *ob)
-{
-  __register_frame_info_table_bases (begin, ob, 0, 0);
-}
-
-void
-__register_frame_table (void *begin)
-{
-  struct object *ob = (struct object *) malloc (sizeof (struct object));
-  __register_frame_info_table_bases (begin, ob, 0, 0);
-}
-
-/* Called from crtbegin.o to deregister the unwind info for an object.  */
-/* ??? Glibc has for a while now exported __register_frame_info and
-   __deregister_frame_info.  If we call __register_frame_info_bases
-   from crtbegin (wherein it is declared weak), and this object does
-   not get pulled from libgcc.a for other reasons, then the
-   invocation of __deregister_frame_info will be resolved from glibc.
-   Since the registration did not happen there, we'll abort.
-
-   Therefore, declare a new deregistration entry point that does the
-   exact same thing, but will resolve to the same library as
-   implements __register_frame_info_bases.  */
-
-void *
-__deregister_frame_info_bases (void *begin)
-{
-  struct object **p;
-  struct object *ob = 0;
-  struct fde_vector *tofree = NULL;
-
-  /* If .eh_frame is empty, we haven't registered.  */
-  if (*(uword *) begin == 0)
-    return ob;
-
-  init_object_mutex_once ();
-  __gthread_mutex_lock (&object_mutex);
-
-  for (p = &unseen_objects; *p ; p = &(*p)->next)
-    if ((*p)->u.single == begin)
-      {
-	ob = *p;
-	*p = ob->next;
-	goto out;
-      }
-
-  for (p = &seen_objects; *p ; p = &(*p)->next)
-    if ((*p)->s.b.sorted)
-      {
-	if ((*p)->u.sort->orig_data == begin)
-	  {
-	    ob = *p;
-	    *p = ob->next;
-	    tofree = ob->u.sort;
-	    goto out;
-	  }
-      }
-    else
-      {
-	if ((*p)->u.single == begin)
-	  {
-	    ob = *p;
-	    *p = ob->next;
-	    goto out;
-	  }
-      }
-
-  __gthread_mutex_unlock (&object_mutex);
-  abort ();
-
- out:
-  __gthread_mutex_unlock (&object_mutex);
-  free (tofree);
-  return (void *) ob;
-}
-hidden_def (__deregister_frame_info_bases)
-
-void *
-__deregister_frame_info (void *begin)
-{
-  return __deregister_frame_info_bases (begin);
-}
-
-void
-__deregister_frame (void *begin)
-{
-  /* If .eh_frame is empty, we haven't registered.  */
-  if (*(uword *) begin != 0)
-    free (__deregister_frame_info_bases (begin));
-}
-
-
-/* Like base_of_encoded_value, but take the base from a struct object
-   instead of an _Unwind_Context.  */
-
-static _Unwind_Ptr
-base_from_object (unsigned char encoding, struct object *ob)
-{
-  if (encoding == DW_EH_PE_omit)
-    return 0;
-
-  switch (encoding & 0x70)
-    {
-    case DW_EH_PE_absptr:
-    case DW_EH_PE_pcrel:
-    case DW_EH_PE_aligned:
-      return 0;
-
-    case DW_EH_PE_textrel:
-      return (_Unwind_Ptr) ob->tbase;
-    case DW_EH_PE_datarel:
-      return (_Unwind_Ptr) ob->dbase;
-    }
-  abort ();
-}
-
-/* Return the FDE pointer encoding from the CIE.  */
-/* ??? This is a subset of extract_cie_info from unwind-dw2.c.  */
-
-static int
-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;
-
-  /* Skip the augmentation string.  */
-  p = aug + strlen ((const char *) aug) + 1;
-  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, &utmp);		/* Skip augmentation length.  */
-  while (1)
-    {
-      /* This is what we're looking for.  */
-      if (*aug == 'R')
-	return *p;
-      /* Personality encoding and pointer.  */
-      else if (*aug == 'P')
-	{
-	  /* ??? Avoid dereferencing indirect pointers, since we're
-	     faking the base address.  Gotta keep DW_EH_PE_aligned
-	     intact, however.  */
-	  p = read_encoded_value_with_base (*p & 0x7F, 0, p + 1, &dummy);
-	}
-      /* LSDA encoding.  */
-      else if (*aug == 'L')
-	p++;
-      /* Otherwise end of string, or unknown augmentation.  */
-      else
-	return DW_EH_PE_absptr;
-      aug++;
-    }
-}
-
-static inline int
-get_fde_encoding (struct dwarf_fde *f)
-{
-  return get_cie_encoding (get_cie (f));
-}
-
-
-/* Sorting an array of FDEs by address.
-   (Ideally we would have the linker sort the FDEs so we don't have to do
-   it at run time. But the linkers are not yet prepared for this.)  */
-
-/* Return the Nth pc_begin value from FDE x.  */
-
-static inline _Unwind_Ptr
-get_pc_begin (fde *x, size_t n)
-{
-  _Unwind_Ptr p;
-  memcpy (&p, x->pc_begin + n * sizeof (_Unwind_Ptr), sizeof (_Unwind_Ptr));
-  return p;
-}
-
-/* Comparison routines.  Three variants of increasing complexity.  */
-
-static int
-fde_unencoded_compare (struct object *ob __attribute__((unused)),
-		       fde *x, fde *y)
-{
-  _Unwind_Ptr x_ptr = get_pc_begin (x, 0);
-  _Unwind_Ptr y_ptr = get_pc_begin (y, 0);
-
-  if (x_ptr > y_ptr)
-    return 1;
-  if (x_ptr < y_ptr)
-    return -1;
-  return 0;
-}
-
-static int
-fde_single_encoding_compare (struct object *ob, fde *x, fde *y)
-{
-  _Unwind_Ptr base, x_ptr, y_ptr;
-
-  base = base_from_object (ob->s.b.encoding, ob);
-  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);
-
-  if (x_ptr > y_ptr)
-    return 1;
-  if (x_ptr < y_ptr)
-    return -1;
-  return 0;
-}
-
-static int
-fde_mixed_encoding_compare (struct object *ob, fde *x, fde *y)
-{
-  int x_encoding, y_encoding;
-  _Unwind_Ptr x_ptr, y_ptr;
-
-  x_encoding = get_fde_encoding (x);
-  read_encoded_value_with_base (x_encoding, base_from_object (x_encoding, ob),
-				x->pc_begin, &x_ptr);
-
-  y_encoding = get_fde_encoding (y);
-  read_encoded_value_with_base (y_encoding, base_from_object (y_encoding, ob),
-				y->pc_begin, &y_ptr);
-
-  if (x_ptr > y_ptr)
-    return 1;
-  if (x_ptr < y_ptr)
-    return -1;
-  return 0;
-}
-
-typedef int (*fde_compare_t) (struct object *, fde *, fde *);
-
-
-/* This is a special mix of insertion sort and heap sort, optimized for
-   the data sets that actually occur. They look like
-   101 102 103 127 128 105 108 110 190 111 115 119 125 160 126 129 130.
-   I.e. a linearly increasing sequence (coming from functions in the text
-   section), with additionally a few unordered elements (coming from functions
-   in gnu_linkonce sections) whose values are higher than the values in the
-   surrounding linear sequence (but not necessarily higher than the values
-   at the end of the linear sequence!).
-   The worst-case total run time is O(N) + O(n log (n)), where N is the
-   total number of FDEs and n is the number of erratic ones.  */
-
-struct fde_accumulator
-{
-  struct fde_vector *linear;
-  struct fde_vector *erratic;
-};
-
-static int
-start_fde_sort (struct fde_accumulator *accu, size_t count)
-{
-  size_t size;
-  if (! count)
-    return 0;
-
-  size = sizeof (struct fde_vector) + sizeof (fde *) * count;
-  if ((accu->linear = (struct fde_vector *) malloc (size)))
-    {
-      accu->linear->count = 0;
-      if ((accu->erratic = (struct fde_vector *) malloc (size)))
-	accu->erratic->count = 0;
-      return 1;
-    }
-  else
-    return 0;
-}
-
-static inline void
-fde_insert (struct fde_accumulator *accu, fde *this_fde)
-{
-  if (accu->linear)
-    accu->linear->array[accu->linear->count++] = this_fde;
-}
-
-/* Split LINEAR into a linear sequence with low values and an erratic
-   sequence with high values, put the linear one (of longest possible
-   length) into LINEAR and the erratic one into ERRATIC. This is O(N).
-
-   Because the longest linear sequence we are trying to locate within the
-   incoming LINEAR array can be interspersed with (high valued) erratic
-   entries.  We construct a chain indicating the sequenced entries.
-   To avoid having to allocate this chain, we overlay it onto the space of
-   the ERRATIC array during construction.  A final pass iterates over the
-   chain to determine what should be placed in the ERRATIC array, and
-   what is the linear sequence.  This overlay is safe from aliasing.  */
-
-static void
-fde_split (struct object *ob, fde_compare_t fde_compare,
-	   struct fde_vector *linear, struct fde_vector *erratic)
-{
-  static fde *marker;
-  size_t count = linear->count;
-  fde **chain_end = &marker;
-  size_t i, j, k;
-
-  /* This should optimize out, but it is wise to make sure this assumption
-     is correct. Should these have different sizes, we cannot cast between
-     them and the overlaying onto ERRATIC will not work.  */
-  if (sizeof (fde *) != sizeof (fde **))
-    abort ();
-
-  for (i = 0; i < count; i++)
-    {
-      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;
-      chain_end = &linear->array[i];
-    }
-
-  /* Each entry in LINEAR which is part of the linear sequence we have
-     discovered will correspond to a non-NULL entry in the chain we built in
-     the ERRATIC array.  */
-  for (i = j = k = 0; i < count; i++)
-    if (erratic->array[i])
-      linear->array[j++] = linear->array[i];
-    else
-      erratic->array[k++] = linear->array[i];
-  linear->count = j;
-  erratic->count = k;
-}
-
-/* This is O(n log(n)).  BSD/OS defines heapsort in stdlib.h, so we must
-   use a name that does not conflict.  */
-
-static void
-frame_heapsort (struct object *ob, fde_compare_t fde_compare,
-		struct fde_vector *erratic)
-{
-  /* For a description of this algorithm, see:
-     Samuel P. Harbison, Guy L. Steele Jr.: C, a reference manual, 2nd ed.,
-     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].  */
-#define SWAP(x,y) do { fde * tmp = x; x = y; y = tmp; } while (0)
-  size_t n = erratic->count;
-  size_t m = n;
-  size_t i;
-
-  while (m > 0)
-    {
-      /* 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;
-	}
-    }
-  while (n > 1)
-    {
-      /* 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;
-	}
-    }
-#undef SWAP
-}
-
-/* Merge V1 and V2, both sorted, and put the result into V1.  */
-static void
-fde_merge (struct object *ob, fde_compare_t fde_compare,
-	   struct fde_vector *v1, struct fde_vector *v2)
-{
-  size_t i1, i2;
-  fde * fde2;
-
-  i2 = v2->count;
-  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);
-      v1->count += v2->count;
-    }
-}
-
-static void
-end_fde_sort (struct object *ob, struct fde_accumulator *accu, size_t count)
-{
-  fde_compare_t fde_compare;
-
-  if (accu->linear->count != count)
-    abort ();
-
-  if (ob->s.b.mixed_encoding)
-    fde_compare = fde_mixed_encoding_compare;
-  else if (ob->s.b.encoding == DW_EH_PE_absptr)
-    fde_compare = fde_unencoded_compare;
-  else
-    fde_compare = fde_single_encoding_compare;
-
-  if (accu->erratic)
-    {
-      fde_split (ob, fde_compare, accu->linear, accu->erratic);
-      if (accu->linear->count + accu->erratic->count != count)
-	abort ();
-      frame_heapsort (ob, fde_compare, accu->erratic);
-      fde_merge (ob, fde_compare, accu->linear, accu->erratic);
-      free (accu->erratic);
-    }
-  else
-    {
-      /* We've not managed to malloc an erratic array,
-	 so heap sort in the linear one.  */
-      frame_heapsort (ob, fde_compare, accu->linear);
-    }
-}
-
-
-/* Update encoding, mixed_encoding, and pc_begin for OB for the
-   fde array beginning at THIS_FDE.  Return the number of fdes
-   encountered along the way.  */
-
-static size_t
-classify_object_over_fdes (struct object *ob, fde *this_fde)
-{
-  struct dwarf_cie *last_cie = 0;
-  size_t count = 0;
-  int encoding = DW_EH_PE_absptr;
-  _Unwind_Ptr base = 0;
-
-  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
-    {
-      struct dwarf_cie *this_cie;
-      _Unwind_Ptr mask, pc_begin;
-
-      /* Skip CIEs.  */
-      if (this_fde->CIE_delta == 0)
-	continue;
-
-      /* Determine the encoding for this FDE.  Note mixed encoded
-	 objects for later.  */
-      this_cie = get_cie (this_fde);
-      if (this_cie != last_cie)
-	{
-	  last_cie = this_cie;
-	  encoding = get_cie_encoding (this_cie);
-	  base = base_from_object (encoding, ob);
-	  if (ob->s.b.encoding == DW_EH_PE_omit)
-	    ob->s.b.encoding = encoding;
-	  else if (ob->s.b.encoding != encoding)
-	    ob->s.b.mixed_encoding = 1;
-	}
-
-      read_encoded_value_with_base (encoding, base, this_fde->pc_begin,
-				    &pc_begin);
-
-      /* Take care to ignore link-once functions that were removed.
-	 In these cases, the function address will be NULL, but if
-	 the encoding is smaller than a pointer a true NULL may not
-	 be representable.  Assume 0 in the representable bits is NULL.  */
-      mask = size_of_encoded_value (encoding);
-      if (mask < sizeof (void *))
-	mask = (1L << (mask << 3)) - 1;
-      else
-	mask = -1;
-
-      if ((pc_begin & mask) == 0)
-	continue;
-
-      count += 1;
-      if ((void *) pc_begin < ob->pc_begin)
-	ob->pc_begin = (void *) pc_begin;
-    }
-
-  return count;
-}
-
-static void
-add_fdes (struct object *ob, struct fde_accumulator *accu, fde *this_fde)
-{
-  struct dwarf_cie *last_cie = 0;
-  int encoding = ob->s.b.encoding;
-  _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
-
-  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
-    {
-      struct dwarf_cie *this_cie;
-
-      /* Skip CIEs.  */
-      if (this_fde->CIE_delta == 0)
-	continue;
-
-      if (ob->s.b.mixed_encoding)
-	{
-	  /* Determine the encoding for this FDE.  Note mixed encoded
-	     objects for later.  */
-	  this_cie = get_cie (this_fde);
-	  if (this_cie != last_cie)
-	    {
-	      last_cie = this_cie;
-	      encoding = get_cie_encoding (this_cie);
-	      base = base_from_object (encoding, ob);
-	    }
-	}
-
-      if (encoding == DW_EH_PE_absptr)
-	{
-	  if (get_pc_begin (this_fde, 0) == 0)
-	    continue;
-	}
-      else
-	{
-	  _Unwind_Ptr pc_begin, mask;
-
-	  read_encoded_value_with_base (encoding, base, this_fde->pc_begin,
-					&pc_begin);
-
-	  /* Take care to ignore link-once functions that were removed.
-	     In these cases, the function address will be NULL, but if
-	     the encoding is smaller than a pointer a true NULL may not
-	     be representable.  Assume 0 in the representable bits is NULL.  */
-	  mask = size_of_encoded_value (encoding);
-	  if (mask < sizeof (void *))
-	    mask = (1L << (mask << 3)) - 1;
-	  else
-	    mask = -1;
-
-	  if ((pc_begin & mask) == 0)
-	    continue;
-	}
-
-      fde_insert (accu, this_fde);
-    }
-}
-
-/* Set up a sorted array of pointers to FDEs for a loaded object.  We
-   count up the entries before allocating the array because it's likely to
-   be faster.  We can be called multiple times, should we have failed to
-   allocate a sorted fde array on a previous occasion.  */
-
-static void
-init_object (struct object* ob)
-{
-  struct fde_accumulator accu;
-  size_t count;
-
-  count = ob->s.b.count;
-  if (count == 0)
-    {
-      if (ob->s.b.from_array)
-	{
-	  fde **p = ob->u.array;
-	  for (count = 0; *p; ++p)
-	    count += classify_object_over_fdes (ob, *p);
-	}
-      else
-	count = classify_object_over_fdes (ob, ob->u.single);
-
-      /* The count field we have in the main struct object is somewhat
-	 limited, but should suffice for virtually all cases.  If the
-	 counted value doesn't fit, re-write a zero.  The worst that
-	 happens is that we re-count next time -- admittedly non-trivial
-	 in that this implies some 2M fdes, but at least we function.  */
-      ob->s.b.count = count;
-      if (ob->s.b.count != count)
-	ob->s.b.count = 0;
-    }
-
-  if (!start_fde_sort (&accu, count))
-    return;
-
-  if (ob->s.b.from_array)
-    {
-      fde **p;
-      for (p = ob->u.array; *p; ++p)
-	add_fdes (ob, &accu, *p);
-    }
-  else
-    add_fdes (ob, &accu, ob->u.single);
-
-  end_fde_sort (ob, &accu, count);
-
-  /* Save the original fde pointer, since this is the key by which the
-     DSO will deregister the object.  */
-  accu.linear->orig_data = ob->u.single;
-  ob->u.sort = accu.linear;
-
-  ob->s.b.sorted = 1;
-}
-
-/* A linear search through a set of FDEs for the given PC.  This is
-   used when there was insufficient memory to allocate and sort an
-   array.  */
-
-static fde *
-linear_search_fdes (struct object *ob, fde *this_fde, void *pc)
-{
-  struct dwarf_cie *last_cie = 0;
-  int encoding = ob->s.b.encoding;
-  _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
-
-  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
-    {
-      struct dwarf_cie *this_cie;
-      _Unwind_Ptr pc_begin, pc_range;
-
-      /* Skip CIEs.  */
-      if (this_fde->CIE_delta == 0)
-	continue;
-
-      if (ob->s.b.mixed_encoding)
-	{
-	  /* Determine the encoding for this FDE.  Note mixed encoded
-	     objects for later.  */
-	  this_cie = get_cie (this_fde);
-	  if (this_cie != last_cie)
-	    {
-	      last_cie = this_cie;
-	      encoding = get_cie_encoding (this_cie);
-	      base = base_from_object (encoding, ob);
-	    }
-	}
-
-      if (encoding == DW_EH_PE_absptr)
-	{
-	  pc_begin = get_pc_begin (this_fde, 0);
-	  pc_range = get_pc_begin (this_fde, 1);
-	  if (pc_begin == 0)
-	    continue;
-	}
-      else
-	{
-	  _Unwind_Ptr mask;
-	  const unsigned char *p;
-
-	  p = read_encoded_value_with_base (encoding, base,
-					    this_fde->pc_begin, &pc_begin);
-	  read_encoded_value_with_base (encoding & 0x0F, 0, p, &pc_range);
-
-	  /* Take care to ignore link-once functions that were removed.
-	     In these cases, the function address will be NULL, but if
-	     the encoding is smaller than a pointer a true NULL may not
-	     be representable.  Assume 0 in the representable bits is NULL.  */
-	  mask = size_of_encoded_value (encoding);
-	  if (mask < sizeof (void *))
-	    mask = (1L << (mask << 3)) - 1;
-	  else
-	    mask = -1;
-
-	  if ((pc_begin & mask) == 0)
-	    continue;
-	}
-
-      if ((_Unwind_Ptr) pc - pc_begin < pc_range)
-	return this_fde;
-    }
-
-  return NULL;
-}
-
-/* Binary search for an FDE containing the given PC.  Here are three
-   implementations of increasing complexity.  */
-
-static fde *
-binary_search_unencoded_fdes (struct object *ob, void *pc)
-{
-  struct fde_vector *vec = ob->u.sort;
-  size_t lo, hi;
-
-  for (lo = 0, hi = vec->count; lo < hi; )
-    {
-      size_t i = (lo + hi) / 2;
-      fde *f = vec->array[i];
-      void *pc_begin;
-      uaddr pc_range;
-
-      pc_begin = (void *) get_pc_begin (f, 0);
-      pc_range = (uaddr) get_pc_begin (f, 1);
-
-      if (pc < pc_begin)
-	hi = i;
-      else if (pc >= pc_begin + pc_range)
-	lo = i + 1;
-      else
-	return f;
-    }
-
-  return NULL;
-}
-
-static fde *
-binary_search_single_encoding_fdes (struct object *ob, void *pc)
-{
-  struct fde_vector *vec = ob->u.sort;
-  int encoding = ob->s.b.encoding;
-  _Unwind_Ptr base = base_from_object (encoding, ob);
-  size_t lo, hi;
-
-  for (lo = 0, hi = vec->count; lo < hi; )
-    {
-      size_t i = (lo + hi) / 2;
-      fde *f = vec->array[i];
-      _Unwind_Ptr pc_begin, pc_range;
-      const unsigned char *p;
-
-      p = read_encoded_value_with_base (encoding, base, f->pc_begin,
-					&pc_begin);
-      read_encoded_value_with_base (encoding & 0x0F, 0, p, &pc_range);
-
-      if ((_Unwind_Ptr) pc < pc_begin)
-	hi = i;
-      else if ((_Unwind_Ptr) pc >= pc_begin + pc_range)
-	lo = i + 1;
-      else
-	return f;
-    }
-
-  return NULL;
-}
-
-static fde *
-binary_search_mixed_encoding_fdes (struct object *ob, void *pc)
-{
-  struct fde_vector *vec = ob->u.sort;
-  size_t lo, hi;
-
-  for (lo = 0, hi = vec->count; lo < hi; )
-    {
-      size_t i = (lo + hi) / 2;
-      fde *f = vec->array[i];
-      _Unwind_Ptr pc_begin, pc_range;
-      const unsigned char *p;
-      int encoding;
-
-      encoding = get_fde_encoding (f);
-      p = read_encoded_value_with_base (encoding,
-					base_from_object (encoding, ob),
-					f->pc_begin, &pc_begin);
-      read_encoded_value_with_base (encoding & 0x0F, 0, p, &pc_range);
-
-      if ((_Unwind_Ptr) pc < pc_begin)
-	hi = i;
-      else if ((_Unwind_Ptr) pc >= pc_begin + pc_range)
-	lo = i + 1;
-      else
-	return f;
-    }
-
-  return NULL;
-}
-
-static fde *
-search_object (struct object* ob, void *pc)
-{
-  /* If the data hasn't been sorted, try to do this now.  We may have
-     more memory available than last time we tried.  */
-  if (! ob->s.b.sorted)
-    {
-      init_object (ob);
-
-      /* Despite the above comment, the normal reason to get here is
-	 that we've not processed this object before.  A quick range
-	 check is in order.  */
-      if (pc < ob->pc_begin)
-	return NULL;
-    }
-
-  if (ob->s.b.sorted)
-    {
-      if (ob->s.b.mixed_encoding)
-	return binary_search_mixed_encoding_fdes (ob, pc);
-      else if (ob->s.b.encoding == DW_EH_PE_absptr)
-	return binary_search_unencoded_fdes (ob, pc);
-      else
-	return binary_search_single_encoding_fdes (ob, pc);
-    }
-  else
-    {
-      /* Long slow labourious linear search, cos we've no memory.  */
-      if (ob->s.b.from_array)
-	{
-	  fde **p;
-	  for (p = ob->u.array; *p ; p++)
-	    {
-	      fde *f = linear_search_fdes (ob, *p, pc);
-	      if (f)
-		return f;
-	    }
-	  return NULL;
-	}
-      else
-	return linear_search_fdes (ob, ob->u.single, pc);
-    }
-}
-
-fde *
-_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
-{
-  struct object *ob;
-  fde *f = NULL;
-
-  init_object_mutex_once ();
-  __gthread_mutex_lock (&object_mutex);
-
-  /* Linear search through the classified objects, to find the one
-     containing the pc.  Note that pc_begin is sorted descending, and
-     we expect objects to be non-overlapping.  */
-  for (ob = seen_objects; ob; ob = ob->next)
-    if (pc >= ob->pc_begin)
-      {
-	f = search_object (ob, pc);
-	if (f)
-	  goto fini;
-	break;
-      }
-
-  /* Classify and search the objects we've not yet processed.  */
-  while ((ob = unseen_objects))
-    {
-      struct object **p;
-
-      unseen_objects = ob->next;
-      f = search_object (ob, pc);
-
-      /* Insert the object into the classified list.  */
-      for (p = &seen_objects; *p ; p = &(*p)->next)
-	if ((*p)->pc_begin < ob->pc_begin)
-	  break;
-      ob->next = *p;
-      *p = ob;
-
-      if (f)
-	goto fini;
-    }
-
- fini:
-  __gthread_mutex_unlock (&object_mutex);
-
-  if (f)
-    {
-      int encoding;
-      _Unwind_Ptr func;
-
-      bases->tbase = ob->tbase;
-      bases->dbase = ob->dbase;
-
-      encoding = ob->s.b.encoding;
-      if (ob->s.b.mixed_encoding)
-	encoding = get_fde_encoding (f);
-      read_encoded_value_with_base (encoding, base_from_object (encoding, ob),
-				    f->pc_begin, &func);
-      bases->func = (void *) func;
-    }
-
-  return f;
-}
-
-#endif