Patch from Anton Blanchard <anton@samba.org>

Unfortunately changes ELF_PLAT_INIT to take 2 args.



 s390x/kernel/binfmt_elf32.c |    2 +-
 x86_64/ia32/ia32_binfmt.c   |    2 +-
 binfmt_elf.c                |   13 ++++++++++---
 asm-alpha/elf.h             |    2 +-
 asm-arm/elf.h               |    2 +-
 asm-cris/elf.h              |    2 +-
 asm-i386/elf.h              |    2 +-
 asm-ia64/elf.h              |    2 +-
 asm-ia64/ia32.h             |    2 +-
 asm-m68k/elf.h              |    2 +-
 asm-m68knommu/elf.h         |    2 +-
 asm-mips/elf.h              |    2 +-
 asm-mips64/elf.h            |    2 +-
 asm-parisc/elf.h            |    2 +-
 asm-ppc64/elf.h             |    3 ++-
 asm-s390/elf.h              |    2 +-
 asm-s390x/elf.h             |    2 +-
 asm-sh/elf.h                |    2 +-
 asm-um/archparam-i386.h     |    2 +-
 asm-v850/elf.h              |    2 +-
 asm-x86_64/elf.h            |    2 +-
 21 files changed, 31 insertions(+), 23 deletions(-)

diff -puN arch/s390x/kernel/binfmt_elf32.c~ppc64-64-bit-exec-fix arch/s390x/kernel/binfmt_elf32.c
--- 25/arch/s390x/kernel/binfmt_elf32.c~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/arch/s390x/kernel/binfmt_elf32.c	2003-02-24 13:17:54.000000000 -0800
@@ -36,7 +36,7 @@
 
 /* For SVR4/S390 the function pointer to be registered with `atexit` is
    passed in R14. */
