Implement dl_iterate_phdr.

Somewhat taken from FreeBSD. Manual page from OpenBSD.
This commit is contained in:
skrll 2010-10-16 10:27:06 +00:00
parent a00a1fe7ff
commit e6cdac9c4b
14 changed files with 293 additions and 52 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1511 2010/10/15 12:29:17 skrll Exp $
# $NetBSD: mi,v 1.1512 2010/10/16 10:27:06 skrll Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -5588,6 +5588,7 @@
./usr/share/man/cat3/disklabel_dkcksum.0 comp-c-catman .cat
./usr/share/man/cat3/disklabel_scan.0 comp-c-catman .cat
./usr/share/man/cat3/div.0 comp-c-catman .cat
./usr/share/man/cat3/dl_iterate_phdr.0 comp-c-catman .cat
./usr/share/man/cat3/dladdr.0 comp-c-catman .cat
./usr/share/man/cat3/dlclose.0 comp-c-catman .cat
./usr/share/man/cat3/dlctl.0 comp-c-catman .cat
@ -11541,6 +11542,7 @@
./usr/share/man/html3/dlclose.html comp-c-htmlman html
./usr/share/man/html3/dlctl.html comp-c-htmlman html
./usr/share/man/html3/dlerror.html comp-c-htmlman html
./usr/share/man/html3/dl_iterate_phdr.html comp-c-htmlman html
./usr/share/man/html3/dlfcn.html comp-c-htmlman html
./usr/share/man/html3/dlopen.html comp-c-htmlman html
./usr/share/man/html3/dlsym.html comp-c-htmlman html
@ -17394,6 +17396,7 @@
./usr/share/man/man3/disklabel_dkcksum.3 comp-c-man .man
./usr/share/man/man3/disklabel_scan.3 comp-c-man .man
./usr/share/man/man3/div.3 comp-c-man .man
./usr/share/man/man3/dl_iterate_phdr.3 comp-c-man .man
./usr/share/man/man3/dladdr.3 comp-c-man .man
./usr/share/man/man3/dlclose.3 comp-c-man .man
./usr/share/man/man3/dlctl.3 comp-c-man .man

View File

