unwind-dw2-fde.h revision 90075
190075Sobrien/* Subroutines needed for unwinding stack frames for exception handling.  */
290075Sobrien/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
390075Sobrien   Free Software Foundation, Inc.
490075Sobrien   Contributed by Jason Merrill <jason@cygnus.com>.
590075Sobrien
690075SobrienThis file is part of GCC.
790075Sobrien
890075SobrienGCC is free software; you can redistribute it and/or modify it under
990075Sobrienthe terms of the GNU General Public License as published by the Free
1090075SobrienSoftware Foundation; either version 2, or (at your option) any later
1190075Sobrienversion.
1290075Sobrien
1390075SobrienIn addition to the permissions in the GNU General Public License, the
1490075SobrienFree Software Foundation gives you unlimited permission to link the
1590075Sobriencompiled version of this file into combinations with other programs,
1690075Sobrienand to distribute those combinations without any restriction coming
1790075Sobrienfrom the use of this file.  (The General Public License restrictions
1890075Sobriendo apply in other respects; for example, they cover modification of
1990075Sobrienthe file, and distribution when not linked into a combine
2090075Sobrienexecutable.)
2190075Sobrien
2290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
2390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
2490075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
2590075Sobrienfor more details.
2690075Sobrien
2790075SobrienYou should have received a copy of the GNU General Public License
2890075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
2990075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
3090075Sobrien02111-1307, USA.  */
3190075Sobrien
3290075Sobrien
3390075Sobrienstruct fde_vector
3490075Sobrien{
3590075Sobrien  void *orig_data;
3690075Sobrien  size_t count;
3790075Sobrien  struct dwarf_fde *array[];
3890075Sobrien};
3990075Sobrien
4090075Sobrienstruct object
4190075Sobrien{
4290075Sobrien  void *pc_begin;
4390075Sobrien  void *tbase;
4490075Sobrien  void *dbase;
4590075Sobrien  union {
4690075Sobrien    struct dwarf_fde *single;
4790075Sobrien    struct dwarf_fde **array;
4890075Sobrien    struct fde_vector *sort;
4990075Sobrien  } u;
5090075Sobrien
5190075Sobrien  union {
5290075Sobrien    struct {
5390075Sobrien      unsigned long sorted : 1;
5490075Sobrien      unsigned long from_array : 1;
5590075Sobrien      unsigned long mixed_encoding : 1;
5690075Sobrien      unsigned long encoding : 8;
5790075Sobrien      /* ??? Wish there was an easy way to detect a 64-bit host here;
5890075Sobrien	 we've got 32 bits left to play with...  */
5990075Sobrien      unsigned long count : 21;
6090075Sobrien    } b;
6190075Sobrien    size_t i;
6290075Sobrien  } s;
6390075Sobrien
6490075Sobrien  struct object *next;
6590075Sobrien};
6690075Sobrien
6790075Sobrien/* This is the original definition of struct object.  While the struct
6890075Sobrien   itself was opaque to users, they did know how large it was, and
6990075Sobrien   allocate one statically in crtbegin for each DSO.  Keep this around
7090075Sobrien   so that we're aware of the static size limitations for the new struct.  */
7190075Sobrienstruct old_object
7290075Sobrien{
7390075Sobrien  void *pc_begin;
7490075Sobrien  void *pc_end;
7590075Sobrien  struct dwarf_fde *fde_begin;
7690075Sobrien  struct dwarf_fde **fde_array;
7790075Sobrien  size_t count;
7890075Sobrien  struct old_object *next;
7990075Sobrien};
8090075Sobrien
8190075Sobrienstruct dwarf_eh_bases
8290075Sobrien{
8390075Sobrien  void *tbase;
8490075Sobrien  void *dbase;
8590075Sobrien  void *func;
8690075Sobrien};
8790075Sobrien
8890075Sobrien
8990075Sobrienextern void __register_frame_info_bases (void *, struct object *,
9090075Sobrien					 void *, void *);
9190075Sobrienextern void __register_frame_info (void *, struct object *);
9290075Sobrienextern void __register_frame (void *);
9390075Sobrienextern void __register_frame_info_table_bases (void *, struct object *,
9490075Sobrien					       void *, void *);
9590075Sobrienextern void __register_frame_info_table (void *, struct object *);
9690075Sobrienextern void __register_frame_table (void *);
9790075Sobrienextern void *__deregister_frame_info (void *);
9890075Sobrienextern void *__deregister_frame_info_bases (void *);
9990075Sobrienextern void __deregister_frame (void *);
10090075Sobrien
10190075Sobrien
10290075Sobrientypedef          int  sword __attribute__ ((mode (SI)));
10390075Sobrientypedef unsigned int  uword __attribute__ ((mode (SI)));
10490075Sobrientypedef unsigned int  uaddr __attribute__ ((mode (pointer)));
10590075Sobrientypedef          int  saddr __attribute__ ((mode (pointer)));
10690075Sobrientypedef unsigned char ubyte;
10790075Sobrien
10890075Sobrien/* Terminology:
10990075Sobrien   CIE - Common Information Element
11090075Sobrien   FDE - Frame Descriptor Element
11190075Sobrien
11290075Sobrien   There is one per function, and it describes where the function code
11390075Sobrien   is located, and what the register lifetimes and stack layout are
11490075Sobrien   within the function.
11590075Sobrien
11690075Sobrien   The data structures are defined in the DWARF specification, although
11790075Sobrien   not in a very readable way (see LITERATURE).
11890075Sobrien
11990075Sobrien   Every time an exception is thrown, the code needs to locate the FDE
12090075Sobrien   for the current function, and starts to look for exception regions
12190075Sobrien   from that FDE. This works in a two-level search:
12290075Sobrien   a) in a linear search, find the shared image (i.e. DLL) containing
12390075Sobrien      the PC
12490075Sobrien   b) using the FDE table for that shared object, locate the FDE using
12590075Sobrien      binary search (which requires the sorting).  */
12690075Sobrien
12790075Sobrien/* The first few fields of a CIE.  The CIE_id field is 0 for a CIE,
12890075Sobrien   to distinguish it from a valid FDE.  FDEs are aligned to an addressing
12990075Sobrien   unit boundary, but the fields within are unaligned.  */
13090075Sobrienstruct dwarf_cie
13190075Sobrien{
13290075Sobrien  uword length;
13390075Sobrien  sword CIE_id;
13490075Sobrien  ubyte version;
13590075Sobrien  unsigned char augmentation[];
13690075Sobrien} __attribute__ ((packed, aligned (__alignof__ (void *))));
13790075Sobrien
13890075Sobrien/* The first few fields of an FDE.  */
13990075Sobrienstruct dwarf_fde
14090075Sobrien{
14190075Sobrien  uword length;
14290075Sobrien  sword CIE_delta;
14390075Sobrien  unsigned char pc_begin[];
14490075Sobrien} __attribute__ ((packed, aligned (__alignof__ (void *))));
14590075Sobrien
14690075Sobrientypedef struct dwarf_fde fde;
14790075Sobrien
14890075Sobrien/* Locate the CIE for a given FDE.  */
14990075Sobrien
15090075Sobrienstatic inline struct dwarf_cie *
15190075Sobrienget_cie (struct dwarf_fde *f)
15290075Sobrien{
15390075Sobrien  return (void *)&f->CIE_delta - f->CIE_delta;
15490075Sobrien}
15590075Sobrien
15690075Sobrienstatic inline fde *
15790075Sobriennext_fde (fde *f)
15890075Sobrien{
15990075Sobrien  return (fde *) ((char *) f + f->length + sizeof (f->length));
16090075Sobrien}
16190075Sobrien
16290075Sobrienextern fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
163