diff options
-rw-r--r-- | sysdeps/generic/unwind-dw2-fde.c | 228 | ||||
-rw-r--r-- | sysdeps/generic/unwind-dw2-fde.h | 49 | ||||
-rw-r--r-- | sysdeps/generic/unwind-dw2.c | 369 | ||||
-rw-r--r-- | sysdeps/generic/unwind-pe.h | 145 |
4 files changed, 441 insertions, 350 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 diff --git a/sysdeps/generic/unwind-dw2-fde.h b/sysdeps/generic/unwind-dw2-fde.h index 83b4470ce5..4fc4836d2a 100644 --- a/sysdeps/generic/unwind-dw2-fde.h +++ b/sysdeps/generic/unwind-dw2-fde.h @@ -1,13 +1,14 @@ /* 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, 2003 + 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 +19,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. */ struct fde_vector @@ -57,12 +58,16 @@ struct object unsigned long mixed_encoding : 1; unsigned long encoding : 8; /* ??? Wish there was an easy way to detect a 64-bit host here; - we've got 32 bits left to play with... */ + we've got 32 bits left to play with... */ unsigned long count : 21; } b; size_t i; } s; +#ifdef DWARF2_OBJECT_END_PTR_EXTENSION + char *fde_end; +#endif + struct object *next; }; #endif @@ -116,7 +121,7 @@ typedef unsigned char ubyte; is located, and what the register lifetimes and stack layout are within the function. - The data structures are defined in the DWARF specfication, although + The data structures are defined in the DWARF specification, although not in a very readable way (see LITERATURE). Every time an exception is thrown, the code needs to locate the FDE @@ -125,7 +130,7 @@ typedef unsigned char ubyte; a) in a linear search, find the shared image (i.e. DLL) containing the PC b) using the FDE table for that shared object, locate the FDE using - binary search (which requires the sorting). */ + binary search (which requires the sorting). */ /* The first few fields of a CIE. The CIE_id field is 0 for a CIE, to distinguish it from a valid FDE. FDEs are aligned to an addressing @@ -159,7 +164,17 @@ get_cie (struct dwarf_fde *f) static inline fde * next_fde (fde *f) { - return (fde *)((char *)f + f->length + sizeof (f->length)); + return (fde *) ((char *) f + f->length + sizeof (f->length)); } extern fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *); + +static inline int +last_fde (struct object *obj __attribute__ ((__unused__)), fde *f) +{ +#ifdef DWARF2_OBJECT_END_PTR_EXTENSION + return (char *)f == obj->fde_end || f->length == 0; +#else + return f->length == 0; +#endif +} diff --git a/sysdeps/generic/unwind-dw2.c b/sysdeps/generic/unwind-dw2.c index 3a53156621..720034427d 100644 --- a/sysdeps/generic/unwind-dw2.c +++ b/sysdeps/generic/unwind-dw2.c @@ -1,22 +1,23 @@ /* DWARF2 exception handling and frame unwind runtime interface routines. - Copyright (C) 1997,1998,1999,2000,2001,2003 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. - 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 + 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. - 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 <stdlib.h> @@ -37,7 +38,8 @@ #include "gthr.h" #endif -#if !USING_SJLJ_EXCEPTIONS + +#ifndef __USING_SJLJ_EXCEPTIONS__ #ifndef STACK_GROWS_DOWNWARD #define STACK_GROWS_DOWNWARD 0 @@ -52,7 +54,14 @@ #define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER #endif -/* This is the register and unwind state for a particular frame. */ +/* Dwarf frame registers used for pre gcc 3.0 compiled glibc. */ +#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS +#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS +#endif + +/* This is the register and unwind state for a particular frame. This + provides the information necessary to unwind up past a frame and return + to its caller. */ struct _Unwind_Context { void *reg[DWARF_FRAME_REGISTERS+1]; @@ -80,7 +89,7 @@ typedef struct { struct { union { - unsigned int reg; + _Unwind_Word reg; _Unwind_Sword offset; const unsigned char *exp; } loc; @@ -112,8 +121,8 @@ typedef struct /* The information we care about from the CIE/FDE. */ _Unwind_Personality_Fn personality; - signed int data_align; - unsigned int code_align; + _Unwind_Sword data_align; + _Unwind_Word code_align; unsigned char retaddr_column; unsigned char fde_encoding; unsigned char lsda_encoding; @@ -138,10 +147,10 @@ static inline void * read_pointer (const void *p) { const union unaligned *up = p; return up->p; } static inline int -read_1u (const void *p) { return *(const unsigned char *)p; } +read_1u (const void *p) { return *(const unsigned char *) p; } static inline int -read_1s (const void *p) { return *(const signed char *)p; } +read_1s (const void *p) { return *(const signed char *) p; } static inline int read_2u (const void *p) { const union unaligned *up = p; return up->u2; } @@ -170,6 +179,14 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index) return * (_Unwind_Word *) context->reg[index]; } +/* Get the value of the CFA as saved in CONTEXT. */ + +_Unwind_Word +_Unwind_GetCFA (struct _Unwind_Context *context) +{ + return context->cfa; +} + /* Overwrite the saved value for register REG in CONTEXT with VAL. */ inline void @@ -206,6 +223,17 @@ _Unwind_GetRegionStart (struct _Unwind_Context *context) return (_Unwind_Ptr) context->bases.func; } +void * +_Unwind_FindEnclosingFunction (void *pc) +{ + struct dwarf_eh_bases bases; + struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases); + if (fde) + return bases.func; + else + return NULL; +} + #ifndef __ia64__ _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *context) @@ -231,7 +259,7 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context, const unsigned char *aug = cie->augmentation; const unsigned char *p = aug + strlen (aug) + 1; const unsigned char *ret = NULL; - _Unwind_Ptr tmp; + _Unwind_Word utmp; /* g++ v2 "eh" has pointer immediately following augmentation string, so it must be handled first. */ @@ -244,8 +272,8 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context, /* Immediately following the augmentation are the code and data alignment and return address column. */ - p = read_uleb128 (p, &tmp); fs->code_align = tmp; - p = read_sleb128 (p, &tmp); fs->data_align = (saddr) tmp; + p = read_uleb128 (p, &fs->code_align); + p = read_sleb128 (p, &fs->data_align); fs->retaddr_column = *p++; fs->lsda_encoding = DW_EH_PE_omit; @@ -254,8 +282,8 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context, the size. */ if (*aug == 'z') { - p = read_uleb128 (p, &tmp); - ret = p + tmp; + p = read_uleb128 (p, &utmp); + ret = p + utmp; fs->saw_z = 1; ++aug; @@ -303,7 +331,7 @@ static _Unwind_Word execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, struct _Unwind_Context *context, _Unwind_Word initial) { - _Unwind_Word stack[64]; /* ??? Assume this is enough. */ + _Unwind_Word stack[64]; /* ??? Assume this is enough. */ int stack_elt; stack[0] = initial; @@ -312,9 +340,8 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, while (op_ptr < op_end) { enum dwarf_location_atom op = *op_ptr++; - _Unwind_Word result = 0, reg; - _Unwind_Sword offset; - _Unwind_Ptr ptrtmp; + _Unwind_Word result, reg, utmp; + _Unwind_Sword offset, stmp; switch (op) { @@ -391,12 +418,11 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, op_ptr += 8; break; case DW_OP_constu: - op_ptr = read_uleb128 (op_ptr, &ptrtmp); - result = ptrtmp; + op_ptr = read_uleb128 (op_ptr, &result); break; case DW_OP_consts: - op_ptr = read_sleb128 (op_ptr, &ptrtmp); - result = (saddr)ptrtmp; + op_ptr = read_sleb128 (op_ptr, &stmp); + result = stmp; break; case DW_OP_reg0: @@ -434,7 +460,7 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, result = _Unwind_GetGR (context, op - DW_OP_reg0); break; case DW_OP_regx: - op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp; + op_ptr = read_uleb128 (op_ptr, ®); result = _Unwind_GetGR (context, reg); break; @@ -470,12 +496,12 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: - op_ptr = read_sleb128 (op_ptr, &ptrtmp); offset = (saddr)ptrtmp; + op_ptr = read_sleb128 (op_ptr, &offset); result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset; break; case DW_OP_bregx: - op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp; - op_ptr = read_sleb128 (op_ptr, &ptrtmp); offset = (saddr)ptrtmp; + op_ptr = read_uleb128 (op_ptr, ®); + op_ptr = read_sleb128 (op_ptr, &offset); result = _Unwind_GetGR (context, reg) + offset; break; @@ -533,14 +559,14 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, { case DW_OP_deref: { - void *ptr = (void *)(_Unwind_Ptr) result; + void *ptr = (void *) (_Unwind_Ptr) result; result = (_Unwind_Ptr) read_pointer (ptr); } break; case DW_OP_deref_size: { - void *ptr = (void *)(_Unwind_Ptr) result; + void *ptr = (void *) (_Unwind_Ptr) result; switch (*op_ptr++) { case 1: @@ -572,12 +598,12 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, result = ~result; break; case DW_OP_plus_uconst: - op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp; - result += reg; + op_ptr = read_uleb128 (op_ptr, &utmp); + result += utmp; break; - /* Avoid warnings. */ + default: - break; + abort (); } break; @@ -597,68 +623,68 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, { /* Binary operations. */ _Unwind_Word first, second; - if ((stack_elt -= 2) < 0) - abort (); - second = stack[stack_elt]; - first = stack[stack_elt + 1]; + if ((stack_elt -= 2) < 0) + abort (); + second = stack[stack_elt]; + first = stack[stack_elt + 1]; - switch (op) - { - case DW_OP_and: - result = second & first; - break; - case DW_OP_div: - result = (_Unwind_Sword)second / (_Unwind_Sword)first; - break; - case DW_OP_minus: - result = second - first; - break; - case DW_OP_mod: - result = (_Unwind_Sword)second % (_Unwind_Sword)first; - break; - case DW_OP_mul: - result = second * first; - break; - case DW_OP_or: - result = second | first; - break; - case DW_OP_plus: - result = second + first; - break; - case DW_OP_shl: - result = second << first; - break; - case DW_OP_shr: - result = second >> first; - break; - case DW_OP_shra: - result = (_Unwind_Sword)second >> first; - break; - case DW_OP_xor: - result = second ^ first; - break; - case DW_OP_le: - result = (_Unwind_Sword)first <= (_Unwind_Sword)second; - break; - case DW_OP_ge: - result = (_Unwind_Sword)first >= (_Unwind_Sword)second; - break; - case DW_OP_eq: - result = (_Unwind_Sword)first == (_Unwind_Sword)second; - break; - case DW_OP_lt: - result = (_Unwind_Sword)first < (_Unwind_Sword)second; - break; - case DW_OP_gt: - result = (_Unwind_Sword)first > (_Unwind_Sword)second; - break; - case DW_OP_ne: - result = (_Unwind_Sword)first != (_Unwind_Sword)second; - break; - default: - /* Avoid warnings. */ - break; - } + switch (op) + { + case DW_OP_and: + result = second & first; + break; + case DW_OP_div: + result = (_Unwind_Sword) second / (_Unwind_Sword) first; + break; + case DW_OP_minus: + result = second - first; + break; + case DW_OP_mod: + result = (_Unwind_Sword) second % (_Unwind_Sword) first; + break; + case DW_OP_mul: + result = second * first; + break; + case DW_OP_or: + result = second | first; + break; + case DW_OP_plus: + result = second + first; + break; + case DW_OP_shl: + result = second << first; + break; + case DW_OP_shr: + result = second >> first; + break; + case DW_OP_shra: + result = (_Unwind_Sword) second >> first; + break; + case DW_OP_xor: + result = second ^ first; + break; + case DW_OP_le: + result = (_Unwind_Sword) first <= (_Unwind_Sword) second; + break; + case DW_OP_ge: + result = (_Unwind_Sword) first >= (_Unwind_Sword) second; + break; + case DW_OP_eq: + result = (_Unwind_Sword) first == (_Unwind_Sword) second; + break; + case DW_OP_lt: + result = (_Unwind_Sword) first < (_Unwind_Sword) second; + break; + case DW_OP_gt: + result = (_Unwind_Sword) first > (_Unwind_Sword) second; + break; + case DW_OP_ne: + result = (_Unwind_Sword) first != (_Unwind_Sword) second; + break; + + default: + abort (); + } } break; @@ -714,20 +740,26 @@ execute_cfa_program (const unsigned char *insn_ptr, /* Don't allow remember/restore between CIE and FDE programs. */ fs->regs.prev = NULL; + /* The comparison with the return address uses < rather than <= because + we are only interested in the effects of code before the call; for a + noreturn function, the return address may point to unrelated code with + a different stack configuration that we are not interested in. We + assume that the call itself is unwind info-neutral; if not, or if + there are delay instructions that adjust the stack, these must be + reflected at the point immediately before the call insn. */ while (insn_ptr < insn_end && fs->pc < context->ra) { unsigned char insn = *insn_ptr++; - _Unwind_Word reg; - _Unwind_Sword offset; - _Unwind_Ptr ptrtmp; + _Unwind_Word reg, utmp; + _Unwind_Sword offset, stmp; if ((insn & 0xc0) == DW_CFA_advance_loc) fs->pc += (insn & 0x3f) * fs->code_align; else if ((insn & 0xc0) == DW_CFA_offset) { reg = insn & 0x3f; - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - offset = ptrtmp * fs->data_align; + insn_ptr = read_uleb128 (insn_ptr, &utmp); + offset = (_Unwind_Sword) utmp * fs->data_align; fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; } @@ -757,28 +789,31 @@ execute_cfa_program (const unsigned char *insn_ptr, break; case DW_CFA_offset_extended: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - offset = ptrtmp * fs->data_align; + insn_ptr = read_uleb128 (insn_ptr, ®); + insn_ptr = read_uleb128 (insn_ptr, &utmp); + offset = (_Unwind_Sword) utmp * fs->data_align; fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; break; case DW_CFA_restore_extended: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, ®); fs->regs.reg[reg].how = REG_UNSAVED; break; case DW_CFA_undefined: case DW_CFA_same_value: + insn_ptr = read_uleb128 (insn_ptr, ®); + break; + case DW_CFA_nop: break; case DW_CFA_register: { _Unwind_Word reg2; - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg2 = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, ®); + insn_ptr = read_uleb128 (insn_ptr, ®2); fs->regs.reg[reg].how = REG_SAVED_REG; fs->regs.reg[reg].loc.reg = reg2; } @@ -793,7 +828,7 @@ execute_cfa_program (const unsigned char *insn_ptr, unused_rs = unused_rs->prev; } else - new_rs = alloca (sizeof (struct frame_state_reg_info)); + new_rs = __builtin_alloca (sizeof (struct frame_state_reg_info)); *new_rs = fs->regs; fs->regs.prev = new_rs; @@ -810,60 +845,55 @@ execute_cfa_program (const unsigned char *insn_ptr, break; case DW_CFA_def_cfa: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - fs->cfa_reg = ptrtmp; - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - fs->cfa_offset = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); + insn_ptr = read_uleb128 (insn_ptr, &utmp); + fs->cfa_offset = utmp; fs->cfa_how = CFA_REG_OFFSET; break; case DW_CFA_def_cfa_register: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - fs->cfa_reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); fs->cfa_how = CFA_REG_OFFSET; break; case DW_CFA_def_cfa_offset: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - fs->cfa_offset = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &utmp); + fs->cfa_offset = utmp; /* cfa_how deliberately not set. */ break; case DW_CFA_def_cfa_expression: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + insn_ptr = read_uleb128 (insn_ptr, &utmp); fs->cfa_exp = insn_ptr; fs->cfa_how = CFA_EXP; - insn_ptr += ptrtmp; + insn_ptr += utmp; break; case DW_CFA_expression: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + insn_ptr = read_uleb128 (insn_ptr, ®); + insn_ptr = read_uleb128 (insn_ptr, &utmp); fs->regs.reg[reg].how = REG_SAVED_EXP; fs->regs.reg[reg].loc.exp = insn_ptr; - insn_ptr += ptrtmp; + insn_ptr += utmp; break; /* From the 2.1 draft. */ case DW_CFA_offset_extended_sf: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; - insn_ptr = read_sleb128 (insn_ptr, &ptrtmp); - offset = (saddr)ptrtmp * fs->data_align; + insn_ptr = read_uleb128 (insn_ptr, ®); + insn_ptr = read_sleb128 (insn_ptr, &stmp); + offset = stmp * fs->data_align; fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; break; case DW_CFA_def_cfa_sf: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - fs->cfa_reg = ptrtmp; - insn_ptr = read_sleb128 (insn_ptr, &ptrtmp); - fs->cfa_offset = (saddr)ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); + insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset); fs->cfa_how = CFA_REG_OFFSET; break; case DW_CFA_def_cfa_offset_sf: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - fs->cfa_offset = ptrtmp; + insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset); /* cfa_how deliberately not set. */ break; @@ -877,16 +907,15 @@ execute_cfa_program (const unsigned char *insn_ptr, break; case DW_CFA_GNU_args_size: - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - context->args_size = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &context->args_size); break; case DW_CFA_GNU_negative_offset_extended: /* Obsoleted by DW_CFA_offset_extended_sf, but used by older PowerPC code. */ - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; - insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); - offset = ptrtmp * fs->data_align; + insn_ptr = read_uleb128 (insn_ptr, ®); + insn_ptr = read_uleb128 (insn_ptr, &utmp); + offset = (_Unwind_Word) utmp * fs->data_align; fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = -offset; break; @@ -897,6 +926,11 @@ execute_cfa_program (const unsigned char *insn_ptr, } } +/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for + its caller and decode it into FS. This function also sets the + args_size and lsda members of CONTEXT, as they are really information + about the caller's frame. */ + static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) { @@ -913,7 +947,7 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) { /* Couldn't find frame unwind info for this function. Try a target-specific fallback mechanism. This will necessarily - not profide a personality routine or LSDA. */ + not provide a personality routine or LSDA. */ #ifdef MD_FALLBACK_FRAME_STATE_FOR MD_FALLBACK_FRAME_STATE_FOR (context, fs, success); return _URC_END_OF_STACK; @@ -937,12 +971,12 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) execute_cfa_program (insn, end, context, fs); /* Locate augmentation for the fde. */ - aug = (unsigned char *)fde + sizeof (*fde); + aug = (unsigned char *) fde + sizeof (*fde); aug += 2 * size_of_encoded_value (fs->fde_encoding); insn = NULL; if (fs->saw_z) { - _Unwind_Ptr i; + _Unwind_Word i; aug = read_uleb128 (aug, &i); insn = aug + i; } @@ -965,10 +999,10 @@ typedef struct frame_state void *eh_ptr; long cfa_offset; long args_size; - long reg_or_offset[DWARF_FRAME_REGISTERS+1]; + long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1]; unsigned short cfa_reg; unsigned short retaddr_column; - char saved[DWARF_FRAME_REGISTERS+1]; + char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1]; } frame_state; #ifndef STATIC @@ -1001,7 +1035,7 @@ __frame_state_for (void *pc_target, struct frame_state *state_in) if (fs.cfa_how == CFA_EXP) return 0; - for (reg = 0; reg < DWARF_FRAME_REGISTERS + 1; reg++) + for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++) { state_in->saved[reg] = fs.regs.reg[reg].how; switch (state_in->saved[reg]) @@ -1059,7 +1093,7 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) that this will not be a problem. */ { const unsigned char *exp = fs->cfa_exp; - _Unwind_Ptr len; + _Unwind_Word len; exp = read_uleb128 (exp, &len); cfa = (void *) (_Unwind_Ptr) @@ -1087,7 +1121,7 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) case REG_SAVED_EXP: { const unsigned char *exp = fs->regs.reg[i].loc.exp; - _Unwind_Ptr len; + _Unwind_Word len; _Unwind_Ptr val; exp = read_uleb128 (exp, &len); @@ -1099,6 +1133,11 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) } } +/* CONTEXT describes the unwind state for a frame, and FS describes the FDE + of its caller. Update CONTEXT to refer to the caller as well. Note + that the args_size and lsda members are not updated here, but later in + uw_frame_state_for. */ + static void uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) { @@ -1113,14 +1152,16 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) /* Fill in CONTEXT for top-of-stack. The only valid registers at this level will be the return address and the CFA. */ -#define uw_init_context(CONTEXT) \ -do { \ - /* Do any necessary initialization to access arbitrary stack frames. \ - On the SPARC, this means flushing the register windows. */ \ - __builtin_unwind_init (); \ - uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \ - __builtin_return_address (0)); \ -} while (0) +#define uw_init_context(CONTEXT) \ + do \ + { \ + /* Do any necessary initialization to access arbitrary stack frames. \ + On the SPARC, this means flushing the register windows. */ \ + __builtin_unwind_init (); \ + uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \ + __builtin_return_address (0)); \ + } \ + while (0) static void uw_init_context_1 (struct _Unwind_Context *context, @@ -1154,12 +1195,14 @@ uw_init_context_1 (struct _Unwind_Context *context, macro because __builtin_eh_return must be invoked in the context of our caller. */ -#define uw_install_context(CURRENT, TARGET) \ -do { \ - long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ - void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ - __builtin_eh_return (offset, handler); \ -} while (0) +#define uw_install_context(CURRENT, TARGET) \ + do \ + { \ + long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ + void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ + __builtin_eh_return (offset, handler); \ + } \ + while (0) static inline void init_dwarf_reg_size_table (void) diff --git a/sysdeps/generic/unwind-pe.h b/sysdeps/generic/unwind-pe.h index 9a031c1f32..f787392881 100644 --- a/sysdeps/generic/unwind-pe.h +++ b/sysdeps/generic/unwind-pe.h @@ -1,28 +1,28 @@ /* Exception handling and frame unwind runtime interface routines. Copyright (C) 2001, 2002 Free Software Foundation, Inc. - 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 + 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. - 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. */ /* @@@ Really this should be out of line, but this also causes link compatibility problems with the base ABI. This is slightly better than duplicating code, however. */ -/* If using C++, references to abort have to be qualified with std::. */ +/* If using C++, references to abort have to be qualified with std::. */ #if __cplusplus #define __gxx_abort std::abort #else @@ -66,10 +66,7 @@ extern const unsigned char *read_encoded_value_with_base This is only defined for fixed-size encodings, and so does not include leb128. */ -#ifndef _LIBC -static -#endif -unsigned int +static unsigned int size_of_encoded_value (unsigned char encoding) #if defined(_LIBC) && !defined(NO_BASE_OF_ENCODED_VALUE) ; @@ -125,14 +122,62 @@ base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context) #endif +/* Read an unsigned leb128 value from P, store the value in VAL, return + P incremented past the value. We assume that a word is large enough to + hold any value so encoded; if it is smaller than a pointer on some target, + pointers should not be leb128 encoded on that target. */ + +static const unsigned char * +read_uleb128 (const unsigned char *p, _Unwind_Word *val) +{ + unsigned int shift = 0; + unsigned char byte; + _Unwind_Word result; + + result = 0; + do + { + byte = *p++; + result |= (byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + *val = result; + return p; +} + +/* Similar, but read a signed leb128 value. */ + +static const unsigned char * +read_sleb128 (const unsigned char *p, _Unwind_Sword *val) +{ + unsigned int shift = 0; + unsigned char byte; + _Unwind_Word result; + + result = 0; + do + { + byte = *p++; + result |= (byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + /* Sign-extend a negative value. */ + if (shift < 8 * sizeof(result) && (byte & 0x40) != 0) + result |= -(1L << shift); + + *val = (_Unwind_Sword) result; + return p; +} + /* Load an encoded value from memory at P. The value is returned in VAL; The function returns P incremented past the value. BASE is as given by base_of_encoded_value for this encoding in the appropriate context. */ -#ifndef _LIBC -static -#endif -const unsigned char * +static const unsigned char * read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, const unsigned char *p, _Unwind_Ptr *val) #if defined(_LIBC) && !defined(NO_BASE_OF_ENCODED_VALUE) @@ -151,56 +196,37 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, } __attribute__((__packed__)); union unaligned *u = (union unaligned *) p; - _Unwind_Ptr result; + _Unwind_Internal_Ptr result; if (encoding == DW_EH_PE_aligned) { - _Unwind_Ptr a = (_Unwind_Ptr)p; + _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p; a = (a + sizeof (void *) - 1) & - sizeof(void *); - result = *(_Unwind_Ptr *) a; - p = (const unsigned char *)(a + sizeof (void *)); + result = *(_Unwind_Internal_Ptr *) a; + p = (const unsigned char *) (a + sizeof (void *)); } else { switch (encoding & 0x0f) { case DW_EH_PE_absptr: - result = (_Unwind_Ptr) u->ptr; + result = (_Unwind_Internal_Ptr) u->ptr; p += sizeof (void *); break; case DW_EH_PE_uleb128: { - unsigned int shift = 0; - unsigned char byte; - - result = 0; - do - { - byte = *p++; - result |= (_Unwind_Ptr)(byte & 0x7f) << shift; - shift += 7; - } - while (byte & 0x80); + _Unwind_Word tmp; + p = read_uleb128 (p, &tmp); + result = (_Unwind_Internal_Ptr) tmp; } break; case DW_EH_PE_sleb128: { - unsigned int shift = 0; - unsigned char byte; - - result = 0; - do - { - byte = *p++; - result |= (_Unwind_Ptr)(byte & 0x7f) << shift; - shift += 7; - } - while (byte & 0x80); - - if (shift < 8 * sizeof(result) && (byte & 0x40) != 0) - result |= -(1L << shift); + _Unwind_Sword tmp; + p = read_sleb128 (p, &tmp); + result = (_Unwind_Internal_Ptr) tmp; } break; @@ -237,9 +263,9 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, if (result != 0) { result += ((encoding & 0x70) == DW_EH_PE_pcrel - ? (_Unwind_Ptr)u : base); + ? (_Unwind_Internal_Ptr) u : base); if (encoding & DW_EH_PE_indirect) - result = *(_Unwind_Ptr *)result; + result = *(_Unwind_Internal_Ptr *) result; } } @@ -263,20 +289,3 @@ read_encoded_value (struct _Unwind_Context *context, unsigned char encoding, } #endif - -/* Read an unsigned leb128 value from P, store the value in VAL, return - P incremented past the value. */ - -static inline const unsigned char * -read_uleb128 (const unsigned char *p, _Unwind_Ptr *val) -{ - return read_encoded_value_with_base (DW_EH_PE_uleb128, 0, p, val); -} - -/* Similar, but read a signed leb128 value. */ - -static inline const unsigned char * -read_sleb128 (const unsigned char *p, _Unwind_Ptr *val) -{ - return read_encoded_value_with_base (DW_EH_PE_sleb128, 0, p, val); -} |