@ -1,11 +1,10 @@
/* $NetBSD: link_elf.h,v 1.9 2010/10/14 07:51:21 skrll Exp $ */
/* $NetBSD: link_elf.h,v 1.10 2010/10/16 10:27:06 skrll Exp $ */
#ifndef _LINK_ELF_H_
#define _LINK_ELF_H_
#include <sys/types.h>
#include <machine/elf_machdep.h>
#include <sys/exec_elf.h>
typedef struct link_map {
caddr_t l_addr; /* Base Address of library */
@ -32,4 +31,23 @@ struct r_debug {
} r_state;
};
struct dl_phdr_info
{
Elf_Addr dlpi_addr; /* module relocation base */
const char *dlpi_name; /* module name */
const Elf_Phdr *dlpi_phdr; /* pointer to module's phdr */
Elf_Half dlpi_phnum; /* number of entries in phdr */
unsigned long long int dlpi_adds; /* total # of loads */
unsigned long long int dlpi_subs; /* total # of unloads */
size_t dlpi_tls_modid;
void *dlpi_tls_data;
};
__BEGIN_DECLS
int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *),
void *);
__END_DECLS
#endif /* _LINK_ELF_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: dlfcn_elf.c,v 1.6 2009/09/24 21:21:33 pooka Exp $ */
/* $NetBSD: dlfcn_elf.c,v 1.7 2010/10/16 10:27:07 skrll Exp $ */
/*
* Copyright (c) 2000 Takuya SHIOZAKI
@ -27,7 +27,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: dlfcn_elf.c,v 1.6 2009/09/24 21:21:33 pooka Exp $");
__RCSID("$NetBSD: dlfcn_elf.c,v 1.7 2010/10/16 10:27:07 skrll Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
@ -45,6 +45,7 @@ __RCSID("$NetBSD: dlfcn_elf.c,v 1.6 2009/09/24 21:21:33 pooka Exp $");
#define dlerror ___dlerror
#define dladdr ___dladdr
#define dlinfo ___dlinfo
#define dl_iterate_phdr ___dl_iterate_phdr
#define ELFSIZE ARCH_ELFSIZE
#include "rtld.h"
@ -56,6 +57,7 @@ __weak_alias(dlsym,___dlsym)
__weak_alias(dlerror,___dlerror)
__weak_alias(dladdr,___dladdr)
__weak_alias(dlinfo,___dlinfo)
__weak_alias(dl_iterate_phdr,___dl_iterate_phdr)
__weak_alias(__dlopen,___dlopen)
__weak_alias(__dlclose,___dlclose)
@ -63,6 +65,7 @@ __weak_alias(__dlsym,___dlsym)
__weak_alias(__dlerror,___dlerror)
__weak_alias(__dladdr,___dladdr)
__weak_alias(__dlinfo,___dlinfo)
__weak_alias(__dl_iterate_phdr,___dl_iterate_phdr)
#endif
/*
@ -124,3 +127,12 @@ dlinfo(void *handle, int req, void *v)
return -1;
}
/*ARGSUSED*/
int
dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
void *data)
{
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: headers.c,v 1.35 2010/10/15 15:08:05 skrll Exp $ */
/* $NetBSD: headers.c,v 1.36 2010/10/16 10:27:07 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: headers.c,v 1.35 2010/10/15 15:08:05 skrll Exp $");
__RCSID("$NetBSD: headers.c,v 1.36 2010/10/16 10:27:07 skrll Exp $");
#endif /* not lint */
#include <err.h>
@ -307,19 +307,26 @@ _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
const Elf_Phdr *phlimit = phdr + phnum;
const Elf_Phdr *ph;
int nsegs = 0;
ptrdiff_t relocoffs = 0;
Elf_Addr vaddr;
obj = _rtld_obj_new();
for (ph = phdr; ph < phlimit; ++ph) {
vaddr = ph->p_vaddr + relocoffs;
switch (ph->p_type) {
case PT_PHDR:
relocoffs = (uintptr_t)phdr - (uintptr_t)ph->p_vaddr;
dbg(("headers: phdr %p phsize %zu relocoffs %lx", obj->phdr,
obj->phsize, (long)relocoffs));
break;
for (ph = phdr; ph < phlimit; ++ph) {
if (ph->p_type != PT_PHDR)
continue;
obj->phdr = (void *)(uintptr_t)phdr->p_vaddr;
obj->phsize = phdr->p_memsz;
obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr);
dbg(("headers: phdr %p phsize %zu relocbase %lx", obj->phdr,
obj->phsize, (long)obj->relocbase));
break;
}
assert(obj->phdr == phdr);
for (ph = phdr; ph < phlimit; ++ph) {
vaddr = (Elf_Addr)obj->relocbase + ph->p_vaddr;
switch (ph->p_type) {
case PT_INTERP:
obj->interp = (const char *)(uintptr_t)vaddr;
@ -330,7 +337,6 @@ _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
if (nsegs == 0) { /* First load segment */
obj->vaddrbase = round_down(vaddr);
obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase;
obj->relocbase = (void *)relocoffs;
obj->textsize = round_up(vaddr + ph->p_memsz) -
obj->vaddrbase;
} else { /* Last load segment */

View File

@ -1,4 +1,4 @@
/* $NetBSD: load.c,v 1.37 2010/02/27 11:16:38 roy Exp $ */
/* $NetBSD: load.c,v 1.38 2010/10/16 10:27:07 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: load.c,v 1.37 2010/02/27 11:16:38 roy Exp $");
__RCSID("$NetBSD: load.c,v 1.38 2010/10/16 10:27:07 skrll Exp $");
#endif /* not lint */
#include <err.h>
@ -156,6 +156,7 @@ _rtld_load_object(const char *filepath, int mode)
*_rtld_objtail = obj;
_rtld_objtail = &obj->next;
_rtld_objcount++;
_rtld_objloads++;
#ifdef RTLD_LOADER
_rtld_linkmap_add(obj); /* for GDB */
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: map_object.c,v 1.40 2010/09/11 11:11:52 skrll Exp $ */
/* $NetBSD: map_object.c,v 1.41 2010/10/16 10:27:07 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -34,7 +34,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: map_object.c,v 1.40 2010/09/11 11:11:52 skrll Exp $");
__RCSID("$NetBSD: map_object.c,v 1.41 2010/10/16 10:27:07 skrll Exp $");
#endif /* not lint */
#include <errno.h>
@ -46,10 +46,13 @@ __RCSID("$NetBSD: map_object.c,v 1.40 2010/09/11 11:11:52 skrll Exp $");
#include <sys/types.h>
#include <sys/mman.h>
#include "debug.h"
#include "rtld.h"
static int protflags(int); /* Elf flags -> mmap protection */
#define EA_UNDEF (~(Elf_Addr)0)
/*
* Map a shared object into memory. The argument is a file descriptor,
* which must be open on the object and positioned at its beginning.
@ -63,6 +66,7 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
Obj_Entry *obj;
Elf_Ehdr *ehdr;
Elf_Phdr *phdr;
size_t phsize;
Elf_Phdr *phlimit;
Elf_Phdr *segs[2];
int nsegs;
@ -83,8 +87,11 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
Elf_Addr data_vlimit;
int data_flags;
caddr_t data_addr;
Elf_Addr phdr_vaddr;
size_t phdr_memsz;
caddr_t gap_addr;
size_t gap_size;
int i;
#ifdef RTLD_LOADER
Elf_Addr clear_vaddr;
caddr_t clear_addr;
@ -152,27 +159,42 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
* in that order.
*/
phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff);
phsize = ehdr->e_phnum * sizeof(phdr[0]);
obj->phdr = NULL;
phdr_vaddr = EA_UNDEF;
phdr_memsz = 0;
phlimit = phdr + ehdr->e_phnum;
nsegs = 0;
while (phdr < phlimit) {
switch (phdr->p_type) {
case PT_INTERP:
obj->interp = (void *)(uintptr_t)phdr->p_vaddr;
dbg(("%s: PT_INTERP %p", obj->path, obj->interp));
break;
case PT_LOAD:
if (nsegs < 2)
segs[nsegs] = phdr;
++nsegs;
dbg(("%s: PT_LOAD %p", obj->path, phdr));
break;
case PT_PHDR:
phdr_vaddr = phdr->p_vaddr;
phdr_memsz = phdr->p_memsz;
dbg(("%s: PT_PHDR %p phsize %zu", obj->path,
(void *)(uintptr_t)phdr_vaddr, phdr_memsz));
break;
case PT_DYNAMIC:
obj->dynamic = (void *)(uintptr_t)phdr->p_vaddr;
dbg(("%s: PT_DYNAMIC %p", obj->path, obj->dynamic));
break;
}
++phdr;
}
phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff);
obj->entry = (void *)(uintptr_t)ehdr->e_entry;
if (!obj->dynamic) {
_rtld_error("%s: not dynamically linked", path);
@ -216,6 +238,39 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
obj->vaddrbase = base_vaddr;
obj->isdynamic = ehdr->e_type == ET_DYN;
obj->phdr_loaded = false;
for (i = 0; i < nsegs; i++) {
if (phdr_vaddr != EA_UNDEF &&
segs[i]->p_vaddr <= phdr_vaddr &&
segs[i]->p_memsz >= phdr_memsz) {
obj->phdr_loaded = true;
break;
}
if (segs[i]->p_offset <= ehdr->e_phoff &&
segs[i]->p_memsz >= phsize) {
phdr_vaddr = segs[i]->p_vaddr + ehdr->e_phoff;
phdr_memsz = phsize;
obj->phdr_loaded = true;
break;
}
}
if (obj->phdr_loaded) {
obj->phdr = (void *)(uintptr_t)phdr_vaddr;
obj->phsize = phdr_memsz;
} else {
Elf_Phdr *buf;
buf = xmalloc(phsize);
if (buf == NULL) {
_rtld_error("%s: cannot allocate program header", path);
goto bad;
}
memcpy(buf, phdr, phsize);
obj->phdr = buf;
obj->phsize = phsize;
}
dbg(("%s: phdr %p phsize %zu (%s)", obj->path, obj->phdr, obj->phsize,
obj->phdr_loaded ? "loaded" : "allocated"));
/* Unmap header if it overlaps the first load section. */
if (base_offset < _rtld_pagesz) {
munmap(ehdr, _rtld_pagesz);
@ -294,6 +349,8 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
obj->entry = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->entry);
if (obj->interp)
obj->interp = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->interp);
if (obj->phdr_loaded)
obj->phdr = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->phdr);
return obj;
@ -325,6 +382,8 @@ _rtld_obj_free(Obj_Entry *obj)
SIMPLEQ_REMOVE_HEAD(&obj->dagmembers, link);
xfree(elm);
}
if (!obj->phdr_loaded)
xfree((void *)(uintptr_t)obj->phdr);
xfree(obj);
#ifdef COMBRELOC
_rtld_combreloc_reset(obj);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.c,v 1.130 2010/03/18 22:17:55 roy Exp $ */
/* $NetBSD: rtld.c,v 1.131 2010/10/16 10:27:07 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: rtld.c,v 1.130 2010/03/18 22:17:55 roy Exp $");
__RCSID("$NetBSD: rtld.c,v 1.131 2010/10/16 10:27:07 skrll Exp $");
#endif /* not lint */
#include <err.h>
@ -83,9 +83,10 @@ struct r_debug _rtld_debug; /* for GDB; */
bool _rtld_trust; /* False for setuid and setgid programs */
Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
Obj_Entry **_rtld_objtail; /* Link field of last object in list */
int _rtld_objcount; /* Number of shared objects */
Obj_Entry *_rtld_objmain; /* The main program shared object */
Obj_Entry _rtld_objself; /* The dynamic linker shared object */
u_int _rtld_objcount; /* Number of objects in _rtld_objlist */
u_int _rtld_objloads; /* Number of objects loaded in _rtld_objlist */
const char _rtld_path[] = _PATH_RTLD;
/* Initialize a fake symbol for resolving undefined weak references. */
@ -501,6 +502,8 @@ _rtld(Elf_Addr *sp, Elf_Addr relocbase)
/* Link the main program into the list of objects. */
*_rtld_objtail = _rtld_objmain;
_rtld_objtail = &_rtld_objmain->next;
_rtld_objcount++;
_rtld_objloads++;
_rtld_linkmap_add(_rtld_objmain);
_rtld_linkmap_add(&_rtld_objself);
@ -1042,6 +1045,38 @@ dlinfo(void *handle, int req, void *v)
return 0;
}
__strong_alias(__dl_iterate_phdr,dl_iterate_phdr);
int
dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *param)
{
struct dl_phdr_info phdr_info;
const Obj_Entry *obj;
int error = 0;
for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
phdr_info.dlpi_addr = (Elf_Addr)obj->relocbase;
phdr_info.dlpi_name = STAILQ_FIRST(&obj->names) ?
STAILQ_FIRST(&obj->names)->name : obj->path;
phdr_info.dlpi_phdr = obj->phdr;
phdr_info.dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
#if 1
phdr_info.dlpi_tls_modid = 0;
phdr_info.dlpi_tls_data = 0;
#else
phdr_info.dlpi_tls_modid = obj->tlsindex;
phdr_info.dlpi_tls_data = obj->tlsinit;
#endif
phdr_info.dlpi_adds = _rtld_objloads;
phdr_info.dlpi_subs = _rtld_objloads - _rtld_objcount;
error = callback(&phdr_info, sizeof(phdr_info), param);
if (error)
break;
}
return error;
}
/*
* Error reporting function. Use it like printf. If formats the message
* into a buffer, and sets things up so that the next call to dlerror()

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.h,v 1.94 2010/10/10 21:27:16 christos Exp $ */
/* $NetBSD: rtld.h,v 1.95 2010/10/16 10:27:07 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -85,6 +85,11 @@ typedef struct Struct_Objlist_Entry {
typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist;
typedef struct Struct_Name_Entry {
STAILQ_ENTRY(Struct_Name_Entry) link;
char name[1];
} Name_Entry;
typedef struct Struct_Needed_Entry {
struct Struct_Needed_Entry *next;
struct Struct_Obj_Entry *obj;
@ -142,8 +147,8 @@ typedef struct Struct_Obj_Entry {
caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */
Elf_Dyn *dynamic; /* Dynamic section */
caddr_t entry; /* Entry point */
const Elf_Phdr *__junk001;
size_t pathlen; /* Pathname length */
const Elf_Phdr *phdr; /* Program header (may be xmalloc'ed) */
size_t phsize; /* Size of program header in bytes */
/* Items from the dynamic section. */
Elf_Addr *pltgot; /* PLTGOT table */
@ -197,8 +202,10 @@ typedef struct Struct_Obj_Entry {
* called */
fini_called:1, /* True if .fini function has been
* called */
initfirst:1; /* True if object's .init/.fini take
* priority over others */
initfirst:1, /* True if object's .init/.fini take
* priority over others */
phdr_loaded:1; /* Phdr is loaded and doesn't need to
* be freed. */
struct link_map linkmap; /* for GDB */
@ -215,6 +222,9 @@ typedef struct Struct_Obj_Entry {
uint32_t nbuckets_m; /* Precomputed for fast remainder */
uint8_t nbuckets_s1;
uint8_t nbuckets_s2;
size_t pathlen; /* Pathname length */
STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we
know about. */
} Obj_Entry;
typedef struct Struct_DoneList {
@ -230,7 +240,8 @@ extern struct r_debug _rtld_debug;
extern Search_Path *_rtld_default_paths;
extern Obj_Entry *_rtld_objlist;
extern Obj_Entry **_rtld_objtail;
extern int _rtld_objcount;
extern u_int _rtld_objcount;
extern u_int _rtld_objloads;
extern Obj_Entry *_rtld_objmain;
extern Obj_Entry _rtld_objself;
extern Search_Path *_rtld_paths;
@ -242,16 +253,17 @@ extern Elf_Sym _rtld_sym_zero;
/* rtld.c */
/*
* We export these symbols using _rtld_symbol_lookup and is_exported.
*/
/* We export these symbols using _rtld_symbol_lookup and is_exported. */
char *dlerror(void);
void *dlopen(const char *, int);
void *dlsym(void *, const char *);
int dlclose(void *);
int dladdr(const void *, Dl_info *);
int dlinfo(void *, int, void *);
int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *),
void *);
/* These aren't exported */
void _rtld_error(const char *, ...)
__attribute__((__format__(__printf__,1,2)));
void _rtld_die(void) __attribute__((__noreturn__));

