summaryrefslogtreecommitdiff
path: root/sys/compat/linux32/common/linux32_exec_elf32.c
diff options
context:
space:
mode:
authorchs <chs@NetBSD.org>2010-07-07 01:30:32 +0000
committerchs <chs@NetBSD.org>2010-07-07 01:30:32 +0000
commit33fa5ccbbf17bc2390e2d136c34926c6f93ac5d1 (patch)
treec52fdcf81396fba59fce0a9c410d0dcc8c104091 /sys/compat/linux32/common/linux32_exec_elf32.c
parent56acc98394a822ba38a843f6385171e0b1aa5e9a (diff)
many changes for COMPAT_LINUX:
- update the linux syscall table for each platform. - support new-style (NPTL) linux pthreads on all platforms. clone() with CLONE_THREAD uses 1 process with many LWPs instead of separate processes. - move the contents of sys__lwp_setprivate() into a new lwp_setprivate() and use that everywhere. - update linux_release[] and linux32_release[] to "2.6.18". - adjust placement of emul fork/exec/exit hooks as needed and adjust other emul code to match. - convert all struct emul definitions to use named initializers. - change the pid allocator to allow multiple pids to refer to the same proc. - remove a few fields from struct proc that are no longer needed. - disable the non-functional "vdso" code in linux32/amd64, glibc works fine without it. - fix a race in the futex code where we could miss a wakeup after a requeue operation. - redo futex locking to be a little more efficient.
Diffstat (limited to 'sys/compat/linux32/common/linux32_exec_elf32.c')
-rw-r--r--sys/compat/linux32/common/linux32_exec_elf32.c172
1 files changed, 79 insertions, 93 deletions
diff --git a/sys/compat/linux32/common/linux32_exec_elf32.c b/sys/compat/linux32/common/linux32_exec_elf32.c
index eac293415ac..9912cb22a9c 100644
--- a/sys/compat/linux32/common/linux32_exec_elf32.c
+++ b/sys/compat/linux32/common/linux32_exec_elf32.c
@@ -1,4 +1,4 @@
-/* $NetBSD: linux32_exec_elf32.c,v 1.10 2010/04/18 23:47:52 jym Exp $ */
+/* $NetBSD: linux32_exec_elf32.c,v 1.11 2010/07/07 01:30:35 chs Exp $ */
/*-
* Copyright (c) 1995, 1998, 2000, 2001,2006 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux32_exec_elf32.c,v 1.10 2010/04/18 23:47:52 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux32_exec_elf32.c,v 1.11 2010/07/07 01:30:35 chs Exp $");
#define ELFSIZE 32
@@ -99,10 +99,6 @@ ELFNAME2(linux32,probe)(struct lwp *l, struct exec_package *epp,
return 0;
}
-/* round up and down to page boundaries. */
-#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
-#define ELF_TRUNC(a, b) ((a) & ~((b) - 1))
-
/*
* Copy arguments onto the stack in the normal way, but add some
* extra information in case of dynamic binding.
@@ -111,131 +107,114 @@ int
linux32_elf32_copyargs(struct lwp *l, struct exec_package *pack,
struct ps_strings *arginfo, char **stackp, void *argp)
{
- struct linux32_extra_stack_data *esdp, esd;
+ Aux32Info ai[LINUX32_ELF_AUX_ENTRIES], *a;
struct elf_args *ap;
struct vattr *vap;
- Elf_Ehdr *eh;
- Elf_Phdr *ph;
- Elf_Addr phdr = 0;
- u_long phsize;
+ size_t len;
int error;
- int i;
if ((error = netbsd32_copyargs(l, pack, arginfo, stackp, argp)) != 0)
return error;
+ a = ai;
+
/*
* Push extra arguments on the stack needed by dynamically
* linked binaries and static binaries as well.
*/
- memset(&esd, 0, sizeof(esd));
- esdp = (struct linux32_extra_stack_data *)(*stackp);
- ap = (struct elf_args *)pack->ep_emul_arg;
- vap = pack->ep_vap;
- eh = (Elf_Ehdr *)pack->ep_hdr;
- /*
- * We forgot this, so we ned to reload it now. XXX keep track of it?
- */
- if (ap == NULL) {
- phsize = eh->e_phnum * sizeof(Elf_Phdr);
- ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
- error = exec_read_from(l, pack->ep_vp, eh->e_phoff, ph, phsize);
- if (error != 0) {
- for (i = 0; i < eh->e_phnum; i++) {
- if (ph[i].p_type == PT_PHDR) {
- phdr = ph[i].p_vaddr;
- break;
- }
- }
- }
- free(ph, M_TEMP);
- }
+ a->a_type = AT_PAGESZ;
+ a->a_v = PAGE_SIZE;
+ a++;
+ if ((ap = (struct elf_args *)pack->ep_emul_arg)) {
- /*
- * The exec_package doesn't have a proc pointer and it's not
- * exactly trivial to add one since the credentials are
- * changing. XXX Linux uses curlwp's credentials.
- * Why can't we use them too? XXXad we do now; what's different
- * about Linux's LWP creds?
- */
+ a->a_type = AT_PHDR;
+ a->a_v = ap->arg_phaddr;
+ a++;
- i = 0;
- esd.ai[i].a_type = LINUX_AT_SYSINFO;
- esd.ai[i++].a_v = NETBSD32PTR32I(&esdp->kernel_vsyscall[0]);
+ a->a_type = AT_PHENT;
+ a->a_v = ap->arg_phentsize;
+ a++;
- esd.ai[i].a_type = LINUX_AT_SYSINFO_EHDR;
- esd.ai[i++].a_v = NETBSD32PTR32I(&esdp->elfhdr);
+ a->a_type = AT_PHNUM;
+ a->a_v = ap->arg_phnum;
+ a++;
- esd.ai[i].a_type = LINUX_AT_HWCAP;
- esd.ai[i++].a_v = LINUX32_CPUCAP;
+ a->a_type = AT_BASE;
+ a->a_v = ap->arg_interp;
+ a++;
- esd.ai[i].a_type = AT_PAGESZ;
- esd.ai[i++].a_v = PAGE_SIZE;
+ a->a_type = AT_FLAGS;
+ a->a_v = 0;
+ a++;
- esd.ai[i].a_type = LINUX_AT_CLKTCK;
- esd.ai[i++].a_v = hz;
+ a->a_type = AT_ENTRY;
+ a->a_v = ap->arg_entry;
+ a++;
- esd.ai[i].a_type = AT_PHDR;
- esd.ai[i++].a_v = (ap ? ap->arg_phaddr: phdr);
+ free(ap, M_TEMP);
+ pack->ep_emul_arg = NULL;
+ }
- esd.ai[i].a_type = AT_PHENT;
- esd.ai[i++].a_v = (ap ? ap->arg_phentsize : eh->e_phentsize);
+ /* Linux-specific items */
+ a->a_type = LINUX_AT_CLKTCK;
+ a->a_v = hz;
+ a++;
- esd.ai[i].a_type = AT_PHNUM;
- esd.ai[i++].a_v = (ap ? ap->arg_phnum : eh->e_phnum);
+ vap = pack->ep_vap;
- esd.ai[i].a_type = AT_BASE;
- esd.ai[i++].a_v = (ap ? ap->arg_interp : 0);
+ a->a_type = LINUX_AT_UID;
+ a->a_v = kauth_cred_getuid(l->l_cred);
+ a++;
- esd.ai[i].a_type = AT_FLAGS;
- esd.ai[i++].a_v = 0;
+ a->a_type = LINUX_AT_EUID;
+ a->a_v = ((vap->va_mode & S_ISUID) ?
+ vap->va_uid : kauth_cred_geteuid(l->l_cred));
+ a++;
- esd.ai[i].a_type = AT_ENTRY;
- esd.ai[i++].a_v = (ap ? ap->arg_entry : eh->e_entry);
+ a->a_type = LINUX_AT_GID;
+ a->a_v = kauth_cred_getgid(l->l_cred);
+ a++;
- esd.ai[i].a_type = LINUX_AT_EGID;
- esd.ai[i++].a_v = ((vap->va_mode & S_ISGID) ?
+ a->a_type = LINUX_AT_EGID;
+ a->a_v = ((vap->va_mode & S_ISGID) ?
vap->va_gid : kauth_cred_getegid(l->l_cred));
+ a++;
- esd.ai[i].a_type = LINUX_AT_GID;
- esd.ai[i++].a_v = kauth_cred_getgid(l->l_cred);
+ a->a_type = LINUX_AT_SECURE;
+ a->a_v = 0;
+ a++;
- esd.ai[i].a_type = LINUX_AT_EUID;
- esd.ai[i++].a_v = ((vap->va_mode & S_ISUID) ?
- vap->va_uid : kauth_cred_geteuid(l->l_cred));
+#if 0
+ a->a_type = LINUX_AT_SYSINFO;
+ a->a_v = NETBSD32PTR32I(&esdp->kernel_vsyscall[0]);
+ a++;
- esd.ai[i].a_type = LINUX_AT_UID;
- esd.ai[i++].a_v = kauth_cred_getuid(l->l_cred);
+ a->a_type = LINUX_AT_SYSINFO_EHDR;
+ a->a_v = NETBSD32PTR32I(&esdp->elfhdr);
+ a++;
- esd.ai[i].a_type = LINUX_AT_SECURE;
- esd.ai[i++].a_v = 0;
+ a->a_type = LINUX_AT_HWCAP;
+ a->a_v = LINUX32_CPUCAP;
+ a++;
- esd.ai[i].a_type = LINUX_AT_PLATFORM;
- esd.ai[i++].a_v = NETBSD32PTR32I(&esdp->hw_platform[0]);
+ a->a_type = LINUX_AT_PLATFORM;
+ a->a_v = NETBSD32PTR32I(&esdp->hw_platform[0]);
+ a++;
+#endif
- esd.ai[i].a_type = AT_NULL;
- esd.ai[i++].a_v = 0;
+ a->a_type = AT_NULL;
+ a->a_v = 0;
+ a++;
-#ifdef DEBUG_LINUX
- if (i != LINUX32_ELF_AUX_ENTRIES) {
- printf("linux32_elf32_copyargs: %d Aux entries\n", i);
- return EINVAL;
- }
-#endif
-
- memcpy(esd.kernel_vsyscall, linux32_kernel_vsyscall,
+#if 0
+ memcpy(esd.kernel_vsyscall, linux32_kernel_vsyscall,
sizeof(linux32_kernel_vsyscall));
memcpy(&esd.elfhdr, eh, sizeof(*eh));
- strcpy(esd.hw_platform, LINUX32_PLATFORM);
-
- if (ap) {
- free((char *)ap, M_TEMP);
- pack->ep_emul_arg = NULL;
- }
+ strcpy(esd.hw_platform, LINUX32_PLATFORM);
/*
* Copy out the ELF auxiliary table and hw platform name
@@ -243,6 +222,13 @@ linux32_elf32_copyargs(struct lwp *l, struct exec_package *pack,
if ((error = copyout(&esd, esdp, sizeof(esd))) != 0)
return error;
*stackp += sizeof(esd);
+#endif
+
+ len = (a - ai) * sizeof(AuxInfo);
+ if ((error = copyout(ai, *stackp, len)) != 0)
+ return error;
+ *stackp += len;
+
return 0;
}