Module Name:    src
Committed By:   skrll
Date:           Sat Oct 16 10:27:08 UTC 2010

Modified Files:
        src/distrib/sets/lists/comp: mi
        src/include: link_elf.h
        src/lib/libc/dlfcn: dlfcn_elf.c
        src/libexec/ld.elf_so: headers.c load.c map_object.c rtld.c rtld.h
            symbol.c
        src/rescue: list.ldd
        src/share/man/man3: Makefile
        src/sys/sys: exec_elf.h
        src/usr.bin/ldd: ldd.c
Added Files:
        src/share/man/man3: dl_iterate_phdr.3

Log Message:
Implement dl_iterate_phdr.

Somewhat taken from FreeBSD. Manual page from OpenBSD.


To generate a diff of this commit:
cvs rdiff -u -r1.1511 -r1.1512 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.9 -r1.10 src/include/link_elf.h
cvs rdiff -u -r1.6 -r1.7 src/lib/libc/dlfcn/dlfcn_elf.c
cvs rdiff -u -r1.35 -r1.36 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.37 -r1.38 src/libexec/ld.elf_so/load.c
cvs rdiff -u -r1.40 -r1.41 src/libexec/ld.elf_so/map_object.c
cvs rdiff -u -r1.130 -r1.131 src/libexec/ld.elf_so/rtld.c
cvs rdiff -u -r1.94 -r1.95 src/libexec/ld.elf_so/rtld.h
cvs rdiff -u -r1.53 -r1.54 src/libexec/ld.elf_so/symbol.c
cvs rdiff -u -r1.3 -r1.4 src/rescue/list.ldd
cvs rdiff -u -r1.55 -r1.56 src/share/man/man3/Makefile
cvs rdiff -u -r0 -r1.1 src/share/man/man3/dl_iterate_phdr.3
cvs rdiff -u -r1.105 -r1.106 src/sys/sys/exec_elf.h
cvs rdiff -u -r1.14 -r1.15 src/usr.bin/ldd/ldd.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.1511 src/distrib/sets/lists/comp/mi:1.1512
--- src/distrib/sets/lists/comp/mi:1.1511	Fri Oct 15 12:29:17 2010
+++ src/distrib/sets/lists/comp/mi	Sat Oct 16 10:27:06 2010
@@ -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

Index: src/include/link_elf.h
diff -u src/include/link_elf.h:1.9 src/include/link_elf.h:1.10
--- src/include/link_elf.h:1.9	Thu Oct 14 07:51:21 2010
+++ src/include/link_elf.h	Sat Oct 16 10:27:06 2010
@@ -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 @@
 	} 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_ */

Index: src/lib/libc/dlfcn/dlfcn_elf.c
diff -u src/lib/libc/dlfcn/dlfcn_elf.c:1.6 src/lib/libc/dlfcn/dlfcn_elf.c:1.7
--- src/lib/libc/dlfcn/dlfcn_elf.c:1.6	Thu Sep 24 21:21:33 2009
+++ src/lib/libc/dlfcn/dlfcn_elf.c	Sat Oct 16 10:27:07 2010
@@ -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 @@
 #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(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(__dlerror,___dlerror)
 __weak_alias(__dladdr,___dladdr)
 __weak_alias(__dlinfo,___dlinfo)
+__weak_alias(__dl_iterate_phdr,___dl_iterate_phdr)
 #endif
 
 /*
@@ -124,3 +127,12 @@
 
 	return -1;
 }
+
+/*ARGSUSED*/
+int
+dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
+    void *data)
+{
+
+	return 0;
+}

