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