Mercurial > hg > CbC > CbC_gcc
comparison gcc/unwind-dw2-fde-darwin.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
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 } |