diff options
author | Jakub Jelinek <jakub@redhat.com> | 2007-07-12 18:26:36 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2007-07-12 18:26:36 +0000 |
commit | 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (patch) | |
tree | 2ea1f8305970753e4a657acb2ccc15ca3eec8e2c /dlfcn | |
parent | 7d58530341304d403a6626d7f7a1913165fe2f32 (diff) | |
download | glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.gz glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.xz glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.zip |
2.5-18.1
Diffstat (limited to 'dlfcn')
-rw-r--r-- | dlfcn/Makefile | 39 | ||||
-rw-r--r-- | dlfcn/bug-atexit1-lib.c | 375 | ||||
-rw-r--r-- | dlfcn/bug-atexit1.c | 23 | ||||
-rw-r--r-- | dlfcn/bug-atexit2-lib.c | 14 | ||||
-rw-r--r-- | dlfcn/bug-atexit2.c | 53 | ||||
-rw-r--r-- | dlfcn/bug-atexit3-lib.cc | 23 | ||||
-rw-r--r-- | dlfcn/bug-atexit3.c | 18 | ||||
-rw-r--r-- | dlfcn/dlclose.c | 3 | ||||
-rw-r--r-- | dlfcn/dlerror.c | 37 | ||||
-rw-r--r-- | dlfcn/dlfcn.c | 39 | ||||
-rw-r--r-- | dlfcn/dlfcn.h | 21 | ||||
-rw-r--r-- | dlfcn/dlinfo.c | 29 | ||||
-rw-r--r-- | dlfcn/dlmopen.c | 26 | ||||
-rw-r--r-- | dlfcn/dlopen.c | 15 | ||||
-rw-r--r-- | dlfcn/dlopenold.c | 8 |
15 files changed, 680 insertions, 43 deletions
diff --git a/dlfcn/Makefile b/dlfcn/Makefile index ed20ae5ccd..63e7b31b2a 100644 --- a/dlfcn/Makefile +++ b/dlfcn/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 1995-2002, 2003, 2004, 2005, 2006 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 @@ -20,13 +20,14 @@ subdir := dlfcn headers := bits/dlfcn.h dlfcn.h extra-libs := libdl libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo \ - dlmopen -routines := $(patsubst %,s%,$(libdl-routines)) + dlmopen dlfcn +routines := $(patsubst %,s%,$(filter-out dlfcn,$(libdl-routines))) elide-routines.os := $(routines) distribute := dlopenold.c glreflib1.c glreflib2.c failtestmod.c \ defaultmod1.c defaultmod2.c errmsg1mod.c modatexit.c \ modcxaatexit.c modstatic.c modstatic2.c \ - bug-dlsym1-lib1.c bug-dlsym1-lib2.c + bug-dlsym1-lib1.c bug-dlsym1-lib2.c bug-atexit1-lib.c \ + bug-atexit2-lib.c extra-libs-others := libdl @@ -34,19 +35,21 @@ include ../Makeconfig ifeq ($(versioning),yes) libdl-routines += dlopenold -libdl-shared-only-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-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \ + bug-atexit3 ifeq (yes,$(have-protected)) tests += tstatexit endif endif modules-names = glreflib1 glreflib2 failtestmod defaultmod1 defaultmod2 \ errmsg1mod modatexit modcxaatexit \ - bug-dlsym1-lib1 bug-dlsym1-lib2 + bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \ + bug-atexit2-lib bug-atexit3-lib failtestmod.so-no-z-defs = yes glreflib2.so-no-z-defs = yes @@ -60,16 +63,12 @@ tststatic-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf tststatic2-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf endif -extra-objs += $(modules-names:=.os) +extra-test-objs += $(modules-names:=.os) generated := $(modules-names:=.so) include ../Rules -LDFLAGS-dl.so = -Wl,-dynamic-linker,$(slibdir)/$(rtld-installed-name) - test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) -$(test-modules): $(objpfx)%.so: $(objpfx)%.os $(common-objpfx)shlib.lds - $(build-module) ifeq ($(build-shared),yes) # Build all the modules even when not actually running test programs. @@ -127,6 +126,22 @@ $(objpfx)bug-dlsym1-lib1.so: $(objpfx)bug-dlsym1-lib2.so \ $(objpfx)bug-dlsym1-lib2.so: $(common-objpfx)libc.so \ $(common-objpfx)libc_nonshared.a +$(objpfx)bug-atexit1: $(libdl) +$(objpfx)bug-atexit1.out: $(objpfx)bug-atexit1-lib.so +$(objpfx)bug-atexit1-lib.so: $(common-objpfx)libc.so \ + $(common-objpfx)libc_nonshared.a + +$(objpfx)bug-atexit2: $(libdl) +$(objpfx)bug-atexit2.out: $(objpfx)bug-atexit2-lib.so +$(objpfx)bug-atexit2-lib.so: $(common-objpfx)libc.so \ + $(common-objpfx)libc_nonshared.a + +LDLIBS-bug-atexit3-lib.so = -lstdc++ -lgcc_eh $(common-objpfx)elf/ld.so \ + $(common-objpfx)libc_nonshared.a +$(objpfx)bug-atexit3: $(libdl) +$(objpfx)bug-atexit3.out: $(objpfx)bug-atexit3-lib.so +$(objpfx)bug-atexit3-lib.so: $(common-objpfx)libc.so \ + $(common-objpfx)libc_nonshared.a # Depend on libc.so so a DT_NEEDED is generated in the shared objects. diff --git a/dlfcn/bug-atexit1-lib.c b/dlfcn/bug-atexit1-lib.c new file mode 100644 index 0000000000..715bb40b23 --- /dev/null +++ b/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/dlfcn/bug-atexit1.c b/dlfcn/bug-atexit1.c new file mode 100644 index 0000000000..e2d1d2f776 --- /dev/null +++ b/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/dlfcn/bug-atexit2-lib.c b/dlfcn/bug-atexit2-lib.c new file mode 100644 index 0000000000..ca39657566 --- /dev/null +++ b/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/dlfcn/bug-atexit2.c b/dlfcn/bug-atexit2.c new file mode 100644 index 0000000000..15e9f7aa01 --- /dev/null +++ b/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/dlfcn/bug-atexit3-lib.cc b/dlfcn/bug-atexit3-lib.cc new file mode 100644 index 0000000000..3d01ea81d2 --- /dev/null +++ b/dlfcn/bug-atexit3-lib.cc @@ -0,0 +1,23 @@ +#include <unistd.h> + +struct statclass +{ + statclass() + { + write (1, "statclass\n", 10); + } + ~statclass() + { + write (1, "~statclass\n", 11); + } +}; + +struct extclass +{ + ~extclass() + { + static statclass var; + } +}; + +extclass globvar; diff --git a/dlfcn/bug-atexit3.c b/dlfcn/bug-atexit3.c new file mode 100644 index 0000000000..897eca8a86 --- /dev/null +++ b/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/dlfcn/dlclose.c b/dlfcn/dlclose.c index 3ddedcffbe..5a344f31ca 100644 --- a/dlfcn/dlclose.c +++ b/dlfcn/dlclose.c @@ -19,6 +19,7 @@ 02111-1307 USA. */ #include <dlfcn.h> +#include <ldsodefs.h> #if !defined SHARED && defined IS_IN_libdl @@ -33,7 +34,7 @@ dlclose (void *handle) static void dlclose_doit (void *handle) { - _dl_close (handle); + GLRO(dl_close) (handle); } int diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c index 8789f4f68b..7ea31d4392 100644 --- a/dlfcn/dlerror.c +++ b/dlfcn/dlerror.c @@ -1,5 +1,5 @@ /* Return error detail for failing <dlfcn.h> functions. - Copyright (C) 1995-2000,2002,2003,2004 Free Software Foundation, Inc. + Copyright (C) 1995-2000,2002,2003,2004,2005 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 @@ -19,6 +19,7 @@ #include <dlfcn.h> #include <libintl.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -40,6 +41,7 @@ struct dl_action_result { int errcode; int returned; + bool malloced; const char *objname; const char *errstring; }; @@ -154,13 +156,13 @@ _dlerror_run (void (*operate) (void *), void *args) { /* Free the error string from the last failed command. This can happen if `dlerror' was not run after an error was found. */ - if (strcmp (result->errstring, "out of memory") != 0) + if (result->malloced) free ((char *) result->errstring); result->errstring = NULL; } result->errcode = GLRO(dl_catch_error) (&result->objname, &result->errstring, - operate, args); + &result->malloced, operate, args); /* If no error we mark that no error string is available. */ result->returned = result->errstring == NULL; @@ -180,13 +182,30 @@ init (void) 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 namespave. */ + struct link_map *map = NULL; + Dl_info info; + if (_dl_addr (check_free, &info, &map, NULL) != 0 + && map != NULL && map->l_ns == 0) + free ((char *) rec->errstring); + } +} + + static void __attribute__ ((destructor)) fini (void) { - if (last_result.errstring != NULL - && strcmp (last_result.errstring, "out of memory") != 0) - free ((char *) last_result.errstring); + check_free (&last_result); } @@ -194,11 +213,7 @@ fini (void) static void free_key_mem (void *mem) { - struct dl_action_result *result = (struct dl_action_result *) mem; - - if (result->errstring != NULL - && strcmp (result->errstring, "out of memory") != 0) - free ((char *) result->errstring); + check_free ((struct dl_action_result *) mem); free (mem); __libc_setspecific (key, NULL); diff --git a/dlfcn/dlfcn.c b/dlfcn/dlfcn.c new file mode 100644 index 0000000000..1ee225ba47 --- /dev/null +++ b/dlfcn/dlfcn.c @@ -0,0 +1,39 @@ +/* Load a shared object at run time. + Copyright (C) 2005 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#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/dlfcn/dlfcn.h b/dlfcn/dlfcn.h index 42c25b8b63..7e373eddf9 100644 --- a/dlfcn/dlfcn.h +++ b/dlfcn/dlfcn.h @@ -1,5 +1,6 @@ /* User functions for run-time dynamic loading. - Copyright (C) 1995-1999,2000,2001,2003,2004 Free Software Foundation, Inc. + Copyright (C) 1995-1999,2000,2001,2003,2004,2006 + 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 @@ -135,6 +136,8 @@ enum 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' @@ -147,7 +150,21 @@ enum expand $ORIGIN in this shared object's dependency file names. */ RTLD_DI_ORIGIN = 6, - RTLD_DI_CONFIGADDR = 3 /* Unsupported, defined by Solaris. */ + 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, }; diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c index 44af55a303..20aa9504fb 100644 --- a/dlfcn/dlinfo.c +++ b/dlfcn/dlinfo.c @@ -1,5 +1,5 @@ /* dlinfo -- Get information from the dynamic linker. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2006, 2007 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 @@ -32,6 +32,10 @@ dlinfo (void *handle, int request, void *arg) #else +# ifdef USE_TLS +# include <dl-tls.h> +# endif + struct dlinfo_args { ElfW(Addr) caller; @@ -54,9 +58,8 @@ dlinfo_doit (void *argsblock) /* 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) - /* There must be exactly one DSO for the range of the virtual - memory. Otherwise something is really broken. */ + if (caller >= l->l_map_start && caller < l->l_map_end + && (l->l_contiguous || _dl_addr_inside_object (l, caller))) break; if (l == NULL) @@ -90,6 +93,24 @@ RTLD_SELF used in code not dynamically loaded")); case RTLD_DI_ORIGIN: strcpy (args->arg, l->l_origin); break; + + case RTLD_DI_TLS_MODID: + *(size_t *) args->arg = 0; +#ifdef USE_TLS + *(size_t *) args->arg = l->l_tls_modid; +#endif + break; + + case RTLD_DI_TLS_DATA: + { + void *data = NULL; +#ifdef USE_TLS + if (l->l_tls_modid != 0) + data = _dl_tls_get_addr_soft (l); +#endif + *(void **) args->arg = data; + break; + } } } diff --git a/dlfcn/dlmopen.c b/dlfcn/dlmopen.c index 5fd6543655..0c6915493b 100644 --- a/dlfcn/dlmopen.c +++ b/dlfcn/dlmopen.c @@ -1,5 +1,5 @@ /* Load a shared object at run time. - Copyright (C) 1995,96,97,98,99,2000,2003,2004 Free Software Foundation, Inc. + Copyright (C) 1995-2000,2003,2004,2006 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 @@ -21,6 +21,7 @@ #include <errno.h> #include <libintl.h> #include <stddef.h> +#include <unistd.h> #include <ldsodefs.h> #if !defined SHARED && defined IS_IN_libdl @@ -54,15 +55,24 @@ dlmopen_doit (void *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) + /* If trying to open the link map for the main executable the namespace + must be the main one. */ + if (args->file == NULL) # endif - GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid namespace")); - - args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN, - args->caller, args->nsid); + GLRO(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 (__builtin_expect (args->mode & RTLD_GLOBAL, 0)) + GLRO(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); } diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c index 6381ffc9b1..bffb512aa3 100644 --- a/dlfcn/dlopen.c +++ b/dlfcn/dlopen.c @@ -1,5 +1,5 @@ /* Load a shared object at run time. - Copyright (C) 1995,96,97,98,99,2000,2003,2004 Free Software Foundation, Inc. + Copyright (C) 1995-2000,2003,2004,2005 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 @@ -18,7 +18,10 @@ 02111-1307 USA. */ #include <dlfcn.h> +#include <libintl.h> #include <stddef.h> +#include <unistd.h> +#include <ldsodefs.h> #if !defined SHARED && defined IS_IN_libdl @@ -56,8 +59,14 @@ dlopen_doit (void *a) { struct dlopen_args *args = (struct dlopen_args *) a; - args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN, - args->caller, args->file == NULL ? LM_ID_BASE : NS); + if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND + | RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE)) + GLRO(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); } diff --git a/dlfcn/dlopenold.c b/dlfcn/dlopenold.c index 148716cdb0..8dae1c40ce 100644 --- a/dlfcn/dlopenold.c +++ b/dlfcn/dlopenold.c @@ -19,6 +19,8 @@ #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. */ @@ -50,8 +52,10 @@ dlopen_doit (void *a) { struct dlopen_args *args = (struct dlopen_args *) a; - args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN, - args->caller, args->file == NULL ? LM_ID_BASE : NS); + 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); |