diff --git a/elf/Makefile b/elf/Makefile index 8e907e6..c55a2e9 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -190,7 +190,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ - tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note + tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ + tst-sonamemove-link tst-sonamemove-dlopen # reldep9 tests-internal += loadtest unload unload2 circleload1 \ neededtest neededtest2 neededtest3 neededtest4 \ @@ -278,7 +279,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-latepthreadmod $(tst-tls-many-dynamic-modules) \ tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \ tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \ - tst-absolute-zero-lib tst-big-note-lib + tst-absolute-zero-lib tst-big-note-lib \ + tst-sonamemove-linkmod1 \ + tst-sonamemove-runmod1 tst-sonamemove-runmod2 ifeq (yes,$(have-mtls-dialect-gnu2)) tests += tst-gnu2-tls1 @@ -1387,6 +1390,28 @@ tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so $(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map +# tst-sonamemove links against an older implementation of the library. +LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ + -Wl,-soname,tst-sonamemove-runmod1.so +LDFLAGS-tst-sonamemove-runmod1.so = -Wl,--no-as-needed \ + -Wl,--version-script=tst-sonamemove-runmod1.map \ + -Wl,-soname,tst-sonamemove-runmod1.so +LDFLAGS-tst-sonamemove-runmod2.so = \ + -Wl,--version-script=tst-sonamemove-runmod2.map \ + -Wl,-soname,tst-sonamemove-runmod2.so +$(objpfx)tst-sonamemove-runmod1.so: $(objpfx)tst-sonamemove-runmod2.so +# Link against the link module, but depend on the run-time modules +# for execution. +$(objpfx)tst-sonamemove-link: $(objpfx)tst-sonamemove-linkmod1.so +$(objpfx)tst-sonamemove-link.out: \ + $(objpfx)tst-sonamemove-runmod1.so \ + $(objpfx)tst-sonamemove-runmod2.so +$(objpfx)tst-sonamemove-dlopen: $(libdl) +$(objpfx)tst-sonamemove-dlopen.out: \ + $(objpfx)tst-sonamemove-runmod1.so \ + $(objpfx)tst-sonamemove-runmod2.so + # Override -z defs, so that we can reference an undefined symbol. # Force lazy binding for the same reason. LDFLAGS-tst-latepthreadmod.so = \ diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 68ecc61..1d046ca 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -536,11 +536,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, } skip: - /* If this current map is the one mentioned in the verneed entry - and we have not found a weak entry, it is a bug. */ - if (symidx == STN_UNDEF && version != NULL && version->filename != NULL - && __glibc_unlikely (_dl_name_match_p (version->filename, map))) - return -1; + ; } while (++i < n); @@ -810,34 +806,10 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, /* Search the relevant loaded objects for a definition. */ for (size_t start = i; *scope != NULL; start = 0, ++scope) - { - int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref, - ¤t_value, *scope, start, version, flags, - skip_map, type_class, undef_map); - if (res > 0) - break; - - if (__glibc_unlikely (res < 0) && skip_map == NULL) - { - /* Oh, oh. The file named in the relocation entry does not - contain the needed symbol. This code is never reached - for unversioned lookups. */ - assert (version != NULL); - const char *reference_name = undef_map ? undef_map->l_name : ""; - struct dl_exception exception; - /* XXX We cannot translate the message. */ - _dl_exception_create_format - (&exception, DSO_FILENAME (reference_name), - "symbol %s version %s not defined in file %s" - " with link time reference%s", - undef_name, version->name, version->filename, - res == -2 ? " (no version symbols)" : ""); - _dl_signal_cexception (0, &exception, N_("relocation error")); - _dl_exception_free (&exception); - *ref = NULL; - return 0; - } - } + if (do_lookup_x (undef_name, new_hash, &old_hash, *ref, + ¤t_value, *scope, start, version, flags, + skip_map, type_class, undef_map) != 0) + break; if (__glibc_unlikely (current_value.s == NULL)) { diff --git a/elf/tst-sonamemove-dlopen.c b/elf/tst-sonamemove-dlopen.c new file mode 100644 index 0000000..c496705 --- /dev/null +++ b/elf/tst-sonamemove-dlopen.c @@ -0,0 +1,35 @@ +/* Check that a moved versioned symbol can be found using dlsym, dlvsym. + Copyright (C) 2019 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 + . */ + +#include +#include +#include + +static int +do_test (void) +{ + /* tst-sonamemove-runmod1.so does not define moved_function, but it + depends on tst-sonamemove-runmod2.so, which does. */ + void *handle = xdlopen ("tst-sonamemove-runmod1.so", RTLD_NOW); + TEST_VERIFY (xdlsym (handle, "moved_function") != NULL); + TEST_VERIFY (xdlvsym (handle, "moved_function", "SONAME_MOVE") != NULL); + + return 0; +} + +#include diff --git a/elf/tst-sonamemove-link.c b/elf/tst-sonamemove-link.c new file mode 100644 index 0000000..4bc3bf3 --- /dev/null +++ b/elf/tst-sonamemove-link.c @@ -0,0 +1,41 @@ +/* Check that a versioned symbol can move from one library to another. + Copyright (C) 2019 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 + . */ + +/* At link time, moved_function is bound to the symbol version + SONAME_MOVE in tst-sonamemove-runmod1.so, using the + tst-sonamemove-linkmod1.so stub object. + + At run time, the process loads the real tst-sonamemove-runmod1.so, + which depends on tst-sonamemove-runmod2.so. + tst-sonamemove-runmod1.so does not define moved_function, but + tst-sonamemove-runmod2.so does. + + The net effect is that the versioned symbol + moved_function@SONAME_MOVE moved from the soname + tst-sonamemove-linkmod1.so at link time to the soname + tst-sonamemove-linkmod2.so at run time. */ +void moved_function (void); + +static int +do_test (void) +{ + moved_function (); + return 0; +} + +#include diff --git a/elf/tst-sonamemove-linkmod1.c b/elf/tst-sonamemove-linkmod1.c new file mode 100644 index 0000000..b8a354e --- /dev/null +++ b/elf/tst-sonamemove-linkmod1.c @@ -0,0 +1,25 @@ +/* Link interface for (lack of) soname matching in versioned symbol refs. + Copyright (C) 2019 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 + . */ + +/* This function moved from tst-sonamemove-runmod1.so. This module is + intended for linking only, to simulate an old application which was + linked against an older version of the library. */ +void +moved_function (void) +{ +} diff --git a/elf/tst-sonamemove-linkmod1.map b/elf/tst-sonamemove-linkmod1.map new file mode 100644 index 0000000..8fe5904 --- /dev/null +++ b/elf/tst-sonamemove-linkmod1.map @@ -0,0 +1,3 @@ +SONAME_MOVE { + global: moved_function; +}; diff --git a/elf/tst-sonamemove-runmod1.c b/elf/tst-sonamemove-runmod1.c new file mode 100644 index 0000000..5c409e2 --- /dev/null +++ b/elf/tst-sonamemove-runmod1.c @@ -0,0 +1,23 @@ +/* Run-time module whose moved_function moved to a library dependency. + Copyright (C) 2019 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 + . */ + +/* Dummy function to add the required symbol version. */ +void +other_function (void) +{ +} diff --git a/elf/tst-sonamemove-runmod1.map b/elf/tst-sonamemove-runmod1.map new file mode 100644 index 0000000..2ea81c6 --- /dev/null +++ b/elf/tst-sonamemove-runmod1.map @@ -0,0 +1,3 @@ +SONAME_MOVE { + global: other_function; +}; diff --git a/elf/tst-sonamemove-runmod2.c b/elf/tst-sonamemove-runmod2.c new file mode 100644 index 0000000..b5e482e --- /dev/null +++ b/elf/tst-sonamemove-runmod2.c @@ -0,0 +1,24 @@ +/* Run-time module with the actual implementation of moved_function. + Copyright (C) 2019 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 + . */ + +/* In the test scenario, this function was originally in + tst-sonamemove-runmod1.so. */ +void +moved_function (void) +{ +} diff --git a/elf/tst-sonamemove-runmod2.map b/elf/tst-sonamemove-runmod2.map new file mode 100644 index 0000000..8fe5904 --- /dev/null +++ b/elf/tst-sonamemove-runmod2.map @@ -0,0 +1,3 @@ +SONAME_MOVE { + global: moved_function; +};