From c8da4f07d763e3bb6769ab4b7cb83774ecbac824 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Fri, 3 Apr 2009 19:17:23 +0000 Subject: [PATCH] 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 PR: standards/133339 Reviewed by: kan --- lib/libc/gen/Makefile.inc | 2 +- lib/libc/gen/dlfcn.c | 8 ++++++++ lib/libc/gen/dlfunc.c | 30 ------------------------------ libexec/rtld-elf/Symbol.map | 1 + libexec/rtld-elf/rtld.c | 14 ++++++++++++++ 5 files changed, 24 insertions(+), 31 deletions(-) delete mode 100644 lib/libc/gen/dlfunc.c diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index a7997ab8c36..0ee2ffb259a 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -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 \ diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c index eac3f1a1396..4be88475a91 100644 --- a/lib/libc/gen/dlfcn.c +++ b/lib/libc/gen/dlfcn.c @@ -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, diff --git a/lib/libc/gen/dlfunc.c b/lib/libc/gen/dlfunc.c deleted file mode 100644 index 72a683a055d..00000000000 --- a/lib/libc/gen/dlfunc.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This source file is in the public domain. - * Garrett A. Wollman, 2002-05-28. - * - * $FreeBSD$ - */ - -#include - -/* - * 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); -} - diff --git a/libexec/rtld-elf/Symbol.map b/libexec/rtld-elf/Symbol.map index 20f8d60f361..ce1e3e5f2b3 100644 --- a/libexec/rtld-elf/Symbol.map +++ b/libexec/rtld-elf/Symbol.map @@ -8,6 +8,7 @@ FBSD_1.0 { dlerror; dlopen; dlsym; + dlfunc; dlvsym; dladdr; dllockinit; diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 07529b3091c..40ed6edc3b1 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -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) {