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;
 }

Reply via email to