Blame sysdeps/generic/unwind-dw2-fde.h

Packit 6c4009
/* Subroutines needed for unwinding stack frames for exception handling.  */
Packit 6c4009
/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
Packit 6c4009
   Contributed by Jason Merrill <jason@cygnus.com>.
Packit 6c4009
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
Packit 6c4009
struct fde_vector
Packit 6c4009
{
Packit 6c4009
  void *orig_data;
Packit 6c4009
  size_t count;
Packit 6c4009
  struct dwarf_fde *array __flexarr;
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
#ifdef _LIBC
Packit 6c4009
#include <gccframe.h>
Packit 6c4009
#else
Packit 6c4009
struct object
Packit 6c4009
{
Packit 6c4009
  void *pc_begin;
Packit 6c4009
  void *tbase;
Packit 6c4009
  void *dbase;
Packit 6c4009
  union {
Packit 6c4009
    struct dwarf_fde *single;
Packit 6c4009
    struct dwarf_fde **array;
Packit 6c4009
    struct fde_vector *sort;
Packit 6c4009
  } u;
Packit 6c4009
Packit 6c4009
  union {
Packit 6c4009
    struct {
Packit 6c4009
      unsigned long sorted : 1;
Packit 6c4009
      unsigned long from_array : 1;
Packit 6c4009
      unsigned long mixed_encoding : 1;
Packit 6c4009
      unsigned long encoding : 8;
Packit 6c4009
      /* ??? Wish there was an easy way to detect a 64-bit host here;
Packit 6c4009
	 we've got 32 bits left to play with...  */
Packit 6c4009
      unsigned long count : 21;
Packit 6c4009
    } b;
Packit 6c4009
    size_t i;
Packit 6c4009
  } s;
Packit 6c4009
Packit 6c4009
#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
Packit 6c4009
  char *fde_end;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  struct object *next;
Packit 6c4009
};
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* This is the original definition of struct object.  While the struct
Packit 6c4009
   itself was opaque to users, they did know how large it was, and
Packit 6c4009
   allocate one statically in crtbegin for each DSO.  Keep this around
Packit 6c4009
   so that we're aware of the static size limitations for the new struct.  */
Packit 6c4009
struct old_object
Packit 6c4009
{
Packit 6c4009
  void *pc_begin;
Packit 6c4009
  void *pc_end;
Packit 6c4009
  struct dwarf_fde *fde_begin;
Packit 6c4009
  struct dwarf_fde **fde_array;
Packit 6c4009
  size_t count;
Packit 6c4009
  struct old_object *next;
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
struct dwarf_eh_bases
Packit 6c4009
{
Packit 6c4009
  void *tbase;
Packit 6c4009
  void *dbase;
Packit 6c4009
  void *func;
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
Packit 6c4009
extern void __register_frame_info_bases (void *, struct object *,
Packit 6c4009
					 void *, void *);
Packit 6c4009
extern void __register_frame_info (void *, struct object *);
Packit 6c4009
extern void __register_frame (void *);
Packit 6c4009
extern void __register_frame_info_table_bases (void *, struct object *,
Packit 6c4009
					       void *, void *);
Packit 6c4009
extern void __register_frame_info_table (void *, struct object *);
Packit 6c4009
extern void __register_frame_table (void *);
Packit 6c4009
extern void *__deregister_frame_info (void *);
Packit 6c4009
extern void *__deregister_frame_info_bases (void *);
Packit 6c4009
extern void __deregister_frame (void *);
Packit 6c4009
Packit 6c4009

Packit 6c4009
typedef          int  sword __attribute__ ((mode (SI)));
Packit 6c4009
typedef unsigned int  uword __attribute__ ((mode (SI)));
Packit 6c4009
typedef unsigned int  uaddr __attribute__ ((mode (pointer)));
Packit 6c4009
typedef          int  saddr __attribute__ ((mode (pointer)));
Packit 6c4009
typedef unsigned char ubyte;
Packit 6c4009
Packit 6c4009
/* Terminology:
Packit 6c4009
   CIE - Common Information Element
Packit 6c4009
   FDE - Frame Descriptor Element
Packit 6c4009
Packit 6c4009
   There is one per function, and it describes where the function code
Packit 6c4009
   is located, and what the register lifetimes and stack layout are
Packit 6c4009
   within the function.
Packit 6c4009
Packit 6c4009
   The data structures are defined in the DWARF specification, although
Packit 6c4009
   not in a very readable way (see LITERATURE).
Packit 6c4009
Packit 6c4009
   Every time an exception is thrown, the code needs to locate the FDE
Packit 6c4009
   for the current function, and starts to look for exception regions
Packit 6c4009
   from that FDE. This works in a two-level search:
Packit 6c4009
   a) in a linear search, find the shared image (i.e. DLL) containing
Packit 6c4009
      the PC
Packit 6c4009
   b) using the FDE table for that shared object, locate the FDE using
Packit 6c4009
      binary search (which requires the sorting).  */
Packit 6c4009
Packit 6c4009
/* The first few fields of a CIE.  The CIE_id field is 0 for a CIE,
Packit 6c4009
   to distinguish it from a valid FDE.  FDEs are aligned to an addressing
Packit 6c4009
   unit boundary, but the fields within are unaligned.  */
Packit 6c4009
struct dwarf_cie
Packit 6c4009
{
Packit 6c4009
  uword length;
Packit 6c4009
  sword CIE_id;
Packit 6c4009
  ubyte version;
Packit 6c4009
  unsigned char augmentation __flexarr;
Packit 6c4009
} __attribute__ ((packed, aligned (__alignof__ (void *))));
Packit 6c4009
Packit 6c4009
/* The first few fields of an FDE.  */
Packit 6c4009
struct dwarf_fde
Packit 6c4009
{
Packit 6c4009
  uword length;
Packit 6c4009
  sword CIE_delta;
Packit 6c4009
  unsigned char pc_begin __flexarr;
Packit 6c4009
} __attribute__ ((packed, aligned (__alignof__ (void *))));
Packit 6c4009
Packit 6c4009
typedef struct dwarf_fde fde;
Packit 6c4009
Packit 6c4009
/* Locate the CIE for a given FDE.  */
Packit 6c4009
Packit 6c4009
static inline struct dwarf_cie *
Packit 6c4009
get_cie (struct dwarf_fde *f)
Packit 6c4009
{
Packit 6c4009
  return (void *)&f->CIE_delta - f->CIE_delta;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static inline fde *
Packit 6c4009
next_fde (fde *f)
Packit 6c4009
{
Packit 6c4009
  return (fde *) ((char *) f + f->length + sizeof (f->length));
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
extern fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
Packit 6c4009
Packit 6c4009
static inline int
Packit 6c4009
last_fde (struct object *obj __attribute__ ((__unused__)), fde *f)
Packit 6c4009
{
Packit 6c4009
#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
Packit 6c4009
  return (char *)f == obj->fde_end || f->length == 0;
Packit 6c4009
#else
Packit 6c4009
  return f->length == 0;
Packit 6c4009
#endif
Packit 6c4009
}