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