diff options
| author | John Polstra <jdp@FreeBSD.org> | 1997-08-02 04:56:44 +0000 |
|---|---|---|
| committer | John Polstra <jdp@FreeBSD.org> | 1997-08-02 04:56:44 +0000 |
| commit | 7e7344e2f4ebf22d7c6c4ba76a775ffc8c6c2f48 (patch) | |
| tree | 8cef03aff5e54cd51ce9f4cf00818a41e368b386 /lib/csu/i386 | |
| parent | 8889c700f314bb2d6fc652ff35a5f3d2d72f5edb (diff) | |
Notes
Diffstat (limited to 'lib/csu/i386')
| -rw-r--r-- | lib/csu/i386/crt0.c | 21 | ||||
| -rw-r--r-- | lib/csu/i386/dlfcn.h | 7 | ||||
| -rw-r--r-- | lib/csu/i386/dlopen.3 | 22 |
3 files changed, 42 insertions, 8 deletions
diff --git a/lib/csu/i386/crt0.c b/lib/csu/i386/crt0.c index 5f7e4ab724ce3..4d217fb08cea2 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 feadf90bc6c71..b6817fe03b26f 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 82651c6b510fe..efd59be557f22 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 |
