diff options
-rw-r--r-- | config.h.in | 4 | ||||
-rwxr-xr-x | configure | 28 | ||||
-rw-r--r-- | configure.ac | 23 | ||||
-rw-r--r-- | include/libc-symbols.h | 5 | ||||
-rw-r--r-- | include/shlib-compat.h | 82 | ||||
-rw-r--r-- | malloc/malloc.c | 2 | ||||
-rw-r--r-- | nptl/libpthread-compat.c | 16 | ||||
-rw-r--r-- | sysdeps/generic/libc-symver.h | 56 | ||||
-rw-r--r-- | sysdeps/ia64/libc-symver.h | 33 | ||||
-rw-r--r-- | time/clock_getcpuclockid.c | 3 | ||||
-rw-r--r-- | time/clock_getres.c | 3 | ||||
-rw-r--r-- | time/clock_gettime.c | 3 | ||||
-rw-r--r-- | time/clock_nanosleep.c | 3 | ||||
-rw-r--r-- | time/clock_settime.c | 3 |
14 files changed, 197 insertions, 67 deletions
diff --git a/config.h.in b/config.h.in index f21bf04e47..ca1547ae67 100644 --- a/config.h.in +++ b/config.h.in @@ -190,6 +190,10 @@ /* Define if the linker defines __ehdr_start. */ #undef HAVE_EHDR_START +/* Define to 1 if the assembler needs intermediate aliases to define + multiple symbol versions for one symbol. */ +#define SYMVER_NEEDS_ALIAS 0 + /* */ @@ -6590,6 +6590,34 @@ elif test "$libc_cv_ehdr_start" = broken; then $as_echo "$as_me: WARNING: linker is broken -- you should upgrade" >&2;} fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the assembler requires one version per symbol" >&5 +$as_echo_n "checking whether the assembler requires one version per symbol... " >&6; } +if ${libc_cv_symver_needs_alias+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<EOF + .text +testfunc: + .globl testfunc + .symver testfunc, testfunc1@VERSION1 + .symver testfunc, testfunc1@VERSION2 +EOF + libc_cv_symver_needs_alias=no + if ${CC-cc} $ASFLAGS -c conftest.s 2>&5; then + libc_cv_symver_needs_alias=no + else + libc_cv_symver_needs_alias=yes + fi + rm conftest.* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_symver_needs_alias" >&5 +$as_echo "$libc_cv_symver_needs_alias" >&6; } +if test "$libc_cv_symver_needs_alias" = yes; then + $as_echo "#define SYMVER_NEEDS_ALIAS 1" >>confdefs.h + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_trap with no external dependencies" >&5 $as_echo_n "checking for __builtin_trap with no external dependencies... " >&6; } if ${libc_cv_builtin_trap+:} false; then : diff --git a/configure.ac b/configure.ac index 6a3a9ab620..fce967f2c2 100644 --- a/configure.ac +++ b/configure.ac @@ -1673,6 +1673,29 @@ elif test "$libc_cv_ehdr_start" = broken; then AC_MSG_WARN([linker is broken -- you should upgrade]) fi +dnl Starting with binutils 2.35, GAS can attach multiple symbol versions +dnl to one symbol (PR 23840). +AC_CACHE_CHECK(whether the assembler requires one version per symbol, + libc_cv_symver_needs_alias, [dnl + cat > conftest.s <<EOF + .text +testfunc: + .globl testfunc + .symver testfunc, testfunc1@VERSION1 + .symver testfunc, testfunc1@VERSION2 +EOF + libc_cv_symver_needs_alias=no + if ${CC-cc} $ASFLAGS -c conftest.s 2>&AS_MESSAGE_LOG_FD; then + libc_cv_symver_needs_alias=no + else + libc_cv_symver_needs_alias=yes + fi + rm conftest.* +]) +if test "$libc_cv_symver_needs_alias" = yes; then + AC_DEFINE(SYMVER_NEEDS_ALIAS) +fi + AC_CACHE_CHECK(for __builtin_trap with no external dependencies, libc_cv_builtin_trap, [dnl libc_cv_builtin_trap=no diff --git a/include/libc-symbols.h b/include/libc-symbols.h index ce5f75a1a2..546fc26a7b 100644 --- a/include/libc-symbols.h +++ b/include/libc-symbols.h @@ -404,12 +404,13 @@ for linking") symbol_version_reference(real, name, version) # define default_symbol_version(real, name, version) \ _default_symbol_version(real, name, version) +/* See <libc-symver.h>. */ # ifdef __ASSEMBLER__ # define _default_symbol_version(real, name, version) \ - .symver real, name##@##@##version + _set_symbol_version (real, name@@version) # else # define _default_symbol_version(real, name, version) \ - __asm__ (".symver " #real "," #name "@@" #version) + _set_symbol_version (real, #name "@@" #version) # endif /* Evalutes to a string literal for VERSION in LIB. */ diff --git a/include/shlib-compat.h b/include/shlib-compat.h index b874e2588f..537851d753 100644 --- a/include/shlib-compat.h +++ b/include/shlib-compat.h @@ -62,6 +62,20 @@ i.e. either GLIBC_2.1 or the "earliest version" specified in shlib-versions if that is newer. */ +/* versioned_symbol (LIB, LOCAL, SYMBOL, VERSION) emits a definition + of SYMBOL with a default (@@) VERSION appropriate for LIB. (The + actually emitted symbol version is adjusted according to the + baseline symbol version for LIB.) The address of the symbol is + taken from LOCAL. Properties of LOCAL are copied to the exported + symbol. In particular, LOCAL itself should be global. It is + unspecified whether SYMBOL@VERSION is associated with LOCAL, or if + an intermediate alias is created. If LOCAL and SYMBOL are + distinct, and LOCAL is also intended for export, its version should + be specified explicitly with versioned_symbol, too. + + If LOCAL is a data symbol and does not have a non-zero initializer, + it should be defined with __attribute__ ((nocommon)) for + compatibility with GCC versions that default to -fcommon. */ # define versioned_symbol(lib, local, symbol, version) \ versioned_symbol_1 (lib, local, symbol, version) # define versioned_symbol_1(lib, local, symbol, version) \ @@ -69,44 +83,25 @@ # define versioned_symbol_2(local, symbol, name) \ default_symbol_version (local, symbol, name) +/* compat_symbol is like versioned_symbol, but emits a compatibility + version (with @ instead of @@). The same issue related to + intermediate aliases applies, so LOCAL should not be listed in the + Versions file, or otherwise it can be exported with an undesired + default symbol version. */ # define compat_symbol(lib, local, symbol, version) \ - compat_symbol_reference (lib, local, symbol, version) - -/* This is similar to compat_symbol, but allows versioning the same symbol - to multiple version without having multiple symbol definitions. For - instance: - - #if (SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_2)) - compat_symbol_unique (libc, old_foo, GLIBC_2_1_2) - #endif - - #if (SHLIB_COMPAT (libpthread, GLIBC_2_2_6, GLIBC_2_3)) - compat_symbol_unique (libc, old_foo, GLIBC_2_2_6) - #endif - - Internally it creates a unique strong alias to the input symbol and - creates one compat_symbol on the alias. Using the above example, - it is similar to: - - #if (SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_2)) - strong_alias (old_foo, old_foo__COUNTER__) - compat_symbol (libc, old_foo__COUNTER__, foo, GLIBC_2_2) - #endif. - - With __COUNTER__ being a monotonic number generated by the compiler. */ - -# define __compat_symbol_unique_concat(x, y) x ## y -# define _compat_symbol_unique_concat(x, y) \ - __compat_symbol_unique_concat (x, y) -# define _compat_symbol_unique_alias(name) \ - _compat_symbol_unique_concat (name, __COUNTER__) -# define _compat_symbol_unique(lib, orig_name, name, version) \ - strong_alias (orig_name, name) \ - compat_symbol (lib, name, orig_name, version) -# define compat_symbol_unique(lib, name, version) \ - _compat_symbol_unique (lib, name, _compat_symbol_unique_alias (name), \ - version) - + compat_symbol_1 (lib, local, symbol, version) +# define compat_symbol_1(lib, local, symbol, version) \ + compat_symbol_2 (local, symbol, VERSION_##lib##_##version) +/* See <libc-symver.h>. */ +# ifdef __ASSEMBLER__ +#define compat_symbol_2(local, symbol, name) \ + _set_symbol_version (local, symbol@name) +# else +# define compat_symbol_2(local, symbol, name) \ + compat_symbol_3 (local, symbol, name) +# define compat_symbol_3(local, symbol, name) \ + _set_symbol_version (local, #symbol "@" #name) +# endif #else /* Not compiling ELF shared libraries at all, so never any old versions. */ @@ -118,16 +113,17 @@ /* This should not appear outside `#if SHLIB_COMPAT (...)'. */ # define compat_symbol(lib, local, symbol, version) ... -# define compat_symbol_unique(lib, name, version) ... #endif /* Use compat_symbol_reference for a reference *or* definition of a - specific version of a symbol. Definitions are primarily used to - ensure tests reference the exact compat symbol required, or define an - interposing symbol of the right version e.g. __malloc_initialize_hook - in mcheck-init.c. Use compat_symbol to define such a symbol within - the shared libraries that are built for users. */ + specific version of a symbol. compat_symbol_reference does not + create intermediate aliases. Definitions are primarily used to + ensure tests reference the exact compat symbol required, or define + an interposing symbol of the right version e.g., + __malloc_initialize_hook in mcheck-init.c. Use compat_symbol to + define such a symbol within the shared libraries that are built for + users. */ #define compat_symbol_reference(lib, local, symbol, version) \ compat_symbol_reference_1 (lib, local, symbol, version) #define compat_symbol_reference_1(lib, local, symbol, version) \ diff --git a/malloc/malloc.c b/malloc/malloc.c index 1f4bbd8edf..530c792997 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -1991,7 +1991,7 @@ static void *memalign_hook_ini (size_t alignment, size_t sz, const void *caller) __THROW; #if HAVE_MALLOC_INIT_HOOK -void weak_variable (*__malloc_initialize_hook) (void) = NULL; +void (*__malloc_initialize_hook) (void) __attribute__ ((nocommon)); compat_symbol (libc, __malloc_initialize_hook, __malloc_initialize_hook, GLIBC_2_0); #endif diff --git a/nptl/libpthread-compat.c b/nptl/libpthread-compat.c index 820dcd6a8f..da537af76e 100644 --- a/nptl/libpthread-compat.c +++ b/nptl/libpthread-compat.c @@ -20,10 +20,10 @@ #include <shlib-compat.h> #ifdef SHARED -static void +void attribute_compat_text_section __attribute_used__ -__libpthread_version_placeholder (void) +__libpthread_version_placeholder_1 (void) { } #endif @@ -37,16 +37,16 @@ __libpthread_version_placeholder (void) there are plenty of other symbols which populate those later versions. */ #if (SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_2)) -compat_symbol_unique (libpthread, - __libpthread_version_placeholder, GLIBC_2_1_2); +compat_symbol (libpthread, __libpthread_version_placeholder_1, + __libpthread_version_placeholder, GLIBC_2_1_2); #endif #if (SHLIB_COMPAT (libpthread, GLIBC_2_2_3, GLIBC_2_2_4)) -compat_symbol_unique (libpthread, - __libpthread_version_placeholder, GLIBC_2_2_3); +compat_symbol (libpthread, __libpthread_version_placeholder_1, + __libpthread_version_placeholder, GLIBC_2_2_3); #endif #if (SHLIB_COMPAT (libpthread, GLIBC_2_2_6, GLIBC_2_3)) -compat_symbol_unique (libpthread, - __libpthread_version_placeholder, GLIBC_2_2_6); +compat_symbol (libpthread, __libpthread_version_placeholder_1, + __libpthread_version_placeholder, GLIBC_2_2_6); #endif diff --git a/sysdeps/generic/libc-symver.h b/sysdeps/generic/libc-symver.h index 11c77ae1cd..69d147e2a8 100644 --- a/sysdeps/generic/libc-symver.h +++ b/sysdeps/generic/libc-symver.h @@ -22,17 +22,67 @@ #ifndef _LIBC_SYMVER_H #define _LIBC_SYMVER_H 1 +#include <config.h> + /* Use symbol_version_reference to specify the version a symbol reference should link to. Use symbol_version or default_symbol_version for the definition of a versioned symbol. The difference is that the latter is a no-op in non-shared - builds. */ + builds. + + _set_symbol_version is similar to symbol_version_reference, except + that this macro expects the name and symbol version as a single + string or token sequence, with an @ or @@ separator. (A string is + used in C mode and a token sequence in assembler mode.) + _set_symbol_version only be used for definitions because it may + introduce an alias symbol that would not be globally unique for + mere references. The _set_symbol_version macro is used to define + default_symbol_version and compat_symbol. */ + #ifdef __ASSEMBLER__ # define symbol_version_reference(real, name, version) \ .symver real, name##@##version -#else /* !__ASSEMBLER__ */ +#else # define symbol_version_reference(real, name, version) \ __asm__ (".symver " #real "," #name "@" #version) -#endif +#endif /* !__ASSEMBLER__ */ + +#if SYMVER_NEEDS_ALIAS +/* If the assembler cannot support multiple versions for the same + symbol, introduce __SInnn_ aliases to which the symbol version is + attached. */ +# define __symbol_version_unique_concat(x, y) __SI ## x ## _ ## y +# define _symbol_version_unique_concat(x, y) \ + __symbol_version_unique_concat (x, y) +# define _symbol_version_unique_alias(name) \ + _symbol_version_unique_concat (name, __COUNTER__) +# ifdef __ASSEMBLER__ +# define _set_symbol_version_2(real, alias, name_version) \ + .globl alias ASM_LINE_SEP \ + .equiv alias, real ASM_LINE_SEP \ + .symver alias, name_version +# else +# define _set_symbol_version_2(real, alias, name_version) \ + __asm__ (".globl " #alias "\n\t" \ + ".equiv " #alias ", " #real "\n\t" \ + ".symver " #alias "," name_version) +# endif +# define _set_symbol_version_1(real, alias, name_version) \ + _set_symbol_version_2 (real, alias, name_version) +/* REAL must be globally unique, so that the counter also produces + globally unique symbols. */ +# define _set_symbol_version(real, name_version) \ + _set_symbol_version_1 (real, _symbol_version_unique_alias (real), \ + name_version) +# else /* !SYMVER_NEEDS_ALIAS */ +# ifdef __ASSEMBLER__ +# define _set_symbol_version(real, name_version) \ + .symver real, name_version +# else +# define _set_symbol_version(real, name_version) \ + __asm__ (".symver " #real "," name_version) +# endif +#endif /* !SYMVER_NEEDS_ALIAS */ + #endif /* _LIBC_SYMVER_H */ diff --git a/sysdeps/ia64/libc-symver.h b/sysdeps/ia64/libc-symver.h new file mode 100644 index 0000000000..63a3e58dde --- /dev/null +++ b/sysdeps/ia64/libc-symver.h @@ -0,0 +1,33 @@ +/* Symbol version management. ia64 version. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _LIBC_SYMVER_H + +#include <sysdeps/generic/libc-symver.h> + +/* ia64 recognizes loc1 as a register name. Add the # suffix to all + symbol references. */ +#if !defined (__ASSEMBLER__) && SYMVER_NEEDS_ALIAS +#undef _set_symbol_version_2 +# define _set_symbol_version_2(real, alias, name_version) \ + __asm__ (".globl " #alias "#\n\t" \ + ".equiv " #alias ", " #real "#\n\t" \ + ".symver " #alias "#," name_version) +#endif + +#endif /* _LIBC_SYMVER_H */ diff --git a/time/clock_getcpuclockid.c b/time/clock_getcpuclockid.c index c148d96c5c..220e2eb016 100644 --- a/time/clock_getcpuclockid.c +++ b/time/clock_getcpuclockid.c @@ -42,6 +42,5 @@ versioned_symbol (libc, __clock_getcpuclockid, clock_getcpuclockid, GLIBC_2_17); /* clock_getcpuclockid moved to libc in version 2.17; old binaries may expect the symbol version it had in librt. */ #if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) -strong_alias (__clock_getcpuclockid, __clock_getcpuclockid_2); -compat_symbol (libc, __clock_getcpuclockid_2, clock_getcpuclockid, GLIBC_2_2); +compat_symbol (libc, __clock_getcpuclockid, clock_getcpuclockid, GLIBC_2_2); #endif diff --git a/time/clock_getres.c b/time/clock_getres.c index 4b31893849..9099b62672 100644 --- a/time/clock_getres.c +++ b/time/clock_getres.c @@ -32,8 +32,7 @@ versioned_symbol (libc, __clock_getres, clock_getres, GLIBC_2_17); /* clock_getres moved to libc in version 2.17; old binaries may expect the symbol version it had in librt. */ #if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) -strong_alias (__clock_getres, __clock_getres_2); -compat_symbol (libc, __clock_getres_2, clock_getres, GLIBC_2_2); +compat_symbol (libc, __clock_getres, clock_getres, GLIBC_2_2); #endif stub_warning (clock_getres) diff --git a/time/clock_gettime.c b/time/clock_gettime.c index fdeaaca3f8..e8e129d201 100644 --- a/time/clock_gettime.c +++ b/time/clock_gettime.c @@ -33,8 +33,7 @@ versioned_symbol (libc, __clock_gettime, clock_gettime, GLIBC_2_17); /* clock_gettime moved to libc in version 2.17; old binaries may expect the symbol version it had in librt. */ #if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) -strong_alias (__clock_gettime, __clock_gettime_2); -compat_symbol (libc, __clock_gettime_2, clock_gettime, GLIBC_2_2); +compat_symbol (libc, __clock_gettime, clock_gettime, GLIBC_2_2); #endif stub_warning (clock_gettime) diff --git a/time/clock_nanosleep.c b/time/clock_nanosleep.c index 7ecb1cfcb8..57b3af2a70 100644 --- a/time/clock_nanosleep.c +++ b/time/clock_nanosleep.c @@ -38,8 +38,7 @@ versioned_symbol (libc, __clock_nanosleep, clock_nanosleep, GLIBC_2_17); /* clock_nanosleep moved to libc in version 2.17; old binaries may expect the symbol version it had in librt. */ #if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) -strong_alias (__clock_nanosleep, __clock_nanosleep_2); -compat_symbol (libc, __clock_nanosleep_2, clock_nanosleep, GLIBC_2_2); +compat_symbol (libc, __clock_nanosleep, clock_nanosleep, GLIBC_2_2); #endif stub_warning (clock_nanosleep) diff --git a/time/clock_settime.c b/time/clock_settime.c index 7676aaeb23..4df4ec56d1 100644 --- a/time/clock_settime.c +++ b/time/clock_settime.c @@ -33,8 +33,7 @@ versioned_symbol (libc, __clock_settime, clock_settime, GLIBC_2_17); /* clock_settime moved to libc in version 2.17; old binaries may expect the symbol version it had in librt. */ #if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) -strong_alias (__clock_settime, __clock_settime_2); -compat_symbol (libc, __clock_settime_2, clock_settime, GLIBC_2_2); +compat_symbol (libc, __clock_settime, clock_settime, GLIBC_2_2); #endif stub_warning (clock_settime) |