diff options
Diffstat (limited to 'arch/arm/kernel/elf.c')
| -rw-r--r-- | arch/arm/kernel/elf.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c new file mode 100644 index 000000000000..513f332f040d --- /dev/null +++ b/arch/arm/kernel/elf.c | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | #include <linux/module.h> | ||
| 2 | #include <linux/sched.h> | ||
| 3 | #include <linux/personality.h> | ||
| 4 | #include <linux/binfmts.h> | ||
| 5 | #include <linux/elf.h> | ||
| 6 | |||
| 7 | int elf_check_arch(const struct elf32_hdr *x) | ||
| 8 | { | ||
| 9 | unsigned int eflags; | ||
| 10 | |||
| 11 | /* Make sure it's an ARM executable */ | ||
| 12 | if (x->e_machine != EM_ARM) | ||
| 13 | return 0; | ||
| 14 | |||
| 15 | /* Make sure the entry address is reasonable */ | ||
| 16 | if (x->e_entry & 1) { | ||
| 17 | if (!(elf_hwcap & HWCAP_THUMB)) | ||
| 18 | return 0; | ||
| 19 | } else if (x->e_entry & 3) | ||
| 20 | return 0; | ||
| 21 | |||
| 22 | eflags = x->e_flags; | ||
| 23 | if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) { | ||
| 24 | /* APCS26 is only allowed if the CPU supports it */ | ||
| 25 | if ((eflags & EF_ARM_APCS_26) && !(elf_hwcap & HWCAP_26BIT)) | ||
| 26 | return 0; | ||
| 27 | |||
| 28 | /* VFP requires the supporting code */ | ||
| 29 | if ((eflags & EF_ARM_VFP_FLOAT) && !(elf_hwcap & HWCAP_VFP)) | ||
| 30 | return 0; | ||
| 31 | } | ||
| 32 | return 1; | ||
| 33 | } | ||
| 34 | EXPORT_SYMBOL(elf_check_arch); | ||
| 35 | |||
| 36 | void elf_set_personality(const struct elf32_hdr *x) | ||
| 37 | { | ||
| 38 | unsigned int eflags = x->e_flags; | ||
| 39 | unsigned int personality = PER_LINUX_32BIT; | ||
| 40 | |||
| 41 | /* | ||
| 42 | * APCS-26 is only valid for OABI executables | ||
| 43 | */ | ||
| 44 | if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) { | ||
| 45 | if (eflags & EF_ARM_APCS_26) | ||
| 46 | personality = PER_LINUX; | ||
| 47 | } | ||
| 48 | |||
| 49 | set_personality(personality); | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Since the FPA coprocessor uses CP1 and CP2, and iWMMXt uses CP0 | ||
| 53 | * and CP1, we only enable access to the iWMMXt coprocessor if the | ||
| 54 | * binary is EABI or softfloat (and thus, guaranteed not to use | ||
| 55 | * FPA instructions.) | ||
| 56 | */ | ||
| 57 | if (elf_hwcap & HWCAP_IWMMXT && | ||
| 58 | eflags & (EF_ARM_EABI_MASK | EF_ARM_SOFT_FLOAT)) { | ||
| 59 | set_thread_flag(TIF_USING_IWMMXT); | ||
| 60 | } else { | ||
| 61 | clear_thread_flag(TIF_USING_IWMMXT); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | EXPORT_SYMBOL(elf_set_personality); | ||
| 65 | |||
| 66 | /* | ||
| 67 | * Set READ_IMPLIES_EXEC if: | ||
| 68 | * - the binary requires an executable stack | ||
| 69 | * - we're running on a CPU which doesn't support NX. | ||
| 70 | */ | ||
| 71 | int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack) | ||
| 72 | { | ||
| 73 | if (executable_stack != EXSTACK_ENABLE_X) | ||
| 74 | return 1; | ||
| 75 | if (cpu_architecture() <= CPU_ARCH_ARMv6) | ||
| 76 | return 1; | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | EXPORT_SYMBOL(arm_elf_read_implies_exec); | ||
