From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12484 invoked by alias); 11 Jun 2003 20:32:09 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 12440 invoked from network); 11 Jun 2003 20:32:08 -0000 Received: from unknown (HELO localhost.localdomain) (195.113.19.66) by sources.redhat.com with SMTP; 11 Jun 2003 20:32:08 -0000 Received: from sunsite.ms.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by localhost.localdomain (8.12.8/8.12.8) with ESMTP id h5BKW6qO007694; Wed, 11 Jun 2003 22:32:06 +0200 Received: (from jakub@localhost) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8/Submit) id h5BKW6dP007692; Wed, 11 Jun 2003 22:32:06 +0200 Date: Wed, 11 Jun 2003 20:32:00 -0000 From: Jakub Jelinek To: Ulrich Drepper , Roland McGrath Cc: Glibc hackers Subject: [PATCH] Allow __libc_dlopen from libraries __libc_dlopen'ed by statically linked executables Message-ID: <20030611203206.GX24872@sunsite.ms.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2003-06/txt/msg00016.txt.bz2 Hi! This patch should make Thorsten's new nss_compat module working even from statically linked binaries. It will work only if the binaries are relinked, but I think we should be clear that there is no guarantee that statically linked binaries using NSS or iconv will work after glibc upgrade unless they have been recompiled/relinked with the new glibc. Tested with a statically linked binary __libc_dlopen'ing shared library doing getpwnam. The impact on libc.so.6 shouldn't be big, basically one more exported symbol, __WORDSIZE bytes in .bss section and in 3 different functions memory load + compare + jump to short unlikely code. 2003-06-11 Jakub Jelinek * elf/Versions (libc): Add _dl_open_hook@GLIBC_PRIVATE. * elf/dl-libc.c (struct dl_open_hook): New. (_dl_open_hook): New variable. (do_dlsym_private): New function. (__libc_dlopen_mode) [!SHARED]: Lookup _dl_open_hook@GLIBC_PRIVATE and initialize it if found. (__libc_dlopen_mode) [SHARED]: If _dl_open_hook is non-NULL, call dlopen_mode hook. (__libc_dlsym) [SHARED]: If _dl_open_hook is non-NULL, call dlsym hook. (__libc_dlclose) [SHARED]: If _dl_open_hook is non-NULL, call dlclose hook. --- libc/elf/Versions.jj 2003-03-20 05:58:48.000000000 -0500 +++ libc/elf/Versions 2003-06-11 10:57:15.000000000 -0400 @@ -21,6 +21,7 @@ libc { # functions used in other libraries _dl_open; _dl_close; _dl_addr; _dl_sym; _dl_vsym; + _dl_open_hook; } } --- libc/elf/dl-libc.c.jj 2002-11-24 19:57:43.000000000 -0500 +++ libc/elf/dl-libc.c 2003-06-11 11:53:10.000000000 -0400 @@ -96,6 +96,50 @@ do_dlclose (void *ptr) _dl_close ((struct link_map *) ptr); } +/* This code is to support __libc_dlopen from __libc_dlopen'ed shared + libraries. We need to ensure the statically linked __libc_dlopen + etc. functions are used instead of the dynamically loaded. */ +struct dl_open_hook +{ + void *(*dlopen_mode) (const char *name, int mode); + void *(*dlsym) (void *map, const char *name); + int (*dlclose) (void *map); +}; + +#ifdef SHARED +extern struct dl_open_hook *_dl_open_hook; +libc_hidden_proto (_dl_open_hook); +struct dl_open_hook *_dl_open_hook __attribute__((nocommon)); +libc_hidden_data_def (_dl_open_hook); +#else +static void +do_dlsym_private (void *ptr) +{ + lookup_t l; + struct r_found_version vers; + vers.name = "GLIBC_PRIVATE"; + 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; + args->ref = NULL; + l = _dl_lookup_versioned_symbol (args->name, args->map, + &args->ref, args->map->l_scope, + &vers, 0, 0); + args->loadbase = l; +} + +static struct dl_open_hook _dl_open_hook = + { + .dlopen_mode = __libc_dlopen_mode, + .dlsym = __libc_dlsym, + .dlclose = __libc_dlclose + }; +#endif + /* ... and these functions call dlerror_run. */ void * @@ -105,7 +149,29 @@ __libc_dlopen_mode (const char *name, in args.name = name; args.mode = mode; +#ifdef SHARED + if (__builtin_expect (_dl_open_hook != NULL, 0)) + return _dl_open_hook->dlopen_mode (name, mode); return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map); +#else + if (dlerror_run (do_dlopen, &args)) + return NULL; + + struct do_dlsym_args sargs; + sargs.map = args.map; + sargs.name = "_dl_open_hook"; + + 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 (void *) args.map; +#endif } void * @@ -115,6 +181,10 @@ __libc_dlsym (void *map, const char *nam args.map = map; args.name = name; +#ifdef SHARED + if (__builtin_expect (_dl_open_hook != NULL, 0)) + return _dl_open_hook->dlsym (map, name); +#endif return (dlerror_run (do_dlsym, &args) ? NULL : (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref))); } @@ -122,6 +192,10 @@ __libc_dlsym (void *map, const char *nam int __libc_dlclose (void *map) { +#ifdef SHARED + if (__builtin_expect (_dl_open_hook != NULL, 0)) + return _dl_open_hook->dlclose (map); +#endif return dlerror_run (do_dlclose, map); } Jakub