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/kern/exec_ecoff.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 /*      $NetBSD: exec_ecoff.c,v 1.32 2019/11/20 19:37:53 pgoyette Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1994 Adam Glass
    5  * Copyright (c) 1993, 1994, 1996, 1999 Christopher G. Demetriou
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by Christopher G. Demetriou
   19  *      for the NetBSD Project.
   20  * 4. The name of the author may not be used to endorse or promote products
   21  *    derived from this software without specific prior written permission
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __KERNEL_RCSID(0, "$NetBSD: exec_ecoff.c,v 1.32 2019/11/20 19:37:53 pgoyette Exp $");
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/proc.h>
   41 #include <sys/vnode.h>
   42 #include <sys/exec.h>
   43 #include <sys/resourcevar.h>
   44 #include <sys/module.h>
   45 #include <sys/exec.h>
   46 #include <sys/exec_ecoff.h>
   47 
   48 MODULE(MODULE_CLASS_EXEC, exec_ecoff, NULL);
   49 
   50 static struct execsw exec_ecoff_execsw = {
   51         .es_hdrsz = ECOFF_HDR_SIZE,
   52         .es_makecmds = exec_ecoff_makecmds,
   53         .u = {
   54                 .ecoff_probe_func = cpu_exec_ecoff_probe,
   55         },
   56         .es_emul = &emul_netbsd,
   57         .es_prio = EXECSW_PRIO_ANY,
   58         .es_arglen = 0,
   59         .es_copyargs = copyargs,
   60         .es_setregs = cpu_exec_ecoff_setregs,
   61         .es_coredump = coredump_netbsd,
   62         .es_setup_stack = exec_setup_stack,
   63 };
   64 
   65 static int
   66 exec_ecoff_modcmd(modcmd_t cmd, void *arg)
   67 {
   68         switch (cmd) {
   69         case MODULE_CMD_INIT:
   70                 return exec_add(&exec_ecoff_execsw, 1);
   71 
   72         case MODULE_CMD_FINI:
   73                 return exec_remove(&exec_ecoff_execsw, 1);
   74 
   75         default:
   76                 return ENOTTY;
   77         }
   78 }
   79 
   80 /*
   81  * exec_ecoff_makecmds(): Check if it's an ecoff-format executable.
   82  *
   83  * Given a proc pointer and an exec package pointer, see if the referent
   84  * of the epp is in ecoff format.  Check 'standard' magic numbers for
   85  * this architecture.  If that fails, return failure.
   86  *
   87  * This function is  responsible for creating a set of vmcmds which can be
   88  * used to build the process's vm space and inserting them into the exec
   89  * package.
   90  */
   91 int
   92 exec_ecoff_makecmds(struct lwp *l, struct exec_package *epp)
   93 {
   94         int error;
   95         struct ecoff_exechdr *execp = epp->ep_hdr;
   96 
   97         if (epp->ep_hdrvalid < ECOFF_HDR_SIZE)
   98                 return ENOEXEC;
   99 
  100         if (ECOFF_BADMAG(execp))
  101                 return ENOEXEC;
  102 
  103         error = (*epp->ep_esch->u.ecoff_probe_func)(l, epp);
  104 
  105         /*
  106          * if there was an error or there are already vmcmds set up,
  107          * we return.  (the latter can happen if cpu_exec_ecoff_hook()
  108          * recursively invokes check_exec() to handle loading of a
  109          * dynamically linked binary's shared loader.
  110          */
  111         if (error || epp->ep_vmcmds.evs_cnt)
  112                 return (error);
  113 
  114         /*
  115          * prepare the exec package to map the executable.
  116          */
  117         switch (execp->a.magic) {
  118         case ECOFF_OMAGIC:
  119                 error = exec_ecoff_prep_omagic(l, epp, epp->ep_hdr,
  120                    epp->ep_vp);
  121                 break;
  122         case ECOFF_NMAGIC:
  123                 error = exec_ecoff_prep_nmagic(l, epp, epp->ep_hdr,
  124                    epp->ep_vp);
  125                 break;
  126         case ECOFF_ZMAGIC:
  127                 error = exec_ecoff_prep_zmagic(l, epp, epp->ep_hdr,
  128                    epp->ep_vp);
  129                 break;
  130         default:
  131                 return ENOEXEC;
  132         }
  133 
  134         /* set up the stack */
  135         if (!error)
  136                 error = (*epp->ep_esch->es_setup_stack)(l, epp);
  137 
  138         if (error)
  139                 kill_vmcmds(&epp->ep_vmcmds);
  140 
  141         return error;
  142 }
  143 
  144 /*
  145  * exec_ecoff_prep_omagic(): Prepare a ECOFF OMAGIC binary's exec package
  146  */
  147 int
  148 exec_ecoff_prep_omagic(struct lwp *l, struct exec_package *epp,
  149     struct ecoff_exechdr *execp, struct vnode *vp)
  150 {
  151         struct ecoff_aouthdr *eap = &execp->a;
  152 
  153         epp->ep_taddr = ECOFF_SEGMENT_ALIGN(execp, eap->text_start);
  154         epp->ep_tsize = eap->tsize;
  155         epp->ep_daddr = ECOFF_SEGMENT_ALIGN(execp, eap->data_start);
  156         epp->ep_dsize = eap->dsize + eap->bsize;
  157         epp->ep_entry = eap->entry;
  158 
  159         /* set up command for text and data segments */
  160         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
  161             eap->tsize + eap->dsize, epp->ep_taddr, vp,
  162             ECOFF_TXTOFF(execp),
  163             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  164 
  165         /* set up command for bss segment */
  166         if (eap->bsize > 0)
  167                 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, eap->bsize,
  168                     ECOFF_SEGMENT_ALIGN(execp, eap->bss_start), NULLVP, 0,
  169                     VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  170 
  171         return 0;
  172 }
  173 
  174 /*
  175  * exec_ecoff_prep_nmagic(): Prepare a 'native' NMAGIC ECOFF binary's exec
  176  *                           package.
  177  */
  178 int
  179 exec_ecoff_prep_nmagic(struct lwp *l, struct exec_package *epp,
  180     struct ecoff_exechdr *execp, struct vnode *vp)
  181 {
  182         struct ecoff_aouthdr *eap = &execp->a;
  183 
  184         epp->ep_taddr = ECOFF_SEGMENT_ALIGN(execp, eap->text_start);
  185         epp->ep_tsize = eap->tsize;
  186         epp->ep_daddr = ECOFF_ROUND(eap->data_start, ECOFF_LDPGSZ);
  187         epp->ep_dsize = eap->dsize + eap->bsize;
  188         epp->ep_entry = eap->entry;
  189 
  190         /* set up command for text segment */
  191         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, epp->ep_tsize,
  192             epp->ep_taddr, vp, ECOFF_TXTOFF(execp),
  193             VM_PROT_READ|VM_PROT_EXECUTE);
  194 
  195         /* set up command for data segment */
  196         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, epp->ep_dsize,
  197             epp->ep_daddr, vp, ECOFF_DATOFF(execp),
  198             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  199 
  200         /* set up command for bss segment */
  201         if (eap->bsize > 0)
  202                 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, eap->bsize,
  203                     ECOFF_SEGMENT_ALIGN(execp, eap->bss_start), NULLVP, 0,
  204                     VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  205 
  206         return 0;
  207 }
  208 
  209 /*
  210  * exec_ecoff_prep_zmagic(): Prepare a ECOFF ZMAGIC binary's exec package
  211  *
  212  * First, set the various offsets/lengths in the exec package.
  213  *
  214  * Then, mark the text image busy (so it can be demand paged) or error
  215  * out if this is not possible.  Finally, set up vmcmds for the
  216  * text, data, bss, and stack segments.
  217  */
  218 int
  219 exec_ecoff_prep_zmagic(struct lwp *l, struct exec_package *epp,
  220     struct ecoff_exechdr *execp, struct vnode *vp)
  221 {
  222         struct ecoff_aouthdr *eap = &execp->a;
  223         int error;
  224 
  225         epp->ep_taddr = ECOFF_SEGMENT_ALIGN(execp, eap->text_start);
  226         epp->ep_tsize = eap->tsize;
  227         epp->ep_daddr = ECOFF_SEGMENT_ALIGN(execp, eap->data_start);
  228         epp->ep_dsize = eap->dsize + eap->bsize;
  229         epp->ep_entry = eap->entry;
  230 
  231         error = vn_marktext(vp);
  232         if (error)
  233                 return (error);
  234 
  235         /* set up command for text segment */
  236         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, eap->tsize,
  237             epp->ep_taddr, vp, ECOFF_TXTOFF(execp),
  238             VM_PROT_READ|VM_PROT_EXECUTE);
  239 
  240         /* set up command for data segment */
  241         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, eap->dsize,
  242             epp->ep_daddr, vp, ECOFF_DATOFF(execp),
  243             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  244 
  245         /* set up command for bss segment */
  246         if (eap->bsize > 0)
  247                 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, eap->bsize,
  248                     ECOFF_SEGMENT_ALIGN(execp, eap->bss_start), NULLVP, 0,
  249                     VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  250 
  251         return 0;
  252 }

Cache object: 6d3cd47aea44bef610cde95b2c542c10


[ 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.