summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>2002-05-29 16:25:43 +0000
committerwollman <wollman@FreeBSD.org>2002-05-29 16:25:43 +0000
commit5bbebb88fb23509498ba2cbfc2a894bbaa78d31c (patch)
tree876b8b56f5abc5a10b03f80b310b2547dc76e4bc
parent929b4f74103ca2c710f7c4dd59c78d91fec585b4 (diff)
downloadFreeBSD-src-5bbebb88fb23509498ba2cbfc2a894bbaa78d31c.zip
FreeBSD-src-5bbebb88fb23509498ba2cbfc2a894bbaa78d31c.tar.gz
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
-rw-r--r--include/dlfcn.h26
-rw-r--r--lib/libc/gen/Makefile.inc2
-rw-r--r--lib/libc/gen/dlfunc.c30
-rw-r--r--lib/libc/gen/dlopen.335
4 files changed, 84 insertions, 9 deletions
diff --git a/include/dlfcn.h b/include/dlfcn.h
index 13fd684..38a38be 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -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_ */
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index cb17c54..8d8fe95 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -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 \
diff --git a/lib/libc/gen/dlfunc.c b/lib/libc/gen/dlfunc.c
new file mode 100644
index 0000000..e3b7959
--- /dev/null
+++ b/lib/libc/gen/dlfunc.c
@@ -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);
+}
+
diff --git a/lib/libc/gen/dlopen.3 b/lib/libc/gen/dlopen.3
index 50b0599..aa7d00f 100644
--- a/lib/libc/gen/dlopen.3
+++ b/lib/libc/gen/dlopen.3
@@ -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
OpenPOWER on IntegriCloud