svn commit: r189362 - in head/sys: amd64/linux32 compat/linux i386/linux

Dmitry Chagin dchagin at FreeBSD.org
Wed Mar 4 04:14:35 PST 2009


Author: dchagin
Date: Wed Mar  4 12:14:33 2009
New Revision: 189362
URL: http://svn.freebsd.org/changeset/base/189362

Log:
  Add AT_PLATFORM, AT_HWCAP and AT_CLKTCK auxiliary vector entries which
  are used by glibc. This silents the message "2.4+ kernel w/o ELF notes?"
  from some programs at start, among them are top and pkill.
  
  Do the assignment of the vector entries in elf_linux_fixup()
  as it is done in glibc.
  
  Fix some minor style issues.
  
  Submitted by:	Marcin Cieslak <saper at SYSTEM PL>
  Approved by:	kib (mentor)
  MFC after:	1 week

Modified:
  head/sys/amd64/linux32/linux.h
  head/sys/amd64/linux32/linux32_sysvec.c
  head/sys/compat/linux/linux_misc.c
  head/sys/compat/linux/linux_misc.h
  head/sys/i386/linux/linux.h
  head/sys/i386/linux/linux_sysvec.c

Modified: head/sys/amd64/linux32/linux.h
==============================================================================
--- head/sys/amd64/linux32/linux.h	Wed Mar  4 06:01:27 2009	(r189361)
+++ head/sys/amd64/linux32/linux.h	Wed Mar  4 12:14:33 2009	(r189362)
@@ -108,6 +108,10 @@ typedef struct {
 
 #define	LINUX_CTL_MAXNAME	10
 
+#define	LINUX_AT_COUNT		16	/* Count of used aux entry types.
+					 * Keep this synchronized with
+					 * elf_linux_fixup() code.
+					 */
 struct l___sysctl_args
 {
 	l_uintptr_t	name;

Modified: head/sys/amd64/linux32/linux32_sysvec.c
==============================================================================
--- head/sys/amd64/linux32/linux32_sysvec.c	Wed Mar  4 06:01:27 2009	(r189361)
+++ head/sys/amd64/linux32/linux32_sysvec.c	Wed Mar  4 12:14:33 2009	(r189362)
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
 #include <amd64/linux32/linux32_proto.h>
 #include <compat/linux/linux_emul.h>
 #include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_misc.h>
 #include <compat/linux/linux_signal.h>
 #include <compat/linux/linux_util.h>
 
@@ -106,6 +107,8 @@ MALLOC_DEFINE(M_LINUX, "linux", "Linux m
 #define	LINUX_SYS_linux_rt_sendsig	0
 #define	LINUX_SYS_linux_sendsig		0
 
+const char *linux_platform = "i686";
+static int linux_szplatform;
 extern char linux_sigcode[];
 extern int linux_szsigcode;
 
@@ -246,7 +249,12 @@ elf_linux_fixup(register_t **stack_base,
 {
 	Elf32_Auxargs *args;
 	Elf32_Addr *base;
-	Elf32_Addr *pos;
+	Elf32_Addr *pos, *uplatform;
+	struct linux32_ps_strings *arginfo;
+
+	arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
+	uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szsigcode -
+	    linux_szplatform);
 
 	KASSERT(curthread->td_proc == imgp->proc,
 	    ("unsafe elf_linux_fixup(), should be curproc"));
@@ -254,8 +262,8 @@ elf_linux_fixup(register_t **stack_base,
 	args = (Elf32_Auxargs *)imgp->auxargs;
 	pos = base + (imgp->args->argc + imgp->args->envc + 2);
 
-	if (args->execfd != -1)
-		AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd);
+	AUXARGS_ENTRY_32(pos, LINUX_AT_HWCAP, cpu_feature);
+	AUXARGS_ENTRY_32(pos, LINUX_AT_CLKTCK, hz);
 	AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr);
 	AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent);
 	AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum);
@@ -263,10 +271,14 @@ elf_linux_fixup(register_t **stack_base,
 	AUXARGS_ENTRY_32(pos, AT_FLAGS, args->flags);
 	AUXARGS_ENTRY_32(pos, AT_ENTRY, args->entry);
 	AUXARGS_ENTRY_32(pos, AT_BASE, args->base);
+	AUXARGS_ENTRY_32(pos, LINUX_AT_SECURE, 0);
 	AUXARGS_ENTRY_32(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
 	AUXARGS_ENTRY_32(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
 	AUXARGS_ENTRY_32(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
 	AUXARGS_ENTRY_32(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
+	AUXARGS_ENTRY_32(pos, LINUX_AT_PLATFORM, PTROUT(uplatform));
+	if (args->execfd != -1)
+		AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd);
 	AUXARGS_ENTRY_32(pos, AT_NULL, 0);
 
 	free(imgp->auxargs, M_TEMP);
@@ -857,23 +869,27 @@ linux_copyout_strings(struct image_param
 	char *stringp, *destp;
 	u_int32_t *stack_base;
 	struct linux32_ps_strings *arginfo;
-	int sigcodesz;
 
 	/*
 	 * Calculate string base and vector table pointers.
 	 * Also deal with signal trampoline code for this exec type.
 	 */
 	arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
-	sigcodesz = *(imgp->proc->p_sysent->sv_szsigcode);
-	destp =	(caddr_t)arginfo - sigcodesz - SPARE_USRSPACE -
-	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
+	destp =	(caddr_t)arginfo - linux_szsigcode - SPARE_USRSPACE -
+	    linux_szplatform - roundup((ARG_MAX - imgp->args->stringspace),
+	    sizeof(char *));
 
 	/*
 	 * install sigcode
 	 */
-	if (sigcodesz)
-		copyout(imgp->proc->p_sysent->sv_sigcode,
-			((caddr_t)arginfo - sigcodesz), sigcodesz);
+	copyout(imgp->proc->p_sysent->sv_sigcode,
+	    ((caddr_t)arginfo - linux_szsigcode), linux_szsigcode);
+
+	/*
+	 * Install LINUX_PLATFORM
+	 */
+	copyout(linux_platform, ((caddr_t)arginfo - linux_szsigcode -
+	    linux_szplatform), linux_szplatform);
 
 	/*
 	 * If we have a valid auxargs ptr, prepare some room
@@ -885,7 +901,7 @@ linux_copyout_strings(struct image_param
 		 * lower compatibility.
 		 */
 		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size :
-		    (AT_COUNT * 2);
+		    (LINUX_AT_COUNT * 2);
 		/*
 		 * The '+ 2' is for the null pointers at the end of each of
 		 * the arg and env vector sets,and imgp->auxarg_size is room
@@ -919,14 +935,14 @@ linux_copyout_strings(struct image_param
 	/*
 	 * Fill in "ps_strings" struct for ps, w, etc.
 	 */
-	suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
+	suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp);
 	suword32(&arginfo->ps_nargvstr, argc);
 
 	/*
 	 * Fill in argument portion of vector table.
 	 */
 	for (; argc > 0; --argc) {
-		suword32(vectp++, (u_int32_t)(intptr_t)destp);
+		suword32(vectp++, (uint32_t)(intptr_t)destp);
 		while (*stringp++ != 0)
 			destp++;
 		destp++;
@@ -935,14 +951,14 @@ linux_copyout_strings(struct image_param
 	/* a null vector table pointer separates the argp's from the envp's */
 	suword32(vectp++, 0);
 
-	suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
+	suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp);
 	suword32(&arginfo->ps_nenvstr, envc);
 
 	/*
 	 * Fill in environment portion of vector table.
 	 */
 	for (; envc > 0; --envc) {
-		suword32(vectp++, (u_int32_t)(intptr_t)destp);
+		suword32(vectp++, (uint32_t)(intptr_t)destp);
 		while (*stringp++ != 0)
 			destp++;
 		destp++;
@@ -1089,6 +1105,8 @@ linux_elf_modevent(module_t mod, int typ
 			    linux_schedtail, NULL, 1000);
 			linux_exec_tag = EVENTHANDLER_REGISTER(process_exec,
 			    linux_proc_exec, NULL, 1000);
+			linux_szplatform = roundup(strlen(linux_platform) + 1,
+			    sizeof(char *));
 			if (bootverbose)
 				printf("Linux ELF exec handler installed\n");
 		} else

Modified: head/sys/compat/linux/linux_misc.c
==============================================================================
--- head/sys/compat/linux/linux_misc.c	Wed Mar  4 06:01:27 2009	(r189361)
+++ head/sys/compat/linux/linux_misc.c	Wed Mar  4 12:14:33 2009	(r189362)
@@ -92,10 +92,6 @@ __FBSDID("$FreeBSD$");
 #include <compat/linux/linux_emul.h>
 #include <compat/linux/linux_misc.h>
 
-#ifdef __i386__
-#include <machine/cputypes.h>
-#endif
-
 #define BSD_TO_LINUX_SIGNAL(sig)	\
 	(((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig)
 
@@ -731,34 +727,8 @@ linux_newuname(struct thread *td, struct
 			*p = '\0';
 			break;
 		}
-#ifdef __i386__
-	{
-		const char *class;
-
-		switch (cpu_class) {
-		case CPUCLASS_686:
-			class = "i686";
-			break;
-		case CPUCLASS_586:
-			class = "i586";
-			break;
-		case CPUCLASS_486:
-			class = "i486";
-			break;
-		default:
-			class = "i386";
-		}
-		strlcpy(utsname.machine, class, LINUX_MAX_UTSNAME);
-	}
-#elif defined(__amd64__)	/* XXX: Linux can change 'personality'. */
-#ifdef COMPAT_LINUX32
-	strlcpy(utsname.machine, "i686", LINUX_MAX_UTSNAME);
-#else
-	strlcpy(utsname.machine, "x86_64", LINUX_MAX_UTSNAME);
-#endif /* COMPAT_LINUX32 */
-#else /* something other than i386 or amd64 - assume we and Linux agree */
-	strlcpy(utsname.machine, machine, LINUX_MAX_UTSNAME);
-#endif /* __i386__ */
+	strlcpy(utsname.machine, linux_platform, LINUX_MAX_UTSNAME);
+
 	mtx_lock(&hostname_mtx);
 	strlcpy(utsname.domainname, V_domainname, LINUX_MAX_UTSNAME);
 	mtx_unlock(&hostname_mtx);

Modified: head/sys/compat/linux/linux_misc.h
==============================================================================
--- head/sys/compat/linux/linux_misc.h	Wed Mar  4 06:01:27 2009	(r189361)
+++ head/sys/compat/linux/linux_misc.h	Wed Mar  4 12:14:33 2009	(r189362)
@@ -45,4 +45,19 @@
 #define	LINUX_MREMAP_MAYMOVE	1
 #define	LINUX_MREMAP_FIXED	2
 
+extern const char *linux_platform;
+
+/*
+ * Non-standard aux entry types used in Linux ELF binaries.
+ */
+
+#define	LINUX_AT_PLATFORM	15	/* String identifying CPU */
+#define	LINUX_AT_HWCAP		16	/* CPU capabilities */
+#define	LINUX_AT_CLKTCK		17	/* frequency at which times() increments */
+#define	LINUX_AT_SECURE		23	/* secure mode boolean */
+#define	LINUX_AT_BASE_PLATFORM	24	/* string identifying real platform, may
+					 * differ from AT_PLATFORM.
+					 */
+#define	LINUX_AT_EXECFN		31	/* filename of program */
+
 #endif	/* _LINUX_MISC_H_ */

Modified: head/sys/i386/linux/linux.h
==============================================================================
--- head/sys/i386/linux/linux.h	Wed Mar  4 06:01:27 2009	(r189361)
+++ head/sys/i386/linux/linux.h	Wed Mar  4 12:14:33 2009	(r189362)
@@ -102,6 +102,10 @@ typedef struct {
 
 #define	LINUX_CTL_MAXNAME	10
 
+#define LINUX_AT_COUNT		16	/* Count of used aux entry types.
+					 * Keep this synchronized with
+					 * elf_linux_fixup() code.
+					 */
 struct l___sysctl_args
 {
 	l_int		*name;

Modified: head/sys/i386/linux/linux_sysvec.c
==============================================================================
--- head/sys/i386/linux/linux_sysvec.c	Wed Mar  4 06:01:27 2009	(r189361)
+++ head/sys/i386/linux/linux_sysvec.c	Wed Mar  4 12:14:33 2009	(r189362)
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_param.h>
 
 #include <machine/cpu.h>
+#include <machine/cputypes.h>
 #include <machine/md_var.h>
 #include <machine/pcb.h>
 
@@ -65,6 +66,7 @@ __FBSDID("$FreeBSD$");
 #include <i386/linux/linux_proto.h>
 #include <compat/linux/linux_emul.h>
 #include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_misc.h>
 #include <compat/linux/linux_signal.h>
 #include <compat/linux/linux_util.h>
 
@@ -107,6 +109,10 @@ static void	linux_prepsyscall(struct tra
 static void     linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
 static void	exec_linux_setregs(struct thread *td, u_long entry,
 				   u_long stack, u_long ps_strings);
+static register_t *linux_copyout_strings(struct image_params *imgp);
+
+static int linux_szplatform;
+const char *linux_platform;
 
 extern LIST_HEAD(futex_list, futex) futex_list;
 extern struct sx futex_sx;
@@ -231,22 +237,30 @@ linux_fixup(register_t **stack_base, str
 	**stack_base = (intptr_t)(void *)argv;
 	(*stack_base)--;
 	**stack_base = imgp->args->argc;
-	return 0;
+	return (0);
 }
 
 static int
 elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
 {
+	struct proc *p;
 	Elf32_Auxargs *args;
+	Elf32_Addr *uplatform;
+	struct ps_strings *arginfo;
 	register_t *pos;
 
 	KASSERT(curthread->td_proc == imgp->proc,
 	    ("unsafe elf_linux_fixup(), should be curproc"));
+
+	p = imgp->proc;
+	arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
+	uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szsigcode -
+	    linux_szplatform);
 	args = (Elf32_Auxargs *)imgp->auxargs;
 	pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
 
-	if (args->execfd != -1)
-		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
+	AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature);
+	AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, hz);
 	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
 	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
 	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
@@ -254,10 +268,14 @@ elf_linux_fixup(register_t **stack_base,
 	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
 	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
 	AUXARGS_ENTRY(pos, AT_BASE, args->base);
+	AUXARGS_ENTRY(pos, LINUX_AT_SECURE, 0);
 	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
 	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
 	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
 	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
+	AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(uplatform));
+	if (args->execfd != -1)
+		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
 	AUXARGS_ENTRY(pos, AT_NULL, 0);
 
 	free(imgp->auxargs, M_TEMP);
@@ -265,9 +283,125 @@ elf_linux_fixup(register_t **stack_base,
 
 	(*stack_base)--;
 	**stack_base = (register_t)imgp->args->argc;
-	return 0;
+	return (0);
 }
 
+/*
+ * Copied from kern/kern_exec.c
+ */
+static register_t *
+linux_copyout_strings(struct image_params *imgp)
+{
+	int argc, envc;
+	char **vectp;
+	char *stringp, *destp;
+	register_t *stack_base;
+	struct ps_strings *arginfo;
+	struct proc *p;
+
+	/*
+	 * Calculate string base and vector table pointers.
+	 * Also deal with signal trampoline code for this exec type.
+	 */
+	p = imgp->proc;
+	arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
+	destp = (caddr_t)arginfo - linux_szsigcode - SPARE_USRSPACE -
+	    linux_szplatform - roundup((ARG_MAX - imgp->args->stringspace),
+	    sizeof(char *));
+
+	/*
+	 * install sigcode
+	 */
+	copyout(p->p_sysent->sv_sigcode, ((caddr_t)arginfo -
+	    linux_szsigcode), linux_szsigcode);
+
+	/*
+	 * install LINUX_PLATFORM
+	 */
+	copyout(linux_platform, ((caddr_t)arginfo - linux_szsigcode -
+	    linux_szplatform), linux_szplatform);
+
+	/*
+	 * If we have a valid auxargs ptr, prepare some room
+	 * on the stack.
+	 */
+	if (imgp->auxargs) {
+		/*
+		 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
+		 * lower compatibility.
+		 */
+		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size :
+		    (LINUX_AT_COUNT * 2);
+		/*
+		 * The '+ 2' is for the null pointers at the end of each of
+		 * the arg and env vector sets,and imgp->auxarg_size is room
+		 * for argument of Runtime loader.
+		 */
+		vectp = (char **)(destp - (imgp->args->argc +
+		    imgp->args->envc + 2 + imgp->auxarg_size) * sizeof(char *));
+	} else {
+		/*
+		 * The '+ 2' is for the null pointers at the end of each of
+		 * the arg and env vector sets
+		 */
+		vectp = (char **)(destp - (imgp->args->argc + imgp->args->envc + 2) *
+		    sizeof(char *));
+	}
+
+	/*
+	 * vectp also becomes our initial stack base
+	 */
+	stack_base = (register_t *)vectp;
+
+	stringp = imgp->args->begin_argv;
+	argc = imgp->args->argc;
+	envc = imgp->args->envc;
+
+	/*
+	 * Copy out strings - arguments and environment.
+	 */
+	copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
+
+	/*
+	 * Fill in "ps_strings" struct for ps, w, etc.
+	 */
+	suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp);
+	suword(&arginfo->ps_nargvstr, argc);
+
+	/*
+	 * Fill in argument portion of vector table.
+	 */
+	for (; argc > 0; --argc) {
+		suword(vectp++, (long)(intptr_t)destp);
+		while (*stringp++ != 0)
+			destp++;
+		destp++;
+	}
+
+	/* a null vector table pointer separates the argp's from the envp's */
+	suword(vectp++, 0);
+
+	suword(&arginfo->ps_envstr, (long)(intptr_t)vectp);
+	suword(&arginfo->ps_nenvstr, envc);
+
+	/*
+	 * Fill in environment portion of vector table.
+	 */
+	for (; envc > 0; --envc) {
+		suword(vectp++, (long)(intptr_t)destp);
+		while (*stringp++ != 0)
+			destp++;
+		destp++;
+	}
+
+	/* end of vector table is a null pointer */
+	suword(vectp, 0);
+
+	return (stack_base);
+}
+
+
+
 extern int _ucodesel, _udatasel;
 extern unsigned long linux_sznonrtsigcode;
 
@@ -808,6 +942,25 @@ exec_linux_setregs(struct thread *td, u_
 	fldcw(&control);
 }
 
+static void
+linux_get_machine(const char **dst)
+{
+
+	switch (cpu_class) {
+	case CPUCLASS_686:
+		*dst = "i686";
+		break;
+	case CPUCLASS_586:
+		*dst = "i586";
+		break;
+	case CPUCLASS_486:
+		*dst = "i486";
+		break;
+	default:
+		*dst = "i386";
+	}
+}
+
 struct sysentvec linux_sysvec = {
 	.sv_size	= LINUX_SYS_MAXSYSCALL,
 	.sv_table	= linux_sysent,
@@ -863,7 +1016,7 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_usrstack	= USRSTACK,
 	.sv_psstrings	= PS_STRINGS,
 	.sv_stackprot	= VM_PROT_ALL,
-	.sv_copyout_strings = exec_copyout_strings,
+	.sv_copyout_strings = linux_copyout_strings,
 	.sv_setregs	= exec_linux_setregs,
 	.sv_fixlimit	= NULL,
 	.sv_maxssiz	= NULL,
@@ -929,6 +1082,9 @@ linux_elf_modevent(module_t mod, int typ
 			      NULL, 1000);
 			linux_exec_tag = EVENTHANDLER_REGISTER(process_exec, linux_proc_exec,
 			      NULL, 1000);
+			linux_get_machine(&linux_platform);
+			linux_szplatform = roundup(strlen(linux_platform) + 1,
+			    sizeof(char *));
 			if (bootverbose)
 				printf("Linux ELF exec handler installed\n");
 		} else


More information about the svn-src-all mailing list