diff options
Diffstat (limited to 'REORG.TODO/dlfcn')
65 files changed, 4237 insertions, 0 deletions
diff --git a/REORG.TODO/dlfcn/Makefile b/REORG.TODO/dlfcn/Makefile new file mode 100644 index 0000000000..94f511d828 --- /dev/null +++ b/REORG.TODO/dlfcn/Makefile @@ -0,0 +1,153 @@ +# Copyright (C) 1995-2017 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 +# <http://www.gnu.org/licenses/>. + +subdir := dlfcn + +include ../Makeconfig + +headers := bits/dlfcn.h dlfcn.h +extra-libs := libdl +libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo \ + dlmopen dlfcn +routines := $(patsubst %,s%,$(filter-out dlfcn,$(libdl-routines))) +elide-routines.os := $(routines) + +extra-libs-others := libdl + +ifeq ($(build-shared),yes) +libdl-routines += dlopenold +libdl-shared-only-routines := dlopenold dlfcn +endif + +ifeq (yes,$(build-shared)) +tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \ + bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \ + bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen +endif +modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \ + defaultmod2 errmsg1mod modatexit modcxaatexit \ + bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \ + bug-atexit2-lib bug-dl-leaf-lib \ + bug-dl-leaf-lib-cb moddummy1 moddummy2 + +failtestmod.so-no-z-defs = yes +glreflib2.so-no-z-defs = yes +errmsg1mod.so-no-z-defs = yes + +ifeq (yes,$(build-shared)) +tests += tststatic tststatic2 tststatic3 tststatic4 tststatic5 +tests-static += tststatic tststatic2 tststatic3 tststatic4 tststatic5 +modules-names += modstatic modstatic2 modstatic3 modstatic5 +tststatic-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf +tststatic2-ENV = $(tststatic-ENV) +tststatic3-ENV = $(tststatic-ENV) +tststatic4-ENV = $(tststatic-ENV) +tststatic5-ENV = $(tststatic-ENV) + +ifneq (,$(CXX)) +modules-names += bug-atexit3-lib +else +tests-unsupported += bug-atexit3 +endif +endif + +extra-test-objs += $(modules-names:=.os) +generated += $(modules-names:=.so) + +include ../Rules + +test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) + +ifeq ($(build-shared),yes) +# Build all the modules even when not actually running test programs. +tests: $(test-modules) +endif + +$(objpfx)glrefmain: $(libdl) +$(objpfx)glrefmain.out: $(objpfx)glrefmain \ + $(objpfx)glreflib1.so $(objpfx)glreflib2.so + +$(objpfx)failtest: $(libdl) +$(objpfx)failtest.out: $(objpfx)failtestmod.so + +$(objpfx)tst-dladdr: $(libdl) +$(objpfx)tst-dladdr.out: $(objpfx)glreflib1.so + +$(objpfx)tst-dlinfo: $(libdl) +$(objpfx)tst-dlinfo.out: $(objpfx)glreflib3.so +LDFLAGS-glreflib3.so = -Wl,-rpath,: + +LDFLAGS-default = $(LDFLAGS-rdynamic) +$(objpfx)default: $(libdl) $(objpfx)defaultmod1.so $(objpfx)defaultmod2.so +$(objpfx)defaultmod1.so: $(libdl) +LDFLAGS-defaultmod2.so = $(LDFLAGS-Bsymbolic) +$(objpfx)defaultmod2.so: $(libdl) + +$(objpfx)errmsg1: $(libdl) +$(objpfx)errmsg1.out: $(objpfx)errmsg1 $(objpfx)errmsg1mod.so + +$(objpfx)tstatexit: $(libdl) +$(objpfx)tstatexit.out: $(objpfx)tstatexit $(objpfx)modatexit.so + +$(objpfx)tstcxaatexit: $(libdl) +$(objpfx)tstcxaatexit.out: $(objpfx)tstcxaatexit $(objpfx)modcxaatexit.so + +$(objpfx)tststatic: $(objpfx)libdl.a +$(objpfx)tststatic.out: $(objpfx)tststatic $(objpfx)modstatic.so + +$(objpfx)tststatic2: $(objpfx)libdl.a +$(objpfx)tststatic2.out: $(objpfx)tststatic2 $(objpfx)modstatic.so \ + $(objpfx)modstatic2.so + +$(objpfx)modstatic2.so: $(libdl) + +$(objpfx)tststatic3: $(objpfx)libdl.a +$(objpfx)tststatic3.out: $(objpfx)tststatic3 $(objpfx)modstatic3.so + +$(objpfx)tststatic4: $(objpfx)libdl.a +$(objpfx)tststatic4.out: $(objpfx)tststatic4 $(objpfx)modstatic3.so + +$(objpfx)tststatic5: $(objpfx)libdl.a +$(objpfx)tststatic5.out: $(objpfx)tststatic5 $(objpfx)modstatic5.so + +$(objpfx)bug-dlopen1: $(libdl) + +$(objpfx)bug-dlsym1: $(libdl) $(objpfx)bug-dlsym1-lib2.so +$(objpfx)bug-dlsym1.out: $(objpfx)bug-dlsym1-lib1.so \ + $(objpfx)bug-dlsym1-lib2.so +$(objpfx)bug-dlsym1-lib1.so: $(objpfx)bug-dlsym1-lib2.so + +$(objpfx)bug-atexit1: $(libdl) +$(objpfx)bug-atexit1.out: $(objpfx)bug-atexit1-lib.so + +$(objpfx)bug-atexit2: $(libdl) +$(objpfx)bug-atexit2.out: $(objpfx)bug-atexit2-lib.so + +ifneq (,$(CXX)) +LDLIBS-bug-atexit3-lib.so = -lstdc++ -lgcc_eh +$(objpfx)bug-atexit3-lib.so: $(libsupport) +$(objpfx)bug-atexit3: $(libdl) +$(objpfx)bug-atexit3.out: $(objpfx)bug-atexit3-lib.so +endif + +$(objpfx)bug-dl-leaf: $(objpfx)bug-dl-leaf-lib.so +$(objpfx)bug-dl-leaf.out: $(objpfx)bug-dl-leaf-lib-cb.so +$(objpfx)bug-dl-leaf-lib.so: $(libdl) +$(objpfx)bug-dl-leaf-lib-cb.so: $(objpfx)bug-dl-leaf-lib.so + +$(objpfx)tst-rec-dlopen: $(libdl) +$(objpfx)tst-rec-dlopen.out: $(objpfx)moddummy1.so $(objpfx)moddummy2.so diff --git a/REORG.TODO/dlfcn/Versions b/REORG.TODO/dlfcn/Versions new file mode 100644 index 0000000000..97902f0dfd --- /dev/null +++ b/REORG.TODO/dlfcn/Versions @@ -0,0 +1,17 @@ +libdl { + GLIBC_2.0 { + dladdr; dlclose; dlerror; dlopen; dlsym; + } + GLIBC_2.1 { + dlopen; dlvsym; + } + GLIBC_2.3.3 { + dladdr1; dlinfo; + } + GLIBC_2.3.4 { + dlmopen; + } + GLIBC_PRIVATE { + _dlfcn_hook; + } +} diff --git a/REORG.TODO/dlfcn/bug-atexit1-lib.c b/REORG.TODO/dlfcn/bug-atexit1-lib.c new file mode 100644 index 0000000000..715bb40b23 --- /dev/null +++ b/REORG.TODO/dlfcn/bug-atexit1-lib.c @@ -0,0 +1,375 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static int next; + +void +f00 (void) +{ + puts ("f00"); + if (next-- != 0) + _exit (1); +} + +void +f01 (void) +{ + puts ("f01"); + if (next-- != 1) + _exit (1); +} + +void +f02 (void) +{ + puts ("f02"); + if (next-- != 2) + _exit (1); +} + +void +f03 (void) +{ + puts ("f03"); + if (next-- != 3) + _exit (1); +} + +void +f04 (void) +{ + puts ("f04"); + if (next-- != 4) + _exit (1); +} + +void +f05 (void) +{ + puts ("f05"); + if (next-- != 5) + _exit (1); +} + +void +f06 (void) +{ + puts ("f06"); + if (next-- != 6) + _exit (1); +} + +void +f07 (void) +{ + puts ("f07"); + if (next-- != 7) + _exit (1); +} + +void +f08 (void) +{ + puts ("f08"); + if (next-- != 8) + _exit (1); +} + +void +f09 (void) +{ + puts ("f09"); + if (next-- != 9) + _exit (1); +} + +void +f10 (void) +{ + puts ("f10"); + if (next-- != 10) + _exit (1); +} + +void +f11 (void) +{ + puts ("f11"); + if (next-- != 11) + _exit (1); +} + +void +f12 (void) +{ + puts ("f12"); + if (next-- != 12) + _exit (1); +} + +void +f13 (void) +{ + puts ("f13"); + if (next-- != 13) + _exit (1); +} + +void +f14 (void) +{ + puts ("f14"); + if (next-- != 14) + _exit (1); +} + +void +f15 (void) +{ + puts ("f15"); + if (next-- != 15) + _exit (1); +} + +void +f16 (void) +{ + puts ("f16"); + if (next-- != 16) + _exit (1); +} + +void +f17 (void) +{ + puts ("f17"); + if (next-- != 17) + _exit (1); +} + +void +f18 (void) +{ + puts ("f18"); + if (next-- != 18) + _exit (1); +} + +void +f19 (void) +{ + puts ("f19"); + if (next-- != 19) + _exit (1); +} + +void +f20 (void) +{ + puts ("f20"); + if (next-- != 20) + _exit (1); +} + +void +f21 (void) +{ + puts ("f21"); + if (next-- != 21) + _exit (1); +} + +void +f22 (void) +{ + puts ("f22"); + if (next-- != 22) + _exit (1); +} + +void +f23 (void) +{ + puts ("f23"); + if (next-- != 23) + _exit (1); +} + +void +f24 (void) +{ + puts ("f24"); + if (next-- != 24) + _exit (1); +} + +void +f25 (void) +{ + puts ("f25"); + if (next-- != 25) + _exit (1); +} + +void +f26 (void) +{ + puts ("f26"); + if (next-- != 26) + _exit (1); +} + +void +f27 (void) +{ + puts ("f27"); + if (next-- != 27) + _exit (1); +} + +void +f28 (void) +{ + puts ("f28"); + if (next-- != 28) + _exit (1); +} + +void +f29 (void) +{ + puts ("f29"); + if (next-- != 29) + _exit (1); +} + +void +f30 (void) +{ + puts ("f30"); + if (next-- != 30) + _exit (1); +} + +void +f31 (void) +{ + puts ("f31"); + if (next-- != 31) + _exit (1); +} + +void +f32 (void) +{ + puts ("f32"); + if (next-- != 32) + _exit (1); +} + +void +f33 (void) +{ + puts ("f33"); + if (next-- != 33) + _exit (1); +} + +void +f34 (void) +{ + puts ("f34"); + if (next-- != 34) + _exit (1); +} + +void +f35 (void) +{ + puts ("f35"); + if (next-- != 35) + _exit (1); +} + +void +f36 (void) +{ + puts ("f36"); + if (next-- != 36) + _exit (1); +} + +void +f37 (void) +{ + puts ("f37"); + if (next-- != 37) + _exit (1); +} + +void +f38 (void) +{ + puts ("f38"); + if (next-- != 38) + _exit (1); +} + +void +f39 (void) +{ + puts ("f39"); + if (next-- != 39) + _exit (1); +} + +void +foo (void) +{ + atexit (f00); + atexit (f01); + atexit (f02); + atexit (f03); + atexit (f04); + atexit (f05); + atexit (f06); + atexit (f07); + atexit (f08); + atexit (f09); + + atexit (f10); + atexit (f11); + atexit (f12); + atexit (f13); + atexit (f14); + atexit (f15); + atexit (f16); + atexit (f17); + atexit (f18); + atexit (f19); + + atexit (f20); + atexit (f21); + atexit (f22); + atexit (f23); + atexit (f24); + atexit (f25); + atexit (f26); + atexit (f27); + atexit (f28); + atexit (f29); + + atexit (f30); + atexit (f31); + atexit (f32); + atexit (f33); + atexit (f34); + atexit (f35); + atexit (f36); + atexit (f37); + atexit (f38); + atexit (f39); + + next = 39; +} diff --git a/REORG.TODO/dlfcn/bug-atexit1.c b/REORG.TODO/dlfcn/bug-atexit1.c new file mode 100644 index 0000000000..e2d1d2f776 --- /dev/null +++ b/REORG.TODO/dlfcn/bug-atexit1.c @@ -0,0 +1,23 @@ +/* Derived from a test case in + http://sourceware.org/bugzilla/show_bug.cgi?id=1158. */ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +static int +do_test (void) +{ + for (int i = 0; i < 2; ++i) + { + void *dso = dlopen ("$ORIGIN/bug-atexit1-lib.so", RTLD_NOW); + void (*fn) (void) = (void (*) (void)) dlsym (dso, "foo"); + fn (); + dlclose (dso); + puts ("round done"); + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/bug-atexit2-lib.c b/REORG.TODO/dlfcn/bug-atexit2-lib.c new file mode 100644 index 0000000000..ca39657566 --- /dev/null +++ b/REORG.TODO/dlfcn/bug-atexit2-lib.c @@ -0,0 +1,14 @@ +#include <stdio.h> +#include <stdlib.h> + +void +fx (void) +{ + puts ("At exit fx"); +} + +void +foo (void) +{ + atexit (fx); +} diff --git a/REORG.TODO/dlfcn/bug-atexit2.c b/REORG.TODO/dlfcn/bug-atexit2.c new file mode 100644 index 0000000000..15e9f7aa01 --- /dev/null +++ b/REORG.TODO/dlfcn/bug-atexit2.c @@ -0,0 +1,53 @@ +/* Derived from a test case in + http://sourceware.org/bugzilla/show_bug.cgi?id=1158. */ +#include <dlfcn.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +static int next = 3; + +static void +f1 (void) +{ + puts ("f1"); + if (next-- != 1) + _exit (1); +} + +static void +f2 (void) +{ + puts ("f2"); + if (next-- != 2) + _exit (1); +} + +static void +f3 (void) +{ + puts ("f3"); + if (next-- != 3) + _exit (1); +} + +static int +do_test (void) +{ + atexit (f1); + + void *dso = dlopen ("$ORIGIN/bug-atexit2-lib.so", RTLD_NOW); + void (*fn) (void) = (void (*) (void)) dlsym (dso, "foo"); + fn (); + + atexit (f2); + + dlclose (dso); + + atexit (f3); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/bug-atexit3-lib.cc b/REORG.TODO/dlfcn/bug-atexit3-lib.cc new file mode 100644 index 0000000000..ed3334709a --- /dev/null +++ b/REORG.TODO/dlfcn/bug-atexit3-lib.cc @@ -0,0 +1,26 @@ +#include <unistd.h> +#include <string.h> + +#include <support/support.h> + +struct statclass +{ + statclass() + { + write_message ("statclass\n"); + } + ~statclass() + { + write_message ("~statclass\n"); + } +}; + +struct extclass +{ + ~extclass() + { + static statclass var; + } +}; + +extclass globvar; diff --git a/REORG.TODO/dlfcn/bug-atexit3.c b/REORG.TODO/dlfcn/bug-atexit3.c new file mode 100644 index 0000000000..897eca8a86 --- /dev/null +++ b/REORG.TODO/dlfcn/bug-atexit3.c @@ -0,0 +1,18 @@ +#include <dlfcn.h> +#include <stdio.h> + +static int +do_test (void) +{ + void *handle = dlopen ("$ORIGIN/bug-atexit3-lib.so", RTLD_LAZY); + if (handle == NULL) + { + printf ("dlopen failed: %s\n", dlerror ()); + return 1; + } + dlclose (handle); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/bug-dl-leaf-lib-cb.c b/REORG.TODO/dlfcn/bug-dl-leaf-lib-cb.c new file mode 100644 index 0000000000..897377651e --- /dev/null +++ b/REORG.TODO/dlfcn/bug-dl-leaf-lib-cb.c @@ -0,0 +1,35 @@ +/* Make sure dlopen/dlclose are not marked as leaf functions. + See bug-dl-leaf-lib.c for details. + + Copyright (C) 2013-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mike Frysinger <vapier@gentoo.org> + + 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 + <http://www.gnu.org/licenses/>. */ + +extern void check_val_init (void); +extern void check_val_fini (void); + +__attribute__ ((__constructor__)) +void construct (void) +{ + check_val_init (); +} + +__attribute__ ((__destructor__)) +void destruct (void) +{ + check_val_fini (); +} diff --git a/REORG.TODO/dlfcn/bug-dl-leaf-lib.c b/REORG.TODO/dlfcn/bug-dl-leaf-lib.c new file mode 100644 index 0000000000..9a1f3ce12a --- /dev/null +++ b/REORG.TODO/dlfcn/bug-dl-leaf-lib.c @@ -0,0 +1,71 @@ +/* Make sure dlopen/dlclose are not marked as leaf functions. + + Copyright (C) 2013-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mike Frysinger <vapier@gentoo.org> + + 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 + <http://www.gnu.org/licenses/>. */ + +/* The bug-dl-leaf.c file will call our lib_main directly. We do this to + keep things simple -- no need to use --export-dynamic with the linker + or build the main ELF as a PIE. + + The lib_main func will modify some of its state while dlopening and + dlclosing the bug-dl-leaf-lib-cb.so library. The constructors and + destructors in that library will call back into this library to also + muck with state (the check_val_xxx funcs). + + If dlclose/dlopen are marked as "leaf" functions, then with newer + versions of gcc, the state modification won't work correctly. */ + +#include <assert.h> +#include <dlfcn.h> + +static int val = 1; +static int called = 0; + +void check_val_init (void) +{ + called = 1; + assert (val == 2); +} + +void check_val_fini (void) +{ + called = 2; + assert (val == 4); +} + +int lib_main (void) +{ + int ret __attribute__ ((unused)); + void *hdl; + + /* Make sure the constructor sees the updated val. */ + val = 2; + hdl = dlopen ("bug-dl-leaf-lib-cb.so", RTLD_GLOBAL | RTLD_LAZY); + val = 3; + assert (hdl); + assert (called == 1); + + /* Make sure the destructor sees the updated val. */ + val = 4; + ret = dlclose (hdl); + val = 5; + assert (ret == 0); + assert (called == 2); + + return !val; +} diff --git a/REORG.TODO/dlfcn/bug-dl-leaf.c b/REORG.TODO/dlfcn/bug-dl-leaf.c new file mode 100644 index 0000000000..423781b395 --- /dev/null +++ b/REORG.TODO/dlfcn/bug-dl-leaf.c @@ -0,0 +1,25 @@ +/* Make sure dlopen/dlclose are not marked as leaf functions. + See bug-dl-leaf-lib.c for details. + + Copyright (C) 2013-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mike Frysinger <vapier@gentoo.org> + + 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 + <http://www.gnu.org/licenses/>. */ + +#define TEST_FUNCTION lib_main () +extern int lib_main (void); + +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/bug-dlopen1.c b/REORG.TODO/dlfcn/bug-dlopen1.c new file mode 100644 index 0000000000..d91810a4f0 --- /dev/null +++ b/REORG.TODO/dlfcn/bug-dlopen1.c @@ -0,0 +1,12 @@ +/* Test case by Bruno Haible. It test whether the dynamic string + token expansion can handle $ signs which do not start one of the + recognized keywords. */ + +#include <dlfcn.h> + +int main (void) +{ + dlopen ("gnu-gettext-GetURL$1", RTLD_GLOBAL | RTLD_LAZY); + dlopen ("gnu-gettext-GetURL${1", RTLD_GLOBAL | RTLD_LAZY); + return 0; +} diff --git a/REORG.TODO/dlfcn/bug-dlsym1-lib1.c b/REORG.TODO/dlfcn/bug-dlsym1-lib1.c new file mode 100644 index 0000000000..4eca2519fb --- /dev/null +++ b/REORG.TODO/dlfcn/bug-dlsym1-lib1.c @@ -0,0 +1,11 @@ +/* Test module for bug-dlsym1.c test case. */ + +extern int dlopen_test_variable; + +extern char foo (void); + +/* here to get the unresolved symbol in our .so */ +char foo(void) +{ + return dlopen_test_variable; +} diff --git a/REORG.TODO/dlfcn/bug-dlsym1-lib2.c b/REORG.TODO/dlfcn/bug-dlsym1-lib2.c new file mode 100644 index 0000000000..4466cbd2d9 --- /dev/null +++ b/REORG.TODO/dlfcn/bug-dlsym1-lib2.c @@ -0,0 +1,3 @@ +/* Test module for bug-dlsym1.c test case. */ + +char dlopen_test_variable; diff --git a/REORG.TODO/dlfcn/bug-dlsym1.c b/REORG.TODO/dlfcn/bug-dlsym1.c new file mode 100644 index 0000000000..3bbf6a2f02 --- /dev/null +++ b/REORG.TODO/dlfcn/bug-dlsym1.c @@ -0,0 +1,28 @@ +/* Test case for bug in dlsym accessing dependency objects' symbols. */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <dlfcn.h> + +int main(void) +{ + void *handle; + char *c; + + /* open lib1.so, which has the unresolved test symbol and a DT_NEEDED + on lib2.so, which provides the symbol */ + if ((handle = dlopen("bug-dlsym1-lib1.so", RTLD_NOW)) == NULL) { + printf("dlopen(\"bug-dlsym1-lib1.so\"): %s\n", dlerror()); + abort(); + } + + if ((c = dlsym(handle, "dlopen_test_variable")) == NULL) { + printf("dlsym(handle, \"dlopen_test_variable\"): %s\n", dlerror()); + abort(); + } + + (void) dlclose(handle); + + return 0; +} diff --git a/REORG.TODO/dlfcn/default.c b/REORG.TODO/dlfcn/default.c new file mode 100644 index 0000000000..612ab79b12 --- /dev/null +++ b/REORG.TODO/dlfcn/default.c @@ -0,0 +1,80 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <string.h> + + +extern int test_in_mod1 (void *); +extern int test_in_mod2 (void *); + + +int +main (int argc, char *argv[]) +{ + int (*ifp) (void); + void *p; + int result = 0; + Dl_info info; + + dladdr(main, &info); + if (info.dli_fname == NULL) + { + printf ("%s: dladdr returns NULL dli_fname\n", __FILE__); + result = 1; + } + else if (strcmp (info.dli_fname, argv[0])) + { + printf ("%s: dladdr returned '%s' as dli_fname\n", __FILE__, info.dli_fname); + result = 1; + } + else + printf ("%s: dladdr returned correct dli_fname\n", __FILE__); + + /* Find function `main'. */ + p = dlsym (RTLD_DEFAULT, "main"); + if (p == NULL) + { + printf ("%s: main not found\n", __FILE__); + result = 1; + } + else if ((int (*)(int, char **))p != main) + { + printf ("%s: wrong address returned for main\n", __FILE__); + result = 1; + } + else + printf ("%s: main correctly found\n", __FILE__); + + ifp = dlsym (RTLD_DEFAULT, "found_in_mod1"); + if ((void *) ifp == NULL) + { + printf ("%s: found_in_mod1 not found\n", __FILE__); + result = 1; + } + else if (ifp () != 1) + { + printf ("%s: wrong address returned for found_in_mod1\n", __FILE__); + result = 1; + } + else + printf ("%s: found_in_mod1 correctly found\n", __FILE__); + + ifp = dlsym (RTLD_DEFAULT, "found_in_mod2"); + if ((void *) ifp == NULL) + { + printf ("%s: found_in_mod2 not found\n", __FILE__); + result = 1; + } + else if (ifp () != 2) + { + printf ("%s: wrong address returned for found_in_mod2\n", __FILE__); + result = 1; + } + else + printf ("%s: found_in_mod2 correctly found\n", __FILE__); + + result |= test_in_mod1 (main); + + result |= test_in_mod2 (main); + + return result; +} diff --git a/REORG.TODO/dlfcn/defaultmod1.c b/REORG.TODO/dlfcn/defaultmod1.c new file mode 100644 index 0000000000..47d229d6b0 --- /dev/null +++ b/REORG.TODO/dlfcn/defaultmod1.c @@ -0,0 +1,64 @@ +#include <dlfcn.h> +#include <stdio.h> + +extern int found_in_mod1 (void); +int +found_in_mod1 (void) +{ + return 1; +} + + +extern int test_in_mod1 (int (*mainp)(int, char **)); +int +test_in_mod1 (int (*mainp)(int, char **)) +{ + int (*ifp) (void); + void *p; + int result = 0; + + /* Find function `main'. */ + p = dlsym (RTLD_DEFAULT, "main"); + if (p == NULL) + { + printf ("%s: main not found\n", __FILE__); + result = 1; + } + else if ((int (*)(int, char **))p != mainp) + { + printf ("%s: wrong address returned for main\n", __FILE__); + result = 1; + } + else + printf ("%s: main correctly found\n", __FILE__); + + ifp = dlsym (RTLD_DEFAULT, "found_in_mod1"); + if ((void *) ifp == NULL) + { + printf ("%s: found_in_mod1 not found\n", __FILE__); + result = 1; + } + else if (ifp () != 1) + { + printf ("%s: wrong address returned for found_in_mod1\n", __FILE__); + result = 1; + } + else + printf ("%s: found_in_mod1 correctly found\n", __FILE__); + + ifp = dlsym (RTLD_DEFAULT, "found_in_mod2"); + if ((void *) ifp == NULL) + { + printf ("%s: found_in_mod2 not found\n", __FILE__); + result = 1; + } + else if (ifp () != 2) + { + printf ("%s: wrong address returned for found_in_mod2\n", __FILE__); + result = 1; + } + else + printf ("%s: found_in_mod2 correctly found\n", __FILE__); + + return result; +} diff --git a/REORG.TODO/dlfcn/defaultmod2.c b/REORG.TODO/dlfcn/defaultmod2.c new file mode 100644 index 0000000000..e0b170815c --- /dev/null +++ b/REORG.TODO/dlfcn/defaultmod2.c @@ -0,0 +1,71 @@ +#include <dlfcn.h> +#include <stdio.h> + +extern int found_in_mod1 (void); +int +found_in_mod1 (void) +{ + return 1; +} + +extern int found_in_mod2 (void); +int +found_in_mod2 (void) +{ + return 2; +} + + +extern int test_in_mod2 (int (*mainp)(int, char **)); +int +test_in_mod2 (int (*mainp)(int, char **)) +{ + int (*ifp) (void); + void *p; + int result = 0; + + /* Find function `main'. */ + p = dlsym (RTLD_DEFAULT, "main"); + if (p == NULL) + { + printf ("%s: main not found\n", __FILE__); + result = 1; + } + else if ((int (*)(int, char **))p != mainp) + { + printf ("%s: wrong address returned for main\n", __FILE__); + result = 1; + } + else + printf ("%s: main correctly found\n", __FILE__); + + ifp = dlsym (RTLD_DEFAULT, "found_in_mod1"); + if ((void *) ifp == NULL) + { + printf ("%s: found_in_mod1 not found\n", __FILE__); + result = 1; + } + else if (ifp () != 1) + { + printf ("%s: wrong address returned for found_in_mod1\n", __FILE__); + result = 1; + } + else + printf ("%s: found_in_mod1 correctly found\n", __FILE__); + + ifp = dlsym (RTLD_DEFAULT, "found_in_mod2"); + if ((void *) ifp == NULL) + { + printf ("%s: found_in_mod2 not found\n", __FILE__); + result = 1; + } + else if (ifp () != 2) + { + printf ("%s: wrong address returned for found_in_mod2\n", __FILE__); + result = 1; + } + else + printf ("%s: found_in_mod2 correctly found\n", __FILE__); + + return result; +} diff --git a/REORG.TODO/dlfcn/dladdr.c b/REORG.TODO/dlfcn/dladdr.c new file mode 100644 index 0000000000..1753434160 --- /dev/null +++ b/REORG.TODO/dlfcn/dladdr.c @@ -0,0 +1,43 @@ +/* Locate the shared object symbol nearest a given address. + Copyright (C) 1996-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> + +#if !defined SHARED && IS_IN (libdl) + +int +dladdr (const void *address, Dl_info *info) +{ + return __dladdr (address, info); +} + +#else + +int +__dladdr (const void *address, Dl_info *info) +{ +# ifdef SHARED + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dladdr (address, info); +# endif + return _dl_addr (address, info, NULL, NULL); +} +# ifdef SHARED +strong_alias (__dladdr, dladdr) +# endif +#endif diff --git a/REORG.TODO/dlfcn/dladdr1.c b/REORG.TODO/dlfcn/dladdr1.c new file mode 100644 index 0000000000..a19f9fdea2 --- /dev/null +++ b/REORG.TODO/dlfcn/dladdr1.c @@ -0,0 +1,53 @@ +/* Locate the shared object symbol nearest a given address. + Copyright (C) 2003-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> + +#if !defined SHARED && IS_IN (libdl) + +int +dladdr1 (const void *address, Dl_info *info, void **extra, int flags) +{ + return __dladdr1 (address, info, extra, flags); +} + +#else + +int +__dladdr1 (const void *address, Dl_info *info, void **extra, int flags) +{ +# ifdef SHARED + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dladdr1 (address, info, extra, flags); +# endif + + switch (flags) + { + default: /* Make this an error? */ + case 0: + return _dl_addr (address, info, NULL, NULL); + case RTLD_DL_SYMENT: + return _dl_addr (address, info, NULL, (const ElfW(Sym) **) extra); + case RTLD_DL_LINKMAP: + return _dl_addr (address, info, (struct link_map **) extra, NULL); + } +} +# ifdef SHARED +strong_alias (__dladdr1, dladdr1) +# endif +#endif diff --git a/REORG.TODO/dlfcn/dlclose.c b/REORG.TODO/dlfcn/dlclose.c new file mode 100644 index 0000000000..da66e20488 --- /dev/null +++ b/REORG.TODO/dlfcn/dlclose.c @@ -0,0 +1,51 @@ +/* Close a handle opened by `dlopen'. + Copyright (C) 1995-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <ldsodefs.h> + +#if !defined SHARED && IS_IN (libdl) + +int +dlclose (void *handle) +{ + return __dlclose (handle); +} + +#else + +static void +dlclose_doit (void *handle) +{ + GLRO(dl_close) (handle); +} + +int +__dlclose (void *handle) +{ +# ifdef SHARED + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dlclose (handle); +# endif + + return _dlerror_run (dlclose_doit, handle) ? -1 : 0; +} +# ifdef SHARED +strong_alias (__dlclose, dlclose) +# endif +#endif diff --git a/REORG.TODO/dlfcn/dlerror.c b/REORG.TODO/dlfcn/dlerror.c new file mode 100644 index 0000000000..c0ead7dcb6 --- /dev/null +++ b/REORG.TODO/dlfcn/dlerror.c @@ -0,0 +1,254 @@ +/* Return error detail for failing <dlfcn.h> functions. + Copyright (C) 1995-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <libintl.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libc-lock.h> +#include <ldsodefs.h> + +#if !defined SHARED && IS_IN (libdl) + +char * +dlerror (void) +{ + return __dlerror (); +} + +#else + +/* Type for storing results of dynamic loading actions. */ +struct dl_action_result + { + int errcode; + int returned; + bool malloced; + const char *objname; + const char *errstring; + }; +static struct dl_action_result last_result; +static struct dl_action_result *static_buf; + +/* This is the key for the thread specific memory. */ +static __libc_key_t key; +__libc_once_define (static, once); + +/* Destructor for the thread-specific data. */ +static void init (void); +static void free_key_mem (void *mem); + + +char * +__dlerror (void) +{ + char *buf = NULL; + struct dl_action_result *result; + +# ifdef SHARED + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dlerror (); +# endif + + /* If we have not yet initialized the buffer do it now. */ + __libc_once (once, init); + + /* Get error string. */ + result = (struct dl_action_result *) __libc_getspecific (key); + if (result == NULL) + result = &last_result; + + /* Test whether we already returned the string. */ + if (result->returned != 0) + { + /* We can now free the string. */ + if (result->errstring != NULL) + { + if (strcmp (result->errstring, "out of memory") != 0) + free ((char *) result->errstring); + result->errstring = NULL; + } + } + else if (result->errstring != NULL) + { + buf = (char *) result->errstring; + int n; + if (result->errcode == 0) + n = __asprintf (&buf, "%s%s%s", + result->objname, + result->objname[0] == '\0' ? "" : ": ", + _(result->errstring)); + else + n = __asprintf (&buf, "%s%s%s: %s", + result->objname, + result->objname[0] == '\0' ? "" : ": ", + _(result->errstring), + strerror (result->errcode)); + if (n != -1) + { + /* We don't need the error string anymore. */ + if (strcmp (result->errstring, "out of memory") != 0) + free ((char *) result->errstring); + result->errstring = buf; + } + + /* Mark the error as returned. */ + result->returned = 1; + } + + return buf; +} +# ifdef SHARED +strong_alias (__dlerror, dlerror) +# endif + +int +internal_function +_dlerror_run (void (*operate) (void *), void *args) +{ + struct dl_action_result *result; + + /* If we have not yet initialized the buffer do it now. */ + __libc_once (once, init); + + /* Get error string and number. */ + if (static_buf != NULL) + result = static_buf; + else + { + /* We don't use the static buffer and so we have a key. Use it + to get the thread-specific buffer. */ + result = __libc_getspecific (key); + if (result == NULL) + { + result = (struct dl_action_result *) calloc (1, sizeof (*result)); + if (result == NULL) + /* We are out of memory. Since this is no really critical + situation we carry on by using the global variable. + This might lead to conflicts between the threads but + they soon all will have memory problems. */ + result = &last_result; + else + /* Set the tsd. */ + __libc_setspecific (key, result); + } + } + + if (result->errstring != NULL) + { + /* Free the error string from the last failed command. This can + happen if `dlerror' was not run after an error was found. */ + if (result->malloced) + free ((char *) result->errstring); + result->errstring = NULL; + } + + result->errcode = _dl_catch_error (&result->objname, &result->errstring, + &result->malloced, operate, args); + + /* If no error we mark that no error string is available. */ + result->returned = result->errstring == NULL; + + return result->errstring != NULL; +} + + +/* Initialize buffers for results. */ +static void +init (void) +{ + if (__libc_key_create (&key, free_key_mem)) + /* Creating the key failed. This means something really went + wrong. In any case use a static buffer which is better than + nothing. */ + static_buf = &last_result; +} + + +static void +check_free (struct dl_action_result *rec) +{ + if (rec->errstring != NULL + && strcmp (rec->errstring, "out of memory") != 0) + { + /* We can free the string only if the allocation happened in the + C library used by the dynamic linker. This means, it is + always the C library in the base namespace. When we're statically + linked, the dynamic linker is part of the program and so always + uses the same C library we use here. */ +#ifdef SHARED + struct link_map *map = NULL; + Dl_info info; + if (_dl_addr (check_free, &info, &map, NULL) != 0 && map->l_ns == 0) +#endif + free ((char *) rec->errstring); + } +} + + +static void +__attribute__ ((destructor)) +fini (void) +{ + check_free (&last_result); +} + + +/* Free the thread specific data, this is done if a thread terminates. */ +static void +free_key_mem (void *mem) +{ + check_free ((struct dl_action_result *) mem); + + free (mem); + __libc_setspecific (key, NULL); +} + +# ifdef SHARED + +struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon)); +libdl_hidden_data_def (_dlfcn_hook) + +# else + +static struct dlfcn_hook _dlfcn_hooks = + { + .dlopen = __dlopen, + .dlclose = __dlclose, + .dlsym = __dlsym, + .dlvsym = __dlvsym, + .dlerror = __dlerror, + .dladdr = __dladdr, + .dladdr1 = __dladdr1, + .dlinfo = __dlinfo, + .dlmopen = __dlmopen + }; + +void +__libc_register_dlfcn_hook (struct link_map *map) +{ + struct dlfcn_hook **hook; + + hook = (struct dlfcn_hook **) __libc_dlsym_private (map, "_dlfcn_hook"); + if (hook != NULL) + *hook = &_dlfcn_hooks; +} +# endif +#endif diff --git a/REORG.TODO/dlfcn/dlfcn.c b/REORG.TODO/dlfcn/dlfcn.c new file mode 100644 index 0000000000..c2bcacdfa6 --- /dev/null +++ b/REORG.TODO/dlfcn/dlfcn.c @@ -0,0 +1,38 @@ +/* Load a shared object at run time. + Copyright (C) 2005-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> + + +int __dlfcn_argc attribute_hidden; +char **__dlfcn_argv attribute_hidden; + + +static void +init (int argc, char *argv[]) +{ + __dlfcn_argc = argc; + __dlfcn_argv = argv; +} + +static void (*const init_array []) (int argc, char *argv[]) + __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) + __attribute_used__ = +{ + init +}; diff --git a/REORG.TODO/dlfcn/dlfcn.h b/REORG.TODO/dlfcn/dlfcn.h new file mode 100644 index 0000000000..b89dc12dc2 --- /dev/null +++ b/REORG.TODO/dlfcn/dlfcn.h @@ -0,0 +1,190 @@ +/* User functions for run-time dynamic loading. + Copyright (C) 1995-2017 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 + <http://www.gnu.org/licenses/>. */ + +#ifndef _DLFCN_H +#define _DLFCN_H 1 + +#include <features.h> +#define __need_size_t +#include <stddef.h> + +/* Collect various system dependent definitions and declarations. */ +#include <bits/dlfcn.h> + + +#ifdef __USE_GNU +/* If the first argument of `dlsym' or `dlvsym' is set to RTLD_NEXT + the run-time address of the symbol called NAME in the next shared + object is returned. The "next" relation is defined by the order + the shared objects were loaded. */ +# define RTLD_NEXT ((void *) -1l) + +/* If the first argument to `dlsym' or `dlvsym' is set to RTLD_DEFAULT + the run-time address of the symbol called NAME in the global scope + is returned. */ +# define RTLD_DEFAULT ((void *) 0) + + +/* Type for namespace indeces. */ +typedef long int Lmid_t; + +/* Special namespace ID values. */ +# define LM_ID_BASE 0 /* Initial namespace. */ +# define LM_ID_NEWLM -1 /* For dlmopen: request new namespace. */ +#endif + + +__BEGIN_DECLS + +/* Open the shared object FILE and map it in; return a handle that can be + passed to `dlsym' to get symbol values from it. */ +extern void *dlopen (const char *__file, int __mode) __THROWNL; + +/* Unmap and close a shared object opened by `dlopen'. + The handle cannot be used again after calling `dlclose'. */ +extern int dlclose (void *__handle) __THROWNL __nonnull ((1)); + +/* Find the run-time address in the shared object HANDLE refers to + of the symbol called NAME. */ +extern void *dlsym (void *__restrict __handle, + const char *__restrict __name) __THROW __nonnull ((2)); + +#ifdef __USE_GNU +/* Like `dlopen', but request object to be allocated in a new namespace. */ +extern void *dlmopen (Lmid_t __nsid, const char *__file, int __mode) __THROWNL; + +/* Find the run-time address in the shared object HANDLE refers to + of the symbol called NAME with VERSION. */ +extern void *dlvsym (void *__restrict __handle, + const char *__restrict __name, + const char *__restrict __version) + __THROW __nonnull ((2, 3)); +#endif + +/* When any of the above functions fails, call this function + to return a string describing the error. Each call resets + the error string so that a following call returns null. */ +extern char *dlerror (void) __THROW; + + +#ifdef __USE_GNU +/* Structure containing information about object searched using + `dladdr'. */ +typedef struct +{ + const char *dli_fname; /* File name of defining object. */ + void *dli_fbase; /* Load address of that object. */ + const char *dli_sname; /* Name of nearest symbol. */ + void *dli_saddr; /* Exact value of nearest symbol. */ +} Dl_info; + +/* Fill in *INFO with the following information about ADDRESS. + Returns 0 iff no shared object's segments contain that address. */ +extern int dladdr (const void *__address, Dl_info *__info) + __THROW __nonnull ((2)); + +/* Same as `dladdr', but additionally sets *EXTRA_INFO according to FLAGS. */ +extern int dladdr1 (const void *__address, Dl_info *__info, + void **__extra_info, int __flags) __THROW __nonnull ((2)); + +/* These are the possible values for the FLAGS argument to `dladdr1'. + This indicates what extra information is stored at *EXTRA_INFO. + It may also be zero, in which case the EXTRA_INFO argument is not used. */ +enum + { + /* Matching symbol table entry (const ElfNN_Sym *). */ + RTLD_DL_SYMENT = 1, + + /* The object containing the address (struct link_map *). */ + RTLD_DL_LINKMAP = 2 + }; + + +/* Get information about the shared object HANDLE refers to. + REQUEST is from among the values below, and determines the use of ARG. + + On success, returns zero. On failure, returns -1 and records an error + message to be fetched with `dlerror'. */ +extern int dlinfo (void *__restrict __handle, + int __request, void *__restrict __arg) + __THROW __nonnull ((1, 3)); + +/* These are the possible values for the REQUEST argument to `dlinfo'. */ +enum + { + /* Treat ARG as `lmid_t *'; store namespace ID for HANDLE there. */ + RTLD_DI_LMID = 1, + + /* Treat ARG as `struct link_map **'; + store the `struct link_map *' for HANDLE there. */ + RTLD_DI_LINKMAP = 2, + + RTLD_DI_CONFIGADDR = 3, /* Unsupported, defined by Solaris. */ + + /* Treat ARG as `Dl_serinfo *' (see below), and fill in to describe the + directories that will be searched for dependencies of this object. + RTLD_DI_SERINFOSIZE fills in just the `dls_cnt' and `dls_size' + entries to indicate the size of the buffer that must be passed to + RTLD_DI_SERINFO to fill in the full information. */ + RTLD_DI_SERINFO = 4, + RTLD_DI_SERINFOSIZE = 5, + + /* Treat ARG as `char *', and store there the directory name used to + expand $ORIGIN in this shared object's dependency file names. */ + RTLD_DI_ORIGIN = 6, + + RTLD_DI_PROFILENAME = 7, /* Unsupported, defined by Solaris. */ + RTLD_DI_PROFILEOUT = 8, /* Unsupported, defined by Solaris. */ + + /* Treat ARG as `size_t *', and store there the TLS module ID + of this object's PT_TLS segment, as used in TLS relocations; + store zero if this object does not define a PT_TLS segment. */ + RTLD_DI_TLS_MODID = 9, + + /* Treat ARG as `void **', and store there a pointer to the calling + thread's TLS block corresponding to this object's PT_TLS segment. + Store a null pointer if this object does not define a PT_TLS + segment, or if the calling thread has not allocated a block for it. */ + RTLD_DI_TLS_DATA = 10, + + RTLD_DI_MAX = 10 + }; + + +/* This is the type of elements in `Dl_serinfo', below. + The `dls_name' member points to space in the buffer passed to `dlinfo'. */ +typedef struct +{ + char *dls_name; /* Name of library search path directory. */ + unsigned int dls_flags; /* Indicates where this directory came from. */ +} Dl_serpath; + +/* This is the structure that must be passed (by reference) to `dlinfo' for + the RTLD_DI_SERINFO and RTLD_DI_SERINFOSIZE requests. */ +typedef struct +{ + size_t dls_size; /* Size in bytes of the whole buffer. */ + unsigned int dls_cnt; /* Number of elements in `dls_serpath'. */ + Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */ +} Dl_serinfo; +#endif /* __USE_GNU */ + + +__END_DECLS + +#endif /* dlfcn.h */ diff --git a/REORG.TODO/dlfcn/dlinfo.c b/REORG.TODO/dlfcn/dlinfo.c new file mode 100644 index 0000000000..a34e947ed3 --- /dev/null +++ b/REORG.TODO/dlfcn/dlinfo.c @@ -0,0 +1,126 @@ +/* dlinfo -- Get information from the dynamic linker. + Copyright (C) 2003-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <link.h> +#include <ldsodefs.h> +#include <libintl.h> + +#if !defined SHARED && IS_IN (libdl) + +int +dlinfo (void *handle, int request, void *arg) +{ + return __dlinfo (handle, request, arg, RETURN_ADDRESS (0)); +} + +#else + +# include <dl-tls.h> + +struct dlinfo_args +{ + ElfW(Addr) caller; + void *handle; + int request; + void *arg; +}; + +static void +dlinfo_doit (void *argsblock) +{ + struct dlinfo_args *const args = argsblock; + struct link_map *l = args->handle; + +# if 0 + if (args->handle == RTLD_SELF) + { + Lmid_t nsid; + + /* Find the highest-addressed object that CALLER is not below. */ + for (nsid = 0; nsid < DL_NNS; ++nsid) + for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next) + if (caller >= l->l_map_start && caller < l->l_map_end + && (l->l_contiguous || _dl_addr_inside_object (l, caller))) + break; + + if (l == NULL) + _dl_signal_error (0, NULL, NULL, N_("\ +RTLD_SELF used in code not dynamically loaded")); + } +# endif + + switch (args->request) + { + case RTLD_DI_CONFIGADDR: + default: + _dl_signal_error (0, NULL, NULL, N_("unsupported dlinfo request")); + break; + + case RTLD_DI_LMID: + *(Lmid_t *) args->arg = l->l_ns; + break; + + case RTLD_DI_LINKMAP: + *(struct link_map **) args->arg = l; + break; + + case RTLD_DI_SERINFO: + _dl_rtld_di_serinfo (l, args->arg, false); + break; + case RTLD_DI_SERINFOSIZE: + _dl_rtld_di_serinfo (l, args->arg, true); + break; + + case RTLD_DI_ORIGIN: + strcpy (args->arg, l->l_origin); + break; + + case RTLD_DI_TLS_MODID: + *(size_t *) args->arg = 0; + *(size_t *) args->arg = l->l_tls_modid; + break; + + case RTLD_DI_TLS_DATA: + { + void *data = NULL; + if (l->l_tls_modid != 0) + data = GLRO(dl_tls_get_addr_soft) (l); + *(void **) args->arg = data; + break; + } + } +} + +int +__dlinfo (void *handle, int request, void *arg DL_CALLER_DECL) +{ +# ifdef SHARED + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dlinfo (handle, request, arg, + DL_CALLER); +# endif + + struct dlinfo_args args = { (ElfW(Addr)) DL_CALLER, + handle, request, arg }; + return _dlerror_run (&dlinfo_doit, &args) ? -1 : 0; +} +# ifdef SHARED +strong_alias (__dlinfo, dlinfo) +# endif +#endif diff --git a/REORG.TODO/dlfcn/dlmopen.c b/REORG.TODO/dlfcn/dlmopen.c new file mode 100644 index 0000000000..07d59ade30 --- /dev/null +++ b/REORG.TODO/dlfcn/dlmopen.c @@ -0,0 +1,107 @@ +/* Load a shared object at run time. + Copyright (C) 1995-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <errno.h> +#include <libintl.h> +#include <stddef.h> +#include <unistd.h> +#include <ldsodefs.h> + +#if !defined SHARED && IS_IN (libdl) + +void * +dlmopen (Lmid_t nsid, const char *file, int mode) +{ + return __dlmopen (nsid, file, mode, RETURN_ADDRESS (0)); +} +static_link_warning (dlmopen) + +#else + +struct dlmopen_args +{ + /* Namespace ID. */ + Lmid_t nsid; + /* The arguments for dlopen_doit. */ + const char *file; + int mode; + /* The return value of dlopen_doit. */ + void *new; + /* Address of the caller. */ + const void *caller; +}; + +static void +dlmopen_doit (void *a) +{ + struct dlmopen_args *args = (struct dlmopen_args *) a; + + /* Non-shared code has no support for multiple namespaces. */ + if (args->nsid != LM_ID_BASE) + { +# ifdef SHARED + /* If trying to open the link map for the main executable the namespace + must be the main one. */ + if (args->file == NULL) +# endif + _dl_signal_error (EINVAL, NULL, NULL, N_("invalid namespace")); + + /* It makes no sense to use RTLD_GLOBAL when loading a DSO into + a namespace other than the base namespace. */ + if (__glibc_unlikely (args->mode & RTLD_GLOBAL)) + _dl_signal_error (EINVAL, NULL, NULL, N_("invalid mode")); + } + + args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN, + args->caller, + args->nsid, __dlfcn_argc, __dlfcn_argv, + __environ); +} + + +void * +__dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL) +{ +# ifdef SHARED + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dlmopen (nsid, file, mode, RETURN_ADDRESS (0)); +# endif + + struct dlmopen_args args; + args.nsid = nsid; + args.file = file; + args.mode = mode; + args.caller = DL_CALLER; + +# ifdef SHARED + return _dlerror_run (dlmopen_doit, &args) ? NULL : args.new; +# else + if (_dlerror_run (dlmopen_doit, &args)) + return NULL; + + __libc_register_dl_open_hook ((struct link_map *) args.new); + __libc_register_dlfcn_hook ((struct link_map *) args.new); + + return args.new; +# endif +} +# ifdef SHARED +strong_alias (__dlmopen, dlmopen) +# endif +#endif diff --git a/REORG.TODO/dlfcn/dlopen.c b/REORG.TODO/dlfcn/dlopen.c new file mode 100644 index 0000000000..22120655d2 --- /dev/null +++ b/REORG.TODO/dlfcn/dlopen.c @@ -0,0 +1,103 @@ +/* Load a shared object at run time. + Copyright (C) 1995-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <libintl.h> +#include <stddef.h> +#include <unistd.h> +#include <ldsodefs.h> + +#if !defined SHARED && IS_IN (libdl) + +void * +dlopen (const char *file, int mode) +{ + return __dlopen (file, mode, RETURN_ADDRESS (0)); +} +static_link_warning (dlopen) + +#else + +struct dlopen_args +{ + /* The arguments for dlopen_doit. */ + const char *file; + int mode; + /* The return value of dlopen_doit. */ + void *new; + /* Address of the caller. */ + const void *caller; +}; + + +/* Non-shared code has no support for multiple namespaces. */ +# ifdef SHARED +# define NS __LM_ID_CALLER +# else +# define NS LM_ID_BASE +# endif + + +static void +dlopen_doit (void *a) +{ + struct dlopen_args *args = (struct dlopen_args *) a; + + if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND + | RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE + | __RTLD_SPROF)) + _dl_signal_error (0, NULL, NULL, _("invalid mode parameter")); + + args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN, + args->caller, + args->file == NULL ? LM_ID_BASE : NS, + __dlfcn_argc, __dlfcn_argv, __environ); +} + + +void * +__dlopen (const char *file, int mode DL_CALLER_DECL) +{ +# ifdef SHARED + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dlopen (file, mode, DL_CALLER); +# endif + + struct dlopen_args args; + args.file = file; + args.mode = mode; + args.caller = DL_CALLER; + +# ifdef SHARED + return _dlerror_run (dlopen_doit, &args) ? NULL : args.new; +# else + if (_dlerror_run (dlopen_doit, &args)) + return NULL; + + __libc_register_dl_open_hook ((struct link_map *) args.new); + __libc_register_dlfcn_hook ((struct link_map *) args.new); + + return args.new; +# endif +} +# ifdef SHARED +# include <shlib-compat.h> +strong_alias (__dlopen, __dlopen_check) +versioned_symbol (libdl, __dlopen_check, dlopen, GLIBC_2_1); +# endif +#endif diff --git a/REORG.TODO/dlfcn/dlopenold.c b/REORG.TODO/dlfcn/dlopenold.c new file mode 100644 index 0000000000..a3db500705 --- /dev/null +++ b/REORG.TODO/dlfcn/dlopenold.c @@ -0,0 +1,79 @@ +/* Load a shared object at run time. + Copyright (C) 1995-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stddef.h> +#include <unistd.h> +#include <ldsodefs.h> + +/* This file is for compatibility with glibc 2.0. Compile it only if + versioning is used. */ +#include <shlib-compat.h> +#if SHLIB_COMPAT (libdl, GLIBC_2_0, GLIBC_2_1) + +struct dlopen_args +{ + /* The arguments for dlopen_doit. */ + const char *file; + int mode; + /* The return value of dlopen_doit. */ + void *new; + /* Address of the caller. */ + const void *caller; +}; + + +/* Non-shared code has no support for multiple namespaces. */ +#ifdef SHARED +# define NS __LM_ID_CALLER +#else +# define NS LM_ID_BASE +#endif + + +static void +dlopen_doit (void *a) +{ + struct dlopen_args *args = (struct dlopen_args *) a; + + args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN, + args->caller, + args->file == NULL ? LM_ID_BASE : NS, + __dlfcn_argc, __dlfcn_argv, __environ); +} + +extern void *__dlopen_nocheck (const char *file, int mode); +void * +__dlopen_nocheck (const char *file, int mode) +{ + struct dlopen_args args; + args.file = file; + args.caller = RETURN_ADDRESS (0); + + if ((mode & RTLD_BINDING_MASK) == 0) + /* By default assume RTLD_LAZY. */ + mode |= RTLD_LAZY; + args.mode = mode; + + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dlopen (file, mode, RETURN_ADDRESS (0)); + + return _dlerror_run (dlopen_doit, &args) ? NULL : args.new; +} +compat_symbol (libdl, __dlopen_nocheck, dlopen, GLIBC_2_0); +#endif diff --git a/REORG.TODO/dlfcn/dlsym.c b/REORG.TODO/dlfcn/dlsym.c new file mode 100644 index 0000000000..7976c5f75c --- /dev/null +++ b/REORG.TODO/dlfcn/dlsym.c @@ -0,0 +1,79 @@ +/* Look up a symbol in a shared object loaded by `dlopen'. + Copyright (C) 1995-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stddef.h> + +#include <ldsodefs.h> + +#if !defined SHARED && IS_IN (libdl) + +void * +dlsym (void *handle, const char *name) +{ + return __dlsym (handle, name, RETURN_ADDRESS (0)); +} + +#else + +struct dlsym_args +{ + /* The arguments to dlsym_doit. */ + void *handle; + const char *name; + void *who; + + /* The return value of dlsym_doit. */ + void *sym; +}; + +static void +dlsym_doit (void *a) +{ + struct dlsym_args *args = (struct dlsym_args *) a; + + args->sym = _dl_sym (args->handle, args->name, args->who); +} + + +void * +__dlsym (void *handle, const char *name DL_CALLER_DECL) +{ +# ifdef SHARED + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dlsym (handle, name, DL_CALLER); +# endif + + struct dlsym_args args; + args.who = DL_CALLER; + args.handle = handle; + args.name = name; + + /* Protect against concurrent loads and unloads. */ + __rtld_lock_lock_recursive (GL(dl_load_lock)); + + void *result = (_dlerror_run (dlsym_doit, &args) ? NULL : args.sym); + + __rtld_lock_unlock_recursive (GL(dl_load_lock)); + + return result; +} +# ifdef SHARED +strong_alias (__dlsym, dlsym) +# endif +#endif diff --git a/REORG.TODO/dlfcn/dlvsym.c b/REORG.TODO/dlfcn/dlvsym.c new file mode 100644 index 0000000000..5ed220b77c --- /dev/null +++ b/REORG.TODO/dlfcn/dlvsym.c @@ -0,0 +1,83 @@ +/* Look up a versioned symbol in a shared object loaded by `dlopen'. + Copyright (C) 1995-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stddef.h> + +#include <ldsodefs.h> + +#if !defined SHARED && IS_IN (libdl) + +void * +weak_function +dlvsym (void *handle, const char *name, const char *version_str) +{ + return __dlvsym (handle, name, version_str, RETURN_ADDRESS (0)); +} + +#else + +struct dlvsym_args +{ + /* The arguments to dlvsym_doit. */ + void *handle; + const char *name; + const char *version; + void *who; + + /* The return values of dlvsym_doit. */ + void *sym; +}; + + +static void +dlvsym_doit (void *a) +{ + struct dlvsym_args *args = (struct dlvsym_args *)a; + + args->sym = _dl_vsym (args->handle, args->name, args->version, args->who); +} + +void * +__dlvsym (void *handle, const char *name, const char *version_str + DL_CALLER_DECL) +{ +# ifdef SHARED + if (__glibc_unlikely (_dlfcn_hook != NULL)) + return _dlfcn_hook->dlvsym (handle, name, version_str, DL_CALLER); +# endif + + struct dlvsym_args args; + args.handle = handle; + args.name = name; + args.who = DL_CALLER; + args.version = version_str; + + /* Protect against concurrent loads and unloads. */ + __rtld_lock_lock_recursive (GL(dl_load_lock)); + + void *result = (_dlerror_run (dlvsym_doit, &args) ? NULL : args.sym); + + __rtld_lock_unlock_recursive (GL(dl_load_lock)); + + return result; +} +# ifdef SHARED +weak_alias (__dlvsym, dlvsym) +# endif +#endif diff --git a/REORG.TODO/dlfcn/errmsg1.c b/REORG.TODO/dlfcn/errmsg1.c new file mode 100644 index 0000000000..9574ca5393 --- /dev/null +++ b/REORG.TODO/dlfcn/errmsg1.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2000-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int +main (void) +{ + void *h; + const char *s; + + /* Test that dlerror works initially. */ + s = dlerror (); + printf ("dlerror() without prior dl*() call returned: %s\n", s); + if (s != NULL) + return 1; + + h = dlopen ("errmsg1mod.so", RTLD_NOW); + if (h != NULL) + { + dlclose (h); + puts ("errmsg1mod.so could be loaded !?"); + exit (1); + } + + s = dlerror (); + puts (s); + + return strstr (s, "errmsg1mod.so") == NULL; +} diff --git a/REORG.TODO/dlfcn/errmsg1mod.c b/REORG.TODO/dlfcn/errmsg1mod.c new file mode 100644 index 0000000000..f80b07fd15 --- /dev/null +++ b/REORG.TODO/dlfcn/errmsg1mod.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2000-2017 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 + <http://www.gnu.org/licenses/>. */ + +extern int bar (void); +extern int foo (void); + +int +foo (void) +{ + return bar (); +} diff --git a/REORG.TODO/dlfcn/failtest.c b/REORG.TODO/dlfcn/failtest.c new file mode 100644 index 0000000000..e0ac4ef638 --- /dev/null +++ b/REORG.TODO/dlfcn/failtest.c @@ -0,0 +1,60 @@ +#include <dlfcn.h> +#include <stdio.h> + + +/* Number of rounds we perform the test. */ +#define TEST_ROUNDS 10 + + +static const char unknown[] = "a-file-with-this-name-does-not-exist"; +static const char exists[] = "failtestmod.so"; + + +int +main (void) +{ + int i; + + setvbuf (stdout, NULL, _IONBF, 0); + + for (i = 0; i < TEST_ROUNDS; ++i) + { + void *dsc; + + printf ("Round %d: Try loading \"%s\"\n", i, unknown); + + dsc = dlopen (unknown, RTLD_NOW); + if (dsc != NULL) + { + printf ("We found a file of name \"%s\": this should not happen\n", + unknown); + return 1; + } + + printf ("Round %d: loading \"%s\" failed\n", i, unknown); + + /* Don't use `dlerror', just load an existing file. */ + dsc = dlopen (exists, RTLD_NOW); + if (dsc == NULL) + { + printf ("Could not load \"%s\": %s\n", exists, dlerror ()); + return 1; + } + + printf ("Round %d: Loaded \"%s\"\n", i, exists); + + dlclose (dsc); + + printf ("Round %d: Unloaded \"%s\"\n", i, exists); + } + + return 0; +} + + +extern void foo (void); + +void +foo (void) +{ +} diff --git a/REORG.TODO/dlfcn/failtestmod.c b/REORG.TODO/dlfcn/failtestmod.c new file mode 100644 index 0000000000..64dadd53ff --- /dev/null +++ b/REORG.TODO/dlfcn/failtestmod.c @@ -0,0 +1,25 @@ +#include <dlfcn.h> +#include <stdio.h> + + +extern void constr (void) __attribute__ ((__constructor__)); +void +__attribute__ ((__constructor__)) +constr (void) +{ + void *handle; + + /* Open the library. */ + handle = dlopen (NULL, RTLD_NOW); + if (handle == NULL) + { + puts ("Cannot get handle to own object"); + return; + } + + /* Get a symbol. */ + dlsym (handle, "main"); + puts ("called dlsym() to get main"); + + dlclose (handle); +} diff --git a/REORG.TODO/dlfcn/glreflib1.c b/REORG.TODO/dlfcn/glreflib1.c new file mode 100644 index 0000000000..bb0193eb0e --- /dev/null +++ b/REORG.TODO/dlfcn/glreflib1.c @@ -0,0 +1,24 @@ +/* Test for dependency tracking added by relocations. + Copyright (C) 2000-2017 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 + <http://www.gnu.org/licenses/>. */ + +extern int ref1 (void); +int +ref1 (void) +{ + return 42; +} diff --git a/REORG.TODO/dlfcn/glreflib2.c b/REORG.TODO/dlfcn/glreflib2.c new file mode 100644 index 0000000000..5aed80cda1 --- /dev/null +++ b/REORG.TODO/dlfcn/glreflib2.c @@ -0,0 +1,26 @@ +/* Test for dependency tracking added by relocations. + Copyright (C) 2000-2017 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 + <http://www.gnu.org/licenses/>. */ + +extern int ref1 (void); + +extern int ref2 (void); +int +ref2 (void) +{ + return ref1 (); +} diff --git a/REORG.TODO/dlfcn/glreflib3.c b/REORG.TODO/dlfcn/glreflib3.c new file mode 100644 index 0000000000..5ac7befa6b --- /dev/null +++ b/REORG.TODO/dlfcn/glreflib3.c @@ -0,0 +1 @@ +#include "glreflib1.c" diff --git a/REORG.TODO/dlfcn/glrefmain.c b/REORG.TODO/dlfcn/glrefmain.c new file mode 100644 index 0000000000..d581031f00 --- /dev/null +++ b/REORG.TODO/dlfcn/glrefmain.c @@ -0,0 +1,80 @@ +/* Test for dependency tracking added by relocations. + Copyright (C) 2000-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <error.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + + +static void * +load (const char *name) +{ + void *d = dlopen (name, RTLD_LAZY | RTLD_GLOBAL); + if (d == NULL) + error (EXIT_FAILURE, errno, "cannot load `%s'", name); + return d; +} + + +#define TEST_FUNCTION do_test () +extern int do_test (void); + +int +do_test (void) +{ + void *d1; + void *d2; + int (*f) (void); + + d1 = load ("glreflib1.so"); + d2 = load ("glreflib2.so"); + + f = dlsym (d2, "ref2"); + if (f == NULL) + error (EXIT_FAILURE, errno, "cannot get pointer to `%s'", "ref2"); + + if (f () != 42) + error (EXIT_FAILURE, 0, "wrong result from `%s'", "ref2"); + + puts ("Correct result in first call"); + fflush (stdout); + + /* Now unload the first file. */ + dlclose (d1); + + puts ("About to call the second time"); + fflush (stdout); + + /* Try calling the function again. */ + if (f () != 42) + error (EXIT_FAILURE, 0, "wrong result from `%s' (second call)", "ref2"); + + puts ("Second call succeeded!"); + fflush (stdout); + + dlclose (d2); + + puts ("glreflib2 also closed"); + fflush (stdout); + + return 0; +} + +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/modatexit.c b/REORG.TODO/dlfcn/modatexit.c new file mode 100644 index 0000000000..e620d10c70 --- /dev/null +++ b/REORG.TODO/dlfcn/modatexit.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2001-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> + +int global; +int *ip; + +extern void dummy (void); +extern void foo (void *p); + +void +dummy (void) +{ + printf ("This is %s\n", __FUNCTION__); + *ip = global = 1; +} + + +void +foo (void *p) +{ + extern void *__dso_handle __attribute__ ((__weak__)); + printf ("This is %s\n", __FUNCTION__); + atexit (dummy); + if (&__dso_handle) puts ("have dso handle"); else puts ("no dso handle"); + ip = p; +} diff --git a/REORG.TODO/dlfcn/modcxaatexit.c b/REORG.TODO/dlfcn/modcxaatexit.c new file mode 100644 index 0000000000..fbda2f3c9f --- /dev/null +++ b/REORG.TODO/dlfcn/modcxaatexit.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2001-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> + +extern void fluffy (void *p); +extern void bar (void *p); + +int global; + +void +fluffy (void *p) +{ + printf ("This is %s\n", __FUNCTION__); + *(int *) p = global = 1; +} + + +void +bar (void *p) +{ + extern void *__dso_handle; + printf ("This is %s\n", __FUNCTION__); + __cxa_atexit (fluffy, p, __dso_handle); +} diff --git a/REORG.TODO/dlfcn/moddummy1.c b/REORG.TODO/dlfcn/moddummy1.c new file mode 100644 index 0000000000..6e549fa7d2 --- /dev/null +++ b/REORG.TODO/dlfcn/moddummy1.c @@ -0,0 +1,10 @@ +/* Provide a dummy DSO for tst-rec-dlopen to use. */ +#include <stdio.h> +#include <stdlib.h> + +int +dummy1 (void) +{ + printf ("Called dummy1()\n"); + return 1; +} diff --git a/REORG.TODO/dlfcn/moddummy2.c b/REORG.TODO/dlfcn/moddummy2.c new file mode 100644 index 0000000000..cb4edc8da7 --- /dev/null +++ b/REORG.TODO/dlfcn/moddummy2.c @@ -0,0 +1,13 @@ +/* Provide a dummy DSO for tst-rec-dlopen to use. */ +#include <stdio.h> +#include <stdlib.h> + +int +dummy2 (void) +{ + printf ("Called dummy2()\n"); + /* If the outer dlopen is not dummy1 (becuase of some error) + then tst-rec-dlopen will see a value of -1 as the returned + result and fail. */ + return -1; +} diff --git a/REORG.TODO/dlfcn/modstatic.c b/REORG.TODO/dlfcn/modstatic.c new file mode 100644 index 0000000000..5ea71171cf --- /dev/null +++ b/REORG.TODO/dlfcn/modstatic.c @@ -0,0 +1,7 @@ +extern int test (int); + +int +test (int a) +{ + return a + a; +} diff --git a/REORG.TODO/dlfcn/modstatic2.c b/REORG.TODO/dlfcn/modstatic2.c new file mode 100644 index 0000000000..9b5aae8b9f --- /dev/null +++ b/REORG.TODO/dlfcn/modstatic2.c @@ -0,0 +1,226 @@ +#include <dlfcn.h> +#include <link.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <gnu/lib-names.h> + +int test (FILE *out, int a); + +int +test (FILE *out, int a) +{ + fputs ("in modstatic2.c (test)\n", out); + + void *handle = dlopen ("modstatic2-nonexistent.so", RTLD_LAZY); + if (handle == NULL) + fprintf (out, "nonexistent: %s\n", dlerror ()); + else + exit (1); + + handle = dlopen ("modstatic2.so", RTLD_LAZY); + if (handle == NULL) + { + fprintf (out, "%s\n", dlerror ()); + exit (1); + } + + int (*test2) (FILE *, int); + test2 = dlsym (handle, "test"); + if (test2 == NULL) + { + fprintf (out, "%s\n", dlerror ()); + exit (1); + } + if (test2 != test) + { + fprintf (out, "test %p != test2 %p\n", test, test2); + exit (1); + } + + Dl_info info; + int res = dladdr (test2, &info); + if (res == 0) + { + fputs ("dladdr returned 0\n", out); + exit (1); + } + else + { + if (strstr (info.dli_fname, "modstatic2.so") == NULL + || strcmp (info.dli_sname, "test") != 0) + { + fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname); + exit (1); + } + if (info.dli_saddr != (void *) test2) + { + fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test2); + exit (1); + } + } + + ElfW(Sym) *sym; + void *symp; + res = dladdr1 (test2, &info, &symp, RTLD_DL_SYMENT); + if (res == 0) + { + fputs ("dladdr1 returned 0\n", out); + exit (1); + } + else + { + if (strstr (info.dli_fname, "modstatic2.so") == NULL + || strcmp (info.dli_sname, "test") != 0) + { + fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname); + exit (1); + } + if (info.dli_saddr != (void *) test2) + { + fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test2); + exit (1); + } + sym = symp; + if (sym == NULL) + { + fputs ("sym == NULL\n", out); + exit (1); + } + if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL + || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT) + { + fprintf (out, "bind %d visibility %d\n", + (int) ELF32_ST_BIND (sym->st_info), + (int) ELF32_ST_VISIBILITY (sym->st_other)); + exit (1); + } + } + + Lmid_t lmid; + res = dlinfo (handle, RTLD_DI_LMID, &lmid); + if (res != 0) + { + fprintf (out, "dlinfo returned %d %s\n", res, dlerror ()); + exit (1); + } + else if (lmid != LM_ID_BASE) + { + fprintf (out, "lmid %d != %d\n", (int) lmid, (int) LM_ID_BASE); + exit (1); + } + + void *handle2 = dlopen (LIBDL_SO, RTLD_LAZY); + if (handle2 == NULL) + { + fprintf (out, "libdl.so: %s\n", dlerror ()); + exit (1); + } + + if (dlvsym (handle2, "_dlfcn_hook", "GLIBC_PRIVATE") == NULL) + { + fprintf (out, "dlvsym: %s\n", dlerror ()); + exit (1); + } + + void *(*dlsymfn) (void *, const char *); + dlsymfn = dlsym (handle2, "dlsym"); + if (dlsymfn == NULL) + { + fprintf (out, "dlsym \"dlsym\": %s\n", dlerror ()); + exit (1); + } + void *test3 = dlsymfn (handle, "test"); + if (test3 == NULL) + { + fprintf (out, "%s\n", dlerror ()); + exit (1); + } + else if (test3 != (void *) test2) + { + fprintf (out, "test2 %p != test3 %p\n", test2, test3); + exit (1); + } + + dlclose (handle2); + dlclose (handle); + + handle = dlmopen (LM_ID_BASE, "modstatic2.so", RTLD_LAZY); + if (handle == NULL) + { + fprintf (out, "%s\n", dlerror ()); + exit (1); + } + dlclose (handle); + + handle = dlmopen (LM_ID_NEWLM, "modstatic2.so", RTLD_LAZY); + if (handle == NULL) + fprintf (out, "LM_ID_NEWLM: %s\n", dlerror ()); + else + { + fputs ("LM_ID_NEWLM unexpectedly succeeded\n", out); + exit (1); + } + + handle = dlopen ("modstatic.so", RTLD_LAZY); + if (handle == NULL) + { + fprintf (out, "%s\n", dlerror ()); + exit (1); + } + + int (*test4) (int); + test4 = dlsym (handle, "test"); + if (test4 == NULL) + { + fprintf (out, "%s\n", dlerror ()); + exit (1); + } + + res = test4 (16); + if (res != 16 + 16) + { + fprintf (out, "modstatic.so (test) returned %d\n", res); + exit (1); + } + + res = dladdr1 (test4, &info, &symp, RTLD_DL_SYMENT); + if (res == 0) + { + fputs ("dladdr1 returned 0\n", out); + exit (1); + } + else + { + if (strstr (info.dli_fname, "modstatic.so") == NULL + || strcmp (info.dli_sname, "test") != 0) + { + fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname); + exit (1); + } + if (info.dli_saddr != (void *) test4) + { + fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test4); + exit (1); + } + sym = symp; + if (sym == NULL) + { + fputs ("sym == NULL\n", out); + exit (1); + } + if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL + || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT) + { + fprintf (out, "bind %d visibility %d\n", + (int) ELF32_ST_BIND (sym->st_info), + (int) ELF32_ST_VISIBILITY (sym->st_other)); + exit (1); + } + } + + dlclose (handle); + + fputs ("leaving modstatic2.c (test)\n", out); + return a + a; +} diff --git a/REORG.TODO/dlfcn/modstatic3.c b/REORG.TODO/dlfcn/modstatic3.c new file mode 100644 index 0000000000..1def09dc4f --- /dev/null +++ b/REORG.TODO/dlfcn/modstatic3.c @@ -0,0 +1,31 @@ +/* DSO used for dlopen testing with a static executable. + Copyright (C) 2013-2017 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 + <http://www.gnu.org/licenses/>. */ + +unsigned int foo; + +unsigned int +getfoo (void) +{ + return foo; +} + +void +setfoo (unsigned int f) +{ + foo = f; +} diff --git a/REORG.TODO/dlfcn/modstatic5.c b/REORG.TODO/dlfcn/modstatic5.c new file mode 100644 index 0000000000..07bd8b9964 --- /dev/null +++ b/REORG.TODO/dlfcn/modstatic5.c @@ -0,0 +1,26 @@ +/* DSO used for GLRO(dl_pagesize) initialization testing with a static + executable. + Copyright (C) 2013-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <unistd.h> + +int +my_getpagesize (void) +{ + return getpagesize (); +} diff --git a/REORG.TODO/dlfcn/sdladdr.c b/REORG.TODO/dlfcn/sdladdr.c new file mode 100644 index 0000000000..c484d63b29 --- /dev/null +++ b/REORG.TODO/dlfcn/sdladdr.c @@ -0,0 +1 @@ +#include "dladdr.c" diff --git a/REORG.TODO/dlfcn/sdladdr1.c b/REORG.TODO/dlfcn/sdladdr1.c new file mode 100644 index 0000000000..a655979bcf --- /dev/null +++ b/REORG.TODO/dlfcn/sdladdr1.c @@ -0,0 +1 @@ +#include "dladdr1.c" diff --git a/REORG.TODO/dlfcn/sdlclose.c b/REORG.TODO/dlfcn/sdlclose.c new file mode 100644 index 0000000000..dc89b98029 --- /dev/null +++ b/REORG.TODO/dlfcn/sdlclose.c @@ -0,0 +1 @@ +#include "dlclose.c" diff --git a/REORG.TODO/dlfcn/sdlerror.c b/REORG.TODO/dlfcn/sdlerror.c new file mode 100644 index 0000000000..f1226a48c5 --- /dev/null +++ b/REORG.TODO/dlfcn/sdlerror.c @@ -0,0 +1 @@ +#include "dlerror.c" diff --git a/REORG.TODO/dlfcn/sdlinfo.c b/REORG.TODO/dlfcn/sdlinfo.c new file mode 100644 index 0000000000..dcc257dd1f --- /dev/null +++ b/REORG.TODO/dlfcn/sdlinfo.c @@ -0,0 +1 @@ +#include "dlinfo.c" diff --git a/REORG.TODO/dlfcn/sdlmopen.c b/REORG.TODO/dlfcn/sdlmopen.c new file mode 100644 index 0000000000..9630c89a7f --- /dev/null +++ b/REORG.TODO/dlfcn/sdlmopen.c @@ -0,0 +1 @@ +#include "dlmopen.c" diff --git a/REORG.TODO/dlfcn/sdlopen.c b/REORG.TODO/dlfcn/sdlopen.c new file mode 100644 index 0000000000..1ff2eb2854 --- /dev/null +++ b/REORG.TODO/dlfcn/sdlopen.c @@ -0,0 +1 @@ +#include "dlopen.c" diff --git a/REORG.TODO/dlfcn/sdlsym.c b/REORG.TODO/dlfcn/sdlsym.c new file mode 100644 index 0000000000..0234f23f8f --- /dev/null +++ b/REORG.TODO/dlfcn/sdlsym.c @@ -0,0 +1 @@ +#include "dlsym.c" diff --git a/REORG.TODO/dlfcn/sdlvsym.c b/REORG.TODO/dlfcn/sdlvsym.c new file mode 100644 index 0000000000..ec4286058c --- /dev/null +++ b/REORG.TODO/dlfcn/sdlvsym.c @@ -0,0 +1 @@ +#include "dlvsym.c" diff --git a/REORG.TODO/dlfcn/tst-dladdr.c b/REORG.TODO/dlfcn/tst-dladdr.c new file mode 100644 index 0000000000..b53fe36504 --- /dev/null +++ b/REORG.TODO/dlfcn/tst-dladdr.c @@ -0,0 +1,75 @@ +/* Test for dladdr. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Volkmar Sieh <vs@caldera.de> and Andreas Jaeger <aj@suse.de>. + + 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <errno.h> +#include <error.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +#define TEST_FUNCTION do_test () +extern int do_test (void); + +int +do_test (void) +{ + void *handle; + int (*sym) (void); /* We load ref1 from glreflib1.c. */ + Dl_info info; + int ret; + + + handle = dlopen ("glreflib1.so", RTLD_NOW); + if (handle == NULL) + error (EXIT_FAILURE, 0, "cannot load: glreflib1.so"); + + sym = dlsym (handle, "ref1"); + if (sym == NULL) + error (EXIT_FAILURE, 0, "dlsym failed"); + + memset (&info, 0, sizeof (info)); + ret = dladdr (sym, &info); + + if (ret == 0) + error (EXIT_FAILURE, 0, "dladdr failed"); + + printf ("ret = %d\n", ret); + printf ("info.dli_fname = %p (\"%s\")\n", info.dli_fname, info.dli_fname); + printf ("info.dli_fbase = %p\n", info.dli_fbase); + printf ("info.dli_sname = %p (\"%s\")\n", info.dli_sname, info.dli_sname); + printf ("info.dli_saddr = %p\n", info.dli_saddr); + + if (info.dli_fname == NULL) + error (EXIT_FAILURE, 0, "dli_fname is NULL"); + if (info.dli_fbase == NULL) + error (EXIT_FAILURE, 0, "dli_fbase is NULL"); + if (info.dli_sname == NULL) + error (EXIT_FAILURE, 0, "dli_sname is NULL"); + if (info.dli_saddr == NULL) + error (EXIT_FAILURE, 0, "dli_saddr is NULL"); + + dlclose (handle); + + return 0; +} + + +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/tst-dlinfo.c b/REORG.TODO/dlfcn/tst-dlinfo.c new file mode 100644 index 0000000000..b1d240e692 --- /dev/null +++ b/REORG.TODO/dlfcn/tst-dlinfo.c @@ -0,0 +1,95 @@ +/* Test for dlinfo. + Copyright (C) 2003-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> +#include <error.h> + +#define TEST_FUNCTION do_test () + +static int +do_test (void) +{ + int status = 0; + + void *handle = dlopen ("glreflib3.so", RTLD_NOW); + if (handle == NULL) + error (EXIT_FAILURE, 0, "cannot load: glreflib1.so: %s", dlerror ()); + +#define TRY(req, arg) \ + if (dlinfo (handle, req, arg) != 0) \ + { \ + printf ("dlinfo failed for %s: %s\n", #req, dlerror ()); \ + status = 1; \ + } \ + else + + struct link_map *l; + TRY (RTLD_DI_LINKMAP, &l) + { + if (l != handle) + { + printf ("bogus link_map? %p != %p\n", l, handle); + status = 1; + } + } + + char origin[8192]; /* >= PATH_MAX, in theory */ + TRY (RTLD_DI_ORIGIN, origin) + { + printf ("origin: %s\n", origin); + } + + Dl_serinfo counts; + TRY (RTLD_DI_SERINFOSIZE, &counts) + { + Dl_serinfo *buf = alloca (counts.dls_size); + buf->dls_cnt = counts.dls_cnt; + buf->dls_size = counts.dls_size; + printf ("%u library directories\n", buf->dls_cnt); + TRY (RTLD_DI_SERINFO, buf) + { + if (counts.dls_cnt != buf->dls_cnt) + { + printf ("??? became %u library directories\n", buf->dls_cnt); + status = 1; + } + for (unsigned int i = 0; i < buf->dls_cnt; ++i) + printf ("\t%#02x\t%s\n", + buf->dls_serpath[i].dls_flags, + buf->dls_serpath[i].dls_name); + } + } + + unsigned long int lmid = 0xdeadbeefUL; + if (dlinfo (handle, RTLD_DI_LMID, &lmid) != 0) + printf ("dlinfo refuses RTLD_DI_LMID: %s\n", dlerror ()); + else + { + printf ("dlinfo RTLD_DI_LMID worked? %#lx\n", lmid); + status = lmid == 0xdeadbeefUL; + } + +#undef TRY + dlclose (handle); + + return status; +} + +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/tst-rec-dlopen.c b/REORG.TODO/dlfcn/tst-rec-dlopen.c new file mode 100644 index 0000000000..7e0bf8214a --- /dev/null +++ b/REORG.TODO/dlfcn/tst-rec-dlopen.c @@ -0,0 +1,178 @@ +/* Test recursive dlopen using malloc hooks. + Copyright (C) 2015-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <dlfcn.h> +#include <stdbool.h> +#include <stdalign.h> +#include <sys/mman.h> +#include <unistd.h> +#include <string.h> + +#define DSO "moddummy1.so" +#define FUNC "dummy1" + +#define DSO1 "moddummy2.so" +#define FUNC1 "dummy2" + +/* Result of the called function. */ +int func_result; + +/* Call function func_name in DSO dso_name via dlopen. */ +void +call_func (const char *dso_name, const char *func_name) +{ + int ret; + void *dso; + int (*func) (void); + char *err; + + /* Open the DSO. */ + dso = dlopen (dso_name, RTLD_NOW|RTLD_GLOBAL); + if (dso == NULL) + { + err = dlerror (); + fprintf (stderr, "%s\n", err); + exit (1); + } + /* Clear any errors. */ + dlerror (); + + /* Lookup func. */ + func = (int (*) (void)) dlsym (dso, func_name); + if (func == NULL) + { + err = dlerror (); + if (err != NULL) + { + fprintf (stderr, "%s\n", err); + exit (1); + } + } + /* Call func. */ + func_result = (*func) (); + + /* Close the library and look for errors too. */ + ret = dlclose (dso); + if (ret != 0) + { + err = dlerror (); + fprintf (stderr, "%s\n", err); + exit (1); + } + +} + +/* If true, call another function from malloc. */ +static bool call_function; + +/* Set to true to indicate that the interposed malloc was called. */ +static bool interposed_malloc_called; + +/* Interposed malloc which optionally calls another function. */ +void * +malloc (size_t size) +{ + interposed_malloc_called = true; + static void *(*original_malloc) (size_t); + + if (original_malloc == NULL) + { + static bool in_initialization; + if (in_initialization) + { + const char *message + = "error: malloc called recursively during initialization\n"; + (void) write (STDOUT_FILENO, message, strlen (message)); + _exit (2); + } + in_initialization = true; + + original_malloc + = (__typeof (original_malloc)) dlsym (RTLD_NEXT, "malloc"); + if (original_malloc == NULL) + { + const char *message + = "error: dlsym for malloc failed\n"; + (void) write (STDOUT_FILENO, message, strlen (message)); + _exit (2); + } + } + + if (call_function) + { + call_function = false; + call_func (DSO1, FUNC1); + call_function = true; + } + return original_malloc (size); +} + +static int +do_test (void) +{ + /* Ensure initialization. */ + { + void *volatile ptr = malloc (1); + free (ptr); + } + + if (!interposed_malloc_called) + { + printf ("error: interposed malloc not called during initialization\n"); + return 1; + } + + call_function = true; + + /* Bug 17702 fixes two things: + * A recursive dlopen unmapping the ld.so.cache. + * An assertion that _r_debug is RT_CONSISTENT at entry to dlopen. + We can only test the latter. Testing the former requires modifying + ld.so.conf to cache the dummy libraries, then running ldconfig, + then run the test. If you do all of that (and glibc's test + infrastructure doesn't support that yet) then the test will + SEGFAULT without the fix. If you don't do that, then the test + will abort because of the assert described in detail below. */ + call_func (DSO, FUNC); + + call_function = false; + + /* The function dummy2() is called by the malloc hook. Check to + see that it was called. This ensures the second recursive + dlopen happened and we called the function in that library. + Before the fix you either get a SIGSEGV when accessing mmap'd + ld.so.cache data or an assertion failure about _r_debug not + beint RT_CONSISTENT. We don't test for the SIGSEGV since it + would require finding moddummy1 or moddummy2 in the cache and + we don't have any infrastructure to test that, but the _r_debug + assertion triggers. */ + printf ("Returned result is %d\n", func_result); + if (func_result <= 0) + { + printf ("FAIL: Function call_func() not called.\n"); + exit (1); + } + + printf ("PASS: Function call_func() called more than once.\n"); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/tstatexit.c b/REORG.TODO/dlfcn/tstatexit.c new file mode 100644 index 0000000000..2073843b8f --- /dev/null +++ b/REORG.TODO/dlfcn/tstatexit.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2001-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + + +extern void *__dso_handle __attribute__ ((__weak__)); + +int +main (void) +{ + const char fname[] = "modatexit.so"; + void *h; + void (*fp) (void *); + int v = 0; + + if (&__dso_handle == NULL) + { + puts ("__dso_handle not available, cannot perform the test"); + exit (0); + } + + h = dlopen (fname, RTLD_NOW); + if (h == NULL) + { + printf ("cannot open \"%s\": %s\n", fname, dlerror ()); + exit (1); + } + + fp = dlsym (h, "foo"); + if (fp == NULL) + { + printf ("cannot find \"foo\": %s\n", dlerror ()); + exit (1); + } + + fp (&v); + + if (dlclose (h) != 0) + { + printf ("cannot close \"%s\": %s\n", fname, dlerror ()); + exit (1); + } + + if (v != 1) + { + puts ("module unload didn't change `v'"); + exit (1); + } + + puts ("finishing now"); + + return 0; +} diff --git a/REORG.TODO/dlfcn/tstcxaatexit.c b/REORG.TODO/dlfcn/tstcxaatexit.c new file mode 100644 index 0000000000..fde645c16b --- /dev/null +++ b/REORG.TODO/dlfcn/tstcxaatexit.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2001-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +extern void *__dso_handle __attribute__ ((__weak__)); + +int +main (void) +{ + const char fname[] = "modcxaatexit.so"; + void *h; + void (*fp) (void *); + int v = 0; + + if (&__dso_handle == NULL) + { + puts ("__dso_handle not available, cannot perform the test"); + exit (0); + } + + h = dlopen (fname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open \"%s\": %s\n", fname, dlerror ()); + exit (1); + } + + fp = dlsym (h, "bar"); + if (fp == NULL) + { + printf ("cannot find \"bar\": %s\n", dlerror ()); + exit (1); + } + + fp (&v); + + if (dlclose (h) != 0) + { + printf ("cannot close \"%s\": %s\n", fname, dlerror ()); + exit (1); + } + + if (v != 1) + { + puts ("module unload didn't change `v'"); + exit (1); + } + + puts ("finishing now"); + + return 0; +} diff --git a/REORG.TODO/dlfcn/tststatic.c b/REORG.TODO/dlfcn/tststatic.c new file mode 100644 index 0000000000..3d6551389e --- /dev/null +++ b/REORG.TODO/dlfcn/tststatic.c @@ -0,0 +1,38 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +static int +do_test (void) +{ + void *handle; + int (*test) (int); + int res; + + handle = dlopen ("modstatic.so", RTLD_LAZY); + if (handle == NULL) + { + printf ("%s\n", dlerror ()); + exit(1); + } + + test = dlsym (handle, "test"); + if (test == NULL) + { + printf ("%s\n", dlerror ()); + exit(1); + } + + res = test (2); + if (res != 4) + { + printf ("Got %i, expected 4\n", res); + exit (1); + } + + dlclose (handle); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/tststatic2.c b/REORG.TODO/dlfcn/tststatic2.c new file mode 100644 index 0000000000..f8cd5a964b --- /dev/null +++ b/REORG.TODO/dlfcn/tststatic2.c @@ -0,0 +1,167 @@ +#include <dlfcn.h> +#include <link.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <gnu/lib-names.h> + +static int +do_test (void) +{ + void *handle = dlopen ("modstatic2-nonexistent.so", RTLD_LAZY); + if (handle == NULL) + printf ("nonexistent: %s\n", dlerror ()); + else + exit (1); + + handle = dlopen ("modstatic2.so", RTLD_LAZY); + if (handle == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + + int (*test) (FILE *, int); + test = dlsym (handle, "test"); + if (test == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + + Dl_info info; + int res = dladdr (test, &info); + if (res == 0) + { + puts ("dladdr returned 0"); + exit (1); + } + else + { + if (strstr (info.dli_fname, "modstatic2.so") == NULL + || strcmp (info.dli_sname, "test") != 0) + { + printf ("fname %s sname %s\n", info.dli_fname, info.dli_sname); + exit (1); + } + if (info.dli_saddr != (void *) test) + { + printf ("saddr %p != test %p\n", info.dli_saddr, test); + exit (1); + } + } + + ElfW(Sym) *sym; + void *symp; + res = dladdr1 (test, &info, &symp, RTLD_DL_SYMENT); + if (res == 0) + { + puts ("dladdr1 returned 0"); + exit (1); + } + else + { + if (strstr (info.dli_fname, "modstatic2.so") == NULL + || strcmp (info.dli_sname, "test") != 0) + { + printf ("fname %s sname %s\n", info.dli_fname, info.dli_sname); + exit (1); + } + if (info.dli_saddr != (void *) test) + { + printf ("saddr %p != test %p\n", info.dli_saddr, test); + exit (1); + } + sym = symp; + if (sym == NULL) + { + puts ("sym == NULL\n"); + exit (1); + } + if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL + || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT) + { + printf ("bind %d visibility %d\n", + (int) ELF32_ST_BIND (sym->st_info), + (int) ELF32_ST_VISIBILITY (sym->st_other)); + exit (1); + } + } + + Lmid_t lmid; + res = dlinfo (handle, RTLD_DI_LMID, &lmid); + if (res != 0) + { + printf ("dlinfo returned %d %s\n", res, dlerror ()); + exit (1); + } + else if (lmid != LM_ID_BASE) + { + printf ("lmid %d != %d\n", (int) lmid, (int) LM_ID_BASE); + exit (1); + } + + res = test (stdout, 2); + if (res != 4) + { + printf ("Got %i, expected 4\n", res); + exit (1); + } + + void *handle2 = dlopen (LIBDL_SO, RTLD_LAZY); + if (handle2 == NULL) + { + printf ("libdl.so: %s\n", dlerror ()); + exit (1); + } + + if (dlvsym (handle2, "_dlfcn_hook", "GLIBC_PRIVATE") == NULL) + { + printf ("dlvsym: %s\n", dlerror ()); + exit (1); + } + + void *(*dlsymfn) (void *, const char *); + dlsymfn = dlsym (handle2, "dlsym"); + if (dlsymfn == NULL) + { + printf ("dlsym \"dlsym\": %s\n", dlerror ()); + exit (1); + } + void *test2 = dlsymfn (handle, "test"); + if (test2 == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + else if (test2 != (void *) test) + { + printf ("test %p != test2 %p\n", test, test2); + exit (1); + } + + dlclose (handle2); + dlclose (handle); + + handle = dlmopen (LM_ID_BASE, "modstatic2.so", RTLD_LAZY); + if (handle == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + dlclose (handle); + + handle = dlmopen (LM_ID_NEWLM, "modstatic2.so", RTLD_LAZY); + if (handle == NULL) + printf ("LM_ID_NEWLM: %s\n", dlerror ()); + else + { + puts ("LM_ID_NEWLM unexpectedly succeeded"); + exit (1); + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/tststatic3.c b/REORG.TODO/dlfcn/tststatic3.c new file mode 100644 index 0000000000..04cef84614 --- /dev/null +++ b/REORG.TODO/dlfcn/tststatic3.c @@ -0,0 +1,128 @@ +/* Global-scope DSO mapping test with a static executable (BZ #15022). + Copyright (C) 2013-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stddef.h> +#include <stdio.h> + +#define MAGIC0 0 +#define MAGIC1 0x5500ffaa +#define MAGIC2 0xaaff0055 + +/* Mapping a DSO into the global scope used to crash in static + executables. Check that it succeeds and then that symbols from + the DSO can be accessed and operate as expected. */ +static int +do_test (void) +{ + unsigned int (*getfoo) (void); + void (*setfoo) (unsigned int); + unsigned int *foop; + unsigned int foo; + void *handle; + + /* Try to map a module into the global scope. */ + handle = dlopen ("modstatic3.so", RTLD_LAZY | RTLD_GLOBAL); + if (handle == NULL) + { + printf ("dlopen (modstatic3.so): %s\n", dlerror ()); + return 1; + } + + /* Get at its symbols. */ + foop = dlsym (handle, "foo"); + if (foop == NULL) + { + printf ("dlsym (foo): %s\n", dlerror ()); + return 1; + } + + getfoo = dlsym (handle, "getfoo"); + if (getfoo == NULL) + { + printf ("dlsym (getfoo): %s\n", dlerror ()); + return 1; + } + + setfoo = dlsym (handle, "setfoo"); + if (setfoo == NULL) + { + printf ("dlsym (setfoo): %s\n", dlerror ()); + return 1; + } + + /* Make sure the view of the initial state is consistent. */ + foo = *foop; + if (foo != MAGIC0) + { + printf ("*foop: got %#x, expected %#x\n", foo, MAGIC0); + return 1; + } + + foo = getfoo (); + if (foo != MAGIC0) + { + printf ("getfoo: got %#x, expected %#x\n", foo, MAGIC0); + return 1; + } + + /* Likewise with one change to its state. */ + setfoo (MAGIC1); + + foo = *foop; + if (foo != MAGIC1) + { + printf ("*foop: got %#x, expected %#x\n", foo, MAGIC1); + return 1; + } + + foo = getfoo (); + if (foo != MAGIC1) + { + printf ("getfoo: got %#x, expected %#x\n", foo, MAGIC1); + return 1; + } + + /* And with another. */ + setfoo (MAGIC2); + + foo = *foop; + if (foo != MAGIC2) + { + printf ("*foop: got %#x, expected %#x\n", foo, MAGIC2); + return 1; + } + + foo = getfoo (); + if (foo != MAGIC2) + { + printf ("getfoo: got %#x, expected %#x\n", foo, MAGIC2); + return 1; + } + + /* All done, clean up. */ + getfoo = NULL; + setfoo = NULL; + foop = NULL; + dlclose (handle); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/tststatic4.c b/REORG.TODO/dlfcn/tststatic4.c new file mode 100644 index 0000000000..55ce52ba85 --- /dev/null +++ b/REORG.TODO/dlfcn/tststatic4.c @@ -0,0 +1,363 @@ +/* Global object symbol access tests with a static executable (BZ #15022). + Copyright (C) 2013-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stddef.h> +#include <stdio.h> + +#define MAGIC0 0 +#define MAGIC1 0x5500ffaa +#define MAGIC2 0xaaff0055 +#define MAGIC3 0xff55aa00 + +/* Check the ability to access the global symbol object and then + global-scope symbol access consistency via different mappings + requested from a static executable. */ +static int +do_test (void) +{ + unsigned int (*initial_getfoo) (void); + void (*initial_setfoo) (unsigned int); + unsigned int (*global_getfoo) (void); + void (*global_setfoo) (unsigned int); + unsigned int (*local_getfoo) (void); + void (*local_setfoo) (unsigned int); + unsigned int *initial_foop; + unsigned int *global_foop; + unsigned int *local_foop; + void *initial_handle; + void *global_handle; + void *local_handle; + unsigned int foo; + + /* Try to map self. */ + initial_handle = dlopen (NULL, RTLD_LAZY | RTLD_GLOBAL); + if (initial_handle == NULL) + { + printf ("dlopen [initial] (NULL): %s\n", dlerror ()); + return 1; + } + + /* Make sure symbol lookups fail gracefully. */ + initial_foop = dlsym (initial_handle, "foo"); + if (initial_foop != NULL) + { + printf ("dlsym [initial] (foo): got %p, expected NULL\n", initial_foop); + return 1; + } + + initial_getfoo = dlsym (initial_handle, "getfoo"); + if (initial_getfoo != NULL) + { + printf ("dlsym [initial] (getfoo): got %p, expected NULL\n", + initial_getfoo); + return 1; + } + + initial_setfoo = dlsym (initial_handle, "setfoo"); + if (initial_setfoo != NULL) + { + printf ("dlsym [initial] (setfoo): got %p, expected NULL\n", + initial_setfoo); + return 1; + } + + /* Try to map a module into the global scope. */ + global_handle = dlopen ("modstatic3.so", RTLD_LAZY | RTLD_GLOBAL); + if (global_handle == NULL) + { + printf ("dlopen [global] (modstatic3.so): %s\n", dlerror ()); + return 1; + } + + /* Get at its symbols. */ + global_foop = dlsym (global_handle, "foo"); + if (global_foop == NULL) + { + printf ("dlsym [global] (foo): %s\n", dlerror ()); + return 1; + } + + global_getfoo = dlsym (global_handle, "getfoo"); + if (global_getfoo == NULL) + { + printf ("dlsym [global] (getfoo): %s\n", dlerror ()); + return 1; + } + + global_setfoo = dlsym (global_handle, "setfoo"); + if (global_setfoo == NULL) + { + printf ("dlsym [global] (setfoo): %s\n", dlerror ()); + return 1; + } + + /* Try to map self again now. */ + local_handle = dlopen (NULL, RTLD_LAZY | RTLD_LOCAL); + if (local_handle == NULL) + { + printf ("dlopen [local] (NULL): %s\n", dlerror ()); + return 1; + } + + /* Make sure we can get at the previously loaded module's symbols + via this handle too. */ + local_foop = dlsym (local_handle, "foo"); + if (local_foop == NULL) + { + printf ("dlsym [local] (foo): %s\n", dlerror ()); + return 1; + } + + local_getfoo = dlsym (local_handle, "getfoo"); + if (local_getfoo == NULL) + { + printf ("dlsym [local] (getfoo): %s\n", dlerror ()); + return 1; + } + + local_setfoo = dlsym (local_handle, "setfoo"); + if (local_setfoo == NULL) + { + printf ("dlsym [local] (setfoo): %s\n", dlerror ()); + return 1; + } + + /* Make sure we can get at the previously loaded module's symbols + via a handle that was obtained before the module was loaded too. */ + initial_foop = dlsym (initial_handle, "foo"); + if (initial_foop == NULL) + { + printf ("dlsym [initial] (foo): %s\n", dlerror ()); + return 1; + } + + initial_getfoo = dlsym (initial_handle, "getfoo"); + if (initial_getfoo == NULL) + { + printf ("dlsym [initial] (getfoo): %s\n", dlerror ()); + return 1; + } + + initial_setfoo = dlsym (initial_handle, "setfoo"); + if (initial_setfoo == NULL) + { + printf ("dlsym [initial] (setfoo): %s\n", dlerror ()); + return 1; + } + + /* Make sure the view of the initial state is consistent. */ + foo = *initial_foop; + if (foo != MAGIC0) + { + printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC0); + return 1; + } + + foo = *global_foop; + if (foo != MAGIC0) + { + printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC0); + return 1; + } + + foo = *local_foop; + if (foo != MAGIC0) + { + printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC0); + return 1; + } + + foo = initial_getfoo (); + if (foo != MAGIC0) + { + printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC0); + return 1; + } + + foo = global_getfoo (); + if (foo != MAGIC0) + { + printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC0); + return 1; + } + + foo = local_getfoo (); + if (foo != MAGIC0) + { + printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC0); + return 1; + } + + /* Likewise with a change to its state made through the first handle. */ + initial_setfoo (MAGIC1); + + foo = *initial_foop; + if (foo != MAGIC1) + { + printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC1); + return 1; + } + + foo = *global_foop; + if (foo != MAGIC1) + { + printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC1); + return 1; + } + + foo = *local_foop; + if (foo != MAGIC1) + { + printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC1); + return 1; + } + + foo = initial_getfoo (); + if (foo != MAGIC1) + { + printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC1); + return 1; + } + + foo = global_getfoo (); + if (foo != MAGIC1) + { + printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC1); + return 1; + } + + foo = local_getfoo (); + if (foo != MAGIC1) + { + printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC1); + return 1; + } + + /* Likewise with a change to its state made through the second handle. */ + global_setfoo (MAGIC2); + + foo = *initial_foop; + if (foo != MAGIC2) + { + printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC2); + return 1; + } + + foo = *global_foop; + if (foo != MAGIC2) + { + printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC2); + return 1; + } + + foo = *local_foop; + if (foo != MAGIC2) + { + printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC2); + return 1; + } + + foo = initial_getfoo (); + if (foo != MAGIC2) + { + printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC2); + return 1; + } + + foo = global_getfoo (); + if (foo != MAGIC2) + { + printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC2); + return 1; + } + + foo = local_getfoo (); + if (foo != MAGIC2) + { + printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC2); + return 1; + } + + /* Likewise with a change to its state made through the third handle. */ + local_setfoo (MAGIC3); + + foo = *initial_foop; + if (foo != MAGIC3) + { + printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC3); + return 1; + } + + foo = *global_foop; + if (foo != MAGIC3) + { + printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC3); + return 1; + } + + foo = *local_foop; + if (foo != MAGIC3) + { + printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC3); + return 1; + } + + foo = initial_getfoo (); + if (foo != MAGIC3) + { + printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC3); + return 1; + } + + foo = global_getfoo (); + if (foo != MAGIC3) + { + printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC3); + return 1; + } + + foo = local_getfoo (); + if (foo != MAGIC3) + { + printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC3); + return 1; + } + + /* All done, clean up. */ + initial_getfoo = NULL; + initial_setfoo = NULL; + initial_foop = NULL; + + local_getfoo = NULL; + local_setfoo = NULL; + local_foop = NULL; + dlclose (local_handle); + + global_getfoo = NULL; + global_setfoo = NULL; + global_foop = NULL; + dlclose (global_handle); + + dlclose (initial_handle); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/dlfcn/tststatic5.c b/REORG.TODO/dlfcn/tststatic5.c new file mode 100644 index 0000000000..782304811d --- /dev/null +++ b/REORG.TODO/dlfcn/tststatic5.c @@ -0,0 +1,76 @@ +/* GLRO(dl_pagesize) initialization DSO test with a static executable. + Copyright (C) 2013-2017 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <stddef.h> +#include <stdio.h> +#include <unistd.h> + +/* Check that the same page size is reported both directly and by a DSO + mapped from a static executable. + + On targets that support different page sizes, the kernel communicates + the size currently in use via the auxiliary vector. This vector is + available to initial startup, but not any DSOs loaded later on. As + static executables do not export their symbols a DSO cannot access + the value obtained by initial startup and the value therefore has to + be passed on to the DSO and stored within its data area explicitly. + This is performed by a call to DL_STATIC_INIT that is defined in a + target-dependent way, and that on variable page size targets stores + it in the GLRO(dl_pagesize) variable of the DSO's dynamic linker. */ +static int +do_test (void) +{ + int pagesize = getpagesize (); + int (*my_getpagesize) (void); + int my_pagesize; + void *handle; + + /* Try to map a module. */ + handle = dlopen ("modstatic5.so", RTLD_LAZY | RTLD_LOCAL); + if (handle == NULL) + { + printf ("dlopen (modstatic5.so): %s\n", dlerror ()); + return 1; + } + + /* Get at its symbol. */ + my_getpagesize = dlsym (handle, "my_getpagesize"); + if (my_getpagesize == NULL) + { + printf ("dlsym (my_getpagesize): %s\n", dlerror ()); + return 1; + } + + /* Make sure the page size reported is the same either way. */ + my_pagesize = my_getpagesize (); + if (my_pagesize != pagesize) + { + printf ("my_getpagesize: got %i, expected %i\n", my_pagesize, pagesize); + return 1; + } + + /* All done, clean up. */ + my_getpagesize = NULL; + dlclose (handle); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |