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 @@
/* 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); \
......
......@@ -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);
......
......@@ -452,6 +452,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
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_binprm * bprm, struct pt_regs * regs)
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_binprm * bprm, struct pt_regs * regs)
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_binprm * bprm, struct pt_regs * regs)
/*
* 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);
......
......@@ -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
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. */
......
......@@ -48,7 +48,7 @@ typedef struct { void *null; } elf_fpregset_t;
/* 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. */
......
......@@ -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; \
......
......@@ -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),
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; \
......
......@@ -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. */
......
......@@ -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
......
......@@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
/* 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
......
......@@ -31,7 +31,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
/* 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
......
......@@ -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
* 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; \
......
......@@ -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
* 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; \
......
......@@ -121,7 +121,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
......
......@@ -84,9 +84,10 @@ ppc64_elf_core_copy_regs(elf_gregset_t dstRegs, struct pt_regs* srcRegs)
#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__
......
......@@ -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
......
......@@ -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); \
......
......@@ -61,7 +61,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
#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; \
......
......@@ -23,7 +23,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
#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; \
......
......@@ -81,7 +81,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
#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] = \
......
......@@ -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),
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; \
......
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