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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to