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