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