1169689Skan/* Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
2117395Skan
3132718Skan   This file is part of GCC.
4117395Skan
5132718Skan   GCC is free software; you can redistribute it and/or modify
6117395Skan   it under the terms of the GNU General Public License as published by
7117395Skan   the Free Software Foundation; either version 2, or (at your option)
8117395Skan   any later version.
9117395Skan
10132718Skan   GCC is distributed in the hope that it will be useful,
11117395Skan   but WITHOUT ANY WARRANTY; without even the implied warranty of
12117395Skan   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13117395Skan   GNU General Public License for more details.
14117395Skan
15117395Skan   You should have received a copy of the GNU General Public License
16132718Skan   along with GCC; see the file COPYING.  If not, write to
17169689Skan   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
18169689Skan   Boston, MA 02110-1301, USA.  */
19117395Skan
20117395Skan/* As a special exception, if you link this library with other files,
21117395Skan   some of which are compiled with GCC, to produce an executable,
22117395Skan   this library does not by itself cause the resulting executable
23117395Skan   to be covered by the GNU General Public License.
24117395Skan   This exception does not however invalidate any other reasons why
25117395Skan   the executable file might be covered by the GNU General Public License.  */
26117395Skan
27117395Skan/* Locate the FDE entry for a given address, using Darwin's keymgr support.  */
28117395Skan
29117395Skan#include "tconfig.h"
30169689Skan#include "tsystem.h"
31117395Skan#include <string.h>
32117395Skan#include <stdlib.h>
33117395Skan#include "dwarf2.h"
34117395Skan#include "unwind.h"
35117395Skan#define NO_BASE_OF_ENCODED_VALUE
36117395Skan#define DWARF2_OBJECT_END_PTR_EXTENSION
37117395Skan#include "unwind-pe.h"
38117395Skan#include "unwind-dw2-fde.h"
39117395Skan/* Carefully don't include gthr.h.  */
40117395Skan
41117395Skantypedef int __gthread_mutex_t;
42117395Skan#define __gthread_mutex_lock(x)  (void)(x)
43117395Skan#define __gthread_mutex_unlock(x) (void)(x)
44117395Skan
45132718Skanstatic const fde * _Unwind_Find_registered_FDE (void *pc,
46132718Skan						struct dwarf_eh_bases *bases);
47117395Skan
48117395Skan#define _Unwind_Find_FDE _Unwind_Find_registered_FDE
49117395Skan#include "unwind-dw2-fde.c"
50117395Skan#undef _Unwind_Find_FDE
51117395Skan
52117395Skan/* KeyMgr stuff.  */
53117395Skan#define KEYMGR_GCC3_LIVE_IMAGE_LIST     301     /* loaded images  */
54117395Skan#define KEYMGR_GCC3_DW2_OBJ_LIST        302     /* Dwarf2 object list  */
55117395Skan
56117395Skanextern void *_keymgr_get_and_lock_processwide_ptr (int);
57117395Skanextern void _keymgr_set_and_unlock_processwide_ptr (int, void *);
58117395Skanextern void _keymgr_unlock_processwide_ptr (int);
59117395Skan
60117395Skanstruct mach_header;
61169689Skanstruct mach_header_64;
62117395Skanextern char *getsectdatafromheader (struct mach_header*, const char*,
63169689Skan				    const char *, unsigned long *);
64169689Skanextern char *getsectdatafromheader_64 (struct mach_header_64*, const char*,
65169689Skan				       const char *, unsigned long *);
66117395Skan
67117395Skan/* This is referenced from KEYMGR_GCC3_DW2_OBJ_LIST.  */
68117395Skanstruct km_object_info {
69117395Skan  struct object *seen_objects;
70117395Skan  struct object *unseen_objects;
71117395Skan  unsigned spare[2];
72117395Skan};
73117395Skan
74117395Skan/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
75117395Skanstruct live_images {
76117395Skan  unsigned long this_size;                      /* sizeof (live_images)  */
77117395Skan  struct mach_header *mh;                       /* the image info  */
78117395Skan  unsigned long vm_slide;
79117395Skan  void (*destructor)(struct live_images *);     /* destructor for this  */
80117395Skan  struct live_images *next;
81117395Skan  unsigned int examined_p;
82117395Skan  void *fde;
83117395Skan  void *object_info;
84117395Skan  unsigned long info[2];                        /* Future use.  */
85117395Skan};
86117395Skan
87117395Skan/* Bits in the examined_p field of struct live_images.  */
88117395Skanenum {
89117395Skan  EXAMINED_IMAGE_MASK = 1,	/* We've seen this one.  */
90117395Skan  ALLOCED_IMAGE_MASK = 2,	/* The FDE entries were allocated by
91117395Skan				   malloc, and must be freed.  This isn't
92117395Skan				   used by newer libgcc versions.  */
93117395Skan  IMAGE_IS_TEXT_MASK = 4,	/* This image is in the TEXT segment.  */
94117395Skan  DESTRUCTOR_MAY_BE_CALLED_LIVE = 8  /* The destructor may be called on an
95117395Skan					object that's part of the live
96117395Skan					image list.  */
97117395Skan};
98117395Skan
99117395Skan/* Delete any data we allocated on a live_images structure.  Either
100117395Skan   IMAGE has already been removed from the
101117395Skan   KEYMGR_GCC3_LIVE_IMAGE_LIST and the struct will be deleted
102117395Skan   after we return, or that list is locked and we're being called
103117395Skan   because this object might be about to be unloaded.  Called by
104117395Skan   KeyMgr.  */
105117395Skan
106132718Skanstatic void
107117395Skanlive_image_destructor (struct live_images *image)
108117395Skan{
109117395Skan  if (image->object_info)
110117395Skan    {
111132718Skan      struct km_object_info *the_obj_info;
112117395Skan
113132718Skan      the_obj_info =
114132718Skan	_keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
115132718Skan      if (the_obj_info)
116132718Skan	{
117132718Skan	  seen_objects = the_obj_info->seen_objects;
118132718Skan	  unseen_objects = the_obj_info->unseen_objects;
119132718Skan
120132718Skan	  /* Free any sorted arrays.  */
121132718Skan	  __deregister_frame_info_bases (image->fde);
122132718Skan
123132718Skan	  the_obj_info->seen_objects = seen_objects;
124132718Skan	  the_obj_info->unseen_objects = unseen_objects;
125132718Skan	}
126132718Skan      _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
127132718Skan					      the_obj_info);
128132718Skan
129117395Skan      free (image->object_info);
130117395Skan      image->object_info = NULL;
131117395Skan      if (image->examined_p & ALLOCED_IMAGE_MASK)
132117395Skan	free (image->fde);
133117395Skan      image->fde = NULL;
134117395Skan    }
135117395Skan  image->examined_p = 0;
136117395Skan  image->destructor = NULL;
137117395Skan}
138117395Skan
139117395Skan/* Run through the list of live images.  If we can allocate memory,
140117395Skan   give each unseen image a new `struct object'.  Even if we can't,
141117395Skan   check whether the PC is inside the FDE of each unseen image.
142117395Skan */
143132718Skan
144132718Skanstatic inline const fde *
145117395Skanexamine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
146117395Skan{
147132718Skan  const fde *result = NULL;
148117395Skan  struct live_images *image;
149117395Skan
150117395Skan  image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
151117395Skan
152117395Skan  for (; image != NULL; image = image->next)
153117395Skan    if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
154117395Skan      {
155169689Skan	char *fde = NULL;
156117395Skan	unsigned long sz;
157132718Skan
158169689Skan	/* For ppc only check whether or not we have __DATA eh frames.  */
159169689Skan#ifdef __ppc__
160117395Skan	fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
161169689Skan#endif
162169689Skan
163117395Skan	if (fde == NULL)
164117395Skan	  {
165169689Skan#if __LP64__
166169689Skan	    fde = getsectdatafromheader_64 ((struct mach_header_64 *) image->mh,
167169689Skan					    "__TEXT", "__eh_frame", &sz);
168169689Skan#else
169117395Skan	    fde = getsectdatafromheader (image->mh, "__TEXT",
170117395Skan					 "__eh_frame", &sz);
171169689Skan#endif
172117395Skan	    if (fde != NULL)
173117395Skan	      image->examined_p |= IMAGE_IS_TEXT_MASK;
174117395Skan	  }
175132718Skan
176117395Skan	/* If .eh_frame is empty, don't register at all.  */
177117395Skan	if (fde != NULL && sz > 0)
178117395Skan	  {
179117395Skan	    char *real_fde = (fde + image->vm_slide);
180117395Skan	    struct object *ob = NULL;
181117395Skan	    struct object panicob;
182132718Skan
183117395Skan	    if (! dont_alloc)
184117395Skan	      ob = calloc (1, sizeof (struct object));
185117395Skan	    dont_alloc |= ob == NULL;
186117395Skan	    if (dont_alloc)
187117395Skan	      ob = &panicob;
188132718Skan
189117395Skan	    ob->pc_begin = (void *)-1;
190117395Skan	    ob->tbase = 0;
191117395Skan	    ob->dbase = 0;
192117395Skan	    ob->u.single = (struct dwarf_fde *)real_fde;
193117395Skan	    ob->s.i = 0;
194117395Skan	    ob->s.b.encoding = DW_EH_PE_omit;
195117395Skan	    ob->fde_end = real_fde + sz;
196132718Skan
197132718Skan	    image->fde = real_fde;
198132718Skan
199132718Skan	    result = search_object (ob, pc);
200132718Skan
201117395Skan	    if (! dont_alloc)
202117395Skan	      {
203132718Skan		struct object **p;
204132718Skan
205117395Skan		image->destructor = live_image_destructor;
206117395Skan		image->object_info = ob;
207132718Skan
208132718Skan		image->examined_p |= (EXAMINED_IMAGE_MASK
209117395Skan				      | DESTRUCTOR_MAY_BE_CALLED_LIVE);
210132718Skan
211132718Skan		/* Insert the object into the classified list.  */
212132718Skan		for (p = &seen_objects; *p ; p = &(*p)->next)
213132718Skan		  if ((*p)->pc_begin < ob->pc_begin)
214132718Skan		    break;
215132718Skan		ob->next = *p;
216132718Skan		*p = ob;
217117395Skan	      }
218132718Skan
219117395Skan	    if (result)
220117395Skan	      {
221117395Skan		int encoding;
222169689Skan		_Unwind_Ptr func;
223132718Skan
224117395Skan		bases->tbase = ob->tbase;
225117395Skan		bases->dbase = ob->dbase;
226132718Skan
227117395Skan		encoding = ob->s.b.encoding;
228117395Skan		if (ob->s.b.mixed_encoding)
229117395Skan		  encoding = get_fde_encoding (result);
230132718Skan		read_encoded_value_with_base (encoding,
231117395Skan					      base_from_object (encoding, ob),
232169689Skan					      result->pc_begin, &func);
233169689Skan		bases->func = (void *) func;
234117395Skan		break;
235117395Skan	      }
236117395Skan	  }
237117395Skan	else
238117395Skan	  image->examined_p |= EXAMINED_IMAGE_MASK;
239117395Skan      }
240117395Skan
241117395Skan  _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
242117395Skan
243117395Skan  return result;
244117395Skan}
245117395Skan
246132718Skanconst fde *
247117395Skan_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
248117395Skan{
249117395Skan  struct km_object_info *the_obj_info;
250132718Skan  const fde *ret = NULL;
251117395Skan
252132718Skan  the_obj_info =
253117395Skan    _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
254117395Skan  if (! the_obj_info)
255117395Skan    the_obj_info = calloc (1, sizeof (*the_obj_info));
256132718Skan
257117395Skan  if (the_obj_info != NULL)
258117395Skan    {
259117395Skan      seen_objects = the_obj_info->seen_objects;
260117395Skan      unseen_objects = the_obj_info->unseen_objects;
261132718Skan
262117395Skan      ret = _Unwind_Find_registered_FDE (pc, bases);
263117395Skan    }
264132718Skan
265117395Skan  /* OK, didn't find it in the list of FDEs we've seen before,
266117395Skan     so go through and look at the new ones.  */
267117395Skan  if (ret == NULL)
268117395Skan    ret = examine_objects (pc, bases, the_obj_info == NULL);
269117395Skan
270117395Skan  if (the_obj_info != NULL)
271117395Skan    {
272117395Skan      the_obj_info->seen_objects = seen_objects;
273117395Skan      the_obj_info->unseen_objects = unseen_objects;
274117395Skan    }
275132718Skan  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
276132718Skan					  the_obj_info);
277117395Skan  return ret;
278117395Skan}
279