Index: src/libexec/ld.elf_so/headers.c
diff -u src/libexec/ld.elf_so/headers.c:1.35 src/libexec/ld.elf_so/headers.c:1.36
--- src/libexec/ld.elf_so/headers.c:1.35	Fri Oct 15 15:08:05 2010
+++ src/libexec/ld.elf_so/headers.c	Sat Oct 16 10:27:07 2010
@@ -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,20 +307,27 @@
 	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) {
+		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 = ph->p_vaddr + relocoffs;
+		vaddr = (Elf_Addr)obj->relocbase + ph->p_vaddr;
 		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;
-
 		case PT_INTERP:
 			obj->interp = (const char *)(uintptr_t)vaddr;
 			break;
@@ -330,7 +337,6 @@
 			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 */

Index: src/libexec/ld.elf_so/load.c
diff -u src/libexec/ld.elf_so/load.c:1.37 src/libexec/ld.elf_so/load.c:1.38
--- src/libexec/ld.elf_so/load.c:1.37	Sat Feb 27 11:16:38 2010
+++ src/libexec/ld.elf_so/load.c	Sat Oct 16 10:27:07 2010
@@ -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_objtail = obj;
 		_rtld_objtail = &obj->next;
 		_rtld_objcount++;
+		_rtld_objloads++;
 #ifdef RTLD_LOADER
 		_rtld_linkmap_add(obj);	/* for GDB */
 #endif

Index: src/libexec/ld.elf_so/map_object.c
diff -u src/libexec/ld.elf_so/map_object.c:1.40 src/libexec/ld.elf_so/map_object.c:1.41
--- src/libexec/ld.elf_so/map_object.c:1.40	Sat Sep 11 11:11:52 2010
+++ src/libexec/ld.elf_so/map_object.c	Sat Oct 16 10:27:07 2010
@@ -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 @@
 #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 @@
 	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 @@
 	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 @@
          * 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 @@
 	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 @@
 		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 @@
 		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);

Index: src/libexec/ld.elf_so/rtld.c
diff -u src/libexec/ld.elf_so/rtld.c:1.130 src/libexec/ld.elf_so/rtld.c:1.131
--- src/libexec/ld.elf_so/rtld.c:1.130	Thu Mar 18 22:17:55 2010
+++ src/libexec/ld.elf_so/rtld.c	Sat Oct 16 10:27:07 2010
@@ -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 @@
 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 @@
 	/* 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 @@
 	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()

Index: src/libexec/ld.elf_so/rtld.h
diff -u src/libexec/ld.elf_so/rtld.h:1.94 src/libexec/ld.elf_so/rtld.h:1.95
--- src/libexec/ld.elf_so/rtld.h:1.94	Sun Oct 10 21:27:16 2010
+++ src/libexec/ld.elf_so/rtld.h	Sat Oct 16 10:27:07 2010
@@ -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 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 @@
 	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 @@
 					 * 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 @@
 	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 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 @@
 
 /* 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__));

Index: src/libexec/ld.elf_so/symbol.c
diff -u src/libexec/ld.elf_so/symbol.c:1.53 src/libexec/ld.elf_so/symbol.c:1.54
--- src/libexec/ld.elf_so/symbol.c:1.53	Mon Apr  5 14:01:26 2010
+++ src/libexec/ld.elf_so/symbol.c	Sat Oct 16 10:27:07 2010
@@ -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 @@
 		(fptr_t)dlerror,
 		(fptr_t)dladdr,
 		(fptr_t)dlinfo,
+		(fptr_t)dl_iterate_phdr,
 		NULL
 	};
 	int i;

Index: src/rescue/list.ldd
diff -u src/rescue/list.ldd:1.3 src/rescue/list.ldd:1.4
--- src/rescue/list.ldd:1.3	Sat Feb 27 11:17:54 2010
+++ src/rescue/list.ldd	Sat Oct 16 10:27:07 2010
@@ -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 @@
 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

Index: src/share/man/man3/Makefile
diff -u src/share/man/man3/Makefile:1.55 src/share/man/man3/Makefile:1.56
--- src/share/man/man3/Makefile:1.55	Tue Jun  8 08:51:09 2010
+++ src/share/man/man3/Makefile	Sat Oct 16 10:27:08 2010
@@ -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 \

Index: src/sys/sys/exec_elf.h
diff -u src/sys/sys/exec_elf.h:1.105 src/sys/sys/exec_elf.h:1.106
--- src/sys/sys/exec_elf.h:1.105	Thu Oct 14 07:57:34 2010
+++ src/sys/sys/exec_elf.h	Sat Oct 16 10:27:08 2010
@@ -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 @@
 	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 @@
 #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 @@
 #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

Index: src/usr.bin/ldd/ldd.c
diff -u src/usr.bin/ldd/ldd.c:1.14 src/usr.bin/ldd/ldd.c:1.15
--- src/usr.bin/ldd/ldd.c:1.14	Sat Feb 27 11:17:05 2010
+++ src/usr.bin/ldd/ldd.c	Sat Oct 16 10:27:08 2010
@@ -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 @@
 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;
 

Added files:

Index: src/share/man/man3/dl_iterate_phdr.3
diff -u /dev/null src/share/man/man3/dl_iterate_phdr.3:1.1
--- /dev/null	Sat Oct 16 10:27:09 2010
+++ src/share/man/man3/dl_iterate_phdr.3	Sat Oct 16 10:27:08 2010
@@ -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 .

Reply via email to