This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hi! This patch makes some dlopen calls from e.g. NSS modules loaded from statically linked programs work. The usual restrictions still apply, i.e. one should only run statically linked programs that use NSS/dlopen/iconv against the glibc they were compiled/linked against, otherwise there are no guarantees plus even then one can't assume everything works as with dynamic linking (e.g. when writing tststatic2 test, I have noticed that doing printf in the dlopened module in between printf's in statically linked program will result in the text from module not being printed (there are 2 different stdout's); I have changed it so that FILE * is passed around). 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. --- libc/malloc/arena.c.jj 2004-10-15 23:08:34.000000000 +0200 +++ libc/malloc/arena.c 2004-10-18 16:52:30.765485691 +0200 @@ -347,6 +347,9 @@ __failing_morecore (ptrdiff_t d) { return (void *) MORECORE_FAILURE; } + +extern struct dl_open_hook *_dl_open_hook; +libc_hidden_proto (_dl_open_hook); # endif # if defined SHARED && defined USE_TLS && !USE___THREAD @@ -429,10 +432,14 @@ ptmalloc_init (void) main_arena.next = &main_arena; #if defined _LIBC && defined SHARED - /* In case this libc copy is in a non-default namespace, never use brk. */ + /* In case this libc copy is in a non-default namespace, never use brk. + Likewise if dlopened from statically linked program. */ Dl_info di; struct link_map *l; - if (_dl_addr (ptmalloc_init, &di, &l, NULL) != 0 && l->l_ns != LM_ID_BASE) + + if (_dl_open_hook != NULL + || (_dl_addr (ptmalloc_init, &di, &l, NULL) != 0 + && l->l_ns != LM_ID_BASE)) __morecore = __failing_morecore; #endif --- libc/dlfcn/sdlopen.c.jj 2004-10-18 21:20:12.848098233 +0200 +++ libc/dlfcn/sdlopen.c 2004-10-18 21:20:12.848098233 +0200 @@ -0,0 +1 @@ +#include "dlopen.c" --- libc/dlfcn/sdlinfo.c.jj 2004-10-18 21:20:12.847098412 +0200 +++ libc/dlfcn/sdlinfo.c 2004-10-18 21:20:12.848098233 +0200 @@ -0,0 +1 @@ +#include "dlinfo.c" --- libc/dlfcn/dlopen.c.jj 2004-10-15 23:08:32.000000000 +0200 +++ libc/dlfcn/dlopen.c 2004-10-18 22:09:50.189932973 +0200 @@ -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 --- libc/dlfcn/dladdr.c.jj 2003-03-10 10:12:11.000000000 +0100 +++ libc/dlfcn/dladdr.c 2004-10-18 20:57:04.564415633 +0200 @@ -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 --- libc/dlfcn/tststatic2.c.jj 2004-10-18 22:32:17.698823901 +0200 +++ libc/dlfcn/tststatic2.c 2004-10-18 23:57:14.970024860 +0200 @@ -0,0 +1,166 @@ +#include <dlfcn.h> +#include <link.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <gnu/lib-names.h> + +int +main (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); + } + +#ifdef DO_VERSIONING + if (dlvsym (handle2, "_dlfcn_hook", "GLIBC_PRIVATE") == NULL) + { + printf ("dlvsym: %s\n", dlerror ()); + exit (1); + } +#endif + + 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; +} --- libc/dlfcn/dlinfo.c.jj 2004-10-15 23:08:32.000000000 +0200 +++ libc/dlfcn/dlinfo.c 2004-10-18 21:03:38.718828131 +0200 @@ -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 l } 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 --- libc/dlfcn/sdladdr.c.jj 2004-10-18 21:20:12.844098948 +0200 +++ libc/dlfcn/sdladdr.c 2004-10-18 21:20:12.844098948 +0200 @@ -0,0 +1 @@ +#include "dladdr.c" --- libc/dlfcn/dlerror.c.jj 2004-03-08 12:01:41.000000000 +0100 +++ libc/dlfcn/dlerror.c 2004-10-18 23:48:45.113480259 +0200 @@ -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 --- libc/dlfcn/dlvsym.c.jj 2004-02-23 09:46:13.000000000 +0100 +++ libc/dlfcn/dlvsym.c 2004-10-18 21:46:33.954859714 +0200 @@ -22,6 +22,17 @@ #include <ldsodefs.h> +#if !defined SHARED && defined 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. */ @@ -44,13 +55,18 @@ dlvsym_doit (void *a) } void * -__dlvsym (void *handle, const char *name, const char *version_str) +__dlvsym (void *handle, const char *name, const char *version_str + DL_CALLER_DECL) { - struct dlvsym_args args; +# ifdef SHARED + if (__builtin_expect (_dlfcn_hook != NULL, 0)) + return _dlfcn_hook->dlvsym (handle, name, version_str, DL_CALLER); +# endif + struct dlvsym_args args; args.handle = handle; args.name = name; - args.who = RETURN_ADDRESS (0); + args.who = DL_CALLER; args.version = version_str; /* Protect against concurrent loads and unloads. */ @@ -62,4 +78,7 @@ __dlvsym (void *handle, const char *name return result; } +# ifdef SHARED weak_alias (__dlvsym, dlvsym) +# endif +#endif --- libc/dlfcn/modstatic2.c.jj 2004-10-18 22:42:28.741800567 +0200 +++ libc/dlfcn/modstatic2.c 2004-10-18 23:57:24.869271016 +0200 @@ -0,0 +1,228 @@ +#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); + } + +#ifdef DO_VERSIONING + if (dlvsym (handle2, "_dlfcn_hook", "GLIBC_PRIVATE") == NULL) + { + fprintf (out, "dlvsym: %s\n", dlerror ()); + exit (1); + } +#endif + + 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; +} --- libc/dlfcn/dlsym.c.jj 2004-02-23 09:46:13.000000000 +0100 +++ libc/dlfcn/dlsym.c 2004-10-18 21:15:49.789861927 +0200 @@ -22,6 +22,16 @@ #include <ldsodefs.h> +#if !defined SHARED && defined 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. */ @@ -43,10 +53,15 @@ dlsym_doit (void *a) void * -dlsym (void *handle, const char *name) +__dlsym (void *handle, const char *name DL_CALLER_DECL) { +# ifdef SHARED + if (__builtin_expect (_dlfcn_hook != NULL, 0)) + return _dlfcn_hook->dlsym (handle, name, DL_CALLER); +# endif + struct dlsym_args args; - args.who = RETURN_ADDRESS (0); + args.who = DL_CALLER; args.handle = handle; args.name = name; @@ -59,3 +74,7 @@ dlsym (void *handle, const char *name) return result; } +# ifdef SHARED +strong_alias (__dlsym, dlsym) +# endif +#endif --- libc/dlfcn/Makefile.jj 2004-10-15 23:08:32.000000000 +0200 +++ libc/dlfcn/Makefile 2004-10-18 23:47:11.232148304 +0200 @@ -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)l $(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) --- libc/dlfcn/dlopenold.c.jj 2004-10-15 23:08:32.000000000 +0200 +++ libc/dlfcn/dlopenold.c 2004-10-18 19:10:12.833804663 +0200 @@ -67,6 +67,9 @@ __dlopen_nocheck (const char *file, int mode |= RTLD_LAZY; args.mode = mode; + if (__builtin_expect (_dlfcn_hook != NULL, 0)) + 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); --- libc/dlfcn/sdlvsym.c.jj 2004-10-18 21:20:12.850097876 +0200 +++ libc/dlfcn/sdlvsym.c 2004-10-18 21:20:12.850097876 +0200 @@ -0,0 +1 @@ +#include "dlvsym.c" --- libc/dlfcn/dladdr1.c.jj 2003-03-10 10:12:11.000000000 +0100 +++ libc/dlfcn/dladdr1.c 2004-10-18 20:58:19.241275042 +0200 @@ -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 *i return _dl_addr (address, info, (struct link_map **) extra, NULL); } } +# ifdef SHARED +strong_alias (__dladdr1, dladdr1) +# endif +#endif --- libc/dlfcn/Versions.jj 2004-10-15 23:08:32.000000000 +0200 +++ libc/dlfcn/Versions 2004-10-18 21:40:34.580972066 +0200 @@ -11,4 +11,7 @@ libdl { GLIBC_2.3.4 { dlmopen; } + GLIBC_PRIVATE { + _dlfcn_hook; + } } --- libc/dlfcn/sdlmopen.c.jj 2004-10-18 21:20:12.000000000 +0200 +++ libc/dlfcn/sdlmopen.c 2004-10-18 23:47:35.610820109 +0200 @@ -0,0 +1 @@ +#include "dlmopen.c" --- libc/dlfcn/sdlsym.c.jj 2004-10-18 21:20:12.849098055 +0200 +++ libc/dlfcn/sdlsym.c 2004-10-18 21:20:12.849098055 +0200 @@ -0,0 +1 @@ +#include "dlsym.c" --- libc/dlfcn/sdlerror.c.jj 2004-10-18 21:20:12.847098412 +0200 +++ libc/dlfcn/sdlerror.c 2004-10-18 21:20:12.847098412 +0200 @@ -0,0 +1 @@ +#include "dlerror.c" --- libc/dlfcn/dlmopen.c.jj 2004-10-14 03:46:27.000000000 +0200 +++ libc/dlfcn/dlmopen.c 2004-10-18 23:42:29.348188934 +0200 @@ -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 --- libc/dlfcn/sdlclose.c.jj 2004-10-18 21:20:12.846098591 +0200 +++ libc/dlfcn/sdlclose.c 2004-10-18 21:20:12.846098591 +0200 @@ -0,0 +1 @@ +#include "dlclose.c" --- libc/dlfcn/dlclose.c.jj 2001-07-06 06:54:45.000000000 +0200 +++ libc/dlfcn/dlclose.c 2004-10-18 20:59:07.666740989 +0200 @@ -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 --- libc/dlfcn/sdladdr1.c.jj 2004-10-18 21:20:12.845098770 +0200 +++ libc/dlfcn/sdladdr1.c 2004-10-18 21:20:12.845098770 +0200 @@ -0,0 +1 @@ +#include "dladdr1.c" --- libc/elf/dl-libc.c.jj 2004-10-15 23:08:33.000000000 +0200 +++ libc/elf/dl-libc.c 2004-10-18 19:00:55.139108595 +0200 @@ -121,7 +121,6 @@ do_dlsym_private (void *ptr) vers.hidden = 1; /* vers.hash = _dl_elf_hash (version); */ vers.hash = 0x0963cf85; - /* FIXME: Shouldn't we use libc.so.6* here? */ vers.filename = NULL; struct do_dlsym_args *args = (struct do_dlsym_args *) ptr; @@ -156,23 +155,36 @@ __libc_dlopen_mode (const char *name, in if (dlerror_run (do_dlopen, &args)) return NULL; + __libc_register_dl_open_hook (args.map); + __libc_register_dlfcn_hook (args.map); + return (void *) args.map; +#endif +} +libc_hidden_def (__libc_dlopen_mode) + +#ifndef SHARED +void * +__libc_dlsym_private (struct link_map *map, const char *name) +{ struct do_dlsym_args sargs; - sargs.map = args.map; - sargs.name = "_dl_open_hook"; + sargs.map = map; + sargs.name = name; if (! dlerror_run (do_dlsym_private, &sargs)) - { - struct dl_open_hook **hook - = (struct dl_open_hook **) - (DL_SYMBOL_ADDRESS (sargs.loadbase, sargs.ref)); - if (hook != NULL) - *hook = &_dl_open_hook; - } + return DL_SYMBOL_ADDRESS (sargs.loadbase, sargs.ref); + return NULL; +} - return (void *) args.map; -#endif +void +__libc_register_dl_open_hook (struct link_map *map) +{ + struct dl_open_hook **hook; + + hook = (struct dl_open_hook **) __libc_dlsym_private (map, "_dl_open_hook"); + if (hook != NULL) + *hook = &_dl_open_hook; } -libc_hidden_def (__libc_dlopen_mode) +#endif void * __libc_dlsym (void *map, const char *name) --- libc/include/libc-symbols.h.jj 2004-10-18 10:20:44.000000000 +0200 +++ libc/include/libc-symbols.h 2004-10-18 18:16:08.989695011 +0200 @@ -762,6 +762,24 @@ for linking") # define libresolv_hidden_data_ver(local, name) #endif +#if defined NOT_IN_libc && defined IS_IN_libdl +# define libdl_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libdl_hidden_def(name) hidden_def (name) +# define libdl_hidden_weak(name) hidden_weak (name) +# define libdl_hidden_ver(local, name) hidden_ver (local, name) +# define libdl_hidden_data_def(name) hidden_data_def (name) +# define libdl_hidden_data_weak(name) hidden_data_weak (name) +# define libdl_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libdl_hidden_proto(name, attrs...) +# define libdl_hidden_def(name) +# define libdl_hidden_weak(name) +# define libdl_hidden_ver(local, name) +# define libdl_hidden_data_def(name) +# define libdl_hidden_data_weak(name) +# define libdl_hidden_data_ver(local, name) +#endif + #ifdef HAVE_BUILTIN_REDIRECTION # define libc_hidden_builtin_proto(name, attrs...) libc_hidden_proto (name, ##attrs) # define libc_hidden_builtin_def(name) libc_hidden_def (name) --- libc/include/dlfcn.h.jj 2004-10-15 23:08:33.000000000 +0200 +++ libc/include/dlfcn.h 2004-10-18 21:33:45.000000000 +0200 @@ -11,8 +11,6 @@ #define __LM_ID_CALLER -2 /* Now define the internal interfaces. */ -extern void *__dlvsym (void *__handle, __const char *__name, - __const char *__version); #define __libc_dlopen(name) __libc_dlopen_mode (name, RTLD_LAZY) extern void *__libc_dlopen_mode (__const char *__name, int __mode); @@ -76,4 +74,62 @@ extern int _dl_catch_error (const char * extern int _dlerror_run (void (*operate) (void *), void *args) internal_function; +#ifdef SHARED +# define DL_CALLER_DECL /* Nothing */ +# define DL_CALLER RETURN_ADDRESS (0) +#else +# define DL_CALLER_DECL , void *dl_caller +# define DL_CALLER dl_caller +#endif + +struct dlfcn_hook +{ + void *(*dlopen) (const char *file, int mode, void *dl_caller); + int (*dlclose) (void *handle); + void *(*dlsym) (void *handle, const char *name, void *dl_caller); + void *(*dlvsym) (void *handle, const char *name, const char *version, + void *dl_caller); + char *(*dlerror) (void); + int (*dladdr) (const void *address, Dl_info *info); + int (*dladdr1) (const void *address, Dl_info *info, + void **extra_info, int flags); + int (*dlinfo) (void *handle, int request, void *arg, void *dl_caller); + void *(*dlmopen) (Lmid_t nsid, const char *file, int mode, void *dl_caller); + void *pad[4]; +}; + +extern struct dlfcn_hook *_dlfcn_hook; +libdl_hidden_proto (_dlfcn_hook) + +extern void *__dlopen (const char *file, int mode DL_CALLER_DECL) + attribute_hidden; +extern void *__dlmopen (Lmid_t nsid, const char *file, int mode DL_CALLER_DECL) + attribute_hidden; +extern int __dlclose (void *handle) + attribute_hidden; +extern void *__dlsym (void *handle, const char *name DL_CALLER_DECL) + attribute_hidden; +extern void *__dlvsym (void *handle, const char *name, const char *version + DL_CALLER_DECL) + attribute_hidden; +extern char *__dlerror (void) + attribute_hidden; +extern int __dladdr (const void *address, Dl_info *info) + attribute_hidden; +extern int __dladdr1 (const void *address, Dl_info *info, + void **extra_info, int flags) + attribute_hidden; +extern int __dlinfo (void *handle, int request, void *arg DL_CALLER_DECL) + attribute_hidden; + +#ifndef SHARED +struct link_map; +extern void * __libc_dlsym_private (struct link_map *map, const char *name) + attribute_hidden; +extern void __libc_register_dl_open_hook (struct link_map *map) + attribute_hidden; +extern void __libc_register_dlfcn_hook (struct link_map *map) + attribute_hidden; +#endif + #endif Jakub
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |