aboutsummaryrefslogtreecommitdiff
path: root/dlfcn
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-07-12 18:26:36 +0000
committerJakub Jelinek <jakub@redhat.com>2007-07-12 18:26:36 +0000
commit0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (patch)
tree2ea1f8305970753e4a657acb2ccc15ca3eec8e2c /dlfcn
parent7d58530341304d403a6626d7f7a1913165fe2f32 (diff)
downloadglibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar
glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.gz
glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.bz2
glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.zip
2.5-18.1
Diffstat (limited to 'dlfcn')
-rw-r--r--dlfcn/Makefile39
-rw-r--r--dlfcn/bug-atexit1-lib.c375
-rw-r--r--dlfcn/bug-atexit1.c23
-rw-r--r--dlfcn/bug-atexit2-lib.c14
-rw-r--r--dlfcn/bug-atexit2.c53
-rw-r--r--dlfcn/bug-atexit3-lib.cc23
-rw-r--r--dlfcn/bug-atexit3.c18
-rw-r--r--dlfcn/dlclose.c3
-rw-r--r--dlfcn/dlerror.c37
-rw-r--r--dlfcn/dlfcn.c39
-rw-r--r--dlfcn/dlfcn.h21
-rw-r--r--dlfcn/dlinfo.c29
-rw-r--r--dlfcn/dlmopen.c26
-rw-r--r--dlfcn/dlopen.c15
-rw-r--r--dlfcn/dlopenold.c8
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);