unwind-dw2-fde-darwin.c revision 132718
143045Sdillon/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
243045Sdillon
3132935Simp   This file is part of GCC.
443045Sdillon
543045Sdillon   GCC is free software; you can redistribute it and/or modify
6132935Simp   it under the terms of the GNU General Public License as published by
7132935Simp   the Free Software Foundation; either version 2, or (at your option)
8132935Simp   any later version.
9132935Simp
10132935Simp   GCC is distributed in the hope that it will be useful,
11132935Simp   but WITHOUT ANY WARRANTY; without even the implied warranty of
12132935Simp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13132935Simp   GNU General Public License for more details.
14132935Simp
15132935Simp   You should have received a copy of the GNU General Public License
16132935Simp   along with GCC; see the file COPYING.  If not, write to
17132935Simp   the Free Software Foundation, 59 Temple Place - Suite 330,
18132935Simp   Boston, MA 02111-1307, USA.  */
19132935Simp
20132935Simp/* As a special exception, if you link this library with other files,
21132935Simp   some of which are compiled with GCC, to produce an executable,
22132935Simp   this library does not by itself cause the resulting executable
23132935Simp   to be covered by the GNU General Public License.
24132935Simp   This exception does not however invalidate any other reasons why
2543045Sdillon   the executable file might be covered by the GNU General Public License.  */
2643045Sdillon
2783551Sdillon/* Locate the FDE entry for a given address, using Darwin's keymgr support.  */
2883551Sdillon
2943045Sdillon#include "tconfig.h"
3043045Sdillon#include <string.h>
3143045Sdillon#include <stdlib.h>
3243045Sdillon#include "dwarf2.h"
3343045Sdillon#include "unwind.h"
3472950Srwatson#define NO_BASE_OF_ENCODED_VALUE
3543045Sdillon#define DWARF2_OBJECT_END_PTR_EXTENSION
36166550Sjhb#include "unwind-pe.h"
3777605Stmm#include "unwind-dw2-fde.h"
3877605Stmm/* Carefully don't include gthr.h.  */
3943045Sdillon
4077605Stmmtypedef int __gthread_mutex_t;
4143045Sdillon#define __gthread_mutex_lock(x)  (void)(x)
4243045Sdillon#define __gthread_mutex_unlock(x) (void)(x)
4343045Sdillon
4469793Sobrienstatic const fde * _Unwind_Find_registered_FDE (void *pc,
4543045Sdillon						struct dwarf_eh_bases *bases);
4643045Sdillon
4743045Sdillon#define _Unwind_Find_FDE _Unwind_Find_registered_FDE
4843045Sdillon#include "unwind-dw2-fde.c"
4972950Srwatson#undef _Unwind_Find_FDE
5043045Sdillon
5172950Srwatson/* KeyMgr stuff.  */
5272950Srwatson#define KEYMGR_GCC3_LIVE_IMAGE_LIST     301     /* loaded images  */
53166550Sjhb#define KEYMGR_GCC3_DW2_OBJ_LIST        302     /* Dwarf2 object list  */
54217744Suqs
55217744Suqsextern void *_keymgr_get_and_lock_processwide_ptr (int);
56217744Suqsextern void _keymgr_set_and_unlock_processwide_ptr (int, void *);
57166550Sjhbextern void _keymgr_unlock_processwide_ptr (int);
5843045Sdillon
59166550Sjhbstruct mach_header;
60166550Sjhbextern char *getsectdatafromheader (struct mach_header*, const char*,
61166550Sjhb			const char *, unsigned long *);
6243045Sdillon
6372950Srwatson/* This is referenced from KEYMGR_GCC3_DW2_OBJ_LIST.  */
6443045Sdillonstruct km_object_info {
6543045Sdillon  struct object *seen_objects;
66166550Sjhb  struct object *unseen_objects;
6772950Srwatson  unsigned spare[2];
68166550Sjhb};
69217744Suqs
7043045Sdillon/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
71166550Sjhbstruct live_images {
72166550Sjhb  unsigned long this_size;                      /* sizeof (live_images)  */
73166550Sjhb  struct mach_header *mh;                       /* the image info  */
74166550Sjhb  unsigned long vm_slide;
75166550Sjhb  void (*destructor)(struct live_images *);     /* destructor for this  */
76166550Sjhb  struct live_images *next;
77166550Sjhb  unsigned int examined_p;
78166550Sjhb  void *fde;
79166550Sjhb  void *object_info;
80166550Sjhb  unsigned long info[2];                        /* Future use.  */
8177605Stmm};
8277605Stmm
8377605Stmm/* Bits in the examined_p field of struct live_images.  */
8477605Stmmenum {
8577605Stmm  EXAMINED_IMAGE_MASK = 1,	/* We've seen this one.  */
8677605Stmm  ALLOCED_IMAGE_MASK = 2,	/* The FDE entries were allocated by
8777605Stmm				   malloc, and must be freed.  This isn't
8877605Stmm				   used by newer libgcc versions.  */
8977605Stmm  IMAGE_IS_TEXT_MASK = 4,	/* This image is in the TEXT segment.  */
9072950Srwatson  DESTRUCTOR_MAY_BE_CALLED_LIVE = 8  /* The destructor may be called on an
9172950Srwatson					object that's part of the live
9243045Sdillon					image list.  */
93217744Suqs};
94217744Suqs
9543045Sdillon/* Delete any data we allocated on a live_images structure.  Either
9643045Sdillon   IMAGE has already been removed from the
9743045Sdillon   KEYMGR_GCC3_LIVE_IMAGE_LIST and the struct will be deleted
9843045Sdillon   after we return, or that list is locked and we're being called
9943045Sdillon   because this object might be about to be unloaded.  Called by
10043045Sdillon   KeyMgr.  */
10143045Sdillon
10243045Sdillonstatic void
10343045Sdillonlive_image_destructor (struct live_images *image)
10472950Srwatson{
10572950Srwatson  if (image->object_info)
10672950Srwatson    {
107166550Sjhb      struct km_object_info *the_obj_info;
10872950Srwatson
10972950Srwatson      the_obj_info =
11043045Sdillon	_keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
111166550Sjhb      if (the_obj_info)
112217744Suqs	{
113217744Suqs	  seen_objects = the_obj_info->seen_objects;
114217744Suqs	  unseen_objects = the_obj_info->unseen_objects;
115166550Sjhb
116166550Sjhb	  /* Free any sorted arrays.  */
117166550Sjhb	  __deregister_frame_info_bases (image->fde);
118166550Sjhb
119166550Sjhb	  the_obj_info->seen_objects = seen_objects;
120166550Sjhb	  the_obj_info->unseen_objects = unseen_objects;
121166550Sjhb	}
122166550Sjhb      _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
123166550Sjhb					      the_obj_info);
124166550Sjhb
125166550Sjhb      free (image->object_info);
126166550Sjhb      image->object_info = NULL;
127166550Sjhb      if (image->examined_p & ALLOCED_IMAGE_MASK)
128166550Sjhb	free (image->fde);
129166550Sjhb      image->fde = NULL;
130166550Sjhb    }
131166550Sjhb  image->examined_p = 0;
132166550Sjhb  image->destructor = NULL;
133166550Sjhb}
134166550Sjhb
135166550Sjhb/* Run through the list of live images.  If we can allocate memory,
136166550Sjhb   give each unseen image a new `struct object'.  Even if we can't,
137166550Sjhb   check whether the PC is inside the FDE of each unseen image.
138166550Sjhb */
139166550Sjhb
140166550Sjhbstatic inline const fde *
141166550Sjhbexamine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
142166550Sjhb{
143166550Sjhb  const fde *result = NULL;
144166550Sjhb  struct live_images *image;
145166550Sjhb
146166550Sjhb  image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
147166550Sjhb
148166550Sjhb  for (; image != NULL; image = image->next)
149166550Sjhb    if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
15077605Stmm      {
15177605Stmm	char *fde;
15272950Srwatson	unsigned long sz;
15377605Stmm
15477605Stmm	fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
15577605Stmm	if (fde == NULL)
15672950Srwatson	  {
157217744Suqs	    fde = getsectdatafromheader (image->mh, "__TEXT",
158217744Suqs					 "__eh_frame", &sz);
159217744Suqs	    if (fde != NULL)
16077605Stmm	      image->examined_p |= IMAGE_IS_TEXT_MASK;
16177605Stmm	  }
16277605Stmm
16377605Stmm	/* If .eh_frame is empty, don't register at all.  */
16477605Stmm	if (fde != NULL && sz > 0)
16572950Srwatson	  {
16677605Stmm	    char *real_fde = (fde + image->vm_slide);
16772950Srwatson	    struct object *ob = NULL;
16872950Srwatson	    struct object panicob;
16977605Stmm
17077605Stmm	    if (! dont_alloc)
17177605Stmm	      ob = calloc (1, sizeof (struct object));
17277605Stmm	    dont_alloc |= ob == NULL;
17372950Srwatson	    if (dont_alloc)
17477605Stmm	      ob = &panicob;
17577605Stmm
17677605Stmm	    ob->pc_begin = (void *)-1;
17777605Stmm	    ob->tbase = 0;
17877605Stmm	    ob->dbase = 0;
17977605Stmm	    ob->u.single = (struct dwarf_fde *)real_fde;
18077605Stmm	    ob->s.i = 0;
18177605Stmm	    ob->s.b.encoding = DW_EH_PE_omit;
18277605Stmm	    ob->fde_end = real_fde + sz;
18377605Stmm
18472950Srwatson	    image->fde = real_fde;
18572950Srwatson
18677605Stmm	    result = search_object (ob, pc);
18777605Stmm
18877605Stmm	    if (! dont_alloc)
18972950Srwatson	      {
19077605Stmm		struct object **p;
19177605Stmm
19277605Stmm		image->destructor = live_image_destructor;
19377605Stmm		image->object_info = ob;
19472950Srwatson
19577605Stmm		image->examined_p |= (EXAMINED_IMAGE_MASK
19672950Srwatson				      | DESTRUCTOR_MAY_BE_CALLED_LIVE);
19777605Stmm
19877605Stmm		/* Insert the object into the classified list.  */
19977605Stmm		for (p = &seen_objects; *p ; p = &(*p)->next)
20077605Stmm		  if ((*p)->pc_begin < ob->pc_begin)
20177605Stmm		    break;
20277605Stmm		ob->next = *p;
20377605Stmm		*p = ob;
20477605Stmm	      }
20572950Srwatson
20677605Stmm	    if (result)
20777605Stmm	      {
20872950Srwatson		int encoding;
20972950Srwatson
21077605Stmm		bases->tbase = ob->tbase;
21177605Stmm		bases->dbase = ob->dbase;
21277605Stmm
21377605Stmm		encoding = ob->s.b.encoding;
21477605Stmm		if (ob->s.b.mixed_encoding)
21577605Stmm		  encoding = get_fde_encoding (result);
21672950Srwatson		read_encoded_value_with_base (encoding,
21772950Srwatson					      base_from_object (encoding, ob),
21872950Srwatson					      result->pc_begin,
21972950Srwatson					      (_Unwind_Ptr *)&bases->func);
220166550Sjhb		break;
221166550Sjhb	      }
222166550Sjhb	  }
223166550Sjhb	else
224166550Sjhb	  image->examined_p |= EXAMINED_IMAGE_MASK;
225166550Sjhb      }
226166550Sjhb
227166550Sjhb  _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
228166550Sjhb
229166550Sjhb  return result;
230166550Sjhb}
231166550Sjhb
232166550Sjhbconst fde *
233166550Sjhb_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
234166550Sjhb{
235166550Sjhb  struct km_object_info *the_obj_info;
236166550Sjhb  const fde *ret = NULL;
237166550Sjhb
238166550Sjhb  the_obj_info =
239166550Sjhb    _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
240166550Sjhb  if (! the_obj_info)
241166550Sjhb    the_obj_info = calloc (1, sizeof (*the_obj_info));
242166550Sjhb
243166550Sjhb  if (the_obj_info != NULL)
244166550Sjhb    {
245166550Sjhb      seen_objects = the_obj_info->seen_objects;
246166550Sjhb      unseen_objects = the_obj_info->unseen_objects;
247166550Sjhb
248217744Suqs      ret = _Unwind_Find_registered_FDE (pc, bases);
249217744Suqs    }
25077605Stmm
25172950Srwatson  /* OK, didn't find it in the list of FDEs we've seen before,
25277605Stmm     so go through and look at the new ones.  */
25377605Stmm  if (ret == NULL)
25472950Srwatson    ret = examine_objects (pc, bases, the_obj_info == NULL);
25572950Srwatson
25672950Srwatson  if (the_obj_info != NULL)
25772950Srwatson    {
25872950Srwatson      the_obj_info->seen_objects = seen_objects;
25972950Srwatson      the_obj_info->unseen_objects = unseen_objects;
26072950Srwatson    }
26172950Srwatson  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
262					  the_obj_info);
263  return ret;
264}
265