View File

@ -1,4 +1,4 @@
/* $NetBSD: symbol.c,v 1.53 2010/04/05 14:01:26 joerg Exp $ */
/* $NetBSD: symbol.c,v 1.54 2010/10/16 10:27:07 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: symbol.c,v 1.53 2010/04/05 14:01:26 joerg Exp $");
__RCSID("$NetBSD: symbol.c,v 1.54 2010/10/16 10:27:07 skrll Exp $");
#endif /* not lint */
#include <err.h>
@ -92,6 +92,7 @@ _rtld_is_exported(const Elf_Sym *def)
(fptr_t)dlerror,
(fptr_t)dladdr,
(fptr_t)dlinfo,
(fptr_t)dl_iterate_phdr,
NULL
};
int i;

View File

@ -1,4 +1,4 @@
# $NetBSD: list.ldd,v 1.3 2010/02/27 11:17:54 roy Exp $
# $NetBSD: list.ldd,v 1.4 2010/10/16 10:27:07 skrll Exp $
PROG ldd
@ -8,5 +8,6 @@ LIBS ${LDD_ELF64DIR}/libldd_elf64.a
SPECIAL ldd keepsymbols _rtld_pagesz _rtld_error _rtld_trust
SPECIAL ldd keepsymbols _rtld_default_paths _rtld_paths
SPECIAL ldd keepsymbols _rtld_xforms _rtld_objmain
SPECIAL ldd keepsymbols _rtld_objtail _rtld_objlist _rtld_objcount
SPECIAL ldd keepsymbols _rtld_objtail _rtld_objlist
SPECIAL ldd keepsymbols _rtld_objcount _rtld_objloads
SPECIAL ldd keepsymbols print_needed main_local main_progname

