diff --git a/lib/csu/common_elf/common.c b/lib/csu/common_elf/common.c index de540d031a34..7c02c0280017 100644 --- a/lib/csu/common_elf/common.c +++ b/lib/csu/common_elf/common.c @@ -1,4 +1,4 @@ -/* $NetBSD: common.c,v 1.12 2003/07/26 19:24:26 salo Exp $ */ +/* $NetBSD: common.c,v 1.13 2003/08/12 09:18:42 skrll Exp $ */ /* * Copyright (c) 1995 Christopher G. Demetriou @@ -74,13 +74,4 @@ _rtld_setup(cleanup, obj) atexit(cleanup); } -#ifdef __weak_alias -__weak_alias(dlopen,_dlopen); -__weak_alias(dlclose,_dlclose); -__weak_alias(dlsym,_dlsym); -__weak_alias(dlerror,_dlerror); -__weak_alias(dladdr,_dladdr); -#endif - -#include #endif /* DYNAMIC */ diff --git a/lib/csu/common_elf/common.h b/lib/csu/common_elf/common.h index fe074255afec..76a788b99907 100644 --- a/lib/csu/common_elf/common.h +++ b/lib/csu/common_elf/common.h @@ -1,4 +1,4 @@ -/* $NetBSD: common.h,v 1.8 2003/07/26 19:24:26 salo Exp $ */ +/* $NetBSD: common.h,v 1.9 2003/08/12 09:18:42 skrll Exp $ */ /* * Copyright (c) 1995 Christopher G. Demetriou @@ -75,8 +75,6 @@ extern void _fini __P((void)); #ifdef DYNAMIC void _rtld_setup __P((void (*)(void), const Obj_Entry *obj)); -const Obj_Entry *__mainprog_obj; - /* * Arrange for _DYNAMIC to be weak and undefined (and therefore to show up * as being at address zero, unless something else defines it). That way, diff --git a/lib/libc/dlfcn/dlfcn_elf.c b/lib/libc/dlfcn/dlfcn_elf.c index c485d567e686..381133ca6211 100644 --- a/lib/libc/dlfcn/dlfcn_elf.c +++ b/lib/libc/dlfcn/dlfcn_elf.c @@ -1,4 +1,4 @@ -/* $NetBSD: dlfcn_elf.c,v 1.3 2002/07/20 08:54:04 yamt Exp $ */ +/* $NetBSD: dlfcn_elf.c,v 1.4 2003/08/12 09:18:43 skrll Exp $ */ /* * Copyright (c) 2000 Takuya SHIOZAKI @@ -27,7 +27,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: dlfcn_elf.c,v 1.3 2002/07/20 08:54:04 yamt Exp $"); +__RCSID("$NetBSD: dlfcn_elf.c,v 1.4 2003/08/12 09:18:43 skrll Exp $"); #endif /* LIBC_SCCS and not lint */ #include "namespace.h" @@ -35,11 +35,6 @@ __RCSID("$NetBSD: dlfcn_elf.c,v 1.3 2002/07/20 08:54:04 yamt Exp $"); #define ELFSIZE ARCH_ELFSIZE #include "rtld.h" -#ifdef __weak_extern -__weak_extern(__mainprog_obj) -#endif -extern const Obj_Entry *__mainprog_obj; - #ifdef __weak_alias __weak_alias(dlopen,__dlopen) __weak_alias(dlclose,__dlclose) @@ -48,4 +43,54 @@ __weak_alias(dlerror,__dlerror) __weak_alias(dladdr,__dladdr) #endif -#include +/* + * For ELF, the dynamic linker directly resolves references to its + * services to functions inside the dynamic linker itself. These + * weak-symbol stubs are necessary so that "ld" won't complain about + * undefined symbols. The stubs are executed only when the program is + * linked statically, or when a given service isn't implemented in the + * dynamic linker. They must return an error if called, and they must + * be weak symbols so that the dynamic linker can override them. + */ + +static char dlfcn_error[] = "Service unavailable"; + +/*ARGSUSED*/ +void * +dlopen(const char *name, int mode) +{ + + return NULL; +} + +/*ARGSUSED*/ +int +dlclose(void *fd) +{ + + return -1; +} + +/*ARGSUSED*/ +void * +dlsym(void *handle, const char *name) +{ + + return NULL; +} + +/*ARGSUSED*/ +__aconst char * +dlerror() +{ + + return dlfcn_error; +} + +/*ARGSUSED*/ +int +dladdr(const void *addr, Dl_info *dli) +{ + + return 0; +} diff --git a/lib/libc/dlfcn/dlfcn_stubs.c b/lib/libc/dlfcn/dlfcn_stubs.c deleted file mode 100644 index 0427fb9d0a2f..000000000000 --- a/lib/libc/dlfcn/dlfcn_stubs.c +++ /dev/null @@ -1,102 +0,0 @@ -/* $NetBSD: dlfcn_stubs.c,v 1.4 2003/07/26 19:24:41 salo Exp $ */ - -/* - * Copyright (c) 1995 Christopher G. Demetriou - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the - * NetBSD Project. See http://www.NetBSD.org/ for - * information about NetBSD. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * <> - */ - -/* - * NOT A STANDALONE FILE! - */ - -void * -dlopen(name, mode) - const char *name; - int mode; -{ - - if (__mainprog_obj == NULL) - return NULL; - return (__mainprog_obj->dlopen)(name, mode); -} - -int -dlclose(fd) - void *fd; -{ - - if (__mainprog_obj == NULL) - return -1; - return (__mainprog_obj->dlclose)(fd); -} - -void * -dlsym(fd, name) - void *fd; - const char *name; -{ - - if (__mainprog_obj == NULL) - return NULL; - return (__mainprog_obj->dlsym)(fd, name); -} - -#if 0 /* not supported for ELF shlibs, apparently */ -int -dlctl(fd, cmd, arg) - void *fd, *arg; - int cmd; -{ - - if (__mainprog_obj == NULL) - return -1; - return (__mainprog_obj->dlctl)(fd, cmd, arg); -} -#endif - -__aconst char * -dlerror() -{ - - if (__mainprog_obj == NULL) - return ("Dynamic linker interface not available"); - return (__mainprog_obj->dlerror)(); -} - -int -dladdr(const void *addr, Dl_info *dli) -{ - - if (__mainprog_obj == NULL) - return -1; - return (__mainprog_obj->dladdr)(addr, dli); -} diff --git a/libexec/ld.elf_so/reloc.c b/libexec/ld.elf_so/reloc.c index 50ef8e1ba3e4..f3376631b822 100644 --- a/libexec/ld.elf_so/reloc.c +++ b/libexec/ld.elf_so/reloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: reloc.c,v 1.80 2003/07/24 10:12:26 skrll Exp $ */ +/* $NetBSD: reloc.c,v 1.81 2003/08/12 09:18:46 skrll Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -196,11 +196,11 @@ _rtld_relocate_objects(Obj_Entry *first, bool bind_now) obj->version = RTLD_VERSION; /* Fill in the dynamic linker entry points. */ - obj->dlopen = _rtld_dlopen; - obj->dlsym = _rtld_dlsym; - obj->dlerror = _rtld_dlerror; - obj->dlclose = _rtld_dlclose; - obj->dladdr = _rtld_dladdr; + obj->dlopen = dlopen; + obj->dlsym = dlsym; + obj->dlerror = dlerror; + obj->dlclose = dlclose; + obj->dladdr = dladdr; dbg(("fixing up PLTGOT")); /* Set the special PLTGOT entries. */ diff --git a/libexec/ld.elf_so/rtld.c b/libexec/ld.elf_so/rtld.c index 1bac1d97490f..bc4178871852 100644 --- a/libexec/ld.elf_so/rtld.c +++ b/libexec/ld.elf_so/rtld.c @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.c,v 1.98 2003/07/24 10:12:26 skrll Exp $ */ +/* $NetBSD: rtld.c,v 1.99 2003/08/12 09:18:48 skrll Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -433,6 +433,9 @@ _rtld(Elf_Addr *sp, Elf_Addr relocbase) real_environ = _rtld_objmain_sym("environ"); if (real_environ) *real_environ = environ; + /* + * Set __mainprog_obj for old binaries. + */ real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj"); if (real___mainprog_obj) *real___mainprog_obj = _rtld_objmain; @@ -458,7 +461,7 @@ _rtld(Elf_Addr *sp, Elf_Addr relocbase) void _rtld_die(void) { - const char *msg = _rtld_dlerror(); + const char *msg = dlerror(); if (msg == NULL) msg = "Fatal error"; @@ -573,7 +576,7 @@ _rtld_unref_dag(Obj_Entry *root) } int -_rtld_dlclose(void *handle) +dlclose(void *handle) { Obj_Entry *root = _rtld_dlcheck(handle); @@ -593,7 +596,7 @@ _rtld_dlclose(void *handle) } char * -_rtld_dlerror(void) +dlerror(void) { char *msg = error_message; @@ -602,7 +605,7 @@ _rtld_dlerror(void) } void * -_rtld_dlopen(const char *name, int mode) +dlopen(const char *name, int mode) { Obj_Entry **old_obj_tail = _rtld_objtail; Obj_Entry *obj = NULL; @@ -659,7 +662,7 @@ _rtld_objmain_sym(const char *name) } void * -_rtld_dlsym(void *handle, const char *name) +dlsym(void *handle, const char *name) { const Obj_Entry *obj; unsigned long hash; @@ -745,7 +748,7 @@ _rtld_dlsym(void *handle, const char *name) } int -_rtld_dladdr(const void *addr, Dl_info *info) +dladdr(const void *addr, Dl_info *info) { const Obj_Entry *obj; const Elf_Sym *def, *best_def; diff --git a/libexec/ld.elf_so/rtld.h b/libexec/ld.elf_so/rtld.h index 654615fab0c6..9a68445468a6 100644 --- a/libexec/ld.elf_so/rtld.h +++ b/libexec/ld.elf_so/rtld.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.h,v 1.69 2003/07/24 10:12:26 skrll Exp $ */ +/* $NetBSD: rtld.h,v 1.70 2003/08/12 09:18:49 skrll Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -211,15 +211,20 @@ extern Objlist _rtld_list_main; extern Elf_Sym _rtld_sym_zero; /* rtld.c */ + +/* + * We export these symbols using _rtld_symbol_lookup and is_exported. + */ +char *dlerror(void); +void *dlopen(const char *, int); +void *dlsym(void *, const char *); +int dlclose(void *); +int dladdr(const void *, Dl_info *); + void _rtld_error(const char *, ...) __attribute__((__format__(__printf__,1,2))); void _rtld_die(void); -char *_rtld_dlerror(void); -void *_rtld_dlopen(const char *, int); void *_rtld_objmain_sym(const char *); -void *_rtld_dlsym(void *, const char *); -int _rtld_dlclose(void *); -int _rtld_dladdr(const void *, Dl_info *); void _rtld_debug_state(void); void _rtld_linkmap_add(Obj_Entry *); void _rtld_linkmap_delete(Obj_Entry *); diff --git a/libexec/ld.elf_so/search.c b/libexec/ld.elf_so/search.c index 7e5655e5b2ff..94ab1a4a5e83 100644 --- a/libexec/ld.elf_so/search.c +++ b/libexec/ld.elf_so/search.c @@ -1,4 +1,4 @@ -/* $NetBSD: search.c,v 1.17 2003/07/24 10:12:26 skrll Exp $ */ +/* $NetBSD: search.c,v 1.18 2003/08/12 09:18:50 skrll Exp $ */ /* * Copyright 1996 Matt Thomas @@ -127,7 +127,7 @@ _rtld_load_library(const char *name, const Obj_Entry *refobj, int mode) } dbg((" Searching for \"%s\" (%p)", name, refobj)); - tmperrorp = _rtld_dlerror(); + tmperrorp = dlerror(); if (tmperrorp != NULL) { strncpy(tmperror, tmperrorp, sizeof tmperror); tmperrorp = tmperror; @@ -165,7 +165,7 @@ pathfound: if (tmperrorp) _rtld_error("%s", tmperror); else - (void)_rtld_dlerror(); + (void)dlerror(); return obj; found: diff --git a/libexec/ld.elf_so/symbol.c b/libexec/ld.elf_so/symbol.c index b53ea72d498c..e259aab198bb 100644 --- a/libexec/ld.elf_so/symbol.c +++ b/libexec/ld.elf_so/symbol.c @@ -1,4 +1,4 @@ -/* $NetBSD: symbol.c,v 1.32 2003/08/05 19:41:53 skrll Exp $ */ +/* $NetBSD: symbol.c,v 1.33 2003/08/12 09:18:50 skrll Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -53,6 +53,29 @@ #include "debug.h" #include "rtld.h" +static bool +_rtld_is_exported(const Elf_Sym *def) +{ + static Elf_Addr _rtld_exports[] = { + (Elf_Addr)dlopen, + (Elf_Addr)dlclose, + (Elf_Addr)dlsym, + (Elf_Addr)dlerror, + (Elf_Addr)dladdr, + NULL + }; + int i; + + Elf_Addr value; + value = (Elf_Addr)(_rtld_objself.relocbase + def->st_value); + + for (i = 0; _rtld_exports[i] != NULL; i++) { + if (value == _rtld_exports[i]) + return true; + } + return false; +} + /* * Hash function for symbol table lookup. Don't even think about changing * this. It is specified by the System V ABI. @@ -225,6 +248,20 @@ _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj, } } + /* + * Search the dynamic linker itself, and possibly resolve the + * symbol from there. This is how the application links to + * dynamic linker services such as dlopen. Only the values listed + * in the "_rtld_exports" array can be resolved from the dynamic linker. + */ + if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { + symp = _rtld_symlook_obj(name, hash, &_rtld_objself, in_plt); + if (symp != NULL && _rtld_is_exported(symp)) { + def = symp; + defobj = &_rtld_objself; + } + } + /* * If we found no definition and the reference is weak, treat the * symbol as having the value zero. @@ -234,7 +271,7 @@ _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj, def = &_rtld_sym_zero; defobj = _rtld_objmain; } - + if (def != NULL) *defobj_out = defobj; else { diff --git a/usr.bin/ldd/ldd_elf/ldd.c b/usr.bin/ldd/ldd_elf/ldd.c index d906093a0432..48ac6f33e672 100644 --- a/usr.bin/ldd/ldd_elf/ldd.c +++ b/usr.bin/ldd/ldd_elf/ldd.c @@ -1,4 +1,4 @@ -/* $NetBSD: ldd.c,v 1.19 2003/05/28 20:45:39 dsl Exp $ */ +/* $NetBSD: ldd.c,v 1.20 2003/08/12 09:18:38 skrll Exp $ */ /*- * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. @@ -197,7 +197,7 @@ _rtld_error(const char *fmt, ...) } char * -_rtld_dlerror() +dlerror() { char *msg = error_message; error_message = NULL;