unwind-dw2-fde.h revision 132718
190075Sobrien/* Subroutines needed for unwinding stack frames for exception handling.  */
2132718Skan/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004
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
32132718Skan#ifndef GCC_UNWIND_DW2_FDE_H
33132718Skan#define GCC_UNWIND_DW2_FDE_H
3490075Sobrien
3590075Sobrienstruct fde_vector
3690075Sobrien{
37132718Skan  const void *orig_data;
3890075Sobrien  size_t count;
39132718Skan  const struct dwarf_fde *array[];
4090075Sobrien};
4190075Sobrien
4290075Sobrienstruct object
4390075Sobrien{
4490075Sobrien  void *pc_begin;
4590075Sobrien  void *tbase;
4690075Sobrien  void *dbase;
4790075Sobrien  union {
48132718Skan    const struct dwarf_fde *single;
4990075Sobrien    struct dwarf_fde **array;
5090075Sobrien    struct fde_vector *sort;
5190075Sobrien  } u;
5290075Sobrien
5390075Sobrien  union {
5490075Sobrien    struct {
5590075Sobrien      unsigned long sorted : 1;
5690075Sobrien      unsigned long from_array : 1;
5790075Sobrien      unsigned long mixed_encoding : 1;
5890075Sobrien      unsigned long encoding : 8;
5990075Sobrien      /* ??? Wish there was an easy way to detect a 64-bit host here;
6090075Sobrien	 we've got 32 bits left to play with...  */
6190075Sobrien      unsigned long count : 21;
6290075Sobrien    } b;
6390075Sobrien    size_t i;
6490075Sobrien  } s;
6590075Sobrien
66117395Skan#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
67117395Skan  char *fde_end;
68117395Skan#endif
69117395Skan
7090075Sobrien  struct object *next;
7190075Sobrien};
7290075Sobrien
7390075Sobrien/* This is the original definition of struct object.  While the struct
7490075Sobrien   itself was opaque to users, they did know how large it was, and
7590075Sobrien   allocate one statically in crtbegin for each DSO.  Keep this around
7690075Sobrien   so that we're aware of the static size limitations for the new struct.  */
7790075Sobrienstruct old_object
7890075Sobrien{
7990075Sobrien  void *pc_begin;
8090075Sobrien  void *pc_end;
8190075Sobrien  struct dwarf_fde *fde_begin;
8290075Sobrien  struct dwarf_fde **fde_array;
8390075Sobrien  size_t count;
8490075Sobrien  struct old_object *next;
8590075Sobrien};
8690075Sobrien
8790075Sobrienstruct dwarf_eh_bases
8890075Sobrien{
8990075Sobrien  void *tbase;
9090075Sobrien  void *dbase;
9190075Sobrien  void *func;
9290075Sobrien};
9390075Sobrien
9490075Sobrien
95132718Skanextern void __register_frame_info_bases (const void *, struct object *,
9690075Sobrien					 void *, void *);
97132718Skanextern void __register_frame_info (const void *, struct object *);
9890075Sobrienextern void __register_frame (void *);
9990075Sobrienextern void __register_frame_info_table_bases (void *, struct object *,
10090075Sobrien					       void *, void *);
10190075Sobrienextern void __register_frame_info_table (void *, struct object *);
10290075Sobrienextern void __register_frame_table (void *);
103132718Skanextern void *__deregister_frame_info (const void *);
104132718Skanextern void *__deregister_frame_info_bases (const void *);
10590075Sobrienextern void __deregister_frame (void *);
10690075Sobrien
10790075Sobrien
10890075Sobrientypedef          int  sword __attribute__ ((mode (SI)));
10990075Sobrientypedef unsigned int  uword __attribute__ ((mode (SI)));
11090075Sobrientypedef unsigned int  uaddr __attribute__ ((mode (pointer)));
11190075Sobrientypedef          int  saddr __attribute__ ((mode (pointer)));
11290075Sobrientypedef unsigned char ubyte;
11390075Sobrien
11490075Sobrien/* Terminology:
11590075Sobrien   CIE - Common Information Element
11690075Sobrien   FDE - Frame Descriptor Element
11790075Sobrien
11890075Sobrien   There is one per function, and it describes where the function code
11990075Sobrien   is located, and what the register lifetimes and stack layout are
12090075Sobrien   within the function.
12190075Sobrien
12290075Sobrien   The data structures are defined in the DWARF specification, although
12390075Sobrien   not in a very readable way (see LITERATURE).
12490075Sobrien
12590075Sobrien   Every time an exception is thrown, the code needs to locate the FDE
12690075Sobrien   for the current function, and starts to look for exception regions
12790075Sobrien   from that FDE. This works in a two-level search:
12890075Sobrien   a) in a linear search, find the shared image (i.e. DLL) containing
12990075Sobrien      the PC
13090075Sobrien   b) using the FDE table for that shared object, locate the FDE using
131117395Skan      binary search (which requires the sorting).  */
13290075Sobrien
13390075Sobrien/* The first few fields of a CIE.  The CIE_id field is 0 for a CIE,
13490075Sobrien   to distinguish it from a valid FDE.  FDEs are aligned to an addressing
13590075Sobrien   unit boundary, but the fields within are unaligned.  */
13690075Sobrienstruct dwarf_cie
13790075Sobrien{
13890075Sobrien  uword length;
13990075Sobrien  sword CIE_id;
14090075Sobrien  ubyte version;
14190075Sobrien  unsigned char augmentation[];
14290075Sobrien} __attribute__ ((packed, aligned (__alignof__ (void *))));
14390075Sobrien
14490075Sobrien/* The first few fields of an FDE.  */
14590075Sobrienstruct dwarf_fde
14690075Sobrien{
14790075Sobrien  uword length;
14890075Sobrien  sword CIE_delta;
14990075Sobrien  unsigned char pc_begin[];
15090075Sobrien} __attribute__ ((packed, aligned (__alignof__ (void *))));
15190075Sobrien
15290075Sobrientypedef struct dwarf_fde fde;
15390075Sobrien
15490075Sobrien/* Locate the CIE for a given FDE.  */
15590075Sobrien
156132718Skanstatic inline const struct dwarf_cie *
157132718Skanget_cie (const struct dwarf_fde *f)
15890075Sobrien{
15990075Sobrien  return (void *)&f->CIE_delta - f->CIE_delta;
16090075Sobrien}
16190075Sobrien
162132718Skanstatic inline const fde *
163132718Skannext_fde (const fde *f)
16490075Sobrien{
165132718Skan  return (const fde *) ((char *) f + f->length + sizeof (f->length));
16690075Sobrien}
16790075Sobrien
168132718Skanextern const fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
169117395Skan
170117395Skanstatic inline int
171132718Skanlast_fde (struct object *obj __attribute__ ((__unused__)), const fde *f)
172117395Skan{
173117395Skan#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
174117395Skan  return (char *)f == obj->fde_end || f->length == 0;
175117395Skan#else
176117395Skan  return f->length == 0;
177117395Skan#endif
178117395Skan}
179132718Skan
180132718Skan#endif /* unwind-dw2-fde.h */
181