diff options
Diffstat (limited to 'sysdeps/generic/unwind-dw2-fde.c')
-rw-r--r-- | sysdeps/generic/unwind-dw2-fde.c | 228 |
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 |