Hi all, attached is a patch to provide all NetBSD binaries with a reference to the auxillary vector. This is a minor change for dynamically linked programs as the usual information are already used by ld.elf_so. It is a major change for statically linked programs as it allows the dl_iterate_phdr interface to work. This is usual for libunwind and TLS support. This works as long as the PHDR is either explicitly or implicitly part of the loaded segments. This seems to be the case on NetBSD by default, but could be enforced by modifying the linker script accordingly.
The loop to find the end of environ can be eliminated if the __ps_strings problem is fixed as that structure contains the number of entries in environ. Further changes could include a careful check of initial system calls of typical process traces. One change to adopt from FreeBSD (IIRC) is to include the initial seed for arc4random to save that system call etc. Joerg
Index: src/lib/csu/alpha/crt0.c =================================================================== --- src/lib/csu/alpha/crt0.c +++ src/lib/csu/alpha/crt0.c @@ -46,14 +46,19 @@ const Obj_Entry *obj; /* from shared loader */ struct ps_strings *ps_strings; { long argc; char **argv, *namep; + size_t i; argc = *(long *)sp; argv = sp + 1; environ = sp + 2 + argc; /* 2: argc + NULL ending argv */ + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(namep, '/')) == NULL) __progname = namep; else Index: src/lib/csu/arm_elf/crt0.c =================================================================== --- src/lib/csu/arm_elf/crt0.c +++ src/lib/csu/arm_elf/crt0.c @@ -73,13 +73,19 @@ void ___start(int argc, char **argv, char **envp, struct ps_strings *ps_strings, const Obj_Entry *obj, void (*cleanup)(void)) { + size_t i; char *ap; - environ = envp; + environ = envp; + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; + __ps_strings = ps_strings; if ((ap = argv[0])) { if ((__progname = _strrchr(ap, '/')) == NULL) __progname = ap; Index: src/lib/csu/common/crt0-common.c =================================================================== --- src/lib/csu/common/crt0-common.c +++ src/lib/csu/common/crt0-common.c @@ -64,11 +64,12 @@ extern void _mcleanup(void); extern unsigned char __etext, __eprol; #endif /* MCRT0 */ char **environ; -struct ps_strings *__ps_strings = 0; +void *__auxinfo; +struct ps_strings *__ps_strings; static char empty_string[] = ""; char *__progname = empty_string; void ___start(int, char **, char **, void (*)(void), @@ -86,11 +87,17 @@ ___start(int argc, char **argv, char **envp, void (*cleanup)(void), /* from shared loader */ const Obj_Entry *obj, /* from shared loader */ struct ps_strings *ps_strings) { + size_t i; + environ = envp; + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if (argv[0] != NULL) { char *c; __progname = argv[0]; for (c = argv[0]; *c; ++c) { Index: src/lib/csu/common_elf/common.h =================================================================== --- src/lib/csu/common_elf/common.h +++ src/lib/csu/common_elf/common.h @@ -65,10 +65,11 @@ static char *_strrchr(char *, int); char **environ; char *__progname = ""; +void *__auxinfo; struct ps_strings *__ps_strings = 0; extern void _init(void); extern void _fini(void); Index: src/lib/csu/hppa/crt0.c =================================================================== --- src/lib/csu/hppa/crt0.c +++ src/lib/csu/hppa/crt0.c @@ -71,14 +71,19 @@ int dp) { int argc; char **argv; int fini_plabel[2]; + size_t i; argc = ps_strings->ps_nargvstr; argv = ps_strings->ps_argvstr; environ = ps_strings->ps_envstr; + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(__progname, '/')) == NULL) __progname = argv[0]; else Index: src/lib/csu/ia64/crt0.c =================================================================== --- src/lib/csu/ia64/crt0.c +++ src/lib/csu/ia64/crt0.c @@ -45,10 +45,11 @@ const Obj_Entry *obj, /* from shared loader */ struct ps_strings *ps_strings) { long argc; char **argv, *namep; + size_t i; __asm __volatile__ ("1: \ { .mii \ mov r...@gprel(1b) \n \ mov r16=ip ;; \n \ @@ -57,10 +58,14 @@ } "); argc = *(long *)sp; argv = sp + 1; environ = sp + 2 + argc; /* 2: argc + NULL ending argv */ + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(namep, '/')) == NULL) __progname = namep; else Index: src/lib/csu/m68k_elf/crt0.c =================================================================== --- src/lib/csu/m68k_elf/crt0.c +++ src/lib/csu/m68k_elf/crt0.c @@ -60,11 +60,17 @@ __start(int argc, char **argv, char **envp, void (*cleanup)(void), /* from shared loader */ const Obj_Entry *obj, /* from shared loader */ struct ps_strings *ps_strings) { + size_t i; + environ = envp; + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(__progname, '/')) == NULL) __progname = argv[0]; else Index: src/lib/csu/mips/crt0.c =================================================================== --- src/lib/csu/mips/crt0.c +++ src/lib/csu/mips/crt0.c @@ -64,10 +64,11 @@ struct ps_strings *ps_strings) { char **ksp; char **argv, *namep; int argc; + size_t i; /* * Grab the argc, argv, and envp set up by the kernel. * Layout of stuff on the stack: * @@ -119,10 +120,14 @@ argc = *(int *)ksp; argv = ksp + 1; environ = ksp + 2 + argc; /* 2: argc + NULL ending argv */ + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(namep, '/')) == NULL) __progname = namep; else Index: src/lib/csu/powerpc/crt0.c =================================================================== --- src/lib/csu/powerpc/crt0.c +++ src/lib/csu/powerpc/crt0.c @@ -56,10 +56,11 @@ const Obj_Entry *obj, /* from shared loader */ void (*cleanup)(void), /* from shared loader */ struct ps_strings *ps_strings) /* NetBSD extension */ { char *namep; + size_t i; /* * Initialize the Small Data Area registers. * _SDA_BASE is defined in the SVR4 ABI for PPC. * _SDA2_BASE is defined in the E[mbedded] ABI for PPC. @@ -75,10 +76,14 @@ else __progname++; } environ = envp; + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if (ps_strings != (struct ps_strings *)0) __ps_strings = ps_strings; #ifdef DYNAMIC Index: src/lib/csu/powerpc64/crt0.c =================================================================== --- src/lib/csu/powerpc64/crt0.c +++ src/lib/csu/powerpc64/crt0.c @@ -58,19 +58,24 @@ const Obj_Entry *obj, /* from shared loader */ void (*cleanup)(void), /* from shared loader */ struct ps_strings *ps_strings) /* NetBSD extension */ { char *namep; + size_t i; if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(namep, '/')) == NULL) __progname = namep; else __progname++; } environ = envp; + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if (ps_strings != (struct ps_strings *)0) __ps_strings = ps_strings; #ifdef DYNAMIC Index: src/lib/csu/sh3_elf/crt0.c =================================================================== --- src/lib/csu/sh3_elf/crt0.c +++ src/lib/csu/sh3_elf/crt0.c @@ -54,11 +54,17 @@ ___start(int argc, char **argv, char **envp, void (*cleanup)(void), /* from shared loader */ const Obj_Entry *obj, /* from shared loader */ struct ps_strings *ps_strings) { + size_t i; + environ = envp; + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(__progname, '/')) == NULL) __progname = argv[0]; else Index: src/lib/csu/sparc64/crt0.c =================================================================== --- src/lib/csu/sparc64/crt0.c +++ src/lib/csu/sparc64/crt0.c @@ -75,14 +75,19 @@ const Obj_Entry *obj, /* from shared loader */ struct ps_strings *ps_strings) { long argc; char **argv, *namep; + size_t i; argc = *(long *)sp; argv = sp + 1; environ = sp + 2 + argc; /* 2: argc + NULL ending argv */ + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if ((namep = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(namep, '/')) == NULL) __progname = namep; else Index: src/lib/csu/sparc_elf/crt0.c =================================================================== --- src/lib/csu/sparc_elf/crt0.c +++ src/lib/csu/sparc_elf/crt0.c @@ -64,11 +64,17 @@ ___start(int argc, char **argv, char **envp, void (*cleanup)(void), /* from shared loader */ const Obj_Entry *obj, /* from shared loader */ struct ps_strings *ps_strings) { + size_t i; + environ = envp; + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(__progname, '/')) == NULL) __progname = argv[0]; else Index: src/lib/csu/vax_elf/crt0.c =================================================================== --- src/lib/csu/vax_elf/crt0.c +++ src/lib/csu/vax_elf/crt0.c @@ -61,11 +61,17 @@ ___start(int argc, char **argv, char **envp, void (*cleanup)(void), /* from shared loader */ const Obj_Entry *obj, /* from shared loader */ struct ps_strings *ps_strings) { + size_t i; + environ = envp; + + for (i = 0; environ[i] != NULL; ) + ++i; + __auxinfo = &environ[i + 1]; if ((__progname = argv[0]) != NULL) { /* NULL ptr if argc = 0 */ if ((__progname = _strrchr(__progname, '/')) == NULL) __progname = argv[0]; else Index: src/lib/libc/dlfcn/dlfcn_elf.c =================================================================== --- src/lib/libc/dlfcn/dlfcn_elf.c +++ src/lib/libc/dlfcn/dlfcn_elf.c @@ -28,11 +28,15 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) __RCSID("$NetBSD: dlfcn_elf.c,v 1.7 2010/10/16 10:27:07 skrll Exp $"); #endif /* LIBC_SCCS and not lint */ +#include "reentrant.h" #include "namespace.h" +#include <errno.h> +#include <string.h> +#include <elf.h> #undef dlopen #undef dlclose #undef dlsym #undef dlerror @@ -126,13 +130,58 @@ { return -1; } +static once_t dl_iterate_phdr_once = ONCE_INITIALIZER; +static const char *dlpi_name; +static const Elf_Phdr *dlpi_phdr; +static Elf_Half dlpi_phnum; + +/* + * Declare as common symbol to allow new libc with older binaries to + * not trigger an undefined reference. + */ +void *__auxinfo; + +static void +dl_iterate_phdr_setup(void) +{ + const AuxInfo *aux; + + if (__auxinfo == NULL) + return; + + for (aux = __auxinfo; aux->a_type != AT_NULL; ++aux) { + switch (aux->a_type) { + case AT_PHDR: + dlpi_phdr = (void *)aux->a_v; + break; + case AT_PHNUM: + dlpi_phnum = aux->a_v; + break; + case AT_SUN_EXECNAME: + dlpi_name = (void *)aux->a_v; + break; + } + } +} + /*ARGSUSED*/ int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data) { + struct dl_phdr_info phdr_info; + + if (__auxinfo == NULL) + return EOPNOTSUPP; + + thr_once(&dl_iterate_phdr_once, dl_iterate_phdr_setup); + + memset(&phdr_info, 0, sizeof(phdr_info)); + phdr_info.dlpi_phdr = dlpi_phdr; + phdr_info.dlpi_phnum = dlpi_phnum; + phdr_info.dlpi_name = dlpi_name; - return 0; + return callback(&phdr_info, sizeof(phdr_info), data); } Index: src/sys/compat/netbsd32/netbsd32_exec_elf32.c =================================================================== --- src/sys/compat/netbsd32/netbsd32_exec_elf32.c +++ src/sys/compat/netbsd32/netbsd32_exec_elf32.c @@ -113,11 +113,11 @@ { if (itp && epp->ep_interp == NULL) { extern const char machine32[]; (void)compat_elf_check_interp(epp, itp, machine32); } - epp->ep_flags |= EXEC_32; + epp->ep_flags |= EXEC_32 | EXEC_FORCEAUX; epp->ep_vm_minaddr = VM_MIN_ADDRESS; epp->ep_vm_maxaddr = USRSTACK32; #ifdef ELF_INTERP_NON_RELOCATABLE *pos = ELF_LINK_ADDR; #endif Index: src/sys/kern/exec_elf.c =================================================================== --- src/sys/kern/exec_elf.c +++ src/sys/kern/exec_elf.c @@ -931,7 +931,8 @@ if ((error = ELF_MD_PROBE_FUNC(l, epp, eh, itp, pos)) != 0) return error; #elif defined(ELF_INTERP_NON_RELOCATABLE) *pos = ELF_LINK_ADDR; #endif + epp->ep_flags |= EXEC_FORCEAUX; return 0; }