The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/arm/elf_machdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright 1996-1998 John D. Polstra.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/param.h>
   32 #include <sys/kernel.h>
   33 #include <sys/systm.h>
   34 #include <sys/exec.h>
   35 #include <sys/imgact.h>
   36 #include <sys/linker.h>
   37 #include <sys/sysent.h>
   38 #include <sys/imgact_elf.h>
   39 #include <sys/proc.h>
   40 #include <sys/syscall.h>
   41 #include <sys/signalvar.h>
   42 #include <sys/vnode.h>
   43 
   44 #include <vm/vm.h>
   45 #include <vm/pmap.h>
   46 #include <vm/vm_param.h>
   47 
   48 #include <machine/elf.h>
   49 #include <machine/md_var.h>
   50 #include <machine/stack.h>
   51 #ifdef VFP
   52 #include <machine/vfp.h>
   53 #endif
   54 
   55 #include "opt_ddb.h"            /* for OPT_DDB */
   56 #include "opt_global.h"         /* for OPT_KDTRACE_HOOKS */
   57 #include "opt_stack.h"          /* for OPT_STACK */
   58 
   59 static boolean_t elf32_arm_abi_supported(struct image_params *, int32_t *,
   60     uint32_t *);
   61 
   62 u_long elf_hwcap;
   63 u_long elf_hwcap2;
   64 
   65 struct sysentvec elf32_freebsd_sysvec = {
   66         .sv_size        = SYS_MAXSYSCALL,
   67         .sv_table       = sysent,
   68         .sv_transtrap   = NULL,
   69         .sv_fixup       = __elfN(freebsd_fixup),
   70         .sv_sendsig     = sendsig,
   71         .sv_sigcode     = sigcode,
   72         .sv_szsigcode   = &szsigcode,
   73         .sv_name        = "FreeBSD ELF32",
   74         .sv_coredump    = __elfN(coredump),
   75         .sv_imgact_try  = NULL,
   76         .sv_minsigstksz = MINSIGSTKSZ,
   77         .sv_minuser     = VM_MIN_ADDRESS,
   78         .sv_maxuser     = VM_MAXUSER_ADDRESS,
   79         .sv_usrstack    = USRSTACK,
   80         .sv_psstrings   = PS_STRINGS,
   81         .sv_stackprot   = VM_PROT_ALL,
   82         .sv_copyout_auxargs = __elfN(freebsd_copyout_auxargs),
   83         .sv_copyout_strings = exec_copyout_strings,
   84         .sv_setregs     = exec_setregs,
   85         .sv_fixlimit    = NULL,
   86         .sv_maxssiz     = NULL,
   87         .sv_flags       =
   88                           SV_ASLR | SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER |
   89                           SV_ABI_FREEBSD | SV_ILP32,
   90         .sv_set_syscall_retval = cpu_set_syscall_retval,
   91         .sv_fetch_syscall_args = cpu_fetch_syscall_args,
   92         .sv_syscallnames = syscallnames,
   93         .sv_shared_page_base = SHAREDPAGE,
   94         .sv_shared_page_len = PAGE_SIZE,
   95         .sv_schedtail   = NULL,
   96         .sv_thread_detach = NULL,
   97         .sv_trap        = NULL,
   98         .sv_hwcap       = &elf_hwcap,
   99         .sv_hwcap2      = &elf_hwcap2,
  100 };
  101 INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
  102 
  103 static Elf32_Brandinfo freebsd_brand_info = {
  104         .brand          = ELFOSABI_FREEBSD,
  105         .machine        = EM_ARM,
  106         .compat_3_brand = "FreeBSD",
  107         .emul_path      = NULL,
  108         .interp_path    = "/libexec/ld-elf.so.1",
  109         .sysvec         = &elf32_freebsd_sysvec,
  110         .interp_newpath = NULL,
  111         .brand_note     = &elf32_freebsd_brandnote,
  112         .flags          = BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
  113         .header_supported= elf32_arm_abi_supported,
  114 };
  115 
  116 SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
  117         (sysinit_cfunc_t) elf32_insert_brand_entry,
  118         &freebsd_brand_info);
  119 
  120 static boolean_t
  121 elf32_arm_abi_supported(struct image_params *imgp, int32_t *osrel __unused,
  122     uint32_t *fctl0 __unused)
  123 {
  124         const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header;
  125 
  126         /*
  127          * When configured for EABI, FreeBSD supports EABI vesions 4 and 5.
  128          */
  129         if (EF_ARM_EABI_VERSION(hdr->e_flags) < EF_ARM_EABI_FREEBSD_MIN) {
  130                 if (bootverbose)
  131                         uprintf("Attempting to execute non EABI binary (rev %d) image %s",
  132                             EF_ARM_EABI_VERSION(hdr->e_flags), imgp->args->fname);
  133                 return (FALSE);
  134         }
  135         return (TRUE);
  136 }
  137 
  138 void
  139 elf32_dump_thread(struct thread *td, void *dst, size_t *off)
  140 {
  141 #ifdef VFP
  142         mcontext_vfp_t vfp;
  143 
  144         if (dst != NULL) {
  145                 get_vfpcontext(td, &vfp);
  146                 *off = elf32_populate_note(NT_ARM_VFP, &vfp, dst, sizeof(vfp),
  147                     NULL);
  148         } else
  149                 *off = elf32_populate_note(NT_ARM_VFP, NULL, NULL, sizeof(vfp),
  150                     NULL);
  151 #endif
  152 }
  153 
  154 bool
  155 elf_is_ifunc_reloc(Elf_Size r_info __unused)
  156 {
  157 
  158         return (false);
  159 }
  160 
  161 /*
  162  * It is possible for the compiler to emit relocations for unaligned data.
  163  * We handle this situation with these inlines.
  164  */
  165 #define RELOC_ALIGNED_P(x) \
  166         (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
  167 
  168 static __inline Elf_Addr
  169 load_ptr(Elf_Addr *where)
  170 {
  171         Elf_Addr res;
  172 
  173         if (RELOC_ALIGNED_P(where))
  174                 return *where;
  175         memcpy(&res, where, sizeof(res));
  176         return (res);
  177 }
  178 
  179 static __inline void
  180 store_ptr(Elf_Addr *where, Elf_Addr val)
  181 {
  182         if (RELOC_ALIGNED_P(where))
  183                 *where = val;
  184         else
  185                 memcpy(where, &val, sizeof(val));
  186 }
  187 #undef RELOC_ALIGNED_P
  188 
  189 /* Process one elf relocation with addend. */
  190 static int
  191 elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
  192     int type, int local, elf_lookup_fn lookup)
  193 {
  194         Elf_Addr *where;
  195         Elf_Addr addr;
  196         Elf_Addr addend;
  197         Elf_Word rtype, symidx;
  198         const Elf_Rel *rel;
  199         const Elf_Rela *rela;
  200         int error;
  201 
  202         switch (type) {
  203         case ELF_RELOC_REL:
  204                 rel = (const Elf_Rel *)data;
  205                 where = (Elf_Addr *) (relocbase + rel->r_offset);
  206                 addend = load_ptr(where);
  207                 rtype = ELF_R_TYPE(rel->r_info);
  208                 symidx = ELF_R_SYM(rel->r_info);
  209                 break;
  210         case ELF_RELOC_RELA:
  211                 rela = (const Elf_Rela *)data;
  212                 where = (Elf_Addr *) (relocbase + rela->r_offset);
  213                 addend = rela->r_addend;
  214                 rtype = ELF_R_TYPE(rela->r_info);
  215                 symidx = ELF_R_SYM(rela->r_info);
  216                 break;
  217         default:
  218                 panic("unknown reloc type %d\n", type);
  219         }
  220 
  221         if (local) {
  222                 if (rtype == R_ARM_RELATIVE) {  /* A + B */
  223                         addr = elf_relocaddr(lf, relocbase + addend);
  224                         if (load_ptr(where) != addr)
  225                                 store_ptr(where, addr);
  226                 }
  227                 return (0);
  228         }
  229 
  230         switch (rtype) {
  231                 case R_ARM_NONE:        /* none */
  232                         break;
  233 
  234                 case R_ARM_ABS32:
  235                         error = lookup(lf, symidx, 1, &addr);
  236                         if (error != 0)
  237                                 return (-1);
  238                         store_ptr(where, addr + load_ptr(where));
  239                         break;
  240 
  241                 case R_ARM_COPY:        /* none */
  242                         /*
  243                          * There shouldn't be copy relocations in kernel
  244                          * objects.
  245                          */
  246                         printf("kldload: unexpected R_COPY relocation, "
  247                             "symbol index %d\n", symidx);
  248                         return (-1);
  249                         break;
  250 
  251                 case R_ARM_JUMP_SLOT:
  252                         error = lookup(lf, symidx, 1, &addr);
  253                         if (error == 0) {
  254                                 store_ptr(where, addr);
  255                                 return (0);
  256                         }
  257                         return (-1);
  258                 case R_ARM_RELATIVE:
  259                         break;
  260 
  261                 default:
  262                         printf("kldload: unexpected relocation type %d, "
  263                             "symbol index %d\n", rtype, symidx);
  264                         return (-1);
  265         }
  266         return(0);
  267 }
  268 
  269 int
  270 elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
  271     elf_lookup_fn lookup)
  272 {
  273 
  274         return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
  275 }
  276 
  277 int
  278 elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
  279     int type, elf_lookup_fn lookup)
  280 {
  281 
  282         return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
  283 }
  284 
  285 int
  286 elf_cpu_load_file(linker_file_t lf)
  287 {
  288 
  289         /*
  290          * The pmap code does not do an icache sync upon establishing executable
  291          * mappings in the kernel pmap.  It's an optimization based on the fact
  292          * that kernel memory allocations always have EXECUTABLE protection even
  293          * when the memory isn't going to hold executable code.  The only time
  294          * kernel memory holding instructions does need a sync is after loading
  295          * a kernel module, and that's when this function gets called.
  296          *
  297          * This syncs data and instruction caches after loading a module.  We
  298          * don't worry about the kernel itself (lf->id is 1) as locore.S did
  299          * that on entry.  Even if data cache maintenance was done by IO code,
  300          * the relocation fixup process creates dirty cache entries that we must
  301          * write back before doing icache sync. The instruction cache sync also
  302          * invalidates the branch predictor cache on platforms that have one.
  303          */
  304         if (lf->id == 1)
  305                 return (0);
  306         dcache_wb_pou((vm_offset_t)lf->address, (vm_size_t)lf->size);
  307         icache_inv_all();
  308 
  309 #if defined(DDB) || defined(KDTRACE_HOOKS) || defined(STACK)
  310         /*
  311          * Inform the stack(9) code of the new module, so it can acquire its
  312          * per-module unwind data.
  313          */
  314         unwind_module_loaded(lf);
  315 #endif
  316 
  317         return (0);
  318 }
  319 
  320 int
  321 elf_cpu_parse_dynamic(caddr_t loadbase __unused, Elf_Dyn *dynamic __unused)
  322 {
  323 
  324         return (0);
  325 }
  326 
  327 int
  328 elf_cpu_unload_file(linker_file_t lf)
  329 {
  330 
  331 #if defined(DDB) || defined(KDTRACE_HOOKS) || defined(STACK)
  332         /* Inform the stack(9) code that this module is gone. */
  333         unwind_module_unloaded(lf);
  334 #endif
  335         return (0);
  336 }

Cache object: 9a4f28c31b48a091790132db34ad1518


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.