comparison gcc/config/darwin-crt3.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
comparison
equal deleted inserted replaced
-1:000000000000 0:a06113de4d67
1 /* __cxa_atexit backwards-compatibility support for Darwin.
2 Copyright (C) 2006, 2009 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 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 /* Don't do anything if we are compiling for a kext multilib. */
26 #ifdef __PIC__
27
28 /* It is incorrect to include config.h here, because this file is being
29 compiled for the target, and hence definitions concerning only the host
30 do not apply. */
31
32 #include "tconfig.h"
33 #include "tsystem.h"
34
35 #include <dlfcn.h>
36 #include <stdbool.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 /* This file works around two different problems.
41
42 The first problem is that there is no __cxa_atexit on Mac OS versions
43 before 10.4. It fixes this by providing a complete atexit and
44 __cxa_atexit emulation called from the regular atexit.
45
46 The second problem is that on all shipping versions of Mac OS,
47 __cxa_finalize and exit() don't work right: they don't run routines
48 that were registered while other atexit routines are running. This
49 is worked around by wrapping each atexit/__cxa_atexit routine with
50 our own routine which ensures that any __cxa_atexit calls while it
51 is running are honoured.
52
53 There are still problems which this does not solve. Before 10.4,
54 shared objects linked with previous compilers won't have their
55 atexit calls properly interleaved with code compiled with newer
56 compilers. Also, atexit routines registered from shared objects
57 linked with previous compilers won't get the bug fix. */
58
59 typedef int (*cxa_atexit_p)(void (*func) (void*), void* arg, const void* dso);
60 typedef void (*cxa_finalize_p)(const void *dso);
61 typedef int (*atexit_p)(void (*func)(void));
62
63 /* These are from "keymgr.h". */
64 extern void *_keymgr_get_and_lock_processwide_ptr (unsigned key);
65 extern int _keymgr_get_and_lock_processwide_ptr_2 (unsigned, void **);
66 extern int _keymgr_set_and_unlock_processwide_ptr (unsigned key, void *ptr);
67
68 extern void *__keymgr_global[];
69 typedef struct _Sinfo_Node {
70 unsigned int size ; /*size of this node*/
71 unsigned short major_version ; /*API major version.*/
72 unsigned short minor_version ; /*API minor version.*/
73 } _Tinfo_Node ;
74
75 #ifdef __ppc__
76 #define CHECK_KEYMGR_ERROR(e) \
77 (((_Tinfo_Node *)__keymgr_global[2])->major_version >= 4 ? (e) : 0)
78 #else
79 #define CHECK_KEYMGR_ERROR(e) (e)
80 #endif
81
82 /* Our globals are stored under this keymgr index. */
83 #define KEYMGR_ATEXIT_LIST 14
84
85 /* The different kinds of callback routines. */
86 typedef void (*atexit_callback)(void);
87 typedef void (*cxa_atexit_callback)(void *);
88
89 /* This structure holds a routine to call. There may be extra fields
90 at the end of the structure that this code doesn't know about. */
91 struct one_atexit_routine
92 {
93 union {
94 atexit_callback ac;
95 cxa_atexit_callback cac;
96 } callback;
97 /* has_arg is 0/2/4 if 'ac' is live, 1/3/5 if 'cac' is live.
98 Higher numbers indicate a later version of the structure that this
99 code doesn't understand and will ignore. */
100 int has_arg;
101 void * arg;
102 };
103
104 struct atexit_routine_list
105 {
106 struct atexit_routine_list * next;
107 struct one_atexit_routine r;
108 };
109
110 /* The various possibilities for status of atexit(). */
111 enum atexit_status {
112 atexit_status_unknown = 0,
113 atexit_status_missing = 1,
114 atexit_status_broken = 2,
115 atexit_status_working = 16
116 };
117
118 struct keymgr_atexit_list
119 {
120 /* Version of this list. This code knows only about version 0.
121 If the version is higher than 0, this code may add new atexit routines
122 but should not attempt to run the list. */
123 short version;
124 /* 1 if an atexit routine is currently being run by this code, 0
125 otherwise. */
126 char running_routines;
127 /* Holds a value from 'enum atexit_status'. */
128 unsigned char atexit_status;
129 /* The list of atexit and cxa_atexit routines registered. If
130 atexit_status_missing it contains all routines registered while
131 linked with this code. If atexit_status_broken it contains all
132 routines registered during cxa_finalize while linked with this
133 code. */
134 struct atexit_routine_list *l;
135 /* &__cxa_atexit; set if atexit_status >= atexit_status_broken. */
136 cxa_atexit_p cxa_atexit_f;
137 /* &__cxa_finalize; set if atexit_status >= atexit_status_broken. */
138 cxa_finalize_p cxa_finalize_f;
139 /* &atexit; set if atexit_status >= atexit_status_working
140 or atexit_status == atexit_status_missing. */
141 atexit_p atexit_f;
142 };
143
144 /* Return 0 if __cxa_atexit has the bug it has in Mac OS 10.4: it
145 fails to call routines registered while an atexit routine is
146 running. Return 1 if it works properly, and -1 if an error occurred. */
147
148 struct atexit_data
149 {
150 int result;
151 cxa_atexit_p cxa_atexit;
152 };
153
154 static void cxa_atexit_check_2 (void *arg)
155 {
156 ((struct atexit_data *)arg)->result = 1;
157 }
158
159 static void cxa_atexit_check_1 (void *arg)
160 {
161 struct atexit_data * aed = arg;
162 if (aed->cxa_atexit (cxa_atexit_check_2, arg, arg) != 0)
163 aed->result = -1;
164 }
165
166 static int
167 check_cxa_atexit (cxa_atexit_p cxa_atexit, cxa_finalize_p cxa_finalize)
168 {
169 struct atexit_data aed = { 0, cxa_atexit };
170
171 /* We re-use &aed as the 'dso' parameter, since it's a unique address. */
172 if (cxa_atexit (cxa_atexit_check_1, &aed, &aed) != 0)
173 return -1;
174 cxa_finalize (&aed);
175 if (aed.result == 0)
176 {
177 /* Call __cxa_finalize again to make sure that cxa_atexit_check_2
178 is removed from the list before AED goes out of scope. */
179 cxa_finalize (&aed);
180 aed.result = 0;
181 }
182 return aed.result;
183 }
184
185 #ifdef __ppc__
186 /* This comes from Csu. It works only before 10.4. The prototype has
187 been altered a bit to avoid casting. */
188 extern int _dyld_func_lookup(const char *dyld_func_name,
189 void *address) __attribute__((visibility("hidden")));
190
191 static void our_atexit (void);
192
193 /* We're running on 10.3.9. Find the address of the system atexit()
194 function. So easy to say, so hard to do. */
195 static atexit_p
196 find_atexit_10_3 (void)
197 {
198 unsigned int (*dyld_image_count_fn)(void);
199 const char *(*dyld_get_image_name_fn)(unsigned int image_index);
200 const void *(*dyld_get_image_header_fn)(unsigned int image_index);
201 const void *(*NSLookupSymbolInImage_fn)(const void *image,
202 const char *symbolName,
203 unsigned int options);
204 void *(*NSAddressOfSymbol_fn)(const void *symbol);
205 unsigned i, count;
206
207 /* Find some dyld functions. */
208 _dyld_func_lookup("__dyld_image_count", &dyld_image_count_fn);
209 _dyld_func_lookup("__dyld_get_image_name", &dyld_get_image_name_fn);
210 _dyld_func_lookup("__dyld_get_image_header", &dyld_get_image_header_fn);
211 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", &NSLookupSymbolInImage_fn);
212 _dyld_func_lookup("__dyld_NSAddressOfSymbol", &NSAddressOfSymbol_fn);
213
214 /* If any of these don't exist, that's an error. */
215 if (! dyld_image_count_fn || ! dyld_get_image_name_fn
216 || ! dyld_get_image_header_fn || ! NSLookupSymbolInImage_fn
217 || ! NSAddressOfSymbol_fn)
218 return NULL;
219
220 count = dyld_image_count_fn ();
221 for (i = 0; i < count; i++)
222 {
223 const char * path = dyld_get_image_name_fn (i);
224 const void * image;
225 const void * symbol;
226
227 if (strcmp (path, "/usr/lib/libSystem.B.dylib") != 0)
228 continue;
229 image = dyld_get_image_header_fn (i);
230 if (! image)
231 return NULL;
232 /* '4' is NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR. */
233 symbol = NSLookupSymbolInImage_fn (image, "_atexit", 4);
234 if (! symbol)
235 return NULL;
236 return NSAddressOfSymbol_fn (symbol);
237 }
238 return NULL;
239 }
240 #endif
241
242 /* Create (if necessary), find, lock, fill in, and return our globals.
243 Return NULL on error, in which case the globals will not be locked.
244 The caller should call keymgr_set_and_unlock. */
245 static struct keymgr_atexit_list *
246 get_globals (void)
247 {
248 struct keymgr_atexit_list * r;
249
250 #ifdef __ppc__
251 /* 10.3.9 doesn't have _keymgr_get_and_lock_processwide_ptr_2 so the
252 PPC side can't use it. On 10.4 this just means the error gets
253 reported a little later when
254 _keymgr_set_and_unlock_processwide_ptr finds that the key was
255 never locked. */
256 r = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
257 #else
258 void * rr;
259 if (_keymgr_get_and_lock_processwide_ptr_2 (KEYMGR_ATEXIT_LIST, &rr))
260 return NULL;
261 r = rr;
262 #endif
263
264 if (r == NULL)
265 {
266 r = calloc (sizeof (struct keymgr_atexit_list), 1);
267 if (! r)
268 return NULL;
269 }
270
271 if (r->atexit_status == atexit_status_unknown)
272 {
273 void *handle;
274
275 handle = dlopen ("/usr/lib/libSystem.B.dylib", RTLD_NOLOAD);
276 if (!handle)
277 {
278 #ifdef __ppc__
279 r->atexit_status = atexit_status_missing;
280 r->atexit_f = find_atexit_10_3 ();
281 if (! r->atexit_f)
282 goto error;
283 if (r->atexit_f (our_atexit))
284 goto error;
285 #else
286 goto error;
287 #endif
288 }
289 else
290 {
291 int chk_result;
292
293 r->cxa_atexit_f = (cxa_atexit_p)dlsym (handle, "__cxa_atexit");
294 r->cxa_finalize_f = (cxa_finalize_p)dlsym (handle, "__cxa_finalize");
295 if (! r->cxa_atexit_f || ! r->cxa_finalize_f)
296 goto error;
297
298 chk_result = check_cxa_atexit (r->cxa_atexit_f, r->cxa_finalize_f);
299 if (chk_result == -1)
300 goto error;
301 else if (chk_result == 0)
302 r->atexit_status = atexit_status_broken;
303 else
304 {
305 r->atexit_f = (atexit_p)dlsym (handle, "atexit");
306 if (! r->atexit_f)
307 goto error;
308 r->atexit_status = atexit_status_working;
309 }
310 }
311 }
312
313 return r;
314
315 error:
316 _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, r);
317 return NULL;
318 }
319
320 /* Add TO_ADD to ATEXIT_LIST. ATEXIT_LIST may be NULL but is
321 always the result of calling _keymgr_get_and_lock_processwide_ptr and
322 so KEYMGR_ATEXIT_LIST is known to be locked; this routine is responsible
323 for unlocking it. */
324
325 static int
326 add_routine (struct keymgr_atexit_list * g,
327 const struct one_atexit_routine * to_add)
328 {
329 struct atexit_routine_list * s
330 = malloc (sizeof (struct atexit_routine_list));
331 int result;
332
333 if (!s)
334 {
335 _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
336 return -1;
337 }
338 s->r = *to_add;
339 s->next = g->l;
340 g->l = s;
341 result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
342 return CHECK_KEYMGR_ERROR (result) == 0 ? 0 : -1;
343 }
344
345 /* This runs the routines in G->L up to STOP. */
346 static struct keymgr_atexit_list *
347 run_routines (struct keymgr_atexit_list *g,
348 struct atexit_routine_list *stop)
349 {
350 for (;;)
351 {
352 struct atexit_routine_list * cur = g->l;
353 if (! cur || cur == stop)
354 break;
355 g->l = cur->next;
356 _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
357
358 switch (cur->r.has_arg) {
359 case 0: case 2: case 4:
360 cur->r.callback.ac ();
361 break;
362 case 1: case 3: case 5:
363 cur->r.callback.cac (cur->r.arg);
364 break;
365 default:
366 /* Don't understand, so don't call it. */
367 break;
368 }
369 free (cur);
370
371 g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
372 if (! g)
373 break;
374 }
375 return g;
376 }
377
378 /* Call the routine described by ROUTINE_PARAM and then call any
379 routines added to KEYMGR_ATEXIT_LIST while that routine was
380 running, all with in_cxa_finalize set. */
381
382 static void
383 cxa_atexit_wrapper (void* routine_param)
384 {
385 struct one_atexit_routine * routine = routine_param;
386 struct keymgr_atexit_list *g;
387 struct atexit_routine_list * base = NULL;
388 char prev_running = 0;
389
390 g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
391 if (g)
392 {
393 prev_running = g->running_routines;
394 g->running_routines = 1;
395 base = g->l;
396 _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
397 }
398
399 if (routine->has_arg)
400 routine->callback.cac (routine->arg);
401 else
402 routine->callback.ac ();
403
404 if (g)
405 g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
406 if (g)
407 g = run_routines (g, base);
408 if (g)
409 {
410 g->running_routines = prev_running;
411 _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
412 }
413 }
414
415 #ifdef __ppc__
416 /* This code is used while running on 10.3.9, when __cxa_atexit doesn't
417 exist in the system library. 10.3.9 only supported regular PowerPC,
418 so this code isn't necessary on x86 or ppc64. */
419
420 /* This routine is called from the system atexit(); it runs everything
421 registered on the KEYMGR_ATEXIT_LIST. */
422
423 static void
424 our_atexit (void)
425 {
426 struct keymgr_atexit_list *g;
427 char prev_running;
428
429 g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
430 if (! g || g->version != 0 || g->atexit_status != atexit_status_missing)
431 return;
432
433 prev_running = g->running_routines;
434 g->running_routines = 1;
435 g = run_routines (g, NULL);
436 if (! g)
437 return;
438 g->running_routines = prev_running;
439 _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
440 }
441 #endif
442
443 /* This is our wrapper around atexit and __cxa_atexit. It will return
444 nonzero if an error occurs, and otherwise:
445 - if in_cxa_finalize is set, or running on 10.3.9, add R to
446 KEYMGR_ATEXIT_LIST; or
447 - call the system __cxa_atexit to add cxa_atexit_wrapper with an argument
448 that indicates how cxa_atexit_wrapper should call R. */
449
450 static int
451 atexit_common (const struct one_atexit_routine *r, const void *dso)
452 {
453 struct keymgr_atexit_list *g = get_globals ();
454
455 if (! g)
456 return -1;
457
458 if (g->running_routines || g->atexit_status == atexit_status_missing)
459 return add_routine (g, r);
460
461 if (g->atexit_status >= atexit_status_working)
462 {
463 int result;
464 if (r->has_arg)
465 {
466 cxa_atexit_p cxa_atexit = g->cxa_atexit_f;
467 result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST,
468 g);
469 if (CHECK_KEYMGR_ERROR (result))
470 return -1;
471 return cxa_atexit (r->callback.cac, r->arg, dso);
472 }
473 else
474 {
475 atexit_p atexit_f = g->atexit_f;
476 result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST,
477 g);
478 if (CHECK_KEYMGR_ERROR (result))
479 return -1;
480 return atexit_f (r->callback.ac);
481 }
482 }
483 else
484 {
485 cxa_atexit_p cxa_atexit = g->cxa_atexit_f;
486 struct one_atexit_routine *alloced;
487 int result;
488
489 result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
490 if (CHECK_KEYMGR_ERROR (result))
491 return -1;
492
493 alloced = malloc (sizeof (struct one_atexit_routine));
494 if (! alloced)
495 return -1;
496 *alloced = *r;
497 return cxa_atexit (cxa_atexit_wrapper, alloced, dso);
498 }
499 }
500
501 /* These are the actual replacement routines; they just funnel into
502 atexit_common. */
503
504 int __cxa_atexit (cxa_atexit_callback func, void* arg,
505 const void* dso) __attribute__((visibility("hidden")));
506
507 int
508 __cxa_atexit (cxa_atexit_callback func, void* arg, const void* dso)
509 {
510 struct one_atexit_routine r;
511 r.callback.cac = func;
512 r.has_arg = 1;
513 r.arg = arg;
514 return atexit_common (&r, dso);
515 }
516
517 int atexit (atexit_callback func) __attribute__((visibility("hidden")));
518
519 /* Use __dso_handle to allow even bundles that call atexit() to be unloaded
520 on 10.4. */
521 extern void __dso_handle;
522
523 int
524 atexit (atexit_callback func)
525 {
526 struct one_atexit_routine r;
527 r.callback.ac = func;
528 r.has_arg = 0;
529 return atexit_common (&r, &__dso_handle);
530 }
531
532 #endif /* __PIC__ */