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:
parent
6f490ce62d
commit
c288e4bb76
@ -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_ */
|
||||
|
@ -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
30
lib/libc/gen/dlfunc.c
Normal 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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user