aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Polstra <jdp@FreeBSD.org>1998-02-06 16:46:46 +0000
committerJohn Polstra <jdp@FreeBSD.org>1998-02-06 16:46:46 +0000
commit663690b388e5292163b29dc674747e7112651ebf (patch)
tree51dbdd1f01b428c5c87fc16c888a361426165b4a
parent14834de44151061869e6aa7e4be7c597a5a440be (diff)
downloadsrc-663690b388e5292163b29dc674747e7112651ebf.tar.gz
src-663690b388e5292163b29dc674747e7112651ebf.zip
Implement dladdr.
Notes
Notes: svn path=/head/; revision=33137
-rw-r--r--gnu/usr.bin/ld/rtld/rtld.c98
-rw-r--r--include/link.h9
-rw-r--r--lib/csu/i386/Makefile4
-rw-r--r--lib/csu/i386/crt0.c42
-rw-r--r--lib/csu/i386/dladdr.3121
-rw-r--r--lib/csu/i386/dlfcn.h15
-rw-r--r--libexec/rtld-aout/rtld.c98
-rw-r--r--sys/sys/link_aout.h9
-rw-r--r--sys/sys/link_elf.h9
9 files changed, 381 insertions, 24 deletions
diff --git a/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c
index b331cdec7513..342ed74be07c 100644
--- a/gnu/usr.bin/ld/rtld/rtld.c
+++ b/gnu/usr.bin/ld/rtld/rtld.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: rtld.c,v 1.50 1997/11/29 03:32:47 jdp Exp $
+ * $Id: rtld.c,v 1.51 1997/12/05 02:06:37 jdp Exp $
*/
#include <sys/param.h>
@@ -174,6 +174,8 @@ struct somap_private {
#define RELOC_PCREL_P(s) ((s)->r_pcrel)
#endif
+#define END_SYM "_end"
+
static char __main_progname[] = "main";
static char *main_progname = __main_progname;
static char us[] = "/usr/libexec/ld.so";
@@ -205,9 +207,10 @@ static void *__dlsym __P((void *, const char *));
static const char *__dlerror __P((void));
static void __dlexit __P((void));
static void *__dlsym3 __P((void *, const char *, void *));
+static int __dladdr __P((const void *, Dl_info *));
static struct ld_entry ld_entry = {
- __dlopen, __dlclose, __dlsym, __dlerror, __dlexit, __dlsym3
+ __dlopen, __dlclose, __dlsym, __dlerror, __dlexit, __dlsym3, __dladdr
};
void xprintf __P((char *, ...));
@@ -302,11 +305,13 @@ struct _dynamic *dp;
struct so_map *main_map;
struct so_map *smp;
char *add_paths;
+ char *main_path;
/* Check version */
if (version != CRT_VERSION_BSD_2 &&
version != CRT_VERSION_BSD_3 &&
version != CRT_VERSION_BSD_4 &&
+ version != CRT_VERSION_BSD_5 &&
version != CRT_VERSION_SUN)
return -1;
@@ -335,6 +340,8 @@ struct _dynamic *dp;
__progname = crtp->crt_ldso;
if (version >= CRT_VERSION_BSD_3)
main_progname = crtp->crt_prog;
+ main_path = version >= CRT_VERSION_BSD_5 ? crtp->crt_argv[0] :
+ main_progname;
/* Some buggy versions of crt0.o have crt_ldso filled in as NULL. */
if (__progname == NULL)
@@ -363,7 +370,7 @@ struct _dynamic *dp;
anon_open();
/* Make a link map entry for the main program */
- main_map = alloc_link_map(main_progname,
+ main_map = alloc_link_map(main_path,
(struct sod *) NULL, (struct so_map *) NULL,
(caddr_t) 0, crtp->crt_dp);
LM_PRIVATE(main_map)->spd_refcount++;
@@ -453,7 +460,7 @@ struct _dynamic *dp;
(void)close(crtp->crt_ldfd);
anon_close();
- return LDSO_VERSION_HAS_DLSYM3;
+ return LDSO_VERSION_HAS_DLADDR;
}
void
@@ -2024,6 +2031,89 @@ resolvesym(fd, sym, retaddr)
return (void *)addr;
}
+static int
+__dladdr(addr, dlip)
+ const void *addr;
+ Dl_info *dlip;
+{
+ struct _dynamic *dp;
+ struct so_map *smp;
+ char *stringbase;
+ long numsyms;
+ int symsize;
+ int i;
+
+ /* Find the shared object that contains the address. */
+ for (smp = link_map_head; smp != NULL; smp = smp->som_next) {
+ struct so_map *src_map;
+ struct somap_private *smpp;
+ struct nzlist *np;
+
+ smpp = LM_PRIVATE(smp);
+ if (smpp->spd_flags & RTLD_RTLD)
+ continue;
+
+ if ((void *)smp->som_addr > addr)
+ continue;
+
+ src_map = smp;
+ if ((np = lookup(END_SYM, &src_map, 1)) == NULL)
+ continue; /* No "_end" symbol?! */
+ if (addr < (void *)(smp->som_addr + np->nz_value))
+ break;
+ }
+ if (smp == NULL) {
+ generror("No shared object contains address");
+ return 0;
+ }
+ dlip->dli_fname = smp->som_path;
+ dlip->dli_fbase = smp->som_addr;
+ dlip->dli_saddr = (void *) 0;
+ dlip->dli_sname = NULL;
+
+ dp = smp->som_dynamic;
+ symsize = LD_VERSION_NZLIST_P(dp->d_version) ?
+ sizeof(struct nzlist) : sizeof(struct nlist);
+ numsyms = LD_STABSZ(dp) / symsize;
+ stringbase = LM_STRINGS(smp);
+
+ for (i = 0; i < numsyms; i++) {
+ struct nzlist *symp = LM_SYMBOL(smp, i);
+ unsigned long value;
+
+ /* Reject all except definitions. */
+ if (symp->nz_type != N_EXT + N_ABS &&
+ symp->nz_type != N_EXT + N_TEXT &&
+ symp->nz_type != N_EXT + N_DATA &&
+ symp->nz_type != N_EXT + N_BSS)
+ continue;
+
+ /*
+ * If the symbol is greater than the specified address, or
+ * if it is further away from addr than the current nearest
+ * symbol, then reject it.
+ */
+ value = (unsigned long) (smp->som_addr + symp->nz_value);
+ if (value > (unsigned long) addr ||
+ value < (unsigned long) dlip->dli_saddr)
+ continue;
+
+ /* Update our idea of the nearest symbol. */
+ dlip->dli_sname = stringbase + symp->nz_strx;
+ dlip->dli_saddr = (void *) value;
+
+ if (dlip->dli_saddr == addr) /* Can't get any closer. */
+ break;
+ }
+ /*
+ * Remove any leading underscore from the symbol name, to hide
+ * our a.out-ness.
+ */
+ if (dlip->dli_sname != NULL && dlip->dli_sname[0] == '_')
+ dlip->dli_sname++;
+ return 1;
+}
+
static void *
__dlsym3(fd, sym, retaddr)
void *fd;
diff --git a/include/link.h b/include/link.h
index 5ff1f7857b1f..9d80d45d7505 100644
--- a/include/link.h
+++ b/include/link.h
@@ -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: link.h,v 1.16 1997/11/28 19:05:11 jdp Exp $
+ * $Id: link.h,v 1.17 1997/12/06 17:59:52 jdp Exp $
*/
/*
@@ -41,6 +41,8 @@
#ifndef _LINK_H_
#define _LINK_H_
+struct dl_info;
+
/*
* A `Shared Object Descriptor' describes a shared object that is needed
* to complete the link edit process of the object containing it.
@@ -158,6 +160,7 @@ struct so_debug {
#define LDSO_VERSION_NONE 0 /* FreeBSD2.0, 2.0.5 */
#define LDSO_VERSION_HAS_DLEXIT 1 /* includes dlexit in ld_entry */
#define LDSO_VERSION_HAS_DLSYM3 2 /* includes 3-argument dlsym */
+#define LDSO_VERSION_HAS_DLADDR 3 /* includes dladdr in ld_entry */
/*
* Entry points into ld.so - user interface to the run-time linker.
@@ -171,6 +174,8 @@ struct ld_entry {
const char *(*dlerror) __P((void)); /* NONE */
void (*dlexit) __P((void)); /* HAS_DLEXIT */
void *(*dlsym3) __P((void *, const char *, void *)); /* HAS_DLSYM3 */
+ int (*dladdr) __P((const void *,
+ struct dl_info *)); /* HAS_DLADDR */
};
/*
@@ -229,6 +234,7 @@ struct crt_ldso {
char *crt_prog; /* Program name (v3) */
char *crt_ldso; /* Link editor name (v4) */
struct ld_entry *crt_ldentry; /* dl*() access (v4) */
+ char **crt_argv; /* argument strings (v5) */
};
/*
@@ -238,6 +244,7 @@ struct crt_ldso {
#define CRT_VERSION_BSD_2 2
#define CRT_VERSION_BSD_3 3
#define CRT_VERSION_BSD_4 4
+#define CRT_VERSION_BSD_5 5
/*
* Maximum number of recognized shared object version numbers.
diff --git a/lib/csu/i386/Makefile b/lib/csu/i386/Makefile
index 15d18923c86a..42907dcde33a 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 b3884e47fa3b..80759cf902ca 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 <sys/param.h>
@@ -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 000000000000..97af8cec5456
--- /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 <dlfcn.h>
+.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 e167ef2c1929..ba61ebfd4953 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_ */
diff --git a/libexec/rtld-aout/rtld.c b/libexec/rtld-aout/rtld.c
index b331cdec7513..342ed74be07c 100644
--- a/libexec/rtld-aout/rtld.c
+++ b/libexec/rtld-aout/rtld.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: rtld.c,v 1.50 1997/11/29 03:32:47 jdp Exp $
+ * $Id: rtld.c,v 1.51 1997/12/05 02:06:37 jdp Exp $
*/
#include <sys/param.h>
@@ -174,6 +174,8 @@ struct somap_private {
#define RELOC_PCREL_P(s) ((s)->r_pcrel)
#endif
+#define END_SYM "_end"
+
static char __main_progname[] = "main";
static char *main_progname = __main_progname;
static char us[] = "/usr/libexec/ld.so";
@@ -205,9 +207,10 @@ static void *__dlsym __P((void *, const char *));
static const char *__dlerror __P((void));
static void __dlexit __P((void));
static void *__dlsym3 __P((void *, const char *, void *));
+static int __dladdr __P((const void *, Dl_info *));
static struct ld_entry ld_entry = {
- __dlopen, __dlclose, __dlsym, __dlerror, __dlexit, __dlsym3
+ __dlopen, __dlclose, __dlsym, __dlerror, __dlexit, __dlsym3, __dladdr
};
void xprintf __P((char *, ...));
@@ -302,11 +305,13 @@ struct _dynamic *dp;
struct so_map *main_map;
struct so_map *smp;
char *add_paths;
+ char *main_path;
/* Check version */
if (version != CRT_VERSION_BSD_2 &&
version != CRT_VERSION_BSD_3 &&
version != CRT_VERSION_BSD_4 &&
+ version != CRT_VERSION_BSD_5 &&
version != CRT_VERSION_SUN)
return -1;
@@ -335,6 +340,8 @@ struct _dynamic *dp;
__progname = crtp->crt_ldso;
if (version >= CRT_VERSION_BSD_3)
main_progname = crtp->crt_prog;
+ main_path = version >= CRT_VERSION_BSD_5 ? crtp->crt_argv[0] :
+ main_progname;
/* Some buggy versions of crt0.o have crt_ldso filled in as NULL. */
if (__progname == NULL)
@@ -363,7 +370,7 @@ struct _dynamic *dp;
anon_open();
/* Make a link map entry for the main program */
- main_map = alloc_link_map(main_progname,
+ main_map = alloc_link_map(main_path,
(struct sod *) NULL, (struct so_map *) NULL,
(caddr_t) 0, crtp->crt_dp);
LM_PRIVATE(main_map)->spd_refcount++;
@@ -453,7 +460,7 @@ struct _dynamic *dp;
(void)close(crtp->crt_ldfd);
anon_close();
- return LDSO_VERSION_HAS_DLSYM3;
+ return LDSO_VERSION_HAS_DLADDR;
}
void
@@ -2024,6 +2031,89 @@ resolvesym(fd, sym, retaddr)
return (void *)addr;
}
+static int
+__dladdr(addr, dlip)
+ const void *addr;
+ Dl_info *dlip;
+{
+ struct _dynamic *dp;
+ struct so_map *smp;
+ char *stringbase;
+ long numsyms;
+ int symsize;
+ int i;
+
+ /* Find the shared object that contains the address. */
+ for (smp = link_map_head; smp != NULL; smp = smp->som_next) {
+ struct so_map *src_map;
+ struct somap_private *smpp;
+ struct nzlist *np;
+
+ smpp = LM_PRIVATE(smp);
+ if (smpp->spd_flags & RTLD_RTLD)
+ continue;
+
+ if ((void *)smp->som_addr > addr)
+ continue;
+
+ src_map = smp;
+ if ((np = lookup(END_SYM, &src_map, 1)) == NULL)
+ continue; /* No "_end" symbol?! */
+ if (addr < (void *)(smp->som_addr + np->nz_value))
+ break;
+ }
+ if (smp == NULL) {
+ generror("No shared object contains address");
+ return 0;
+ }
+ dlip->dli_fname = smp->som_path;
+ dlip->dli_fbase = smp->som_addr;
+ dlip->dli_saddr = (void *) 0;
+ dlip->dli_sname = NULL;
+
+ dp = smp->som_dynamic;
+ symsize = LD_VERSION_NZLIST_P(dp->d_version) ?
+ sizeof(struct nzlist) : sizeof(struct nlist);
+ numsyms = LD_STABSZ(dp) / symsize;
+ stringbase = LM_STRINGS(smp);
+
+ for (i = 0; i < numsyms; i++) {
+ struct nzlist *symp = LM_SYMBOL(smp, i);
+ unsigned long value;
+
+ /* Reject all except definitions. */
+ if (symp->nz_type != N_EXT + N_ABS &&
+ symp->nz_type != N_EXT + N_TEXT &&
+ symp->nz_type != N_EXT + N_DATA &&
+ symp->nz_type != N_EXT + N_BSS)
+ continue;
+
+ /*
+ * If the symbol is greater than the specified address, or
+ * if it is further away from addr than the current nearest
+ * symbol, then reject it.
+ */
+ value = (unsigned long) (smp->som_addr + symp->nz_value);
+ if (value > (unsigned long) addr ||
+ value < (unsigned long) dlip->dli_saddr)
+ continue;
+
+ /* Update our idea of the nearest symbol. */
+ dlip->dli_sname = stringbase + symp->nz_strx;
+ dlip->dli_saddr = (void *) value;
+
+ if (dlip->dli_saddr == addr) /* Can't get any closer. */
+ break;
+ }
+ /*
+ * Remove any leading underscore from the symbol name, to hide
+ * our a.out-ness.
+ */
+ if (dlip->dli_sname != NULL && dlip->dli_sname[0] == '_')
+ dlip->dli_sname++;
+ return 1;
+}
+
static void *
__dlsym3(fd, sym, retaddr)
void *fd;
diff --git a/sys/sys/link_aout.h b/sys/sys/link_aout.h
index 5ff1f7857b1f..9d80d45d7505 100644
--- a/sys/sys/link_aout.h
+++ b/sys/sys/link_aout.h
@@ -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: link.h,v 1.16 1997/11/28 19:05:11 jdp Exp $
+ * $Id: link.h,v 1.17 1997/12/06 17:59:52 jdp Exp $
*/
/*
@@ -41,6 +41,8 @@
#ifndef _LINK_H_
#define _LINK_H_
+struct dl_info;
+
/*
* A `Shared Object Descriptor' describes a shared object that is needed
* to complete the link edit process of the object containing it.
@@ -158,6 +160,7 @@ struct so_debug {
#define LDSO_VERSION_NONE 0 /* FreeBSD2.0, 2.0.5 */
#define LDSO_VERSION_HAS_DLEXIT 1 /* includes dlexit in ld_entry */
#define LDSO_VERSION_HAS_DLSYM3 2 /* includes 3-argument dlsym */
+#define LDSO_VERSION_HAS_DLADDR 3 /* includes dladdr in ld_entry */
/*
* Entry points into ld.so - user interface to the run-time linker.
@@ -171,6 +174,8 @@ struct ld_entry {
const char *(*dlerror) __P((void)); /* NONE */
void (*dlexit) __P((void)); /* HAS_DLEXIT */
void *(*dlsym3) __P((void *, const char *, void *)); /* HAS_DLSYM3 */
+ int (*dladdr) __P((const void *,
+ struct dl_info *)); /* HAS_DLADDR */
};
/*
@@ -229,6 +234,7 @@ struct crt_ldso {
char *crt_prog; /* Program name (v3) */
char *crt_ldso; /* Link editor name (v4) */
struct ld_entry *crt_ldentry; /* dl*() access (v4) */
+ char **crt_argv; /* argument strings (v5) */
};
/*
@@ -238,6 +244,7 @@ struct crt_ldso {
#define CRT_VERSION_BSD_2 2
#define CRT_VERSION_BSD_3 3
#define CRT_VERSION_BSD_4 4
+#define CRT_VERSION_BSD_5 5
/*
* Maximum number of recognized shared object version numbers.
diff --git a/sys/sys/link_elf.h b/sys/sys/link_elf.h
index 5ff1f7857b1f..9d80d45d7505 100644
--- a/sys/sys/link_elf.h
+++ b/sys/sys/link_elf.h
@@ -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: link.h,v 1.16 1997/11/28 19:05:11 jdp Exp $
+ * $Id: link.h,v 1.17 1997/12/06 17:59:52 jdp Exp $
*/
/*
@@ -41,6 +41,8 @@
#ifndef _LINK_H_
#define _LINK_H_
+struct dl_info;
+
/*
* A `Shared Object Descriptor' describes a shared object that is needed
* to complete the link edit process of the object containing it.
@@ -158,6 +160,7 @@ struct so_debug {
#define LDSO_VERSION_NONE 0 /* FreeBSD2.0, 2.0.5 */
#define LDSO_VERSION_HAS_DLEXIT 1 /* includes dlexit in ld_entry */
#define LDSO_VERSION_HAS_DLSYM3 2 /* includes 3-argument dlsym */
+#define LDSO_VERSION_HAS_DLADDR 3 /* includes dladdr in ld_entry */
/*
* Entry points into ld.so - user interface to the run-time linker.
@@ -171,6 +174,8 @@ struct ld_entry {
const char *(*dlerror) __P((void)); /* NONE */
void (*dlexit) __P((void)); /* HAS_DLEXIT */
void *(*dlsym3) __P((void *, const char *, void *)); /* HAS_DLSYM3 */
+ int (*dladdr) __P((const void *,
+ struct dl_info *)); /* HAS_DLADDR */
};
/*
@@ -229,6 +234,7 @@ struct crt_ldso {
char *crt_prog; /* Program name (v3) */
char *crt_ldso; /* Link editor name (v4) */
struct ld_entry *crt_ldentry; /* dl*() access (v4) */
+ char **crt_argv; /* argument strings (v5) */
};
/*
@@ -238,6 +244,7 @@ struct crt_ldso {
#define CRT_VERSION_BSD_2 2
#define CRT_VERSION_BSD_3 3
#define CRT_VERSION_BSD_4 4
+#define CRT_VERSION_BSD_5 5
/*
* Maximum number of recognized shared object version numbers.