Implement dladdr.
This commit is contained in:
parent
14834de441
commit
663690b388
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
|
121
lib/csu/i386/dladdr.3
Normal file
121
lib/csu/i386/dladdr.3
Normal file
@ -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
|
@ -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_ */
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user