-#define ELF_PLAT_INIT(_r) \
+#define ELF_PLAT_INIT(_r, load_addr) \
 	do { \
 	_r->gprs[14] = 0; \
 	set_thread_flag(TIF_31BIT); \
diff -puN arch/x86_64/ia32/ia32_binfmt.c~ppc64-64-bit-exec-fix arch/x86_64/ia32/ia32_binfmt.c
--- 25/arch/x86_64/ia32/ia32_binfmt.c~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/arch/x86_64/ia32/ia32_binfmt.c	2003-02-24 13:17:54.000000000 -0800
@@ -217,7 +217,7 @@ do {							\
 # define CONFIG_BINFMT_ELF_MODULE	CONFIG_BINFMT_ELF32_MODULE
 #endif
 
-#define ELF_PLAT_INIT(r)		elf32_init(r)
+#define ELF_PLAT_INIT(r, load_addr)	elf32_init(r)
 #define setup_arg_pages(bprm)		ia32_setup_arg_pages(bprm)
 int ia32_setup_arg_pages(struct linux_binprm *bprm);
 
diff -puN fs/binfmt_elf.c~ppc64-64-bit-exec-fix fs/binfmt_elf.c
--- 25/fs/binfmt_elf.c~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/fs/binfmt_elf.c	2003-02-24 13:17:54.000000000 -0800
@@ -455,6 +455,7 @@ static int load_elf_binary(struct linux_
 	unsigned int size;
 	unsigned long elf_entry, interp_load_addr = 0;
 	unsigned long start_code, end_code, start_data, end_data;
+	unsigned long reloc_func_desc = 0;
 	struct elfhdr elf_ex;
 	struct elfhdr interp_elf_ex;
   	struct exec interp_ex;
@@ -698,6 +699,7 @@ static int load_elf_binary(struct linux_
 				load_bias += error -
 				             ELF_PAGESTART(load_bias + vaddr);
 				load_addr += load_bias;
+				reloc_func_desc = load_addr;
 			}
 		}
 		k = elf_ppnt->p_vaddr;
@@ -744,6 +746,7 @@ static int load_elf_binary(struct linux_
 			send_sig(SIGSEGV, current, 0);
 			return 0;
 		}
+		reloc_func_desc = interp_load_addr;
 	} else {
 		elf_entry = elf_ex.e_entry;
 	}
@@ -791,10 +794,14 @@ static int load_elf_binary(struct linux_
 	/*
 	 * The ABI may specify that certain registers be set up in special
 	 * ways (on i386 %edx is the address of a DT_FINI function, for
-	 * example.  This macro performs whatever initialization to
-	 * the regs structure is required.
+	 * example.  In addition, it may also specify (eg, PowerPC64 ELF)
+	 * that the e_entry field is the address of the function descriptor
+	 * for the startup routine, rather than the address of the startup
+	 * routine itself.  This macro performs whatever initialization to
+	 * the regs structure is required as well as any relocations to the
+	 * function descriptor entries when executing dynamically links apps.
 	 */
-	ELF_PLAT_INIT(regs);
+	ELF_PLAT_INIT(regs, reloc_func_desc);
 #endif
 
 	start_thread(regs, elf_entry, bprm->p);
diff -puN include/asm-alpha/elf.h~ppc64-64-bit-exec-fix include/asm-alpha/elf.h
--- 25/include/asm-alpha/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-alpha/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -50,7 +50,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
    we start programs with a value of 0 to indicate that there is no
    such function.  */
 
-#define ELF_PLAT_INIT(_r)       _r->r0 = 0
+#define ELF_PLAT_INIT(_r, load_addr)	_r->r0 = 0
 
 /* The registers are layed out in pt_regs for PAL and syscall
    convenience.  Re-order them for the linear elf_gregset_t.  */
diff -puN include/asm-arm/elf.h~ppc64-64-bit-exec-fix include/asm-arm/elf.h
--- 25/include/asm-arm/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-arm/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -48,7 +48,7 @@ typedef struct { void *null; } elf_fpreg
 /* When the program starts, a1 contains a pointer to a function to be 
    registered with atexit, as per the SVR4 ABI.  A value of 0 means we 
    have no such handler.  */
-#define ELF_PLAT_INIT(_r)	(_r)->ARM_r0 = 0
+#define ELF_PLAT_INIT(_r, load_addr)	(_r)->ARM_r0 = 0
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports. */
diff -puN include/asm-cris/elf.h~ppc64-64-bit-exec-fix include/asm-cris/elf.h
--- 25/include/asm-cris/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-cris/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -39,7 +39,7 @@ typedef unsigned long elf_fpregset_t;
 	   A value of 0 tells we have no such handler.  */
 	
 	/* Explicitly set registers to 0 to increase determinism.  */
-#define ELF_PLAT_INIT(_r)	do { \
+#define ELF_PLAT_INIT(_r, load_addr)	do { \
 	(_r)->r13 = 0; (_r)->r12 = 0; (_r)->r11 = 0; (_r)->r10 = 0; \
 	(_r)->r9 = 0;  (_r)->r8 = 0;  (_r)->r7 = 0;  (_r)->r6 = 0;  \
 	(_r)->r5 = 0;  (_r)->r4 = 0;  (_r)->r3 = 0;  (_r)->r2 = 0;  \
diff -puN include/asm-i386/elf.h~ppc64-64-bit-exec-fix include/asm-i386/elf.h
--- 25/include/asm-i386/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-i386/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -43,7 +43,7 @@ typedef struct user_fxsr_struct elf_fpxr
    We might as well make sure everything else is cleared too (except for %esp),
    just to make things more deterministic.
  */
-#define ELF_PLAT_INIT(_r)	do { \
+#define ELF_PLAT_INIT(_r, load_addr)	do { \
 	_r->ebx = 0; _r->ecx = 0; _r->edx = 0; \
 	_r->esi = 0; _r->edi = 0; _r->ebp = 0; \
 	_r->eax = 0; \
diff -puN include/asm-ia64/elf.h~ppc64-64-bit-exec-fix include/asm-ia64/elf.h
--- 25/include/asm-ia64/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-ia64/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -50,7 +50,7 @@
  * talk to him...
  */
 extern void ia64_init_addr_space (void);
-#define ELF_PLAT_INIT(_r)	ia64_init_addr_space()
+#define ELF_PLAT_INIT(_r, load_addr)	ia64_init_addr_space()
 
 /* ELF register definitions.  This is needed for core dump support.  */
 
diff -puN include/asm-ia64/ia32.h~ppc64-64-bit-exec-fix include/asm-ia64/ia32.h
--- 25/include/asm-ia64/ia32.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-ia64/ia32.h	2003-02-24 13:17:54.000000000 -0800
@@ -306,7 +306,7 @@ struct old_linux32_dirent {
 #define ELF_ET_DYN_BASE		(IA32_PAGE_OFFSET/3 + 0x1000000)
 
 void ia64_elf32_init(struct pt_regs *regs);
-#define ELF_PLAT_INIT(_r)	ia64_elf32_init(_r)
+#define ELF_PLAT_INIT(_r, load_addr)	ia64_elf32_init(_r)
 
 #define elf_addr_t	u32
 
diff -puN include/asm-m68k/elf.h~ppc64-64-bit-exec-fix include/asm-m68k/elf.h
--- 25/include/asm-m68k/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-m68k/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fp
 /* For SVR4/m68k the function pointer to be registered with `atexit' is
    passed in %a1.  Although my copy of the ABI has no such statement, it
    is actually used on ASV.  */
-#define ELF_PLAT_INIT(_r)	_r->a1 = 0
+#define ELF_PLAT_INIT(_r, load_addr)	_r->a1 = 0
 
 #define USE_ELF_CORE_DUMP
 #ifndef CONFIG_SUN3
diff -puN include/asm-m68knommu/elf.h~ppc64-64-bit-exec-fix include/asm-m68knommu/elf.h
--- 25/include/asm-m68knommu/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-m68knommu/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fp
 /* For SVR4/m68k the function pointer to be registered with `atexit' is
    passed in %a1.  Although my copy of the ABI has no such statement, it
    is actually used on ASV.  */
-#define ELF_PLAT_INIT(_r)	_r->a1 = 0
+#define ELF_PLAT_INIT(_r, load_addr)	_r->a1 = 0
 
 #define USE_ELF_CORE_DUMP
 #ifndef CONFIG_SUN3
diff -puN include/asm-mips64/elf.h~ppc64-64-bit-exec-fix include/asm-mips64/elf.h
--- 25/include/asm-mips64/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-mips64/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -76,7 +76,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
  * See comments in asm-alpha/elf.h, this is the same thing
  * on the MIPS.
  */
-#define ELF_PLAT_INIT(_r)	do { \
+#define ELF_PLAT_INIT(_r, load_addr)	do { \
 	_r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0;	\
 	_r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0;	\
 	_r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0;	\
diff -puN include/asm-mips/elf.h~ppc64-64-bit-exec-fix include/asm-mips/elf.h
--- 25/include/asm-mips/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-mips/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -73,7 +73,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
  * See comments in asm-alpha/elf.h, this is the same thing
  * on the MIPS.
  */
-#define ELF_PLAT_INIT(_r)	do { \
+#define ELF_PLAT_INIT(_r, load_addr)	do { \
 	_r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0;	\
 	_r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0;	\
 	_r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0;	\
diff -puN include/asm-parisc/elf.h~ppc64-64-bit-exec-fix include/asm-parisc/elf.h
--- 25/include/asm-parisc/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-parisc/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -118,7 +118,7 @@ struct pt_regs;	/* forward declaration..
    So that we can use the same startup file with static executables,
    we start programs with a value of 0 to indicate that there is no
    such function.  */
-#define ELF_PLAT_INIT(_r)       _r->gr[23] = 0
+#define ELF_PLAT_INIT(_r, load_addr)       _r->gr[23] = 0
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
diff -puN include/asm-s390/elf.h~ppc64-64-bit-exec-fix include/asm-s390/elf.h
--- 25/include/asm-s390/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-s390/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -36,7 +36,7 @@ typedef s390_regs elf_gregset_t;
 
 /* For SVR4/S390 the function pointer to be registered with `atexit` is
    passed in R14. */
-#define ELF_PLAT_INIT(_r) \
+#define ELF_PLAT_INIT(_r, load_addr) \
 	_r->gprs[14] = 0
 
 #define USE_ELF_CORE_DUMP
diff -puN include/asm-s390x/elf.h~ppc64-64-bit-exec-fix include/asm-s390x/elf.h
--- 25/include/asm-s390x/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-s390x/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -36,7 +36,7 @@ typedef s390_regs elf_gregset_t;
 
 /* For SVR4/S390 the function pointer to be registered with `atexit` is
    passed in R14. */
-#define ELF_PLAT_INIT(_r) \
+#define ELF_PLAT_INIT(_r, load_addr) \
 	do { \
 	_r->gprs[14] = 0; \
 	clear_thread_flag(TIF_31BIT); \
diff -puN include/asm-sh/elf.h~ppc64-64-bit-exec-fix include/asm-sh/elf.h
--- 25/include/asm-sh/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-sh/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -61,7 +61,7 @@ typedef struct user_fpu_struct elf_fpreg
 
 #define ELF_PLATFORM  (NULL)
 
-#define ELF_PLAT_INIT(_r) \
+#define ELF_PLAT_INIT(_r, load_addr) \
   do { _r->regs[0]=0; _r->regs[1]=0; _r->regs[2]=0; _r->regs[3]=0; \
        _r->regs[4]=0; _r->regs[5]=0; _r->regs[6]=0; _r->regs[7]=0; \
        _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \
diff -puN include/asm-um/archparam-i386.h~ppc64-64-bit-exec-fix include/asm-um/archparam-i386.h
--- 25/include/asm-um/archparam-i386.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-um/archparam-i386.h	2003-02-24 13:17:54.000000000 -0800
@@ -23,7 +23,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR
 #define ELF_DATA        ELFDATA2LSB
 #define ELF_ARCH        EM_386
 
-#define ELF_PLAT_INIT(regs) do { \
+#define ELF_PLAT_INIT(regs, load_addr) do { \
 	PT_REGS_EBX(regs) = 0; \
 	PT_REGS_ECX(regs) = 0; \
 	PT_REGS_EDX(regs) = 0; \
diff -puN include/asm-v850/elf.h~ppc64-64-bit-exec-fix include/asm-v850/elf.h
--- 25/include/asm-v850/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-v850/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -81,7 +81,7 @@ typedef struct user_fpu_struct elf_fpreg
 
 #define ELF_PLATFORM  (NULL)
 
-#define ELF_PLAT_INIT(_r)						      \
+#define ELF_PLAT_INIT(_r, load_addr)					      \
   do {									      \
 	 _r->gpr[0] =  _r->gpr[1] =  _r->gpr[2] =  _r->gpr[3] =		      \
 	 _r->gpr[4] =  _r->gpr[5] =  _r->gpr[6] =  _r->gpr[7] =		      \
diff -puN include/asm-x86_64/elf.h~ppc64-64-bit-exec-fix include/asm-x86_64/elf.h
--- 25/include/asm-x86_64/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-x86_64/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -39,7 +39,7 @@ typedef struct user_i387_struct elf_fpre
    We might as well make sure everything else is cleared too (except for %esp),
    just to make things more deterministic.
  */
-#define ELF_PLAT_INIT(_r)	do { \
+#define ELF_PLAT_INIT(_r, load_addr)	do { \
 	struct task_struct *cur = current; \
 	(_r)->rbx = 0; (_r)->rcx = 0; (_r)->rdx = 0; \
 	(_r)->rsi = 0; (_r)->rdi = 0; (_r)->rbp = 0; \
diff -puN include/asm-ppc64/elf.h~ppc64-64-bit-exec-fix include/asm-ppc64/elf.h
--- 25/include/asm-ppc64/elf.h~ppc64-64-bit-exec-fix	2003-02-24 13:17:54.000000000 -0800
+++ 25-akpm/include/asm-ppc64/elf.h	2003-02-24 13:17:54.000000000 -0800
@@ -84,9 +84,10 @@ ppc64_elf_core_copy_regs(elf_gregset_t d
 
 #define ELF_PLATFORM	(NULL)
 
-#define ELF_PLAT_INIT(_r)	do { \
+#define ELF_PLAT_INIT(_r, load_addr)	do { \
 	memset(_r->gpr, 0, sizeof(_r->gpr)); \
 	_r->ctr = _r->link = _r->xer = _r->ccr = 0; \
+	_r->gpr[2] = load_addr; \
 } while (0)
 
 #ifdef __KERNEL__

_