Patch from Anton Blanchard Unfortunately changes ELF_PLAT_INIT to take 2 args. arch/s390x/kernel/binfmt_elf32.c | 2 +- arch/x86_64/ia32/ia32_binfmt.c | 2 +- fs/binfmt_elf.c | 13 ++++++++++--- include/asm-alpha/elf.h | 2 +- include/asm-arm/elf.h | 2 +- include/asm-cris/elf.h | 2 +- include/asm-i386/elf.h | 2 +- include/asm-ia64/elf.h | 2 +- include/asm-ia64/ia32.h | 2 +- include/asm-m68k/elf.h | 2 +- include/asm-m68knommu/elf.h | 2 +- include/asm-mips/elf.h | 2 +- include/asm-mips64/elf.h | 2 +- include/asm-parisc/elf.h | 2 +- include/asm-ppc64/elf.h | 3 ++- include/asm-s390/elf.h | 2 +- include/asm-s390x/elf.h | 2 +- include/asm-sh/elf.h | 2 +- include/asm-um/archparam-i386.h | 2 +- include/asm-v850/elf.h | 2 +- include/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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/arch/s390x/kernel/binfmt_elf32.c 2003-03-08 23:27:45.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/arch/x86_64/ia32/ia32_binfmt.c 2003-03-08 23:27:45.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/fs/binfmt_elf.c 2003-03-08 23:27:46.000000000 -0800 @@ -452,6 +452,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; @@ -695,6 +696,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; @@ -742,6 +744,7 @@ static int load_elf_binary(struct linux_ retval = -ENOEXEC; /* Nobody gets to see this, but.. */ goto out; } + reloc_func_desc = interp_load_addr; } else { elf_entry = elf_ex.e_entry; } @@ -789,10 +792,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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-alpha/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-arm/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-cris/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-i386/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-ia64/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-ia64/ia32.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-m68k/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-m68knommu/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-mips64/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-mips/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-parisc/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-s390/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-s390x/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-sh/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-um/archparam-i386.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-v850/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-x86_64/elf.h 2003-03-08 23:27:46.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-03-08 23:27:45.000000000 -0800 +++ 25-akpm/include/asm-ppc64/elf.h 2003-03-08 23:27:46.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__ _