summaryrefslogtreecommitdiffstats
path: root/lib/csu/i386
diff options
context:
space:
mode:
Diffstat (limited to 'lib/csu/i386')
-rw-r--r--lib/csu/i386/Makefile64
-rw-r--r--lib/csu/i386/c++rt0.c86
-rw-r--r--lib/csu/i386/crt0.c433
-rw-r--r--lib/csu/i386/dlfcn.h53
-rw-r--r--lib/csu/i386/dlopen.3213
5 files changed, 849 insertions, 0 deletions
diff --git a/lib/csu/i386/Makefile b/lib/csu/i386/Makefile
new file mode 100644
index 0000000..1b3e61f
--- /dev/null
+++ b/lib/csu/i386/Makefile
@@ -0,0 +1,64 @@
+# from: @(#)Makefile 5.6 (Berkeley) 5/22/91
+# $Id$
+
+CFLAGS+= -DLIBC_SCCS -fno-omit-frame-pointer
+OBJS= crt0.o c++rt0.o gcrt0.o scrt0.o sgcrt0.o
+CLEANFILES+= a.out
+MAN3+= dlopen.3
+MLINKS+= dlopen.3 dlsym.3 \
+ dlopen.3 dlerror.3 \
+ dlopen.3 dlclose.3
+
+all: ${OBJS}
+
+crt0.o: crt0.c
+ ${CC} ${CFLAGS} -c -DCRT0 -DDYNAMIC ${.CURDIR}/crt0.c -o ${.TARGET}
+ ${LD} -x -r ${.TARGET}
+ mv -f a.out ${.TARGET}
+
+c++rt0.o: c++rt0.c
+ ${CC} ${CFLAGS} -fpic -c ${.CURDIR}/c++rt0.c
+ @${LD} -x -r ${.TARGET}
+ @mv -f a.out ${.TARGET}
+
+#
+# gcrt0.o doesn't really depend on crt0.o, but this is the easiest way
+# to get the dependencies mostly correct.
+#
+gcrt0.o: crt0.o
+ ${CC} ${CFLAGS} -c -DMCRT0 -DDYNAMIC ${.CURDIR}/crt0.c -o ${.TARGET}
+ ${LD} -x -r ${.TARGET}
+ mv -f a.out ${.TARGET}
+
+# dependencies fudged as for gcrt0.o
+scrt0.o: crt0.o
+ ${CC} ${CFLAGS} -c -DCRT0 ${.CURDIR}/crt0.c -o ${.TARGET}
+ ${LD} -x -r ${.TARGET}
+ mv -f a.out ${.TARGET}
+
+# dependencies fudged as for gcrt0.o
+sgcrt0.o: scrt0.o
+ ${CC} ${CFLAGS} -c -DMCRT0 ${.CURDIR}/crt0.c -o ${.TARGET}
+ ${LD} -x -r ${.TARGET}
+ mv -f a.out ${.TARGET}
+
+beforeinstall:
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/dlfcn.h \
+ ${DESTDIR}/usr/include
+
+realinstall:
+.for i in ${OBJS}
+ ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m 444 $i \
+ ${DESTDIR}/usr/lib
+.endfor
+
+depend: .depend
+
+.depend: crt0.c c++rt0.c
+ rm -f .depend
+ mkdep ${CFLAGS} -DCRT0 -DDYNAMIC ${.CURDIR}/crt0.c
+ mkdep -a ${CFLAGS} ${.CURDIR}/c++rt0.c
+
+lint tags:
+
+.include <bsd.prog.mk>
diff --git a/lib/csu/i386/c++rt0.c b/lib/csu/i386/c++rt0.c
new file mode 100644
index 0000000..94fa5c5
--- /dev/null
+++ b/lib/csu/i386/c++rt0.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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$
+ */
+
+/*
+ * Run-time module for GNU C++ compiled shared libraries.
+ *
+ * The linker constructs the following arrays of pointers to global
+ * constructors and destructors. The first element contains the
+ * number of pointers in each.
+ * The tables are also null-terminated.
+ */
+void (*__CTOR_LIST__[2])(void);
+void (*__DTOR_LIST__[2])(void);
+
+static void
+__dtors(void)
+{
+ unsigned long i = (unsigned long) __DTOR_LIST__[0];
+ void (**p)(void) = __DTOR_LIST__ + i;
+
+ while (i--)
+ (**p--)();
+}
+
+static void
+__ctors(void)
+{
+ void (**p)(void) = __CTOR_LIST__ + 1;
+
+ while (*p)
+ (**p++)();
+}
+
+extern void __init() asm(".init");
+extern void __fini() asm(".fini");
+
+void
+__init(void)
+{
+ static int initialized = 0;
+
+ /*
+ * Call global constructors.
+ * Arrange to call global destructors at exit.
+ */
+ if (!initialized) {
+ initialized = 1;
+ __ctors();
+ }
+
+}
+
+void
+__fini(void)
+{
+ __dtors();
+}
diff --git a/lib/csu/i386/crt0.c b/lib/csu/i386/crt0.c
new file mode 100644
index 0000000..5f7e4ab
--- /dev/null
+++ b/lib/csu/i386/crt0.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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$
+ */
+
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#ifdef DYNAMIC
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <a.out.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <link.h>
+
+/* !!!
+ * This is gross, ld.so is a ZMAGIC a.out, but has `sizeof(hdr)' for
+ * an entry point and not at PAGSIZ as the N_*ADDR macros assume.
+ */
+#undef N_DATADDR
+#define N_DATADDR(x) ((x).a_text)
+
+#undef N_BSSADDR
+#define N_BSSADDR(x) ((x).a_text + (x).a_data)
+
+#ifndef N_GETMAGIC
+#define N_GETMAGIC(x) ((x).a_magic)
+#endif /* N_GETMAGIC */
+
+#ifndef MAP_PRIVATE
+#define MAP_PRIVATE MAP_COPY
+#endif /* MAP_PRIVATE */
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif /* MAP_FILE */
+
+#ifndef MAP_ANON
+#define MAP_ANON 0
+#endif /* MAP_ANON */
+
+#ifdef DEBUG
+/*
+ * We need these two because we are going to call them before the ld.so is
+ * finished (as a matter of fact before we know if it exists !) so we must
+ * provide these versions for them
+ */
+static char *_getenv();
+static int _strncmp();
+#endif /* DEBUG */
+
+#ifndef LDSO
+#define LDSO "/usr/libexec/ld.so"
+#endif /* LDSO */
+
+extern struct _dynamic _DYNAMIC;
+static struct ld_entry *ld_entry;
+static void __do_dynamic_link ();
+#endif /* DYNAMIC */
+
+int _callmain();
+int errno;
+static char empty[1];
+char *__progname = empty;
+char **environ;
+
+extern unsigned char etext;
+extern unsigned char eprol asm ("eprol");
+extern start() asm("start");
+extern mcount() asm ("mcount");
+extern int main(int argc, char **argv, char **envp);
+int __syscall(int syscall,...);
+#ifdef MCRT0
+void monstartup(void *low, void *high);
+#endif /* MCRT0 */
+
+
+/*
+ * We need these system calls, but can't use library stubs because the are
+ * not accessible until we have done the ld.so stunt.
+ */
+
+#define _exit(v) \
+ __syscall(SYS_exit, (int)(v))
+#define _open(name, f, m) \
+ __syscall(SYS_open, (char *)(name), (int)(f), (int)(m))
+#define _read(fd, s, n) \
+ __syscall(SYS_read, (int)(fd), (void *)(s), (size_t)(n))
+#define _write(fd, s, n) \
+ __syscall(SYS_write, (int)(fd), (void *)(s), (size_t)(n))
+#define _mmap(addr, len, prot, flags, fd, off) \
+ (caddr_t) __syscall(SYS_mmap, (caddr_t)(addr), (size_t)(len), \
+ (int)(prot), (int)(flags), (int)(fd), (long)0L, (off_t)(off))
+
+#define _PUTNMSG(str, len) _write(2, (str), (len))
+#define _PUTMSG(str) _PUTNMSG((str), sizeof (str) - 1)
+#define _FATAL(str) ( _PUTMSG(str), _exit(1) )
+
+
+int
+start()
+{
+ struct kframe {
+ int kargc;
+ char *kargv[1]; /* size depends on kargc */
+ char kargstr[1]; /* size varies */
+ char kenvstr[1]; /* size varies */
+ };
+ /*
+ * ALL REGISTER VARIABLES!!!
+ */
+ register struct kframe *kfp;
+ register char **targv;
+ register char **argv;
+ extern void _mcleanup();
+#ifdef DYNAMIC
+ volatile caddr_t x;
+#endif
+
+#ifdef lint
+ kfp = 0;
+#else /* not lint */
+ /* just above the saved frame pointer */
+ asm ("lea 4(%%ebp), %0" : "=r" (kfp) );
+#endif /* not lint */
+ for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
+ /* void */ ;
+ if (targv >= (char **)(*argv))
+ --targv;
+ environ = targv;
+
+ if (argv[0]) {
+ register char *s;
+ __progname = argv[0];
+ for (s=__progname; *s != '\0'; s++)
+ if (*s == '/')
+ __progname = s+1;
+ }
+
+#ifdef DYNAMIC
+ /* ld(1) convention: if DYNAMIC = 0 then statically linked */
+ /* sometimes GCC is too smart/stupid for its own good */
+ x = (caddr_t)&_DYNAMIC;
+ if (x)
+ __do_dynamic_link();
+#endif /* DYNAMIC */
+
+asm("eprol:");
+
+#ifdef MCRT0
+ atexit(_mcleanup);
+ monstartup(&eprol, &etext);
+#endif /* MCRT0 */
+
+asm ("__callmain:"); /* Defined for the benefit of debuggers */
+ exit(main(kfp->kargc, argv, environ));
+}
+
+#ifdef DYNAMIC
+static void
+__do_dynamic_link ()
+{
+ struct crt_ldso crt;
+ struct exec hdr;
+ char *ldso;
+ int (*entry)();
+ int ret;
+
+#ifdef DEBUG
+ /* Provision for alternate ld.so - security risk! */
+ if (!(ldso = _getenv("LDSO")))
+#endif
+ ldso = LDSO;
+
+ crt.crt_ldfd = _open(ldso, 0, 0);
+ if (crt.crt_ldfd == -1) {
+ _PUTMSG("Couldn't open ");
+ _PUTMSG(LDSO);
+ _FATAL(".\n");
+ }
+
+ /* Read LDSO exec header */
+ if (_read(crt.crt_ldfd, &hdr, sizeof hdr) < sizeof hdr) {
+ _FATAL("Failure reading ld.so\n");
+ }
+ if ((N_GETMAGIC_NET(hdr) != ZMAGIC) && (N_GETMAGIC(hdr) != QMAGIC)) {
+ _FATAL("Bad magic: ld.so\n");
+ }
+
+ /* We use MAP_ANON */
+ crt.crt_dzfd = -1;
+
+ /* Map in ld.so */
+ crt.crt_ba = (int)_mmap(0, hdr.a_text,
+ PROT_READ|PROT_EXEC,
+ MAP_FILE|MAP_PRIVATE,
+ crt.crt_ldfd, N_TXTOFF(hdr));
+ if (crt.crt_ba == -1) {
+ _FATAL("Cannot map ld.so (text)\n");
+ }
+
+ /* Map in data segment of ld.so writable */
+ if ((int)_mmap((caddr_t)(crt.crt_ba+N_DATADDR(hdr)), hdr.a_data,
+ PROT_READ|PROT_WRITE,
+ MAP_FIXED|MAP_FILE|MAP_PRIVATE,
+ crt.crt_ldfd, N_DATOFF(hdr)) == -1) {
+ _FATAL("Cannot map ld.so (data)\n");
+ }
+
+ /* Map bss segment of ld.so zero */
+ if (hdr.a_bss && (int)_mmap((caddr_t)(crt.crt_ba+N_BSSADDR(hdr)),
+ hdr.a_bss,
+ PROT_READ|PROT_WRITE,
+ MAP_FIXED|MAP_ANON|MAP_PRIVATE,
+ crt.crt_dzfd, 0) == -1) {
+ _FATAL("Cannot map ld.so (bss)\n");
+ }
+
+ crt.crt_dp = &_DYNAMIC;
+ crt.crt_ep = environ;
+ crt.crt_bp = (caddr_t)_callmain;
+ crt.crt_prog = __progname;
+ crt.crt_ldso = ldso;
+ crt.crt_ldentry = NULL;
+
+ entry = (int (*)())(crt.crt_ba + sizeof hdr);
+ ret = (*entry)(CRT_VERSION_BSD_4, &crt);
+ ld_entry = crt.crt_ldentry;
+ if (ret == -1 && ld_entry == NULL) {
+ /* if version 4 not recognised, try version 3 */
+ ret = (*entry)(CRT_VERSION_BSD_3, &crt);
+ ld_entry = _DYNAMIC.d_entry;
+ }
+ if (ret == -1) {
+ _PUTMSG("ld.so failed");
+ if (ld_entry != NULL) {
+ char *msg = (ld_entry->dlerror)();
+ if(msg != NULL) {
+ char *endp;
+ _PUTMSG(": ");
+ for(endp = msg; *endp != '\0'; ++endp)
+ ; /* Find the end */
+ _PUTNMSG(msg, endp - msg);
+ }
+ }
+ _FATAL("\n");
+ }
+
+
+ if (ret >= LDSO_VERSION_HAS_DLEXIT)
+ atexit(ld_entry->dlexit);
+
+ return;
+}
+
+/*
+ * DL stubs
+ */
+
+void *
+dlopen(name, mode)
+char *name;
+int mode;
+{
+ if (ld_entry == NULL)
+ return NULL;
+
+ return (ld_entry->dlopen)(name, mode);
+}
+
+int
+dlclose(fd)
+void *fd;
+{
+ if (ld_entry == NULL)
+ return -1;
+
+ return (ld_entry->dlclose)(fd);
+}
+
+void *
+dlsym(fd, name)
+void *fd;
+char *name;
+{
+ if (ld_entry == NULL)
+ return NULL;
+
+ return (ld_entry->dlsym)(fd, name);
+}
+
+
+char *
+dlerror()
+{
+ if (ld_entry == NULL)
+ return "Service unavailable";
+
+ return (ld_entry->dlerror)();
+}
+
+
+/*
+ * Support routines
+ */
+
+#ifdef DEBUG
+static int
+_strncmp(s1, s2, n)
+ register char *s1, *s2;
+ register n;
+{
+
+ if (n == 0)
+ return (0);
+ do {
+ if (*s1 != *s2++)
+ return (*(unsigned char *)s1 - *(unsigned char *)--s2);
+ if (*s1++ == 0)
+ break;
+ } while (--n != 0);
+ return (0);
+}
+
+static char *
+_getenv(name)
+ register char *name;
+{
+ extern char **environ;
+ register int len;
+ register char **P, *C;
+
+ for (C = name, len = 0; *C && *C != '='; ++C, ++len);
+ for (P = environ; *P; ++P)
+ if (!_strncmp(*P, name, len))
+ if (*(C = *P + len) == '=') {
+ return(++C);
+ }
+ return (char *)0;
+}
+
+#endif /* DEBUG */
+
+ asm(" ___syscall:");
+ asm(" popl %ecx");
+ asm(" popl %eax");
+ asm(" pushl %ecx");
+ asm(" .byte 0x9a");
+ asm(" .long 0");
+ asm(" .word 7");
+ asm(" pushl %ecx");
+ asm(" jc 1f");
+ asm(" ret");
+ asm(" 1:");
+ asm(" movl $-1,%eax");
+ asm(" ret");
+
+#else /* DYNAMIC */
+
+/*
+ * DL stubs for static linking case (just return error)
+ */
+
+void *
+dlopen(name, mode)
+char *name;
+int mode;
+{
+ return NULL;
+}
+
+int
+dlclose(fd)
+void *fd;
+{
+ return -1;
+}
+
+void *
+dlsym(fd, name)
+void *fd;
+char *name;
+{
+ return NULL;
+}
+
+
+char *
+dlerror()
+{
+ return "Service unavailable";
+}
+#endif /* DYNAMIC */
+
+
+/*
+ * Support routines
+ */
+
+#ifdef MCRT0
+asm (" .text");
+asm ("_eprol:");
+#endif
diff --git a/lib/csu/i386/dlfcn.h b/lib/csu/i386/dlfcn.h
new file mode 100644
index 0000000..feadf90
--- /dev/null
+++ b/lib/csu/i386/dlfcn.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)err.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _DLFCN_H_
+#define _DLFCN_H_
+#include <sys/cdefs.h>
+
+/*
+ * Modes for dlopen().
+ */
+#define RTLD_LAZY 1 /* Bind function calls lazily */
+#define RTLD_NOW 2 /* Bind function calls immediately */
+
+__BEGIN_DECLS
+void *dlopen __P((char *, int));
+void *dlsym __P((void *, char *));
+char *dlerror __P((void));
+int dlclose __P((void *));
+__END_DECLS
+
+#endif /* !_DLFCN_H_ */
diff --git a/lib/csu/i386/dlopen.3 b/lib/csu/i386/dlopen.3
new file mode 100644
index 0000000..82651c6
--- /dev/null
+++ b/lib/csu/i386/dlopen.3
@@ -0,0 +1,213 @@
+.\" This source code is a product of Sun Microsystems, Inc. and is provided
+.\" for unrestricted use provided that this legend is included on all tape
+.\" media and as a part of the software program in whole or part. Users
+.\" may copy or modify this source code without charge, but are not authorized
+.\" to license or distribute it to anyone else except as part of a product or
+.\" program developed by the user.
+.\"
+.\" THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC.
+.\" SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY
+.\" OF SUCH SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT
+.\" EXPRESS OR IMPLIED WARRANTY OF ANY KIND. SUN MICROSYSTEMS, INC. DISCLAIMS
+.\" ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
+.\" NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT,
+.\" INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+.\" FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY.
+.\"
+.\" This source code is provided with no support and without any obligation on
+.\" the part of Sun Microsystems, Inc. to assist in its use, correction,
+.\" modification or enhancement.
+.\"
+.\" SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+.\" INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS
+.\" SOURCE CODE OR ANY PART THEREOF.
+.\"
+.\" Sun Microsystems, Inc.
+.\" 2550 Garcia Avenue
+.\" Mountain View, California 94043
+.\"
+.\" Copyright (c) 1991 Sun Microsystems, Inc.
+.\"
+.\" @(#) dlopen.3 1.6 90/01/31 SMI
+.Dd September 24, 1989
+.Os FreeBSD
+.Dt DLOPEN 3
+.Sh NAME
+.Nm dlopen, dlsym, dlerror, dlclose
+.Nd programmatic interface to the dynamic linker
+.Sh SYNOPSIS
+.Fd #include <dlfcn.h>
+.Ft void *
+.Fn dlopen "char *path" "int mode"
+.Ft void *
+.Fn dlsym "void *handle" "char *symbol"
+.Ft char *
+.Fn dlerror "void"
+.Ft int
+.Fn dlclose "void *handle"
+.Sh DESCRIPTION
+These functions provide a simple programmatic interface to the services of the
+dynamic linker.
+Operations are provided to add new shared objects to a
+program's address space, to obtain the address bindings of symbols
+defined by such
+objects, and to remove such objects when their use is no longer required.
+.Pp
+.Fn dlopen
+provides access to the shared object in
+.Fa path ,
+returning a descriptor that can be used for later
+references to the object in calls to
+.Fn dlsym
+and
+.Fn dlclose .
+If
+.Fa path
+was not in the address space prior to the call to
+.Fn dlopen ,
+it is placed in the address space.
+When an object is first loaded into the address space in this way, its
+function
+.Fn _init ,
+if any, is called by the dynamic linker.
+(Note that
+.Ql _init
+is the name as expressed in the C language.
+From assembly language, the name would appear as
+.Ql __init
+instead.)
+If
+.Fa path
+has already been placed in the address space in a previous call to
+.Fn dlopen ,
+it is not added a second time, although a reference count of
+.Fn dlopen
+operations on
+.Fa path
+is maintained.
+A null pointer supplied for
+.Fa path
+is interpreted as a reference to the main
+executable of the process.
+.Fa mode
+controls the way in which external function references from the
+loaded object are bound to their referents.
+It must contains one of the following values:
+.Bl -tag -width RTLD_LAZYX
+.It Dv RTLD_LAZY
+Each external function reference is resolved when the function is first
+called.
+.It Dv RTLD_NOW
+All external function references are bound immediately by
+.Fn dlopen .
+.El
+.Pp
+.Dv RTLD_LAZY
+is normally preferred, for reasons of efficiency.
+However,
+.Dv RTLD_NOW
+is useful to ensure that any undefined symbols are discovered during the
+call to
+.Fn dlopen .
+If
+.Fn dlopen
+fails, it returns a null pointer, and sets an error condition which may
+be interrogated with
+.Fn dlerror .
+.Pp
+.Fn dlsym
+returns the address binding of the symbol described in the null-terminated
+character string
+.Fa symbol ,
+as it occurs in the shared object identified by
+.Fa handle .
+Note that
+.Fa symbol
+is the assembly language representation of the symbol name.
+The assembly language representation of a C language symbol contains an
+extra underscore at the beginning.
+For example, the symbol
+.Ql foo
+in C would appear as
+.Ql _foo
+in assembly language, and in the
+.Fa symbol
+argument to
+.Fn dlsym .
+The symbols exported by objects added to the address space by
+.Fn dlopen
+can be accessed only through calls to
+.Fn dlsym .
+Such symbols do not supersede any definition of those symbols already present
+in the address space when the object is loaded, nor are they available to
+satisfy normal dynamic linking references.
+A null pointer supplied as the value of
+.Fa handle
+is interpreted as a reference to the executable from which the call to
+.Fn dlsym
+is being made. Thus a shared object can reference its own symbols.
+.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 dlerror
+returns a null-terminated character string describing the last error that
+occurred during a call to
+.Fn dlopen ,
+.Fn dlsym ,
+or
+.Fn dlclose .
+If no such error has occurred,
+.Fn dlerror
+returns a null pointer.
+At each call to
+.Fn dlerror ,
+the error indication is reset. Thus in the case of two calls
+to
+.Fn dlerror ,
+where the second call follows the first immediately, the second call
+will always return a null pointer.
+.Pp
+.Fn dlclose
+deletes a reference to the shared object referenced by
+.Fa handle .
+If the reference count drops to 0, the object is removed from the
+address space, and
+.Fa handle
+is rendered invalid.
+Just before removing a shared object in this way, the dynamic linker
+calls the object's
+.Fn _fini
+function, if such a function is defined by the object.
+As with
+.Ql _init ,
+.Ql _fini
+is the C language name of the function.
+If
+.Fn dlclose
+is successful, it returns a value of 0.
+Otherwise it returns -1, and sets an error condition that can be
+interrogated with
+.Fn dlerror .
+.Pp
+The object-intrinsic functions
+.Fn _init
+and
+.Fn _fini
+are called with no arguments, and are not expected to return values.
+.Sh ERRORS
+.Fn dlopen
+and
+.Fn dlsym
+return the 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
+retrieved via a call to
+.Fn dlerror .
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr link 5 ,
+.Xr rtld 1
OpenPOWER on IntegriCloud