/* Subroutines needed for unwinding stack frames for exception handling. */
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008,
+ 2009, 2010 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GCC.
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
+Software Foundation; either version 3, 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
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file. (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
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 GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
#ifndef _Unwind_Find_FDE
#include "tconfig.h"
/* The unseen_objects list contains objects that have been registered
but not yet categorized in any way. The seen_objects list has had
- it's pc_begin and count fields initialized at minimum, and is sorted
+ its pc_begin and count fields initialized at minimum, and is sorted
by decreasing value of pc_begin. */
static struct object *unseen_objects;
static struct object *seen_objects;
void *tbase, void *dbase)
{
/* If .eh_frame is empty, don't register at all. */
- if ((uword *) begin == 0 || *(uword *) begin == 0)
+ if ((const uword *) begin == 0 || *(const uword *) begin == 0)
return;
ob->pc_begin = (void *)-1;
struct object *ob = 0;
/* If .eh_frame is empty, we haven't registered. */
- if ((uword *) begin == 0 || *(uword *) begin == 0)
+ if ((const uword *) begin == 0 || *(const uword *) begin == 0)
return ob;
init_object_mutex_once ();
{
const unsigned char *aug, *p;
_Unwind_Ptr dummy;
- _Unwind_Word utmp;
- _Unwind_Sword stmp;
+ _uleb128_t utmp;
+ _sleb128_t stmp;
aug = cie->augmentation;
+ p = aug + strlen ((const char *)aug) + 1; /* Skip the augmentation string. */
+ if (__builtin_expect (cie->version >= 4, 0))
+ {
+ if (p[0] != sizeof (void *) || p[1] != 0)
+ return DW_EH_PE_omit; /* We are not prepared to handle unexpected
+ address sizes or segment selectors. */
+ p += 2; /* Skip address size and segment size. */
+ }
+
if (aug[0] != 'z')
return DW_EH_PE_absptr;
- p = aug + strlen ((const char *)aug) + 1; /* Skip the augmentation string. */
p = read_uleb128 (p, &utmp); /* Skip code alignment. */
p = read_sleb128 (p, &stmp); /* Skip data alignment. */
if (cie->version == 1) /* Skip return address column. */
fde_unencoded_compare (struct object *ob __attribute__((unused)),
const fde *x, const fde *y)
{
- _Unwind_Ptr x_ptr = *(_Unwind_Ptr *) x->pc_begin;
- _Unwind_Ptr y_ptr = *(_Unwind_Ptr *) y->pc_begin;
+ _Unwind_Ptr x_ptr, y_ptr;
+ memcpy (&x_ptr, x->pc_begin, sizeof (_Unwind_Ptr));
+ memcpy (&y_ptr, y->pc_begin, sizeof (_Unwind_Ptr));
if (x_ptr > y_ptr)
return 1;
{
static const fde *marker;
size_t count = linear->count;
- const fde **chain_end = ▮
+ const fde *const *chain_end = ▮
size_t i, j, k;
/* This should optimize out, but it is wise to make sure this assumption
for (i = 0; i < count; i++)
{
- const fde **probe;
+ const fde *const *probe;
for (probe = chain_end;
probe != &marker && fde_compare (ob, linear->array[i], *probe) < 0;
probe = chain_end)
{
- chain_end = (const fde **) erratic->array[probe - linear->array];
+ chain_end = (const fde *const*) erratic->array[probe - linear->array];
erratic->array[probe - linear->array] = NULL;
}
erratic->array[i] = (const fde *) chain_end;
{
last_cie = this_cie;
encoding = get_cie_encoding (this_cie);
+ if (encoding == DW_EH_PE_omit)
+ return -1;
base = base_from_object (encoding, ob);
if (ob->s.b.encoding == DW_EH_PE_omit)
ob->s.b.encoding = encoding;
be representable. Assume 0 in the representable bits is NULL. */
mask = size_of_encoded_value (encoding);
if (mask < sizeof (void *))
- mask = (1L << (mask << 3)) - 1;
+ mask = (((_Unwind_Ptr) 1) << (mask << 3)) - 1;
else
mask = -1;
if (encoding == DW_EH_PE_absptr)
{
- if (*(_Unwind_Ptr *) this_fde->pc_begin == 0)
+ _Unwind_Ptr ptr;
+ memcpy (&ptr, this_fde->pc_begin, sizeof (_Unwind_Ptr));
+ if (ptr == 0)
continue;
}
else
be representable. Assume 0 in the representable bits is NULL. */
mask = size_of_encoded_value (encoding);
if (mask < sizeof (void *))
- mask = (1L << (mask << 3)) - 1;
+ mask = (((_Unwind_Ptr) 1) << (mask << 3)) - 1;
else
mask = -1;
{
fde **p = ob->u.array;
for (count = 0; *p; ++p)
- count += classify_object_over_fdes (ob, *p);
+ {
+ size_t cur_count = classify_object_over_fdes (ob, *p);
+ if (cur_count == (size_t) -1)
+ goto unhandled_fdes;
+ count += cur_count;
+ }
}
else
- count = classify_object_over_fdes (ob, ob->u.single);
+ {
+ count = classify_object_over_fdes (ob, ob->u.single);
+ if (count == (size_t) -1)
+ {
+ static const fde terminator;
+ unhandled_fdes:
+ ob->s.i = 0;
+ ob->s.b.encoding = DW_EH_PE_omit;
+ ob->u.single = &terminator;
+ return;
+ }
+ }
/* The count field we have in the main struct object is somewhat
limited, but should suffice for virtually all cases. If the
if (encoding == DW_EH_PE_absptr)
{
- pc_begin = ((_Unwind_Ptr *) this_fde->pc_begin)[0];
- pc_range = ((_Unwind_Ptr *) this_fde->pc_begin)[1];
+ const _Unwind_Ptr *pc_array = (const _Unwind_Ptr *) this_fde->pc_begin;
+ pc_begin = pc_array[0];
+ pc_range = pc_array[1];
if (pc_begin == 0)
continue;
}
be representable. Assume 0 in the representable bits is NULL. */
mask = size_of_encoded_value (encoding);
if (mask < sizeof (void *))
- mask = (1L << (mask << 3)) - 1;
+ mask = (((_Unwind_Ptr) 1) << (mask << 3)) - 1;
else
mask = -1;
for (lo = 0, hi = vec->count; lo < hi; )
{
size_t i = (lo + hi) / 2;
- const fde *f = vec->array[i];
+ const fde *const f = vec->array[i];
void *pc_begin;
uaddr pc_range;
-
- pc_begin = ((void **) f->pc_begin)[0];
- pc_range = ((uaddr *) f->pc_begin)[1];
+ memcpy (&pc_begin, (const void * const *) f->pc_begin, sizeof (void *));
+ memcpy (&pc_range, (const uaddr *) f->pc_begin + 1, sizeof (uaddr));
if (pc < pc_begin)
hi = i;
}
else
{
- /* Long slow labourious linear search, cos we've no memory. */
+ /* Long slow laborious linear search, cos we've no memory. */
if (ob->s.b.from_array)
{
fde **p;
if (f)
{
int encoding;
+ _Unwind_Ptr func;
bases->tbase = ob->tbase;
bases->dbase = ob->dbase;
if (ob->s.b.mixed_encoding)
encoding = get_fde_encoding (f);
read_encoded_value_with_base (encoding, base_from_object (encoding, ob),
- f->pc_begin, (_Unwind_Ptr *)&bases->func);
+ f->pc_begin, &func);
+ bases->func = (void *) func;
}
return f;