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.57 2005/02/26 23:10:19 perry 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.57 2005/02/26 23:10:19 perry 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         if (execp->a_bss)
  205                 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
  206                     epp->ep_daddr + execp->a_data, NULLVP, 0,
  207                     VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  208 
  209         return (*epp->ep_esch->es_setup_stack)(p, epp);
  210 }
  211 
  212 /*
  213  * exec_aout_prep_nmagic(): Prepare Linux NMAGIC package.
  214  * Not different from the normal stuff.
  215  */
  216 
  217 static int
  218 exec_linux_aout_prep_nmagic(p, epp)
  219         struct proc *p;
  220         struct exec_package *epp;
  221 {
  222         struct exec *execp = epp->ep_hdr;
  223         long bsize, baddr;
  224 
  225         epp->ep_taddr = LINUX_N_TXTADDR(*execp, NMAGIC);
  226         epp->ep_tsize = execp->a_text;
  227         epp->ep_daddr = LINUX_N_DATADDR(*execp, NMAGIC);
  228         epp->ep_dsize = execp->a_data + execp->a_bss;
  229         epp->ep_entry = execp->a_entry;
  230 
  231         /* set up command for text segment */
  232         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_text,
  233             epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, NMAGIC),
  234             VM_PROT_READ|VM_PROT_EXECUTE);
  235 
  236         /* set up command for data segment */
  237         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_data,
  238             epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, NMAGIC),
  239             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  240 
  241         /* set up command for bss segment */
  242         baddr = roundup(epp->ep_daddr + execp->a_data, PAGE_SIZE);
  243         bsize = epp->ep_daddr + epp->ep_dsize - baddr;
  244         if (bsize > 0)
  245                 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr,
  246                     NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  247 
  248         return (*epp->ep_esch->es_setup_stack)(p, epp);
  249 }
  250 
  251 /*
  252  * exec_aout_prep_omagic(): Prepare Linux OMAGIC package.
  253  * Business as usual.
  254  */
  255 
  256 static int
  257 exec_linux_aout_prep_omagic(p, epp)
  258         struct proc *p;
  259         struct exec_package *epp;
  260 {
  261         struct exec *execp = epp->ep_hdr;
  262         long dsize, bsize, baddr;
  263 
  264         epp->ep_taddr = LINUX_N_TXTADDR(*execp, OMAGIC);
  265         epp->ep_tsize = execp->a_text;
  266         epp->ep_daddr = LINUX_N_DATADDR(*execp, OMAGIC);
  267         epp->ep_dsize = execp->a_data + execp->a_bss;
  268         epp->ep_entry = execp->a_entry;
  269 
  270         /* set up command for text and data segments */
  271         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
  272             execp->a_text + execp->a_data, epp->ep_taddr, epp->ep_vp,
  273             LINUX_N_TXTOFF(*execp, OMAGIC), VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  274 
  275         /* set up command for bss segment */
  276         baddr = roundup(epp->ep_daddr + execp->a_data, PAGE_SIZE);
  277         bsize = epp->ep_daddr + epp->ep_dsize - baddr;
  278         if (bsize > 0)
  279                 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr,
  280                     NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  281 
  282         /*
  283          * Make sure (# of pages) mapped above equals (vm_tsize + vm_dsize);
  284          * obreak(2) relies on this fact. Both `vm_tsize' and `vm_dsize' are
  285          * computed (in execve(2)) by rounding *up* `ep_tsize' and `ep_dsize'
  286          * respectively to page boundaries.
  287          * Compensate `ep_dsize' for the amount of data covered by the last
  288          * text page.
  289          */
  290         dsize = epp->ep_dsize + execp->a_text - roundup(execp->a_text,
  291                                                         PAGE_SIZE);
  292         epp->ep_dsize = (dsize > 0) ? dsize : 0;
  293         return (*epp->ep_esch->es_setup_stack)(p, epp);
  294 }
  295 
  296 static int
  297 exec_linux_aout_prep_qmagic(p, epp)
  298         struct proc *p;
  299         struct exec_package *epp;
  300 {
  301         struct exec *execp = epp->ep_hdr;
  302         int error;
  303 
  304         epp->ep_taddr = LINUX_N_TXTADDR(*execp, QMAGIC);
  305         epp->ep_tsize = execp->a_text;
  306         epp->ep_daddr = LINUX_N_DATADDR(*execp, QMAGIC);
  307         epp->ep_dsize = execp->a_data + execp->a_bss;
  308         epp->ep_entry = execp->a_entry;
  309 
  310         error = vn_marktext(epp->ep_vp);
  311         if (error)
  312                 return (error);
  313 
  314         /* set up command for text segment */
  315         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text,
  316             epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, QMAGIC),
  317             VM_PROT_READ|VM_PROT_EXECUTE);
  318 
  319         /* set up command for data segment */
  320         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data,
  321             epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, QMAGIC),
  322             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  323 
  324         /* set up command for bss segment */
  325         if (execp->a_bss)
  326                 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
  327                     epp->ep_daddr + execp->a_data, NULLVP, 0,
  328                     VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
  329 
  330         return (*epp->ep_esch->es_setup_stack)(p, epp);
  331 }

Cache object: 3eafc2b7ae8d09bf21d32ea0e360c6a6


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