diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index eb834601ace..073ed11d321 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,23 @@ +2014-10-30 Joseph Myers + + * Makefile.in (libgcc.map.in): New target. + (libgcc.map): Use libgcc.map.in. + * config/t-softfp (softfp_compat): New variable to be set by + users. + [$(softfp_compat) = y] (softfp_map_dep, softfp_set_symver): New + variables. + [$(softfp_compat) = y] (softfp_file_list): Use files in the build + directory. + [$(softfp_compat) = y] ($(softfp_file_list)): Generate wrappers + that use compat symbols and disable all code unless [SHARED]. + * config/t-softfp-compat: New file. + * find-symver.awk: New file. + * configure.ac (--with-glibc-version): New configure option. + (ppc_fp_compat): New variable set for powerpc*-*-linux*. + * configure: Regenerate. + * config.host (powerpc*-*-linux*): Use ${ppc_fp_compat} for + soft-float and e500. + 2014-10-29 Joseph Myers * config/t-hardfp (hardfp_exclusions): Document new variable for diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index 4008a859349..357e15c3761 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -922,12 +922,16 @@ ifeq ($(enable_shared),yes) # Map-file generation. ifneq ($(SHLIB_MKMAP),) -libgcc.map: $(SHLIB_MKMAP) $(SHLIB_MAPFILES) $(libgcc-s-objects) - { $(NM) $(SHLIB_NM_FLAGS) $(libgcc-s-objects); echo %%; \ - cat $(SHLIB_MAPFILES) \ +libgcc.map.in: $(SHLIB_MAPFILES) + { cat $(SHLIB_MAPFILES) \ | sed -e '/^[ ]*#/d' \ -e 's/^%\(if\|else\|elif\|endif\|define\)/#\1/' \ | $(gcc_compile_bare) -E -xassembler-with-cpp -; \ + } > tmp-$@ + mv tmp-$@ $@ +libgcc.map: $(SHLIB_MKMAP) libgcc.map.in $(libgcc-s-objects) + { $(NM) $(SHLIB_NM_FLAGS) $(libgcc-s-objects); echo %%; \ + cat libgcc.map.in; \ } | $(AWK) -f $(SHLIB_MKMAP) $(SHLIB_MKMAP_OPTS) > tmp-$@ mv tmp-$@ $@ libgcc_s$(SHLIB_EXT): libgcc.map diff --git a/libgcc/config.host b/libgcc/config.host index 6d0fccdab2d..f3cc2765583 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -998,13 +998,13 @@ powerpc*-*-linux*) tmake_file="${tmake_file} t-hardfp-sfdf t-hardfp" ;; soft) - tmake_file="${tmake_file} t-softfp-sfdf t-softfp" + tmake_file="${tmake_file} t-softfp-sfdf ${ppc_fp_compat} t-softfp" ;; e500v1) - tmake_file="${tmake_file} rs6000/t-e500v1-fp t-softfp t-hardfp" + tmake_file="${tmake_file} rs6000/t-e500v1-fp ${ppc_fp_compat} t-softfp t-hardfp" ;; e500v2) - tmake_file="${tmake_file} t-hardfp-sfdf rs6000/t-e500v2-fp t-softfp t-hardfp" + tmake_file="${tmake_file} t-hardfp-sfdf rs6000/t-e500v2-fp ${ppc_fp_compat} t-softfp t-hardfp" ;; *) echo "Unknown ppc_fp_type $ppc_fp_type" 1>&2 diff --git a/libgcc/config/t-softfp b/libgcc/config/t-softfp index 43e0b4d578d..e9fece7583d 100644 --- a/libgcc/config/t-softfp +++ b/libgcc/config/t-softfp @@ -35,6 +35,11 @@ # the above settings, also define softfp_extras as a list of those # functions, e.g. unorddf2. # +# If the functions should only be built as compat symbols for shared +# libgcc, not available for new links, also define: +# +# softfp_compat := y +# # If the libgcc2.c functions should not be replaced, also define: # # softfp_exclude_libgcc2 := y @@ -52,7 +57,8 @@ # softfp_wrap_end: text to put at the end of wrapper source files, # e.g. '#endif' # -# This is another temporary measure. +# This is another temporary measure, and cannot be used together with +# softfp_compat. softfp_float_funcs = add$(m)3 div$(m)3 eq$(m)2 ge$(m)2 le$(m)2 mul$(m)3 \ neg$(m)2 sub$(m)3 unord$(m)2 @@ -77,16 +83,36 @@ softfp_func_list := $(filter-out floatdidf floatdisf fixunsdfsi fixunssfsi \ floatundidf floatundisf floatundixf floatunditf,$(softfp_func_list)) endif -ifeq ($(softfp_wrap_start),) -softfp_file_list := \ - $(addsuffix .c,$(addprefix $(srcdir)/soft-fp/,$(softfp_func_list))) +ifeq ($(softfp_compat),y) +softfp_file_list := $(addsuffix .c,$(softfp_func_list)) + +ifeq ($(enable_shared),yes) +softfp_map_dep := libgcc.map.in else +softfp_map_dep := +endif +softfp_set_symver = echo "asm (\".symver $(1),$(1)@`$(AWK) -f $(srcdir)/find-symver.awk -v symbol=$(1) libgcc.map.in`\");" >> $@ +$(softfp_file_list): $(softfp_map_dep) + echo '#ifdef SHARED' > $@ + echo '#include "soft-fp/$@"' >> $@ +ifeq ($(enable_shared),yes) + $(call softfp_set_symver,__$(*F)) + if grep strong_alias $(srcdir)/soft-fp/$@ > /dev/null; then \ + alias=`grep strong_alias $(srcdir)/soft-fp/$@ | sed -e 's/.*, *//' -e 's/).*//'`; \ + $(call softfp_set_symver,$$alias); \ + fi +endif + echo '#endif' >> $@ +else ifneq ($(softfp_wrap_start),) softfp_file_list := $(addsuffix .c,$(softfp_func_list)) $(softfp_file_list): echo $(softfp_wrap_start) > $@ echo '#include "soft-fp/$@"' >> $@ echo $(softfp_wrap_end) >> $@ +else +softfp_file_list := \ + $(addsuffix .c,$(addprefix $(srcdir)/soft-fp/,$(softfp_func_list))) endif # Disable missing prototype and type limit warnings. The prototypes diff --git a/libgcc/config/t-softfp-compat b/libgcc/config/t-softfp-compat new file mode 100644 index 00000000000..2afc9488a06 --- /dev/null +++ b/libgcc/config/t-softfp-compat @@ -0,0 +1 @@ +softfp_compat := y diff --git a/libgcc/configure b/libgcc/configure index 7a154db9de9..3f53aafacaa 100644 --- a/libgcc/configure +++ b/libgcc/configure @@ -666,6 +666,7 @@ enable_decimal_float with_system_libunwind enable_sjlj_exceptions enable_explicit_exception_frame_registration +with_glibc_version enable_tls ' ac_precious_vars='build_alias @@ -1318,6 +1319,8 @@ Optional Packages: --with-slibdir=DIR shared libraries in DIR LIBDIR --with-build-libsubdir=DIR Directory where to find libraries for build system --with-system-libunwind use installed libunwind + --with-glibc-version=M.N + assume GCC used with glibc version M.N or later Some influential environment variables: CC C compiler command @@ -4376,6 +4379,38 @@ fi $as_echo "$libgcc_cv_mips_hard_float" >&6; } esac +# Determine the version of glibc, if any, used on the target. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for target glibc version" >&5 +$as_echo_n "checking for target glibc version... " >&6; } + +# Check whether --with-glibc-version was given. +if test "${with_glibc_version+set}" = set; then : + withval=$with_glibc_version; +if echo "$with_glibc_version" | grep '^[0-9][0-9]*\.[0-9][0-9]*$'; then + glibc_version_major=`echo "$with_glibc_version" | sed -e 's/\..*//'` + glibc_version_minor=`echo "$with_glibc_version" | sed -e 's/.*\.//'` +else + as_fn_error "option --with-glibc-version requires a version number M.N" "$LINENO" 5 +fi +else + +if ac_fn_c_compute_int "$LINENO" "__GLIBC__" "glibc_version_major" "#include "; then : + +else + glibc_version_major=0 +fi + +if ac_fn_c_compute_int "$LINENO" "__GLIBC_MINOR__" "glibc_version_minor" "#include "; then : + +else + glibc_version_minor=0 +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibc_version_major.$glibc_version_minor" >&5 +$as_echo "$glibc_version_major.$glibc_version_minor" >&6; } + # Determine floating-point type for powerpc*-*-linux*. # Single-precision-only FPRs are not a supported configuration for # this target, so are not allowed for in this test. @@ -4396,6 +4431,20 @@ ppc_fp_type=hard EOF eval `${CC-cc} -E conftest.c | grep ppc_fp_type=` rm -f conftest.c +# glibc 2.19 and later provide all the soft-fp functions, with proper +# interactions with exception and rounding mode handling, so +# make libgcc's versions into compat symbols if a recent enough glibc +# version is being used. +ppc_fp_compat= +case ${ppc_fp_type} in +soft|e500v1|e500v2) + if test $glibc_version_major -gt 2 \ + || ( test $glibc_version_major -eq 2 \ + && test $glibc_version_minor -ge 19 ); then + ppc_fp_compat="t-softfp-compat" + fi + ;; +esac ;; esac diff --git a/libgcc/configure.ac b/libgcc/configure.ac index 710f15a8279..79d0ea43493 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -320,6 +320,25 @@ mips*-*-*) [libgcc_cv_mips_hard_float=no])]) esac +# Determine the version of glibc, if any, used on the target. +AC_MSG_CHECKING([for target glibc version]) +AC_ARG_WITH([glibc-version], + [AS_HELP_STRING([--with-glibc-version=M.N], + [assume GCC used with glibc version M.N or later])], [ +if [echo "$with_glibc_version" | grep '^[0-9][0-9]*\.[0-9][0-9]*$']; then + glibc_version_major=`echo "$with_glibc_version" | sed -e 's/\..*//'` + glibc_version_minor=`echo "$with_glibc_version" | sed -e 's/.*\.//'` +else + AC_MSG_ERROR([option --with-glibc-version requires a version number M.N]) +fi], [ +AC_COMPUTE_INT([glibc_version_major], [__GLIBC__], + [#include ], + [glibc_version_major=0]) +AC_COMPUTE_INT([glibc_version_minor], [__GLIBC_MINOR__], + [#include ], + [glibc_version_minor=0])]) +AC_MSG_RESULT([$glibc_version_major.$glibc_version_minor]) + # Determine floating-point type for powerpc*-*-linux*. # Single-precision-only FPRs are not a supported configuration for # this target, so are not allowed for in this test. @@ -340,6 +359,20 @@ ppc_fp_type=hard EOF eval `${CC-cc} -E conftest.c | grep ppc_fp_type=` rm -f conftest.c +# glibc 2.19 and later provide all the soft-fp functions, with proper +# interactions with exception and rounding mode handling, so +# make libgcc's versions into compat symbols if a recent enough glibc +# version is being used. +ppc_fp_compat= +case ${ppc_fp_type} in +soft|e500v1|e500v2) + if test $glibc_version_major -gt 2 \ + || ( test $glibc_version_major -eq 2 \ + && test $glibc_version_minor -ge 19 ); then + ppc_fp_compat="t-softfp-compat" + fi + ;; +esac ;; esac diff --git a/libgcc/find-symver.awk b/libgcc/find-symver.awk new file mode 100644 index 00000000000..adf5ba78455 --- /dev/null +++ b/libgcc/find-symver.awk @@ -0,0 +1,28 @@ +# Extract the version of a single symbol from the version map. +# Copyright (C) 2014 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 3, or (at your option) any later +# version. +# +# 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 COPYING3. If not see +# . + +/^[A-Z]/ { + version = $1; + next; +} + +$1 == symbol { + print version + exit +}