Mercurial > hg > CbC > CbC_gcc
annotate gcc/unwind-dw2-fde-darwin.c @ 77:65b2ea5f1266
documents
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 20 Sep 2011 17:16:36 +0900 |
parents | f6334be47118 |
children |
rev | line source |
---|---|
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1 /* Copyright (C) 2001, 2002, 2003, 2005, 2009, 2010 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2 Free Software Foundation, Inc. |
0 | 3 |
4 This file is part of GCC. | |
5 | |
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. | |
10 | |
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. | |
15 | |
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. | |
19 | |
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/>. */ | |
24 | |
25 /* Locate the FDE entry for a given address, using Darwin's keymgr support. */ | |
26 | |
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. */ | |
38 | |
39 typedef int __gthread_mutex_t; | |
40 #define __gthread_mutex_lock(x) (void)(x) | |
41 #define __gthread_mutex_unlock(x) (void)(x) | |
42 | |
43 static const fde * _Unwind_Find_registered_FDE (void *pc, | |
44 struct dwarf_eh_bases *bases); | |
45 | |
46 #define _Unwind_Find_FDE _Unwind_Find_registered_FDE | |
47 #include "unwind-dw2-fde.c" | |
48 #undef _Unwind_Find_FDE | |
49 | |
50 /* KeyMgr stuff. */ | |
51 #define KEYMGR_GCC3_LIVE_IMAGE_LIST 301 /* loaded images */ | |
52 #define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */ | |
53 | |
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); | |
57 | |
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 *); | |
64 | |
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]; | |
70 }; | |
71 | |
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. */ | |
83 }; | |
84 | |
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. */ | |
95 }; | |
96 | |
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. */ | |
103 | |
104 static void | |
105 live_image_destructor (struct live_images *image) | |
106 { | |
107 if (image->object_info) | |
108 { | |
109 struct km_object_info *the_obj_info; | |
110 | |
111 the_obj_info = | |
112 _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST); | |
113 if (the_obj_info) | |
114 { | |
115 seen_objects = the_obj_info->seen_objects; | |
116 unseen_objects = the_obj_info->unseen_objects; | |
117 | |
118 /* Free any sorted arrays. */ | |
119 __deregister_frame_info_bases (image->fde); | |
120 | |
121 the_obj_info->seen_objects = seen_objects; | |
122 the_obj_info->unseen_objects = unseen_objects; | |
123 } | |
124 _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST, | |
125 the_obj_info); | |
126 | |
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; | |
132 } | |
133 image->examined_p = 0; | |
134 image->destructor = NULL; | |
135 } | |
136 | |
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. | |
140 */ | |
141 | |
142 static inline const fde * | |
143 examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc) | |
144 { | |
145 const fde *result = NULL; | |
146 struct live_images *image; | |
147 | |
148 image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST); | |
149 | |
150 for (; image != NULL; image = image->next) | |
151 if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0) | |
152 { | |
153 char *fde = NULL; | |
154 unsigned long sz; | |
155 | |
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 | |
160 | |
161 if (fde == NULL) | |
162 { | |
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; | |
172 } | |
173 | |
174 /* If .eh_frame is empty, don't register at all. */ | |
175 if (fde != NULL && sz > 0) | |
176 { | |
177 char *real_fde = (fde + image->vm_slide); | |
178 struct object *ob = NULL; | |
179 struct object panicob; | |
180 | |
181 if (! dont_alloc) | |
182 ob = calloc (1, sizeof (struct object)); | |
183 dont_alloc |= ob == NULL; | |
184 if (dont_alloc) | |
185 ob = &panicob; | |
186 | |
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; | |
194 | |
195 image->fde = real_fde; | |
196 | |
197 result = search_object (ob, pc); | |
198 | |
199 if (! dont_alloc) | |
200 { | |
201 struct object **p; | |
202 | |
203 image->destructor = live_image_destructor; | |
204 image->object_info = ob; | |
205 | |
206 image->examined_p |= (EXAMINED_IMAGE_MASK | |
207 | DESTRUCTOR_MAY_BE_CALLED_LIVE); | |
208 | |
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; | |
215 } | |
216 | |
217 if (result) | |
218 { | |
219 int encoding; | |
220 _Unwind_Ptr func; | |
221 | |
222 bases->tbase = ob->tbase; | |
223 bases->dbase = ob->dbase; | |
224 | |
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; | |
233 } | |
234 } | |
235 else | |
236 image->examined_p |= EXAMINED_IMAGE_MASK; | |
237 } | |
238 | |
239 _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST); | |
240 | |
241 return result; | |
242 } | |
243 | |
244 const fde * | |
245 _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases) | |
246 { | |
247 struct km_object_info *the_obj_info; | |
248 const fde *ret = NULL; | |
249 | |
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)); | |
254 | |
255 if (the_obj_info != NULL) | |
256 { | |
257 seen_objects = the_obj_info->seen_objects; | |
258 unseen_objects = the_obj_info->unseen_objects; | |
259 | |
260 ret = _Unwind_Find_registered_FDE (pc, bases); | |
261 } | |
262 | |
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); | |
267 | |
268 if (the_obj_info != NULL) | |
269 { | |
270 the_obj_info->seen_objects = seen_objects; | |
271 the_obj_info->unseen_objects = unseen_objects; | |
272 } | |
273 _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST, | |
274 the_obj_info); | |
275 return ret; | |
276 } | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
277 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
278 void * |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
279 _darwin10_Unwind_FindEnclosingFunction (void *pc ATTRIBUTE_UNUSED) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
280 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
281 #if __MACH__ && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
282 struct dwarf_eh_bases bases; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
283 const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
284 if (fde) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
285 return bases.func; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
286 #endif |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
287 return NULL; |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
288 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
289 |