aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-10-18 23:17:46 +0000
committerUlrich Drepper <drepper@redhat.com>2004-10-18 23:17:46 +0000
commit5f21997b9d6a49ddbed85b044e2be7b182c095a2 (patch)
tree3b63a3a63ebeb466456f52480bd06df198f1dcf5
parent790b6c7a7f65dec508a2e71e6d922ec166640afc (diff)
downloadglibc-5f21997b9d6a49ddbed85b044e2be7b182c095a2.tar.xz
glibc-5f21997b9d6a49ddbed85b044e2be7b182c095a2.zip
2004-10-18 Jakub Jelinek <jakub@redhat.com> * elf/dl-libc.c (__libc_dlsym_private, __libc_register_dl_open_hook): New functions. (__libc_dlopen_mode): Call __libc_register_dl_open_hook and __libc_register_dlfcn_hook. * dlfcn/Makefile (routines, elide-routines.os): Set. Add rules to build and test tststatic2. * dlfcn/tststatic2.c: New test. * dlfcn/modstatic2.c: New test module. * dlfcn/dladdr.c: Call _dlfcn_hook from libdl.so if not NULL. Define __ prefixed routine in libc.a and in libdl.a just call it. * dlfcn/dladdr1.c: Likewise. * dlfcn/dlclose.c: Likewise. * dlfcn/dlerror.c: Likewise. * dlfcn/dlinfo.c: Likewise. * dlfcn/dlmopen.c: Likewise. * dlfcn/dlopen.c: Likewise. * dlfcn/dlopenold.c: Likewise. * dlfcn/dlsym.c: Likewise. * dlfcn/dlvsym.c: Likewise. * dlfcn/sdladdr.c: New file. * dlfcn/sdladdr1.c: New file. * dlfcn/sdlclose.c: New file. * dlfcn/sdlerror.c: New file. * dlfcn/sdlinfo.c: New file. * dlfcn/sdlopen.c: New file. * dlfcn/sdlsym.c: New file. * dlfcn/sdlvsym.c: New file. * dlfcn/Versions (libdl): Export _dlfcn_hook@GLIBC_PRIVATE. * include/dlfcn.h (DL_CALLER_DECL, DL_CALLER RETURN_ADDRESS): Define. (struct dlfcn_hook): New type. (_dlfcn_hook): New extern decl. (__dlopen, __dlclose, __dlsym, __dlerror, __dladdr, __dladdr1, __dlinfo, __dlmopen, __libc_dlsym_private, __libc_register_dl_open_hook, __libc_register_dlfcn_hook): New prototypes. (__dlvsym): Use DL_CALLER_DECL. * include/libc-symbols.h: Define libdl_hidden_proto and friends. * malloc/arena.c (_dl_open_hook): Extern decl. (ptmalloc_init): Don't call _dl_addr when dlopened from statically linked programs but don't use brk for them either.
-rw-r--r--ChangeLog44
-rw-r--r--dlfcn/Makefile18
-rw-r--r--dlfcn/Versions3
-rw-r--r--dlfcn/dladdr.c21
-rw-r--r--dlfcn/dladdr1.c21
-rw-r--r--dlfcn/dlclose.c24
-rw-r--r--dlfcn/dlerror.c52
-rw-r--r--dlfcn/dlinfo.c28
-rw-r--r--dlfcn/dlmopen.c39
-rw-r--r--dlfcn/dlopen.c48
-rw-r--r--dlfcn/dlopenold.c3
-rw-r--r--dlfcn/dlsym.c23
-rw-r--r--dlfcn/dlvsym.c25
-rw-r--r--dlfcn/modstatic2.c228
-rw-r--r--dlfcn/sdladdr.c1
-rw-r--r--dlfcn/sdladdr1.c1
-rw-r--r--dlfcn/sdlclose.c1
-rw-r--r--dlfcn/sdlerror.c1
-rw-r--r--dlfcn/sdlinfo.c1
-rw-r--r--dlfcn/sdlmopen.c1
-rw-r--r--dlfcn/sdlopen.c1
-rw-r--r--dlfcn/sdlsym.c1
-rw-r--r--dlfcn/sdlvsym.c1
-rw-r--r--dlfcn/tststatic2.c166
-rw-r--r--include/dlfcn.h60
-rw-r--r--include/libc-symbols.h18
-rw-r--r--malloc/arena.c11
27 files changed, 803 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 1a056e6685..0e173987cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,47 @@
+2004-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ * elf/dl-libc.c (__libc_dlsym_private, __libc_register_dl_open_hook):
+ New functions.
+ (__libc_dlopen_mode): Call __libc_register_dl_open_hook and
+ __libc_register_dlfcn_hook.
+ * dlfcn/Makefile (routines, elide-routines.os): Set.
+ Add rules to build and test tststatic2.
+ * dlfcn/tststatic2.c: New test.
+ * dlfcn/modstatic2.c: New test module.
+ * dlfcn/dladdr.c: Call _dlfcn_hook from libdl.so if not NULL.
+ Define __ prefixed routine in libc.a and in libdl.a just call it.
+ * dlfcn/dladdr1.c: Likewise.
+ * dlfcn/dlclose.c: Likewise.
+ * dlfcn/dlerror.c: Likewise.
+ * dlfcn/dlinfo.c: Likewise.
+ * dlfcn/dlmopen.c: Likewise.
+ * dlfcn/dlopen.c: Likewise.
+ * dlfcn/dlopenold.c: Likewise.
+ * dlfcn/dlsym.c: Likewise.
+ * dlfcn/dlvsym.c: Likewise.
+ * dlfcn/sdladdr.c: New file.
+ * dlfcn/sdladdr1.c: New file.
+ * dlfcn/sdlclose.c: New file.
+ * dlfcn/sdlerror.c: New file.
+ * dlfcn/sdlinfo.c: New file.
+ * dlfcn/sdlopen.c: New file.
+ * dlfcn/sdlsym.c: New file.
+ * dlfcn/sdlvsym.c: New file.
+ * dlfcn/Versions (libdl): Export _dlfcn_hook@GLIBC_PRIVATE.
+ * include/dlfcn.h (DL_CALLER_DECL, DL_CALLER RETURN_ADDRESS): Define.
+ (struct dlfcn_hook): New type.
+ (_dlfcn_hook): New extern decl.
+ (__dlopen, __dlclose, __dlsym, __dlerror, __dladdr, __dladdr1,
+ __dlinfo, __dlmopen, __libc_dlsym_private,
+ __libc_register_dl_open_hook, __libc_register_dlfcn_hook): New
+ prototypes.
+ (__dlvsym): Use DL_CALLER_DECL.
+ * include/libc-symbols.h: Define libdl_hidden_proto and friends.
+
+ * malloc/arena.c (_dl_open_hook): Extern decl.
+ (ptmalloc_init): Don't call _dl_addr when dlopened from statically
+ linked programs but don't use brk for them either.
+
2004-10-18 Roland McGrath <roland@redhat.com>
* dlfcn/bug-dlsym1.c (main): Remove bogus setenv call.
diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index 4330a8a59d..ed20ae5ccd 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -21,9 +21,11 @@ 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))
+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 \
+ modcxaatexit.c modstatic.c modstatic2.c \
bug-dlsym1-lib1.c bug-dlsym1-lib2.c
extra-libs-others := libdl
@@ -51,10 +53,11 @@ glreflib2.so-no-z-defs = yes
errmsg1mod.so-no-z-defs = yes
ifeq (yesyesyes,$(build-static)$(build-shared)$(elf))
-tests += tststatic
-tests-static += tststatic
-modules-names += modstatic
+tests += tststatic tststatic2
+tests-static += tststatic tststatic2
+modules-names += modstatic modstatic2
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)
@@ -106,7 +109,12 @@ $(objpfx)modatexit.so: $(common-objpfx)libc.so $(common-objpfx)libc_nonshared.a
$(objpfx)tststatic: $(objpfx)libdl.a
$(objpfx)tststatic.out: $(objpfx)tststatic $(objpfx)modstatic.so
-$(objpfx)modstatic.so: $(common-objpfx)libc.so $(common-objpfx)libc_nonshared.a
+$(objpfx)tststatic2: $(objpfx)libdl.a
+$(objpfx)tststatic2.out: $(objpfx)tststatic2 $(objpfx)modstatic.so \
+ $(objpfx)modstatic2.so
+
+$(objpfx)modstatic2.so: $(libdl) $(common-objpfx)libc.so \
+ $(common-objpfx)libc_nonshared.a
$(objpfx)bug-dlopen1: $(libdl)
diff --git a/dlfcn/Versions b/dlfcn/Versions
index 6a41c238aa..97902f0dfd 100644
--- a/dlfcn/Versions
+++ b/dlfcn/Versions
@@ -11,4 +11,7 @@ libdl {
GLIBC_2.3.4 {
dlmopen;
}
+ GLIBC_PRIVATE {
+ _dlfcn_hook;
+ }
}
diff --git a/dlfcn/dladdr.c b/dlfcn/dladdr.c
index b5490e5a8d..d0462b94ff 100644
--- a/dlfcn/dladdr.c
+++ b/dlfcn/dladdr.c
@@ -1,5 +1,6 @@
/* Locate the shared object symbol nearest a given address.
- Copyright (C) 1996, 1997, 1998, 1999, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2003, 2004
+ 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,8 +20,26 @@
#include <dlfcn.h>
+#if !defined SHARED && defined 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 (__builtin_expect (_dlfcn_hook != NULL, 0))
+ 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/dlfcn/dladdr1.c b/dlfcn/dladdr1.c
index 51b53b5861..0f2b603f7c 100644
--- a/dlfcn/dladdr1.c
+++ b/dlfcn/dladdr1.c
@@ -1,5 +1,5 @@
/* Locate the shared object symbol nearest a given address.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004 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,9 +19,24 @@
#include <dlfcn.h>
+#if !defined SHARED && defined 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 (__builtin_expect (_dlfcn_hook != NULL, 0))
+ return _dlfcn_hook->dladdr1 (address, info, extra, flags);
+# endif
+
switch (flags)
{
default: /* Make this an error? */
@@ -33,3 +48,7 @@ dladdr1 (const void *address, Dl_info *info, void **extra, int flags)
return _dl_addr (address, info, (struct link_map **) extra, NULL);
}
}
+# ifdef SHARED
+strong_alias (__dladdr1, dladdr1)
+# endif
+#endif
diff --git a/dlfcn/dlclose.c b/dlfcn/dlclose.c
index 046e6d4d98..3ddedcffbe 100644
--- a/dlfcn/dlclose.c
+++ b/dlfcn/dlclose.c
@@ -1,5 +1,6 @@
/* Close a handle opened by `dlopen'.
- Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2004
+ 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 +20,16 @@
#include <dlfcn.h>
+#if !defined SHARED && defined IS_IN_libdl
+
+int
+dlclose (void *handle)
+{
+ return __dlclose (handle);
+}
+
+#else
+
static void
dlclose_doit (void *handle)
{
@@ -26,7 +37,16 @@ dlclose_doit (void *handle)
}
int
-dlclose (void *handle)
+__dlclose (void *handle)
{
+# ifdef SHARED
+ if (__builtin_expect (_dlfcn_hook != NULL, 0))
+ 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/dlfcn/dlerror.c b/dlfcn/dlerror.c
index 1cde04b080..8789f4f68b 100644
--- a/dlfcn/dlerror.c
+++ b/dlfcn/dlerror.c
@@ -25,6 +25,16 @@
#include <bits/libc-lock.h>
#include <ldsodefs.h>
+#if !defined SHARED && defined IS_IN_libdl
+
+char *
+dlerror (void)
+{
+ return __dlerror ();
+}
+
+#else
+
/* Type for storing results of dynamic loading actions. */
struct dl_action_result
{
@@ -46,11 +56,16 @@ static void free_key_mem (void *mem);
char *
-dlerror (void)
+__dlerror (void)
{
char *buf = NULL;
struct dl_action_result *result;
+# ifdef SHARED
+ if (__builtin_expect (_dlfcn_hook != NULL, 0))
+ return _dlfcn_hook->dlerror ();
+# endif
+
/* If we have not yet initialized the buffer do it now. */
__libc_once (once, init);
@@ -99,6 +114,9 @@ dlerror (void)
return buf;
}
+# ifdef SHARED
+strong_alias (__dlerror, dlerror)
+# endif
int
internal_function
@@ -185,3 +203,35 @@ free_key_mem (void *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/dlfcn/dlinfo.c b/dlfcn/dlinfo.c
index d54a13259a..44af55a303 100644
--- a/dlfcn/dlinfo.c
+++ b/dlfcn/dlinfo.c
@@ -22,6 +22,16 @@
#include <ldsodefs.h>
#include <libintl.h>
+#if !defined SHARED && defined IS_IN_libdl
+
+int
+dlinfo (void *handle, int request, void *arg)
+{
+ return __dlinfo (handle, request, arg, RETURN_ADDRESS (0));
+}
+
+#else
+
struct dlinfo_args
{
ElfW(Addr) caller;
@@ -36,7 +46,7 @@ dlinfo_doit (void *argsblock)
struct dlinfo_args *const args = argsblock;
struct link_map *l = args->handle;
-#if 0
+# if 0
if (args->handle == RTLD_SELF)
{
Lmid_t nsid;
@@ -53,7 +63,7 @@ dlinfo_doit (void *argsblock)
GLRO(dl_signal_error) (0, NULL, NULL, N_("\
RTLD_SELF used in code not dynamically loaded"));
}
-#endif
+# endif
switch (args->request)
{
@@ -84,9 +94,19 @@ RTLD_SELF used in code not dynamically loaded"));
}
int
-dlinfo (void *handle, int request, void *arg)
+__dlinfo (void *handle, int request, void *arg DL_CALLER_DECL)
{
- struct dlinfo_args args = { (ElfW(Addr)) RETURN_ADDRESS (0),
+# ifdef SHARED
+ if (__builtin_expect (_dlfcn_hook != NULL, 0))
+ 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/dlfcn/dlmopen.c b/dlfcn/dlmopen.c
index fb2a50bb1d..5fd6543655 100644
--- a/dlfcn/dlmopen.c
+++ b/dlfcn/dlmopen.c
@@ -23,6 +23,17 @@
#include <stddef.h>
#include <ldsodefs.h>
+#if !defined SHARED && defined 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. */
@@ -43,11 +54,11 @@ dlmopen_doit (void *a)
/* Non-shared code has no support for multiple namespaces. */
if (args->nsid != LM_ID_BASE)
-#ifdef SHARED
+# 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
+# endif
GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid namespace"));
args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN,
@@ -56,14 +67,32 @@ dlmopen_doit (void *a)
void *
-dlmopen (Lmid_t nsid, const char *file, int mode)
+__dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL)
{
+# ifdef SHARED
+ if (__builtin_expect (_dlfcn_hook != NULL, 0))
+ 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 = RETURN_ADDRESS (0);
+ 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
}
-static_link_warning (dlmopen)
+# ifdef SHARED
+strong_alias (__dlmopen, dlmopen)
+# endif
+#endif
diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c
index cfd7963545..6381ffc9b1 100644
--- a/dlfcn/dlopen.c
+++ b/dlfcn/dlopen.c
@@ -20,6 +20,17 @@
#include <dlfcn.h>
#include <stddef.h>
+#if !defined SHARED && defined 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. */
@@ -33,11 +44,11 @@ struct dlopen_args
/* Non-shared code has no support for multiple namespaces. */
-#ifdef SHARED
-# define NS __LM_ID_CALLER
-#else
-# define NS LM_ID_BASE
-#endif
+# ifdef SHARED
+# define NS __LM_ID_CALLER
+# else
+# define NS LM_ID_BASE
+# endif
static void
@@ -50,17 +61,34 @@ dlopen_doit (void *a)
}
-extern void *__dlopen_check (const char *file, int mode);
void *
-__dlopen_check (const char *file, int mode)
+__dlopen (const char *file, int mode DL_CALLER_DECL)
{
+# ifdef SHARED
+ if (__builtin_expect (_dlfcn_hook != NULL, 0))
+ return _dlfcn_hook->dlopen (file, mode, DL_CALLER);
+# endif
+
struct dlopen_args args;
args.file = file;
args.mode = mode;
- args.caller = RETURN_ADDRESS (0);
+ 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
}
-#include <shlib-compat.h>
+# ifdef SHARED
+# include <shlib-compat.h>
+strong_alias (__dlopen, __dlopen_check)
versioned_symbol (libdl, __dlopen_check, dlopen, GLIBC_2_1);
-static_link_warning (dlopen)
+# endif
+#endif
diff --git a/dlfcn/dlopenold.c b/dlfcn/dlopenold.c
index f10674aba3..148716cdb0 100644
--- a/dlfcn/dlopenold.c
+++ b/dlfcn/dlopenold.c
@@ -67,6 +67,9 @@ __dlopen_nocheck (const char *file, int mode)
mode