Subject: Re: compatibility and emulation fixes for exec_elf
To: None <tech-kern@NetBSD.org, port-mips@NetBSD.org>
From: Matthias Drochner <M.Drochner@fz-juelich.de>
List: tech-kern
Date: 10/30/2003 20:37:23
This is a multipart MIME message.
--==_Exmh_52098809409620
Content-Type: text/plain; charset=us-ascii
M.Drochner@fz-juelich.de said:
> -In principle, case (3) above wouldn't be needed anymore, and the
> address return argument to the "probe" function could be replaced
> by just a flag bit.
svr4 emulation code uses hardcoded addresses, so this can't be done
I'll append patches which implement the rest of my proposal:
-fix for ELF_INTERP_NON_RELOCATABLE
-nuke irix_load_addr()
-make NO_ADDR the default and remove then unneeded assignments in
emulation elf_probe() functions
-allocate buffer for interpreter name only if needed
(The mips/elf_machdep patch switching off ELF_INTERP_NON_RELOCATABLE
if no COMPAT_16 is needed is from simonb.)
kern/exec_elf32.c could still be streanlined a bit. In particular
NO_ADDR is only used internally now and could be removed from the
public namespace. I also don't see a point in having 2 ways to
express the same: ELF_NO_ADDR and ELFDEFNNAME(NO_ADDR). Also,
ELF_NO_ADDR and ELF_LINK_ADDR are used for the same thing partially.
If noone objects, I'll commit that stuff soon, probably tomorrow.
best regards
Matthias
--==_Exmh_52098809409620
Content-Type: text/plain ; name="elf.txt"; charset=us-ascii
Content-Description: elf.txt
Content-Disposition: attachment; filename="elf.txt"
Index: arch/mips/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/include/elf_machdep.h,v
retrieving revision 1.8
diff -u -p -r1.8 elf_machdep.h
--- arch/mips/include/elf_machdep.h 9 Dec 2001 23:05:58 -0000 1.8
+++ arch/mips/include/elf_machdep.h 30 Oct 2003 19:30:55 -0000
@@ -86,10 +86,16 @@
#define DT_MIPS_HIPAGENO 0x70000014
#define DT_MIPS_RLD_MAP 0x70000016 /* address of loader map */
+#ifdef _KERNEL
+#ifdef _KERNEL_OPT
+#include "opt_compat_netbsd.h"
+#endif
+#ifdef COMPAT_16
/*
+ * Up to 1.6, the ELF dynamic loader (ld.elf_so) was not relocatable.
* Tell the kernel ELF exec code not to try relocating the interpreter
- * (ld.so) for dynamically-linked ELF binaries.
+ * for dynamically-linked ELF binaries.
*/
-#ifdef _KERNEL
#define ELF_INTERP_NON_RELOCATABLE
-#endif
+#endif /* COMPAT_16 */
+#endif /* _KERNEL */
Index: kern/exec_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/kern/exec_elf32.c,v
retrieving revision 1.94
diff -u -p -r1.94 exec_elf32.c
--- kern/exec_elf32.c 8 Aug 2003 18:53:13 -0000 1.94
+++ kern/exec_elf32.c 30 Oct 2003 19:30:56 -0000
@@ -399,8 +399,6 @@ ELFNAME(load_file)(struct proc *p, struc
if ((error = exec_read_from(p, vp, eh.e_phoff, ph, phsize)) != 0)
goto bad;
- /* this breaks on, e.g., OpenBSD-compatible mips shared binaries. */
-#ifndef ELF_INTERP_NON_RELOCATABLE
/*
* If no position to load the interpreter was set by a probe
* function, pick the same address that a non-fixed mmap(0, ..)
@@ -429,8 +427,7 @@ ELFNAME(load_file)(struct proc *p, struc
addr = VM_DEFAULT_ADDRESS(epp->ep_daddr,
round_page(limit) - trunc_page(base_ph->p_vaddr));
} else
-#endif /* !ELF_INTERP_NON_RELOCATABLE */
- addr = *last;
+ addr = *last; /* may be ELF_LINK_ADDR */
/*
* Load all the necessary sections
@@ -452,6 +449,8 @@ ELFNAME(load_file)(struct proc *p, struc
*/
base_ph = ph0;
flags = VMCMD_BASE;
+ if (addr == ELF_LINK_ADDR)
+ addr = ph0->p_vaddr;
if (p->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN)
addr = ELF_TRUNC(addr, ph0->p_align);
else
@@ -574,14 +573,13 @@ ELFNAME2(exec,makecmds)(struct proc *p,
epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR);
epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR);
- MALLOC(interp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
- interp[0] = '\0';
-
for (i = 0; i < eh->e_phnum; i++) {
pp = &ph[i];
if (pp->p_type == PT_INTERP) {
if (pp->p_filesz >= MAXPATHLEN)
goto bad;
+ MALLOC(interp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
+ interp[0] = '\0';
if ((error = exec_read_from(p, epp->ep_vp,
pp->p_offset, interp, pp->p_filesz)) != 0)
goto bad;
@@ -599,16 +597,15 @@ ELFNAME2(exec,makecmds)(struct proc *p,
* exists. Emulation packages may possibly replace the interpreter in
* interp[] with a changed path (/emul/xxx/<path>).
*/
- if (!epp->ep_esch->u.elf_probe_func) {
- pos = ELFDEFNNAME(NO_ADDR);
- } else {
- vaddr_t startp = 0;
+ pos = ELFDEFNNAME(NO_ADDR);
+ if (epp->ep_esch->u.elf_probe_func) {
+ vaddr_t startp = (vaddr_t)pos;
error = (*epp->ep_esch->u.elf_probe_func)(p, epp, eh, interp,
&startp);
- pos = (Elf_Addr)startp;
if (error)
goto bad;
+ pos = (Elf_Addr)startp;
}
/*
@@ -675,7 +672,7 @@ ELFNAME2(exec,makecmds)(struct proc *p,
* Check if we found a dynamically linked binary and arrange to load
* its interpreter
*/
- if (interp[0]) {
+ if (interp) {
struct elf_args *ap;
int i = epp->ep_vmcmds.evs_used;
u_long interp_offset;
@@ -696,6 +693,8 @@ ELFNAME2(exec,makecmds)(struct proc *p,
ap->arg_entry = eh->e_entry;
epp->ep_emul_arg = ap;
+
+ FREE(interp, M_TEMP);
} else
epp->ep_entry = eh->e_entry;
@@ -704,7 +703,6 @@ ELFNAME2(exec,makecmds)(struct proc *p,
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0,
epp->ep_vp, 0, VM_PROT_READ);
#endif
- FREE(interp, M_TEMP);
free(ph, M_TEMP);
return (*epp->ep_esch->es_setup_stack)(p, epp);
@@ -779,6 +777,8 @@ ELFNAME2(netbsd,probe)(struct proc *p, s
if ((error = ELFNAME2(netbsd,signature)(p, epp, eh)) != 0)
return error;
- *pos = ELFDEFNNAME(NO_ADDR);
+#ifdef ELF_INTERP_NON_RELOCATABLE
+ *pos = ELF_LINK_ADDR;
+#endif
return 0;
}
Index: sys/exec_elf.h
===================================================================
RCS file: /cvsroot/src/sys/sys/exec_elf.h,v
retrieving revision 1.72
diff -u -p -r1.72 exec_elf.h
--- sys/exec_elf.h 8 Aug 2003 18:54:16 -0000 1.72
+++ sys/exec_elf.h 30 Oct 2003 19:30:56 -0000
@@ -768,12 +768,16 @@ struct netbsd_elfcore_procinfo {
#define ELF_AUX_ENTRIES 12 /* Size of aux array passed to loader */
#define ELF32_NO_ADDR (~(Elf32_Addr)0) /* Indicates addr. not yet filled in */
+#define ELF32_LINK_ADDR ((Elf32_Addr)-2) /* advises to use link address */
#define ELF64_NO_ADDR (~(Elf64_Addr)0) /* Indicates addr. not yet filled in */
+#define ELF64_LINK_ADDR ((Elf64_Addr)-2) /* advises to use link address */
#if defined(ELFSIZE) && (ELFSIZE == 64)
#define ELF_NO_ADDR ELF64_NO_ADDR
+#define ELF_LINK_ADDR ELF64_LINK_ADDR
#elif defined(ELFSIZE) && (ELFSIZE == 32)
#define ELF_NO_ADDR ELF32_NO_ADDR
+#define ELF_LINK_ADDR ELF32_LINK_ADDR
#endif
#ifndef ELF32_EHDR_FLAGS_OK
Index: compat/freebsd/freebsd_exec_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/compat/freebsd/freebsd_exec_elf32.c,v
retrieving revision 1.11
diff -u -p -r1.11 freebsd_exec_elf32.c
--- compat/freebsd/freebsd_exec_elf32.c 29 Jun 2003 22:29:16 -0000 1.11
+++ compat/freebsd/freebsd_exec_elf32.c 30 Oct 2003 19:30:56 -0000
@@ -115,12 +115,11 @@ ELFNAME2(freebsd,probe)(p, epp, veh, itp
free(ph, M_TEMP);
}
- if (itp[0]) {
+ if (itp) {
if ((error = emul_find_interp(p, epp->ep_esch->es_emul->e_path,
itp)))
return error;
}
- *pos = ELF_NO_ADDR;
#ifdef DEBUG_FREEBSD_ELF
printf("freebsd_elf32_probe: returning 0\n");
#endif
Index: compat/ibcs2/ibcs2_exec_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/compat/ibcs2/ibcs2_exec_elf32.c,v
retrieving revision 1.6
diff -u -p -r1.6 ibcs2_exec_elf32.c
--- compat/ibcs2/ibcs2_exec_elf32.c 29 Jun 2003 22:29:20 -0000 1.6
+++ compat/ibcs2/ibcs2_exec_elf32.c 30 Oct 2003 19:30:56 -0000
@@ -132,10 +132,9 @@ ibcs2_elf32_probe(p, epp, eh, itp, pos)
if ((error = ibcs2_elf32_signature(p, epp, eh)) != 0)
return error;
- if (itp[0]) {
+ if (itp) {
if ((error = emul_find_interp(p, epp->ep_esch->es_emul->e_path, itp)))
return error;
}
- *pos = ELF32_NO_ADDR;
return 0;
}
Index: compat/irix/irix_exec_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/compat/irix/irix_exec_elf32.c,v
retrieving revision 1.8
diff -u -p -r1.8 irix_exec_elf32.c
--- compat/irix/irix_exec_elf32.c 6 Aug 2003 01:04:44 -0000 1.8
+++ compat/irix/irix_exec_elf32.c 30 Oct 2003 19:30:56 -0000
@@ -63,8 +63,6 @@ __KERNEL_RCSID(0, "$NetBSD: irix_exec_el
#include <compat/irix/irix_exec.h>
-static int irix_load_addr(struct proc *, char *, vaddr_t *);
-
/*
* IRIX o32 ABI probe function
*/
@@ -85,7 +83,7 @@ ELFNAME2(irix,probe_o32)(p, epp, eh, itp
IRIX_EF_IRIX_ABIO32)
return error;
- if (itp[0]) {
+ if (itp) {
/* o32 binaries use /lib/libc.so.1 */
if (strncmp(itp, "/lib/libc.so", 12) &&
strncmp(itp, "/usr/lib/libc.so", 16))
@@ -93,10 +91,7 @@ ELFNAME2(irix,probe_o32)(p, epp, eh, itp
if ((error = emul_find_interp(p, epp->ep_esch->es_emul->e_path,
itp)))
return error;
- if ((error = irix_load_addr(p, itp, pos)) != 0)
- return error;
- } else {
- *pos = ELF_NO_ADDR;
+ *pos = ELF_LINK_ADDR;
}
#ifdef DEBUG_IRIX
printf("irix_probe_o32: returning 0\n");
@@ -126,7 +121,7 @@ ELFNAME2(irix,probe_n32)(p, epp, eh, itp
IRIX_EF_IRIX_ABIN32)
return error;
- if (itp[0]) {
+ if (itp) {
/* n32 binaries use /lib32/libc.so.1 */
if (strncmp(itp, "/lib32/libc.so", 14) &&
strncmp(itp, "/usr/lib32/libc.so", 18))
@@ -135,7 +130,6 @@ ELFNAME2(irix,probe_n32)(p, epp, eh, itp
itp)))
return error;
}
- *pos = ELF_NO_ADDR;
#ifdef DEBUG_IRIX
printf("irix_probe_n32: returning 0\n");
printf("epp->ep_vm_minaddr = 0x%lx\n", epp->ep_vm_minaddr);
@@ -263,73 +257,4 @@ ELFNAME2(irix,copyargs)(p, pack, arginfo
printf("*stackp = %p\n", *stackp);
#endif
return 0;
-}
-
-/*
- * Find the load address of the intepreter. Most of the code is
- * borrowed from sys/kern/exec_elf32.c:load_file().
- * There is nothing specific to IRIX here, it may move to
- * sys/compat/compat_util.c if another emulation needs it.
- */
-#define MAXPHNUM 50
-static int
-irix_load_addr(p, itp, pos)
- struct proc *p;
- char *itp;
- vaddr_t *pos;
-{
- int error = 0;
- int i;
- struct nameidata nd;
- struct vnode *vp;
- Elf_Ehdr eh;
- Elf_Phdr *ph = NULL;
- u_long phsize;
-
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, itp, p);
- if ((error = namei(&nd)) != 0)
- return ELFDEFNNAME(NO_ADDR);
- vp = nd.ni_vp;
-
- /* Check this is a regular file */
- if (vp->v_type != VREG) {
- VOP_UNLOCK(vp, 0);
- error = EACCES;
- goto bad;
- }
-
- VOP_UNLOCK(vp, 0);
-
- if ((error = exec_read_from(p, vp, 0, &eh, sizeof(eh))) != 0)
- goto bad;
-
- if ((error = ELFNAME(check_header)(&eh, ET_DYN)) != 0)
- goto bad;
-
- if (eh.e_phnum > MAXPHNUM)
- goto bad;
-
- phsize = eh.e_phnum * sizeof(Elf_Phdr);
- ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
- if ((error = exec_read_from(p, vp, eh.e_phoff, ph, phsize)) != 0)
- goto bad;
-
- /* Look for the first loadable section */
- for (i = 0; i < eh.e_phnum; i++)
- if (ph[i].p_type == PT_LOAD)
- break;
- if (i == eh.e_phnum) {
- error = ENOEXEC;
- goto bad;
- }
-
- *pos = ph[i].p_vaddr;
-#ifdef DEBUG_IRIX
- printf("irix_load_addr: file %s, addr %p\n", itp, (void *)*pos);
-#endif
-bad:
- if (ph != NULL)
- free(ph, M_TEMP);
- vrele(vp);
- return error;
}
Index: compat/linux/common/linux_exec_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/compat/linux/common/linux_exec_elf32.c,v
retrieving revision 1.65
diff -u -p -r1.65 linux_exec_elf32.c
--- compat/linux/common/linux_exec_elf32.c 27 Oct 2003 07:07:34 -0000 1.65
+++ compat/linux/common/linux_exec_elf32.c 30 Oct 2003 19:30:56 -0000
@@ -294,7 +294,7 @@ ELFNAME2(linux,signature)(p, epp, eh, it
}
/* Check for certain intepreter names. */
- if (itp[0]) {
+ if (itp) {
if (!strncmp(itp, "/lib/ld-linux", 13) ||
!strncmp(itp, "/lib/ld.so.", 11))
error = 0;
@@ -329,12 +329,11 @@ ELFNAME2(linux,probe)(p, epp, eh, itp, p
1)
return error;
- if (itp[0]) {
+ if (itp) {
if ((error = emul_find_interp(p, epp->ep_esch->es_emul->e_path,
itp)))
return (error);
}
- *pos = ELF_NO_ADDR;
DPRINTF(("linux_probe: returning 0\n"));
return 0;
}
Index: compat/netbsd32/netbsd32_exec_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_exec_elf32.c,v
retrieving revision 1.20
diff -u -p -r1.20 netbsd32_exec_elf32.c
--- compat/netbsd32/netbsd32_exec_elf32.c 13 Oct 2003 14:22:20 -0000 1.20
+++ compat/netbsd32/netbsd32_exec_elf32.c 30 Oct 2003 19:30:56 -0000
@@ -105,7 +105,7 @@ ELFNAME2(netbsd32,probe_noteless)(struct
{
int error;
- if (itp[0]) {
+ if (itp) {
/* Translate interpreter name if needed */
if ((error = emul_find_interp(p, epp->ep_esch->es_emul->e_path,
itp)) != 0)
@@ -114,7 +114,9 @@ ELFNAME2(netbsd32,probe_noteless)(struct
epp->ep_flags |= EXEC_32;
epp->ep_vm_minaddr = VM_MIN_ADDRESS;
epp->ep_vm_maxaddr = USRSTACK32;
- *pos = ELFDEFNNAME(NO_ADDR);
+#ifdef ELF_INTERP_NON_RELOCATABLE
+ *pos = ELF_LINK_ADDR;
+#endif
return 0;
}
Index: compat/svr4/svr4_exec.h
===================================================================
RCS file: /cvsroot/src/sys/compat/svr4/svr4_exec.h,v
retrieving revision 1.22
diff -u -p -r1.22 svr4_exec.h
--- compat/svr4/svr4_exec.h 29 Jun 2003 22:29:46 -0000 1.22
+++ compat/svr4/svr4_exec.h 30 Oct 2003 19:30:56 -0000
@@ -68,10 +68,6 @@
#define SVR4_INTERP_ADDR 0x10000000
#endif
-#ifndef SVR4_INTERP_ADDR
-# define SVR4_INTERP_ADDR ELFDEFNNAME(NO_ADDR)
-#endif
-
extern const struct emul emul_svr4;
void svr4_setregs __P((struct lwp *, struct exec_package *, u_long));
Index: compat/svr4/svr4_exec_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/compat/svr4/svr4_exec_elf32.c,v
retrieving revision 1.7
diff -u -p -r1.7 svr4_exec_elf32.c
--- compat/svr4/svr4_exec_elf32.c 29 Jun 2003 22:29:46 -0000 1.7
+++ compat/svr4/svr4_exec_elf32.c 30 Oct 2003 19:30:56 -0000
@@ -71,10 +71,12 @@ svr4_elf32_probe(p, epp, eh, itp, pos)
{
int error;
- if (itp[0]) {
+ if (itp) {
if ((error = emul_find_interp(p, epp->ep_esch->es_emul->e_path, itp)))
return error;
}
+#ifdef SVR4_INTERP_ADDR
*pos = SVR4_INTERP_ADDR;
+#endif
return 0;
}
Index: compat/svr4/svr4_exec_elf64.c
===================================================================
RCS file: /cvsroot/src/sys/compat/svr4/svr4_exec_elf64.c,v
retrieving revision 1.8
diff -u -p -r1.8 svr4_exec_elf64.c
--- compat/svr4/svr4_exec_elf64.c 29 Jun 2003 22:29:46 -0000 1.8
+++ compat/svr4/svr4_exec_elf64.c 30 Oct 2003 19:30:56 -0000
@@ -71,10 +71,12 @@ svr4_elf64_probe(p, epp, eh, itp, pos)
{
int error;
- if (itp[0]) {
+ if (itp) {
if ((error = emul_find_interp(p, epp->ep_esch->es_emul->e_path, itp)))
return error;
}
+#ifdef SVR4_INTERP_ADDR
*pos = SVR4_INTERP_ADDR;
+#endif
return 0;
}
Index: compat/svr4_32/svr4_32_exec.h
===================================================================
RCS file: /cvsroot/src/sys/compat/svr4_32/svr4_32_exec.h,v
retrieving revision 1.7
diff -u -p -r1.7 svr4_32_exec.h
--- compat/svr4_32/svr4_32_exec.h 29 Jun 2003 22:29:50 -0000 1.7
+++ compat/svr4_32/svr4_32_exec.h 30 Oct 2003 19:30:56 -0000
@@ -67,10 +67,6 @@ int svr4_32_copyargs __P((struct proc *,
#endif
#endif
-#ifndef SVR4_32_INTERP_ADDR
-# define SVR4_32_INTERP_ADDR ELFDEFNNAME(NO_ADDR)
-#endif
-
extern const struct emul emul_svr4_32;
void svr4_32_setregs __P((struct lwp *, struct exec_package *, u_long));
Index: compat/svr4_32/svr4_32_exec_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/compat/svr4_32/svr4_32_exec_elf32.c,v
retrieving revision 1.12
diff -u -p -r1.12 svr4_32_exec_elf32.c
--- compat/svr4_32/svr4_32_exec_elf32.c 29 Jun 2003 22:29:50 -0000 1.12
+++ compat/svr4_32/svr4_32_exec_elf32.c 30 Oct 2003 19:30:56 -0000
@@ -284,11 +284,13 @@ svr4_32_elf32_probe(p, epp, eh, itp, pos
{
int error;
- if (itp[0]) {
+ if (itp) {
if ((error = emul_find_interp(p, epp->ep_esch->es_emul->e_path, itp)))
return error;
}
epp->ep_flags |= EXEC_32;
+#ifdef SVR4_32_INTERP_ADDR
*pos = SVR4_32_INTERP_ADDR;
+#endif
return 0;
}
--==_Exmh_52098809409620--