diff options
author | Geoffrey Keating <geoffk@apple.com> | 2006-03-16 02:37:09 +0000 |
---|---|---|
committer | Geoffrey Keating <geoffk@apple.com> | 2006-03-16 02:37:09 +0000 |
commit | 34df2308eeb8717d1c7c79719bc5f1bb6adbcc45 (patch) | |
tree | b6ff2fd69076032fa47ae9dc5b1da921c649b574 /gcc/config | |
parent | 97191b5d7f2372f71255f12ae2b28889985716ad (diff) |
2006-03-15 Geoffrey Keating <geoffk@apple.com>
* config.gcc (*-*-darwin*): Don't build crt2.o for all Darwin ports.
Do switch on default_use_cxa_atexit.
(powerpc*-*-darwin*): Build crt2.o on powerpc.
* config/darwin-crt3.o: New.
* config/darwin.h (LINK_SPEC): If -shared-libgcc, make linker default
to 10.3. Pass '-multiply_defined suppress' if crt3.o is in use.
(STARTFILE_SPEC): Add crt3.o when -shared-libgcc and appropriate
OS version.
* config/rs6000/t-darwin: Move crt2.o building to here.
* config/rs6000/darwin.h (C_COMMON_OVERRIDE_OPTIONS): Update
Mac OS version for using __cxa_get_exception_ptr. Don't test versions
of __cxa_atexit.
2006-03-15 Geoffrey Keating <geoffk@apple.com>
* g++.old-deja/g++.other/init18.C: New.
* g++.old-deja/g++.other/init5.C: Remove xfail.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@112121 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/darwin-crt3.c | 208 | ||||
-rw-r--r-- | gcc/config/darwin.h | 32 | ||||
-rw-r--r-- | gcc/config/rs6000/darwin.h | 10 | ||||
-rw-r--r-- | gcc/config/rs6000/t-darwin | 6 | ||||
-rw-r--r-- | gcc/config/t-darwin | 7 |
5 files changed, 241 insertions, 22 deletions
diff --git a/gcc/config/darwin-crt3.c b/gcc/config/darwin-crt3.c new file mode 100644 index 00000000000..698b375c69c --- /dev/null +++ b/gcc/config/darwin-crt3.c @@ -0,0 +1,208 @@ +/* __cxa_atexit backwards-compatibility support for Darwin. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ + +/* It is incorrect to include config.h here, because this file is being + compiled for the target, and hence definitions concerning only the host + do not apply. */ + +#include "tconfig.h" +#include "tsystem.h" + +#include <dlfcn.h> +#include <stdbool.h> +#include <stdlib.h> + +/* This file works around two different problems. + + The first problem is that there is no __cxa_atexit on Mac OS versions + before 10.4. It fixes this by providing one, and having it called from + a destructor. This is not quite as good as having a real __cxa_atexit, + but it's good enough to imitate the behaviour that you'd get if + you didn't have one. + + The second problem is that on 10.4 Mac OS versions, __cxa_finalize + doesn't work right: it doesn't run routines that were registered + while other atexit routines are running. This is worked around by + installing our own handler so that it runs last, and repeatedly + running __cxa_finalize until no new calls to __cxa_atexit are made. */ + +typedef int (*cxa_atexit_p)(void (*func) (void*), void* arg, void* dso); + +#ifdef __ppc__ +void __cxa_finalize (void* dso) __attribute__((weak)); +#else +void __cxa_finalize (void* dso); +#endif + +/* new_atexit_routines is set if __cxa_finalize exists in the system C + library and our copy of __cxa_atexit has been called. */ + +static bool new_atexit_routines; + +/* first_atexit_handler is called after all other atexit routines + that were registered before __cxa_finalize is called. + It may be called more than once, but is not re-entered. */ + +static void +first_atexit_handler(void* dso) +{ + /* Keep running __cxa_finalize until no new atexit routines are + registered. + Note that this means __cxa_finalize will be called at least twice, + even if the first call didn't register any new routines. */ + while (new_atexit_routines) { + new_atexit_routines = false; + __cxa_finalize (dso); + }; +} + +/* This is our wrapper around __cxa_atexit that's called if __cxa_finalize + exists in the system library. All it does is, on its first call, + install first_atexit_handler; and on every call, set new_atexit_routines + and pass control to the system __cxa_atexit. + This proves to be somewhat more complicated than you might expect, + because it may be called in a multithreaded environment. Fortunately + it turns out to be possible to do what's needed without resorting + to locking. */ + +static int +cxa_atexit_wrapper (void (*func) (void*), void* arg, void* dso) +{ + static volatile cxa_atexit_p real_cxa_atexit; + cxa_atexit_p auto_cxa_atexit = real_cxa_atexit; + if (! auto_cxa_atexit) + { + void* handle = dlopen ("/usr/lib/libSystem.B.dylib", RTLD_NOLOAD); + if (! handle) + return -1; + + auto_cxa_atexit = (cxa_atexit_p)dlsym (handle, "__cxa_atexit"); + if (! auto_cxa_atexit) + return -1; + } + /* At this point, auto_cxa_atexit contains the address of + the system __cxa_atexit. */ + if (! real_cxa_atexit) + { + /* Install our handler above before any other handlers + for this image, so it will be called last. */ + int result = (*auto_cxa_atexit)(first_atexit_handler, dso, dso); + if (result != 0) + return result; + /* Now set the global real_cxa_atexit to prevent further + installations of first_atexit_handler. Do this after + the installation so that if another thread sees it is set, + it can be sure that first_atexit_handler really has been + installed. */ + real_cxa_atexit = auto_cxa_atexit; + } + /* At this point, we know that first_atexit_handler has been + installed at least once, and real_cxa_atexit is not NULL. */ + /* It's not necessary to mark new_atexit_routines as volatile, so long + as this write eventually happens before this shared object is + unloaded. */ + new_atexit_routines = true; + /* Call the original __cxa_atexit for this function. */ + return (*auto_cxa_atexit)(func, arg, dso); +} + +#ifdef __ppc__ +/* This code is used while running on 10.3.9, when __cxa_atexit doesn't + exist in the system library. 10.3.9 only supported regular PowerPC, + so this code isn't necessary on x86 or ppc64. */ + +/* This structure holds a routine to call. */ +struct atexit_routine +{ + struct atexit_routine * next; + void (*func)(void *); + void * arg; +}; + +static struct atexit_routine * volatile atexit_routines_list; + +/* If __cxa_atexit doesn't exist at all in the system library, this + routine is used; it completely emulates __cxa_atexit. + + This routine has to be thread-safe, but fortunately this just means + that it has to do atomic list insertion. */ + +static int +cxa_atexit_substitute (void (*func) (void*), void* arg, + /* The 'dso' value will always be equal to this + object's __dso_handle. */ + void* dso __attribute__((unused))) +{ + struct atexit_routine * s = malloc (sizeof (struct atexit_routine)); + struct atexit_routine * next, * old_next; + if (!s) + return -1; + s->func = func; + s->arg = arg; + next = atexit_routines_list; + do { + s->next = old_next = next; + next = __sync_val_compare_and_swap (&atexit_routines_list, old_next, s); + } while (next != old_next); + return 0; +} + +/* The routines added in cxa_atexit_substitute get run here, in a destructor. + This routine doesn't have to be thread-safe. */ + +static void cxa_dtor (void) __attribute__((destructor)); +static void +cxa_dtor (void) +{ + while (atexit_routines_list) + { + struct atexit_routine * working_list = atexit_routines_list; + atexit_routines_list = NULL; + while (working_list) + { + struct atexit_routine * called_routine = working_list; + working_list->func (working_list->arg); + working_list = working_list->next; + free (called_routine); + } + } +} +#endif + +int __cxa_atexit (void (*func) (void*), void* arg, + void* dso) __attribute__((visibility("hidden"))); +int +__cxa_atexit (void (*func) (void*), void* arg, void* dso) +{ +#ifdef __ppc__ + if (! __cxa_finalize) + return cxa_atexit_substitute (func, arg, dso); +#endif + return cxa_atexit_wrapper (func, arg, dso); +} diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index a2c276dd4da..edced4d80cf 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -262,9 +262,13 @@ Boston, MA 02110-1301, USA. */ %{Zimage_base*:-image_base %*} \ %{Zinit*:-init %*} \ %{mmacosx-version-min=*:-macosx_version_min %*} \ + %{!mmacosx-version-min=*:%{shared-libgcc:-macosx_version_min 10.3}} \ %{nomultidefs} \ %{Zmulti_module:-multi_module} %{Zsingle_module:-single_module} \ %{Zmultiply_defined*:-multiply_defined %*} \ + %{!Zmultiply_defined*:%{shared-libgcc: \ + %:version-compare(< 10.5 mmacosx-version-min= -multiply_defined) \ + %:version-compare(< 10.5 mmacosx-version-min= suppress)}} \ %{Zmultiplydefinedunused*:-multiply_defined_unused %*} \ %{prebind} %{noprebind} %{nofixprebinding} %{prebind_all_twolevel_modules} \ %{read_only_relocs} \ @@ -319,19 +323,25 @@ Boston, MA 02110-1301, USA. */ %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_s.10.5) \ -lgcc}" -/* We specify crt0.o as -lcrt0.o so that ld will search the library path. */ +/* We specify crt0.o as -lcrt0.o so that ld will search the library path. + + crt3.o provides __cxa_atexit on systems that don't have it. Since + it's only used with C++, which requires passing -shared-libgcc, key + off that to avoid unnecessarily adding a destructor to every + powerpc program built. */ #undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}} \ - %{!Zbundle:%{pg:%{static:-lgcrt0.o} \ - %{!static:%{object:-lgcrt0.o} \ - %{!object:%{preload:-lgcrt0.o} \ - %{!preload:-lgcrt1.o %(darwin_crt2)}}}} \ - %{!pg:%{static:-lcrt0.o} \ - %{!static:%{object:-lcrt0.o} \ - %{!object:%{preload:-lcrt0.o} \ - %{!preload:-lcrt1.o %(darwin_crt2)}}}}}}" +#define STARTFILE_SPEC \ + "%{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}} \ + %{!Zbundle:%{pg:%{static:-lgcrt0.o} \ + %{!static:%{object:-lgcrt0.o} \ + %{!object:%{preload:-lgcrt0.o} \ + %{!preload:-lgcrt1.o %(darwin_crt2)}}}} \ + %{!pg:%{static:-lcrt0.o} \ + %{!static:%{object:-lcrt0.o} \ + %{!object:%{preload:-lcrt0.o} \ + %{!preload:-lcrt1.o %(darwin_crt2)}}}}}} \ + %{shared-libgcc:%:version-compare(< 10.5 mmacosx-version-min= -lcrt3.o)}" /* The native Darwin linker doesn't necessarily place files in the order that they're specified on the link line. Thus, it is pointless diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h index c116fa4e852..adefe2fdf13 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -97,17 +97,11 @@ do { \ #define C_COMMON_OVERRIDE_OPTIONS do { \ /* On powerpc, __cxa_get_exception_ptr is available starting in the \ - 10.5 libstdc++.dylib. */ \ + 10.4.6 libstdc++.dylib. */ \ if ((! darwin_macosx_version_min \ - || strverscmp (darwin_macosx_version_min, "10.5") < 0) \ + || strverscmp (darwin_macosx_version_min, "10.4.6") < 0) \ && flag_use_cxa_get_exception_ptr == 2) \ flag_use_cxa_get_exception_ptr = 0; \ - /* On powerpc, __cxa_atexit is available starting in the 10.4 \ - libSystem.dylib. */ \ - if ((! darwin_macosx_version_min \ - || strverscmp (darwin_macosx_version_min, "10.4") < 0) \ - && flag_use_cxa_atexit == 2) \ - flag_use_cxa_atexit = 0; \ } while (0) /* Darwin has 128-bit long double support in libc in 10.4 and later. diff --git a/gcc/config/rs6000/t-darwin b/gcc/config/rs6000/t-darwin index 264cb63c87d..8dd9832b9a2 100644 --- a/gcc/config/rs6000/t-darwin +++ b/gcc/config/rs6000/t-darwin @@ -25,3 +25,9 @@ LIB2ADDEH += $(srcdir)/config/rs6000/darwin-fallback.c darwin-fpsave.o: $(srcdir)/config/rs6000/darwin-asm.h darwin-tramp.o: $(srcdir)/config/rs6000/darwin-asm.h + +# Explain how to build crt2.o +$(T)crt2$(objext): $(srcdir)/config/darwin-crt2.c $(GCC_PASSES) \ + $(TCONFIG_H) stmp-int-hdrs tsystem.h + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \ + -c $(srcdir)/config/darwin-crt2.c -o $(T)crt2$(objext) diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin index 3e524f36901..5995f30131f 100644 --- a/gcc/config/t-darwin +++ b/gcc/config/t-darwin @@ -12,11 +12,12 @@ darwin-c.o: $(srcdir)/config/darwin-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ gt-darwin.h : s-gtype ; @true -# Explain how to build crt2.o -$(T)crt2$(objext): $(srcdir)/config/darwin-crt2.c $(GCC_PASSES) \ +# How to build crt3.o +EXTRA_MULTILIB_PARTS=crt3.o +$(T)crt3$(objext): $(srcdir)/config/darwin-crt3.c $(GCC_PASSES) \ $(TCONFIG_H) stmp-int-hdrs tsystem.h $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \ - -c $(srcdir)/config/darwin-crt2.c -o $(T)crt2$(objext) + -c $(srcdir)/config/darwin-crt3.c -o $(T)crt3$(objext) # Use unwind-dw2-fde-darwin LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-darwin.c \ |