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