summaryrefslogtreecommitdiffstats
path: root/lib/csu/i386
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>1997-08-02 04:56:44 +0000
committerjdp <jdp@FreeBSD.org>1997-08-02 04:56:44 +0000
commit2ed649b29bd1a1fa268f541c5f3195c4991cbfdc (patch)
treeed789b37fcc472aafb171c517eb3204ef69c2334 /lib/csu/i386
parentc0b9ea4c76fc283b66952dea5e873a3cb2b26a8c (diff)
downloadFreeBSD-src-2ed649b29bd1a1fa268f541c5f3195c4991cbfdc.zip
FreeBSD-src-2ed649b29bd1a1fa268f541c5f3195c4991cbfdc.tar.gz
Implement dlsym(RTLD_NEXT, symbol).
Diffstat (limited to 'lib/csu/i386')
-rw-r--r--lib/csu/i386/crt0.c21
-rw-r--r--lib/csu/i386/dlfcn.h7
-rw-r--r--lib/csu/i386/dlopen.322
3 files changed, 42 insertions, 8 deletions
diff --git a/lib/csu/i386/crt0.c b/lib/csu/i386/crt0.c
index 5f7e4ab..4d217fb 100644
--- a/lib/csu/i386/crt0.c
+++ b/lib/csu/i386/crt0.c
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id$
+ * $Id: crt0.c,v 1.29 1997/02/22 14:57:44 peter Exp $
*/
#include <sys/param.h>
@@ -94,6 +94,8 @@ static char empty[1];
char *__progname = empty;
char **environ;
+static int ldso_version;
+
extern unsigned char etext;
extern unsigned char eprol asm ("eprol");
extern start() asm("start");
@@ -194,7 +196,6 @@ __do_dynamic_link ()
struct exec hdr;
char *ldso;
int (*entry)();
- int ret;
#ifdef DEBUG
/* Provision for alternate ld.so - security risk! */
@@ -254,14 +255,14 @@ __do_dynamic_link ()
crt.crt_ldentry = NULL;
entry = (int (*)())(crt.crt_ba + sizeof hdr);
- ret = (*entry)(CRT_VERSION_BSD_4, &crt);
+ ldso_version = (*entry)(CRT_VERSION_BSD_4, &crt);
ld_entry = crt.crt_ldentry;
- if (ret == -1 && ld_entry == NULL) {
+ if (ldso_version == -1 && ld_entry == NULL) {
/* if version 4 not recognised, try version 3 */
- ret = (*entry)(CRT_VERSION_BSD_3, &crt);
+ ldso_version = (*entry)(CRT_VERSION_BSD_3, &crt);
ld_entry = _DYNAMIC.d_entry;
}
- if (ret == -1) {
+ if (ldso_version == -1) {
_PUTMSG("ld.so failed");
if (ld_entry != NULL) {
char *msg = (ld_entry->dlerror)();
@@ -277,7 +278,7 @@ __do_dynamic_link ()
}
- if (ret >= LDSO_VERSION_HAS_DLEXIT)
+ if (ldso_version >= LDSO_VERSION_HAS_DLEXIT)
atexit(ld_entry->dlexit);
return;
@@ -316,7 +317,11 @@ char *name;
if (ld_entry == NULL)
return NULL;
- return (ld_entry->dlsym)(fd, name);
+ if (ldso_version >= LDSO_VERSION_HAS_DLSYM3) {
+ void *retaddr = *(&fd - 1); /* XXX - ABI/machine dependent */
+ return (ld_entry->dlsym3)(fd, name, retaddr);
+ } else
+ return (ld_entry->dlsym)(fd, name);
}
diff --git a/lib/csu/i386/dlfcn.h b/lib/csu/i386/dlfcn.h
index feadf90..b6817fe 100644
--- a/lib/csu/i386/dlfcn.h
+++ b/lib/csu/i386/dlfcn.h
@@ -43,6 +43,13 @@
#define RTLD_LAZY 1 /* Bind function calls lazily */
#define RTLD_NOW 2 /* Bind function calls immediately */
+/*
+ * Special handle argument for dlsym(). It causes the search for the
+ * symbol to begin in the next shared object after the one containing
+ * the caller.
+ */
+#define RTLD_NEXT ((void *) -1)
+
__BEGIN_DECLS
void *dlopen __P((char *, int));
void *dlsym __P((void *, char *));
diff --git a/lib/csu/i386/dlopen.3 b/lib/csu/i386/dlopen.3
index 82651c6..efd59be 100644
--- a/lib/csu/i386/dlopen.3
+++ b/lib/csu/i386/dlopen.3
@@ -152,6 +152,28 @@ returns a null pointer if the symbol cannot be found, and sets an error
condition which may be queried with
.Fn dlerror .
.Pp
+If
+.Fn dlsym
+is called with the special
+.Fa handle
+.Dv RTLD_NEXT ,
+then the search for the symbol is limited to the shared objects
+which were loaded after the one issuing the call to
+.Fn dlsym .
+Thus, if the function is called from the main program, all
+the shared libraries are searched.
+If it is called from a shared library, all subsequent shared
+libraries are searched.
+.Dv RTLD_NEXT
+is useful for implementing wrappers around library functions.
+For example, a wrapper function
+.Fn getpid
+could access the
+.Dq real
+.Fn getpid
+with
+.Li dlsym(RTLD_NEXT, \&"_getpid\&") .
+.Pp
.Fn dlerror
returns a null-terminated character string describing the last error that
occurred during a call to
OpenPOWER on IntegriCloud