diff options
-rw-r--r-- | elf/Makefile | 42 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod1.c | 39 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod10.c | 41 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod11.cc | 45 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod12.cc | 44 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod13.cc | 45 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod13.h | 24 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod2.c | 38 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod3.c | 38 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod4.c | 37 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod5.c | 38 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod6.cc | 44 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod7.cc | 45 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod8.c | 41 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc-mod9.cc | 44 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc.c | 148 | ||||
-rw-r--r-- | elf/tst-dlopen-nodelete-reloc.h | 38 |
17 files changed, 789 insertions, 2 deletions
diff --git a/elf/Makefile b/elf/Makefile index 0debea7759..22a7553d50 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -191,7 +191,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ tst-addr1 tst-thrlock \ tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \ - tst-nodelete) \ + tst-nodelete tst-dlopen-nodelete-reloc) \ tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ @@ -271,7 +271,20 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-auditmod9a tst-auditmod9b \ $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ tst-nodelete-uniquemod tst-nodelete-rtldmod \ - tst-nodelete-zmod) \ + tst-nodelete-zmod \ + tst-dlopen-nodelete-reloc-mod1 \ + tst-dlopen-nodelete-reloc-mod2 \ + tst-dlopen-nodelete-reloc-mod3 \ + tst-dlopen-nodelete-reloc-mod4 \ + tst-dlopen-nodelete-reloc-mod5 \ + tst-dlopen-nodelete-reloc-mod6 \ + tst-dlopen-nodelete-reloc-mod7 \ + tst-dlopen-nodelete-reloc-mod8 \ + tst-dlopen-nodelete-reloc-mod9 \ + tst-dlopen-nodelete-reloc-mod10 \ + tst-dlopen-nodelete-reloc-mod11 \ + tst-dlopen-nodelete-reloc-mod12 \ + tst-dlopen-nodelete-reloc-mod13) \ tst-initordera1 tst-initorderb1 \ tst-initordera2 tst-initorderb2 \ tst-initordera3 tst-initordera4 \ @@ -1627,3 +1640,28 @@ $(objpfx)tst-dlopenfailmod1.so: \ $(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so $(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library) + +$(objpfx)tst-dlopen-nodelete-reloc: $(libdl) +$(objpfx)tst-dlopen-nodelete-reloc.out: \ + $(objpfx)tst-dlopen-nodelete-reloc-mod1.so \ + $(objpfx)tst-dlopen-nodelete-reloc-mod2.so \ + $(objpfx)tst-dlopen-nodelete-reloc-mod3.so \ + $(objpfx)tst-dlopen-nodelete-reloc-mod4.so \ + $(objpfx)tst-dlopen-nodelete-reloc-mod5.so +tst-dlopen-nodelete-reloc-mod2.so-no-z-defs = yes +LDFLAGS-tst-dlopen-nodelete-reloc-mod2.so = -Wl,-z,nodelete +LDFLAGS-tst-dlopen-nodelete-reloc-mod5.so = -Wl,-z,nodelete +$(objpfx)tst-dlopen-nodelete-reloc-mod4.so: \ + $(objpfx)tst-dlopen-nodelete-reloc-mod3.so +LDFLAGS-tst-dlopen-nodelete-reloc-mod4.so = -Wl,--no-as-needed +$(objpfx)tst-dlopen-nodelete-reloc-mod5.so: \ + $(objpfx)tst-dlopen-nodelete-reloc-mod4.so +LDFLAGS-tst-dlopen-nodelete-reloc-mod5.so = -Wl,--no-as-needed +tst-dlopen-nodelete-reloc-mod5.so-no-z-defs = yes +$(objpfx)tst-dlopen-nodelete-reloc-mod8.so: $(libdl) +$(objpfx)tst-dlopen-nodelete-reloc-mod10.so: $(libdl) +$(objpfx)tst-dlopen-nodelete-reloc-mod13.so: \ + $(objpfx)tst-dlopen-nodelete-reloc-mod12.so +# Prevent self-reference from marking the object as NODELETE. +LDFLAGS-tst-dlopen-nodelete-reloc-mod12.so = -Wl,-Bsymbolic +LDFLAGS-tst-dlopen-nodelete-reloc-mod13.so = -Wl,--no-as-needed diff --git a/elf/tst-dlopen-nodelete-reloc-mod1.c b/elf/tst-dlopen-nodelete-reloc-mod1.c new file mode 100644 index 0000000000..8927a9f851 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod1.c @@ -0,0 +1,39 @@ +/* Test propagation of NODELETE to an already-loaded object via relocation. + Non-NODELETE helper module. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Globally exported. Set by the main program to true before + termination, and used by tst-dlopen-nodelete-reloc-mod2.so to + trigger marking his module as NODELETE (and also for its destructor + check). */ +bool may_finalize_mod1 = false; + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod1) + { + puts ("error: tst-dlopen-nodelete-reloc-mod1.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod10.c b/elf/tst-dlopen-nodelete-reloc-mod10.c new file mode 100644 index 0000000000..30748b73ec --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod10.c @@ -0,0 +1,41 @@ +/* Helper module to load tst-dlopen-nodelete-reloc-mod11.so. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stddef.h> +#include <stdio.h> +#include <unistd.h> + +static void *handle; + +static void __attribute__ ((constructor)) +init (void) +{ + handle = dlopen ("tst-dlopen-nodelete-reloc-mod11.so", RTLD_NOW); + if (handle == NULL) + { + printf ("error: dlopen in module 10: %s\n", dlerror ()); + _exit (1); + } +} + +static void __attribute__ ((destructor)) +fini (void) +{ + dlclose (handle); +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod11.cc b/elf/tst-dlopen-nodelete-reloc-mod11.cc new file mode 100644 index 0000000000..5aba0a4e64 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod11.cc @@ -0,0 +1,45 @@ +/* Second module defining a unique symbol (loaded indirectly). + 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 + <https://www.gnu.org/licenses/>. */ + +#include "tst-dlopen-nodelete-reloc.h" + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Just a flag here, not used for NODELETE processing. */ +bool may_finalize_mod11 = false; + +/* Trigger the creation of a unique symbol. This should cause + tst-dlopen-nodelete-reloc-mod9.so to be marked as NODELETE. */ +char * +global_function_mod11 (void) +{ + return function_with_local_static_2 (); +} + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod11) + { + puts ("error: tst-dlopen-nodelete-reloc-mod11.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod12.cc b/elf/tst-dlopen-nodelete-reloc-mod12.cc new file mode 100644 index 0000000000..3573c61ba3 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod12.cc @@ -0,0 +1,44 @@ +/* First module for NODELETE test defining a unique symbol (with DT_NEEDED). + 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 + <https://www.gnu.org/licenses/>. */ + +#include "tst-dlopen-nodelete-reloc.h" + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Just a flag here, not used for NODELETE processing. */ +bool may_finalize_mod12 = false; + +/* Trigger the creation of a unique symbol. */ +char * +global_function_mod12 (void) +{ + return function_with_local_static_3 (); +} + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod12) + { + puts ("error: tst-dlopen-nodelete-reloc-mod12.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod13.cc b/elf/tst-dlopen-nodelete-reloc-mod13.cc new file mode 100644 index 0000000000..9ba166f197 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod13.cc @@ -0,0 +1,45 @@ +/* Second module for NODELETE test defining a unique symbol (with DT_NEEDED). + 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 + <https://www.gnu.org/licenses/>. */ + +#include "tst-dlopen-nodelete-reloc.h" + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Just a flag here, not used for NODELETE processing. */ +bool may_finalize_mod13 = false; + +/* Trigger the creation of a unique symbol. This should cause + tst-dlopen-nodelete-reloc-mod12.so to be marked as NODELETE. */ +char * +global_function_mod13 (void) +{ + return function_with_local_static_3 (); +} + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod13) + { + puts ("error: tst-dlopen-nodelete-reloc-mod13.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod13.h b/elf/tst-dlopen-nodelete-reloc-mod13.h new file mode 100644 index 0000000000..5d338481a3 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod13.h @@ -0,0 +1,24 @@ +/* Inline function which produces a unique symbol. + 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 + <https://www.gnu.org/licenses/>. */ + +inline char * +third_function_with_local_static (void) +{ + static char local; + return &local; +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod2.c b/elf/tst-dlopen-nodelete-reloc-mod2.c new file mode 100644 index 0000000000..81ea8e5af2 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod2.c @@ -0,0 +1,38 @@ +/* Test propagation of NODELETE to an already-loaded object via relocation. + NODELETE helper module. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Defined in tst-dlopen-nodelete-reloc-mod1.so. This dependency is + not expressed via DT_NEEDED, so this reference marks the other + object as NODELETE dynamically, during initially relocation. */ +extern bool may_finalize_mod1; + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod1) + { + puts ("error: tst-dlopen-nodelete-reloc-mod2.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod3.c b/elf/tst-dlopen-nodelete-reloc-mod3.c new file mode 100644 index 0000000000..d33f4ec763 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod3.c @@ -0,0 +1,38 @@ +/* Test propagation of NODELETE to an already-loaded object via relocation. + Non-NODELETE helper module. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Globally exported. Set by the main program to true before + termination, and used by tst-dlopen-nodelete-reloc-mod4.so, + tst-dlopen-nodelete-reloc-mod5.so. */ +bool may_finalize_mod3 = false; + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod3) + { + puts ("error: tst-dlopen-nodelete-reloc-mod3.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod4.c b/elf/tst-dlopen-nodelete-reloc-mod4.c new file mode 100644 index 0000000000..7e6633aebb --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod4.c @@ -0,0 +1,37 @@ +/* Test propagation of NODELETE to an already-loaded object via relocation. + Intermediate helper module. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Defined in tst-dlopen-nodelete-reloc-mod3.so. The dependency is + expressed via DT_NEEDED. */ +extern bool may_finalize_mod3; + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod3) + { + puts ("error: tst-dlopen-nodelete-reloc-mod4.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod5.c b/elf/tst-dlopen-nodelete-reloc-mod5.c new file mode 100644 index 0000000000..f876fa0f97 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod5.c @@ -0,0 +1,38 @@ +/* Test propagation of NODELETE to an already-loaded object via relocation. + NODELETE helper module. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Defined in tst-dlopen-nodelete-reloc-mod3.so. The dependency is + expressed via DT_NEEDED on the intermedia DSO + tst-dlopen-nodelete-reloc-mod3.so. */ +extern bool may_finalize_mod3; + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod3) + { + puts ("error: tst-dlopen-nodelete-reloc-mod5.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod6.cc b/elf/tst-dlopen-nodelete-reloc-mod6.cc new file mode 100644 index 0000000000..72db5d4b8f --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod6.cc @@ -0,0 +1,44 @@ +/* First module for NODELETE test defining a unique symbol. + 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 + <https://www.gnu.org/licenses/>. */ + +#include "tst-dlopen-nodelete-reloc.h" + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Just a flag here, not used for NODELETE processing. */ +bool may_finalize_mod6 = false; + +/* Trigger the creation of a unique symbol. */ +char * +global_function_mod6 (void) +{ + return function_with_local_static_1 (); +} + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod6) + { + puts ("error: tst-dlopen-nodelete-reloc-mod6.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod7.cc b/elf/tst-dlopen-nodelete-reloc-mod7.cc new file mode 100644 index 0000000000..0faeea78ba --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod7.cc @@ -0,0 +1,45 @@ +/* Second module for NODELETE test defining a unique symbol. + 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 + <https://www.gnu.org/licenses/>. */ + +#include "tst-dlopen-nodelete-reloc.h" + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Just a flag here, not used for NODELETE processing. */ +bool may_finalize_mod7 = false; + +/* Trigger the creation of a unique symbol. This should cause + tst-dlopen-nodelete-reloc-mod6.so to be marked as NODELETE. */ +char * +global_function_mod7 (void) +{ + return function_with_local_static_2 (); +} + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod7) + { + puts ("error: tst-dlopen-nodelete-reloc-mod7.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod8.c b/elf/tst-dlopen-nodelete-reloc-mod8.c new file mode 100644 index 0000000000..ebb1c35fab --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod8.c @@ -0,0 +1,41 @@ +/* Helper module to load tst-dlopen-nodelete-reloc-mod9.so. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stddef.h> +#include <stdio.h> +#include <unistd.h> + +static void *handle; + +static void __attribute__ ((constructor)) +init (void) +{ + handle = dlopen ("tst-dlopen-nodelete-reloc-mod9.so", RTLD_NOW); + if (handle == NULL) + { + printf ("error: dlopen in module 8: %s\n", dlerror ()); + _exit (1); + } +} + +static void __attribute__ ((destructor)) +fini (void) +{ + dlclose (handle); +} diff --git a/elf/tst-dlopen-nodelete-reloc-mod9.cc b/elf/tst-dlopen-nodelete-reloc-mod9.cc new file mode 100644 index 0000000000..d3d8aa390d --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc-mod9.cc @@ -0,0 +1,44 @@ +/* First module defining a unique symbol (loaded indirectly). + 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 + <https://www.gnu.org/licenses/>. */ + +#include "tst-dlopen-nodelete-reloc.h" + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +/* Just a flag here, not used for NODELETE processing. */ +bool may_finalize_mod9 = false; + +/* Trigger the creation of a unique symbol. */ +char * +global_function_mod9 (void) +{ + return function_with_local_static_2 (); +} + +static void __attribute__ ((destructor)) +fini (void) +{ + if (!may_finalize_mod9) + { + puts ("error: tst-dlopen-nodelete-reloc-mod9.so destructor" + " called too early"); + _exit (1); + } +} diff --git a/elf/tst-dlopen-nodelete-reloc.c b/elf/tst-dlopen-nodelete-reloc.c new file mode 100644 index 0000000000..9d86c89b86 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc.c @@ -0,0 +1,148 @@ +/* Test propagation of NODELETE to an already-loaded object via relocation. + 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 + <https://www.gnu.org/licenses/>. */ + +/* This test exercises NODELETE propagation due to data relocations + and unique symbols. + + First test: Global scope variant, data relocation as the NODELETE + trigger. mod1 is loaded first. + + mod2 ---(may_finalize_mod1 relocation dependency)---> mod1 + (NODELETE) (marked as NODELETE) + + Second test: Local scope variant, data relocation. mod3 is loaded + first, then mod5. + + mod5 ---(DT_NEEDED)---> mod4 ---(DT_NEEDED)---> mod3 + (NODELETE) (not NODELETE) ^ + \ / (marked as + `--(may_finalize_mod3 relocation dependency)--/ NODELETE) + + Third test: Shared local scope with unique symbol. mod6 is loaded + first, then mod7. No explicit dependencies between the two objects. + + mod7 ---(unique symbol)---> mod6 + (marked as NODELETE) + + Forth test: Non-shared scopes with unique symbol. mod8 and mod10 + are loaded from the main program. mod8 loads mod9 from an ELF + constructor, mod10 loads mod11. There are no DT_NEEDED + dependencies. The unique symbol dependency is: + + mod9 ---(unique symbol)---> mod11 + (marked as NODELETE) + + Fifth test: Shared local scope with unique symbol, like test 3, but + this time, there is also a DT_NEEDED dependency: + + DT_NEEDED + mod13 ---(unique symbol)---> mod12 + (marked as NODELETE) + */ + +#include <stdio.h> +#include <string.h> +#include <stdbool.h> +#include <support/check.h> +#include <support/xdlfcn.h> + +static int +do_test (void) +{ +#if 0 + /* First case: global scope, regular data symbol. Open the object + which is not NODELETE initially. */ + void *mod1 = xdlopen ("tst-dlopen-nodelete-reloc-mod1.so", + RTLD_NOW | RTLD_GLOBAL); + /* This is used to indicate that the ELF destructor may be + called. */ + bool *may_finalize_mod1 = xdlsym (mod1, "may_finalize_mod1"); + /* Open the NODELETE object. */ + void *mod2 = xdlopen ("tst-dlopen-nodelete-reloc-mod2.so", RTLD_NOW); + /* This has no effect because the DSO is directly marked as + NODELETE. */ + xdlclose (mod2); + /* This has no effect because the DSO has been indirectly marked as + NODELETE due to a relocation dependency. */ + xdlclose (mod1); +#endif + + /* Second case: local scope, regular data symbol. Open the object + which is not NODELETE initially. */ + void *mod3 = xdlopen ("tst-dlopen-nodelete-reloc-mod3.so", RTLD_NOW); + bool *may_finalize_mod3 = xdlsym (mod3, "may_finalize_mod3"); + /* Open the NODELETE object. */ + void *mod5 = xdlopen ("tst-dlopen-nodelete-reloc-mod5.so", RTLD_NOW); + /* Again those have no effect because of NODELETE. */ + //xdlclose (mod5); + (void) mod5; + xdlclose (mod3); + + /* Third case: Unique symbol. */ + void *mod6 = xdlopen ("tst-dlopen-nodelete-reloc-mod6.so", RTLD_NOW); + bool *may_finalize_mod6 = xdlsym (mod6, "may_finalize_mod6"); + void *mod7 = xdlopen ("tst-dlopen-nodelete-reloc-mod7.so", RTLD_NOW); + bool *may_finalize_mod7 = xdlsym (mod7, "may_finalize_mod7"); + /* This should not have any effect because of the unique symbol. */ + xdlclose (mod6); + /* mod7 is not NODELETE and can be closed. */ + *may_finalize_mod7 = true; + xdlclose (mod7); + + /* Fourth case: Unique symbol, indirect loading. */ + void *mod8 = xdlopen ("tst-dlopen-nodelete-reloc-mod8.so", RTLD_NOW); + void *mod9 = xdlopen ("tst-dlopen-nodelete-reloc-mod9.so", + RTLD_NOW | RTLD_NOLOAD); + bool *may_finalize_mod9 = xdlsym (mod9, "may_finalize_mod9"); + xdlclose (mod9); /* Drop mod9 reference. */ + void *mod10 = xdlopen ("tst-dlopen-nodelete-reloc-mod10.so", RTLD_NOW); + void *mod11 = xdlopen ("tst-dlopen-nodelete-reloc-mod11.so", + RTLD_NOW | RTLD_NOLOAD); + bool *may_finalize_mod11 = xdlsym (mod11, "may_finalize_mod11"); + xdlclose (mod11); /* Drop mod11 reference. */ + /* This should not have any effect because of the unique symbol. */ + xdlclose (mod6); + /* mod11 is not NODELETE and can be closed. */ + *may_finalize_mod11 = true; + /* Trigger closing of mod11, too. */ + xdlclose (mod10); + /* Does not trigger closing of mod9. */ + *may_finalize_mod9 = true; + xdlclose (mod8); + + /* Fifth case: Unique symbol, with DT_NEEDED dependency. */ + void *mod12 = xdlopen ("tst-dlopen-nodelete-reloc-mod12.so", RTLD_NOW); + bool *may_finalize_mod12 = xdlsym (mod12, "may_finalize_mod12"); + void *mod13 = xdlopen ("tst-dlopen-nodelete-reloc-mod13.so", RTLD_NOW); + bool *may_finalize_mod13 = xdlsym (mod13, "may_finalize_mod13"); + /* This should not have any effect because of the unique symbol. */ + xdlclose (mod12); + /* mod13 is not NODELETE and can be closed. */ + *may_finalize_mod13 = true; + xdlclose (mod13); + + /* Prepare for the process exit. */ +// *may_finalize_mod1 = true; + *may_finalize_mod3 = true; + *may_finalize_mod6 = true; + //*may_finalize_mod9 = true; + *may_finalize_mod12 = true; + return 0; +} + +#include <support/test-driver.c> diff --git a/elf/tst-dlopen-nodelete-reloc.h b/elf/tst-dlopen-nodelete-reloc.h new file mode 100644 index 0000000000..b1e5da5ad8 --- /dev/null +++ b/elf/tst-dlopen-nodelete-reloc.h @@ -0,0 +1,38 @@ +/* Inline functions which produce unique symbols. + 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 + <https://www.gnu.org/licenses/>. */ + +inline char * +function_with_local_static_1 (void) +{ + static char local; + return &local; +} + +inline char * +function_with_local_static_2 (void) +{ + static char local; + return &local; +} + +inline char * +function_with_local_static_3 (void) +{ + static char local; + return &local; +} |