# HG changeset patch # Parent f8524f7e5b59a6cfd43b780f5a8ee8e6d0346e3d Add support for launching soft-float binaries with ld-elf-soft.so instead of ld-elf.so ala ld-elf32.so. Differential revision: https://reviews.freebsd.org/D2418 diff -r f8524f7e5b59 sys/arm/arm/elf_machdep.c --- a/sys/arm/arm/elf_machdep.c +++ b/sys/arm/arm/elf_machdep.c @@ -47,6 +47,9 @@ #include static boolean_t elf32_arm_abi_supported(struct image_params *); +#ifdef COMPAT_ARM_SOFT_FLOAT +static boolean_t elf32_arm_soft_supported(struct image_params *); +#endif struct sysentvec elf32_freebsd_sysvec = { .sv_size = SYS_MAXSYSCALL, @@ -100,6 +103,26 @@ SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIR (sysinit_cfunc_t) elf32_insert_brand_entry, &freebsd_brand_info); +#ifdef COMPAT_ARM_SOFT_FLOAT +static Elf32_Brandinfo freebsd_brand_info_soft = { + .brand = ELFOSABI_FREEBSD, + .machine = EM_ARM, + .compat_3_brand = "FreeBSD", + .emul_path = NULL, + .interp_path = "/libexec/ld-elf.so.1", + .sysvec = &elf32_freebsd_sysvec, + .interp_newpath = "/libexec/ld-elf-soft.so.1", + .brand_note = &elf32_freebsd_brandnote, + .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE, + .header_supported= elf32_arm_soft_supported, +}; + +SYSINIT(elf32soft, SI_SUB_EXEC, SI_ORDER_FIRST, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &freebsd_brand_info_soft); +#endif + + static boolean_t elf32_arm_abi_supported(struct image_params *imgp) { @@ -107,16 +130,50 @@ elf32_arm_abi_supported(struct image_par /* * When configured for EABI, FreeBSD supports EABI vesions 4 and 5. + * The most common is version 0, OABI, which is a guaranteed core dump + * if we execute it. Versions 1, 2, and 3 were never a FreeBSD thing, + * so reject them. */ if (EF_ARM_EABI_VERSION(hdr->e_flags) < EF_ARM_EABI_FREEBSD_MIN) { if (bootverbose) - uprintf("Attempting to execute non EABI binary (rev %d) image %s", - EF_ARM_EABI_VERSION(hdr->e_flags), imgp->args->fname); + uprintf("Attempting to execute OABI binary image %s", + imgp->args->fname); return (FALSE); } + +#ifdef COMPAT_ARM_SOFT_FLOAT + /* + * When we're differentiating between hard and soft float, only execute + * hard float excutables via this vector. We have a separate vector for + * softfloat so it can use different libraries that are mutually + * compatible. + */ + if ((hdr->e_flags & EF_ARM_VFP_FLOAT) == 0) + return (FALSE); +#endif return (TRUE); } +#ifdef COMPAT_ARM_SOFT_FLOAT +static boolean_t +elf32_arm_soft_supported(struct image_params *imgp) +{ + const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; + + /* + * Looking specifically for EABI 4 or 5 soft float programs. + * Note: FreeBSD 10 and earlier didn't set EF_ARM_SOFT_FLOAT + * on these binaries like it should have, so interpret + * that as meaning 'soft float' too. + */ + if (EF_ARM_EABI_VERSION(hdr->e_flags) < EF_ARM_EABI_FREEBSD_MIN || + (hdr->e_flags & EF_ARM_VFP_FLOAT) != 0) + return (FALSE); + + return (TRUE); +} +#endif + void elf32_dump_thread(struct thread *td __unused, void *dst __unused, size_t *off __unused) diff -r f8524f7e5b59 sys/conf/options.arm --- a/sys/conf/options.arm +++ b/sys/conf/options.arm @@ -7,6 +7,7 @@ ARM_MANY_BOARD opt_global.h ARM_NEW_PMAP opt_global.h NKPT2PG opt_pmap.h ARM_WANT_TP_ADDRESS opt_global.h +COMPAT_ARM_SOFT_FLOAT opt_global.h COUNTS_PER_SEC opt_timer.h CPU_ARM9 opt_global.h CPU_ARM9E opt_global.h