diff options
Diffstat (limited to 'arch/mips/kernel/elf.c')
-rw-r--r-- | arch/mips/kernel/elf.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c index 4a4d9e067c89..858605639965 100644 --- a/arch/mips/kernel/elf.c +++ b/arch/mips/kernel/elf.c @@ -68,15 +68,23 @@ static struct mode_req none_req = { true, true, false, true, true }; int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf, bool is_interp, struct arch_elf_state *state) { - struct elf32_hdr *ehdr32 = _ehdr; + union { + struct elf32_hdr e32; + struct elf64_hdr e64; + } *ehdr = _ehdr; struct elf32_phdr *phdr32 = _phdr; struct elf64_phdr *phdr64 = _phdr; struct mips_elf_abiflags_v0 abiflags; + bool elf32; + u32 flags; int ret; + elf32 = ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32; + flags = elf32 ? ehdr->e32.e_flags : ehdr->e64.e_flags; + /* Lets see if this is an O32 ELF */ - if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) { - if (ehdr32->e_flags & EF_MIPS_FP64) { + if (elf32) { + if (flags & EF_MIPS_FP64) { /* * Set MIPS_ABI_FP_OLD_64 for EF_MIPS_FP64. We will override it * later if needed @@ -123,10 +131,17 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf, int arch_check_elf(void *_ehdr, bool has_interpreter, struct arch_elf_state *state) { - struct elf32_hdr *ehdr = _ehdr; + union { + struct elf32_hdr e32; + struct elf64_hdr e64; + } *ehdr = _ehdr; struct mode_req prog_req, interp_req; int fp_abi, interp_fp_abi, abi0, abi1, max_abi; - bool is_mips64; + bool elf32; + u32 flags; + + elf32 = ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32; + flags = elf32 ? ehdr->e32.e_flags : ehdr->e64.e_flags; if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) return 0; @@ -142,21 +157,18 @@ int arch_check_elf(void *_ehdr, bool has_interpreter, abi0 = abi1 = fp_abi; } - is_mips64 = (ehdr->e_ident[EI_CLASS] == ELFCLASS64) || - (ehdr->e_flags & EF_MIPS_ABI2); + if (elf32 && !(flags & EF_MIPS_ABI2)) { + /* Default to a mode capable of running code expecting FR=0 */ + state->overall_fp_mode = cpu_has_mips_r6 ? FP_FRE : FP_FR0; - if (is_mips64) { + /* Allow all ABIs we know about */ + max_abi = MIPS_ABI_FP_64A; + } else { /* MIPS64 code always uses FR=1, thus the default is easy */ state->overall_fp_mode = FP_FR1; /* Disallow access to the various FPXX & FP64 ABIs */ max_abi = MIPS_ABI_FP_SOFT; - } else { - /* Default to a mode capable of running code expecting FR=0 */ - state->overall_fp_mode = cpu_has_mips_r6 ? FP_FRE : FP_FR0; - - /* Allow all ABIs we know about */ - max_abi = MIPS_ABI_FP_64A; } if ((abi0 > max_abi && abi0 != MIPS_ABI_FP_UNKNOWN) || |