Commit 544db1a2 authored by Andrew Morton's avatar Andrew Morton Committed by Dave Jones

[PATCH] Pass the load address into ELF_PLAT_INIT()

Patch from Anton Blanchard <anton@samba.org>

With ppc64 64bit dynamic executables we have to relocate the contents of the
function descriptor.  Passing in the load address to ELF_PLAT_INIT allows us
to do this.

The patch allows ppc64 to run 64-bit executables and is a no-op for other
architectures.
parent eb5ef7e6
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
/* For SVR4/S390 the function pointer to be registered with `atexit` is /* For SVR4/S390 the function pointer to be registered with `atexit` is
passed in R14. */ passed in R14. */
#define ELF_PLAT_INIT(_r) \ #define ELF_PLAT_INIT(_r, load_addr) \
do { \ do { \
_r->gprs[14] = 0; \ _r->gprs[14] = 0; \
set_thread_flag(TIF_31BIT); \ set_thread_flag(TIF_31BIT); \
......
...@@ -217,7 +217,7 @@ do { \ ...@@ -217,7 +217,7 @@ do { \
# define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE # define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE
#endif #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) #define setup_arg_pages(bprm) ia32_setup_arg_pages(bprm)
int ia32_setup_arg_pages(struct linux_binprm *bprm); int ia32_setup_arg_pages(struct linux_binprm *bprm);
......
...@@ -452,6 +452,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -452,6 +452,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
unsigned int size; unsigned int size;
unsigned long elf_entry, interp_load_addr = 0; unsigned long elf_entry, interp_load_addr = 0;
unsigned long start_code, end_code, start_data, end_data; unsigned long start_code, end_code, start_data, end_data;
unsigned long reloc_func_desc = 0;
struct elfhdr elf_ex; struct elfhdr elf_ex;
struct elfhdr interp_elf_ex; struct elfhdr interp_elf_ex;
struct exec interp_ex; struct exec interp_ex;
...@@ -695,6 +696,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -695,6 +696,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
load_bias += error - load_bias += error -
ELF_PAGESTART(load_bias + vaddr); ELF_PAGESTART(load_bias + vaddr);
load_addr += load_bias; load_addr += load_bias;
reloc_func_desc = load_addr;
} }
} }
k = elf_ppnt->p_vaddr; k = elf_ppnt->p_vaddr;
...@@ -742,6 +744,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -742,6 +744,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
retval = -ENOEXEC; /* Nobody gets to see this, but.. */ retval = -ENOEXEC; /* Nobody gets to see this, but.. */
goto out; goto out;
} }
reloc_func_desc = interp_load_addr;
} else { } else {
elf_entry = elf_ex.e_entry; elf_entry = elf_ex.e_entry;
} }
...@@ -789,10 +792,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -789,10 +792,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* /*
* The ABI may specify that certain registers be set up in special * 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 * ways (on i386 %edx is the address of a DT_FINI function, for
* example. This macro performs whatever initialization to * example. In addition, it may also specify (eg, PowerPC64 ELF)
* the regs structure is required. * 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 #endif
start_thread(regs, elf_entry, bprm->p); start_thread(regs, elf_entry, bprm->p);
......
...@@ -50,7 +50,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; ...@@ -50,7 +50,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
we start programs with a value of 0 to indicate that there is no we start programs with a value of 0 to indicate that there is no
such function. */ 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 /* The registers are layed out in pt_regs for PAL and syscall
convenience. Re-order them for the linear elf_gregset_t. */ convenience. Re-order them for the linear elf_gregset_t. */
......
...@@ -48,7 +48,7 @@ typedef struct { void *null; } elf_fpregset_t; ...@@ -48,7 +48,7 @@ typedef struct { void *null; } elf_fpregset_t;
/* When the program starts, a1 contains a pointer to a function to be /* 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 registered with atexit, as per the SVR4 ABI. A value of 0 means we
have no such handler. */ 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 /* This yields a mask that user programs can use to figure out what
instruction set this cpu supports. */ instruction set this cpu supports. */
......
...@@ -39,7 +39,7 @@ typedef unsigned long elf_fpregset_t; ...@@ -39,7 +39,7 @@ typedef unsigned long elf_fpregset_t;
A value of 0 tells we have no such handler. */ A value of 0 tells we have no such handler. */
/* Explicitly set registers to 0 to increase determinism. */ /* 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)->r13 = 0; (_r)->r12 = 0; (_r)->r11 = 0; (_r)->r10 = 0; \
(_r)->r9 = 0; (_r)->r8 = 0; (_r)->r7 = 0; (_r)->r6 = 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; \ (_r)->r5 = 0; (_r)->r4 = 0; (_r)->r3 = 0; (_r)->r2 = 0; \
......
...@@ -43,7 +43,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t; ...@@ -43,7 +43,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
We might as well make sure everything else is cleared too (except for %esp), We might as well make sure everything else is cleared too (except for %esp),
just to make things more deterministic. 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->ebx = 0; _r->ecx = 0; _r->edx = 0; \
_r->esi = 0; _r->edi = 0; _r->ebp = 0; \ _r->esi = 0; _r->edi = 0; _r->ebp = 0; \
_r->eax = 0; \ _r->eax = 0; \
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
* talk to him... * talk to him...
*/ */
extern void ia64_init_addr_space (void); 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. */ /* ELF register definitions. This is needed for core dump support. */
......
...@@ -306,7 +306,7 @@ struct old_linux32_dirent { ...@@ -306,7 +306,7 @@ struct old_linux32_dirent {
#define ELF_ET_DYN_BASE (IA32_PAGE_OFFSET/3 + 0x1000000) #define ELF_ET_DYN_BASE (IA32_PAGE_OFFSET/3 + 0x1000000)
void ia64_elf32_init(struct pt_regs *regs); 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 #define elf_addr_t u32
......
...@@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t; ...@@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
/* For SVR4/m68k the function pointer to be registered with `atexit' is /* 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 passed in %a1. Although my copy of the ABI has no such statement, it
is actually used on ASV. */ 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 #define USE_ELF_CORE_DUMP
#ifndef CONFIG_SUN3 #ifndef CONFIG_SUN3
......
...@@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t; ...@@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
/* For SVR4/m68k the function pointer to be registered with `atexit' is /* 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 passed in %a1. Although my copy of the ABI has no such statement, it
is actually used on ASV. */ 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 #define USE_ELF_CORE_DUMP
#ifndef CONFIG_SUN3 #ifndef CONFIG_SUN3
......
...@@ -73,7 +73,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; ...@@ -73,7 +73,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
* See comments in asm-alpha/elf.h, this is the same thing * See comments in asm-alpha/elf.h, this is the same thing
* on the MIPS. * 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[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[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0; \
_r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \ _r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \
......
...@@ -76,7 +76,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; ...@@ -76,7 +76,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
* See comments in asm-alpha/elf.h, this is the same thing * See comments in asm-alpha/elf.h, this is the same thing
* on the MIPS. * 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[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[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0; \
_r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \ _r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \
......
...@@ -121,7 +121,7 @@ struct pt_regs; /* forward declaration... */ ...@@ -121,7 +121,7 @@ struct pt_regs; /* forward declaration... */
So that we can use the same startup file with static executables, 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 we start programs with a value of 0 to indicate that there is no
such function. */ 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 USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096 #define ELF_EXEC_PAGESIZE 4096
......
...@@ -84,9 +84,10 @@ ppc64_elf_core_copy_regs(elf_gregset_t dstRegs, struct pt_regs* srcRegs) ...@@ -84,9 +84,10 @@ ppc64_elf_core_copy_regs(elf_gregset_t dstRegs, struct pt_regs* srcRegs)
#define ELF_PLATFORM (NULL) #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)); \ memset(_r->gpr, 0, sizeof(_r->gpr)); \
_r->ctr = _r->link = _r->xer = _r->ccr = 0; \ _r->ctr = _r->link = _r->xer = _r->ccr = 0; \
_r->gpr[2] = load_addr; \
} while (0) } while (0)
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -36,7 +36,7 @@ typedef s390_regs elf_gregset_t; ...@@ -36,7 +36,7 @@ typedef s390_regs elf_gregset_t;
/* For SVR4/S390 the function pointer to be registered with `atexit` is /* For SVR4/S390 the function pointer to be registered with `atexit` is
passed in R14. */ passed in R14. */
#define ELF_PLAT_INIT(_r) \ #define ELF_PLAT_INIT(_r, load_addr) \
_r->gprs[14] = 0 _r->gprs[14] = 0
#define USE_ELF_CORE_DUMP #define USE_ELF_CORE_DUMP
......
...@@ -36,7 +36,7 @@ typedef s390_regs elf_gregset_t; ...@@ -36,7 +36,7 @@ typedef s390_regs elf_gregset_t;
/* For SVR4/S390 the function pointer to be registered with `atexit` is /* For SVR4/S390 the function pointer to be registered with `atexit` is
passed in R14. */ passed in R14. */
#define ELF_PLAT_INIT(_r) \ #define ELF_PLAT_INIT(_r, load_addr) \
do { \ do { \
_r->gprs[14] = 0; \ _r->gprs[14] = 0; \
clear_thread_flag(TIF_31BIT); \ clear_thread_flag(TIF_31BIT); \
......
...@@ -61,7 +61,7 @@ typedef struct user_fpu_struct elf_fpregset_t; ...@@ -61,7 +61,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define ELF_PLATFORM (NULL) #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; \ 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[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; \ _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \
......
...@@ -23,7 +23,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; ...@@ -23,7 +23,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
#define ELF_DATA ELFDATA2LSB #define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_386 #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_EBX(regs) = 0; \
PT_REGS_ECX(regs) = 0; \ PT_REGS_ECX(regs) = 0; \
PT_REGS_EDX(regs) = 0; \ PT_REGS_EDX(regs) = 0; \
......
...@@ -81,7 +81,7 @@ typedef struct user_fpu_struct elf_fpregset_t; ...@@ -81,7 +81,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define ELF_PLATFORM (NULL) #define ELF_PLATFORM (NULL)
#define ELF_PLAT_INIT(_r) \ #define ELF_PLAT_INIT(_r, load_addr) \
do { \ do { \
_r->gpr[0] = _r->gpr[1] = _r->gpr[2] = _r->gpr[3] = \ _r->gpr[0] = _r->gpr[1] = _r->gpr[2] = _r->gpr[3] = \
_r->gpr[4] = _r->gpr[5] = _r->gpr[6] = _r->gpr[7] = \ _r->gpr[4] = _r->gpr[5] = _r->gpr[6] = _r->gpr[7] = \
......
...@@ -39,7 +39,7 @@ typedef struct user_i387_struct elf_fpregset_t; ...@@ -39,7 +39,7 @@ typedef struct user_i387_struct elf_fpregset_t;
We might as well make sure everything else is cleared too (except for %esp), We might as well make sure everything else is cleared too (except for %esp),
just to make things more deterministic. 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; \ struct task_struct *cur = current; \
(_r)->rbx = 0; (_r)->rcx = 0; (_r)->rdx = 0; \ (_r)->rbx = 0; (_r)->rcx = 0; (_r)->rdx = 0; \
(_r)->rsi = 0; (_r)->rdi = 0; (_r)->rbp = 0; \ (_r)->rsi = 0; (_r)->rdi = 0; (_r)->rbp = 0; \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment