Resolve dlsym(3) and friends directly so that dlsym(RTLD_NEXT,...) works.
Previously dlsym resolved to the version in crt0.o or libc which would mean that the caller's shared object couldn't be determined correctly using __builtin_return_address(0). Mainly from FreeBSD, but adapted by me. Benefits of this solutions are: - backward comptibility maintained - existing broken binaries are fixed with a new ld.elf_so - __mainprog_obj can be removed from crt0.o - we do the same thing as FreeBSD Fixes PR 22067. OKed by Jason and Christos.
This commit is contained in:
parent
b4c1c6117c
commit
d900731978
|
@ -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 <dlfcn_stubs.c>
|
||||
#endif /* DYNAMIC */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
#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 <dlfcn_stubs.c>
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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 <matt@3am-software.com>
|
||||
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue