Reorganize dlfcn.h slightly to separate out XSI and BSD interfaces.

Add new dlfunc() interface, which is a version of dlsym() with a
return type that can be cast to a function pointer without turning
your computer into a frog.

Reviewed by:	freebsd-standards
This commit is contained in:
Garrett Wollman 2002-05-29 16:25:43 +00:00
parent 1ec84e5051
commit dc12134a80
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=97475
4 changed files with 84 additions and 9 deletions

View file

@ -63,10 +63,31 @@ typedef struct dl_info {
void *dli_saddr; /* Address of nearest symbol */
} Dl_info;
/*
* The actual type declared by this typedef is immaterial, provided that
* it is a function pointer. Its purpose is to provide a return type for
* dlfunc() which can be cast to a function pointer type without depending
* on behavior undefined by the C standard, which might trigger a compiler
* diagnostic. We intentionally declare a unique type signature to force
* a diagnostic should the application not cast the return value of dlfunc()
* appropriately.
*/
struct __dlfunc_arg {
int __dlfunc_dummy;
};
typedef void (*__dlfunc_t)(struct __dlfunc_arg);
__BEGIN_DECLS
int dladdr(const void *, Dl_info *);
/* XSI functions first */
int dlclose(void *);
const char *dlerror(void);
void *dlopen(const char *, int);
void *dlsym(void * /* __restrict */, const char * /* __restrict */);
#if __BSD_VISIBLE
int dladdr(const void *, Dl_info *);
__dlfunc_t dlfunc(void * /* __restrict */, const char * /* __restrict */);
void dllockinit(void *_context,
void *(*_lock_create)(void *_context),
void (*_rlock_acquire)(void *_lock),
@ -74,8 +95,7 @@ void dllockinit(void *_context,
void (*_lock_release)(void *_lock),
void (*_lock_destroy)(void *_lock),
void (*_context_destroy)(void *_context));
void *dlopen(const char *, int);
void *dlsym(void *, const char *);
#endif /* __BSD_VISIBLE */
__END_DECLS
#endif /* !_DLFCN_H_ */

View file

@ -8,7 +8,7 @@ SRCS+= __xuname.c _pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \
alarm.c arc4random.c assert.c basename.c \
clock.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
dlfcn.c drand48.c erand48.c err.c errlst.c \
dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c \
exec.c fmtcheck.c fnmatch.c fstab.c ftok.c fts.c \
getbootfile.c getbsize.c \
getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \

30
lib/libc/gen/dlfunc.c Normal file
View file

@ -0,0 +1,30 @@
/*
* 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 *handle, const char *symbol)
{
union {
void *d;
__dlfunc_t f;
} rv;
rv.d = dlsym(handle, symbol);
return (rv.f);
}

View file

@ -32,11 +32,11 @@
.\" @(#) dlopen.3 1.6 90/01/31 SMI
.\" $FreeBSD$
.\"
.Dd September 24, 1989
.Dd May 28, 2002
.Os
.Dt DLOPEN 3
.Sh NAME
.Nm dlopen , dlsym , dlerror , dlclose
.Nm dlopen , dlsym , dlfunc , dlerror , dlclose
.Nd programmatic interface to the dynamic linker
.Sh LIBRARY
.Lb libc
@ -46,6 +46,8 @@
.Fn dlopen "const char *path" "int mode"
.Ft void *
.Fn dlsym "void *handle" "const char *symbol"
.Ft __dlfunc_t
.Fn dlfunc "void *handle" "const char *symbol"
.Ft const char *
.Fn dlerror "void"
.Ft int
@ -214,17 +216,39 @@ could access the
.Fn getpid
with
.Li dlsym(RTLD_NEXT, \&"getpid\&") .
(Actually, the
.Fn dlfunc
interface, below, should be used, since
.Fn getpid
is a function and not a data object.)
.Pp
.Fn dlsym
returns a null pointer if the symbol cannot be found, and sets an error
condition which may be queried with
.Fn dlerror .
.Pp
.Fn dlfunc
implements all of the behavior of
.Fn dlsym ,
but has a return type which can be cast to a function pointer without
triggering compiler diagnostics.
.Po Fn dlsym
returns a data pointer; in the C standard, conversions between
data and function pointer types are undefined. Some compilers and
.Xr lint 1
utilities warn about such casts.
.Pc
The precise return type of
.Fn dlfunc
is unspecified; applications must cast it to an appropriate function pointer
type.
.Pp
.Fn dlerror
returns a null-terminated character string describing the last error that
occurred during a call to
.Fn dlopen ,
.Fn dlsym ,
.Fn dlfunc ,
or
.Fn dlclose .
If no such error has occurred,
@ -277,10 +301,11 @@ still the case when using the (obsolete)
.Fl aout
option to the C language compiler.
.Sh ERRORS
.Fn dlopen
.Fn dlopen ,
.Fn dlsym ,
and
.Fn dlsym
return the null pointer in the event of errors.
.Fn dlfunc
return a null pointer in the event of errors.
.Fn dlclose
returns 0 on success, or -1 if an error occurred.
Whenever an error has been detected, a message detailing it can be