View File

@ -1,8 +1,9 @@
# $NetBSD: Makefile,v 1.55 2010/06/08 08:51:09 jruoho Exp $
# $NetBSD: Makefile,v 1.56 2010/10/16 10:27:08 skrll Exp $
# @(#)Makefile 8.2 (Berkeley) 12/13/93
MAN= _DIAGASSERT.3 __CONCAT.3 __UNCONST.3 CMSG_DATA.3 \
__arraycount.3 assert.3 bits.3 bitstring.3 dirent.3 dlfcn.3 end.3 \
__arraycount.3 assert.3 bits.3 bitstring.3 dirent.3 \
dlfcn.3 dl_iterate_phdr.3 end.3 \
fast_divide32.3 ffs32.3 gcq.3 \
ilog2.3 intro.3 inttypes.3 iso646.3 \
offsetof.3 queue.3 rb.3 sigevent.3 \

View File

@ -0,0 +1,84 @@
.\" $NetBSD: dl_iterate_phdr.3,v 1.1 2010/10/16 10:27:08 skrll Exp $
.\" $OpenBSD: dl_iterate_phdr.3,v 1.3 2007/05/31 19:19:48 jmc Exp $
.\"
.\" Copyright (c) 2005 Mark Kettenis
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd October 16, 2010
.Dt DL_ITERATE_PHDR 3
.Os
.Sh NAME
.Nm dl_iterate_phdr
.Nd iterate over program headers
.Sh SYNOPSIS
.Fd #include <link.h>
.Ft int
.Fn dl_iterate_phdr "int (*callback)(struct dl_phdr_info *, size_t, void*)" "void *data"
.Sh DESCRIPTION
The
.Fn dl_iterate_phdr
function iterates over all shared objects loaded into a process's
address space, calling
.Fa callback
for each shared object, passing it information about the object's
program headers and the
.Fa data
argument.
The information about the program headers is passed in a structure
that is defined as:
.Bd -literal
struct dl_phdr_info {
Elf_Addr dlpi_addr;
const char *dlpi_name;
const Elf_Phdr *dlpi_phdr;
Elf_Half dlpi_phnum;
unsigned long long int dlpi_adds;
unsigned long long int dlpi_subs;
size_t dlpi_tls_modid;
void *dlpi_tls_data;
};
.Ed
.Pp
The members of
.Li struct dl_phdr_info
have the following meaning:
.Bl -tag -width XXXdlpi_phdr
.It Fa dlpi_addr
The base address at which the shared object is mapped into the address
space of the calling process.
.It Fa dlpi_name
The name of the shared object.
.It Fa dlpi_phdr
A pointer to the shared object's program headers.
.It Fa dlpi_phnum
The number of program headers in the shared object.
.It Fa dlpi_adds
The number of objects added into the main program.
.It Fa dlpi_subs
The number of objects removed from the main program.
.El
.Pp
To make it possible for programs to check whether any new members have
been added, the size of the structure is passed as an argument to
.Fa callback .
.Sh SEE ALSO
.Xr ld 1 ,
.Xr ld.elf_so 1 ,
.Xr dlfcn 3 ,
.Xr elf 5
.Sh HISTORY
The
.Nm
function first appeared in
.Nx 6.0 .

View File

@ -1,4 +1,4 @@
/* $NetBSD: exec_elf.h,v 1.105 2010/10/14 07:57:34 skrll Exp $ */
/* $NetBSD: exec_elf.h,v 1.106 2010/10/16 10:27:08 skrll Exp $ */
/*-
* Copyright (c) 1994 The NetBSD Foundation, Inc.
@ -46,14 +46,6 @@
#include <inttypes.h>
#endif /* _KERNEL || _STANDALONE */
#if defined(ELFSIZE)
#define CONCAT(x,y) __CONCAT(x,y)
#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE))
#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
#endif
#if HAVE_NBTOOL_CONFIG_H
#include <nbinclude/machine/elf_machdep.h>
#else
@ -842,6 +834,18 @@ struct netbsd_elfcore_procinfo {
int32_t cpi_siglwp; /* LWP target of killing signal */
};
#if !defined(ELFSIZE) && defined(ARCH_ELFSIZE)
#define ELFSIZE ARCH_ELFSIZE
#endif
#if defined(ELFSIZE)
#define CONCAT(x,y) __CONCAT(x,y)
#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE))
#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
#endif
#if defined(ELFSIZE) && (ELFSIZE == 32)
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Phdr Elf32_Phdr
@ -852,6 +856,7 @@ struct netbsd_elfcore_procinfo {
#define Elf_Dyn Elf32_Dyn
#define Elf_Word Elf32_Word
#define Elf_Sword Elf32_Sword
#define Elf_Half Elf32_Half
#define Elf_Addr Elf32_Addr
#define Elf_Off Elf32_Off
#define Elf_SOff Elf32_SOff
@ -872,6 +877,7 @@ struct netbsd_elfcore_procinfo {
#define Elf_Dyn Elf64_Dyn
#define Elf_Word Elf64_Word
#define Elf_Sword Elf64_Sword
#define Elf_Half Elf64_Half
#define Elf_Addr Elf64_Addr
#define Elf_Off Elf64_Off
#define Elf_SOff Elf64_SOff

View File

@ -1,4 +1,4 @@
/* $NetBSD: ldd.c,v 1.14 2010/02/27 11:17:05 roy Exp $ */
/* $NetBSD: ldd.c,v 1.15 2010/10/16 10:27:08 skrll Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@ -62,7 +62,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ldd.c,v 1.14 2010/02/27 11:17:05 roy Exp $");
__RCSID("$NetBSD: ldd.c,v 1.15 2010/10/16 10:27:08 skrll Exp $");
#endif /* not lint */
#include <sys/types.h>
@ -92,7 +92,9 @@ bool _rtld_trust; /* False for setuid and setgid programs */
Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
Obj_Entry **_rtld_objtail = &_rtld_objlist;
/* Link field of last object in list */
int _rtld_objcount; /* Number of shared objects */
u_int _rtld_objcount; /* Number of shared objects */
u_int _rtld_objloads; /* Number of objects loaded */
Obj_Entry *_rtld_objmain; /* The main program shared object */
size_t _rtld_pagesz;