]>
Commit | Line | Data |
---|---|---|
a5544970 | 1 | /* Copyright (C) 2001-2019 Free Software Foundation, Inc. |
3cfe49da | 2 | |
54a7b573 | 3 | This file is part of GCC. |
3cfe49da | 4 | |
54a7b573 | 5 | GCC is free software; you can redistribute it and/or modify |
3cfe49da | 6 | it under the terms of the GNU General Public License as published by |
748086b7 | 7 | the Free Software Foundation; either version 3, or (at your option) |
3cfe49da GK |
8 | any later version. |
9 | ||
54a7b573 | 10 | GCC is distributed in the hope that it will be useful, |
3cfe49da GK |
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 | ||
748086b7 JJ |
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. | |
3cfe49da | 18 | |
748086b7 JJ |
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/>. */ | |
3cfe49da GK |
23 | |
24 | /* Locate the FDE entry for a given address, using Darwin's keymgr support. */ | |
25 | ||
26 | #include "tconfig.h" | |
2ba99e3d | 27 | #include "tsystem.h" |
335c9de7 ZW |
28 | #include <string.h> |
29 | #include <stdlib.h> | |
a80b0574 | 30 | #include "dwarf2.h" |
3cfe49da GK |
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 | ||
f1518966 AJ |
42 | static const fde * _Unwind_Find_registered_FDE (void *pc, |
43 | struct dwarf_eh_bases *bases); | |
3cfe49da GK |
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; | |
59d8fe27 | 58 | struct mach_header_64; |
3cfe49da | 59 | extern char *getsectdatafromheader (struct mach_header*, const char*, |
2834a5fe JH |
60 | const char *, unsigned long *); |
61 | extern char *getsectdatafromheader_64 (struct mach_header_64*, const char*, | |
62 | const char *, unsigned long *); | |
3cfe49da GK |
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. */ | |
481a8181 GK |
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. */ | |
3cfe49da GK |
94 | }; |
95 | \f | |
481a8181 GK |
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. */ | |
3cfe49da | 102 | |
f1518966 | 103 | static void |
3cfe49da GK |
104 | live_image_destructor (struct live_images *image) |
105 | { | |
106 | if (image->object_info) | |
107 | { | |
ea00486e GK |
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); | |
3cfe49da GK |
125 | |
126 | free (image->object_info); | |
127 | image->object_info = NULL; | |
128 | if (image->examined_p & ALLOCED_IMAGE_MASK) | |
129 | free (image->fde); | |
481a8181 | 130 | image->fde = NULL; |
3cfe49da | 131 | } |
481a8181 GK |
132 | image->examined_p = 0; |
133 | image->destructor = NULL; | |
3cfe49da GK |
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 | */ | |
f1518966 AJ |
140 | |
141 | static inline const fde * | |
3cfe49da GK |
142 | examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc) |
143 | { | |
f1518966 | 144 | const fde *result = NULL; |
3cfe49da GK |
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 | { | |
90c92323 | 152 | char *fde = NULL; |
3cfe49da | 153 | unsigned long sz; |
f1518966 | 154 | |
90c92323 EC |
155 | /* For ppc only check whether or not we have __DATA eh frames. */ |
156 | #ifdef __ppc__ | |
3cfe49da | 157 | fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz); |
59d8fe27 | 158 | #endif |
90c92323 | 159 | |
3cfe49da GK |
160 | if (fde == NULL) |
161 | { | |
90c92323 | 162 | #if __LP64__ |
59d8fe27 | 163 | fde = getsectdatafromheader_64 ((struct mach_header_64 *) image->mh, |
c0e8f5d3 | 164 | "__TEXT", "__eh_frame", &sz); |
59d8fe27 | 165 | #else |
3cfe49da GK |
166 | fde = getsectdatafromheader (image->mh, "__TEXT", |
167 | "__eh_frame", &sz); | |
59d8fe27 | 168 | #endif |
3cfe49da GK |
169 | if (fde != NULL) |
170 | image->examined_p |= IMAGE_IS_TEXT_MASK; | |
171 | } | |
f1518966 | 172 | |
3cfe49da GK |
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; | |
f1518966 | 179 | |
3cfe49da GK |
180 | if (! dont_alloc) |
181 | ob = calloc (1, sizeof (struct object)); | |
182 | dont_alloc |= ob == NULL; | |
183 | if (dont_alloc) | |
184 | ob = &panicob; | |
f1518966 | 185 | |
3cfe49da GK |
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; | |
f1518966 | 193 | |
ea00486e | 194 | image->fde = real_fde; |
f1518966 | 195 | |
ea00486e | 196 | result = search_object (ob, pc); |
f1518966 | 197 | |
3cfe49da GK |
198 | if (! dont_alloc) |
199 | { | |
ea00486e GK |
200 | struct object **p; |
201 | ||
3cfe49da GK |
202 | image->destructor = live_image_destructor; |
203 | image->object_info = ob; | |
f1518966 AJ |
204 | |
205 | image->examined_p |= (EXAMINED_IMAGE_MASK | |
481a8181 | 206 | | DESTRUCTOR_MAY_BE_CALLED_LIVE); |
ea00486e GK |
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; | |
3cfe49da | 214 | } |
ea00486e | 215 | |
3cfe49da GK |
216 | if (result) |
217 | { | |
218 | int encoding; | |
950ccbc4 | 219 | _Unwind_Ptr func; |
f1518966 | 220 | |
3cfe49da GK |
221 | bases->tbase = ob->tbase; |
222 | bases->dbase = ob->dbase; | |
f1518966 | 223 | |
3cfe49da GK |
224 | encoding = ob->s.b.encoding; |
225 | if (ob->s.b.mixed_encoding) | |
226 | encoding = get_fde_encoding (result); | |
f1518966 | 227 | read_encoded_value_with_base (encoding, |
3cfe49da | 228 | base_from_object (encoding, ob), |
950ccbc4 NS |
229 | result->pc_begin, &func); |
230 | bases->func = (void *) func; | |
3cfe49da GK |
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 | ||
f1518966 | 243 | const fde * |
3cfe49da GK |
244 | _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases) |
245 | { | |
246 | struct km_object_info *the_obj_info; | |
f1518966 | 247 | const fde *ret = NULL; |
3cfe49da | 248 | |
f1518966 | 249 | the_obj_info = |
3cfe49da GK |
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)); | |
f1518966 | 253 | |
3cfe49da GK |
254 | if (the_obj_info != NULL) |
255 | { | |
256 | seen_objects = the_obj_info->seen_objects; | |
257 | unseen_objects = the_obj_info->unseen_objects; | |
f1518966 | 258 | |
3cfe49da GK |
259 | ret = _Unwind_Find_registered_FDE (pc, bases); |
260 | } | |
f1518966 | 261 | |
3cfe49da GK |
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; | |
3cfe49da | 271 | } |
ea00486e GK |
272 | _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST, |
273 | the_obj_info); | |
3cfe49da GK |
274 | return ret; |
275 | } |