Allow the NULL, RTLD_SELF and RTLD_NEXT handles to work with dlfunc(3).

dlfunc() called dlsym() to do the work, and dlsym() determines the dso
that originating the call by the return address. Due to this, dlfunc()
operated as if the caller is always the libc.

To fix this, move the dlfunc() to rtld, where it can call the internal
implementation of dlsym, and still correctly fetch return address.
Provide usual weak stub for the symbol from libc for static binaries.
dlfunc is put to FBSD_1.0 symver namespace in the ld.so export to
override dlfunc@FBSD_1.0 weak symbol, exported by libc.

Reported, analyzed and tested by:	Tijl Coosemans <tijl ulyssis org>
PR: standards/133339
Reviewed by:	kan
This commit is contained in:
Konstantin Belousov 2009-04-03 19:17:23 +00:00
parent 6437e6da3d
commit c8da4f07d7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=190673
5 changed files with 24 additions and 31 deletions

View File

@ -9,7 +9,7 @@ SRCS+= __getosreldate.c __xuname.c \
alarm.c arc4random.c assert.c basename.c check_utility_compat.c \
clock.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c errno.c \
dlfcn.c drand48.c erand48.c err.c errlst.c errno.c \
exec.c fdevname.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \
fpclassify.c frexp.c fstab.c ftok.c fts.c fts-compat.c ftw.c \
getbootfile.c getbsize.c \

View File

@ -105,6 +105,14 @@ dlsym(void * __restrict handle, const char * __restrict name)
return NULL;
}
#pragma weak dlfunc
dlfunc_t
dlfunc(void * __restrict handle, const char * __restrict name)
{
_rtld_error(sorry);
return NULL;
}
#pragma weak dlvsym
void *
dlvsym(void * __restrict handle, const char * __restrict name,

View File

@ -1,30 +0,0 @@
/*
* This source file is in the public domain.
* Garrett A. Wollman, 2002-05-28.
*
* $FreeBSD$
*/
#include <dlfcn.h>
/*
* Implement the dlfunc() interface, which behaves exactly the same as
* dlsym() except that it returns a function pointer instead of a data
* pointer. This can be used by applications to avoid compiler warnings
* about undefined behavior, and is intended as prior art for future
* POSIX standardization. This function requires that all pointer types
* have the same representation, which is true on all platforms FreeBSD
* runs on, but is not guaranteed by the C standard.
*/
dlfunc_t
dlfunc(void * __restrict handle, const char * __restrict symbol)
{
union {
void *d;
dlfunc_t f;
} rv;
rv.d = dlsym(handle, symbol);
return (rv.f);
}

View File

@ -8,6 +8,7 @@ FBSD_1.0 {
dlerror;
dlopen;
dlsym;
dlfunc;
dlvsym;
dladdr;
dllockinit;

View File

@ -200,6 +200,7 @@ static func_ptr_type exports[] = {
(func_ptr_type) &dlerror,
(func_ptr_type) &dlopen,
(func_ptr_type) &dlsym,
(func_ptr_type) &dlfunc,
(func_ptr_type) &dlvsym,
(func_ptr_type) &dladdr,
(func_ptr_type) &dllockinit,
@ -2170,6 +2171,19 @@ dlsym(void *handle, const char *name)
SYMLOOK_DLSYM);
}
dlfunc_t
dlfunc(void *handle, const char *name)
{
union {
void *d;
dlfunc_t f;
} rv;
rv.d = do_dlsym(handle, name, __builtin_return_address(0), NULL,
SYMLOOK_DLSYM);
return (rv.f);
}
void *
dlvsym(void *handle, const char *name, const char *version)
{