From d5b09c81eced1f16f3f4629fb7fbafca071830c8 Mon Sep 17 00:00:00 2001 From: jdp Date: Fri, 6 Feb 1998 16:46:46 +0000 Subject: Implement dladdr. --- lib/csu/i386/Makefile | 4 +- lib/csu/i386/crt0.c | 42 ++++++++++++++---- lib/csu/i386/dladdr.3 | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/csu/i386/dlfcn.h | 15 ++++++- 4 files changed, 169 insertions(+), 13 deletions(-) create mode 100644 lib/csu/i386/dladdr.3 (limited to 'lib/csu') diff --git a/lib/csu/i386/Makefile b/lib/csu/i386/Makefile index 15d1892..42907dc 100644 --- a/lib/csu/i386/Makefile +++ b/lib/csu/i386/Makefile @@ -1,10 +1,10 @@ # from: @(#)Makefile 5.6 (Berkeley) 5/22/91 -# $Id: Makefile,v 1.32 1997/10/11 02:37:42 asami Exp $ +# $Id: Makefile,v 1.33 1998/01/12 18:29:02 eivind Exp $ CFLAGS+= -DLIBC_SCCS -fno-omit-frame-pointer -I${.CURDIR} OBJS= crt0.o c++rt0.o gcrt0.o scrt0.o sgcrt0.o CLEANFILES+= a.out -MAN3+= dlopen.3 +MAN3+= dladdr.3 dlopen.3 MLINKS+= dlopen.3 dlsym.3 \ dlopen.3 dlerror.3 \ dlopen.3 dlclose.3 diff --git a/lib/csu/i386/crt0.c b/lib/csu/i386/crt0.c index b3884e4..80759cf 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: crt0.c,v 1.30 1997/08/02 04:56:33 jdp Exp $ + * $Id: crt0.c,v 1.31 1997/11/22 03:34:45 brian Exp $ */ #include @@ -85,7 +85,7 @@ static int _strncmp(); extern struct _dynamic _DYNAMIC; static struct ld_entry *ld_entry; -static void __do_dynamic_link (); +static void __do_dynamic_link(char **argv); #endif /* DYNAMIC */ int _callmain(); @@ -174,7 +174,7 @@ start() /* sometimes GCC is too smart/stupid for its own good */ x = (caddr_t)&_DYNAMIC; if (x) - __do_dynamic_link(); + __do_dynamic_link(argv); #endif /* DYNAMIC */ asm("eprol:"); @@ -190,7 +190,8 @@ asm ("__callmain:"); /* Defined for the benefit of debuggers */ #ifdef DYNAMIC static void -__do_dynamic_link () +__do_dynamic_link(argv) + char **argv; { struct crt_ldso crt; struct exec hdr; @@ -253,14 +254,20 @@ __do_dynamic_link () crt.crt_prog = __progname; crt.crt_ldso = ldso; crt.crt_ldentry = NULL; + crt.crt_argv = argv; entry = (int (*)())(crt.crt_ba + sizeof hdr); - ldso_version = (*entry)(CRT_VERSION_BSD_4, &crt); + ldso_version = (*entry)(CRT_VERSION_BSD_5, &crt); ld_entry = crt.crt_ldentry; if (ldso_version == -1 && ld_entry == NULL) { - /* if version 4 not recognised, try version 3 */ - ldso_version = (*entry)(CRT_VERSION_BSD_3, &crt); - ld_entry = _DYNAMIC.d_entry; + /* If version 5 not recognised, try version 4 */ + ldso_version = (*entry)(CRT_VERSION_BSD_4, &crt); + ld_entry = crt.crt_ldentry; + if (ldso_version == -1 && ld_entry == NULL) { + /* if version 4 not recognised, try version 3 */ + ldso_version = (*entry)(CRT_VERSION_BSD_3, &crt); + ld_entry = _DYNAMIC.d_entry; + } } if (ldso_version == -1) { _PUTMSG("ld.so failed"); @@ -334,6 +341,16 @@ dlerror() return (ld_entry->dlerror)(); } +int +dladdr(addr, dlip) + const void *addr; + Dl_info *dlip; +{ + if (ld_entry == NULL || ldso_version < LDSO_VERSION_HAS_DLADDR) + return 0; + return (ld_entry->dladdr)(addr, dlip); +} + /* * Support routines @@ -419,12 +436,19 @@ const char *name; return NULL; } - const char * dlerror() { return "Service unavailable"; } + +int +dladdr(addr, dlip) + const void *addr; + Dl_info *dlip; +{ + return 0; +} #endif /* DYNAMIC */ diff --git a/lib/csu/i386/dladdr.3 b/lib/csu/i386/dladdr.3 new file mode 100644 index 0000000..97af8ce --- /dev/null +++ b/lib/csu/i386/dladdr.3 @@ -0,0 +1,121 @@ +.\" +.\" Copyright (c) 1998 John D. Polstra +.\" 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +.\" +.\" $Id$ +.\" +.Dd February 5, 1998 +.Os FreeBSD +.Dt DLADDR 3 +.Sh NAME +.Nm dladdr +.Nd find the shared object containing a given address +.Sh SYNOPSIS +.Fd #include +.Ft int +.Fn dladdr "const void *addr" "Dl_info *info" +.Sh DESCRIPTION +.Nm +queries the dynamic linker for information about the shared object +containing the address +.Fa addr . +The information is returned in the structure specified by +.Fa info . +The structure contains at least the following members: +.Bl -tag -width "XXXconst char *dli_fname" +.It Li "const char *dli_fname" +The pathname of the shared object containing the address. +.It Li "void *dli_fbase" +The base address at which the shared object is mapped into the +address space of the calling process. +.It Li "const char *dli_sname" +The name of the nearest run-time symbol with a value less than or +equal to +.Fa addr . +When possible, the symbol name is returned as it would appear in C +source code. +.Pp +If no symbol with a suitable value is found, both this field and +.Va dli_saddr +are set to +.Dv NULL . +.It Li "void *dli_saddr" +The value of the symbol returned in +.Li dli_sname . +.El +.Pp +.Nm +is available only in dynamically linked programs. +.Sh ERRORS +If a mapped shared object containing +.Fa addr +cannot be found, +.Nm +returns 0. +In that case, a message detailing the failure can be retrieved by +calling +.Fn dlerror . +.Pp +On success, a non-zero value is returned. +.Sh SEE ALSO +.Xr dlopen 3 , +.Xr rtld 1 +.Sh HISTORY +The +.Nm +function first appeared in the Solaris operating system. +.Sh BUGS +This implementation is bug-compatible with the Solaris +implementation. In particular, the following bugs are present: +.Bl -bullet +.It +If +.Fa addr +lies in the main executable rather than in a shared library, the +pathname returned in +.Va dli_fname +may not be correct. The pathname is taken directly from +.Va argv[0] +of the calling process. When executing a program specified by its +full pathname, most shells set +.Va argv[0] +to the pathname. But this is not required of shells or guaranteed +by the operating system. +.It +If +.Fa addr +is of the form +.Va &func , +where +.Va func +is a global function, its value may be an unpleasant surprise. In +dynamically linked programs, the address of a global function is +considered to point to its program linkage table entry, rather than to +the entry point of the function itself. This causes most global +functions to appear to be defined within the main executable, rather +than in the shared libraries where the actual code resides. +.It +Returning 0 as an indication of failure goes against long-standing +Unix tradition. +.El diff --git a/lib/csu/i386/dlfcn.h b/lib/csu/i386/dlfcn.h index e167ef2..ba61ebf 100644 --- a/lib/csu/i386/dlfcn.h +++ b/lib/csu/i386/dlfcn.h @@ -50,11 +50,22 @@ */ #define RTLD_NEXT ((void *) -1) +/* + * Structure filled in by dladdr(). + */ +typedef struct dl_info { + const char *dli_fname; /* Pathname of shared object */ + void *dli_fbase; /* Base address of shared object */ + const char *dli_sname; /* Name of nearest symbol */ + void *dli_saddr; /* Address of nearest symbol */ +} Dl_info; + __BEGIN_DECLS +int dladdr __P((const void *, Dl_info *)); +int dlclose __P((void *)); +const char *dlerror __P((void)); void *dlopen __P((const char *, int)); void *dlsym __P((void *, const char *)); -const char *dlerror __P((void)); -int dlclose __P((void *)); __END_DECLS #endif /* !_DLFCN_H_ */ -- cgit v1.1