/* 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 GCC.
#ifndef _Unwind_Find_FDE
#include "tconfig.h"
#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
#include "dwarf2.h"
#include "unwind.h"
#define NO_BASE_OF_ENCODED_VALUE
#endif
#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
-static void
+static void
init_object_mutex (void)
{
__GTHREAD_MUTEX_INIT_FUNCTION (&object_mutex);
void *tbase, void *dbase)
{
/* If .eh_frame is empty, don't register at all. */
- if (*(uword *)begin == 0)
+ if ((uword *) begin == 0 || *(uword *) begin == 0)
return;
ob->pc_begin = (void *)-1;
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);
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));
- __register_frame_info (begin, ob);
+ __register_frame_info (begin, ob);
}
/* Similar, but BEGIN is actually a pointer to a table of unwind entries
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
+ exact same thing, but will resolve to the same library as
implements __register_frame_info_bases. */
void *
struct object *ob = 0;
/* If .eh_frame is empty, we haven't registered. */
- if (*(uword *)begin == 0)
+ if ((uword *) begin == 0 || *(uword *) begin == 0)
return ob;
init_object_mutex_once ();
__deregister_frame (void *begin)
{
/* If .eh_frame is empty, we haven't registered. */
- if (*(uword *)begin != 0)
+ if (*(uword *) begin != 0)
free (__deregister_frame_info (begin));
}
return 1;
}
else
- return 0;
+ return 0;
}
static inline void
/* 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.
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;
+ 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];
}
erratic->count = k;
}
+#define SWAP(x,y) do { fde * tmp = x; x = y; y = tmp; } while (0)
+
+/* Convert a semi-heap to a heap. A semi-heap is a heap except possibly
+ for the first (root) node; push it down to its rightful place. */
+
+static void
+frame_downheap (struct object *ob, fde_compare_t fde_compare, fde **a,
+ int lo, int hi)
+{
+ int i, j;
+
+ for (i = lo, j = 2*i+1;
+ j < hi;
+ j = 2*i+1)
+ {
+ if (j+1 < hi && fde_compare (ob, a[j], a[j+1]) < 0)
+ ++j;
+
+ if (fde_compare (ob, a[i], a[j]) < 0)
+ {
+ SWAP (a[i], a[j]);
+ i = j;
+ }
+ else
+ break;
+ }
+}
+
/* This is O(n log(n)). BSD/OS defines heapsort in stdlib.h, so we must
use a name that does not conflict. */
/* 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)
+ int m;
+
+ /* Expand our heap incrementally from the end of the array, heapifying
+ each resulting semi-heap as we go. After each step, a[m] is the top
+ of a heap. */
+ for (m = n/2-1; m >= 0; --m)
+ frame_downheap (ob, fde_compare, a, m, n);
+
+ /* Shrink our heap incrementally from the end of the array, first
+ swapping out the largest element a[0] and then re-heapifying the
+ resulting semi-heap. After each step, a[0..m) is a heap. */
+ for (m = n-1; m >= 1; --m)
{
- /* 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;
- }
+ SWAP (a[0], a[m]);
+ frame_downheap (ob, fde_compare, a, 0, m);
}
#undef SWAP
}
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;
}
}
}
\f
-/* Update encoding, mixed_encoding, and pc_begin for OB for the
+/* 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. */
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;
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;
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;
if (encoding == DW_EH_PE_absptr)
{
- if (*(_Unwind_Ptr *)this_fde->pc_begin == 0)
+ if (*(_Unwind_Ptr *) this_fde->pc_begin == 0)
continue;
}
else
{
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);
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;
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;
}
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;
{
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;
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;
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;
&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;
{
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;
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;
{
/* 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