Skip to contentSkip to conversation

binfmt_elf.c fix with PPC update

PATCH New Benjamin Herrenschmidt 1 participant 1 message Apr 11, 2001

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 binfmt_elf.c fix with PPC update

Hi Linus !

Enclosed is a (not big ;) patch against 2.4.4pre1 that does a few inter-dependant things, one beeing a bug fix for everybody, the other is a mix of bug fix & cleanup on PPC:

- binfmt_elf.c : fix DLINFO_ITEMS so that final alignement on the stack takes into account the AT_NULL entry (or it won't align).

Remove hackish PPC addition (now re-done properly). Add a simple way (via 2 macros) for include/asm-xxx/elf.h to add platform specific entries to it while keeping the alignement right.

- Remove shove_aux_table() in arch/ppc/kernel/process.c. That routine used to lookup the aux table on the stack and move it up to align it to a 16 bytes boundary (ABI). Now done via the ARCH_DLINFO in include/asm-ppc/elf.h

- Re-implement the alignement mecanism properly, taking into account a pair glibc bugs we had until now (not doing so results in breaking existing userland binaries).

- Add 3 new aux table entries for PPC containing some cache line size information. Those are part of our PPC SysV ABI, and were never properly implemented, possibly because of conflict in the AT_xxxx numbers assigned to them. This was now "fixed" and the next glibc release will understand them. Those informations are necessary for glibc to properly handle various brands of PPC CPUs when doing cache invalidates or using cache trick to speed up copy operations.

The patch has been tested on PPC, glibc is ready for it, and it's simple enough not to damage other archs. Next are coming the PPC AT_HWCAP infos, still beeing worked on.

Feel free to comment, not agree, whatever, I'd be glad however if you could explain me if you don't want to merge that now as our glibc maintainer is waiting for it ;)

Regards,
Ben.

fs/binfmt_elf.c +12 -4
@@ -36,7 +36,7 @@
 #include <asm/param.h>
 #include <asm/pgalloc.h>
 
-#define DLINFO_ITEMS 13
+#define DLINFO_ITEMS 14
 
 #include <linux/elf.h>
 
@@ -135,12 +135,13 @@
 
 	/*
 	 * Force 16 byte _final_ alignment here for generality.
-	 * Leave an extra 16 bytes free so that on the PowerPC we
-	 * can move the aux table up to start on a 16-byte boundary.
 	 */
-	sp = (elf_addr_t *)((~15UL & (unsigned long)(u_platform)) - 16UL);
+	sp = (elf_addr_t *)(~15UL & (unsigned long)(u_platform));
 	csp = sp;
 	csp -= DLINFO_ITEMS*2 + (k_platform ? 2 : 0);
+#ifdef DLINFO_ARCH_ITEMS
+	csp -= DLINFO_ARCH_ITEMS*2;
+#endif
 	csp -= envc+1;
 	csp -= argc+1;
 	csp -= (!ibcs ? 3 : 1);	/* argc itself */
@@ -174,6 +175,13 @@
 	NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid);
 	NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid);
 	NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid);
+#ifdef ARCH_DLINFO
+	/* 
+	 * ARCH_DLINFO must come last so platform specific code can enforce
+	 * special alignment requirements on the AUXV if necessary (eg. PPC).
+	 */
+	ARCH_DLINFO;
+#endif
 #undef NEW_AUX_ENT
 
 	sp -= envc+1;
arch/ppc/kernel/process.c +0 -40
@@ -378,45 +378,6 @@
 }
 
 /*
- * XXX ld.so expects the auxiliary table to start on
- * a 16-byte boundary, so we have to find it and
- * move it up. :-(
- */
-static inline void shove_aux_table(unsigned long sp)
-{
-	int argc;
-	char *p;
-	unsigned long e;
-	unsigned long aux_start, offset;
-
-	if (__get_user(argc, (int *)sp))
-		return;
-	sp += sizeof(int) + (argc + 1) * sizeof(char *);
-	/* skip over the environment pointers */
-	do {
-		if (__get_user(p, (char **)sp))
-			return;
-		sp += sizeof(char *);
-	} while (p != NULL);
-	aux_start = sp;
-	/* skip to the end of the auxiliary table */
-	do {
-		if (__get_user(e, (unsigned long *)sp))
-			return;
-		sp += 2 * sizeof(unsigned long);
-	} while (e != AT_NULL);
-	offset = ((aux_start + 15) & ~15) - aux_start;
-	if (offset != 0) {
-		do {
-			sp -= sizeof(unsigned long);
-			if (__get_user(e, (unsigned long *)sp)
-			    || __put_user(e, (unsigned long *)(sp + offset)))
-				return;
-		} while (sp > aux_start);
-	}
-}
-
-/*
  * Set up a thread for executing a new program
  */
 void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
@@ -425,7 +386,6 @@
 	regs->nip = nip;
 	regs->gpr[1] = sp;
 	regs->msr = MSR_USER;
-	shove_aux_table(sp);
 	if (last_task_used_math == current)
 		last_task_used_math = 0;
 	if (last_task_used_altivec == current)
include/asm-ppc/elf.h +35 -9

55 lines not on this page · raw message