mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-12 16:20:06 +00:00
Update from recent gcc version.
This commit is contained in:
parent
6a1aff6912
commit
6180ac2f06
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user