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/compat/linux/common/linux_exec_aout.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: linux_exec_aout.c,v 1.55 2003/08/08 18:57:06 christos Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Christos Zoulas, Frank van der Linden and Eric Haszlakiewicz.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * based on exec_aout.c, sunos_exec.c and svr4_exec.c
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __KERNEL_RCSID(0, "$NetBSD: linux_exec_aout.c,v 1.55 2003/08/08 18:57:06 christos Exp $");
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/kernel.h>
   49 #include <sys/proc.h>
   50 #include <sys/malloc.h>
   51 #include <sys/namei.h>
   52 #include <sys/vnode.h>
   53 #include <sys/mount.h>
   54 #include <sys/exec.h>
   55 #include <sys/exec_elf.h>
   56 
   57 #include <sys/mman.h>
   58 #include <sys/sa.h>
   59 #include <sys/syscallargs.h>
   60 
   61 #include <machine/cpu.h>
   62 #include <machine/reg.h>
   63 
   64 #include <compat/linux/common/linux_types.h>
   65 #include <compat/linux/common/linux_signal.h>
   66 #include <compat/linux/common/linux_util.h>
   67 #include <compat/linux/common/linux_exec.h>
   68 #include <compat/linux/common/linux_machdep.h>
   69 
   70 #include <compat/linux/linux_syscallargs.h>
   71 #include <compat/linux/linux_syscall.h>
   72 
   73 int linux_aout_copyargs __P((struct proc *, struct exec_package *,
   74     struct ps_strings *, char **, void *));
   75 
   76 static int exec_linux_aout_prep_zmagic __P((struct proc *,
   77     struct exec_package *));
   78 static int exec_linux_aout_prep_nmagic __P((struct proc *,
   79     struct exec_package *));
   80 static int exec_linux_aout_prep_omagic __P((struct proc *,
   81     struct exec_package *));
   82 static int exec_linux_aout_prep_qmagic __P((struct proc *,
   83     struct exec_package *));
   84 
   85 int
   86 linux_aout_copyargs(p, pack, arginfo, stackp, argp)
   87         struct proc *p;
   88         struct exec_package *pack;
   89         struct ps_strings *arginfo;
   90         char **stackp;
   91         void *argp;
   92 {
   93         char **cpp = (char **)*stackp;
   94         char **stk = (char **)*stackp;
   95         char *dp, *sp;
   96         size_t len;
   97         void *nullp = NULL;
   98         int argc = arginfo->ps_nargvstr;
   99         int envc = arginfo->ps_nenvstr;
  100         int error;
  101 
  102         if ((error = copyout(&argc, cpp++, sizeof(argc))) != 0)
  103                 return error;
  104 
  105         /* leave room for envp and argv */
  106         cpp += 2;
  107         if ((error = copyout(&cpp, &stk[1], sizeof (cpp))) != 0)
  108                 return error;
  109 
  110         dp = (char *) (cpp + argc + envc + 2);
  111         sp = argp;
  112 
  113         /* XXX don't copy them out, remap them! */
  114         arginfo->ps_argvstr = cpp; /* remember location of argv for later */
  115 
  116         for (; --argc >= 0; sp += len, dp += len)
  117                 if ((error = copyout(&dp, cpp++, sizeof(dp))) != 0 ||
  118                     (error = copyoutstr(sp, dp, ARG_MAX, &len)) != 0)
  119                         return error;
  120 
  121         if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0)
  122                 return error;
  123 
  124         if ((error = copyout(&cpp, &stk[2], sizeof (cpp))) != 0)
  125                 return error;
  126 
  127         arginfo->ps_envstr = cpp; /* remember location of envp for later */
  128 
  129         for (; --envc >= 0; sp += len, dp += len)
  130                 if ((error = copyout(&dp, cpp++, sizeof(dp))) != 0 ||
  131                     (error = copyoutstr(sp, dp, ARG_MAX, &len)) != 0)
  132                         return error;
  133 
  134         if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0)
  135                 return error;
  136 
  137         *stackp = (char *)cpp;
  138         return 0;
  139 }
  140 
  141 int
  142 exec_linux_aout_makecmds(p, epp)
  143         struct proc *p;
  144         struct exec_package *epp;
  145 {
  146         struct exec *linux_ep = epp->ep_hdr;
  147         int machtype, magic;
  148         int error = ENOEXEC;
  149 
  150         magic = LINUX_N_MAGIC(linux_ep);
  151         machtype = LINUX_N_MACHTYPE(linux_ep);
  152 
  153 
  154         if (machtype != LINUX_MID_MACHINE)
  155                 return (ENOEXEC);
  156 
  157         switch (magic) {
  158         case QMAGIC:
  159                 error = exec_linux_aout_prep_qmagic(p, epp);
  160                 break;
  161         case ZMAGIC:
  162                 error = exec_linux_aout_prep_zmagic(p, epp);
  163                 break;
  164         case NMAGIC:
  165                 error = exec_linux_aout_prep_nmagic(p, epp);
  166                 break;
  167         case OMAGIC:
  168                 error = exec_linux_aout_prep_omagic(p, epp);
  169                 break;
  170         }
  171         return error;
  172 }
  173 
  174 /*
  175  * Since text starts at 0x400 in Linux ZMAGIC executables, and 0x400
  176  * is very likely not page aligned on most architectures, it is treated
  177  * as an NMAGIC here. XXX
  178  */
  179 
  180 static int
  181 exec_linux_aout_prep_zmagic(p, epp)
  182         struct proc *p;
  183         struct exec_package *epp;
  184 {
  185         struct exec *execp = epp->ep_hdr;
  186 
  187         epp->ep_taddr = LINUX_N_TXTADDR(*execp, ZMAGIC);
  188         epp->ep_tsize = execp->a_text;
  189         epp->ep_daddr = LINUX_N_DATADDR(*execp, ZMAGIC);
  190         epp->ep_dsize = execp->a_data + execp->a_bss;
  191         epp->ep_entry = execp->a_entry;
  192 
  193         /* set up command for text segment */
  194         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_text,
  195             epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, ZMAGIC),
  196             VM_PROT_READ|VM_PROT_EXECUTE);
  197 
  198         /* set up command for data segment */
  199         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_data,
  200             epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, ZMAGIC),
  201             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  202 
  203         /* set up command for bss segment */
  204         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
  205             epp->ep_daddr + execp->a_data, NULLVP, 0,
  206             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  207 
  208         return (*epp->ep_esch->es_setup_stack)(p, epp);
  209 }
  210 
  211 /*
  212  * exec_aout_prep_nmagic(): Prepare Linux NMAGIC package.
  213  * Not different from the normal stuff.
  214  */
  215 
  216 static int
  217 exec_linux_aout_prep_nmagic(p, epp)
  218         struct proc *p;
  219         struct exec_package *epp;
  220 {
  221         struct exec *execp = epp->ep_hdr;
  222         long bsize, baddr;
  223 
  224         epp->ep_taddr = LINUX_N_TXTADDR(*execp, NMAGIC);
  225         epp->ep_tsize = execp->a_text;
  226         epp->ep_daddr = LINUX_N_DATADDR(*execp, NMAGIC);
  227         epp->ep_dsize = execp->a_data + execp->a_bss;
  228         epp->ep_entry = execp->a_entry;
  229 
  230         /* set up command for text segment */
  231         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_text,
  232             epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, NMAGIC),
  233             VM_PROT_READ|VM_PROT_EXECUTE);
  234 
  235         /* set up command for data segment */
  236         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_data,
  237             epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, NMAGIC),
  238             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  239 
  240         /* set up command for bss segment */
  241         baddr = roundup(epp->ep_daddr + execp->a_data, PAGE_SIZE);
  242         bsize = epp->ep_daddr + epp->ep_dsize - baddr;
  243         if (bsize > 0)
  244                 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr,
  245                     NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  246 
  247         return (*epp->ep_esch->es_setup_stack)(p, epp);
  248 }
  249 
  250 /*
  251  * exec_aout_prep_omagic(): Prepare Linux OMAGIC package.
  252  * Business as usual.
  253  */
  254 
  255 static int
  256 exec_linux_aout_prep_omagic(p, epp)
  257         struct proc *p;
  258         struct exec_package *epp;
  259 {
  260         struct exec *execp = epp->ep_hdr;
  261         long dsize, bsize, baddr;
  262 
  263         epp->ep_taddr = LINUX_N_TXTADDR(*execp, OMAGIC);
  264         epp->ep_tsize = execp->a_text;
  265         epp->ep_daddr = LINUX_N_DATADDR(*execp, OMAGIC);
  266         epp->ep_dsize = execp->a_data + execp->a_bss;
  267         epp->ep_entry = execp->a_entry;
  268 
  269         /* set up command for text and data segments */
  270         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
  271             execp->a_text + execp->a_data, epp->ep_taddr, epp->ep_vp,
  272             LINUX_N_TXTOFF(*execp, OMAGIC), VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  273 
  274         /* set up command for bss segment */
  275         baddr = roundup(epp->ep_daddr + execp->a_data, PAGE_SIZE);
  276         bsize = epp->ep_daddr + epp->ep_dsize - baddr;
  277         if (bsize > 0)
  278                 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr,
  279                     NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  280 
  281         /*
  282          * Make sure (# of pages) mapped above equals (vm_tsize + vm_dsize);
  283          * obreak(2) relies on this fact. Both `vm_tsize' and `vm_dsize' are
  284          * computed (in execve(2)) by rounding *up* `ep_tsize' and `ep_dsize'
  285          * respectively to page boundaries.
  286          * Compensate `ep_dsize' for the amount of data covered by the last
  287          * text page. 
  288          */
  289         dsize = epp->ep_dsize + execp->a_text - roundup(execp->a_text,
  290                                                         PAGE_SIZE);
  291         epp->ep_dsize = (dsize > 0) ? dsize : 0;
  292         return (*epp->ep_esch->es_setup_stack)(p, epp);
  293 }
  294 
  295 static int
  296 exec_linux_aout_prep_qmagic(p, epp)
  297         struct proc *p;
  298         struct exec_package *epp;
  299 {
  300         struct exec *execp = epp->ep_hdr;
  301         int error;
  302 
  303         epp->ep_taddr = LINUX_N_TXTADDR(*execp, QMAGIC);
  304         epp->ep_tsize = execp->a_text;
  305         epp->ep_daddr = LINUX_N_DATADDR(*execp, QMAGIC);
  306         epp->ep_dsize = execp->a_data + execp->a_bss;
  307         epp->ep_entry = execp->a_entry;
  308 
  309         error = vn_marktext(epp->ep_vp);
  310         if (error)
  311                 return (error);
  312 
  313         /* set up command for text segment */
  314         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text,
  315             epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, QMAGIC),
  316             VM_PROT_READ|VM_PROT_EXECUTE);
  317 
  318         /* set up command for data segment */
  319         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data,
  320             epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, QMAGIC),
  321             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  322 
  323         /* set up command for bss segment */
  324         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
  325             epp->ep_daddr + execp->a_data, NULLVP, 0,
  326             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  327 
  328         return (*epp->ep_esch->es_setup_stack)(p, epp);
  329 }

Cache object: a01df80047dff1c98daa34f0ca8e7ffd


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