xref: /dflybsd-src/contrib/gcc-4.7/libgcc/config/unwind-dw2-fde-darwin.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Copyright (C) 2001, 2002, 2003, 2005, 2009, 2010
2*e4b17023SJohn Marino    Free Software Foundation, Inc.
3*e4b17023SJohn Marino 
4*e4b17023SJohn Marino    This file is part of GCC.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino    GCC is free software; you can redistribute it and/or modify
7*e4b17023SJohn Marino    it under the terms of the GNU General Public License as published by
8*e4b17023SJohn Marino    the Free Software Foundation; either version 3, or (at your option)
9*e4b17023SJohn Marino    any later version.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino    GCC is distributed in the hope that it will be useful,
12*e4b17023SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*e4b17023SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*e4b17023SJohn Marino    GNU General Public License for more details.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino    Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino    permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino    3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino    You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino    a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*e4b17023SJohn Marino    <http://www.gnu.org/licenses/>.  */
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino /* Locate the FDE entry for a given address, using Darwin's keymgr support.  */
26*e4b17023SJohn Marino 
27*e4b17023SJohn Marino #include "tconfig.h"
28*e4b17023SJohn Marino #include "tsystem.h"
29*e4b17023SJohn Marino #include <string.h>
30*e4b17023SJohn Marino #include <stdlib.h>
31*e4b17023SJohn Marino #include "dwarf2.h"
32*e4b17023SJohn Marino #include "unwind.h"
33*e4b17023SJohn Marino #define NO_BASE_OF_ENCODED_VALUE
34*e4b17023SJohn Marino #define DWARF2_OBJECT_END_PTR_EXTENSION
35*e4b17023SJohn Marino #include "unwind-pe.h"
36*e4b17023SJohn Marino #include "unwind-dw2-fde.h"
37*e4b17023SJohn Marino /* Carefully don't include gthr.h.  */
38*e4b17023SJohn Marino 
39*e4b17023SJohn Marino typedef int __gthread_mutex_t;
40*e4b17023SJohn Marino #define __gthread_mutex_lock(x)  (void)(x)
41*e4b17023SJohn Marino #define __gthread_mutex_unlock(x) (void)(x)
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino static const fde * _Unwind_Find_registered_FDE (void *pc,
44*e4b17023SJohn Marino 						struct dwarf_eh_bases *bases);
45*e4b17023SJohn Marino 
46*e4b17023SJohn Marino #define _Unwind_Find_FDE _Unwind_Find_registered_FDE
47*e4b17023SJohn Marino #include "unwind-dw2-fde.c"
48*e4b17023SJohn Marino #undef _Unwind_Find_FDE
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino /* KeyMgr stuff.  */
51*e4b17023SJohn Marino #define KEYMGR_GCC3_LIVE_IMAGE_LIST     301     /* loaded images  */
52*e4b17023SJohn Marino #define KEYMGR_GCC3_DW2_OBJ_LIST        302     /* Dwarf2 object list  */
53*e4b17023SJohn Marino 
54*e4b17023SJohn Marino extern void *_keymgr_get_and_lock_processwide_ptr (int);
55*e4b17023SJohn Marino extern void _keymgr_set_and_unlock_processwide_ptr (int, void *);
56*e4b17023SJohn Marino extern void _keymgr_unlock_processwide_ptr (int);
57*e4b17023SJohn Marino 
58*e4b17023SJohn Marino struct mach_header;
59*e4b17023SJohn Marino struct mach_header_64;
60*e4b17023SJohn Marino extern char *getsectdatafromheader (struct mach_header*, const char*,
61*e4b17023SJohn Marino 				    const char *, unsigned long *);
62*e4b17023SJohn Marino extern char *getsectdatafromheader_64 (struct mach_header_64*, const char*,
63*e4b17023SJohn Marino 				       const char *, unsigned long *);
64*e4b17023SJohn Marino 
65*e4b17023SJohn Marino /* This is referenced from KEYMGR_GCC3_DW2_OBJ_LIST.  */
66*e4b17023SJohn Marino struct km_object_info {
67*e4b17023SJohn Marino   struct object *seen_objects;
68*e4b17023SJohn Marino   struct object *unseen_objects;
69*e4b17023SJohn Marino   unsigned spare[2];
70*e4b17023SJohn Marino };
71*e4b17023SJohn Marino 
72*e4b17023SJohn Marino /* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
73*e4b17023SJohn Marino struct live_images {
74*e4b17023SJohn Marino   unsigned long this_size;                      /* sizeof (live_images)  */
75*e4b17023SJohn Marino   struct mach_header *mh;                       /* the image info  */
76*e4b17023SJohn Marino   unsigned long vm_slide;
77*e4b17023SJohn Marino   void (*destructor)(struct live_images *);     /* destructor for this  */
78*e4b17023SJohn Marino   struct live_images *next;
79*e4b17023SJohn Marino   unsigned int examined_p;
80*e4b17023SJohn Marino   void *fde;
81*e4b17023SJohn Marino   void *object_info;
82*e4b17023SJohn Marino   unsigned long info[2];                        /* Future use.  */
83*e4b17023SJohn Marino };
84*e4b17023SJohn Marino 
85*e4b17023SJohn Marino /* Bits in the examined_p field of struct live_images.  */
86*e4b17023SJohn Marino enum {
87*e4b17023SJohn Marino   EXAMINED_IMAGE_MASK = 1,	/* We've seen this one.  */
88*e4b17023SJohn Marino   ALLOCED_IMAGE_MASK = 2,	/* The FDE entries were allocated by
89*e4b17023SJohn Marino 				   malloc, and must be freed.  This isn't
90*e4b17023SJohn Marino 				   used by newer libgcc versions.  */
91*e4b17023SJohn Marino   IMAGE_IS_TEXT_MASK = 4,	/* This image is in the TEXT segment.  */
92*e4b17023SJohn Marino   DESTRUCTOR_MAY_BE_CALLED_LIVE = 8  /* The destructor may be called on an
93*e4b17023SJohn Marino 					object that's part of the live
94*e4b17023SJohn Marino 					image list.  */
95*e4b17023SJohn Marino };
96*e4b17023SJohn Marino 
97*e4b17023SJohn Marino /* Delete any data we allocated on a live_images structure.  Either
98*e4b17023SJohn Marino    IMAGE has already been removed from the
99*e4b17023SJohn Marino    KEYMGR_GCC3_LIVE_IMAGE_LIST and the struct will be deleted
100*e4b17023SJohn Marino    after we return, or that list is locked and we're being called
101*e4b17023SJohn Marino    because this object might be about to be unloaded.  Called by
102*e4b17023SJohn Marino    KeyMgr.  */
103*e4b17023SJohn Marino 
104*e4b17023SJohn Marino static void
live_image_destructor(struct live_images * image)105*e4b17023SJohn Marino live_image_destructor (struct live_images *image)
106*e4b17023SJohn Marino {
107*e4b17023SJohn Marino   if (image->object_info)
108*e4b17023SJohn Marino     {
109*e4b17023SJohn Marino       struct km_object_info *the_obj_info;
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino       the_obj_info =
112*e4b17023SJohn Marino 	_keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
113*e4b17023SJohn Marino       if (the_obj_info)
114*e4b17023SJohn Marino 	{
115*e4b17023SJohn Marino 	  seen_objects = the_obj_info->seen_objects;
116*e4b17023SJohn Marino 	  unseen_objects = the_obj_info->unseen_objects;
117*e4b17023SJohn Marino 
118*e4b17023SJohn Marino 	  /* Free any sorted arrays.  */
119*e4b17023SJohn Marino 	  __deregister_frame_info_bases (image->fde);
120*e4b17023SJohn Marino 
121*e4b17023SJohn Marino 	  the_obj_info->seen_objects = seen_objects;
122*e4b17023SJohn Marino 	  the_obj_info->unseen_objects = unseen_objects;
123*e4b17023SJohn Marino 	}
124*e4b17023SJohn Marino       _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
125*e4b17023SJohn Marino 					      the_obj_info);
126*e4b17023SJohn Marino 
127*e4b17023SJohn Marino       free (image->object_info);
128*e4b17023SJohn Marino       image->object_info = NULL;
129*e4b17023SJohn Marino       if (image->examined_p & ALLOCED_IMAGE_MASK)
130*e4b17023SJohn Marino 	free (image->fde);
131*e4b17023SJohn Marino       image->fde = NULL;
132*e4b17023SJohn Marino     }
133*e4b17023SJohn Marino   image->examined_p = 0;
134*e4b17023SJohn Marino   image->destructor = NULL;
135*e4b17023SJohn Marino }
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino /* Run through the list of live images.  If we can allocate memory,
138*e4b17023SJohn Marino    give each unseen image a new `struct object'.  Even if we can't,
139*e4b17023SJohn Marino    check whether the PC is inside the FDE of each unseen image.
140*e4b17023SJohn Marino  */
141*e4b17023SJohn Marino 
142*e4b17023SJohn Marino static inline const fde *
examine_objects(void * pc,struct dwarf_eh_bases * bases,int dont_alloc)143*e4b17023SJohn Marino examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
144*e4b17023SJohn Marino {
145*e4b17023SJohn Marino   const fde *result = NULL;
146*e4b17023SJohn Marino   struct live_images *image;
147*e4b17023SJohn Marino 
148*e4b17023SJohn Marino   image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino   for (; image != NULL; image = image->next)
151*e4b17023SJohn Marino     if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
152*e4b17023SJohn Marino       {
153*e4b17023SJohn Marino 	char *fde = NULL;
154*e4b17023SJohn Marino 	unsigned long sz;
155*e4b17023SJohn Marino 
156*e4b17023SJohn Marino 	/* For ppc only check whether or not we have __DATA eh frames.  */
157*e4b17023SJohn Marino #ifdef __ppc__
158*e4b17023SJohn Marino 	fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
159*e4b17023SJohn Marino #endif
160*e4b17023SJohn Marino 
161*e4b17023SJohn Marino 	if (fde == NULL)
162*e4b17023SJohn Marino 	  {
163*e4b17023SJohn Marino #if __LP64__
164*e4b17023SJohn Marino 	    fde = getsectdatafromheader_64 ((struct mach_header_64 *) image->mh,
165*e4b17023SJohn Marino 					    "__TEXT", "__eh_frame", &sz);
166*e4b17023SJohn Marino #else
167*e4b17023SJohn Marino 	    fde = getsectdatafromheader (image->mh, "__TEXT",
168*e4b17023SJohn Marino 					 "__eh_frame", &sz);
169*e4b17023SJohn Marino #endif
170*e4b17023SJohn Marino 	    if (fde != NULL)
171*e4b17023SJohn Marino 	      image->examined_p |= IMAGE_IS_TEXT_MASK;
172*e4b17023SJohn Marino 	  }
173*e4b17023SJohn Marino 
174*e4b17023SJohn Marino 	/* If .eh_frame is empty, don't register at all.  */
175*e4b17023SJohn Marino 	if (fde != NULL && sz > 0)
176*e4b17023SJohn Marino 	  {
177*e4b17023SJohn Marino 	    char *real_fde = (fde + image->vm_slide);
178*e4b17023SJohn Marino 	    struct object *ob = NULL;
179*e4b17023SJohn Marino 	    struct object panicob;
180*e4b17023SJohn Marino 
181*e4b17023SJohn Marino 	    if (! dont_alloc)
182*e4b17023SJohn Marino 	      ob = calloc (1, sizeof (struct object));
183*e4b17023SJohn Marino 	    dont_alloc |= ob == NULL;
184*e4b17023SJohn Marino 	    if (dont_alloc)
185*e4b17023SJohn Marino 	      ob = &panicob;
186*e4b17023SJohn Marino 
187*e4b17023SJohn Marino 	    ob->pc_begin = (void *)-1;
188*e4b17023SJohn Marino 	    ob->tbase = 0;
189*e4b17023SJohn Marino 	    ob->dbase = 0;
190*e4b17023SJohn Marino 	    ob->u.single = (struct dwarf_fde *)real_fde;
191*e4b17023SJohn Marino 	    ob->s.i = 0;
192*e4b17023SJohn Marino 	    ob->s.b.encoding = DW_EH_PE_omit;
193*e4b17023SJohn Marino 	    ob->fde_end = real_fde + sz;
194*e4b17023SJohn Marino 
195*e4b17023SJohn Marino 	    image->fde = real_fde;
196*e4b17023SJohn Marino 
197*e4b17023SJohn Marino 	    result = search_object (ob, pc);
198*e4b17023SJohn Marino 
199*e4b17023SJohn Marino 	    if (! dont_alloc)
200*e4b17023SJohn Marino 	      {
201*e4b17023SJohn Marino 		struct object **p;
202*e4b17023SJohn Marino 
203*e4b17023SJohn Marino 		image->destructor = live_image_destructor;
204*e4b17023SJohn Marino 		image->object_info = ob;
205*e4b17023SJohn Marino 
206*e4b17023SJohn Marino 		image->examined_p |= (EXAMINED_IMAGE_MASK
207*e4b17023SJohn Marino 				      | DESTRUCTOR_MAY_BE_CALLED_LIVE);
208*e4b17023SJohn Marino 
209*e4b17023SJohn Marino 		/* Insert the object into the classified list.  */
210*e4b17023SJohn Marino 		for (p = &seen_objects; *p ; p = &(*p)->next)
211*e4b17023SJohn Marino 		  if ((*p)->pc_begin < ob->pc_begin)
212*e4b17023SJohn Marino 		    break;
213*e4b17023SJohn Marino 		ob->next = *p;
214*e4b17023SJohn Marino 		*p = ob;
215*e4b17023SJohn Marino 	      }
216*e4b17023SJohn Marino 
217*e4b17023SJohn Marino 	    if (result)
218*e4b17023SJohn Marino 	      {
219*e4b17023SJohn Marino 		int encoding;
220*e4b17023SJohn Marino 		_Unwind_Ptr func;
221*e4b17023SJohn Marino 
222*e4b17023SJohn Marino 		bases->tbase = ob->tbase;
223*e4b17023SJohn Marino 		bases->dbase = ob->dbase;
224*e4b17023SJohn Marino 
225*e4b17023SJohn Marino 		encoding = ob->s.b.encoding;
226*e4b17023SJohn Marino 		if (ob->s.b.mixed_encoding)
227*e4b17023SJohn Marino 		  encoding = get_fde_encoding (result);
228*e4b17023SJohn Marino 		read_encoded_value_with_base (encoding,
229*e4b17023SJohn Marino 					      base_from_object (encoding, ob),
230*e4b17023SJohn Marino 					      result->pc_begin, &func);
231*e4b17023SJohn Marino 		bases->func = (void *) func;
232*e4b17023SJohn Marino 		break;
233*e4b17023SJohn Marino 	      }
234*e4b17023SJohn Marino 	  }
235*e4b17023SJohn Marino 	else
236*e4b17023SJohn Marino 	  image->examined_p |= EXAMINED_IMAGE_MASK;
237*e4b17023SJohn Marino       }
238*e4b17023SJohn Marino 
239*e4b17023SJohn Marino   _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
240*e4b17023SJohn Marino 
241*e4b17023SJohn Marino   return result;
242*e4b17023SJohn Marino }
243*e4b17023SJohn Marino 
244*e4b17023SJohn Marino const fde *
_Unwind_Find_FDE(void * pc,struct dwarf_eh_bases * bases)245*e4b17023SJohn Marino _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
246*e4b17023SJohn Marino {
247*e4b17023SJohn Marino   struct km_object_info *the_obj_info;
248*e4b17023SJohn Marino   const fde *ret = NULL;
249*e4b17023SJohn Marino 
250*e4b17023SJohn Marino   the_obj_info =
251*e4b17023SJohn Marino     _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
252*e4b17023SJohn Marino   if (! the_obj_info)
253*e4b17023SJohn Marino     the_obj_info = calloc (1, sizeof (*the_obj_info));
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino   if (the_obj_info != NULL)
256*e4b17023SJohn Marino     {
257*e4b17023SJohn Marino       seen_objects = the_obj_info->seen_objects;
258*e4b17023SJohn Marino       unseen_objects = the_obj_info->unseen_objects;
259*e4b17023SJohn Marino 
260*e4b17023SJohn Marino       ret = _Unwind_Find_registered_FDE (pc, bases);
261*e4b17023SJohn Marino     }
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino   /* OK, didn't find it in the list of FDEs we've seen before,
264*e4b17023SJohn Marino      so go through and look at the new ones.  */
265*e4b17023SJohn Marino   if (ret == NULL)
266*e4b17023SJohn Marino     ret = examine_objects (pc, bases, the_obj_info == NULL);
267*e4b17023SJohn Marino 
268*e4b17023SJohn Marino   if (the_obj_info != NULL)
269*e4b17023SJohn Marino     {
270*e4b17023SJohn Marino       the_obj_info->seen_objects = seen_objects;
271*e4b17023SJohn Marino       the_obj_info->unseen_objects = unseen_objects;
272*e4b17023SJohn Marino     }
273*e4b17023SJohn Marino   _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
274*e4b17023SJohn Marino 					  the_obj_info);
275*e4b17023SJohn Marino   return ret;
276*e4b17023SJohn Marino }
277*e4b17023SJohn Marino 
278*e4b17023SJohn Marino void *
_darwin10_Unwind_FindEnclosingFunction(void * pc ATTRIBUTE_UNUSED)279*e4b17023SJohn Marino _darwin10_Unwind_FindEnclosingFunction (void *pc ATTRIBUTE_UNUSED)
280*e4b17023SJohn Marino {
281*e4b17023SJohn Marino #if __MACH__ && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060)
282*e4b17023SJohn Marino   struct dwarf_eh_bases bases;
283*e4b17023SJohn Marino   const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
284*e4b17023SJohn Marino   if (fde)
285*e4b17023SJohn Marino     return bases.func;
286*e4b17023SJohn Marino #endif
287*e4b17023SJohn Marino   return NULL;
288*e4b17023SJohn Marino }
289*e4b17023SJohn Marino 
290