Implement dladdr.
This commit is contained in:
parent
14834de441
commit
663690b388
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=33137
@ -27,7 +27,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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>
|
#include <sys/param.h>
|
||||||
@ -174,6 +174,8 @@ struct somap_private {
|
|||||||
#define RELOC_PCREL_P(s) ((s)->r_pcrel)
|
#define RELOC_PCREL_P(s) ((s)->r_pcrel)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define END_SYM "_end"
|
||||||
|
|
||||||
static char __main_progname[] = "main";
|
static char __main_progname[] = "main";
|
||||||
static char *main_progname = __main_progname;
|
static char *main_progname = __main_progname;
|
||||||
static char us[] = "/usr/libexec/ld.so";
|
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 const char *__dlerror __P((void));
|
||||||
static void __dlexit __P((void));
|
static void __dlexit __P((void));
|
||||||
static void *__dlsym3 __P((void *, const char *, void *));
|
static void *__dlsym3 __P((void *, const char *, void *));
|
||||||
|
static int __dladdr __P((const void *, Dl_info *));
|
||||||
|
|
||||||
static struct ld_entry ld_entry = {
|
static struct ld_entry ld_entry = {
|
||||||
__dlopen, __dlclose, __dlsym, __dlerror, __dlexit, __dlsym3
|
__dlopen, __dlclose, __dlsym, __dlerror, __dlexit, __dlsym3, __dladdr
|
||||||
};
|
};
|
||||||
|
|
||||||
void xprintf __P((char *, ...));
|
void xprintf __P((char *, ...));
|
||||||
@ -302,11 +305,13 @@ struct _dynamic *dp;
|
|||||||
struct so_map *main_map;
|
struct so_map *main_map;
|
||||||
struct so_map *smp;
|
struct so_map *smp;
|
||||||
char *add_paths;
|
char *add_paths;
|
||||||
|
char *main_path;
|
||||||
|
|
||||||
/* Check version */
|
/* Check version */
|
||||||
if (version != CRT_VERSION_BSD_2 &&
|
if (version != CRT_VERSION_BSD_2 &&
|
||||||
version != CRT_VERSION_BSD_3 &&
|
version != CRT_VERSION_BSD_3 &&
|
||||||
version != CRT_VERSION_BSD_4 &&
|
version != CRT_VERSION_BSD_4 &&
|
||||||
|
version != CRT_VERSION_BSD_5 &&
|
||||||
version != CRT_VERSION_SUN)
|
version != CRT_VERSION_SUN)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -335,6 +340,8 @@ struct _dynamic *dp;
|
|||||||
__progname = crtp->crt_ldso;
|
__progname = crtp->crt_ldso;
|
||||||
if (version >= CRT_VERSION_BSD_3)
|
if (version >= CRT_VERSION_BSD_3)
|
||||||
main_progname = crtp->crt_prog;
|
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. */
|
/* Some buggy versions of crt0.o have crt_ldso filled in as NULL. */
|
||||||
if (__progname == NULL)
|
if (__progname == NULL)
|
||||||
@ -363,7 +370,7 @@ struct _dynamic *dp;
|
|||||||
anon_open();
|
anon_open();
|
||||||
|
|
||||||
/* Make a link map entry for the main program */
|
/* 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,
|
(struct sod *) NULL, (struct so_map *) NULL,
|
||||||
(caddr_t) 0, crtp->crt_dp);
|
(caddr_t) 0, crtp->crt_dp);
|
||||||
LM_PRIVATE(main_map)->spd_refcount++;
|
LM_PRIVATE(main_map)->spd_refcount++;
|
||||||
@ -453,7 +460,7 @@ struct _dynamic *dp;
|
|||||||
(void)close(crtp->crt_ldfd);
|
(void)close(crtp->crt_ldfd);
|
||||||
anon_close();
|
anon_close();
|
||||||
|
|
||||||
return LDSO_VERSION_HAS_DLSYM3;
|
return LDSO_VERSION_HAS_DLADDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2024,6 +2031,89 @@ resolvesym(fd, sym, retaddr)
|
|||||||
return (void *)addr;
|
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 *
|
static void *
|
||||||
__dlsym3(fd, sym, retaddr)
|
__dlsym3(fd, sym, retaddr)
|
||||||
void *fd;
|
void *fd;
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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_
|
#ifndef _LINK_H_
|
||||||
#define _LINK_H_
|
#define _LINK_H_
|
||||||
|
|
||||||
|
struct dl_info;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A `Shared Object Descriptor' describes a shared object that is needed
|
* A `Shared Object Descriptor' describes a shared object that is needed
|
||||||
* to complete the link edit process of the object containing it.
|
* 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_NONE 0 /* FreeBSD2.0, 2.0.5 */
|
||||||
#define LDSO_VERSION_HAS_DLEXIT 1 /* includes dlexit in ld_entry */
|
#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_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.
|
* 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 */
|
const char *(*dlerror) __P((void)); /* NONE */
|
||||||
void (*dlexit) __P((void)); /* HAS_DLEXIT */
|
void (*dlexit) __P((void)); /* HAS_DLEXIT */
|
||||||
void *(*dlsym3) __P((void *, const char *, void *)); /* HAS_DLSYM3 */
|
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_prog; /* Program name (v3) */
|
||||||
char *crt_ldso; /* Link editor name (v4) */
|
char *crt_ldso; /* Link editor name (v4) */
|
||||||
struct ld_entry *crt_ldentry; /* dl*() access (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_2 2
|
||||||
#define CRT_VERSION_BSD_3 3
|
#define CRT_VERSION_BSD_3 3
|
||||||
#define CRT_VERSION_BSD_4 4
|
#define CRT_VERSION_BSD_4 4
|
||||||
|
#define CRT_VERSION_BSD_5 5
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Maximum number of recognized shared object version numbers.
|
* Maximum number of recognized shared object version numbers.
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# from: @(#)Makefile 5.6 (Berkeley) 5/22/91
|
# 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}
|
CFLAGS+= -DLIBC_SCCS -fno-omit-frame-pointer -I${.CURDIR}
|
||||||
OBJS= crt0.o c++rt0.o gcrt0.o scrt0.o sgcrt0.o
|
OBJS= crt0.o c++rt0.o gcrt0.o scrt0.o sgcrt0.o
|
||||||
CLEANFILES+= a.out
|
CLEANFILES+= a.out
|
||||||
MAN3+= dlopen.3
|
MAN3+= dladdr.3 dlopen.3
|
||||||
MLINKS+= dlopen.3 dlsym.3 \
|
MLINKS+= dlopen.3 dlsym.3 \
|
||||||
dlopen.3 dlerror.3 \
|
dlopen.3 dlerror.3 \
|
||||||
dlopen.3 dlclose.3
|
dlopen.3 dlclose.3
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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>
|
#include <sys/param.h>
|
||||||
@ -85,7 +85,7 @@ static int _strncmp();
|
|||||||
|
|
||||||
extern struct _dynamic _DYNAMIC;
|
extern struct _dynamic _DYNAMIC;
|
||||||
static struct ld_entry *ld_entry;
|
static struct ld_entry *ld_entry;
|
||||||
static void __do_dynamic_link ();
|
static void __do_dynamic_link(char **argv);
|
||||||
#endif /* DYNAMIC */
|
#endif /* DYNAMIC */
|
||||||
|
|
||||||
int _callmain();
|
int _callmain();
|
||||||
@ -174,7 +174,7 @@ start()
|
|||||||
/* sometimes GCC is too smart/stupid for its own good */
|
/* sometimes GCC is too smart/stupid for its own good */
|
||||||
x = (caddr_t)&_DYNAMIC;
|
x = (caddr_t)&_DYNAMIC;
|
||||||
if (x)
|
if (x)
|
||||||
__do_dynamic_link();
|
__do_dynamic_link(argv);
|
||||||
#endif /* DYNAMIC */
|
#endif /* DYNAMIC */
|
||||||
|
|
||||||
asm("eprol:");
|
asm("eprol:");
|
||||||
@ -190,7 +190,8 @@ asm ("__callmain:"); /* Defined for the benefit of debuggers */
|
|||||||
|
|
||||||
#ifdef DYNAMIC
|
#ifdef DYNAMIC
|
||||||
static void
|
static void
|
||||||
__do_dynamic_link ()
|
__do_dynamic_link(argv)
|
||||||
|
char **argv;
|
||||||
{
|
{
|
||||||
struct crt_ldso crt;
|
struct crt_ldso crt;
|
||||||
struct exec hdr;
|
struct exec hdr;
|
||||||
@ -253,14 +254,20 @@ __do_dynamic_link ()
|
|||||||
crt.crt_prog = __progname;
|
crt.crt_prog = __progname;
|
||||||
crt.crt_ldso = ldso;
|
crt.crt_ldso = ldso;
|
||||||
crt.crt_ldentry = NULL;
|
crt.crt_ldentry = NULL;
|
||||||
|
crt.crt_argv = argv;
|
||||||
|
|
||||||
entry = (int (*)())(crt.crt_ba + sizeof hdr);
|
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;
|
ld_entry = crt.crt_ldentry;
|
||||||
if (ldso_version == -1 && ld_entry == NULL) {
|
if (ldso_version == -1 && ld_entry == NULL) {
|
||||||
/* if version 4 not recognised, try version 3 */
|
/* If version 5 not recognised, try version 4 */
|
||||||
ldso_version = (*entry)(CRT_VERSION_BSD_3, &crt);
|
ldso_version = (*entry)(CRT_VERSION_BSD_4, &crt);
|
||||||
ld_entry = _DYNAMIC.d_entry;
|
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) {
|
if (ldso_version == -1) {
|
||||||
_PUTMSG("ld.so failed");
|
_PUTMSG("ld.so failed");
|
||||||
@ -334,6 +341,16 @@ dlerror()
|
|||||||
return (ld_entry->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
|
* Support routines
|
||||||
@ -419,12 +436,19 @@ const char *name;
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
dlerror()
|
dlerror()
|
||||||
{
|
{
|
||||||
return "Service unavailable";
|
return "Service unavailable";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dladdr(addr, dlip)
|
||||||
|
const void *addr;
|
||||||
|
Dl_info *dlip;
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* DYNAMIC */
|
#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)
|
#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
|
__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 *dlopen __P((const char *, int));
|
||||||
void *dlsym __P((void *, const char *));
|
void *dlsym __P((void *, const char *));
|
||||||
const char *dlerror __P((void));
|
|
||||||
int dlclose __P((void *));
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* !_DLFCN_H_ */
|
#endif /* !_DLFCN_H_ */
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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>
|
#include <sys/param.h>
|
||||||
@ -174,6 +174,8 @@ struct somap_private {
|
|||||||
#define RELOC_PCREL_P(s) ((s)->r_pcrel)
|
#define RELOC_PCREL_P(s) ((s)->r_pcrel)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define END_SYM "_end"
|
||||||
|
|
||||||
static char __main_progname[] = "main";
|
static char __main_progname[] = "main";
|
||||||
static char *main_progname = __main_progname;
|
static char *main_progname = __main_progname;
|
||||||
static char us[] = "/usr/libexec/ld.so";
|
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 const char *__dlerror __P((void));
|
||||||
static void __dlexit __P((void));
|
static void __dlexit __P((void));
|
||||||
static void *__dlsym3 __P((void *, const char *, void *));
|
static void *__dlsym3 __P((void *, const char *, void *));
|
||||||
|
static int __dladdr __P((const void *, Dl_info *));
|
||||||
|
|
||||||
static struct ld_entry ld_entry = {
|
static struct ld_entry ld_entry = {
|
||||||
__dlopen, __dlclose, __dlsym, __dlerror, __dlexit, __dlsym3
|
__dlopen, __dlclose, __dlsym, __dlerror, __dlexit, __dlsym3, __dladdr
|
||||||
};
|
};
|
||||||
|
|
||||||
void xprintf __P((char *, ...));
|
void xprintf __P((char *, ...));
|
||||||
@ -302,11 +305,13 @@ struct _dynamic *dp;
|
|||||||
struct so_map *main_map;
|
struct so_map *main_map;
|
||||||
struct so_map *smp;
|
struct so_map *smp;
|
||||||
char *add_paths;
|
char *add_paths;
|
||||||
|
char *main_path;
|
||||||
|
|
||||||
/* Check version */
|
/* Check version */
|
||||||
if (version != CRT_VERSION_BSD_2 &&
|
if (version != CRT_VERSION_BSD_2 &&
|
||||||
version != CRT_VERSION_BSD_3 &&
|
version != CRT_VERSION_BSD_3 &&
|
||||||
version != CRT_VERSION_BSD_4 &&
|
version != CRT_VERSION_BSD_4 &&
|
||||||
|
version != CRT_VERSION_BSD_5 &&
|
||||||
version != CRT_VERSION_SUN)
|
version != CRT_VERSION_SUN)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -335,6 +340,8 @@ struct _dynamic *dp;
|
|||||||
__progname = crtp->crt_ldso;
|
__progname = crtp->crt_ldso;
|
||||||
if (version >= CRT_VERSION_BSD_3)
|
if (version >= CRT_VERSION_BSD_3)
|
||||||
main_progname = crtp->crt_prog;
|
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. */
|
/* Some buggy versions of crt0.o have crt_ldso filled in as NULL. */
|
||||||
if (__progname == NULL)
|
if (__progname == NULL)
|
||||||
@ -363,7 +370,7 @@ struct _dynamic *dp;
|
|||||||
anon_open();
|
anon_open();
|
||||||
|
|
||||||
/* Make a link map entry for the main program */
|
/* 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,
|
(struct sod *) NULL, (struct so_map *) NULL,
|
||||||
(caddr_t) 0, crtp->crt_dp);
|
(caddr_t) 0, crtp->crt_dp);
|
||||||
LM_PRIVATE(main_map)->spd_refcount++;
|
LM_PRIVATE(main_map)->spd_refcount++;
|
||||||
@ -453,7 +460,7 @@ struct _dynamic *dp;
|
|||||||
(void)close(crtp->crt_ldfd);
|
(void)close(crtp->crt_ldfd);
|
||||||
anon_close();
|
anon_close();
|
||||||
|
|
||||||
return LDSO_VERSION_HAS_DLSYM3;
|
return LDSO_VERSION_HAS_DLADDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2024,6 +2031,89 @@ resolvesym(fd, sym, retaddr)
|
|||||||
return (void *)addr;
|
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 *
|
static void *
|
||||||
__dlsym3(fd, sym, retaddr)
|
__dlsym3(fd, sym, retaddr)
|
||||||
void *fd;
|
void *fd;
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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_
|
#ifndef _LINK_H_
|
||||||
#define _LINK_H_
|
#define _LINK_H_
|
||||||
|
|
||||||
|
struct dl_info;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A `Shared Object Descriptor' describes a shared object that is needed
|
* A `Shared Object Descriptor' describes a shared object that is needed
|
||||||
* to complete the link edit process of the object containing it.
|
* 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_NONE 0 /* FreeBSD2.0, 2.0.5 */
|
||||||
#define LDSO_VERSION_HAS_DLEXIT 1 /* includes dlexit in ld_entry */
|
#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_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.
|
* 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 */
|
const char *(*dlerror) __P((void)); /* NONE */
|
||||||
void (*dlexit) __P((void)); /* HAS_DLEXIT */
|
void (*dlexit) __P((void)); /* HAS_DLEXIT */
|
||||||
void *(*dlsym3) __P((void *, const char *, void *)); /* HAS_DLSYM3 */
|
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_prog; /* Program name (v3) */
|
||||||
char *crt_ldso; /* Link editor name (v4) */
|
char *crt_ldso; /* Link editor name (v4) */
|
||||||
struct ld_entry *crt_ldentry; /* dl*() access (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_2 2
|
||||||
#define CRT_VERSION_BSD_3 3
|
#define CRT_VERSION_BSD_3 3
|
||||||
#define CRT_VERSION_BSD_4 4
|
#define CRT_VERSION_BSD_4 4
|
||||||
|
#define CRT_VERSION_BSD_5 5
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Maximum number of recognized shared object version numbers.
|
* 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
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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_
|
#ifndef _LINK_H_
|
||||||
#define _LINK_H_
|
#define _LINK_H_
|
||||||
|
|
||||||
|
struct dl_info;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A `Shared Object Descriptor' describes a shared object that is needed
|
* A `Shared Object Descriptor' describes a shared object that is needed
|
||||||
* to complete the link edit process of the object containing it.
|
* 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_NONE 0 /* FreeBSD2.0, 2.0.5 */
|
||||||
#define LDSO_VERSION_HAS_DLEXIT 1 /* includes dlexit in ld_entry */
|
#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_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.
|
* 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 */
|
const char *(*dlerror) __P((void)); /* NONE */
|
||||||
void (*dlexit) __P((void)); /* HAS_DLEXIT */
|
void (*dlexit) __P((void)); /* HAS_DLEXIT */
|
||||||
void *(*dlsym3) __P((void *, const char *, void *)); /* HAS_DLSYM3 */
|
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_prog; /* Program name (v3) */
|
||||||
char *crt_ldso; /* Link editor name (v4) */
|
char *crt_ldso; /* Link editor name (v4) */
|
||||||
struct ld_entry *crt_ldentry; /* dl*() access (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_2 2
|
||||||
#define CRT_VERSION_BSD_3 3
|
#define CRT_VERSION_BSD_3 3
|
||||||
#define CRT_VERSION_BSD_4 4
|
#define CRT_VERSION_BSD_4 4
|
||||||
|
#define CRT_VERSION_BSD_5 5
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Maximum number of recognized shared object version numbers.
|
* Maximum number of recognized shared object version numbers.
|
||||||
|
Loading…
Reference in New Issue
Block a user