Index: lib/libc/dlfcn/dlfcn_elf.c =================================================================== RCS file: /cvsroot/src/lib/libc/dlfcn/dlfcn_elf.c,v retrieving revision 1.6 diff -u -p -u -r1.6 dlfcn_elf.c --- lib/libc/dlfcn/dlfcn_elf.c 24 Sep 2009 21:21:33 -0000 1.6 +++ lib/libc/dlfcn/dlfcn_elf.c 14 Oct 2010 20:24:29 -0000 @@ -45,6 +45,7 @@ __RCSID("$NetBSD: dlfcn_elf.c,v 1.6 2009 #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; +} Index: libexec/ld.elf_so/load.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/load.c,v retrieving revision 1.37 diff -u -p -u -r1.37 load.c --- libexec/ld.elf_so/load.c 27 Feb 2010 11:16:38 -0000 1.37 +++ libexec/ld.elf_so/load.c 14 Oct 2010 20:24:32 -0000 @@ -156,6 +156,7 @@ _rtld_load_object(const char *filepath, *_rtld_objtail = obj; _rtld_objtail = &obj->next; _rtld_objcount++; + _rtld_objloads++; #ifdef RTLD_LOADER _rtld_linkmap_add(obj); /* for GDB */ #endif Index: libexec/ld.elf_so/map_object.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/map_object.c,v retrieving revision 1.40 diff -u -p -u -r1.40 map_object.c --- libexec/ld.elf_so/map_object.c 11 Sep 2010 11:11:52 -0000 1.40 +++ libexec/ld.elf_so/map_object.c 14 Oct 2010 20:24:33 -0000 @@ -46,10 +46,13 @@ __RCSID("$NetBSD: map_object.c,v 1.40 20 #include #include +#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 f 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 f 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 f * 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 f 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 f 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); Index: libexec/ld.elf_so/rtld.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/rtld.c,v retrieving revision 1.130 diff -u -p -u -r1.130 rtld.c --- libexec/ld.elf_so/rtld.c 18 Mar 2010 22:17:55 -0000 1.130 +++ libexec/ld.elf_so/rtld.c 14 Oct 2010 20:24:33 -0000 @@ -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() Index: libexec/ld.elf_so/rtld.h =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/rtld.h,v retrieving revision 1.94 diff -u -p -u -r1.94 rtld.h --- libexec/ld.elf_so/rtld.h 10 Oct 2010 21:27:16 -0000 1.94 +++ libexec/ld.elf_so/rtld.h 14 Oct 2010 20:24:33 -0000 @@ -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__)); Index: libexec/ld.elf_so/symbol.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/symbol.c,v retrieving revision 1.53 diff -u -p -u -r1.53 symbol.c --- libexec/ld.elf_so/symbol.c 5 Apr 2010 14:01:26 -0000 1.53 +++ libexec/ld.elf_so/symbol.c 14 Oct 2010 20:24:34 -0000 @@ -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; Index: rescue/list.ldd =================================================================== RCS file: /cvsroot/src/rescue/list.ldd,v retrieving revision 1.3 diff -u -p -u -r1.3 list.ldd --- rescue/list.ldd 27 Feb 2010 11:17:54 -0000 1.3 +++ rescue/list.ldd 14 Oct 2010 20:24:35 -0000 @@ -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 Index: sys/sys/exec_elf.h =================================================================== RCS file: /cvsroot/src/sys/sys/exec_elf.h,v retrieving revision 1.105 diff -u -p -u -r1.105 exec_elf.h --- sys/sys/exec_elf.h 14 Oct 2010 07:57:34 -0000 1.105 +++ sys/sys/exec_elf.h 14 Oct 2010 20:25:02 -0000 @@ -46,14 +46,6 @@ #include #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 #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 Index: usr.bin/ldd/ldd.c =================================================================== RCS file: /cvsroot/src/usr.bin/ldd/ldd.c,v retrieving revision 1.14 diff -u -p -u -r1.14 ldd.c --- usr.bin/ldd/ldd.c 27 Feb 2010 11:17:05 -0000 1.14 +++ usr.bin/ldd/ldd.c 14 Oct 2010 20:25:04 -0000 @@ -92,7 +92,9 @@ bool _rtld_trust; /* False for setuid a 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;