Index: head/sys/alpha/alpha/elf_machdep.c =================================================================== --- head/sys/alpha/alpha/elf_machdep.c (revision 100383) +++ head/sys/alpha/alpha/elf_machdep.c (revision 100384) @@ -1,122 +1,160 @@ /*- * Copyright 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include +#include +#include +#include +#include #include #include #include +#include +struct sysentvec elf64_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf64_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF64", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf64_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_ALPHA, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf64_freebsd_sysvec + }; + +SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf64_insert_brand_entry, + &freebsd_brand_info); + /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, const void *data, int type) { Elf_Addr relocbase = (Elf_Addr) lf->address; Elf_Addr *where; Elf_Addr addr; Elf_Addr addend; Elf_Word rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; switch (type) { case ELF_RELOC_REL: rel = (const Elf_Rel *)data; where = (Elf_Addr *) (relocbase + rel->r_offset); addend = *where; rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); break; case ELF_RELOC_RELA: rela = (const Elf_Rela *)data; where = (Elf_Addr *) (relocbase + rela->r_offset); addend = rela->r_addend; rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); break; default: panic("elf_reloc: unknown relocation mode %d\n", type); } switch (rtype) { case R_ALPHA_NONE: break; case R_ALPHA_REFQUAD: addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; addr += addend; if (*where != addr) *where = addr; break; case R_ALPHA_GLOB_DAT: addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; - addr += addend; + addr += addend; if (*where != addr) *where = addr; break; case R_ALPHA_JMP_SLOT: /* No point in lazy binding for kernel modules. */ addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; if (*where != addr) *where = addr; break; case R_ALPHA_RELATIVE: addr = relocbase + addend; if (*where != addr) *where = addr; break; case R_ALPHA_COPY: /* * There shouldn't be copy relocations in kernel * objects. */ printf("kldload: unexpected R_COPY relocation\n"); return -1; default: printf("kldload: unexpected relocation type %d\n", (int) rtype); return -1; } return(0); } Index: head/sys/alpha/linux/linux_sysvec.c =================================================================== --- head/sys/alpha/linux/linux_sysvec.c (revision 100383) +++ head/sys/alpha/linux/linux_sysvec.c (revision 100384) @@ -1,275 +1,277 @@ /*- * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ /* XXX we use functions that might not exist. */ #include "opt_compat.h" #ifndef COMPAT_43 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef szsigcode MODULE_VERSION(linux, 1); MODULE_DEPEND(linux, osf1, 1, 1, 1); MODULE_DEPEND(linux, sysvmsg, 1, 1, 1); MODULE_DEPEND(linux, sysvsem, 1, 1, 1); MODULE_DEPEND(linux, sysvshm, 1, 1, 1); MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); #if BYTE_ORDER == LITTLE_ENDIAN #define SHELLMAGIC 0x2123 /* #! */ #else #define SHELLMAGIC 0x2321 #endif SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); static int elf_linux_fixup(long **stack_base, struct image_params *iparams); static int exec_linux_imgact_try(struct image_params *iparams); static int elf_linux_fixup(long **stack_base, struct image_params *imgp) { long *pos; Elf64_Auxargs *args; args = (Elf64_Auxargs *)imgp->auxargs; pos = *stack_base + (imgp->argc + imgp->envc + 2); if (args->trace) { AUXARGS_ENTRY(pos, AT_DEBUG, 1); } if (args->execfd != -1) { AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); } AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); PROC_LOCK(imgp->proc); AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); PROC_UNLOCK(imgp->proc); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; **stack_base = (long)imgp->argc; return 0; } /* * If a linux binary is exec'ing something, try this image activator * first. We override standard shell script execution in order to * be able to modify the interpreter path. We only do this if a linux * binary is doing the exec, so we do not create an EXEC module for it. */ static int exec_linux_imgact_try(imgp) struct image_params *imgp; { const char *head; int error; head = (const char *)imgp->image_header; error = -1; /* * The interpreter for shell scripts run from a linux binary needs * to be located in /compat/linux if possible in order to recursively * maintain linux path emulation. */ if (((const short *)head)[0] == SHELLMAGIC) { /* * Run our normal shell image activator. If it succeeds * attempt to use the alternate path for the interpreter. If * an alternate path is found, use our stringspace to store it. */ if ((error = exec_shell_imgact(imgp)) == 0) { char *rpath = NULL; linux_emul_find(FIRST_THREAD_IN_PROC(imgp->proc), NULL, imgp->interpreter_name, &rpath, 0); if (rpath != imgp->interpreter_name) { int len = strlen(rpath) + 1; if (len <= MAXSHELLCMDLEN) { memcpy(imgp->interpreter_name, rpath, len); } free(rpath, M_TEMP); } } } return(error); } /* * To maintain OSF/1 compat, linux uses BSD signals & errnos on their * alpha port. This greatly simplfies things for us. */ struct sysentvec elf_linux_sysvec = { LINUX_SYS_MAXSYSCALL, linux_sysent, 0, 0, 0, 0, 0, 0, elf_linux_fixup, osendsig, linux_sigcode, &linux_szsigcode, 0, "Linux ELF", - elf_coredump, + elf64_coredump, exec_linux_imgact_try, LINUX_MINSIGSTKSZ }; static Elf64_Brandinfo linux_brand = { ELFOSABI_LINUX, + EM_ALPHA, "Linux", "/compat/linux", "/lib/ld-linux.so.1", &elf_linux_sysvec }; static Elf64_Brandinfo linux_glibc2brand = { ELFOSABI_LINUX, + EM_ALPHA, "Linux", "/compat/linux", "/lib/ld-linux.so.2", &elf_linux_sysvec }; Elf64_Brandinfo *linux_brandlist[] = { &linux_brand, &linux_glibc2brand, NULL }; static int linux_elf_modevent(module_t mod, int type, void *data) { Elf64_Brandinfo **brandinfo; int error; struct linux_ioctl_handler **lihp; error = 0; switch(type) { case MOD_LOAD: for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) - if (elf_insert_brand_entry(*brandinfo) < 0) + if (elf64_insert_brand_entry(*brandinfo) < 0) error = EINVAL; if (error == 0) { SET_FOREACH(lihp, linux_ioctl_handler_set) linux_ioctl_register_handler(*lihp); if (bootverbose) printf("Linux ELF exec handler installed\n"); } else printf("cannot insert Linux ELF brand handler\n"); break; case MOD_UNLOAD: for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) - if (elf_brand_inuse(*brandinfo)) + if (elf64_brand_inuse(*brandinfo)) error = EBUSY; if (error == 0) { for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) - if (elf_remove_brand_entry(*brandinfo) < 0) + if (elf64_remove_brand_entry(*brandinfo) < 0) error = EINVAL; } if (error == 0) { SET_FOREACH(lihp, linux_ioctl_handler_set) linux_ioctl_unregister_handler(*lihp); if (bootverbose) printf("Linux ELF exec handler removed\n"); } else printf("Could not deinstall ELF interpreter entry\n"); break; default: break; } return error; } static moduledata_t linux_elf_mod = { "linuxelf", linux_elf_modevent, 0 }; DUMMY(rt_sigreturn); DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); Index: head/sys/alpha/osf1/imgact_osf1.c =================================================================== --- head/sys/alpha/osf1/imgact_osf1.c (revision 100383) +++ head/sys/alpha/osf1/imgact_osf1.c (revision 100384) @@ -1,262 +1,262 @@ /* * Copyright (c) 1998-1999 Andrew Gallatin * All rights reserved. * * Based heavily on imgact_linux.c which is * Copyright (c) 1994-1996 Søren Schmidt. * Which in turn is based heavily on /sys/kern/imgact_aout.c which is: * Copyright (c) 1993, David Greenman * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern struct sysentvec osf1_sysvec; #ifdef DEBUG #define DPRINTF(a) printf a; #else #define DPRINTF(a) #endif static int exec_osf1_imgact(struct image_params *imgp) { int error; int path_not_saved; size_t bytes; const struct ecoff_exechdr *execp; const struct ecoff_aouthdr *eap; struct vmspace *vmspace; vm_offset_t baddr; vm_offset_t bsize; vm_offset_t bss_start; vm_offset_t daddr; vm_offset_t dend; vm_offset_t dsize; vm_offset_t raw_dend; vm_offset_t taddr; vm_offset_t tend; vm_offset_t tsize; struct nameidata *ndp; Osf_Auxargs *osf_auxargs; GIANT_REQUIRED; execp = (const struct ecoff_exechdr*)imgp->image_header; eap = &execp->a; ndp = NULL; /* check to make sure we have an alpha ecoff executable */ if (ECOFF_BADMAG(execp)) return -1; /* verfify it an OSF/1 exectutable */ if (eap->magic != ECOFF_ZMAGIC) { printf("unknown ecoff magic %x\n", eap->magic); return ENOEXEC; } osf_auxargs = malloc(sizeof(Osf_Auxargs), M_TEMP, M_WAITOK | M_ZERO); imgp->auxargs = osf_auxargs; osf_auxargs->executable = osf_auxargs->exec_path; path_not_saved = copyinstr(imgp->fname, osf_auxargs->executable, PATH_MAX, &bytes); if (execp->f.f_flags & DYNAMIC_FLAG) { if (path_not_saved) { uprintf("path to dynamic exectutable not found\n"); free(imgp->auxargs, M_TEMP); return(path_not_saved); } /* * Unmap the executable & attempt to slide in * /sbin/loader in its place. */ if (imgp->firstpage) exec_unmap_first_page(imgp); /* * Replicate what execve does, and map the first * page of the loader. */ ndp = (struct nameidata *)malloc(sizeof(struct nameidata), M_TEMP, M_WAITOK); NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_SYSSPACE, "/compat/osf1/sbin/loader", FIRST_THREAD_IN_PROC(imgp->proc)); error = namei(ndp); if (error) { uprintf("imgact_osf1: can't read /compat/osf1/sbin/loader\n"); free(imgp->auxargs, M_TEMP); return(error); } if (imgp->vp) { vrele(imgp->vp); /* leaking in the nameizone ??? XXX */ } imgp->vp = ndp->ni_vp; error = exec_map_first_page(imgp); VOP_UNLOCK(imgp->vp, 0, FIRST_THREAD_IN_PROC(imgp->proc)); osf_auxargs->loader = "/compat/osf1/sbin/loader"; } execp = (const struct ecoff_exechdr*)imgp->image_header; eap = &execp->a; taddr = ECOFF_SEGMENT_ALIGN(execp, eap->text_start); tend = round_page(eap->text_start + eap->tsize); tsize = tend - taddr; daddr = ECOFF_SEGMENT_ALIGN(execp, eap->data_start); dend = round_page(eap->data_start + eap->dsize); dsize = dend - daddr; bss_start = ECOFF_SEGMENT_ALIGN(execp, eap->bss_start); bsize = eap->bsize; imgp->entry_addr = eap->entry; /* copy in arguments and/or environment from old process */ error = exec_extract_strings(imgp); if (error) goto bail; /* * Destroy old process VM and create a new one (with a new stack). */ - exec_new_vmspace(imgp); + exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); /* * The vm space can now be changed. */ vmspace = imgp->proc->p_vmspace; imgp->interpreted = 0; imgp->proc->p_sysent = &osf1_sysvec; if ((eap->tsize != 0 || eap->dsize != 0) && imgp->vp->v_writecount != 0) { #ifdef DIAGNOSTIC if (imgp->vp->v_flag & VTEXT) panic("exec: a VTEXT vnode has writecount != 0\n"); #endif return ETXTBSY; } imgp->vp->v_flag |= VTEXT; /* set up text segment */ if ((error = vm_mmap(&vmspace->vm_map, &taddr, tsize, VM_PROT_READ|VM_PROT_EXECUTE, VM_PROT_ALL, MAP_FIXED|MAP_COPY, (caddr_t)imgp->vp, ECOFF_TXTOFF(execp)))) { DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error)); return error; } /* .. data .. */ if ((error = vm_mmap(&vmspace->vm_map, &daddr, dsize, VM_PROT_READ|VM_PROT_EXECUTE|VM_PROT_WRITE, VM_PROT_ALL, MAP_FIXED|MAP_COPY, (caddr_t)imgp->vp, ECOFF_DATOFF(execp)))) { DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error)); goto bail; } /* .. bss .. */ if (round_page(bsize)) { baddr = bss_start; if ((error = vm_map_find(&vmspace->vm_map, NULL, (vm_offset_t) 0, &baddr, round_page(bsize), FALSE, VM_PROT_ALL, VM_PROT_ALL, FALSE))) { DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error)); goto bail; } } raw_dend = (eap->data_start + eap->dsize); if (dend > raw_dend) { caddr_t zeros; zeros = malloc(dend-raw_dend,M_TEMP,M_WAITOK|M_ZERO); if ((error = copyout(zeros, (caddr_t)raw_dend, dend-raw_dend))) { uprintf("Can't zero start of bss, error %d\n",error); free(zeros,M_TEMP); goto bail; } free(zeros,M_TEMP); } vmspace->vm_tsize = btoc(round_page(tsize)); vmspace->vm_dsize = btoc((round_page(dsize) + round_page(bsize))); vmspace->vm_taddr = (caddr_t)taddr; vmspace->vm_daddr = (caddr_t)daddr; return(0); bail: free(imgp->auxargs, M_TEMP); if (ndp) { VOP_CLOSE(ndp->ni_vp, FREAD, imgp->proc->p_ucred, FIRST_THREAD_IN_PROC(imgp->proc)); vrele(ndp->ni_vp); } return(error); } /* * Tell kern_execve.c about it, with a little help from the linker. */ struct execsw osf1_execsw = { exec_osf1_imgact, "OSF/1 ECOFF" }; EXEC_SET(osf1_ecoff, osf1_execsw); Index: head/sys/amd64/amd64/elf_machdep.c =================================================================== --- head/sys/amd64/amd64/elf_machdep.c (revision 100383) +++ head/sys/amd64/amd64/elf_machdep.c (revision 100384) @@ -1,116 +1,156 @@ /*- * Copyright 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include +#include #include #include +#include +#include +#include +#include +#include #include +#include + +struct sysentvec elf32_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF32", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf32_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_386, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf32_freebsd_sysvec + }; + +SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &freebsd_brand_info); /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, const void *data, int type) { Elf_Addr relocbase = (Elf_Addr) lf->address; Elf_Addr *where; Elf_Addr addr; Elf_Addr addend; Elf_Word rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; switch (type) { case ELF_RELOC_REL: rel = (const Elf_Rel *)data; where = (Elf_Addr *) (relocbase + rel->r_offset); addend = *where; rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); break; case ELF_RELOC_RELA: rela = (const Elf_Rela *)data; where = (Elf_Addr *) (relocbase + rela->r_offset); addend = rela->r_addend; rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); break; default: panic("unknown reloc type %d\n", type); } switch (rtype) { case R_386_NONE: /* none */ break; case R_386_32: /* S + A */ addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; addr += addend; if (*where != addr) *where = addr; break; case R_386_PC32: /* S + A - P */ addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; addr += addend - (Elf_Addr)where; if (*where != addr) *where = addr; break; case R_386_COPY: /* none */ /* * There shouldn't be copy relocations in kernel * objects. */ printf("kldload: unexpected R_COPY relocation\n"); return -1; break; case R_386_GLOB_DAT: /* S */ addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; if (*where != addr) *where = addr; break; case R_386_RELATIVE: /* B + A */ addr = relocbase + addend; if (*where != addr) *where = addr; break; default: printf("kldload: unexpected relocation type %d\n", rtype); return -1; } return(0); } Index: head/sys/amd64/ia32/ia32.h =================================================================== --- head/sys/amd64/ia32/ia32.h (nonexistent) +++ head/sys/amd64/ia32/ia32.h (revision 100384) @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2001 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IA64_IA32_IA32_H_ +#define _IA64_IA32_IA32_H_ + +#define PTRIN(v) (void *)(uintptr_t) (v) +#define PTROUT(v) (u_int32_t)(uintptr_t) (v) + +#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0) +#define PTRIN_CP(src,dst,fld) \ + do { (dst).fld = PTRIN((src).fld); } while (0) +#define PTROUT_CP(src,dst,fld) \ + do { (dst).fld = PTROUT((src).fld); } while (0) + +struct timeval32 { + int32_t tv_sec; + int32_t tv_usec; +}; +#define TV_CP(src,dst,fld) do { \ + CP((src).fld,(dst).fld,tv_sec); \ + CP((src).fld,(dst).fld,tv_usec); \ +} while (0); + +struct timespec32 { + u_int32_t tv_sec; + u_int32_t tv_nsec; +}; +#define TS_CP(src,dst,fld) do { \ + CP((src).fld,(dst).fld,tv_sec); \ + CP((src).fld,(dst).fld,tv_nsec); \ +} while (0); + +struct rusage32 { + struct timeval32 ru_utime; + struct timeval32 ru_stime; + int32_t ru_maxrss; + int32_t ru_ixrss; + int32_t ru_idrss; + int32_t ru_isrss; + int32_t ru_minflt; + int32_t ru_majflt; + int32_t ru_nswap; + int32_t ru_inblock; + int32_t ru_oublock; + int32_t ru_msgsnd; + int32_t ru_msgrcv; + int32_t ru_nsignals; + int32_t ru_nvcsw; + int32_t ru_nivcsw; +}; + +struct statfs32 { + int32_t f_spare2; + int32_t f_bsize; + int32_t f_iosize; + int32_t f_blocks; + int32_t f_bfree; + int32_t f_bavail; + int32_t f_files; + int32_t f_ffree; + fsid_t f_fsid; + uid_t f_owner; + int32_t f_type; + int32_t f_flags; + int32_t f_syncwrites; + int32_t f_asyncwrites; + char f_fstypename[MFSNAMELEN]; + char f_mntonname[MNAMELEN]; + int32_t f_syncreads; + int32_t f_asyncreads; + int16_t f_spares1; + char f_mntfromname[MNAMELEN]; + int16_t f_spares2; + int32_t f_spare[2]; +}; + +#endif /* !_IA64_IA32_IA32_H_ */ Property changes on: head/sys/amd64/ia32/ia32.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/amd64/ia32/ia32_misc.c =================================================================== --- head/sys/amd64/ia32/ia32_misc.c (nonexistent) +++ head/sys/amd64/ia32/ia32_misc.c (revision 100384) @@ -0,0 +1,1339 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Must come after sys/malloc.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Must come after sys/selinfo.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static const char ia32_emul_path[] = "/compat/ia32"; +/* + * [ taken from the linux emulator ] + * Search an alternate path before passing pathname arguments on + * to system calls. Useful for keeping a separate 'emulation tree'. + * + * If cflag is set, we check if an attempt can be made to create + * the named file, i.e. we check if the directory it should + * be in exists. + */ +int +ia32_emul_find(td, sgp, prefix, path, pbuf, cflag) + struct thread *td; + caddr_t *sgp; /* Pointer to stackgap memory */ + const char *prefix; + char *path; + char **pbuf; + int cflag; +{ + int error; + size_t len, sz; + char *buf, *cp, *ptr; + struct ucred *ucred; + struct nameidata nd; + struct nameidata ndroot; + struct vattr vat; + struct vattr vatroot; + + buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + *pbuf = path; + + for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) + continue; + + sz = MAXPATHLEN - (ptr - buf); + + /* + * If sgp is not given then the path is already in kernel space + */ + if (sgp == NULL) + error = copystr(path, ptr, sz, &len); + else + error = copyinstr(path, ptr, sz, &len); + + if (error) { + free(buf, M_TEMP); + return error; + } + + if (*ptr != '/') { + free(buf, M_TEMP); + return EINVAL; + } + + /* + * We know that there is a / somewhere in this pathname. + * Search backwards for it, to find the file's parent dir + * to see if it exists in the alternate tree. If it does, + * and we want to create a file (cflag is set). We don't + * need to worry about the root comparison in this case. + */ + + if (cflag) { + for (cp = &ptr[len] - 1; *cp != '/'; cp--) + ; + *cp = '\0'; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + *cp = '/'; + } else { + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + /* + * We now compare the vnode of the ia32_root to the one + * vnode asked. If they resolve to be the same, then we + * ignore the match so that the real root gets used. + * This avoids the problem of traversing "../.." to find the + * root directory and never finding it, because "/" resolves + * to the emulation root directory. This is expensive :-( + */ + NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path, + td); + + if ((error = namei(&ndroot)) != 0) { + /* Cannot happen! */ + free(buf, M_TEMP); + vrele(nd.ni_vp); + return error; + } + + ucred = td->td_ucred; + if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) { + goto bad; + } + + if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred, + td)) != 0) { + goto bad; + } + + if (vat.va_fsid == vatroot.va_fsid && + vat.va_fileid == vatroot.va_fileid) { + error = ENOENT; + goto bad; + } + + } + if (sgp == NULL) + *pbuf = buf; + else { + sz = &ptr[len] - buf; + *pbuf = stackgap_alloc(sgp, sz + 1); + error = copyout(buf, *pbuf, sz); + free(buf, M_TEMP); + } + + vrele(nd.ni_vp); + if (!cflag) + vrele(ndroot.ni_vp); + + return error; + +bad: + vrele(ndroot.ni_vp); + vrele(nd.ni_vp); + free(buf, M_TEMP); + return error; +} + +int +ia32_open(struct thread *td, struct ia32_open_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return open(td, (struct open_args *) uap); +} + +int +ia32_wait4(struct thread *td, struct ia32_wait4_args *uap) +{ + int error; + caddr_t sg; + struct rusage32 *rusage32, ru32; + struct rusage *rusage = NULL, ru; + + rusage32 = SCARG(uap, rusage); + if (rusage32) { + sg = stackgap_init(); + rusage = stackgap_alloc(&sg, sizeof(struct rusage)); + SCARG(uap, rusage) = (struct rusage32 *)rusage; + } + error = wait4(td, (struct wait_args *)uap); + if (error) + return (error); + if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) { + TV_CP(ru, ru32, ru_utime); + TV_CP(ru, ru32, ru_stime); + CP(ru, ru32, ru_maxrss); + CP(ru, ru32, ru_ixrss); + CP(ru, ru32, ru_idrss); + CP(ru, ru32, ru_isrss); + CP(ru, ru32, ru_minflt); + CP(ru, ru32, ru_majflt); + CP(ru, ru32, ru_nswap); + CP(ru, ru32, ru_inblock); + CP(ru, ru32, ru_oublock); + CP(ru, ru32, ru_msgsnd); + CP(ru, ru32, ru_msgrcv); + CP(ru, ru32, ru_nsignals); + CP(ru, ru32, ru_nvcsw); + CP(ru, ru32, ru_nivcsw); + error = copyout(&ru32, rusage32, sizeof(ru32)); + } + return (error); +} + +static void +copy_statfs(struct statfs *in, struct statfs32 *out) +{ + CP(*in, *out, f_bsize); + CP(*in, *out, f_iosize); + CP(*in, *out, f_blocks); + CP(*in, *out, f_bfree); + CP(*in, *out, f_bavail); + CP(*in, *out, f_files); + CP(*in, *out, f_ffree); + CP(*in, *out, f_fsid); + CP(*in, *out, f_owner); + CP(*in, *out, f_type); + CP(*in, *out, f_flags); + CP(*in, *out, f_flags); + CP(*in, *out, f_syncwrites); + CP(*in, *out, f_asyncwrites); + bcopy(in->f_fstypename, + out->f_fstypename, MFSNAMELEN); + bcopy(in->f_mntonname, + out->f_mntonname, MNAMELEN); + CP(*in, *out, f_syncreads); + CP(*in, *out, f_asyncreads); + bcopy(in->f_mntfromname, + out->f_mntfromname, MNAMELEN); +} + +int +ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *sp32, stat32; + struct statfs *sp = NULL, stat; + int maxcount, count, i; + + sp32 = SCARG(uap, buf); + maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32); + + if (sp32) { + sg = stackgap_init(); + sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); + SCARG(uap, buf) = (struct statfs32 *)sp; + } + error = getfsstat(td, (struct getfsstat_args *) uap); + if (sp32 && !error) { + count = td->td_retval[0]; + for (i = 0; i < count; i++) { + error = copyin(&sp[i], &stat, sizeof(stat)); + if (error) + return (error); + copy_statfs(&stat, &stat32); + error = copyout(&stat32, &sp32[i], sizeof(stat32)); + if (error) + return (error); + } + } + return (error); +} + +int +ia32_access(struct thread *td, struct ia32_access_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return access(td, (struct access_args *)uap); +} + +int +ia32_chflags(struct thread *td, struct ia32_chflags_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return chflags(td, (struct chflags_args *)uap); +} + +struct sigaltstack32 { + u_int32_t ss_sp; + u_int32_t ss_size; + int ss_flags; +}; + +int +ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap) +{ + int error; + caddr_t sg; + struct sigaltstack32 *p32, *op32, s32; + struct sigaltstack *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, ss); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + SCARG(uap, ss) = (struct sigaltstack32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + PTRIN_CP(s32, s, ss_sp); + CP(s32, s, ss_size); + CP(s32, s, ss_flags); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oss); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + SCARG(uap, oss) = (struct sigaltstack32 *)op; + } + error = sigaltstack(td, (struct sigaltstack_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + PTROUT_CP(s, s32, ss_sp); + CP(s, s32, ss_size); + CP(s, s32, ss_flags); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_execve(struct thread *td, struct ia32_execve_args *uap) +{ + int error; + caddr_t sg; + struct execve_args ap; + u_int32_t *p32, arg; + char **p; + int count; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, fname)); + SCARG(&ap, fname) = SCARG(uap, fname); + + if (SCARG(uap, argv)) { + count = 0; + p32 = SCARG(uap, argv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + count++; + } while (arg != 0); + p = stackgap_alloc(&sg, count * sizeof(char *)); + SCARG(&ap, argv) = p; + p32 = SCARG(uap, argv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + *p++ = PTRIN(arg); + } while (arg != 0); + } + if (SCARG(uap, envv)) { + count = 0; + p32 = SCARG(uap, envv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + count++; + } while (arg != 0); + p = stackgap_alloc(&sg, count * sizeof(char *)); + SCARG(&ap, envv) = p; + p32 = SCARG(uap, envv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + *p++ = PTRIN(arg); + } while (arg != 0); + } + + return execve(td, &ap); +} + +static int +ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, + int prot, int fd, off_t pos) +{ + vm_map_t map; + vm_map_entry_t entry; + int rv; + + map = &td->td_proc->p_vmspace->vm_map; + if (fd != -1) + prot |= VM_PROT_WRITE; + + if (vm_map_lookup_entry(map, start, &entry)) { + if ((entry->protection & prot) != prot) { + rv = vm_map_protect(map, + trunc_page(start), + round_page(end), + entry->protection | prot, + FALSE); + if (rv != KERN_SUCCESS) + return (EINVAL); + } + } else { + vm_offset_t addr = trunc_page(start); + rv = vm_map_find(map, 0, 0, + &addr, PAGE_SIZE, FALSE, prot, + VM_PROT_ALL, 0); + if (rv != KERN_SUCCESS) + return (EINVAL); + } + + if (fd != -1) { + struct pread_args r; + SCARG(&r, fd) = fd; + SCARG(&r, buf) = (void *) start; + SCARG(&r, nbyte) = end - start; + SCARG(&r, offset) = pos; + return (pread(td, &r)); + } else { + while (start < end) { + subyte((void *) start, 0); + start++; + } + return (0); + } +} + +int +ia32_mmap(struct thread *td, struct ia32_mmap_args *uap) +{ + struct mmap_args ap; + vm_offset_t addr = (vm_offset_t) SCARG(uap, addr); + vm_size_t len = SCARG(uap, len); + int prot = SCARG(uap, prot); + int flags = SCARG(uap, flags); + int fd = SCARG(uap, fd); + off_t pos = (SCARG(uap, poslo) + | ((off_t)SCARG(uap, poshi) << 32)); + vm_size_t pageoff; + int error; + + /* + * Attempt to handle page size hassles. + */ + pageoff = (pos & PAGE_MASK); + if (flags & MAP_FIXED) { + vm_offset_t start, end; + start = addr; + end = addr + len; + + if (start != trunc_page(start)) { + error = ia32_mmap_partial(td, start, round_page(start), + prot, fd, pos); + if (fd != -1) + pos += round_page(start) - start; + start = round_page(start); + } + if (end != round_page(end)) { + vm_offset_t t = trunc_page(end); + error = ia32_mmap_partial(td, t, end, + prot, fd, + pos + t - start); + end = trunc_page(end); + } + if (end > start && fd != -1 && (pos & PAGE_MASK)) { + /* + * We can't map this region at all. The specified + * address doesn't have the same alignment as the file + * position. Fake the mapping by simply reading the + * entire region into memory. First we need to make + * sure the region exists. + */ + vm_map_t map; + struct pread_args r; + int rv; + + prot |= VM_PROT_WRITE; + map = &td->td_proc->p_vmspace->vm_map; + rv = vm_map_remove(map, start, end); + if (rv != KERN_SUCCESS) + return (EINVAL); + rv = vm_map_find(map, 0, 0, + &start, end - start, FALSE, + prot, VM_PROT_ALL, 0); + if (rv != KERN_SUCCESS) + return (EINVAL); + SCARG(&r, fd) = fd; + SCARG(&r, buf) = (void *) start; + SCARG(&r, nbyte) = end - start; + SCARG(&r, offset) = pos; + error = pread(td, &r); + if (error) + return (error); + + td->td_retval[0] = addr; + return (0); + } + if (end == start) { + /* + * After dealing with the ragged ends, there + * might be none left. + */ + td->td_retval[0] = addr; + return (0); + } + addr = start; + len = end - start; + } + + SCARG(&ap, addr) = (void *) addr; + SCARG(&ap, len) = len; + SCARG(&ap, prot) = prot; + SCARG(&ap, flags) = flags; + SCARG(&ap, fd) = fd; + SCARG(&ap, pos) = pos; + + return (mmap(td, &ap)); +} + +struct itimerval32 { + struct timeval32 it_interval; + struct timeval32 it_value; +}; + +int +ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap) +{ + int error; + caddr_t sg; + struct itimerval32 *p32, *op32, s32; + struct itimerval *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, itv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct itimerval)); + SCARG(uap, itv) = (struct itimerval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + TV_CP(s32, s, it_interval); + TV_CP(s32, s, it_value); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oitv); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct itimerval)); + SCARG(uap, oitv) = (struct itimerval32 *)op; + } + error = setitimer(td, (struct setitimer_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + TV_CP(s, s32, it_interval); + TV_CP(s, s32, it_value); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_select(struct thread *td, struct ia32_select_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tv) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + /* + * XXX big-endian needs to convert the fd_sets too. + */ + return (select(td, (struct select_args *) uap)); +} + +int +ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tp); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tp) = (struct timeval32 *)p; + } + error = gettimeofday(td, (struct gettimeofday_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + CP(s, s32, tv_sec); + CP(s, s32, tv_usec); + error = copyout(&s32, p32, sizeof(s32)); + if (error) + return (error); + } + return (error); +} + +int +ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap) +{ + int error; + caddr_t sg; + struct rusage32 *p32, s32; + struct rusage *p = NULL, s; + + p32 = SCARG(uap, rusage); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct rusage)); + SCARG(uap, rusage) = (struct rusage32 *)p; + } + error = getrusage(td, (struct getrusage_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + TV_CP(s, s32, ru_utime); + TV_CP(s, s32, ru_stime); + CP(s, s32, ru_maxrss); + CP(s, s32, ru_ixrss); + CP(s, s32, ru_idrss); + CP(s, s32, ru_isrss); + CP(s, s32, ru_minflt); + CP(s, s32, ru_majflt); + CP(s, s32, ru_nswap); + CP(s, s32, ru_inblock); + CP(s, s32, ru_oublock); + CP(s, s32, ru_msgsnd); + CP(s, s32, ru_msgrcv); + CP(s, s32, ru_nsignals); + CP(s, s32, ru_nvcsw); + CP(s, s32, ru_nivcsw); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +struct iovec32 { + u_int32_t iov_base; + int iov_len; +}; +#define STACKGAPLEN 400 + +int +ia32_readv(struct thread *td, struct ia32_readv_args *uap) +{ + int error, osize, nsize, i; + caddr_t sg; + struct readv_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ a; + struct iovec32 *oio; + struct iovec *nio; + + sg = stackgap_init(); + + if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec))) + return (EINVAL); + + osize = SCARG(uap, iovcnt) * sizeof (struct iovec32); + nsize = SCARG(uap, iovcnt) * sizeof (struct iovec); + + oio = malloc(osize, M_TEMP, M_WAITOK); + nio = malloc(nsize, M_TEMP, M_WAITOK); + + error = 0; + if ((error = copyin(SCARG(uap, iovp), oio, osize))) + goto punt; + for (i = 0; i < SCARG(uap, iovcnt); i++) { + nio[i].iov_base = PTRIN(oio[i].iov_base); + nio[i].iov_len = oio[i].iov_len; + } + + SCARG(&a, fd) = SCARG(uap, fd); + SCARG(&a, iovp) = stackgap_alloc(&sg, nsize); + SCARG(&a, iovcnt) = SCARG(uap, iovcnt); + + if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize))) + goto punt; + error = readv(td, &a); + +punt: + free(oio, M_TEMP); + free(nio, M_TEMP); + return (error); +} + +int +ia32_writev(struct thread *td, struct ia32_writev_args *uap) +{ + int error, i, nsize, osize; + caddr_t sg; + struct writev_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ a; + struct iovec32 *oio; + struct iovec *nio; + + sg = stackgap_init(); + + if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec))) + return (EINVAL); + + osize = SCARG(uap, iovcnt) * sizeof (struct iovec32); + nsize = SCARG(uap, iovcnt) * sizeof (struct iovec); + + oio = malloc(osize, M_TEMP, M_WAITOK); + nio = malloc(nsize, M_TEMP, M_WAITOK); + + error = 0; + if ((error = copyin(SCARG(uap, iovp), oio, osize))) + goto punt; + for (i = 0; i < SCARG(uap, iovcnt); i++) { + nio[i].iov_base = PTRIN(oio[i].iov_base); + nio[i].iov_len = oio[i].iov_len; + } + + SCARG(&a, fd) = SCARG(uap, fd); + SCARG(&a, iovp) = stackgap_alloc(&sg, nsize); + SCARG(&a, iovcnt) = SCARG(uap, iovcnt); + + if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize))) + goto punt; + error = writev(td, &a); + +punt: + free(oio, M_TEMP); + free(nio, M_TEMP); + return (error); +} + +int +ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tv) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + return (settimeofday(td, (struct settimeofday_args *) uap)); +} + +int +ia32_utimes(struct thread *td, struct ia32_utimes_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32[2]; + struct timeval *p = NULL, s[2]; + + p32 = SCARG(uap, tptr); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); + SCARG(uap, tptr) = (struct timeval32 *)p; + error = copyin(p32, s32, sizeof(s32)); + if (error) + return (error); + CP(s32[0], s[0], tv_sec); + CP(s32[0], s[0], tv_usec); + CP(s32[1], s[1], tv_sec); + CP(s32[1], s[1], tv_usec); + error = copyout(s, p, sizeof(s)); + if (error) + return (error); + } + return (utimes(td, (struct utimes_args *) uap)); +} + +int +ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, *op32, s32; + struct timeval *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, delta); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, delta) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, olddelta); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, olddelta) = (struct timeval32 *)op; + } + error = utimes(td, (struct utimes_args *) uap); + if (error) + return error; + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + CP(s, s32, tv_sec); + CP(s, s32, tv_usec); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_statfs(struct thread *td, struct ia32_statfs_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *p32, s32; + struct statfs *p = NULL, s; + + p32 = SCARG(uap, buf); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct statfs)); + SCARG(uap, buf) = (struct statfs32 *)p; + } + error = statfs(td, (struct statfs_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_statfs(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *p32, s32; + struct statfs *p = NULL, s; + + p32 = SCARG(uap, buf); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct statfs)); + SCARG(uap, buf) = (struct statfs32 *)p; + } + error = fstatfs(td, (struct fstatfs_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_statfs(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_semsys(struct thread *td, struct ia32_semsys_args *uap) +{ + /* + * Vector through to semsys if it is loaded. + */ + return sysent[169].sy_call(td, uap); +} + +int +ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap) +{ + /* + * Vector through to msgsys if it is loaded. + */ + return sysent[170].sy_call(td, uap); +} + +int +ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap) +{ + /* + * Vector through to shmsys if it is loaded. + */ + return sysent[171].sy_call(td, uap); +} + +int +ia32_pread(struct thread *td, struct ia32_pread_args *uap) +{ + struct pread_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, buf) = SCARG(uap, buf); + SCARG(&ap, nbyte) = SCARG(uap, nbyte); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + return (pread(td, &ap)); +} + +int +ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap) +{ + struct pwrite_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, buf) = SCARG(uap, buf); + SCARG(&ap, nbyte) = SCARG(uap, nbyte); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + return (pwrite(td, &ap)); +} + +int +ia32_lseek(struct thread *td, struct ia32_lseek_args *uap) +{ + int error; + struct lseek_args ap; + off_t pos; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + SCARG(&ap, whence) = SCARG(uap, whence); + error = lseek(td, &ap); + /* Expand the quad return into two parts for eax and edx */ + pos = *(off_t *)(td->td_retval); + td->td_retval[0] = pos & 0xffffffff; /* %eax */ + td->td_retval[1] = pos >> 32; /* %edx */ + return error; +} + +int +ia32_truncate(struct thread *td, struct ia32_truncate_args *uap) +{ + struct truncate_args ap; + + SCARG(&ap, path) = SCARG(uap, path); + SCARG(&ap, length) = (SCARG(uap, lengthlo) + | ((off_t)SCARG(uap, lengthhi) << 32)); + return (truncate(td, &ap)); +} + +int +ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap) +{ + struct ftruncate_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, length) = (SCARG(uap, lengthlo) + | ((off_t)SCARG(uap, lengthhi) << 32)); + return (ftruncate(td, &ap)); +} + +int +ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap) +{ + struct sendfile_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, s) = SCARG(uap, s); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + SCARG(&ap, nbytes) = SCARG(uap, nbytes); /* XXX check */ + SCARG(&ap, hdtr) = SCARG(uap, hdtr); /* XXX check */ + SCARG(&ap, sbytes) = SCARG(uap, sbytes); /* XXX FIXME!! */ + SCARG(&ap, flags) = SCARG(uap, flags); + return (sendfile(td, &ap)); +} + +struct stat32 { + udev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + udev_t st_rdev; + struct timespec32 st_atimespec; + struct timespec32 st_mtimespec; + struct timespec32 st_ctimespec; + off_t st_size; + int64_t st_blocks; + u_int32_t st_blksize; + u_int32_t st_flags; + u_int32_t st_gen; +}; + +static void +copy_stat( struct stat *in, struct stat32 *out) +{ + CP(*in, *out, st_dev); + CP(*in, *out, st_ino); + CP(*in, *out, st_mode); + CP(*in, *out, st_nlink); + CP(*in, *out, st_uid); + CP(*in, *out, st_gid); + CP(*in, *out, st_rdev); + TS_CP(*in, *out, st_atimespec); + TS_CP(*in, *out, st_mtimespec); + TS_CP(*in, *out, st_ctimespec); + CP(*in, *out, st_size); + CP(*in, *out, st_blocks); + CP(*in, *out, st_blksize); + CP(*in, *out, st_flags); + CP(*in, *out, st_gen); +} + +int +ia32_stat(struct thread *td, struct ia32_stat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = stat(td, (struct stat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_fstat(struct thread *td, struct ia32_fstat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = fstat(td, (struct fstat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_lstat(struct thread *td, struct ia32_lstat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = lstat(td, (struct lstat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +/* + * MPSAFE + */ +int +ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap) +{ + int error, name[CTL_MAXNAME]; + size_t j, oldlen; + + if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) + return (EINVAL); + + error = copyin(uap->name, &name, uap->namelen * sizeof(int)); + if (error) + return (error); + + mtx_lock(&Giant); + + if (uap->oldlenp) + oldlen = fuword32(uap->oldlenp); + else + oldlen = 0; + error = userland_sysctl(td, name, uap->namelen, + uap->old, &oldlen, 1, + uap->new, uap->newlen, &j); + if (error && error != ENOMEM) + goto done2; + if (uap->oldlenp) { + suword32(uap->oldlenp, j); + } +done2: + mtx_unlock(&Giant); + return (error); +} + +struct sigaction32 { + u_int32_t sa_u; + int sa_flags; + sigset_t sa_mask; +}; + +int +ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap) +{ + int error; + caddr_t sg; + struct sigaction32 *p32, *op32, s32; + struct sigaction *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, act); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(uap, act) = (struct sigaction32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + s.sa_handler = PTRIN(s32.sa_u); + CP(s32, s, sa_flags); + CP(s32, s, sa_mask); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oact); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(uap, oact) = (struct sigaction32 *)op; + } + error = sigaction(td, (struct sigaction_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + s32.sa_u = PTROUT(s.sa_handler); + CP(s, s32, sa_flags); + CP(s, s32, sa_mask); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +#if 0 + +int +ia32_xxx(struct thread *td, struct ia32_xxx_args *uap) +{ + int error; + caddr_t sg; + struct yyy32 *p32, s32; + struct yyy *p = NULL, s; + + p32 = SCARG(uap, zzz); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct yyy)); + SCARG(uap, zzz) = (struct yyy32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + /* translate in */ + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + error = xxx(td, (struct xxx_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + /* translate out */ + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +#endif Property changes on: head/sys/amd64/ia32/ia32_misc.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/amd64/ia32/ia32_sysvec.c =================================================================== --- head/sys/amd64/ia32/ia32_sysvec.c (nonexistent) +++ head/sys/amd64/ia32/ia32_sysvec.c (revision 100384) @@ -0,0 +1,365 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#define __ELF_WORD_SIZE 32 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static register_t *ia32_copyout_strings(struct image_params *imgp); +static void ia32_setregs(struct thread *td, u_long entry, u_long stack, + u_long ps_strings); + +extern struct sysent ia32_sysent[]; + +static char ia32_sigcode[] = { + 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */ + 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */ + 0x50, /* pushl %eax */ + 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */ + 0x75, 0x03, /* jne 9f */ + 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */ + 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */ + 0x50, /* pushl %eax */ + 0xcd, 0x80, /* int $0x80 */ + 0xeb, 0xfe, /* 0: jmp 0b */ + 0, 0, 0, 0 +}; +static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3; + +struct sysentvec ia32_freebsd_sysvec = { + SYS_MAXSYSCALL, + ia32_sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + ia32_sigcode, + &ia32_szsigcode, + 0, + "FreeBSD ELF", + elf32_coredump, + NULL, + MINSIGSTKSZ, + 4096, + IA32_USRSTACK, + IA32_USRSTACK, + ia32_copyout_strings, + ia32_setregs +}; + +static Elf32_Brandinfo ia32_brand_info = { + ELFOSABI_FREEBSD, + EM_386, + "FreeBSD", + "/compat/ia32", + "/usr/libexec/ld-elf.so.1", + &ia32_freebsd_sysvec + }; + +SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &ia32_brand_info); + +static register_t * +ia32_copyout_strings(struct image_params *imgp) +{ + int argc, envc; + u_int32_t *vectp; + char *stringp, *destp; + u_int32_t *stack_base; + struct ia32_ps_strings *arginfo; + int szsigcode; + + /* + * Calculate string base and vector table pointers. + * Also deal with signal trampoline code for this exec type. + */ + arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS; + szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); + destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - + roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + + /* + * install sigcode + */ + if (szsigcode) + copyout(imgp->proc->p_sysent->sv_sigcode, + ((caddr_t)arginfo - szsigcode), szsigcode); + + /* + * If we have a valid auxargs ptr, prepare some room + * on the stack. + */ + if (imgp->auxargs) { + /* + * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for + * lower compatibility. + */ + imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size + : (AT_COUNT * 2); + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets,and imgp->auxarg_size is room + * for argument of Runtime loader. + */ + vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + + imgp->auxarg_size) * sizeof(u_int32_t)); + + } else + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets + */ + vectp = (u_int32_t *) + (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); + + /* + * vectp also becomes our initial stack base + */ + stack_base = vectp; + + stringp = imgp->stringbase; + argc = imgp->argc; + envc = imgp->envc; + + /* + * Copy out strings - arguments and environment. + */ + copyout(stringp, destp, ARG_MAX - imgp->stringspace); + + /* + * Fill in "ps_strings" struct for ps, w, etc. + */ + suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nargvstr, argc); + + /* + * Fill in argument portion of vector table. + */ + for (; argc > 0; --argc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* a null vector table pointer separates the argp's from the envp's */ + suword32(vectp++, 0); + + suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nenvstr, envc); + + /* + * Fill in environment portion of vector table. + */ + for (; envc > 0; --envc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* end of vector table is a null pointer */ + suword32(vectp, 0); + + return ((register_t *)stack_base); +} + +static void +ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +{ + struct trapframe *frame = td->td_frame; + vm_offset_t gdt, ldt; + u_int64_t codesel, datasel, ldtsel; + u_int64_t codeseg, dataseg, gdtseg, ldtseg; + struct segment_descriptor desc; + struct vmspace *vmspace = td->td_proc->p_vmspace; + + /* + * Make sure that we restore the entire trapframe after an + * execve. + */ + frame->tf_flags &= ~FRAME_SYSCALL; + + bzero(frame->tf_r, sizeof(frame->tf_r)); + bzero(frame->tf_f, sizeof(frame->tf_f)); + + frame->tf_cr_iip = entry; + frame->tf_cr_ipsr = (IA64_PSR_IC + | IA64_PSR_I + | IA64_PSR_IT + | IA64_PSR_DT + | IA64_PSR_RT + | IA64_PSR_DFH + | IA64_PSR_IS + | IA64_PSR_BN + | IA64_PSR_CPL_USER); + frame->tf_r[FRAME_R12] = stack; + + codesel = LSEL(LUCODE_SEL, SEL_UPL); + datasel = LSEL(LUDATA_SEL, SEL_UPL); + ldtsel = GSEL(GLDT_SEL, SEL_UPL); + +#if 1 + frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32) + | (datasel << 16) | datasel; + frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel; +#else + frame->tf_r[FRAME_R16] = datasel; + frame->tf_r[FRAME_R17] = codesel; + frame->tf_r[FRAME_R18] = datasel; + frame->tf_r[FRAME_R19] = datasel; + frame->tf_r[FRAME_R20] = datasel; + frame->tf_r[FRAME_R21] = datasel; + frame->tf_r[FRAME_R22] = ldtsel; +#endif + + /* + * Build the GDT and LDT. + */ + gdt = IA32_USRSTACK; + vm_map_find(&vmspace->vm_map, 0, 0, + &gdt, PAGE_SIZE, 0, + VM_PROT_ALL, VM_PROT_ALL, 0); + ldt = gdt + 4096; + + desc.sd_lolimit = 8*NLDT-1; + desc.sd_lobase = ldt & 0xffffff; + desc.sd_type = SDT_SYSLDT; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = 0; + desc.sd_def32 = 0; + desc.sd_gran = 0; + desc.sd_hibase = ldt >> 24; + copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc)); + + desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff; + desc.sd_lobase = 0; + desc.sd_type = SDT_MEMERA; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16; + desc.sd_def32 = 1; + desc.sd_gran = 1; + desc.sd_hibase = 0; + copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc)); + desc.sd_type = SDT_MEMRWA; + copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc)); + + codeseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMERA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + dataseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMRWA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + ia64_set_csd(codeseg); + ia64_set_ssd(dataseg); + frame->tf_r[FRAME_R24] = dataseg; /* ESD */ + frame->tf_r[FRAME_R27] = dataseg; /* DSD */ + frame->tf_r[FRAME_R28] = dataseg; /* FSD */ + frame->tf_r[FRAME_R29] = dataseg; /* GSD */ + + gdtseg = gdt /* base */ + + ((8L*NGDT - 1) << 32) /* limit */ + + ((long)SDT_SYSNULL << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + ldtseg = ldt /* base */ + + ((8L*NLDT - 1) << 32) /* limit */ + + ((long)SDT_SYSLDT << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */ + frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */ + + ia64_set_eflag(PSL_USER); + + /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ + frame->tf_r[FRAME_R11] = IA32_PS_STRINGS; + + /* + * XXX - Linux emulator + * Make sure sure edx is 0x0 on entry. Linux binaries depend + * on it. + */ + td->td_retval[1] = 0; +} Property changes on: head/sys/amd64/ia32/ia32_sysvec.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/amd64/ia32/ia32_util.h =================================================================== --- head/sys/amd64/ia32/ia32_util.h (nonexistent) +++ head/sys/amd64/ia32/ia32_util.h (revision 100384) @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 1998-1999 Andrew Gallatin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + + +#include +#include +#include + + +#ifndef SCARG +#define SCARG(p, x) (p)->x +#endif + +struct ia32_ps_strings { + u_int32_t ps_argvstr; /* first of 0 or more argument strings */ + int ps_nargvstr; /* the number of argument strings */ + u_int32_t ps_envstr; /* first of 0 or more environment strings */ + int ps_nenvstr; /* the number of environment strings */ +}; + +#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE) +#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings)) + +static __inline caddr_t stackgap_init(void); +static __inline void *stackgap_alloc(caddr_t *, size_t); + +static __inline caddr_t +stackgap_init() +{ +#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) + return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE); +#undef szsigcode +} + +static __inline void * +stackgap_alloc(sgp, sz) + caddr_t *sgp; + size_t sz; +{ + void *p; + + p = (void *) *sgp; + *sgp += ALIGN(sz); + return p; +} + + +extern const char ia32_emul_path[]; +int ia32_emul_find(struct thread *, caddr_t *, const char *, char *, + char **, int); + +#define CHECKALT(p, sgp, path, i) \ + do { \ + int _error; \ + \ + _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \ + &path, i); \ + if (_error == EFAULT) \ + return (_error); \ + } while (0) + +#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0) +#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1) Property changes on: head/sys/amd64/ia32/ia32_util.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/amd64/ia32/syscalls.master =================================================================== --- head/sys/amd64/ia32/syscalls.master (revision 100383) +++ head/sys/amd64/ia32/syscalls.master (revision 100384) @@ -1,562 +1,563 @@ $FreeBSD$ ; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94 ; from: src/sys/kern/syscalls.master 1.107 ; ; System call name/number master file. ; Processed to created init_sysent.c, syscalls.c and syscall.h. ; Columns: number [M]type nargs namespc name alt{name,tag,rtyp}/comments ; number system call number, must be in order ; type one of [M]STD, [M]OBSOL, [M]UNIMPL, [M]COMPAT, [M]CPT_NOA, ; [M]LIBCOMPAT, [M]NODEF, [M]NOARGS, [M]NOPROTO, [M]NOIMPL, ; [M]NOSTD ; namespc one of POSIX, BSD, NOHIDE ; name psuedo-prototype of syscall routine ; If one of the following alts is different, then all appear: ; altname name of system call if different ; alttag name of args struct tag if different from [o]`name'"_args" ; altrtyp return type if not int (bogus - syscalls always return int) ; for UNIMPL/OBSOL, name continues with comments ; types: ; [M] e.g. like MSTD -- means the system call is MP-safe. If no ; M prefix is used, the syscall wrapper will obtain the Giant ; lock for the syscall. ; STD always included ; COMPAT included on COMPAT #ifdef ; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h ; OBSOL obsolete, not included in system, only specifies name ; UNIMPL not implemented, placeholder only ; NOSTD implemented but as a lkm that can be statically ; compiled in sysent entry will be filled with lkmsys ; so the SYSCALL_MODULE macro works ; #ifdef's, etc. may be included, and are copied to the output files. #include #include #include +#include +#include +#include ; Reserved/unimplemented system calls in the range 0-150 inclusive ; are reserved for use in future Berkeley releases. ; Additional system calls implemented in vendor and other ; redistributions should be placed in the reserved range at the end ; of the current calls. -0 STD NOHIDE { int nosys(void); } syscall nosys_args int -1 MSTD NOHIDE { void sys_exit(int rval); } exit sys_exit_args void -2 MSTD POSIX { int fork(void); } -3 MSTD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); } -4 MSTD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); } -5 STD POSIX { int open(char *path, int flags, int mode); } +0 MNOPROTO NOHIDE { int nosys(void); } syscall nosys_args int +1 MNOPROTO NOHIDE { void sys_exit(int rval); } exit sys_exit_args void +2 MNOPROTO POSIX { int fork(void); } +3 MNOPROTO POSIX { ssize_t read(int fd, void *buf, size_t nbyte); } +4 MNOPROTO POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); } +5 STD POSIX { int ia32_open(char *path, int flags, int mode); } ; XXX should be { int open(const char *path, int flags, ...); } ; but we're not ready for `const' or varargs. ; XXX man page says `mode_t mode'. -6 MSTD POSIX { int close(int fd); } -7 MSTD BSD { int wait4(int pid, int *status, int options, \ - struct rusage *rusage); } wait4 wait_args int -8 COMPAT BSD { int creat(char *path, int mode); } -9 STD POSIX { int link(char *path, char *link); } -10 STD POSIX { int unlink(char *path); } +6 MNOPROTO POSIX { int close(int fd); } +7 MSTD BSD { int ia32_wait4(int pid, int *status, int options, \ + struct rusage32 *rusage); } +8 OBSOL BSD old creat +9 NOPROTO POSIX { int link(char *path, char *link); } +10 NOPROTO POSIX { int unlink(char *path); } 11 OBSOL NOHIDE execv -12 STD POSIX { int chdir(char *path); } -13 STD BSD { int fchdir(int fd); } -14 STD POSIX { int mknod(char *path, int mode, int dev); } -15 STD POSIX { int chmod(char *path, int mode); } -16 STD POSIX { int chown(char *path, int uid, int gid); } -17 MSTD BSD { int obreak(char *nsize); } break obreak_args int -18 STD BSD { int getfsstat(struct statfs *buf, long bufsize, \ - int flags); } -19 COMPAT POSIX { long lseek(int fd, long offset, int whence); } -20 MSTD POSIX { pid_t getpid(void); } -21 STD BSD { int mount(char *type, char *path, int flags, \ +12 NOPROTO POSIX { int chdir(char *path); } +13 NOPROTO BSD { int fchdir(int fd); } +14 NOPROTO POSIX { int mknod(char *path, int mode, int dev); } +15 NOPROTO POSIX { int chmod(char *path, int mode); } +16 NOPROTO POSIX { int chown(char *path, int uid, int gid); } +17 MNOPROTO BSD { int obreak(char *nsize); } break obreak_args int +18 STD BSD { int ia32_getfsstat(struct statfs32 *buf, \ + long bufsize, int flags); } +19 OBSOL POSIX olseek +20 MNOPROTO POSIX { pid_t getpid(void); } +21 NOPROTO BSD { int mount(char *type, char *path, int flags, \ caddr_t data); } ; XXX `path' should have type `const char *' but we're not ready for that. -22 STD BSD { int unmount(char *path, int flags); } -23 MSTD POSIX { int setuid(uid_t uid); } -24 MSTD POSIX { uid_t getuid(void); } -25 MSTD POSIX { uid_t geteuid(void); } -26 STD BSD { int ptrace(int req, pid_t pid, caddr_t addr, \ +22 NOPROTO BSD { int unmount(char *path, int flags); } +23 MNOPROTO POSIX { int setuid(uid_t uid); } +24 MNOPROTO POSIX { uid_t getuid(void); } +25 MNOPROTO POSIX { uid_t geteuid(void); } +26 NOPROTO BSD { int ptrace(int req, pid_t pid, caddr_t addr, \ int data); } -27 MSTD BSD { int recvmsg(int s, struct msghdr *msg, int flags); } -28 MSTD BSD { int sendmsg(int s, caddr_t msg, int flags); } -29 MSTD BSD { int recvfrom(int s, caddr_t buf, size_t len, \ +27 UNIMPL BSD recvmsg +28 MNOPROTO BSD { int sendmsg(int s, caddr_t msg, int flags); } +29 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \ int flags, caddr_t from, int *fromlenaddr); } -30 MSTD BSD { int accept(int s, caddr_t name, int *anamelen); } -31 MSTD BSD { int getpeername(int fdes, caddr_t asa, int *alen); } -32 MSTD BSD { int getsockname(int fdes, caddr_t asa, int *alen); } -33 STD POSIX { int access(char *path, int flags); } -34 STD BSD { int chflags(char *path, int flags); } -35 STD BSD { int fchflags(int fd, int flags); } -36 STD BSD { int sync(void); } -37 MSTD POSIX { int kill(int pid, int signum); } -38 COMPAT POSIX { int stat(char *path, struct ostat *ub); } -39 MSTD POSIX { pid_t getppid(void); } -40 COMPAT POSIX { int lstat(char *path, struct ostat *ub); } -41 STD POSIX { int dup(u_int fd); } -42 STD POSIX { int pipe(void); } -43 MSTD POSIX { gid_t getegid(void); } -44 MSTD BSD { int profil(caddr_t samples, size_t size, \ +30 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } +31 MNOPROTO BSD { int getpeername(int fdes, caddr_t asa, int *alen); } +32 MNOPROTO BSD { int getsockname(int fdes, caddr_t asa, int *alen); } +33 STD POSIX { int ia32_access(char *path, int flags); } +34 STD BSD { int ia32_chflags(char *path, int flags); } +35 NOPROTO BSD { int fchflags(int fd, int flags); } +36 NOPROTO BSD { int sync(void); } +37 MNOPROTO POSIX { int kill(int pid, int signum); } +38 UNIMPL POSIX ostat +39 MNOPROTO POSIX { pid_t getppid(void); } +40 UNIMPL POSIX olstat +41 NOPROTO POSIX { int dup(u_int fd); } +42 NOPROTO POSIX { int pipe(void); } +43 MNOPROTO POSIX { gid_t getegid(void); } +44 MNOPROTO BSD { int profil(caddr_t samples, size_t size, \ size_t offset, u_int scale); } -45 STD BSD { int ktrace(const char *fname, int ops, int facs, \ +45 NOPROTO BSD { int ktrace(const char *fname, int ops, int facs, \ int pid); } -46 MCOMPAT POSIX { int sigaction(int signum, struct osigaction *nsa, \ - struct osigaction *osa); } -47 MSTD POSIX { gid_t getgid(void); } -48 MCOMPAT POSIX { int sigprocmask(int how, osigset_t mask); } -; XXX note nonstandard (bogus) calling convention - the libc stub passes -; us the mask, not a pointer to it, and we return the old mask as the -; (int) return value. -49 MSTD BSD { int getlogin(char *namebuf, u_int namelen); } -50 MSTD BSD { int setlogin(char *namebuf); } -51 MSTD BSD { int acct(char *path); } -52 MCOMPAT POSIX { int sigpending(void); } -53 MSTD BSD { int sigaltstack(stack_t *ss, stack_t *oss); } -54 MSTD POSIX { int ioctl(int fd, u_long com, caddr_t data); } -55 MSTD BSD { int reboot(int opt); } -56 STD POSIX { int revoke(char *path); } -57 STD POSIX { int symlink(char *path, char *link); } -58 STD POSIX { int readlink(char *path, char *buf, int count); } -59 MSTD POSIX { int execve(char *fname, char **argv, char **envv); } -60 MSTD POSIX { int umask(int newmask); } umask umask_args int -61 STD BSD { int chroot(char *path); } -62 MCOMPAT POSIX { int fstat(int fd, struct ostat *sb); } -63 MCOMPAT BSD { int getkerninfo(int op, char *where, size_t *size, \ - int arg); } getkerninfo getkerninfo_args int -64 MCOMPAT BSD { int getpagesize(void); } \ - getpagesize getpagesize_args int -65 STD BSD { int msync(void *addr, size_t len, int flags); } -66 MSTD BSD { int vfork(void); } +46 UNIMPL POSIX osigaction +47 MNOPROTO POSIX { gid_t getgid(void); } +48 UNIMPL POSIX osigprocmask +49 MNOPROTO BSD { int getlogin(char *namebuf, u_int namelen); } +50 MNOPROTO BSD { int setlogin(char *namebuf); } +51 MNOPROTO BSD { int acct(char *path); } +52 MNOPROTO POSIX { int sigpending(void); } +53 STD BSD { int ia32_sigaltstack(struct sigaltstack32 *ss, struct sigaltstack32 *oss); } +54 MNOPROTO POSIX { int ioctl(int fd, u_long com, caddr_t data); } +55 MNOPROTO BSD { int reboot(int opt); } +56 NOPROTO POSIX { int revoke(char *path); } +57 NOPROTO POSIX { int symlink(char *path, char *link); } +58 NOPROTO POSIX { int readlink(char *path, char *buf, int count); } +59 STD POSIX { int ia32_execve(char *fname, u_int32_t *argv, u_int32_t *envv); } +60 MNOPROTO POSIX { int umask(int newmask); } umask umask_args int +61 NOPROTO BSD { int chroot(char *path); } +62 OBSOL POSIX ofstat +63 OBSOL BSD ogetkerninfo +64 OBSOL BSD ogetpagesize +65 OBSOL BSD omsync +66 OBSOL BSD ovfork 67 OBSOL NOHIDE vread 68 OBSOL NOHIDE vwrite -69 MSTD BSD { int sbrk(int incr); } -70 MSTD BSD { int sstk(int incr); } -71 MCOMPAT BSD { int mmap(void *addr, int len, int prot, \ - int flags, int fd, long pos); } -72 MSTD BSD { int ovadvise(int anom); } vadvise ovadvise_args int -73 MSTD BSD { int munmap(void *addr, size_t len); } -74 MSTD BSD { int mprotect(const void *addr, size_t len, int prot); } -75 MSTD BSD { int madvise(void *addr, size_t len, int behav); } +69 MNOPROTO BSD { int sbrk(int incr); } +70 MNOPROTO BSD { int sstk(int incr); } +71 OBSOL BSD ommap +72 MNOPROTO BSD { int ovadvise(int anom); } vadvise ovadvise_args int +73 MNOPROTO BSD { int munmap(void *addr, size_t len); } +74 MNOPROTO BSD { int mprotect(const void *addr, size_t len, int prot); } +75 MNOPROTO BSD { int madvise(void *addr, size_t len, int behav); } 76 OBSOL NOHIDE vhangup 77 OBSOL NOHIDE vlimit -78 MSTD BSD { int mincore(const void *addr, size_t len, \ +78 MNOPROTO BSD { int mincore(const void *addr, size_t len, \ char *vec); } -79 MSTD POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); } -80 MSTD POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); } -81 MSTD POSIX { int getpgrp(void); } -82 MSTD POSIX { int setpgid(int pid, int pgid); } -83 MSTD BSD { int setitimer(u_int which, struct itimerval *itv, \ - struct itimerval *oitv); } -84 MCOMPAT BSD { int wait(void); } -85 MSTD BSD { int swapon(char *name); } -86 MSTD BSD { int getitimer(u_int which, struct itimerval *itv); } -87 MCOMPAT BSD { int gethostname(char *hostname, u_int len); } \ - gethostname gethostname_args int -88 MCOMPAT BSD { int sethostname(char *hostname, u_int len); } \ - sethostname sethostname_args int -89 MSTD BSD { int getdtablesize(void); } -90 MSTD POSIX { int dup2(u_int from, u_int to); } +79 MNOPROTO POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); } +80 MNOPROTO POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); } +81 MNOPROTO POSIX { int getpgrp(void); } +82 MNOPROTO POSIX { int setpgid(int pid, int pgid); } +83 STD BSD { int ia32_setitimer(u_int which, \ + struct itimerval32 *itv, \ + struct itimerval32 *oitv); } +84 OBSOL BSD owait +85 OBSOL BSD oswapon +86 OBSOL BSD ogetitimer +87 OBSOL BSD ogethostname +88 OBSOL BSD osethostname +89 MNOPROTO BSD { int getdtablesize(void); } +90 MNOPROTO POSIX { int dup2(u_int from, u_int to); } 91 UNIMPL BSD getdopt -92 MSTD POSIX { int fcntl(int fd, int cmd, long arg); } +92 MNOPROTO POSIX { int fcntl(int fd, int cmd, long arg); } ; XXX should be { int fcntl(int fd, int cmd, ...); } ; but we're not ready for varargs. ; XXX man page says `int arg' too. -93 MSTD BSD { int select(int nd, fd_set *in, fd_set *ou, \ - fd_set *ex, struct timeval *tv); } +93 STD BSD { int ia32_select(int nd, fd_set *in, fd_set *ou, \ + fd_set *ex, struct timeval32 *tv); } +; XXX need to override for big-endian - little-endian should work fine. 94 UNIMPL BSD setdopt -95 STD POSIX { int fsync(int fd); } -96 MSTD BSD { int setpriority(int which, int who, int prio); } -97 MSTD BSD { int socket(int domain, int type, int protocol); } -98 MSTD BSD { int connect(int s, caddr_t name, int namelen); } -99 MCPT_NOA BSD { int accept(int s, caddr_t name, int *anamelen); } \ +95 NOPROTO POSIX { int fsync(int fd); } +96 MNOPROTO BSD { int setpriority(int which, int who, int prio); } +97 MNOPROTO BSD { int socket(int domain, int type, int protocol); } +98 MNOPROTO BSD { int connect(int s, caddr_t name, int namelen); } +99 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } \ accept accept_args int -100 MSTD BSD { int getpriority(int which, int who); } -101 MCOMPAT BSD { int send(int s, caddr_t buf, int len, int flags); } -102 MCOMPAT BSD { int recv(int s, caddr_t buf, int len, int flags); } -103 STD BSD { int osigreturn(struct osigcontext *sigcntxp); } -104 MSTD BSD { int bind(int s, caddr_t name, int namelen); } -105 MSTD BSD { int setsockopt(int s, int level, int name, \ +100 MNOPROTO BSD { int getpriority(int which, int who); } +101 OBSOL BSD osend +102 OBSOL BSD orecv +103 OBSOL BSD osigreturn +104 MNOPROTO BSD { int bind(int s, caddr_t name, int namelen); } +105 MNOPROTO BSD { int setsockopt(int s, int level, int name, \ caddr_t val, int valsize); } -106 MSTD BSD { int listen(int s, int backlog); } +106 MNOPROTO BSD { int listen(int s, int backlog); } 107 OBSOL NOHIDE vtimes -108 MCOMPAT BSD { int sigvec(int signum, struct sigvec *nsv, \ - struct sigvec *osv); } -109 MCOMPAT BSD { int sigblock(int mask); } -110 MCOMPAT BSD { int sigsetmask(int mask); } -111 MCOMPAT POSIX { int sigsuspend(osigset_t mask); } -; XXX note nonstandard (bogus) calling convention - the libc stub passes -; us the mask, not a pointer to it. -112 MCOMPAT BSD { int sigstack(struct sigstack *nss, \ - struct sigstack *oss); } -113 MCOMPAT BSD { int recvmsg(int s, struct omsghdr *msg, int flags); } -114 MCOMPAT BSD { int sendmsg(int s, caddr_t msg, int flags); } +108 OBSOL BSD osigvec +109 OBSOL BSD osigblock +110 OBSOL BSD osigsetmask +111 OBSOL POSIX osigsuspend +112 OBSOL BSD osigstack +113 OBSOL BSD orecvmsg +114 OBSOL BSD osendmsg 115 OBSOL NOHIDE vtrace -116 MSTD BSD { int gettimeofday(struct timeval *tp, \ +116 STD BSD { int ia32_gettimeofday(struct timeval32 *tp, \ struct timezone *tzp); } -117 MSTD BSD { int getrusage(int who, struct rusage *rusage); } -118 MSTD BSD { int getsockopt(int s, int level, int name, \ +117 STD BSD { int ia32_getrusage(int who, struct rusage32 *rusage); } +118 MNOPROTO BSD { int getsockopt(int s, int level, int name, \ caddr_t val, int *avalsize); } 119 UNIMPL NOHIDE resuba (BSD/OS 2.x) -120 MSTD BSD { int readv(int fd, struct iovec *iovp, u_int iovcnt); } -121 MSTD BSD { int writev(int fd, struct iovec *iovp, \ +120 STD BSD { int ia32_readv(int fd, struct iovec32 *iovp, u_int iovcnt); } +121 STD BSD { int ia32_writev(int fd, struct iovec32 *iovp, \ u_int iovcnt); } -122 MSTD BSD { int settimeofday(struct timeval *tv, \ +122 STD BSD { int ia32_settimeofday(struct timeval32 *tv, \ struct timezone *tzp); } -123 STD BSD { int fchown(int fd, int uid, int gid); } -124 STD BSD { int fchmod(int fd, int mode); } -125 MCPT_NOA BSD { int recvfrom(int s, caddr_t buf, size_t len, \ +123 NOPROTO BSD { int fchown(int fd, int uid, int gid); } +124 NOPROTO BSD { int fchmod(int fd, int mode); } +125 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \ int flags, caddr_t from, int *fromlenaddr); } \ recvfrom recvfrom_args int -126 MSTD BSD { int setreuid(int ruid, int euid); } -127 MSTD BSD { int setregid(int rgid, int egid); } -128 STD POSIX { int rename(char *from, char *to); } -129 COMPAT BSD { int truncate(char *path, long length); } -130 COMPAT BSD { int ftruncate(int fd, long length); } -131 MSTD BSD { int flock(int fd, int how); } -132 STD POSIX { int mkfifo(char *path, int mode); } -133 MSTD BSD { int sendto(int s, caddr_t buf, size_t len, \ +126 MNOPROTO BSD { int setreuid(int ruid, int euid); } +127 MNOPROTO BSD { int setregid(int rgid, int egid); } +128 NOPROTO POSIX { int rename(char *from, char *to); } +129 OBSOL BSD otruncate +130 OBSOL BSD ftruncate +131 MNOPROTO BSD { int flock(int fd, int how); } +132 NOPROTO POSIX { int mkfifo(char *path, int mode); } +133 MNOPROTO BSD { int sendto(int s, caddr_t buf, size_t len, \ int flags, caddr_t to, int tolen); } -134 MSTD BSD { int shutdown(int s, int how); } -135 MSTD BSD { int socketpair(int domain, int type, int protocol, \ +134 MNOPROTO BSD { int shutdown(int s, int how); } +135 MNOPROTO BSD { int socketpair(int domain, int type, int protocol, \ int *rsv); } -136 STD POSIX { int mkdir(char *path, int mode); } -137 STD POSIX { int rmdir(char *path); } -138 STD BSD { int utimes(char *path, struct timeval *tptr); } +136 NOPROTO POSIX { int mkdir(char *path, int mode); } +137 NOPROTO POSIX { int rmdir(char *path); } +138 STD BSD { int ia32_utimes(char *path, \ + struct timeval32 *tptr); } 139 OBSOL NOHIDE 4.2 sigreturn -140 MSTD BSD { int adjtime(struct timeval *delta, \ - struct timeval *olddelta); } -141 MCOMPAT BSD { int getpeername(int fdes, caddr_t asa, int *alen); } -142 MCOMPAT BSD { long gethostid(void); } -143 MCOMPAT BSD { int sethostid(long hostid); } -144 MCOMPAT BSD { int getrlimit(u_int which, struct orlimit *rlp); } -145 MCOMPAT BSD { int setrlimit(u_int which, struct orlimit *rlp); } -146 MCOMPAT BSD { int killpg(int pgid, int signum); } -147 MSTD POSIX { int setsid(void); } -148 STD BSD { int quotactl(char *path, int cmd, int uid, \ +140 STD BSD { int ia32_adjtime(struct timeval32 *delta, \ + struct timeval32 *olddelta); } +141 OBSOL BSD ogetpeername +142 OBSOL BSD ogethostid +143 OBSOL BSD sethostid +144 OBSOL BSD getrlimit +145 OBSOL BSD setrlimit +146 OBSOL BSD killpg +147 MNOPROTO POSIX { int setsid(void); } +148 NOPROTO BSD { int quotactl(char *path, int cmd, int uid, \ caddr_t arg); } -149 MCOMPAT BSD { int quota(void); } -150 MCPT_NOA BSD { int getsockname(int fdec, caddr_t asa, int *alen); }\ - getsockname getsockname_args int +149 OBSOL BSD oquota +150 OBSOL BSD ogetsockname ; Syscalls 151-180 inclusive are reserved for vendor-specific ; system calls. (This includes various calls added for compatibity ; with other Unix variants.) ; Some of these calls are now supported by BSD... 151 UNIMPL NOHIDE sem_lock (BSD/OS 2.x) 152 UNIMPL NOHIDE sem_wakeup (BSD/OS 2.x) 153 UNIMPL NOHIDE asyncdaemon (BSD/OS 2.x) 154 UNIMPL NOHIDE nosys ; 155 is initialized by the NFS code, if present. -155 MNOIMPL BSD { int nfssvc(int flag, caddr_t argp); } -156 COMPAT BSD { int getdirentries(int fd, char *buf, u_int count, \ +155 UNIMPL NOHIDE nfssvc +156 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \ long *basep); } -157 STD BSD { int statfs(char *path, struct statfs *buf); } -158 STD BSD { int fstatfs(int fd, struct statfs *buf); } +157 STD BSD { int ia32_statfs(char *path, struct statfs32 *buf); } +158 STD BSD { int ia32_fstatfs(int fd, struct statfs32 *buf); } 159 UNIMPL NOHIDE nosys 160 UNIMPL NOHIDE nosys -161 STD BSD { int getfh(char *fname, struct fhandle *fhp); } -162 MSTD BSD { int getdomainname(char *domainname, int len); } -163 MSTD BSD { int setdomainname(char *domainname, int len); } -164 MSTD BSD { int uname(struct utsname *name); } -165 STD BSD { int sysarch(int op, char *parms); } -166 MSTD BSD { int rtprio(int function, pid_t pid, \ +161 NOPROTO BSD { int getfh(char *fname, struct fhandle *fhp); } +162 MNOPROTO BSD { int getdomainname(char *domainname, int len); } +163 MNOPROTO BSD { int setdomainname(char *domainname, int len); } +164 MNOPROTO BSD { int uname(struct utsname *name); } +165 NOPROTO BSD { int sysarch(int op, char *parms); } +166 MNOPROTO BSD { int rtprio(int function, pid_t pid, \ struct rtprio *rtp); } 167 UNIMPL NOHIDE nosys 168 UNIMPL NOHIDE nosys -; 169 is initialized by the SYSVSEM code if present or loaded -169 MNOSTD BSD { int semsys(int which, int a2, int a3, int a4, \ +169 STD BSD { int ia32_semsys(int which, int a2, int a3, int a4, \ int a5); } -; 169 is initialized by the SYSVMSG code if present or loaded -; XXX should be { int semsys(int which, ...); } -170 MNOSTD BSD { int msgsys(int which, int a2, int a3, int a4, \ +170 STD BSD { int ia32_msgsys(int which, int a2, int a3, int a4, \ int a5, int a6); } -; 169 is initialized by the SYSVSHM code if present or loaded -; XXX should be { int msgsys(int which, ...); } -171 MNOSTD BSD { int shmsys(int which, int a2, int a3, int a4); } -; XXX should be { int shmsys(int which, ...); } +171 STD BSD { int ia32_shmsys(int which, int a2, int a3, int a4); } 172 UNIMPL NOHIDE nosys -173 MSTD POSIX { ssize_t pread(int fd, void *buf, size_t nbyte, \ - int pad, off_t offset); } -174 MSTD POSIX { ssize_t pwrite(int fd, const void *buf, \ - size_t nbyte, int pad, off_t offset); } +173 STD POSIX { ssize_t ia32_pread(int fd, void *buf, size_t nbyte, \ + int pad, u_int32_t offsetlo, u_int32_t offsethi); } +; XXX note - bigendian is different +174 STD POSIX { ssize_t ia32_pwrite(int fd, const void *buf, \ + size_t nbyte, int pad, u_int32_t offsetlo, \ + u_int32_t offsethi); } +; XXX note - bigendian is different 175 UNIMPL NOHIDE nosys -176 MSTD BSD { int ntp_adjtime(struct timex *tp); } +176 MNOPROTO BSD { int ntp_adjtime(struct timex *tp); } 177 UNIMPL NOHIDE sfork (BSD/OS 2.x) 178 UNIMPL NOHIDE getdescriptor (BSD/OS 2.x) 179 UNIMPL NOHIDE setdescriptor (BSD/OS 2.x) 180 UNIMPL NOHIDE nosys ; Syscalls 181-199 are used by/reserved for BSD -181 MSTD POSIX { int setgid(gid_t gid); } -182 MSTD BSD { int setegid(gid_t egid); } -183 MSTD BSD { int seteuid(uid_t euid); } +181 MNOPROTO POSIX { int setgid(gid_t gid); } +182 MNOPROTO BSD { int setegid(gid_t egid); } +183 MNOPROTO BSD { int seteuid(uid_t euid); } 184 UNIMPL BSD lfs_bmapv 185 UNIMPL BSD lfs_markv 186 UNIMPL BSD lfs_segclean 187 UNIMPL BSD lfs_segwait -188 STD POSIX { int stat(char *path, struct stat *ub); } -189 MSTD POSIX { int fstat(int fd, struct stat *sb); } -190 STD POSIX { int lstat(char *path, struct stat *ub); } -191 STD POSIX { int pathconf(char *path, int name); } -192 MSTD POSIX { int fpathconf(int fd, int name); } +188 STD POSIX { int ia32_stat(char *path, struct stat32 *ub); } +189 STD POSIX { int ia32_fstat(int fd, struct stat32 *ub); } +190 STD POSIX { int ia32_lstat(char *path, struct stat32 *ub); } +191 NOPROTO POSIX { int pathconf(char *path, int name); } +192 MNOPROTO POSIX { int fpathconf(int fd, int name); } 193 UNIMPL NOHIDE nosys -194 MSTD BSD { int getrlimit(u_int which, \ +194 MNOPROTO BSD { int getrlimit(u_int which, \ struct rlimit *rlp); } \ getrlimit __getrlimit_args int -195 MSTD BSD { int setrlimit(u_int which, \ +195 MNOPROTO BSD { int setrlimit(u_int which, \ struct rlimit *rlp); } \ setrlimit __setrlimit_args int -196 STD BSD { int getdirentries(int fd, char *buf, u_int count, \ +196 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \ long *basep); } -197 MSTD BSD { caddr_t mmap(caddr_t addr, size_t len, int prot, \ - int flags, int fd, int pad, off_t pos); } -198 STD NOHIDE { int nosys(void); } __syscall __syscall_args int -199 STD POSIX { off_t lseek(int fd, int pad, off_t offset, \ +197 STD BSD { caddr_t ia32_mmap(caddr_t addr, size_t len, \ + int prot, int flags, int fd, int pad, \ + u_int32_t poslo, u_int32_t poshi); } +198 NOPROTO NOHIDE { int nosys(void); } __syscall __syscall_args int +; XXX note - bigendian is different +199 STD POSIX { off_t ia32_lseek(int fd, int pad, \ + u_int32_t offsetlo, u_int32_t offsethi, \ int whence); } -200 STD BSD { int truncate(char *path, int pad, off_t length); } -201 STD BSD { int ftruncate(int fd, int pad, off_t length); } -202 MSTD BSD { int __sysctl(int *name, u_int namelen, void *old, \ - size_t *oldlenp, void *new, size_t newlen); } \ - __sysctl sysctl_args int -; properly, __sysctl should be a NOHIDE, but making an exception -; here allows to avoid one in libc/sys/Makefile.inc. -203 MSTD BSD { int mlock(const void *addr, size_t len); } -204 MSTD BSD { int munlock(const void *addr, size_t len); } -205 STD BSD { int undelete(char *path); } -206 STD BSD { int futimes(int fd, struct timeval *tptr); } -207 MSTD BSD { int getpgid(pid_t pid); } +; XXX note - bigendian is different +200 STD BSD { int ia32_truncate(char *path, int pad, \ + u_int32_t lengthlo, u_int32_t lengthhi); } +; XXX note - bigendian is different +201 STD BSD { int ia32_ftruncate(int fd, int pad, \ + u_int32_t lengthlo, u_int32_t lengthhi); } +202 MSTD BSD { int ia32_sysctl(int *name, u_int namelen, \ + void *old, u_int32_t *oldlenp, void *new, \ + u_int32_t newlen); } +203 MNOPROTO BSD { int mlock(const void *addr, size_t len); } +204 MNOPROTO BSD { int munlock(const void *addr, size_t len); } +205 NOPROTO BSD { int undelete(char *path); } +206 NOPROTO BSD { int futimes(int fd, struct timeval *tptr); } +207 MNOPROTO BSD { int getpgid(pid_t pid); } 208 UNIMPL NOHIDE newreboot (NetBSD) -209 MSTD BSD { int poll(struct pollfd *fds, u_int nfds, \ +209 MNOPROTO BSD { int poll(struct pollfd *fds, u_int nfds, \ int timeout); } ; ; The following are reserved for loadable syscalls ; -210 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -211 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -212 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -213 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -214 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -215 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -216 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -217 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -218 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -219 NODEF NOHIDE lkmnosys lkmnosys nosys_args int +210 UNIMPL NOHIDE +211 UNIMPL NOHIDE +212 UNIMPL NOHIDE +213 UNIMPL NOHIDE +214 UNIMPL NOHIDE +215 UNIMPL NOHIDE +216 UNIMPL NOHIDE +217 UNIMPL NOHIDE +218 UNIMPL NOHIDE +219 UNIMPL NOHIDE ; ; The following were introduced with NetBSD/4.4Lite-2 ; They are initialized by thier respective modules/sysinits -220 MNOSTD BSD { int __semctl(int semid, int semnum, int cmd, \ +220 MNOPROTO BSD { int __semctl(int semid, int semnum, int cmd, \ union semun *arg); } -221 MNOSTD BSD { int semget(key_t key, int nsems, int semflg); } -222 MNOSTD BSD { int semop(int semid, struct sembuf *sops, \ +221 MNOPROTO BSD { int semget(key_t key, int nsems, int semflg); } +222 MNOPROTO BSD { int semop(int semid, struct sembuf *sops, \ u_int nsops); } 223 UNIMPL NOHIDE semconfig -224 MNOSTD BSD { int msgctl(int msqid, int cmd, \ +224 MNOPROTO BSD { int msgctl(int msqid, int cmd, \ struct msqid_ds *buf); } -225 MNOSTD BSD { int msgget(key_t key, int msgflg); } -226 MNOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ +225 MNOPROTO BSD { int msgget(key_t key, int msgflg); } +226 MNOPROTO BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ int msgflg); } -227 MNOSTD BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \ +227 MNOPROTO BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \ long msgtyp, int msgflg); } -228 MNOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); } -229 MNOSTD BSD { int shmctl(int shmid, int cmd, \ +228 MNOPROTO BSD { int shmat(int shmid, void *shmaddr, int shmflg); } +229 MNOPROTO BSD { int shmctl(int shmid, int cmd, \ struct shmid_ds *buf); } -230 MNOSTD BSD { int shmdt(void *shmaddr); } -231 MNOSTD BSD { int shmget(key_t key, int size, int shmflg); } +230 MNOPROTO BSD { int shmdt(void *shmaddr); } +231 MNOPROTO BSD { int shmget(key_t key, int size, int shmflg); } ; -232 MSTD POSIX { int clock_gettime(clockid_t clock_id, \ +232 MNOPROTO POSIX { int clock_gettime(clockid_t clock_id, \ struct timespec *tp); } -233 MSTD POSIX { int clock_settime(clockid_t clock_id, \ +233 MNOPROTO POSIX { int clock_settime(clockid_t clock_id, \ const struct timespec *tp); } -234 MSTD POSIX { int clock_getres(clockid_t clock_id, \ +234 MNOPROTO POSIX { int clock_getres(clockid_t clock_id, \ struct timespec *tp); } 235 UNIMPL NOHIDE timer_create 236 UNIMPL NOHIDE timer_delete 237 UNIMPL NOHIDE timer_settime 238 UNIMPL NOHIDE timer_gettime 239 UNIMPL NOHIDE timer_getoverrun -240 MSTD POSIX { int nanosleep(const struct timespec *rqtp, \ +240 MNOPROTO POSIX { int nanosleep(const struct timespec *rqtp, \ struct timespec *rmtp); } 241 UNIMPL NOHIDE nosys 242 UNIMPL NOHIDE nosys 243 UNIMPL NOHIDE nosys 244 UNIMPL NOHIDE nosys 245 UNIMPL NOHIDE nosys 246 UNIMPL NOHIDE nosys 247 UNIMPL NOHIDE nosys 248 UNIMPL NOHIDE nosys 249 UNIMPL NOHIDE nosys ; syscall numbers initially used in OpenBSD -250 MSTD BSD { int minherit(void *addr, size_t len, int inherit); } -251 MSTD BSD { int rfork(int flags); } -252 MSTD BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \ +250 MNOPROTO BSD { int minherit(void *addr, size_t len, int inherit); } +251 MNOPROTO BSD { int rfork(int flags); } +252 MNOPROTO BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \ int timeout); } -253 STD BSD { int issetugid(void); } -254 STD BSD { int lchown(char *path, int uid, int gid); } +253 NOPROTO BSD { int issetugid(void); } +254 NOPROTO BSD { int lchown(char *path, int uid, int gid); } 255 UNIMPL NOHIDE nosys 256 UNIMPL NOHIDE nosys 257 UNIMPL NOHIDE nosys 258 UNIMPL NOHIDE nosys 259 UNIMPL NOHIDE nosys 260 UNIMPL NOHIDE nosys 261 UNIMPL NOHIDE nosys 262 UNIMPL NOHIDE nosys 263 UNIMPL NOHIDE nosys 264 UNIMPL NOHIDE nosys 265 UNIMPL NOHIDE nosys 266 UNIMPL NOHIDE nosys 267 UNIMPL NOHIDE nosys 268 UNIMPL NOHIDE nosys 269 UNIMPL NOHIDE nosys 270 UNIMPL NOHIDE nosys 271 UNIMPL NOHIDE nosys -272 STD BSD { int getdents(int fd, char *buf, size_t count); } +272 NOPROTO BSD { int getdents(int fd, char *buf, size_t count); } 273 UNIMPL NOHIDE nosys -274 STD BSD { int lchmod(char *path, mode_t mode); } +274 NOPROTO BSD { int lchmod(char *path, mode_t mode); } 275 NOPROTO BSD { int lchown(char *path, uid_t uid, gid_t gid); } netbsd_lchown lchown_args int -276 STD BSD { int lutimes(char *path, struct timeval *tptr); } +276 NOPROTO BSD { int lutimes(char *path, struct timeval *tptr); } 277 MNOPROTO BSD { int msync(void *addr, size_t len, int flags); } netbsd_msync msync_args int -278 STD BSD { int nstat(char *path, struct nstat *ub); } -279 MSTD BSD { int nfstat(int fd, struct nstat *sb); } -280 STD BSD { int nlstat(char *path, struct nstat *ub); } +278 NOPROTO BSD { int nstat(char *path, struct nstat *ub); } +279 MNOPROTO BSD { int nfstat(int fd, struct nstat *sb); } +280 NOPROTO BSD { int nlstat(char *path, struct nstat *ub); } 281 UNIMPL NOHIDE nosys 282 UNIMPL NOHIDE nosys 283 UNIMPL NOHIDE nosys 284 UNIMPL NOHIDE nosys 285 UNIMPL NOHIDE nosys 286 UNIMPL NOHIDE nosys 287 UNIMPL NOHIDE nosys 288 UNIMPL NOHIDE nosys 289 UNIMPL NOHIDE nosys 290 UNIMPL NOHIDE nosys 291 UNIMPL NOHIDE nosys 292 UNIMPL NOHIDE nosys 293 UNIMPL NOHIDE nosys 294 UNIMPL NOHIDE nosys 295 UNIMPL NOHIDE nosys 296 UNIMPL NOHIDE nosys ; XXX 297 is 300 in NetBSD -297 STD BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } -298 STD BSD { int fhopen(const struct fhandle *u_fhp, int flags); } -299 STD BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } +297 NOPROTO BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } +298 NOPROTO BSD { int fhopen(const struct fhandle *u_fhp, int flags); } +299 NOPROTO BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } ; syscall numbers for FreeBSD -300 MSTD BSD { int modnext(int modid); } -301 MSTD BSD { int modstat(int modid, struct module_stat* stat); } -302 MSTD BSD { int modfnext(int modid); } -303 MSTD BSD { int modfind(const char *name); } -304 MSTD BSD { int kldload(const char *file); } -305 MSTD BSD { int kldunload(int fileid); } -306 MSTD BSD { int kldfind(const char *file); } -307 MSTD BSD { int kldnext(int fileid); } -308 MSTD BSD { int kldstat(int fileid, struct kld_file_stat* stat); } -309 MSTD BSD { int kldfirstmod(int fileid); } -310 MSTD BSD { int getsid(pid_t pid); } -311 MSTD BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } -312 MSTD BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } +300 MNOPROTO BSD { int modnext(int modid); } +301 MNOPROTO BSD { int modstat(int modid, struct module_stat* stat); } +302 MNOPROTO BSD { int modfnext(int modid); } +303 MNOPROTO BSD { int modfind(const char *name); } +304 MNOPROTO BSD { int kldload(const char *file); } +305 MNOPROTO BSD { int kldunload(int fileid); } +306 MNOPROTO BSD { int kldfind(const char *file); } +307 MNOPROTO BSD { int kldnext(int fileid); } +308 MNOPROTO BSD { int kldstat(int fileid, struct kld_file_stat* stat); } +309 MNOPROTO BSD { int kldfirstmod(int fileid); } +310 MNOPROTO BSD { int getsid(pid_t pid); } +311 MNOPROTO BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } +312 MNOPROTO BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } 313 OBSOL NOHIDE signanosleep -314 NOSTD BSD { int aio_return(struct aiocb *aiocbp); } -315 NOSTD BSD { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } -316 NOSTD BSD { int aio_cancel(int fd, struct aiocb *aiocbp); } -317 NOSTD BSD { int aio_error(struct aiocb *aiocbp); } -318 NOSTD BSD { int aio_read(struct aiocb *aiocbp); } -319 NOSTD BSD { int aio_write(struct aiocb *aiocbp); } -320 NOSTD BSD { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); } -321 MSTD BSD { int yield(void); } +314 UNIMPL NOHIDE aio_return +315 UNIMPL NOHIDE aio_suspend +316 UNIMPL NOHIDE aio_cancel +317 UNIMPL NOHIDE aio_error +318 UNIMPL NOHIDE aio_read +319 UNIMPL NOHIDE aio_write +320 UNIMPL NOHIDE lio_listio +321 MNOPROTO BSD { int yield(void); } 322 OBSOL NOHIDE thr_sleep 323 OBSOL NOHIDE thr_wakeup -324 MSTD BSD { int mlockall(int how); } -325 MSTD BSD { int munlockall(void); } -326 STD BSD { int __getcwd(u_char *buf, u_int buflen); } +324 MNOPROTO BSD { int mlockall(int how); } +325 MNOPROTO BSD { int munlockall(void); } +326 NOPROTO BSD { int __getcwd(u_char *buf, u_int buflen); } -327 MSTD POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); } -328 MSTD POSIX { int sched_getparam (pid_t pid, struct sched_param *param); } +327 MNOPROTO POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); } +328 MNOPROTO POSIX { int sched_getparam (pid_t pid, struct sched_param *param); } -329 MSTD POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } -330 MSTD POSIX { int sched_getscheduler (pid_t pid); } +329 MNOPROTO POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } +330 MNOPROTO POSIX { int sched_getscheduler (pid_t pid); } -331 MSTD POSIX { int sched_yield (void); } -332 MSTD POSIX { int sched_get_priority_max (int policy); } -333 MSTD POSIX { int sched_get_priority_min (int policy); } -334 MSTD POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); } -335 STD BSD { int utrace(const void *addr, size_t len); } -336 MSTD BSD { int sendfile(int fd, int s, off_t offset, size_t nbytes, \ - struct sf_hdtr *hdtr, off_t *sbytes, int flags); } -337 STD BSD { int kldsym(int fileid, int cmd, void *data); } -338 MSTD BSD { int jail(struct jail *jail); } +331 MNOPROTO POSIX { int sched_yield (void); } +332 MNOPROTO POSIX { int sched_get_priority_max (int policy); } +333 MNOPROTO POSIX { int sched_get_priority_min (int policy); } +334 MNOPROTO POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); } +335 NOPROTO BSD { int utrace(const void *addr, size_t len); } +; XXX note - bigendian is different +336 MSTD BSD { int ia32_sendfile(int fd, int s, u_int32_t offsetlo, \ + u_int32_t offsethi, size_t nbytes, \ + struct sf_hdtr *hdtr, off_t *sbytes, int flags); } +337 NOPROTO BSD { int kldsym(int fileid, int cmd, void *data); } +338 MNOPROTO BSD { int jail(struct jail *jail); } 339 UNIMPL BSD pioctl -340 MSTD POSIX { int sigprocmask(int how, const sigset_t *set, \ +340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \ sigset_t *oset); } -341 MSTD POSIX { int sigsuspend(const sigset_t *sigmask); } -342 MSTD POSIX { int sigaction(int sig, const struct sigaction *act, \ - struct sigaction *oact); } -343 MSTD POSIX { int sigpending(sigset_t *set); } -344 STD BSD { int sigreturn(const struct __ucontext *sigcntxp); } +341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); } +342 STD POSIX { int ia32_sigaction(int sig, \ + struct sigaction32 *act, \ + struct sigaction32 *oact); } +343 MNOPROTO POSIX { int sigpending(sigset_t *set); } +344 MNOPROTO BSD { int sigreturn(const struct __ucontext *sigcntxp); } 345 UNIMPL NOHIDE sigtimedwait 346 UNIMPL NOHIDE sigwaitinfo -347 MSTD BSD { int __acl_get_file(const char *path, \ +347 MNOPROTO BSD { int __acl_get_file(const char *path, \ acl_type_t type, struct acl *aclp); } -348 MSTD BSD { int __acl_set_file(const char *path, \ +348 MNOPROTO BSD { int __acl_set_file(const char *path, \ acl_type_t type, struct acl *aclp); } -349 MSTD BSD { int __acl_get_fd(int filedes, acl_type_t type, \ +349 MNOPROTO BSD { int __acl_get_fd(int filedes, acl_type_t type, \ struct acl *aclp); } -350 MSTD BSD { int __acl_set_fd(int filedes, acl_type_t type, \ +350 MNOPROTO BSD { int __acl_set_fd(int filedes, acl_type_t type, \ struct acl *aclp); } -351 MSTD BSD { int __acl_delete_file(const char *path, \ +351 MNOPROTO BSD { int __acl_delete_file(const char *path, \ acl_type_t type); } -352 MSTD BSD { int __acl_delete_fd(int filedes, acl_type_t type); } -353 MSTD BSD { int __acl_aclcheck_file(const char *path, \ +352 MNOPROTO BSD { int __acl_delete_fd(int filedes, acl_type_t type); } +353 MNOPROTO BSD { int __acl_aclcheck_file(const char *path, \ acl_type_t type, struct acl *aclp); } -354 MSTD BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \ +354 MNOPROTO BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \ struct acl *aclp); } -355 STD BSD { int extattrctl(const char *path, int cmd, \ +355 NOPROTO BSD { int extattrctl(const char *path, int cmd, \ const char *filename, int attrnamespace, \ const char *attrname); } -356 STD BSD { int extattr_set_file(const char *path, \ +356 NOPROTO BSD { int extattr_set_file(const char *path, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } -357 STD BSD { ssize_t extattr_get_file(const char *path, \ +357 NOPROTO BSD { ssize_t extattr_get_file(const char *path, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } -358 STD BSD { int extattr_delete_file(const char *path, \ +358 NOPROTO BSD { int extattr_delete_file(const char *path, \ int attrnamespace, const char *attrname); } -359 NOSTD BSD { int aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); } -360 MSTD BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } -361 MSTD BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } -362 MSTD BSD { int kqueue(void); } -363 MSTD BSD { int kevent(int fd, \ +359 UNIMPL NOHIDE aio_waitcomplete +360 MNOPROTO BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } +361 MNOPROTO BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } +362 MNOPROTO BSD { int kqueue(void); } +363 MNOPROTO BSD { int kevent(int fd, \ const struct kevent *changelist, int nchanges, \ struct kevent *eventlist, int nevents, \ const struct timespec *timeout); } -364 STD BSD { int __cap_get_proc(struct cap *cap_p); } -365 STD BSD { int __cap_set_proc(struct cap *cap_p); } -366 STD BSD { int __cap_get_fd(int fd, struct cap *cap_p); } -367 STD BSD { int __cap_get_file(const char *path_p, struct cap *cap_p); } -368 STD BSD { int __cap_set_fd(int fd, struct cap *cap_p); } -369 STD BSD { int __cap_set_file(const char *path_p, struct cap *cap_p); } -370 NODEF NOHIDE lkmressys lkmressys nosys_args int -371 STD BSD { int extattr_set_fd(int fd, int attrnamespace, \ +364 UNIMPL NOHIDE __cap_get_proc +365 UNIMPL NOHIDE __cap_set_proc +366 UNIMPL NOHIDE __cap_get_fd +367 UNIMPL NOHIDE __cap_get_file +368 UNIMPL NOHIDE __cap_set_fd +369 UNIMPL NOHIDE __cap_set_file +370 UNIMPL NOHIDE lkmressys +371 NOPROTO BSD { int extattr_set_fd(int fd, int attrnamespace, \ const char *attrname, void *data, \ size_t nbytes); } -372 STD BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \ +372 NOPROTO BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \ const char *attrname, void *data, size_t nbytes); } -373 STD BSD { int extattr_delete_fd(int fd, int attrnamespace, \ +373 NOPROTO BSD { int extattr_delete_fd(int fd, int attrnamespace, \ const char *attrname); } -374 MSTD BSD { int __setugid(int flag); } -375 NOIMPL BSD { int nfsclnt(int flag, caddr_t argp); } -376 STD BSD { int eaccess(char *path, int flags); } +374 MNOPROTO BSD { int __setugid(int flag); } +375 UNIMPL BSD nfsclnt +376 NOPROTO BSD { int eaccess(char *path, int flags); } 377 UNIMPL BSD afs_syscall -378 STD BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \ +378 NOPROTO BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \ int flags); } -379 STD BSD { int kse_exit(void); } -380 STD BSD { int kse_wakeup(void); } -381 STD BSD { int kse_new(struct kse_mailbox * mbx, \ +379 NOPROTO BSD { int kse_exit(void); } +380 NOPROTO BSD { int kse_wakeup(void); } +381 NOPROTO BSD { int kse_new(struct kse_mailbox * mbx, \ int new_grp_flag); } -382 STD BSD { int thread_wakeup(struct thread_mailbox *tmbx); } -383 STD BSD { int kse_yield(void); } +382 NOPROTO BSD { int thread_wakeup(struct thread_mailbox *tmbx); } +383 NOPROTO BSD { int kse_yield(void); } 384 UNIMPL BSD __mac_get_proc 385 UNIMPL BSD __mac_set_proc 386 UNIMPL BSD __mac_get_fd 387 UNIMPL BSD __mac_get_file 388 UNIMPL BSD __mac_set_fd 389 UNIMPL BSD __mac_set_file +390 NOPROTO BSD { int kenv(int what, const char *name, char *value, \ + int len); } +391 NOPROTO BSD { int lchflags(const char *path, int flags); } +392 NOPROTO BSD { int uuidgen(struct uuid *store, int count); } Index: head/sys/compat/freebsd32/freebsd32.h =================================================================== --- head/sys/compat/freebsd32/freebsd32.h (nonexistent) +++ head/sys/compat/freebsd32/freebsd32.h (revision 100384) @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2001 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IA64_IA32_IA32_H_ +#define _IA64_IA32_IA32_H_ + +#define PTRIN(v) (void *)(uintptr_t) (v) +#define PTROUT(v) (u_int32_t)(uintptr_t) (v) + +#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0) +#define PTRIN_CP(src,dst,fld) \ + do { (dst).fld = PTRIN((src).fld); } while (0) +#define PTROUT_CP(src,dst,fld) \ + do { (dst).fld = PTROUT((src).fld); } while (0) + +struct timeval32 { + int32_t tv_sec; + int32_t tv_usec; +}; +#define TV_CP(src,dst,fld) do { \ + CP((src).fld,(dst).fld,tv_sec); \ + CP((src).fld,(dst).fld,tv_usec); \ +} while (0); + +struct timespec32 { + u_int32_t tv_sec; + u_int32_t tv_nsec; +}; +#define TS_CP(src,dst,fld) do { \ + CP((src).fld,(dst).fld,tv_sec); \ + CP((src).fld,(dst).fld,tv_nsec); \ +} while (0); + +struct rusage32 { + struct timeval32 ru_utime; + struct timeval32 ru_stime; + int32_t ru_maxrss; + int32_t ru_ixrss; + int32_t ru_idrss; + int32_t ru_isrss; + int32_t ru_minflt; + int32_t ru_majflt; + int32_t ru_nswap; + int32_t ru_inblock; + int32_t ru_oublock; + int32_t ru_msgsnd; + int32_t ru_msgrcv; + int32_t ru_nsignals; + int32_t ru_nvcsw; + int32_t ru_nivcsw; +}; + +struct statfs32 { + int32_t f_spare2; + int32_t f_bsize; + int32_t f_iosize; + int32_t f_blocks; + int32_t f_bfree; + int32_t f_bavail; + int32_t f_files; + int32_t f_ffree; + fsid_t f_fsid; + uid_t f_owner; + int32_t f_type; + int32_t f_flags; + int32_t f_syncwrites; + int32_t f_asyncwrites; + char f_fstypename[MFSNAMELEN]; + char f_mntonname[MNAMELEN]; + int32_t f_syncreads; + int32_t f_asyncreads; + int16_t f_spares1; + char f_mntfromname[MNAMELEN]; + int16_t f_spares2; + int32_t f_spare[2]; +}; + +#endif /* !_IA64_IA32_IA32_H_ */ Property changes on: head/sys/compat/freebsd32/freebsd32.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- head/sys/compat/freebsd32/freebsd32_misc.c (nonexistent) +++ head/sys/compat/freebsd32/freebsd32_misc.c (revision 100384) @@ -0,0 +1,1339 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Must come after sys/malloc.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Must come after sys/selinfo.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static const char ia32_emul_path[] = "/compat/ia32"; +/* + * [ taken from the linux emulator ] + * Search an alternate path before passing pathname arguments on + * to system calls. Useful for keeping a separate 'emulation tree'. + * + * If cflag is set, we check if an attempt can be made to create + * the named file, i.e. we check if the directory it should + * be in exists. + */ +int +ia32_emul_find(td, sgp, prefix, path, pbuf, cflag) + struct thread *td; + caddr_t *sgp; /* Pointer to stackgap memory */ + const char *prefix; + char *path; + char **pbuf; + int cflag; +{ + int error; + size_t len, sz; + char *buf, *cp, *ptr; + struct ucred *ucred; + struct nameidata nd; + struct nameidata ndroot; + struct vattr vat; + struct vattr vatroot; + + buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + *pbuf = path; + + for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) + continue; + + sz = MAXPATHLEN - (ptr - buf); + + /* + * If sgp is not given then the path is already in kernel space + */ + if (sgp == NULL) + error = copystr(path, ptr, sz, &len); + else + error = copyinstr(path, ptr, sz, &len); + + if (error) { + free(buf, M_TEMP); + return error; + } + + if (*ptr != '/') { + free(buf, M_TEMP); + return EINVAL; + } + + /* + * We know that there is a / somewhere in this pathname. + * Search backwards for it, to find the file's parent dir + * to see if it exists in the alternate tree. If it does, + * and we want to create a file (cflag is set). We don't + * need to worry about the root comparison in this case. + */ + + if (cflag) { + for (cp = &ptr[len] - 1; *cp != '/'; cp--) + ; + *cp = '\0'; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + *cp = '/'; + } else { + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + /* + * We now compare the vnode of the ia32_root to the one + * vnode asked. If they resolve to be the same, then we + * ignore the match so that the real root gets used. + * This avoids the problem of traversing "../.." to find the + * root directory and never finding it, because "/" resolves + * to the emulation root directory. This is expensive :-( + */ + NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path, + td); + + if ((error = namei(&ndroot)) != 0) { + /* Cannot happen! */ + free(buf, M_TEMP); + vrele(nd.ni_vp); + return error; + } + + ucred = td->td_ucred; + if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) { + goto bad; + } + + if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred, + td)) != 0) { + goto bad; + } + + if (vat.va_fsid == vatroot.va_fsid && + vat.va_fileid == vatroot.va_fileid) { + error = ENOENT; + goto bad; + } + + } + if (sgp == NULL) + *pbuf = buf; + else { + sz = &ptr[len] - buf; + *pbuf = stackgap_alloc(sgp, sz + 1); + error = copyout(buf, *pbuf, sz); + free(buf, M_TEMP); + } + + vrele(nd.ni_vp); + if (!cflag) + vrele(ndroot.ni_vp); + + return error; + +bad: + vrele(ndroot.ni_vp); + vrele(nd.ni_vp); + free(buf, M_TEMP); + return error; +} + +int +ia32_open(struct thread *td, struct ia32_open_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return open(td, (struct open_args *) uap); +} + +int +ia32_wait4(struct thread *td, struct ia32_wait4_args *uap) +{ + int error; + caddr_t sg; + struct rusage32 *rusage32, ru32; + struct rusage *rusage = NULL, ru; + + rusage32 = SCARG(uap, rusage); + if (rusage32) { + sg = stackgap_init(); + rusage = stackgap_alloc(&sg, sizeof(struct rusage)); + SCARG(uap, rusage) = (struct rusage32 *)rusage; + } + error = wait4(td, (struct wait_args *)uap); + if (error) + return (error); + if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) { + TV_CP(ru, ru32, ru_utime); + TV_CP(ru, ru32, ru_stime); + CP(ru, ru32, ru_maxrss); + CP(ru, ru32, ru_ixrss); + CP(ru, ru32, ru_idrss); + CP(ru, ru32, ru_isrss); + CP(ru, ru32, ru_minflt); + CP(ru, ru32, ru_majflt); + CP(ru, ru32, ru_nswap); + CP(ru, ru32, ru_inblock); + CP(ru, ru32, ru_oublock); + CP(ru, ru32, ru_msgsnd); + CP(ru, ru32, ru_msgrcv); + CP(ru, ru32, ru_nsignals); + CP(ru, ru32, ru_nvcsw); + CP(ru, ru32, ru_nivcsw); + error = copyout(&ru32, rusage32, sizeof(ru32)); + } + return (error); +} + +static void +copy_statfs(struct statfs *in, struct statfs32 *out) +{ + CP(*in, *out, f_bsize); + CP(*in, *out, f_iosize); + CP(*in, *out, f_blocks); + CP(*in, *out, f_bfree); + CP(*in, *out, f_bavail); + CP(*in, *out, f_files); + CP(*in, *out, f_ffree); + CP(*in, *out, f_fsid); + CP(*in, *out, f_owner); + CP(*in, *out, f_type); + CP(*in, *out, f_flags); + CP(*in, *out, f_flags); + CP(*in, *out, f_syncwrites); + CP(*in, *out, f_asyncwrites); + bcopy(in->f_fstypename, + out->f_fstypename, MFSNAMELEN); + bcopy(in->f_mntonname, + out->f_mntonname, MNAMELEN); + CP(*in, *out, f_syncreads); + CP(*in, *out, f_asyncreads); + bcopy(in->f_mntfromname, + out->f_mntfromname, MNAMELEN); +} + +int +ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *sp32, stat32; + struct statfs *sp = NULL, stat; + int maxcount, count, i; + + sp32 = SCARG(uap, buf); + maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32); + + if (sp32) { + sg = stackgap_init(); + sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); + SCARG(uap, buf) = (struct statfs32 *)sp; + } + error = getfsstat(td, (struct getfsstat_args *) uap); + if (sp32 && !error) { + count = td->td_retval[0]; + for (i = 0; i < count; i++) { + error = copyin(&sp[i], &stat, sizeof(stat)); + if (error) + return (error); + copy_statfs(&stat, &stat32); + error = copyout(&stat32, &sp32[i], sizeof(stat32)); + if (error) + return (error); + } + } + return (error); +} + +int +ia32_access(struct thread *td, struct ia32_access_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return access(td, (struct access_args *)uap); +} + +int +ia32_chflags(struct thread *td, struct ia32_chflags_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return chflags(td, (struct chflags_args *)uap); +} + +struct sigaltstack32 { + u_int32_t ss_sp; + u_int32_t ss_size; + int ss_flags; +}; + +int +ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap) +{ + int error; + caddr_t sg; + struct sigaltstack32 *p32, *op32, s32; + struct sigaltstack *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, ss); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + SCARG(uap, ss) = (struct sigaltstack32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + PTRIN_CP(s32, s, ss_sp); + CP(s32, s, ss_size); + CP(s32, s, ss_flags); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oss); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + SCARG(uap, oss) = (struct sigaltstack32 *)op; + } + error = sigaltstack(td, (struct sigaltstack_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + PTROUT_CP(s, s32, ss_sp); + CP(s, s32, ss_size); + CP(s, s32, ss_flags); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_execve(struct thread *td, struct ia32_execve_args *uap) +{ + int error; + caddr_t sg; + struct execve_args ap; + u_int32_t *p32, arg; + char **p; + int count; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, fname)); + SCARG(&ap, fname) = SCARG(uap, fname); + + if (SCARG(uap, argv)) { + count = 0; + p32 = SCARG(uap, argv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + count++; + } while (arg != 0); + p = stackgap_alloc(&sg, count * sizeof(char *)); + SCARG(&ap, argv) = p; + p32 = SCARG(uap, argv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + *p++ = PTRIN(arg); + } while (arg != 0); + } + if (SCARG(uap, envv)) { + count = 0; + p32 = SCARG(uap, envv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + count++; + } while (arg != 0); + p = stackgap_alloc(&sg, count * sizeof(char *)); + SCARG(&ap, envv) = p; + p32 = SCARG(uap, envv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + *p++ = PTRIN(arg); + } while (arg != 0); + } + + return execve(td, &ap); +} + +static int +ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, + int prot, int fd, off_t pos) +{ + vm_map_t map; + vm_map_entry_t entry; + int rv; + + map = &td->td_proc->p_vmspace->vm_map; + if (fd != -1) + prot |= VM_PROT_WRITE; + + if (vm_map_lookup_entry(map, start, &entry)) { + if ((entry->protection & prot) != prot) { + rv = vm_map_protect(map, + trunc_page(start), + round_page(end), + entry->protection | prot, + FALSE); + if (rv != KERN_SUCCESS) + return (EINVAL); + } + } else { + vm_offset_t addr = trunc_page(start); + rv = vm_map_find(map, 0, 0, + &addr, PAGE_SIZE, FALSE, prot, + VM_PROT_ALL, 0); + if (rv != KERN_SUCCESS) + return (EINVAL); + } + + if (fd != -1) { + struct pread_args r; + SCARG(&r, fd) = fd; + SCARG(&r, buf) = (void *) start; + SCARG(&r, nbyte) = end - start; + SCARG(&r, offset) = pos; + return (pread(td, &r)); + } else { + while (start < end) { + subyte((void *) start, 0); + start++; + } + return (0); + } +} + +int +ia32_mmap(struct thread *td, struct ia32_mmap_args *uap) +{ + struct mmap_args ap; + vm_offset_t addr = (vm_offset_t) SCARG(uap, addr); + vm_size_t len = SCARG(uap, len); + int prot = SCARG(uap, prot); + int flags = SCARG(uap, flags); + int fd = SCARG(uap, fd); + off_t pos = (SCARG(uap, poslo) + | ((off_t)SCARG(uap, poshi) << 32)); + vm_size_t pageoff; + int error; + + /* + * Attempt to handle page size hassles. + */ + pageoff = (pos & PAGE_MASK); + if (flags & MAP_FIXED) { + vm_offset_t start, end; + start = addr; + end = addr + len; + + if (start != trunc_page(start)) { + error = ia32_mmap_partial(td, start, round_page(start), + prot, fd, pos); + if (fd != -1) + pos += round_page(start) - start; + start = round_page(start); + } + if (end != round_page(end)) { + vm_offset_t t = trunc_page(end); + error = ia32_mmap_partial(td, t, end, + prot, fd, + pos + t - start); + end = trunc_page(end); + } + if (end > start && fd != -1 && (pos & PAGE_MASK)) { + /* + * We can't map this region at all. The specified + * address doesn't have the same alignment as the file + * position. Fake the mapping by simply reading the + * entire region into memory. First we need to make + * sure the region exists. + */ + vm_map_t map; + struct pread_args r; + int rv; + + prot |= VM_PROT_WRITE; + map = &td->td_proc->p_vmspace->vm_map; + rv = vm_map_remove(map, start, end); + if (rv != KERN_SUCCESS) + return (EINVAL); + rv = vm_map_find(map, 0, 0, + &start, end - start, FALSE, + prot, VM_PROT_ALL, 0); + if (rv != KERN_SUCCESS) + return (EINVAL); + SCARG(&r, fd) = fd; + SCARG(&r, buf) = (void *) start; + SCARG(&r, nbyte) = end - start; + SCARG(&r, offset) = pos; + error = pread(td, &r); + if (error) + return (error); + + td->td_retval[0] = addr; + return (0); + } + if (end == start) { + /* + * After dealing with the ragged ends, there + * might be none left. + */ + td->td_retval[0] = addr; + return (0); + } + addr = start; + len = end - start; + } + + SCARG(&ap, addr) = (void *) addr; + SCARG(&ap, len) = len; + SCARG(&ap, prot) = prot; + SCARG(&ap, flags) = flags; + SCARG(&ap, fd) = fd; + SCARG(&ap, pos) = pos; + + return (mmap(td, &ap)); +} + +struct itimerval32 { + struct timeval32 it_interval; + struct timeval32 it_value; +}; + +int +ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap) +{ + int error; + caddr_t sg; + struct itimerval32 *p32, *op32, s32; + struct itimerval *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, itv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct itimerval)); + SCARG(uap, itv) = (struct itimerval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + TV_CP(s32, s, it_interval); + TV_CP(s32, s, it_value); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oitv); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct itimerval)); + SCARG(uap, oitv) = (struct itimerval32 *)op; + } + error = setitimer(td, (struct setitimer_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + TV_CP(s, s32, it_interval); + TV_CP(s, s32, it_value); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_select(struct thread *td, struct ia32_select_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tv) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + /* + * XXX big-endian needs to convert the fd_sets too. + */ + return (select(td, (struct select_args *) uap)); +} + +int +ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tp); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tp) = (struct timeval32 *)p; + } + error = gettimeofday(td, (struct gettimeofday_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + CP(s, s32, tv_sec); + CP(s, s32, tv_usec); + error = copyout(&s32, p32, sizeof(s32)); + if (error) + return (error); + } + return (error); +} + +int +ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap) +{ + int error; + caddr_t sg; + struct rusage32 *p32, s32; + struct rusage *p = NULL, s; + + p32 = SCARG(uap, rusage); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct rusage)); + SCARG(uap, rusage) = (struct rusage32 *)p; + } + error = getrusage(td, (struct getrusage_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + TV_CP(s, s32, ru_utime); + TV_CP(s, s32, ru_stime); + CP(s, s32, ru_maxrss); + CP(s, s32, ru_ixrss); + CP(s, s32, ru_idrss); + CP(s, s32, ru_isrss); + CP(s, s32, ru_minflt); + CP(s, s32, ru_majflt); + CP(s, s32, ru_nswap); + CP(s, s32, ru_inblock); + CP(s, s32, ru_oublock); + CP(s, s32, ru_msgsnd); + CP(s, s32, ru_msgrcv); + CP(s, s32, ru_nsignals); + CP(s, s32, ru_nvcsw); + CP(s, s32, ru_nivcsw); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +struct iovec32 { + u_int32_t iov_base; + int iov_len; +}; +#define STACKGAPLEN 400 + +int +ia32_readv(struct thread *td, struct ia32_readv_args *uap) +{ + int error, osize, nsize, i; + caddr_t sg; + struct readv_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ a; + struct iovec32 *oio; + struct iovec *nio; + + sg = stackgap_init(); + + if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec))) + return (EINVAL); + + osize = SCARG(uap, iovcnt) * sizeof (struct iovec32); + nsize = SCARG(uap, iovcnt) * sizeof (struct iovec); + + oio = malloc(osize, M_TEMP, M_WAITOK); + nio = malloc(nsize, M_TEMP, M_WAITOK); + + error = 0; + if ((error = copyin(SCARG(uap, iovp), oio, osize))) + goto punt; + for (i = 0; i < SCARG(uap, iovcnt); i++) { + nio[i].iov_base = PTRIN(oio[i].iov_base); + nio[i].iov_len = oio[i].iov_len; + } + + SCARG(&a, fd) = SCARG(uap, fd); + SCARG(&a, iovp) = stackgap_alloc(&sg, nsize); + SCARG(&a, iovcnt) = SCARG(uap, iovcnt); + + if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize))) + goto punt; + error = readv(td, &a); + +punt: + free(oio, M_TEMP); + free(nio, M_TEMP); + return (error); +} + +int +ia32_writev(struct thread *td, struct ia32_writev_args *uap) +{ + int error, i, nsize, osize; + caddr_t sg; + struct writev_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ a; + struct iovec32 *oio; + struct iovec *nio; + + sg = stackgap_init(); + + if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec))) + return (EINVAL); + + osize = SCARG(uap, iovcnt) * sizeof (struct iovec32); + nsize = SCARG(uap, iovcnt) * sizeof (struct iovec); + + oio = malloc(osize, M_TEMP, M_WAITOK); + nio = malloc(nsize, M_TEMP, M_WAITOK); + + error = 0; + if ((error = copyin(SCARG(uap, iovp), oio, osize))) + goto punt; + for (i = 0; i < SCARG(uap, iovcnt); i++) { + nio[i].iov_base = PTRIN(oio[i].iov_base); + nio[i].iov_len = oio[i].iov_len; + } + + SCARG(&a, fd) = SCARG(uap, fd); + SCARG(&a, iovp) = stackgap_alloc(&sg, nsize); + SCARG(&a, iovcnt) = SCARG(uap, iovcnt); + + if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize))) + goto punt; + error = writev(td, &a); + +punt: + free(oio, M_TEMP); + free(nio, M_TEMP); + return (error); +} + +int +ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tv) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + return (settimeofday(td, (struct settimeofday_args *) uap)); +} + +int +ia32_utimes(struct thread *td, struct ia32_utimes_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32[2]; + struct timeval *p = NULL, s[2]; + + p32 = SCARG(uap, tptr); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); + SCARG(uap, tptr) = (struct timeval32 *)p; + error = copyin(p32, s32, sizeof(s32)); + if (error) + return (error); + CP(s32[0], s[0], tv_sec); + CP(s32[0], s[0], tv_usec); + CP(s32[1], s[1], tv_sec); + CP(s32[1], s[1], tv_usec); + error = copyout(s, p, sizeof(s)); + if (error) + return (error); + } + return (utimes(td, (struct utimes_args *) uap)); +} + +int +ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, *op32, s32; + struct timeval *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, delta); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, delta) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, olddelta); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, olddelta) = (struct timeval32 *)op; + } + error = utimes(td, (struct utimes_args *) uap); + if (error) + return error; + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + CP(s, s32, tv_sec); + CP(s, s32, tv_usec); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_statfs(struct thread *td, struct ia32_statfs_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *p32, s32; + struct statfs *p = NULL, s; + + p32 = SCARG(uap, buf); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct statfs)); + SCARG(uap, buf) = (struct statfs32 *)p; + } + error = statfs(td, (struct statfs_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_statfs(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *p32, s32; + struct statfs *p = NULL, s; + + p32 = SCARG(uap, buf); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct statfs)); + SCARG(uap, buf) = (struct statfs32 *)p; + } + error = fstatfs(td, (struct fstatfs_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_statfs(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_semsys(struct thread *td, struct ia32_semsys_args *uap) +{ + /* + * Vector through to semsys if it is loaded. + */ + return sysent[169].sy_call(td, uap); +} + +int +ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap) +{ + /* + * Vector through to msgsys if it is loaded. + */ + return sysent[170].sy_call(td, uap); +} + +int +ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap) +{ + /* + * Vector through to shmsys if it is loaded. + */ + return sysent[171].sy_call(td, uap); +} + +int +ia32_pread(struct thread *td, struct ia32_pread_args *uap) +{ + struct pread_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, buf) = SCARG(uap, buf); + SCARG(&ap, nbyte) = SCARG(uap, nbyte); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + return (pread(td, &ap)); +} + +int +ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap) +{ + struct pwrite_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, buf) = SCARG(uap, buf); + SCARG(&ap, nbyte) = SCARG(uap, nbyte); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + return (pwrite(td, &ap)); +} + +int +ia32_lseek(struct thread *td, struct ia32_lseek_args *uap) +{ + int error; + struct lseek_args ap; + off_t pos; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + SCARG(&ap, whence) = SCARG(uap, whence); + error = lseek(td, &ap); + /* Expand the quad return into two parts for eax and edx */ + pos = *(off_t *)(td->td_retval); + td->td_retval[0] = pos & 0xffffffff; /* %eax */ + td->td_retval[1] = pos >> 32; /* %edx */ + return error; +} + +int +ia32_truncate(struct thread *td, struct ia32_truncate_args *uap) +{ + struct truncate_args ap; + + SCARG(&ap, path) = SCARG(uap, path); + SCARG(&ap, length) = (SCARG(uap, lengthlo) + | ((off_t)SCARG(uap, lengthhi) << 32)); + return (truncate(td, &ap)); +} + +int +ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap) +{ + struct ftruncate_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, length) = (SCARG(uap, lengthlo) + | ((off_t)SCARG(uap, lengthhi) << 32)); + return (ftruncate(td, &ap)); +} + +int +ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap) +{ + struct sendfile_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, s) = SCARG(uap, s); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + SCARG(&ap, nbytes) = SCARG(uap, nbytes); /* XXX check */ + SCARG(&ap, hdtr) = SCARG(uap, hdtr); /* XXX check */ + SCARG(&ap, sbytes) = SCARG(uap, sbytes); /* XXX FIXME!! */ + SCARG(&ap, flags) = SCARG(uap, flags); + return (sendfile(td, &ap)); +} + +struct stat32 { + udev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + udev_t st_rdev; + struct timespec32 st_atimespec; + struct timespec32 st_mtimespec; + struct timespec32 st_ctimespec; + off_t st_size; + int64_t st_blocks; + u_int32_t st_blksize; + u_int32_t st_flags; + u_int32_t st_gen; +}; + +static void +copy_stat( struct stat *in, struct stat32 *out) +{ + CP(*in, *out, st_dev); + CP(*in, *out, st_ino); + CP(*in, *out, st_mode); + CP(*in, *out, st_nlink); + CP(*in, *out, st_uid); + CP(*in, *out, st_gid); + CP(*in, *out, st_rdev); + TS_CP(*in, *out, st_atimespec); + TS_CP(*in, *out, st_mtimespec); + TS_CP(*in, *out, st_ctimespec); + CP(*in, *out, st_size); + CP(*in, *out, st_blocks); + CP(*in, *out, st_blksize); + CP(*in, *out, st_flags); + CP(*in, *out, st_gen); +} + +int +ia32_stat(struct thread *td, struct ia32_stat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = stat(td, (struct stat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_fstat(struct thread *td, struct ia32_fstat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = fstat(td, (struct fstat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_lstat(struct thread *td, struct ia32_lstat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = lstat(td, (struct lstat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +/* + * MPSAFE + */ +int +ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap) +{ + int error, name[CTL_MAXNAME]; + size_t j, oldlen; + + if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) + return (EINVAL); + + error = copyin(uap->name, &name, uap->namelen * sizeof(int)); + if (error) + return (error); + + mtx_lock(&Giant); + + if (uap->oldlenp) + oldlen = fuword32(uap->oldlenp); + else + oldlen = 0; + error = userland_sysctl(td, name, uap->namelen, + uap->old, &oldlen, 1, + uap->new, uap->newlen, &j); + if (error && error != ENOMEM) + goto done2; + if (uap->oldlenp) { + suword32(uap->oldlenp, j); + } +done2: + mtx_unlock(&Giant); + return (error); +} + +struct sigaction32 { + u_int32_t sa_u; + int sa_flags; + sigset_t sa_mask; +}; + +int +ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap) +{ + int error; + caddr_t sg; + struct sigaction32 *p32, *op32, s32; + struct sigaction *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, act); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(uap, act) = (struct sigaction32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + s.sa_handler = PTRIN(s32.sa_u); + CP(s32, s, sa_flags); + CP(s32, s, sa_mask); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oact); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(uap, oact) = (struct sigaction32 *)op; + } + error = sigaction(td, (struct sigaction_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + s32.sa_u = PTROUT(s.sa_handler); + CP(s, s32, sa_flags); + CP(s, s32, sa_mask); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +#if 0 + +int +ia32_xxx(struct thread *td, struct ia32_xxx_args *uap) +{ + int error; + caddr_t sg; + struct yyy32 *p32, s32; + struct yyy *p = NULL, s; + + p32 = SCARG(uap, zzz); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct yyy)); + SCARG(uap, zzz) = (struct yyy32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + /* translate in */ + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + error = xxx(td, (struct xxx_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + /* translate out */ + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +#endif Property changes on: head/sys/compat/freebsd32/freebsd32_misc.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/compat/freebsd32/freebsd32_util.h =================================================================== --- head/sys/compat/freebsd32/freebsd32_util.h (nonexistent) +++ head/sys/compat/freebsd32/freebsd32_util.h (revision 100384) @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 1998-1999 Andrew Gallatin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + + +#include +#include +#include + + +#ifndef SCARG +#define SCARG(p, x) (p)->x +#endif + +struct ia32_ps_strings { + u_int32_t ps_argvstr; /* first of 0 or more argument strings */ + int ps_nargvstr; /* the number of argument strings */ + u_int32_t ps_envstr; /* first of 0 or more environment strings */ + int ps_nenvstr; /* the number of environment strings */ +}; + +#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE) +#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings)) + +static __inline caddr_t stackgap_init(void); +static __inline void *stackgap_alloc(caddr_t *, size_t); + +static __inline caddr_t +stackgap_init() +{ +#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) + return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE); +#undef szsigcode +} + +static __inline void * +stackgap_alloc(sgp, sz) + caddr_t *sgp; + size_t sz; +{ + void *p; + + p = (void *) *sgp; + *sgp += ALIGN(sz); + return p; +} + + +extern const char ia32_emul_path[]; +int ia32_emul_find(struct thread *, caddr_t *, const char *, char *, + char **, int); + +#define CHECKALT(p, sgp, path, i) \ + do { \ + int _error; \ + \ + _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \ + &path, i); \ + if (_error == EFAULT) \ + return (_error); \ + } while (0) + +#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0) +#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1) Property changes on: head/sys/compat/freebsd32/freebsd32_util.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/compat/freebsd32/syscalls.master =================================================================== --- head/sys/compat/freebsd32/syscalls.master (revision 100383) +++ head/sys/compat/freebsd32/syscalls.master (revision 100384) @@ -1,562 +1,563 @@ $FreeBSD$ ; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94 ; from: src/sys/kern/syscalls.master 1.107 ; ; System call name/number master file. ; Processed to created init_sysent.c, syscalls.c and syscall.h. ; Columns: number [M]type nargs namespc name alt{name,tag,rtyp}/comments ; number system call number, must be in order ; type one of [M]STD, [M]OBSOL, [M]UNIMPL, [M]COMPAT, [M]CPT_NOA, ; [M]LIBCOMPAT, [M]NODEF, [M]NOARGS, [M]NOPROTO, [M]NOIMPL, ; [M]NOSTD ; namespc one of POSIX, BSD, NOHIDE ; name psuedo-prototype of syscall routine ; If one of the following alts is different, then all appear: ; altname name of system call if different ; alttag name of args struct tag if different from [o]`name'"_args" ; altrtyp return type if not int (bogus - syscalls always return int) ; for UNIMPL/OBSOL, name continues with comments ; types: ; [M] e.g. like MSTD -- means the system call is MP-safe. If no ; M prefix is used, the syscall wrapper will obtain the Giant ; lock for the syscall. ; STD always included ; COMPAT included on COMPAT #ifdef ; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h ; OBSOL obsolete, not included in system, only specifies name ; UNIMPL not implemented, placeholder only ; NOSTD implemented but as a lkm that can be statically ; compiled in sysent entry will be filled with lkmsys ; so the SYSCALL_MODULE macro works ; #ifdef's, etc. may be included, and are copied to the output files. #include #include #include +#include +#include +#include ; Reserved/unimplemented system calls in the range 0-150 inclusive ; are reserved for use in future Berkeley releases. ; Additional system calls implemented in vendor and other ; redistributions should be placed in the reserved range at the end ; of the current calls. -0 STD NOHIDE { int nosys(void); } syscall nosys_args int -1 MSTD NOHIDE { void sys_exit(int rval); } exit sys_exit_args void -2 MSTD POSIX { int fork(void); } -3 MSTD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); } -4 MSTD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); } -5 STD POSIX { int open(char *path, int flags, int mode); } +0 MNOPROTO NOHIDE { int nosys(void); } syscall nosys_args int +1 MNOPROTO NOHIDE { void sys_exit(int rval); } exit sys_exit_args void +2 MNOPROTO POSIX { int fork(void); } +3 MNOPROTO POSIX { ssize_t read(int fd, void *buf, size_t nbyte); } +4 MNOPROTO POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); } +5 STD POSIX { int ia32_open(char *path, int flags, int mode); } ; XXX should be { int open(const char *path, int flags, ...); } ; but we're not ready for `const' or varargs. ; XXX man page says `mode_t mode'. -6 MSTD POSIX { int close(int fd); } -7 MSTD BSD { int wait4(int pid, int *status, int options, \ - struct rusage *rusage); } wait4 wait_args int -8 COMPAT BSD { int creat(char *path, int mode); } -9 STD POSIX { int link(char *path, char *link); } -10 STD POSIX { int unlink(char *path); } +6 MNOPROTO POSIX { int close(int fd); } +7 MSTD BSD { int ia32_wait4(int pid, int *status, int options, \ + struct rusage32 *rusage); } +8 OBSOL BSD old creat +9 NOPROTO POSIX { int link(char *path, char *link); } +10 NOPROTO POSIX { int unlink(char *path); } 11 OBSOL NOHIDE execv -12 STD POSIX { int chdir(char *path); } -13 STD BSD { int fchdir(int fd); } -14 STD POSIX { int mknod(char *path, int mode, int dev); } -15 STD POSIX { int chmod(char *path, int mode); } -16 STD POSIX { int chown(char *path, int uid, int gid); } -17 MSTD BSD { int obreak(char *nsize); } break obreak_args int -18 STD BSD { int getfsstat(struct statfs *buf, long bufsize, \ - int flags); } -19 COMPAT POSIX { long lseek(int fd, long offset, int whence); } -20 MSTD POSIX { pid_t getpid(void); } -21 STD BSD { int mount(char *type, char *path, int flags, \ +12 NOPROTO POSIX { int chdir(char *path); } +13 NOPROTO BSD { int fchdir(int fd); } +14 NOPROTO POSIX { int mknod(char *path, int mode, int dev); } +15 NOPROTO POSIX { int chmod(char *path, int mode); } +16 NOPROTO POSIX { int chown(char *path, int uid, int gid); } +17 MNOPROTO BSD { int obreak(char *nsize); } break obreak_args int +18 STD BSD { int ia32_getfsstat(struct statfs32 *buf, \ + long bufsize, int flags); } +19 OBSOL POSIX olseek +20 MNOPROTO POSIX { pid_t getpid(void); } +21 NOPROTO BSD { int mount(char *type, char *path, int flags, \ caddr_t data); } ; XXX `path' should have type `const char *' but we're not ready for that. -22 STD BSD { int unmount(char *path, int flags); } -23 MSTD POSIX { int setuid(uid_t uid); } -24 MSTD POSIX { uid_t getuid(void); } -25 MSTD POSIX { uid_t geteuid(void); } -26 STD BSD { int ptrace(int req, pid_t pid, caddr_t addr, \ +22 NOPROTO BSD { int unmount(char *path, int flags); } +23 MNOPROTO POSIX { int setuid(uid_t uid); } +24 MNOPROTO POSIX { uid_t getuid(void); } +25 MNOPROTO POSIX { uid_t geteuid(void); } +26 NOPROTO BSD { int ptrace(int req, pid_t pid, caddr_t addr, \ int data); } -27 MSTD BSD { int recvmsg(int s, struct msghdr *msg, int flags); } -28 MSTD BSD { int sendmsg(int s, caddr_t msg, int flags); } -29 MSTD BSD { int recvfrom(int s, caddr_t buf, size_t len, \ +27 UNIMPL BSD recvmsg +28 MNOPROTO BSD { int sendmsg(int s, caddr_t msg, int flags); } +29 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \ int flags, caddr_t from, int *fromlenaddr); } -30 MSTD BSD { int accept(int s, caddr_t name, int *anamelen); } -31 MSTD BSD { int getpeername(int fdes, caddr_t asa, int *alen); } -32 MSTD BSD { int getsockname(int fdes, caddr_t asa, int *alen); } -33 STD POSIX { int access(char *path, int flags); } -34 STD BSD { int chflags(char *path, int flags); } -35 STD BSD { int fchflags(int fd, int flags); } -36 STD BSD { int sync(void); } -37 MSTD POSIX { int kill(int pid, int signum); } -38 COMPAT POSIX { int stat(char *path, struct ostat *ub); } -39 MSTD POSIX { pid_t getppid(void); } -40 COMPAT POSIX { int lstat(char *path, struct ostat *ub); } -41 STD POSIX { int dup(u_int fd); } -42 STD POSIX { int pipe(void); } -43 MSTD POSIX { gid_t getegid(void); } -44 MSTD BSD { int profil(caddr_t samples, size_t size, \ +30 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } +31 MNOPROTO BSD { int getpeername(int fdes, caddr_t asa, int *alen); } +32 MNOPROTO BSD { int getsockname(int fdes, caddr_t asa, int *alen); } +33 STD POSIX { int ia32_access(char *path, int flags); } +34 STD BSD { int ia32_chflags(char *path, int flags); } +35 NOPROTO BSD { int fchflags(int fd, int flags); } +36 NOPROTO BSD { int sync(void); } +37 MNOPROTO POSIX { int kill(int pid, int signum); } +38 UNIMPL POSIX ostat +39 MNOPROTO POSIX { pid_t getppid(void); } +40 UNIMPL POSIX olstat +41 NOPROTO POSIX { int dup(u_int fd); } +42 NOPROTO POSIX { int pipe(void); } +43 MNOPROTO POSIX { gid_t getegid(void); } +44 MNOPROTO BSD { int profil(caddr_t samples, size_t size, \ size_t offset, u_int scale); } -45 STD BSD { int ktrace(const char *fname, int ops, int facs, \ +45 NOPROTO BSD { int ktrace(const char *fname, int ops, int facs, \ int pid); } -46 MCOMPAT POSIX { int sigaction(int signum, struct osigaction *nsa, \ - struct osigaction *osa); } -47 MSTD POSIX { gid_t getgid(void); } -48 MCOMPAT POSIX { int sigprocmask(int how, osigset_t mask); } -; XXX note nonstandard (bogus) calling convention - the libc stub passes -; us the mask, not a pointer to it, and we return the old mask as the -; (int) return value. -49 MSTD BSD { int getlogin(char *namebuf, u_int namelen); } -50 MSTD BSD { int setlogin(char *namebuf); } -51 MSTD BSD { int acct(char *path); } -52 MCOMPAT POSIX { int sigpending(void); } -53 MSTD BSD { int sigaltstack(stack_t *ss, stack_t *oss); } -54 MSTD POSIX { int ioctl(int fd, u_long com, caddr_t data); } -55 MSTD BSD { int reboot(int opt); } -56 STD POSIX { int revoke(char *path); } -57 STD POSIX { int symlink(char *path, char *link); } -58 STD POSIX { int readlink(char *path, char *buf, int count); } -59 MSTD POSIX { int execve(char *fname, char **argv, char **envv); } -60 MSTD POSIX { int umask(int newmask); } umask umask_args int -61 STD BSD { int chroot(char *path); } -62 MCOMPAT POSIX { int fstat(int fd, struct ostat *sb); } -63 MCOMPAT BSD { int getkerninfo(int op, char *where, size_t *size, \ - int arg); } getkerninfo getkerninfo_args int -64 MCOMPAT BSD { int getpagesize(void); } \ - getpagesize getpagesize_args int -65 STD BSD { int msync(void *addr, size_t len, int flags); } -66 MSTD BSD { int vfork(void); } +46 UNIMPL POSIX osigaction +47 MNOPROTO POSIX { gid_t getgid(void); } +48 UNIMPL POSIX osigprocmask +49 MNOPROTO BSD { int getlogin(char *namebuf, u_int namelen); } +50 MNOPROTO BSD { int setlogin(char *namebuf); } +51 MNOPROTO BSD { int acct(char *path); } +52 MNOPROTO POSIX { int sigpending(void); } +53 STD BSD { int ia32_sigaltstack(struct sigaltstack32 *ss, struct sigaltstack32 *oss); } +54 MNOPROTO POSIX { int ioctl(int fd, u_long com, caddr_t data); } +55 MNOPROTO BSD { int reboot(int opt); } +56 NOPROTO POSIX { int revoke(char *path); } +57 NOPROTO POSIX { int symlink(char *path, char *link); } +58 NOPROTO POSIX { int readlink(char *path, char *buf, int count); } +59 STD POSIX { int ia32_execve(char *fname, u_int32_t *argv, u_int32_t *envv); } +60 MNOPROTO POSIX { int umask(int newmask); } umask umask_args int +61 NOPROTO BSD { int chroot(char *path); } +62 OBSOL POSIX ofstat +63 OBSOL BSD ogetkerninfo +64 OBSOL BSD ogetpagesize +65 OBSOL BSD omsync +66 OBSOL BSD ovfork 67 OBSOL NOHIDE vread 68 OBSOL NOHIDE vwrite -69 MSTD BSD { int sbrk(int incr); } -70 MSTD BSD { int sstk(int incr); } -71 MCOMPAT BSD { int mmap(void *addr, int len, int prot, \ - int flags, int fd, long pos); } -72 MSTD BSD { int ovadvise(int anom); } vadvise ovadvise_args int -73 MSTD BSD { int munmap(void *addr, size_t len); } -74 MSTD BSD { int mprotect(const void *addr, size_t len, int prot); } -75 MSTD BSD { int madvise(void *addr, size_t len, int behav); } +69 MNOPROTO BSD { int sbrk(int incr); } +70 MNOPROTO BSD { int sstk(int incr); } +71 OBSOL BSD ommap +72 MNOPROTO BSD { int ovadvise(int anom); } vadvise ovadvise_args int +73 MNOPROTO BSD { int munmap(void *addr, size_t len); } +74 MNOPROTO BSD { int mprotect(const void *addr, size_t len, int prot); } +75 MNOPROTO BSD { int madvise(void *addr, size_t len, int behav); } 76 OBSOL NOHIDE vhangup 77 OBSOL NOHIDE vlimit -78 MSTD BSD { int mincore(const void *addr, size_t len, \ +78 MNOPROTO BSD { int mincore(const void *addr, size_t len, \ char *vec); } -79 MSTD POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); } -80 MSTD POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); } -81 MSTD POSIX { int getpgrp(void); } -82 MSTD POSIX { int setpgid(int pid, int pgid); } -83 MSTD BSD { int setitimer(u_int which, struct itimerval *itv, \ - struct itimerval *oitv); } -84 MCOMPAT BSD { int wait(void); } -85 MSTD BSD { int swapon(char *name); } -86 MSTD BSD { int getitimer(u_int which, struct itimerval *itv); } -87 MCOMPAT BSD { int gethostname(char *hostname, u_int len); } \ - gethostname gethostname_args int -88 MCOMPAT BSD { int sethostname(char *hostname, u_int len); } \ - sethostname sethostname_args int -89 MSTD BSD { int getdtablesize(void); } -90 MSTD POSIX { int dup2(u_int from, u_int to); } +79 MNOPROTO POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); } +80 MNOPROTO POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); } +81 MNOPROTO POSIX { int getpgrp(void); } +82 MNOPROTO POSIX { int setpgid(int pid, int pgid); } +83 STD BSD { int ia32_setitimer(u_int which, \ + struct itimerval32 *itv, \ + struct itimerval32 *oitv); } +84 OBSOL BSD owait +85 OBSOL BSD oswapon +86 OBSOL BSD ogetitimer +87 OBSOL BSD ogethostname +88 OBSOL BSD osethostname +89 MNOPROTO BSD { int getdtablesize(void); } +90 MNOPROTO POSIX { int dup2(u_int from, u_int to); } 91 UNIMPL BSD getdopt -92 MSTD POSIX { int fcntl(int fd, int cmd, long arg); } +92 MNOPROTO POSIX { int fcntl(int fd, int cmd, long arg); } ; XXX should be { int fcntl(int fd, int cmd, ...); } ; but we're not ready for varargs. ; XXX man page says `int arg' too. -93 MSTD BSD { int select(int nd, fd_set *in, fd_set *ou, \ - fd_set *ex, struct timeval *tv); } +93 STD BSD { int ia32_select(int nd, fd_set *in, fd_set *ou, \ + fd_set *ex, struct timeval32 *tv); } +; XXX need to override for big-endian - little-endian should work fine. 94 UNIMPL BSD setdopt -95 STD POSIX { int fsync(int fd); } -96 MSTD BSD { int setpriority(int which, int who, int prio); } -97 MSTD BSD { int socket(int domain, int type, int protocol); } -98 MSTD BSD { int connect(int s, caddr_t name, int namelen); } -99 MCPT_NOA BSD { int accept(int s, caddr_t name, int *anamelen); } \ +95 NOPROTO POSIX { int fsync(int fd); } +96 MNOPROTO BSD { int setpriority(int which, int who, int prio); } +97 MNOPROTO BSD { int socket(int domain, int type, int protocol); } +98 MNOPROTO BSD { int connect(int s, caddr_t name, int namelen); } +99 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } \ accept accept_args int -100 MSTD BSD { int getpriority(int which, int who); } -101 MCOMPAT BSD { int send(int s, caddr_t buf, int len, int flags); } -102 MCOMPAT BSD { int recv(int s, caddr_t buf, int len, int flags); } -103 STD BSD { int osigreturn(struct osigcontext *sigcntxp); } -104 MSTD BSD { int bind(int s, caddr_t name, int namelen); } -105 MSTD BSD { int setsockopt(int s, int level, int name, \ +100 MNOPROTO BSD { int getpriority(int which, int who); } +101 OBSOL BSD osend +102 OBSOL BSD orecv +103 OBSOL BSD osigreturn +104 MNOPROTO BSD { int bind(int s, caddr_t name, int namelen); } +105 MNOPROTO BSD { int setsockopt(int s, int level, int name, \ caddr_t val, int valsize); } -106 MSTD BSD { int listen(int s, int backlog); } +106 MNOPROTO BSD { int listen(int s, int backlog); } 107 OBSOL NOHIDE vtimes -108 MCOMPAT BSD { int sigvec(int signum, struct sigvec *nsv, \ - struct sigvec *osv); } -109 MCOMPAT BSD { int sigblock(int mask); } -110 MCOMPAT BSD { int sigsetmask(int mask); } -111 MCOMPAT POSIX { int sigsuspend(osigset_t mask); } -; XXX note nonstandard (bogus) calling convention - the libc stub passes -; us the mask, not a pointer to it. -112 MCOMPAT BSD { int sigstack(struct sigstack *nss, \ - struct sigstack *oss); } -113 MCOMPAT BSD { int recvmsg(int s, struct omsghdr *msg, int flags); } -114 MCOMPAT BSD { int sendmsg(int s, caddr_t msg, int flags); } +108 OBSOL BSD osigvec +109 OBSOL BSD osigblock +110 OBSOL BSD osigsetmask +111 OBSOL POSIX osigsuspend +112 OBSOL BSD osigstack +113 OBSOL BSD orecvmsg +114 OBSOL BSD osendmsg 115 OBSOL NOHIDE vtrace -116 MSTD BSD { int gettimeofday(struct timeval *tp, \ +116 STD BSD { int ia32_gettimeofday(struct timeval32 *tp, \ struct timezone *tzp); } -117 MSTD BSD { int getrusage(int who, struct rusage *rusage); } -118 MSTD BSD { int getsockopt(int s, int level, int name, \ +117 STD BSD { int ia32_getrusage(int who, struct rusage32 *rusage); } +118 MNOPROTO BSD { int getsockopt(int s, int level, int name, \ caddr_t val, int *avalsize); } 119 UNIMPL NOHIDE resuba (BSD/OS 2.x) -120 MSTD BSD { int readv(int fd, struct iovec *iovp, u_int iovcnt); } -121 MSTD BSD { int writev(int fd, struct iovec *iovp, \ +120 STD BSD { int ia32_readv(int fd, struct iovec32 *iovp, u_int iovcnt); } +121 STD BSD { int ia32_writev(int fd, struct iovec32 *iovp, \ u_int iovcnt); } -122 MSTD BSD { int settimeofday(struct timeval *tv, \ +122 STD BSD { int ia32_settimeofday(struct timeval32 *tv, \ struct timezone *tzp); } -123 STD BSD { int fchown(int fd, int uid, int gid); } -124 STD BSD { int fchmod(int fd, int mode); } -125 MCPT_NOA BSD { int recvfrom(int s, caddr_t buf, size_t len, \ +123 NOPROTO BSD { int fchown(int fd, int uid, int gid); } +124 NOPROTO BSD { int fchmod(int fd, int mode); } +125 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \ int flags, caddr_t from, int *fromlenaddr); } \ recvfrom recvfrom_args int -126 MSTD BSD { int setreuid(int ruid, int euid); } -127 MSTD BSD { int setregid(int rgid, int egid); } -128 STD POSIX { int rename(char *from, char *to); } -129 COMPAT BSD { int truncate(char *path, long length); } -130 COMPAT BSD { int ftruncate(int fd, long length); } -131 MSTD BSD { int flock(int fd, int how); } -132 STD POSIX { int mkfifo(char *path, int mode); } -133 MSTD BSD { int sendto(int s, caddr_t buf, size_t len, \ +126 MNOPROTO BSD { int setreuid(int ruid, int euid); } +127 MNOPROTO BSD { int setregid(int rgid, int egid); } +128 NOPROTO POSIX { int rename(char *from, char *to); } +129 OBSOL BSD otruncate +130 OBSOL BSD ftruncate +131 MNOPROTO BSD { int flock(int fd, int how); } +132 NOPROTO POSIX { int mkfifo(char *path, int mode); } +133 MNOPROTO BSD { int sendto(int s, caddr_t buf, size_t len, \ int flags, caddr_t to, int tolen); } -134 MSTD BSD { int shutdown(int s, int how); } -135 MSTD BSD { int socketpair(int domain, int type, int protocol, \ +134 MNOPROTO BSD { int shutdown(int s, int how); } +135 MNOPROTO BSD { int socketpair(int domain, int type, int protocol, \ int *rsv); } -136 STD POSIX { int mkdir(char *path, int mode); } -137 STD POSIX { int rmdir(char *path); } -138 STD BSD { int utimes(char *path, struct timeval *tptr); } +136 NOPROTO POSIX { int mkdir(char *path, int mode); } +137 NOPROTO POSIX { int rmdir(char *path); } +138 STD BSD { int ia32_utimes(char *path, \ + struct timeval32 *tptr); } 139 OBSOL NOHIDE 4.2 sigreturn -140 MSTD BSD { int adjtime(struct timeval *delta, \ - struct timeval *olddelta); } -141 MCOMPAT BSD { int getpeername(int fdes, caddr_t asa, int *alen); } -142 MCOMPAT BSD { long gethostid(void); } -143 MCOMPAT BSD { int sethostid(long hostid); } -144 MCOMPAT BSD { int getrlimit(u_int which, struct orlimit *rlp); } -145 MCOMPAT BSD { int setrlimit(u_int which, struct orlimit *rlp); } -146 MCOMPAT BSD { int killpg(int pgid, int signum); } -147 MSTD POSIX { int setsid(void); } -148 STD BSD { int quotactl(char *path, int cmd, int uid, \ +140 STD BSD { int ia32_adjtime(struct timeval32 *delta, \ + struct timeval32 *olddelta); } +141 OBSOL BSD ogetpeername +142 OBSOL BSD ogethostid +143 OBSOL BSD sethostid +144 OBSOL BSD getrlimit +145 OBSOL BSD setrlimit +146 OBSOL BSD killpg +147 MNOPROTO POSIX { int setsid(void); } +148 NOPROTO BSD { int quotactl(char *path, int cmd, int uid, \ caddr_t arg); } -149 MCOMPAT BSD { int quota(void); } -150 MCPT_NOA BSD { int getsockname(int fdec, caddr_t asa, int *alen); }\ - getsockname getsockname_args int +149 OBSOL BSD oquota +150 OBSOL BSD ogetsockname ; Syscalls 151-180 inclusive are reserved for vendor-specific ; system calls. (This includes various calls added for compatibity ; with other Unix variants.) ; Some of these calls are now supported by BSD... 151 UNIMPL NOHIDE sem_lock (BSD/OS 2.x) 152 UNIMPL NOHIDE sem_wakeup (BSD/OS 2.x) 153 UNIMPL NOHIDE asyncdaemon (BSD/OS 2.x) 154 UNIMPL NOHIDE nosys ; 155 is initialized by the NFS code, if present. -155 MNOIMPL BSD { int nfssvc(int flag, caddr_t argp); } -156 COMPAT BSD { int getdirentries(int fd, char *buf, u_int count, \ +155 UNIMPL NOHIDE nfssvc +156 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \ long *basep); } -157 STD BSD { int statfs(char *path, struct statfs *buf); } -158 STD BSD { int fstatfs(int fd, struct statfs *buf); } +157 STD BSD { int ia32_statfs(char *path, struct statfs32 *buf); } +158 STD BSD { int ia32_fstatfs(int fd, struct statfs32 *buf); } 159 UNIMPL NOHIDE nosys 160 UNIMPL NOHIDE nosys -161 STD BSD { int getfh(char *fname, struct fhandle *fhp); } -162 MSTD BSD { int getdomainname(char *domainname, int len); } -163 MSTD BSD { int setdomainname(char *domainname, int len); } -164 MSTD BSD { int uname(struct utsname *name); } -165 STD BSD { int sysarch(int op, char *parms); } -166 MSTD BSD { int rtprio(int function, pid_t pid, \ +161 NOPROTO BSD { int getfh(char *fname, struct fhandle *fhp); } +162 MNOPROTO BSD { int getdomainname(char *domainname, int len); } +163 MNOPROTO BSD { int setdomainname(char *domainname, int len); } +164 MNOPROTO BSD { int uname(struct utsname *name); } +165 NOPROTO BSD { int sysarch(int op, char *parms); } +166 MNOPROTO BSD { int rtprio(int function, pid_t pid, \ struct rtprio *rtp); } 167 UNIMPL NOHIDE nosys 168 UNIMPL NOHIDE nosys -; 169 is initialized by the SYSVSEM code if present or loaded -169 MNOSTD BSD { int semsys(int which, int a2, int a3, int a4, \ +169 STD BSD { int ia32_semsys(int which, int a2, int a3, int a4, \ int a5); } -; 169 is initialized by the SYSVMSG code if present or loaded -; XXX should be { int semsys(int which, ...); } -170 MNOSTD BSD { int msgsys(int which, int a2, int a3, int a4, \ +170 STD BSD { int ia32_msgsys(int which, int a2, int a3, int a4, \ int a5, int a6); } -; 169 is initialized by the SYSVSHM code if present or loaded -; XXX should be { int msgsys(int which, ...); } -171 MNOSTD BSD { int shmsys(int which, int a2, int a3, int a4); } -; XXX should be { int shmsys(int which, ...); } +171 STD BSD { int ia32_shmsys(int which, int a2, int a3, int a4); } 172 UNIMPL NOHIDE nosys -173 MSTD POSIX { ssize_t pread(int fd, void *buf, size_t nbyte, \ - int pad, off_t offset); } -174 MSTD POSIX { ssize_t pwrite(int fd, const void *buf, \ - size_t nbyte, int pad, off_t offset); } +173 STD POSIX { ssize_t ia32_pread(int fd, void *buf, size_t nbyte, \ + int pad, u_int32_t offsetlo, u_int32_t offsethi); } +; XXX note - bigendian is different +174 STD POSIX { ssize_t ia32_pwrite(int fd, const void *buf, \ + size_t nbyte, int pad, u_int32_t offsetlo, \ + u_int32_t offsethi); } +; XXX note - bigendian is different 175 UNIMPL NOHIDE nosys -176 MSTD BSD { int ntp_adjtime(struct timex *tp); } +176 MNOPROTO BSD { int ntp_adjtime(struct timex *tp); } 177 UNIMPL NOHIDE sfork (BSD/OS 2.x) 178 UNIMPL NOHIDE getdescriptor (BSD/OS 2.x) 179 UNIMPL NOHIDE setdescriptor (BSD/OS 2.x) 180 UNIMPL NOHIDE nosys ; Syscalls 181-199 are used by/reserved for BSD -181 MSTD POSIX { int setgid(gid_t gid); } -182 MSTD BSD { int setegid(gid_t egid); } -183 MSTD BSD { int seteuid(uid_t euid); } +181 MNOPROTO POSIX { int setgid(gid_t gid); } +182 MNOPROTO BSD { int setegid(gid_t egid); } +183 MNOPROTO BSD { int seteuid(uid_t euid); } 184 UNIMPL BSD lfs_bmapv 185 UNIMPL BSD lfs_markv 186 UNIMPL BSD lfs_segclean 187 UNIMPL BSD lfs_segwait -188 STD POSIX { int stat(char *path, struct stat *ub); } -189 MSTD POSIX { int fstat(int fd, struct stat *sb); } -190 STD POSIX { int lstat(char *path, struct stat *ub); } -191 STD POSIX { int pathconf(char *path, int name); } -192 MSTD POSIX { int fpathconf(int fd, int name); } +188 STD POSIX { int ia32_stat(char *path, struct stat32 *ub); } +189 STD POSIX { int ia32_fstat(int fd, struct stat32 *ub); } +190 STD POSIX { int ia32_lstat(char *path, struct stat32 *ub); } +191 NOPROTO POSIX { int pathconf(char *path, int name); } +192 MNOPROTO POSIX { int fpathconf(int fd, int name); } 193 UNIMPL NOHIDE nosys -194 MSTD BSD { int getrlimit(u_int which, \ +194 MNOPROTO BSD { int getrlimit(u_int which, \ struct rlimit *rlp); } \ getrlimit __getrlimit_args int -195 MSTD BSD { int setrlimit(u_int which, \ +195 MNOPROTO BSD { int setrlimit(u_int which, \ struct rlimit *rlp); } \ setrlimit __setrlimit_args int -196 STD BSD { int getdirentries(int fd, char *buf, u_int count, \ +196 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \ long *basep); } -197 MSTD BSD { caddr_t mmap(caddr_t addr, size_t len, int prot, \ - int flags, int fd, int pad, off_t pos); } -198 STD NOHIDE { int nosys(void); } __syscall __syscall_args int -199 STD POSIX { off_t lseek(int fd, int pad, off_t offset, \ +197 STD BSD { caddr_t ia32_mmap(caddr_t addr, size_t len, \ + int prot, int flags, int fd, int pad, \ + u_int32_t poslo, u_int32_t poshi); } +198 NOPROTO NOHIDE { int nosys(void); } __syscall __syscall_args int +; XXX note - bigendian is different +199 STD POSIX { off_t ia32_lseek(int fd, int pad, \ + u_int32_t offsetlo, u_int32_t offsethi, \ int whence); } -200 STD BSD { int truncate(char *path, int pad, off_t length); } -201 STD BSD { int ftruncate(int fd, int pad, off_t length); } -202 MSTD BSD { int __sysctl(int *name, u_int namelen, void *old, \ - size_t *oldlenp, void *new, size_t newlen); } \ - __sysctl sysctl_args int -; properly, __sysctl should be a NOHIDE, but making an exception -; here allows to avoid one in libc/sys/Makefile.inc. -203 MSTD BSD { int mlock(const void *addr, size_t len); } -204 MSTD BSD { int munlock(const void *addr, size_t len); } -205 STD BSD { int undelete(char *path); } -206 STD BSD { int futimes(int fd, struct timeval *tptr); } -207 MSTD BSD { int getpgid(pid_t pid); } +; XXX note - bigendian is different +200 STD BSD { int ia32_truncate(char *path, int pad, \ + u_int32_t lengthlo, u_int32_t lengthhi); } +; XXX note - bigendian is different +201 STD BSD { int ia32_ftruncate(int fd, int pad, \ + u_int32_t lengthlo, u_int32_t lengthhi); } +202 MSTD BSD { int ia32_sysctl(int *name, u_int namelen, \ + void *old, u_int32_t *oldlenp, void *new, \ + u_int32_t newlen); } +203 MNOPROTO BSD { int mlock(const void *addr, size_t len); } +204 MNOPROTO BSD { int munlock(const void *addr, size_t len); } +205 NOPROTO BSD { int undelete(char *path); } +206 NOPROTO BSD { int futimes(int fd, struct timeval *tptr); } +207 MNOPROTO BSD { int getpgid(pid_t pid); } 208 UNIMPL NOHIDE newreboot (NetBSD) -209 MSTD BSD { int poll(struct pollfd *fds, u_int nfds, \ +209 MNOPROTO BSD { int poll(struct pollfd *fds, u_int nfds, \ int timeout); } ; ; The following are reserved for loadable syscalls ; -210 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -211 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -212 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -213 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -214 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -215 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -216 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -217 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -218 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -219 NODEF NOHIDE lkmnosys lkmnosys nosys_args int +210 UNIMPL NOHIDE +211 UNIMPL NOHIDE +212 UNIMPL NOHIDE +213 UNIMPL NOHIDE +214 UNIMPL NOHIDE +215 UNIMPL NOHIDE +216 UNIMPL NOHIDE +217 UNIMPL NOHIDE +218 UNIMPL NOHIDE +219 UNIMPL NOHIDE ; ; The following were introduced with NetBSD/4.4Lite-2 ; They are initialized by thier respective modules/sysinits -220 MNOSTD BSD { int __semctl(int semid, int semnum, int cmd, \ +220 MNOPROTO BSD { int __semctl(int semid, int semnum, int cmd, \ union semun *arg); } -221 MNOSTD BSD { int semget(key_t key, int nsems, int semflg); } -222 MNOSTD BSD { int semop(int semid, struct sembuf *sops, \ +221 MNOPROTO BSD { int semget(key_t key, int nsems, int semflg); } +222 MNOPROTO BSD { int semop(int semid, struct sembuf *sops, \ u_int nsops); } 223 UNIMPL NOHIDE semconfig -224 MNOSTD BSD { int msgctl(int msqid, int cmd, \ +224 MNOPROTO BSD { int msgctl(int msqid, int cmd, \ struct msqid_ds *buf); } -225 MNOSTD BSD { int msgget(key_t key, int msgflg); } -226 MNOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ +225 MNOPROTO BSD { int msgget(key_t key, int msgflg); } +226 MNOPROTO BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ int msgflg); } -227 MNOSTD BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \ +227 MNOPROTO BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \ long msgtyp, int msgflg); } -228 MNOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); } -229 MNOSTD BSD { int shmctl(int shmid, int cmd, \ +228 MNOPROTO BSD { int shmat(int shmid, void *shmaddr, int shmflg); } +229 MNOPROTO BSD { int shmctl(int shmid, int cmd, \ struct shmid_ds *buf); } -230 MNOSTD BSD { int shmdt(void *shmaddr); } -231 MNOSTD BSD { int shmget(key_t key, int size, int shmflg); } +230 MNOPROTO BSD { int shmdt(void *shmaddr); } +231 MNOPROTO BSD { int shmget(key_t key, int size, int shmflg); } ; -232 MSTD POSIX { int clock_gettime(clockid_t clock_id, \ +232 MNOPROTO POSIX { int clock_gettime(clockid_t clock_id, \ struct timespec *tp); } -233 MSTD POSIX { int clock_settime(clockid_t clock_id, \ +233 MNOPROTO POSIX { int clock_settime(clockid_t clock_id, \ const struct timespec *tp); } -234 MSTD POSIX { int clock_getres(clockid_t clock_id, \ +234 MNOPROTO POSIX { int clock_getres(clockid_t clock_id, \ struct timespec *tp); } 235 UNIMPL NOHIDE timer_create 236 UNIMPL NOHIDE timer_delete 237 UNIMPL NOHIDE timer_settime 238 UNIMPL NOHIDE timer_gettime 239 UNIMPL NOHIDE timer_getoverrun -240 MSTD POSIX { int nanosleep(const struct timespec *rqtp, \ +240 MNOPROTO POSIX { int nanosleep(const struct timespec *rqtp, \ struct timespec *rmtp); } 241 UNIMPL NOHIDE nosys 242 UNIMPL NOHIDE nosys 243 UNIMPL NOHIDE nosys 244 UNIMPL NOHIDE nosys 245 UNIMPL NOHIDE nosys 246 UNIMPL NOHIDE nosys 247 UNIMPL NOHIDE nosys 248 UNIMPL NOHIDE nosys 249 UNIMPL NOHIDE nosys ; syscall numbers initially used in OpenBSD -250 MSTD BSD { int minherit(void *addr, size_t len, int inherit); } -251 MSTD BSD { int rfork(int flags); } -252 MSTD BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \ +250 MNOPROTO BSD { int minherit(void *addr, size_t len, int inherit); } +251 MNOPROTO BSD { int rfork(int flags); } +252 MNOPROTO BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \ int timeout); } -253 STD BSD { int issetugid(void); } -254 STD BSD { int lchown(char *path, int uid, int gid); } +253 NOPROTO BSD { int issetugid(void); } +254 NOPROTO BSD { int lchown(char *path, int uid, int gid); } 255 UNIMPL NOHIDE nosys 256 UNIMPL NOHIDE nosys 257 UNIMPL NOHIDE nosys 258 UNIMPL NOHIDE nosys 259 UNIMPL NOHIDE nosys 260 UNIMPL NOHIDE nosys 261 UNIMPL NOHIDE nosys 262 UNIMPL NOHIDE nosys 263 UNIMPL NOHIDE nosys 264 UNIMPL NOHIDE nosys 265 UNIMPL NOHIDE nosys 266 UNIMPL NOHIDE nosys 267 UNIMPL NOHIDE nosys 268 UNIMPL NOHIDE nosys 269 UNIMPL NOHIDE nosys 270 UNIMPL NOHIDE nosys 271 UNIMPL NOHIDE nosys -272 STD BSD { int getdents(int fd, char *buf, size_t count); } +272 NOPROTO BSD { int getdents(int fd, char *buf, size_t count); } 273 UNIMPL NOHIDE nosys -274 STD BSD { int lchmod(char *path, mode_t mode); } +274 NOPROTO BSD { int lchmod(char *path, mode_t mode); } 275 NOPROTO BSD { int lchown(char *path, uid_t uid, gid_t gid); } netbsd_lchown lchown_args int -276 STD BSD { int lutimes(char *path, struct timeval *tptr); } +276 NOPROTO BSD { int lutimes(char *path, struct timeval *tptr); } 277 MNOPROTO BSD { int msync(void *addr, size_t len, int flags); } netbsd_msync msync_args int -278 STD BSD { int nstat(char *path, struct nstat *ub); } -279 MSTD BSD { int nfstat(int fd, struct nstat *sb); } -280 STD BSD { int nlstat(char *path, struct nstat *ub); } +278 NOPROTO BSD { int nstat(char *path, struct nstat *ub); } +279 MNOPROTO BSD { int nfstat(int fd, struct nstat *sb); } +280 NOPROTO BSD { int nlstat(char *path, struct nstat *ub); } 281 UNIMPL NOHIDE nosys 282 UNIMPL NOHIDE nosys 283 UNIMPL NOHIDE nosys 284 UNIMPL NOHIDE nosys 285 UNIMPL NOHIDE nosys 286 UNIMPL NOHIDE nosys 287 UNIMPL NOHIDE nosys 288 UNIMPL NOHIDE nosys 289 UNIMPL NOHIDE nosys 290 UNIMPL NOHIDE nosys 291 UNIMPL NOHIDE nosys 292 UNIMPL NOHIDE nosys 293 UNIMPL NOHIDE nosys 294 UNIMPL NOHIDE nosys 295 UNIMPL NOHIDE nosys 296 UNIMPL NOHIDE nosys ; XXX 297 is 300 in NetBSD -297 STD BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } -298 STD BSD { int fhopen(const struct fhandle *u_fhp, int flags); } -299 STD BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } +297 NOPROTO BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } +298 NOPROTO BSD { int fhopen(const struct fhandle *u_fhp, int flags); } +299 NOPROTO BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } ; syscall numbers for FreeBSD -300 MSTD BSD { int modnext(int modid); } -301 MSTD BSD { int modstat(int modid, struct module_stat* stat); } -302 MSTD BSD { int modfnext(int modid); } -303 MSTD BSD { int modfind(const char *name); } -304 MSTD BSD { int kldload(const char *file); } -305 MSTD BSD { int kldunload(int fileid); } -306 MSTD BSD { int kldfind(const char *file); } -307 MSTD BSD { int kldnext(int fileid); } -308 MSTD BSD { int kldstat(int fileid, struct kld_file_stat* stat); } -309 MSTD BSD { int kldfirstmod(int fileid); } -310 MSTD BSD { int getsid(pid_t pid); } -311 MSTD BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } -312 MSTD BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } +300 MNOPROTO BSD { int modnext(int modid); } +301 MNOPROTO BSD { int modstat(int modid, struct module_stat* stat); } +302 MNOPROTO BSD { int modfnext(int modid); } +303 MNOPROTO BSD { int modfind(const char *name); } +304 MNOPROTO BSD { int kldload(const char *file); } +305 MNOPROTO BSD { int kldunload(int fileid); } +306 MNOPROTO BSD { int kldfind(const char *file); } +307 MNOPROTO BSD { int kldnext(int fileid); } +308 MNOPROTO BSD { int kldstat(int fileid, struct kld_file_stat* stat); } +309 MNOPROTO BSD { int kldfirstmod(int fileid); } +310 MNOPROTO BSD { int getsid(pid_t pid); } +311 MNOPROTO BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } +312 MNOPROTO BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } 313 OBSOL NOHIDE signanosleep -314 NOSTD BSD { int aio_return(struct aiocb *aiocbp); } -315 NOSTD BSD { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } -316 NOSTD BSD { int aio_cancel(int fd, struct aiocb *aiocbp); } -317 NOSTD BSD { int aio_error(struct aiocb *aiocbp); } -318 NOSTD BSD { int aio_read(struct aiocb *aiocbp); } -319 NOSTD BSD { int aio_write(struct aiocb *aiocbp); } -320 NOSTD BSD { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); } -321 MSTD BSD { int yield(void); } +314 UNIMPL NOHIDE aio_return +315 UNIMPL NOHIDE aio_suspend +316 UNIMPL NOHIDE aio_cancel +317 UNIMPL NOHIDE aio_error +318 UNIMPL NOHIDE aio_read +319 UNIMPL NOHIDE aio_write +320 UNIMPL NOHIDE lio_listio +321 MNOPROTO BSD { int yield(void); } 322 OBSOL NOHIDE thr_sleep 323 OBSOL NOHIDE thr_wakeup -324 MSTD BSD { int mlockall(int how); } -325 MSTD BSD { int munlockall(void); } -326 STD BSD { int __getcwd(u_char *buf, u_int buflen); } +324 MNOPROTO BSD { int mlockall(int how); } +325 MNOPROTO BSD { int munlockall(void); } +326 NOPROTO BSD { int __getcwd(u_char *buf, u_int buflen); } -327 MSTD POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); } -328 MSTD POSIX { int sched_getparam (pid_t pid, struct sched_param *param); } +327 MNOPROTO POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); } +328 MNOPROTO POSIX { int sched_getparam (pid_t pid, struct sched_param *param); } -329 MSTD POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } -330 MSTD POSIX { int sched_getscheduler (pid_t pid); } +329 MNOPROTO POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } +330 MNOPROTO POSIX { int sched_getscheduler (pid_t pid); } -331 MSTD POSIX { int sched_yield (void); } -332 MSTD POSIX { int sched_get_priority_max (int policy); } -333 MSTD POSIX { int sched_get_priority_min (int policy); } -334 MSTD POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); } -335 STD BSD { int utrace(const void *addr, size_t len); } -336 MSTD BSD { int sendfile(int fd, int s, off_t offset, size_t nbytes, \ - struct sf_hdtr *hdtr, off_t *sbytes, int flags); } -337 STD BSD { int kldsym(int fileid, int cmd, void *data); } -338 MSTD BSD { int jail(struct jail *jail); } +331 MNOPROTO POSIX { int sched_yield (void); } +332 MNOPROTO POSIX { int sched_get_priority_max (int policy); } +333 MNOPROTO POSIX { int sched_get_priority_min (int policy); } +334 MNOPROTO POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); } +335 NOPROTO BSD { int utrace(const void *addr, size_t len); } +; XXX note - bigendian is different +336 MSTD BSD { int ia32_sendfile(int fd, int s, u_int32_t offsetlo, \ + u_int32_t offsethi, size_t nbytes, \ + struct sf_hdtr *hdtr, off_t *sbytes, int flags); } +337 NOPROTO BSD { int kldsym(int fileid, int cmd, void *data); } +338 MNOPROTO BSD { int jail(struct jail *jail); } 339 UNIMPL BSD pioctl -340 MSTD POSIX { int sigprocmask(int how, const sigset_t *set, \ +340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \ sigset_t *oset); } -341 MSTD POSIX { int sigsuspend(const sigset_t *sigmask); } -342 MSTD POSIX { int sigaction(int sig, const struct sigaction *act, \ - struct sigaction *oact); } -343 MSTD POSIX { int sigpending(sigset_t *set); } -344 STD BSD { int sigreturn(const struct __ucontext *sigcntxp); } +341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); } +342 STD POSIX { int ia32_sigaction(int sig, \ + struct sigaction32 *act, \ + struct sigaction32 *oact); } +343 MNOPROTO POSIX { int sigpending(sigset_t *set); } +344 MNOPROTO BSD { int sigreturn(const struct __ucontext *sigcntxp); } 345 UNIMPL NOHIDE sigtimedwait 346 UNIMPL NOHIDE sigwaitinfo -347 MSTD BSD { int __acl_get_file(const char *path, \ +347 MNOPROTO BSD { int __acl_get_file(const char *path, \ acl_type_t type, struct acl *aclp); } -348 MSTD BSD { int __acl_set_file(const char *path, \ +348 MNOPROTO BSD { int __acl_set_file(const char *path, \ acl_type_t type, struct acl *aclp); } -349 MSTD BSD { int __acl_get_fd(int filedes, acl_type_t type, \ +349 MNOPROTO BSD { int __acl_get_fd(int filedes, acl_type_t type, \ struct acl *aclp); } -350 MSTD BSD { int __acl_set_fd(int filedes, acl_type_t type, \ +350 MNOPROTO BSD { int __acl_set_fd(int filedes, acl_type_t type, \ struct acl *aclp); } -351 MSTD BSD { int __acl_delete_file(const char *path, \ +351 MNOPROTO BSD { int __acl_delete_file(const char *path, \ acl_type_t type); } -352 MSTD BSD { int __acl_delete_fd(int filedes, acl_type_t type); } -353 MSTD BSD { int __acl_aclcheck_file(const char *path, \ +352 MNOPROTO BSD { int __acl_delete_fd(int filedes, acl_type_t type); } +353 MNOPROTO BSD { int __acl_aclcheck_file(const char *path, \ acl_type_t type, struct acl *aclp); } -354 MSTD BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \ +354 MNOPROTO BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \ struct acl *aclp); } -355 STD BSD { int extattrctl(const char *path, int cmd, \ +355 NOPROTO BSD { int extattrctl(const char *path, int cmd, \ const char *filename, int attrnamespace, \ const char *attrname); } -356 STD BSD { int extattr_set_file(const char *path, \ +356 NOPROTO BSD { int extattr_set_file(const char *path, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } -357 STD BSD { ssize_t extattr_get_file(const char *path, \ +357 NOPROTO BSD { ssize_t extattr_get_file(const char *path, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } -358 STD BSD { int extattr_delete_file(const char *path, \ +358 NOPROTO BSD { int extattr_delete_file(const char *path, \ int attrnamespace, const char *attrname); } -359 NOSTD BSD { int aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); } -360 MSTD BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } -361 MSTD BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } -362 MSTD BSD { int kqueue(void); } -363 MSTD BSD { int kevent(int fd, \ +359 UNIMPL NOHIDE aio_waitcomplete +360 MNOPROTO BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } +361 MNOPROTO BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } +362 MNOPROTO BSD { int kqueue(void); } +363 MNOPROTO BSD { int kevent(int fd, \ const struct kevent *changelist, int nchanges, \ struct kevent *eventlist, int nevents, \ const struct timespec *timeout); } -364 STD BSD { int __cap_get_proc(struct cap *cap_p); } -365 STD BSD { int __cap_set_proc(struct cap *cap_p); } -366 STD BSD { int __cap_get_fd(int fd, struct cap *cap_p); } -367 STD BSD { int __cap_get_file(const char *path_p, struct cap *cap_p); } -368 STD BSD { int __cap_set_fd(int fd, struct cap *cap_p); } -369 STD BSD { int __cap_set_file(const char *path_p, struct cap *cap_p); } -370 NODEF NOHIDE lkmressys lkmressys nosys_args int -371 STD BSD { int extattr_set_fd(int fd, int attrnamespace, \ +364 UNIMPL NOHIDE __cap_get_proc +365 UNIMPL NOHIDE __cap_set_proc +366 UNIMPL NOHIDE __cap_get_fd +367 UNIMPL NOHIDE __cap_get_file +368 UNIMPL NOHIDE __cap_set_fd +369 UNIMPL NOHIDE __cap_set_file +370 UNIMPL NOHIDE lkmressys +371 NOPROTO BSD { int extattr_set_fd(int fd, int attrnamespace, \ const char *attrname, void *data, \ size_t nbytes); } -372 STD BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \ +372 NOPROTO BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \ const char *attrname, void *data, size_t nbytes); } -373 STD BSD { int extattr_delete_fd(int fd, int attrnamespace, \ +373 NOPROTO BSD { int extattr_delete_fd(int fd, int attrnamespace, \ const char *attrname); } -374 MSTD BSD { int __setugid(int flag); } -375 NOIMPL BSD { int nfsclnt(int flag, caddr_t argp); } -376 STD BSD { int eaccess(char *path, int flags); } +374 MNOPROTO BSD { int __setugid(int flag); } +375 UNIMPL BSD nfsclnt +376 NOPROTO BSD { int eaccess(char *path, int flags); } 377 UNIMPL BSD afs_syscall -378 STD BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \ +378 NOPROTO BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \ int flags); } -379 STD BSD { int kse_exit(void); } -380 STD BSD { int kse_wakeup(void); } -381 STD BSD { int kse_new(struct kse_mailbox * mbx, \ +379 NOPROTO BSD { int kse_exit(void); } +380 NOPROTO BSD { int kse_wakeup(void); } +381 NOPROTO BSD { int kse_new(struct kse_mailbox * mbx, \ int new_grp_flag); } -382 STD BSD { int thread_wakeup(struct thread_mailbox *tmbx); } -383 STD BSD { int kse_yield(void); } +382 NOPROTO BSD { int thread_wakeup(struct thread_mailbox *tmbx); } +383 NOPROTO BSD { int kse_yield(void); } 384 UNIMPL BSD __mac_get_proc 385 UNIMPL BSD __mac_set_proc 386 UNIMPL BSD __mac_get_fd 387 UNIMPL BSD __mac_get_file 388 UNIMPL BSD __mac_set_fd 389 UNIMPL BSD __mac_set_file +390 NOPROTO BSD { int kenv(int what, const char *name, char *value, \ + int len); } +391 NOPROTO BSD { int lchflags(const char *path, int flags); } +392 NOPROTO BSD { int uuidgen(struct uuid *store, int count); } Index: head/sys/compat/ia32/ia32_sysvec.c =================================================================== --- head/sys/compat/ia32/ia32_sysvec.c (nonexistent) +++ head/sys/compat/ia32/ia32_sysvec.c (revision 100384) @@ -0,0 +1,365 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#define __ELF_WORD_SIZE 32 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static register_t *ia32_copyout_strings(struct image_params *imgp); +static void ia32_setregs(struct thread *td, u_long entry, u_long stack, + u_long ps_strings); + +extern struct sysent ia32_sysent[]; + +static char ia32_sigcode[] = { + 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */ + 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */ + 0x50, /* pushl %eax */ + 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */ + 0x75, 0x03, /* jne 9f */ + 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */ + 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */ + 0x50, /* pushl %eax */ + 0xcd, 0x80, /* int $0x80 */ + 0xeb, 0xfe, /* 0: jmp 0b */ + 0, 0, 0, 0 +}; +static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3; + +struct sysentvec ia32_freebsd_sysvec = { + SYS_MAXSYSCALL, + ia32_sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + ia32_sigcode, + &ia32_szsigcode, + 0, + "FreeBSD ELF", + elf32_coredump, + NULL, + MINSIGSTKSZ, + 4096, + IA32_USRSTACK, + IA32_USRSTACK, + ia32_copyout_strings, + ia32_setregs +}; + +static Elf32_Brandinfo ia32_brand_info = { + ELFOSABI_FREEBSD, + EM_386, + "FreeBSD", + "/compat/ia32", + "/usr/libexec/ld-elf.so.1", + &ia32_freebsd_sysvec + }; + +SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &ia32_brand_info); + +static register_t * +ia32_copyout_strings(struct image_params *imgp) +{ + int argc, envc; + u_int32_t *vectp; + char *stringp, *destp; + u_int32_t *stack_base; + struct ia32_ps_strings *arginfo; + int szsigcode; + + /* + * Calculate string base and vector table pointers. + * Also deal with signal trampoline code for this exec type. + */ + arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS; + szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); + destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - + roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + + /* + * install sigcode + */ + if (szsigcode) + copyout(imgp->proc->p_sysent->sv_sigcode, + ((caddr_t)arginfo - szsigcode), szsigcode); + + /* + * If we have a valid auxargs ptr, prepare some room + * on the stack. + */ + if (imgp->auxargs) { + /* + * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for + * lower compatibility. + */ + imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size + : (AT_COUNT * 2); + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets,and imgp->auxarg_size is room + * for argument of Runtime loader. + */ + vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + + imgp->auxarg_size) * sizeof(u_int32_t)); + + } else + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets + */ + vectp = (u_int32_t *) + (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); + + /* + * vectp also becomes our initial stack base + */ + stack_base = vectp; + + stringp = imgp->stringbase; + argc = imgp->argc; + envc = imgp->envc; + + /* + * Copy out strings - arguments and environment. + */ + copyout(stringp, destp, ARG_MAX - imgp->stringspace); + + /* + * Fill in "ps_strings" struct for ps, w, etc. + */ + suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nargvstr, argc); + + /* + * Fill in argument portion of vector table. + */ + for (; argc > 0; --argc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* a null vector table pointer separates the argp's from the envp's */ + suword32(vectp++, 0); + + suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nenvstr, envc); + + /* + * Fill in environment portion of vector table. + */ + for (; envc > 0; --envc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* end of vector table is a null pointer */ + suword32(vectp, 0); + + return ((register_t *)stack_base); +} + +static void +ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +{ + struct trapframe *frame = td->td_frame; + vm_offset_t gdt, ldt; + u_int64_t codesel, datasel, ldtsel; + u_int64_t codeseg, dataseg, gdtseg, ldtseg; + struct segment_descriptor desc; + struct vmspace *vmspace = td->td_proc->p_vmspace; + + /* + * Make sure that we restore the entire trapframe after an + * execve. + */ + frame->tf_flags &= ~FRAME_SYSCALL; + + bzero(frame->tf_r, sizeof(frame->tf_r)); + bzero(frame->tf_f, sizeof(frame->tf_f)); + + frame->tf_cr_iip = entry; + frame->tf_cr_ipsr = (IA64_PSR_IC + | IA64_PSR_I + | IA64_PSR_IT + | IA64_PSR_DT + | IA64_PSR_RT + | IA64_PSR_DFH + | IA64_PSR_IS + | IA64_PSR_BN + | IA64_PSR_CPL_USER); + frame->tf_r[FRAME_R12] = stack; + + codesel = LSEL(LUCODE_SEL, SEL_UPL); + datasel = LSEL(LUDATA_SEL, SEL_UPL); + ldtsel = GSEL(GLDT_SEL, SEL_UPL); + +#if 1 + frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32) + | (datasel << 16) | datasel; + frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel; +#else + frame->tf_r[FRAME_R16] = datasel; + frame->tf_r[FRAME_R17] = codesel; + frame->tf_r[FRAME_R18] = datasel; + frame->tf_r[FRAME_R19] = datasel; + frame->tf_r[FRAME_R20] = datasel; + frame->tf_r[FRAME_R21] = datasel; + frame->tf_r[FRAME_R22] = ldtsel; +#endif + + /* + * Build the GDT and LDT. + */ + gdt = IA32_USRSTACK; + vm_map_find(&vmspace->vm_map, 0, 0, + &gdt, PAGE_SIZE, 0, + VM_PROT_ALL, VM_PROT_ALL, 0); + ldt = gdt + 4096; + + desc.sd_lolimit = 8*NLDT-1; + desc.sd_lobase = ldt & 0xffffff; + desc.sd_type = SDT_SYSLDT; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = 0; + desc.sd_def32 = 0; + desc.sd_gran = 0; + desc.sd_hibase = ldt >> 24; + copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc)); + + desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff; + desc.sd_lobase = 0; + desc.sd_type = SDT_MEMERA; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16; + desc.sd_def32 = 1; + desc.sd_gran = 1; + desc.sd_hibase = 0; + copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc)); + desc.sd_type = SDT_MEMRWA; + copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc)); + + codeseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMERA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + dataseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMRWA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + ia64_set_csd(codeseg); + ia64_set_ssd(dataseg); + frame->tf_r[FRAME_R24] = dataseg; /* ESD */ + frame->tf_r[FRAME_R27] = dataseg; /* DSD */ + frame->tf_r[FRAME_R28] = dataseg; /* FSD */ + frame->tf_r[FRAME_R29] = dataseg; /* GSD */ + + gdtseg = gdt /* base */ + + ((8L*NGDT - 1) << 32) /* limit */ + + ((long)SDT_SYSNULL << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + ldtseg = ldt /* base */ + + ((8L*NLDT - 1) << 32) /* limit */ + + ((long)SDT_SYSLDT << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */ + frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */ + + ia64_set_eflag(PSL_USER); + + /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ + frame->tf_r[FRAME_R11] = IA32_PS_STRINGS; + + /* + * XXX - Linux emulator + * Make sure sure edx is 0x0 on entry. Linux binaries depend + * on it. + */ + td->td_retval[1] = 0; +} Property changes on: head/sys/compat/ia32/ia32_sysvec.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/compat/ia32/ia32_util.h =================================================================== --- head/sys/compat/ia32/ia32_util.h (nonexistent) +++ head/sys/compat/ia32/ia32_util.h (revision 100384) @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 1998-1999 Andrew Gallatin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + + +#include +#include +#include + + +#ifndef SCARG +#define SCARG(p, x) (p)->x +#endif + +struct ia32_ps_strings { + u_int32_t ps_argvstr; /* first of 0 or more argument strings */ + int ps_nargvstr; /* the number of argument strings */ + u_int32_t ps_envstr; /* first of 0 or more environment strings */ + int ps_nenvstr; /* the number of environment strings */ +}; + +#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE) +#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings)) + +static __inline caddr_t stackgap_init(void); +static __inline void *stackgap_alloc(caddr_t *, size_t); + +static __inline caddr_t +stackgap_init() +{ +#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) + return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE); +#undef szsigcode +} + +static __inline void * +stackgap_alloc(sgp, sz) + caddr_t *sgp; + size_t sz; +{ + void *p; + + p = (void *) *sgp; + *sgp += ALIGN(sz); + return p; +} + + +extern const char ia32_emul_path[]; +int ia32_emul_find(struct thread *, caddr_t *, const char *, char *, + char **, int); + +#define CHECKALT(p, sgp, path, i) \ + do { \ + int _error; \ + \ + _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \ + &path, i); \ + if (_error == EFAULT) \ + return (_error); \ + } while (0) + +#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0) +#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1) Property changes on: head/sys/compat/ia32/ia32_util.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/compat/pecoff/imgact_pecoff.c =================================================================== --- head/sys/compat/pecoff/imgact_pecoff.c (revision 100383) +++ head/sys/compat/pecoff/imgact_pecoff.c (revision 100384) @@ -1,649 +1,649 @@ /* $NetBSD$ */ /* $FreeBSD$ */ /* * Copyright (c) 2000 Masaru OKI * Copyright (c) 1994, 1995, 1998 Scott Bartram * Copyright (c) 1994 Adam Glass * Copyright (c) 1993, 1994 Christopher G. Demetriou * * originally from NetBSD kern/exec_ecoff.c * * Copyright (c) 2000 Takanori Watanabe * Copyright (c) 2000 KUROSAWA Takahiro * Copyright (c) 1995-1996 Sen Schmidt * Copyright (c) 1996 Peter Wemm * All rights reserved. * * originally from FreeBSD kern/imgact_elf.c * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Masaru OKI. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "opt_pecoff.h" #define PECOFF_PE_SIGNATURE "PE\0\0" static int pecoff_fixup(register_t **, struct image_params *); static int pecoff_coredump(register struct thread *, register struct vnode *, off_t); #ifndef PECOFF_DEBUG #define DPRINTF(a) #else #define DPRINTF(a) printf a #endif static struct sysentvec pecoff_sysvec = { SYS_MAXSYSCALL, sysent, 0, 0, 0, 0, 0, 0, pecoff_fixup, sendsig, sigcode, &szsigcode, 0, "FreeBSD PECoff", pecoff_coredump, NULL, MINSIGSTKSZ }; static const char signature[] = PECOFF_PE_SIGNATURE; static int exec_pecoff_coff_prep_omagic(struct image_params *, struct coff_filehdr *, struct coff_aouthdr *, int peoffs); static int exec_pecoff_coff_prep_nmagic(struct image_params *, struct coff_filehdr *, struct coff_aouthdr *, int peoffs); static int exec_pecoff_coff_prep_zmagic(struct image_params *, struct coff_filehdr *, struct coff_aouthdr *, int peoffs); static int exec_pecoff_coff_makecmds(struct image_params *, struct coff_filehdr *, int); static int pecoff_signature(struct thread *, struct vnode *, const struct pecoff_dos_filehdr *); static int pecoff_read_from(struct thread *, struct vnode *, int, caddr_t, int); static int pecoff_load_section(struct thread * td, struct vmspace * vmspace, struct vnode * vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot); static int pecoff_fixup(register_t ** stack_base, struct image_params * imgp) { int len = sizeof(struct pecoff_args); struct pecoff_imghdr *ap; register_t *pos; pos = *stack_base + (imgp->argc + imgp->envc + 2); ap = (struct pecoff_imghdr *) imgp->auxargs; if (copyout(ap, pos, len)) { return NULL; } free(ap, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; suword(*stack_base, (long) imgp->argc); return 0; } static int pecoff_coredump(register struct thread * td, register struct vnode * vp, off_t limit) { register struct ucred *cred = td->td_ucred; struct proc *p = td->td_proc; register struct vmspace *vm = p->p_vmspace; int error; #ifdef PECOFF_DEBUG struct vm_map *map; struct vm_map_entry *ent; struct reg regs; #endif if (ctob((UAREA_PAGES+KSTACK_PAGES) + vm->vm_dsize + vm->vm_ssize) >= limit) return (EFAULT); PROC_LOCK(p); fill_kinfo_proc(p, &p->p_uarea->u_kproc); PROC_UNLOCK(p); #if PECOFF_DEBUG fill_regs(td, ®s); printf("EIP%x\n", regs.r_eip); printf("EAX%x EBX%x ECX%x EDI%x\n", regs.r_eax, regs.r_ebx, regs.r_ecx, regs.r_edi); map = &vm->vm_map; ent = &map->header; printf("%p %p %p\n", ent, ent->prev, ent->next); #endif error = cpu_coredump(td, vp, cred); if (error == 0) error = vn_rdwr_inchunks(UIO_WRITE, vp, vm->vm_daddr, (int)ctob(vm->vm_dsize), (off_t)ctob((UAREA_PAGES+KSTACK_PAGES)), UIO_USERSPACE, IO_UNIT, cred, (int *)NULL, td); if (error == 0) error = vn_rdwr_inchunks(UIO_WRITE, vp, (caddr_t)trunc_page(USRSTACK - ctob(vm->vm_ssize)), round_page(ctob(vm->vm_ssize)), (off_t)ctob((UAREA_PAGES+KSTACK_PAGES)) + ctob(vm->vm_dsize), UIO_USERSPACE, IO_UNIT, cred, (int *)NULL, td); return (error); } static int pecoff_load_section(struct thread * td, struct vmspace * vmspace, struct vnode * vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) { size_t map_len; vm_offset_t map_addr; int error, rv; size_t copy_len; size_t copy_map_len; size_t copy_start; vm_object_t object; vm_offset_t copy_map_offset; vm_offset_t file_addr; vm_offset_t data_buf = 0; object = vp->v_object; error = 0; map_addr = trunc_page((vm_offset_t) vmaddr); file_addr = trunc_page(offset); DPRINTF(("SECARG:%x %p %x %x\n", offset, vmaddr, memsz, filsz)); if (file_addr != offset) { /* * The section is not on page boundary. We can't use * vm_map_insert(). Use copyin instead. */ map_len = round_page(memsz); copy_len = filsz; copy_map_offset = file_addr; copy_map_len = round_page(offset + filsz) - file_addr; copy_start = offset - file_addr; DPRINTF(("offset=%x vmaddr=%lx filsz=%x memsz=%x\n", offset, (long)vmaddr, filsz, memsz)); DPRINTF(("map_len=%x copy_len=%x copy_map_offset=%x" " copy_map_len=%x copy_start=%x\n", map_len, copy_len, copy_map_offset, copy_map_len, copy_start)); } else { map_len = trunc_page(filsz); if (map_len != 0) { vm_object_reference(object); vm_map_lock(&vmspace->vm_map); rv = vm_map_insert(&vmspace->vm_map, object, file_addr, /* file offset */ map_addr, /* virtual start */ map_addr + map_len, /* virtual end */ prot, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT); vm_map_unlock(&vmspace->vm_map); if (rv != KERN_SUCCESS) { vm_object_deallocate(object); return EINVAL; } /* we can stop now if we've covered it all */ if (memsz == filsz) return 0; } copy_map_offset = trunc_page(offset + filsz); copy_map_len = PAGE_SIZE; copy_start = 0; copy_len = (offset + filsz) - trunc_page(offset + filsz); map_addr = trunc_page((vm_offset_t) vmaddr + filsz); map_len = round_page((vm_offset_t) vmaddr + memsz) - map_addr; } if (map_len != 0) { vm_map_lock(&vmspace->vm_map); rv = vm_map_insert(&vmspace->vm_map, NULL, 0, map_addr, map_addr + map_len, VM_PROT_ALL, VM_PROT_ALL, 0); vm_map_unlock(&vmspace->vm_map); DPRINTF(("EMP-rv:%d,%x %x\n", rv, map_addr, map_addr + map_len)); if (rv != KERN_SUCCESS) { return EINVAL; } } DPRINTF(("COPYARG %x %x\n", map_addr, copy_len)); if (copy_len != 0) { vm_object_reference(object); rv = vm_map_find(exec_map, object, copy_map_offset, &data_buf, copy_map_len, TRUE, VM_PROT_READ, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); if (rv != KERN_SUCCESS) { vm_object_deallocate(object); return EINVAL; } /* send the page fragment to user space */ error = copyout((caddr_t) data_buf + copy_start, (caddr_t) map_addr, copy_len); vm_map_remove(exec_map, data_buf, data_buf + copy_map_len); DPRINTF(("%d\n", error)); if (error) return (error); } /* * set it to the specified protection */ vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot, FALSE); return error; } static int pecoff_load_file(struct thread * td, const char *file, u_long * addr, u_long * entry, u_long * ldexport) { struct nameidata nd; struct pecoff_dos_filehdr dh; struct coff_filehdr *fp = 0; struct coff_aouthdr *ap; struct pecoff_opthdr *wp; struct coff_scnhdr *sh = 0; struct vmspace *vmspace = td->td_proc->p_vmspace; struct vattr attr; struct image_params image_params, *imgp; int peofs; int error, i, scnsiz; imgp = &image_params; /* * Initialize part of the common data */ imgp->proc = td->td_proc; imgp->uap = NULL; imgp->attr = &attr; imgp->firstpage = NULL; NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, td); if ((error = namei(&nd)) != 0) { nd.ni_vp = NULL; goto fail; } NDFREE(&nd, NDF_ONLY_PNBUF); imgp->vp = nd.ni_vp; /* * Check permissions, modes, uid, etc on the file, and "open" it. */ error = exec_check_permissions(imgp); if (error) { VOP_UNLOCK(nd.ni_vp, 0, td); goto fail; } VOP_UNLOCK(nd.ni_vp, 0, td); if (error) goto fail; if ((error = pecoff_read_from(td, imgp->vp, 0, (caddr_t) & dh, sizeof(dh))) != 0) goto fail; if ((error = pecoff_signature(td, imgp->vp, &dh) != 0)) goto fail; fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK); peofs = dh.d_peofs + sizeof(signature) - 1; if ((error = pecoff_read_from(td, imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE) != 0)) goto fail; if (COFF_BADMAG(fp)) { error = ENOEXEC; goto fail; } ap = (void *) ((char *) fp + sizeof(struct coff_filehdr)); wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr)); /* read section header */ scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns; sh = malloc(scnsiz, M_TEMP, M_WAITOK); if ((error = pecoff_read_from(td, imgp->vp, peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz)) != 0) goto fail; /* * Read Section infomation and map sections. */ for (i = 0; i < fp->f_nscns; i++) { int prot = 0; if (sh[i].s_flags & COFF_STYP_DISCARD) continue; /* XXX ? */ if ((sh[i].s_flags & COFF_STYP_TEXT) && (sh[i].s_flags & COFF_STYP_EXEC) == 0) continue; if ((sh[i].s_flags & (COFF_STYP_TEXT | COFF_STYP_DATA | COFF_STYP_BSS)) == 0) continue; prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0; prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0; prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0; sh[i].s_vaddr += wp->w_base; /* RVA --> VA */ if ((error = pecoff_load_section(td, vmspace, imgp->vp, sh[i].s_scnptr ,(caddr_t) sh[i].s_vaddr, sh[i].s_paddr, sh[i].s_size ,prot)) != 0) goto fail; } *entry = wp->w_base + ap->a_entry; *addr = wp->w_base; *ldexport = wp->w_imghdr[0].i_vaddr + wp->w_base; fail: if (fp) free(fp, M_TEMP); if (sh) free(sh, M_TEMP); if (nd.ni_vp) vrele(nd.ni_vp); return error; } static int exec_pecoff_coff_prep_omagic(struct image_params * imgp, struct coff_filehdr * fp, struct coff_aouthdr * ap, int peofs) { return ENOEXEC; } static int exec_pecoff_coff_prep_nmagic(struct image_params * imgp, struct coff_filehdr * fp, struct coff_aouthdr * ap, int peofs) { return ENOEXEC; } static int exec_pecoff_coff_prep_zmagic(struct image_params * imgp, struct coff_filehdr * fp, struct coff_aouthdr * ap, int peofs) { int scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns; int error = ENOEXEC, i; int prot; u_long text_size = 0, data_size = 0, dsize; u_long text_addr = 0, data_addr = VM_MAXUSER_ADDRESS; u_long ldexport, ldbase; struct pecoff_opthdr *wp; struct coff_scnhdr *sh; struct vmspace *vmspace; struct pecoff_args *argp = NULL; sh = malloc(scnsiz, M_TEMP, M_WAITOK); wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr)); error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp, peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz); if ((error = exec_extract_strings(imgp)) != 0) goto fail; - exec_new_vmspace(imgp); + exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); vmspace = imgp->proc->p_vmspace; for (i = 0; i < fp->f_nscns; i++) { prot = VM_PROT_WRITE; /* XXX for relocation? */ prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0; prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0; prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0; sh[i].s_vaddr += wp->w_base; if (sh[i].s_flags & COFF_STYP_DISCARD) continue; if ((sh[i].s_flags & COFF_STYP_TEXT) != 0) { error = pecoff_load_section( FIRST_THREAD_IN_PROC(imgp->proc), vmspace, imgp->vp, sh[i].s_scnptr, (caddr_t) sh[i].s_vaddr, sh[i].s_paddr, sh[i].s_size ,prot); DPRINTF(("ERROR%d\n", error)); if (error) goto fail; text_addr = trunc_page(sh[i].s_vaddr); text_size = trunc_page(sh[i].s_size + sh[i].s_vaddr - text_addr); } if ((sh[i].s_flags & (COFF_STYP_DATA|COFF_STYP_BSS)) != 0) { if (pecoff_load_section( FIRST_THREAD_IN_PROC(imgp->proc), vmspace, imgp->vp, sh[i].s_scnptr, (caddr_t) sh[i].s_vaddr, sh[i].s_paddr, sh[i].s_size, prot) != 0) goto fail; data_addr = min(trunc_page(sh[i].s_vaddr), data_addr); dsize = round_page(sh[i].s_vaddr + sh[i].s_paddr) - data_addr; data_size = max(dsize, data_size); } } vmspace->vm_tsize = text_size >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t) (uintptr_t) text_addr; vmspace->vm_dsize = data_size >> PAGE_SHIFT; vmspace->vm_daddr = (caddr_t) (uintptr_t) data_addr; argp = malloc(sizeof(struct pecoff_args), M_TEMP, M_WAITOK); if (argp == NULL) { error = ENOMEM; goto fail; } argp->a_base = wp->w_base; argp->a_entry = wp->w_base + ap->a_entry; argp->a_end = data_addr + data_size; argp->a_subsystem = wp->w_subvers; error = pecoff_load_file(FIRST_THREAD_IN_PROC(imgp->proc), "/usr/libexec/ld.so.dll", &ldbase, &imgp->entry_addr, &ldexport); if (error) goto fail; argp->a_ldbase = ldbase; argp->a_ldexport = ldexport; memcpy(argp->a_imghdr, wp->w_imghdr, sizeof(struct pecoff_imghdr) * 16); for (i = 0; i < 16; i++) { argp->a_imghdr[i].i_vaddr += wp->w_base; } imgp->proc->p_sysent = &pecoff_sysvec; if (error) goto fail; imgp->auxargs = argp; imgp->auxarg_size = sizeof(struct pecoff_args); imgp->interpreted = 0; imgp->vp->v_flag |= VTEXT; if (sh != NULL) free(sh, M_TEMP); return 0; fail: error = (error) ? error : ENOEXEC; if (sh != NULL) free(sh, M_TEMP); if (argp != NULL) free(argp, M_TEMP); return error; } int exec_pecoff_coff_makecmds(struct image_params * imgp, struct coff_filehdr * fp, int peofs) { struct coff_aouthdr *ap; int error; if (COFF_BADMAG(fp)) { return ENOEXEC; } ap = (void *) ((char *) fp + sizeof(struct coff_filehdr)); switch (ap->a_magic) { case COFF_OMAGIC: error = exec_pecoff_coff_prep_omagic(imgp, fp, ap, peofs); break; case COFF_NMAGIC: error = exec_pecoff_coff_prep_nmagic(imgp, fp, ap, peofs); break; case COFF_ZMAGIC: error = exec_pecoff_coff_prep_zmagic(imgp, fp, ap, peofs); break; default: return ENOEXEC; } return error; } static int pecoff_signature(td, vp, dp) struct thread *td; struct vnode *vp; const struct pecoff_dos_filehdr *dp; { int error; char buf[512]; char *pesig; if (DOS_BADMAG(dp)) { return ENOEXEC; } error = pecoff_read_from(td, vp, dp->d_peofs, buf, sizeof(buf)); if (error) { return error; } pesig = buf; if (memcmp(pesig, signature, sizeof(signature) - 1) == 0) { return 0; } return EFTYPE; } int pecoff_read_from(td, vp, pos, buf, siz) struct thread *td; struct vnode *vp; int pos; caddr_t buf; int siz; { int error; size_t resid; error = vn_rdwr(UIO_READ, vp, buf, siz, pos, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, &resid, td); if (error) return error; if (resid != 0) { return ENOEXEC; } return 0; } static int imgact_pecoff(struct image_params * imgp) { const struct pecoff_dos_filehdr *dp = (const struct pecoff_dos_filehdr *) imgp->image_header; struct coff_filehdr *fp; int error, peofs; error = pecoff_signature(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp, dp); if (error) { return -1; } peofs = dp->d_peofs + sizeof(signature) - 1; fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK); error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE); if (error) { free(fp, M_TEMP); return error; } error = exec_pecoff_coff_makecmds(imgp, fp, peofs); free(fp, M_TEMP); return error; } static struct execsw pecoff_execsw = {imgact_pecoff, "FreeBSD PEcoff"}; EXEC_SET(pecoff, pecoff_execsw); Index: head/sys/compat/svr4/imgact_svr4.c =================================================================== --- head/sys/compat/svr4/imgact_svr4.c (revision 100383) +++ head/sys/compat/svr4/imgact_svr4.c (revision 100384) @@ -1,240 +1,240 @@ /*- * Copyright (c) 1998 Mark Newton * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Based heavily on /sys/kern/imgact_aout.c which is: * Copyright (c) 1993, David Greenman * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int exec_svr4_imgact(struct image_params *iparams); static int exec_svr4_imgact(imgp) struct image_params *imgp; { const struct exec *a_out = (const struct exec *) imgp->image_header; struct vmspace *vmspace; vm_offset_t vmaddr; unsigned long virtual_offset, file_offset; vm_offset_t buffer; unsigned long bss_size; int error; if (((a_out->a_magic >> 16) & 0xff) != 0x64) return -1; /* * Set file/virtual offset based on a.out variant. */ switch ((int)(a_out->a_magic & 0xffff)) { case 0413: virtual_offset = 0; file_offset = 1024; break; case 0314: virtual_offset = 4096; file_offset = 0; break; default: return (-1); } bss_size = round_page(a_out->a_bss); #ifdef DEBUG printf("imgact: text: %08lx, data: %08lx, bss: %08lx\n", a_out->a_text, a_out->a_data, bss_size); #endif /* * Check various fields in header for validity/bounds. */ if (a_out->a_entry < virtual_offset || a_out->a_entry >= virtual_offset + a_out->a_text || a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) return (-1); /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > imgp->attr->va_size) return (EFAULT); /* For p_rlimit below. */ mtx_assert(&Giant, MA_OWNED); /* * text/data/bss must not exceed limits */ if (a_out->a_text > maxtsiz || a_out->a_data + bss_size > imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) return (ENOMEM); /* copy in arguments and/or environment from old process */ error = exec_extract_strings(imgp); if (error) return (error); /* * Destroy old process VM and create a new one (with a new stack) */ - exec_new_vmspace(imgp); + exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); vmspace = imgp->proc->p_vmspace; /* * Check if file_offset page aligned,. * Currently we cannot handle misalinged file offsets, * and so we read in the entire image (what a waste). */ if (file_offset & PAGE_MASK) { #ifdef DEBUG printf("imgact: Non page aligned binary %lu\n", file_offset); #endif /* * Map text+data+bss read/write/execute */ vmaddr = virtual_offset; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, a_out->a_text + a_out->a_data + bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return error; error = vm_mmap(kernel_map, &buffer, round_page(a_out->a_text + a_out->a_data + file_offset), VM_PROT_READ, VM_PROT_READ, 0, (caddr_t) imgp->vp, trunc_page(file_offset)); if (error) return error; error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, a_out->a_text + a_out->a_data); vm_map_remove(kernel_map, buffer, buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); if (error) return error; /* * remove write enable on the 'text' part */ error = vm_map_protect(&vmspace->vm_map, vmaddr, vmaddr + a_out->a_text, VM_PROT_EXECUTE|VM_PROT_READ, TRUE); if (error) return error; } else { #ifdef DEBUG printf("imgact: Page aligned binary %lu\n", file_offset); #endif /* * Map text+data read/execute */ vmaddr = virtual_offset; error = vm_mmap(&vmspace->vm_map, &vmaddr, a_out->a_text + a_out->a_data, VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, (caddr_t)imgp->vp, file_offset); if (error) return (error); #ifdef DEBUG printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr, a_out->a_text + a_out->a_data); #endif /* * allow read/write of data */ error = vm_map_protect(&vmspace->vm_map, vmaddr + a_out->a_text, vmaddr + a_out->a_text + a_out->a_data, VM_PROT_ALL, FALSE); if (error) return (error); /* * Allocate anon demand-zeroed area for uninitialized data */ if (bss_size != 0) { vmaddr = virtual_offset + a_out->a_text + a_out->a_data; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return (error); #ifdef DEBUG printf("imgact: bssaddr=%08lx, length=%08lx\n", (u_long)vmaddr, bss_size); #endif } /* Indicate that this file should not be modified */ imgp->vp->v_flag |= VTEXT; } /* Fill in process VM information */ vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT; vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t)virtual_offset; vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text; /* Fill in image_params */ imgp->interpreted = 0; imgp->entry_addr = a_out->a_entry; imgp->proc->p_sysent = &svr4_sysvec; return (0); } /* * Tell kern_execve.c about it, with a little help from the linker. */ struct execsw svr4_execsw = { exec_svr4_imgact, "svr4 ELF" }; EXEC_SET(execsw_set, svr4_execsw); Index: head/sys/compat/svr4/svr4_sysvec.c =================================================================== --- head/sys/compat/svr4/svr4_sysvec.c (revision 100383) +++ head/sys/compat/svr4/svr4_sysvec.c (revision 100384) @@ -1,412 +1,413 @@ /* * Copyright (c) 1998 Mark Newton * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christos Zoulas. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ /* XXX we use functions that might not exist. */ #include "opt_compat.h" #ifndef COMPAT_43 #error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int bsd_to_svr4_errno[ELAST+1] = { 0, SVR4_EPERM, SVR4_ENOENT, SVR4_ESRCH, SVR4_EINTR, SVR4_EIO, SVR4_ENXIO, SVR4_E2BIG, SVR4_ENOEXEC, SVR4_EBADF, SVR4_ECHILD, SVR4_EDEADLK, SVR4_ENOMEM, SVR4_EACCES, SVR4_EFAULT, SVR4_ENOTBLK, SVR4_EBUSY, SVR4_EEXIST, SVR4_EXDEV, SVR4_ENODEV, SVR4_ENOTDIR, SVR4_EISDIR, SVR4_EINVAL, SVR4_ENFILE, SVR4_EMFILE, SVR4_ENOTTY, SVR4_ETXTBSY, SVR4_EFBIG, SVR4_ENOSPC, SVR4_ESPIPE, SVR4_EROFS, SVR4_EMLINK, SVR4_EPIPE, SVR4_EDOM, SVR4_ERANGE, SVR4_EAGAIN, SVR4_EINPROGRESS, SVR4_EALREADY, SVR4_ENOTSOCK, SVR4_EDESTADDRREQ, SVR4_EMSGSIZE, SVR4_EPROTOTYPE, SVR4_ENOPROTOOPT, SVR4_EPROTONOSUPPORT, SVR4_ESOCKTNOSUPPORT, SVR4_EOPNOTSUPP, SVR4_EPFNOSUPPORT, SVR4_EAFNOSUPPORT, SVR4_EADDRINUSE, SVR4_EADDRNOTAVAIL, SVR4_ENETDOWN, SVR4_ENETUNREACH, SVR4_ENETRESET, SVR4_ECONNABORTED, SVR4_ECONNRESET, SVR4_ENOBUFS, SVR4_EISCONN, SVR4_ENOTCONN, SVR4_ESHUTDOWN, SVR4_ETOOMANYREFS, SVR4_ETIMEDOUT, SVR4_ECONNREFUSED, SVR4_ELOOP, SVR4_ENAMETOOLONG, SVR4_EHOSTDOWN, SVR4_EHOSTUNREACH, SVR4_ENOTEMPTY, SVR4_EPROCLIM, SVR4_EUSERS, SVR4_EDQUOT, SVR4_ESTALE, SVR4_EREMOTE, SVR4_EBADRPC, SVR4_ERPCMISMATCH, SVR4_EPROGUNAVAIL, SVR4_EPROGMISMATCH, SVR4_EPROCUNAVAIL, SVR4_ENOLCK, SVR4_ENOSYS, SVR4_EFTYPE, SVR4_EAUTH, SVR4_ENEEDAUTH, SVR4_EIDRM, SVR4_ENOMSG, }; static int svr4_fixup(register_t **stack_base, struct image_params *imgp); extern struct sysent svr4_sysent[]; #undef szsigcode #undef sigcode extern int svr4_szsigcode; extern char svr4_sigcode[]; struct sysentvec svr4_sysvec = { SVR4_SYS_MAXSYSCALL, svr4_sysent, 0xff, SVR4_SIGTBLSZ, bsd_to_svr4_sig, ELAST, /* ELAST */ bsd_to_svr4_errno, 0, svr4_fixup, svr4_sendsig, svr4_sigcode, &svr4_szsigcode, NULL, "SVR4", - elf_coredump, + elf32_coredump, NULL, SVR4_MINSIGSTKSZ }; Elf32_Brandinfo svr4_brand = { ELFOSABI_SYSV, + EM_386, /* XXX only implemented for x86 so far. */ "SVR4", svr4_emul_path, "/lib/libc.so.1", &svr4_sysvec }; const char svr4_emul_path[] = "/compat/svr4"; static int svr4_fixup(register_t **stack_base, struct image_params *imgp) { Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; register_t *pos; pos = *stack_base + (imgp->argc + imgp->envc + 2); if (args->trace) { AUXARGS_ENTRY(pos, AT_DEBUG, 1); } if (args->execfd != -1) { AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); } AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); PROC_LOCK(imgp->proc); AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); PROC_UNLOCK(imgp->proc); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; **stack_base = (int)imgp->argc; return 0; } /* * Search an alternate path before passing pathname arguments on * to system calls. Useful for keeping a separate 'emulation tree'. * * If cflag is set, we check if an attempt can be made to create * the named file, i.e. we check if the directory it should * be in exists. * * Code shamelessly stolen by Mark Newton from IBCS2 emulation code. */ int svr4_emul_find(td, sgp, prefix, path, pbuf, cflag) struct thread *td; caddr_t *sgp; /* Pointer to stackgap memory */ const char *prefix; char *path; char **pbuf; int cflag; { struct nameidata nd; struct nameidata ndroot; struct vattr vat; struct vattr vatroot; int error; char *ptr, *buf, *cp; size_t sz, len; buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); *pbuf = path; for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) continue; sz = MAXPATHLEN - (ptr - buf); /* * If sgp is not given then the path is already in kernel space */ if (sgp == NULL) error = copystr(path, ptr, sz, &len); else error = copyinstr(path, ptr, sz, &len); if (error) { free(buf, M_TEMP); return error; } if (*ptr != '/') { free(buf, M_TEMP); return EINVAL; } /* * We know that there is a / somewhere in this pathname. * Search backwards for it, to find the file's parent dir * to see if it exists in the alternate tree. If it does, * and we want to create a file (cflag is set). We don't * need to worry about the root comparison in this case. */ if (cflag) { for (cp = &ptr[len] - 1; *cp != '/'; cp--); *cp = '\0'; NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); if ((error = namei(&nd)) != 0) { free(buf, M_TEMP); return error; } NDFREE(&nd, NDF_ONLY_PNBUF); *cp = '/'; } else { NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); if ((error = namei(&nd)) != 0) { free(buf, M_TEMP); return error; } NDFREE(&nd, NDF_ONLY_PNBUF); /* * We now compare the vnode of the svr4_root to the one * vnode asked. If they resolve to be the same, then we * ignore the match so that the real root gets used. * This avoids the problem of traversing "../.." to find the * root directory and never finding it, because "/" resolves * to the emulation root directory. This is expensive :-( */ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path, td); if ((error = namei(&ndroot)) != 0) { /* Cannot happen! */ free(buf, M_TEMP); vrele(nd.ni_vp); return error; } NDFREE(&ndroot, NDF_ONLY_PNBUF); if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) { goto done; } if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td)) != 0) { goto done; } if (vat.va_fsid == vatroot.va_fsid && vat.va_fileid == vatroot.va_fileid) { error = ENOENT; goto done; } } if (sgp == NULL) *pbuf = buf; else { sz = &ptr[len] - buf; *pbuf = stackgap_alloc(sgp, sz + 1); error = copyout(buf, *pbuf, sz); free(buf, M_TEMP); } done: vrele(nd.ni_vp); if (!cflag) vrele(ndroot.ni_vp); return error; } static int svr4_elf_modevent(module_t mod, int type, void *data) { int error; error = 0; switch(type) { case MOD_LOAD: - if (elf_insert_brand_entry(&svr4_brand) < 0) + if (elf32_insert_brand_entry(&svr4_brand) < 0) error = EINVAL; if (error) printf("cannot insert svr4 elf brand handler\n"); else if (bootverbose) printf("svr4 ELF exec handler installed\n"); break; case MOD_UNLOAD: /* Only allow the emulator to be removed if it isn't in use. */ - if (elf_brand_inuse(&svr4_brand) != 0) { + if (elf32_brand_inuse(&svr4_brand) != 0) { error = EBUSY; - } else if (elf_remove_brand_entry(&svr4_brand) < 0) { + } else if (elf32_remove_brand_entry(&svr4_brand) < 0) { error = EINVAL; } if (error) printf("Could not deinstall ELF interpreter entry (error %d)\n", error); else if (bootverbose) printf("svr4 ELF exec handler removed\n"); break; default: break; } return error; } static moduledata_t svr4_elf_mod = { "svr4elf", svr4_elf_modevent, 0 }; DECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); MODULE_DEPEND(svr4elf, streams, 1, 1, 1); Index: head/sys/conf/files =================================================================== --- head/sys/conf/files (revision 100383) +++ head/sys/conf/files (revision 100384) @@ -1,1376 +1,1378 @@ # $FreeBSD$ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and # dependency lines other than the first are silently ignored. # aicasm optional ahc \ dependency "$S/dev/aic7xxx/aicasm/*.[chyl]" \ compile-with "${MAKE} -f $S/dev/aic7xxx/aicasm/Makefile MAKESRCPATH=$S/dev/aic7xxx/aicasm" \ no-obj no-implicit-rule \ clean "aicasm aicasm_gram.c aicasm_scan.c y.tab.h" aic7xxx_{seq,reg}.h optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend \ clean "aic7xxx_seq.h aic7xxx_reg.h" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_{seq,reg}.h optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule before-depend \ clean "aic79xx_seq.h aic79xx_reg.h" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" kern/device_if.m standard kern/bus_if.m standard kern/clock_if.m optional genclock kern/linker_if.m standard cam/cam.c optional scbus cam/cam_extend.c optional scbus cam/cam_periph.c optional scbus cam/cam_queue.c optional scbus cam/cam_sim.c optional scbus cam/cam_xpt.c optional scbus cam/scsi/scsi_all.c optional scbus cam/scsi/scsi_cd.c optional cd cam/scsi/scsi_ch.c optional ch cam/scsi/scsi_da.c optional da cam/scsi/scsi_low.c optional ct cam/scsi/scsi_low.c optional ncv cam/scsi/scsi_low.c optional nsp cam/scsi/scsi_low.c optional stg cam/scsi/scsi_low_pisa.c optional ct cam/scsi/scsi_low_pisa.c optional ncv cam/scsi/scsi_low_pisa.c optional nsp cam/scsi/scsi_low_pisa.c optional stg cam/scsi/scsi_pass.c optional pass cam/scsi/scsi_pt.c optional pt cam/scsi/scsi_sa.c optional sa cam/scsi/scsi_ses.c optional ses cam/scsi/scsi_targ_bh.c optional targbh cam/scsi/scsi_target.c optional targ coda/coda_fbsd.c count vcoda coda/coda_namecache.c optional vcoda coda/coda_psdev.c optional vcoda coda/coda_subr.c optional vcoda coda/coda_venus.c optional vcoda coda/coda_vfsops.c optional vcoda coda/coda_vnops.c optional vcoda compat/linprocfs/linprocfs.c optional linprocfs contrib/dev/acpica/dbcmds.c optional acpica acpi_debug nowerror contrib/dev/acpica/dbdisasm.c optional acpica acpi_debug nowerror contrib/dev/acpica/dbdisply.c optional acpica acpi_debug nowerror contrib/dev/acpica/dbexec.c optional acpica acpi_debug nowerror contrib/dev/acpica/dbfileio.c optional acpica acpi_debug nowerror contrib/dev/acpica/dbhistry.c optional acpica acpi_debug nowerror contrib/dev/acpica/dbinput.c optional acpica acpi_debug nowerror contrib/dev/acpica/dbstats.c optional acpica acpi_debug nowerror contrib/dev/acpica/dbutils.c optional acpica acpi_debug nowerror contrib/dev/acpica/dbxface.c optional acpica acpi_debug nowerror contrib/dev/acpica/dsfield.c optional acpica nowerror contrib/dev/acpica/dsmethod.c optional acpica contrib/dev/acpica/dsmthdat.c optional acpica contrib/dev/acpica/dsobject.c optional acpica contrib/dev/acpica/dsopcode.c optional acpica nowerror contrib/dev/acpica/dsutils.c optional acpica contrib/dev/acpica/dswexec.c optional acpica contrib/dev/acpica/dswload.c optional acpica contrib/dev/acpica/dswscope.c optional acpica contrib/dev/acpica/dswstate.c optional acpica contrib/dev/acpica/evevent.c optional acpica contrib/dev/acpica/evmisc.c optional acpica contrib/dev/acpica/evregion.c optional acpica contrib/dev/acpica/evrgnini.c optional acpica contrib/dev/acpica/evsci.c optional acpica contrib/dev/acpica/evxface.c optional acpica contrib/dev/acpica/evxfevnt.c optional acpica contrib/dev/acpica/evxfregn.c optional acpica contrib/dev/acpica/exconfig.c optional acpica contrib/dev/acpica/exconvrt.c optional acpica nowerror contrib/dev/acpica/excreate.c optional acpica contrib/dev/acpica/exdump.c optional acpica nowerror contrib/dev/acpica/exfield.c optional acpica contrib/dev/acpica/exfldio.c optional acpica contrib/dev/acpica/exmisc.c optional acpica contrib/dev/acpica/exmutex.c optional acpica contrib/dev/acpica/exnames.c optional acpica contrib/dev/acpica/exoparg1.c optional acpica contrib/dev/acpica/exoparg2.c optional acpica contrib/dev/acpica/exoparg3.c optional acpica contrib/dev/acpica/exoparg6.c optional acpica nowerror contrib/dev/acpica/exprep.c optional acpica contrib/dev/acpica/exregion.c optional acpica contrib/dev/acpica/exresnte.c optional acpica contrib/dev/acpica/exresolv.c optional acpica contrib/dev/acpica/exresop.c optional acpica nowerror contrib/dev/acpica/exstore.c optional acpica contrib/dev/acpica/exstoren.c optional acpica contrib/dev/acpica/exstorob.c optional acpica contrib/dev/acpica/exsystem.c optional acpica contrib/dev/acpica/exutils.c optional acpica contrib/dev/acpica/hwacpi.c optional acpica contrib/dev/acpica/hwgpe.c optional acpica nowerror contrib/dev/acpica/hwregs.c optional acpica nowerror contrib/dev/acpica/hwsleep.c optional acpica contrib/dev/acpica/hwtimer.c optional acpica contrib/dev/acpica/nsaccess.c optional acpica contrib/dev/acpica/nsalloc.c optional acpica contrib/dev/acpica/nsdump.c optional acpica nowerror contrib/dev/acpica/nseval.c optional acpica contrib/dev/acpica/nsinit.c optional acpica contrib/dev/acpica/nsload.c optional acpica contrib/dev/acpica/nsnames.c optional acpica nowerror contrib/dev/acpica/nsobject.c optional acpica contrib/dev/acpica/nssearch.c optional acpica contrib/dev/acpica/nsutils.c optional acpica contrib/dev/acpica/nswalk.c optional acpica contrib/dev/acpica/nsxfname.c optional acpica nowerror contrib/dev/acpica/nsxfobj.c optional acpica contrib/dev/acpica/psargs.c optional acpica contrib/dev/acpica/psfind.c optional acpica contrib/dev/acpica/psopcode.c optional acpica contrib/dev/acpica/psparse.c optional acpica contrib/dev/acpica/psscope.c optional acpica contrib/dev/acpica/pstree.c optional acpica contrib/dev/acpica/psutils.c optional acpica contrib/dev/acpica/pswalk.c optional acpica contrib/dev/acpica/psxface.c optional acpica contrib/dev/acpica/rsaddr.c optional acpica contrib/dev/acpica/rscalc.c optional acpica contrib/dev/acpica/rscreate.c optional acpica contrib/dev/acpica/rsdump.c optional acpica nowerror contrib/dev/acpica/rsio.c optional acpica contrib/dev/acpica/rsirq.c optional acpica contrib/dev/acpica/rslist.c optional acpica contrib/dev/acpica/rsmemory.c optional acpica contrib/dev/acpica/rsmisc.c optional acpica contrib/dev/acpica/rsutils.c optional acpica contrib/dev/acpica/rsxface.c optional acpica contrib/dev/acpica/tbconvrt.c optional acpica contrib/dev/acpica/tbget.c optional acpica contrib/dev/acpica/tbinstal.c optional acpica contrib/dev/acpica/tbutils.c optional acpica contrib/dev/acpica/tbxface.c optional acpica contrib/dev/acpica/tbxfroot.c optional acpica contrib/dev/acpica/utalloc.c optional acpica contrib/dev/acpica/utclib.c optional acpica nowerror contrib/dev/acpica/utcopy.c optional acpica nowerror contrib/dev/acpica/utdebug.c optional acpica nowerror contrib/dev/acpica/utdelete.c optional acpica contrib/dev/acpica/uteval.c optional acpica contrib/dev/acpica/utglobal.c optional acpica nowerror contrib/dev/acpica/utinit.c optional acpica contrib/dev/acpica/utmath.c optional acpica contrib/dev/acpica/utmisc.c optional acpica nowerror contrib/dev/acpica/utobject.c optional acpica nowerror contrib/dev/acpica/utxface.c optional acpica contrib/ipfilter/netinet/fil.c optional ipfilter inet contrib/ipfilter/netinet/ip_auth.c optional ipfilter inet contrib/ipfilter/netinet/ip_fil.c optional ipfilter inet contrib/ipfilter/netinet/ip_frag.c optional ipfilter inet contrib/ipfilter/netinet/ip_log.c optional ipfilter inet contrib/ipfilter/netinet/ip_nat.c optional ipfilter inet contrib/ipfilter/netinet/ip_proxy.c optional ipfilter inet contrib/ipfilter/netinet/ip_state.c optional ipfilter inet contrib/ipfilter/netinet/mlfk_ipl.c optional ipfilter inet crypto/blowfish/bf_skey.c optional ipsec ipsec_esp crypto/cast128/cast128.c optional ipsec ipsec_esp crypto/des/des_ecb.c optional ipsec ipsec_esp crypto/des/des_setkey.c optional ipsec ipsec_esp crypto/rijndael/rijndael-alg-fst.c optional ipsec ipsec_esp crypto/rijndael/rijndael-api-fst.c optional ipsec ipsec_esp crypto/sha1.c optional ipsec crypto/sha2/sha2.c optional ipsec ddb/db_access.c optional ddb ddb/db_break.c optional ddb ddb/db_command.c optional ddb ddb/db_elf.c optional ddb ddb/db_examine.c optional ddb ddb/db_expr.c optional ddb ddb/db_input.c optional ddb ddb/db_kld.c optional ddb ddb/db_lex.c optional ddb ddb/db_output.c optional ddb ddb/db_print.c optional ddb ddb/db_ps.c optional ddb ddb/db_run.c optional ddb ddb/db_sym.c optional ddb ddb/db_sysctl.c optional ddb ddb/db_trap.c optional ddb ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb dev/aac/aac.c optional aac dev/aac/aac_debug.c optional aac dev/aac/aac_disk.c optional aac dev/aac/aac_pci.c optional aac pci dev/aac/aac_cam.c optional aacp aac dev/acpica/acpi.c optional acpica dev/acpica/acpica_support.c optional acpica dev/acpica/acpi_acad.c optional acpica nowerror dev/acpica/acpi_battery.c optional acpica dev/acpica/acpi_button.c optional acpica dev/acpica/acpi_cmbat.c optional acpica nowerror dev/acpica/acpi_cpu.c optional acpica dev/acpica/acpi_ec.c optional acpica dev/acpica/acpi_lid.c optional acpica dev/acpica/acpi_pcib.c optional acpica pci dev/acpica/acpi_powerres.c optional acpica nowerror dev/acpica/acpi_resource.c optional acpica dev/acpica/acpi_thermal.c optional acpica dev/acpica/acpi_timer.c optional acpica dev/acpica/Osd/OsdDebug.c optional acpica dev/acpica/Osd/OsdHardware.c optional acpica dev/acpica/Osd/OsdInterrupt.c optional acpica dev/acpica/Osd/OsdMemory.c optional acpica dev/acpica/Osd/OsdSchedule.c optional acpica dev/acpica/Osd/OsdStream.c optional acpica dev/acpica/Osd/OsdSynch.c optional acpica dev/acpica/Osd/OsdTable.c optional acpica dev/advansys/adv_eisa.c optional adv eisa dev/advansys/adv_pci.c optional adv pci dev/advansys/advansys.c optional adv dev/advansys/advlib.c optional adv dev/advansys/advmcode.c optional adv dev/advansys/adw_pci.c optional adw pci dev/advansys/adwcam.c optional adw dev/advansys/adwlib.c optional adw dev/advansys/adwmcode.c optional adw dev/aha/aha.c optional aha dev/aha/aha_isa.c optional aha isa dev/aha/aha_mca.c optional aha mca dev/ahb/ahb.c optional ahb eisa dev/aic/aic.c optional aic dev/aic/aic_pccard.c optional aic card dev/aic/aic_pccard.c optional aic pccard dev/aic7xxx/aic7770.c optional ahc eisa dev/aic7xxx/ahc_eisa.c optional ahc eisa #dev/aic7xxx/ahc_isa.c optional ahc isa dev/aic7xxx/ahc_pci.c optional ahc pci dev/aic7xxx/aic7xxx.c optional ahc dev/aic7xxx/aic7xxx_93cx6.c optional ahc dev/aic7xxx/aic7xxx_osm.c optional ahc dev/aic7xxx/aic7xxx_pci.c optional ahc pci dev/aic7xxx/ahd_pci.c optional ahd pci dev/aic7xxx/aic79xx.c optional ahd pci dev/aic7xxx/aic79xx_osm.c optional ahd pci dev/aic7xxx/aic79xx_pci.c optional ahd pci dev/amr/amr.c optional amr dev/amr/amr_disk.c optional amr dev/amr/amr_pci.c optional amr dev/an/if_an.c optional an dev/an/if_an_isa.c optional an isa dev/an/if_an_pccard.c optional an card dev/an/if_an_pccard.c optional an pccard dev/an/if_an_pci.c optional an pci dev/ar/if_ar.c optional ar dev/ar/if_ar_pci.c optional ar pci dev/asr/asr.c optional asr pci dev/ata/ata-all.c optional ata dev/ata/ata-isa.c optional ata isa dev/ata/ata-card.c optional ata card dev/ata/ata-card.c optional ata pccard dev/ata/ata-pci.c optional ata pci dev/ata/ata-dma.c optional ata pci dev/ata/ata-disk.c optional atadisk dev/ata/ata-raid.c optional atadisk dev/ata/atapi-all.c optional atapicd dev/ata/atapi-all.c optional atapifd dev/ata/atapi-all.c optional atapist dev/ata/atapi-cd.c optional atapicd dev/ata/atapi-fd.c optional atapifd dev/ata/atapi-tape.c optional atapist dev/awi/am79c930.c optional awi dev/awi/awi.c optional awi dev/awi/awi_wep.c optional awi dev/awi/awi_wicfg.c optional awi dev/awi/if_awi_pccard.c optional awi card dev/awi/if_awi_pccard.c optional awi pccard dev/bge/if_bge.c optional bge dev/bktr/bktr_audio.c optional bktr pci dev/bktr/bktr_card.c optional bktr pci dev/bktr/bktr_core.c count bktr pci dev/bktr/bktr_i2c.c optional bktr pci smbus dev/bktr/bktr_os.c optional bktr pci dev/bktr/bktr_tuner.c optional bktr pci dev/buslogic/bt.c optional bt dev/buslogic/bt_eisa.c optional bt eisa dev/buslogic/bt_isa.c optional bt isa dev/buslogic/bt_mca.c optional bt mca dev/buslogic/bt_pci.c optional bt pci dev/cardbus/cardbus.c optional cardbus dev/cardbus/cardbus_cis.c optional cardbus dev/ccd/ccd.c optional ccd dev/ciss/ciss.c optional ciss dev/cm/smc90cx6.c optional cm dev/cnw/if_cnw.c optional cnw card #dev/cnw/if_cnw.c optional cnw pccard dev/cs/if_cs.c optional cs dev/cs/if_cs_isa.c optional cs isa dev/cs/if_cs_pccard.c optional cs card dev/cs/if_cs_pccard.c optional cs pccard dev/dgb/dgb.c count dgb dev/digi/digi.c optional digi dev/digi/digi_isa.c optional digi dev/digi/digi_pci.c optional digi dev/digi/CX.c optional digi_CX dev/digi/CX_PCI.c optional digi_CX_PCI dev/digi/EPCX.c optional digi_EPCX dev/digi/EPCX_PCI.c optional digi_EPCX_PCI dev/digi/Xe.c optional digi_Xe dev/digi/Xem.c optional digi_Xem dev/digi/Xr.c optional digi_Xr #dev/dpt/dpt_control.c optional dpt dev/dpt/dpt_eisa.c optional dpt eisa dev/dpt/dpt_pci.c optional dpt pci dev/dpt/dpt_scsi.c optional dpt dev/drm/gamma_dma.c optional gammadrm dev/drm/gamma_drv.c optional gammadrm dev/drm/mga_dma.c optional mgadrm dev/drm/mga_drv.c optional mgadrm dev/drm/mga_state.c optional mgadrm dev/drm/mga_warp.c optional mgadrm dev/drm/r128_cce.c optional r128drm dev/drm/r128_drv.c optional r128drm dev/drm/r128_state.c optional r128drm dev/drm/radeon_cp.c optional radeondrm dev/drm/radeon_drv.c optional radeondrm dev/drm/radeon_state.c optional radeondrm dev/drm/tdfx_drv.c optional tdfxdrm dev/ed/if_ed.c optional ed dev/ed/if_ed_pccard.c optional ed card dev/ed/if_ed_pccard.c optional ed pccard dev/ed/if_ed_pci.c optional ed pci dev/en/midway.c optional en dev/ep/if_ep.c optional ep dev/ep/if_ep_eisa.c optional ep eisa dev/ep/if_ep_isa.c optional ep isa dev/ep/if_ep_mca.c optional ep mca dev/ep/if_ep_pccard.c optional ep card dev/ep/if_ep_pccard.c optional ep pccard dev/ex/if_ex.c optional ex dev/ex/if_ex_isa.c optional ex isa dev/ex/if_ex_pccard.c optional ex card #dev/ex/if_ex_pccard.c optional ex pccard dev/exca/exca.c optional pccbb dev/fe/if_fe.c optional fe dev/fe/if_fe_pccard.c optional fe card dev/fe/if_fe_pccard.c optional fe pccard dev/fxp/if_fxp.c optional fxp dev/gem/if_gem.c optional gem dev/gem/if_gem_pci.c optional gem pci dev/gx/if_gx.c optional gx dev/hea/eni.c optional hea nowerror dev/hea/eni_buffer.c optional hea nowerror dev/hea/eni_globals.c optional hea dev/hea/eni_if.c optional hea dev/hea/eni_init.c optional hea dev/hea/eni_intr.c optional hea dev/hea/eni_receive.c optional hea dev/hea/eni_transmit.c optional hea dev/hea/eni_vcm.c optional hea nowerror dev/hea/hea_pci.c optional hea pci dev/hea/hea_freebsd.c optional hea dev/hfa/fore_buffer.c optional hfa dev/hfa/fore_command.c optional hfa dev/hfa/fore_globals.c optional hfa dev/hfa/fore_if.c optional hfa dev/hfa/fore_init.c optional hfa dev/hfa/fore_intr.c optional hfa #dev/hfa/fore_load.c optional hfa nowerror dev/hfa/fore_output.c optional hfa dev/hfa/fore_receive.c optional hfa dev/hfa/fore_stats.c optional hfa dev/hfa/fore_timer.c optional hfa dev/hfa/fore_transmit.c optional hfa dev/hfa/fore_vcm.c optional hfa dev/hfa/hfa_freebsd.c optional hfa #dev/hfa/hfa_eisa.c optional hfa eisa dev/hfa/hfa_pci.c optional hfa pci #dev/hfa/hfa_sbus.c optional hfa sbus dev/hme/if_hme.c optional hme dev/hme/if_hme_pci.c optional hme pci dev/hme/if_hme_sbus.c optional hme sbus dev/ichsmb/ichsmb.c optional ichsmb dev/ichsmb/ichsmb_pci.c optional ichsmb pci dev/ida/ida.c optional ida dev/ida/ida_disk.c optional ida dev/ida/ida_eisa.c optional ida eisa dev/ida/ida_pci.c optional ida pci dev/ie/if_ie.c count ie isa nowerror dev/iicbus/iicbb_if.m optional iicbb dev/iicbus/iicbus_if.m optional iicbus dev/iicbus/if_ic.c optional ic dev/iicbus/iic.c optional iic dev/iicbus/iicbb.c optional iicbb dev/iicbus/iicbus.c optional iicbus dev/iicbus/iiconf.c optional iicbus dev/iicbus/iicsmb.c optional iicsmb \ dependency "iicbus_if.h" dev/iir/iir.c optional iir dev/iir/iir_ctrl.c optional iir dev/iir/iir_pci.c optional iir pci dev/isp/isp.c optional isp dev/isp/isp_freebsd.c optional isp dev/isp/isp_target.c optional isp dev/isp/isp_pci.c optional isp pci dev/isp/isp_sbus.c optional isp sbus dev/ispfw/ispfw.c optional ispfw dev/joy/joy.c optional joy dev/joy/joy_isa.c optional joy isa dev/joy/joy_pccard.c optional joy pccard dev/lge/if_lge.c optional lge dev/lmc/if_lmc.c optional lmc nowerror dev/lnc/if_lnc.c optional lnc dev/lnc/if_lnc_pci.c optional lnc pci dev/ncv/ncr53c500.c optional ncv dev/ncv/ncr53c500_pccard.c optional ncv card #dev/ncv/ncr53c500_pccard.c optional ncv pccard dev/nsp/nsp.c optional nsp dev/nsp/nsp_pccard.c optional nsp card #dev/nsp/nsp_pccard.c optional nsp pccard dev/mca/mca_bus.c optional mca dev/md/md.c optional md dev/mii/amphy.c optional miibus dev/mii/bmtphy.c optional miibus dev/mii/brgphy.c optional miibus dev/mii/dcphy.c optional miibus pci dev/mii/e1000phy.c optional miibus dev/mii/exphy.c optional miibus dev/mii/inphy.c optional miibus dev/mii/mii.c optional miibus dev/mii/mii_physubr.c optional miibus dev/mii/mlphy.c optional miibus dev/mii/nsphy.c optional miibus dev/mii/nsgphy.c optional miibus dev/mii/pnphy.c optional miibus dev/mii/pnaphy.c optional miibus dev/mii/rlphy.c optional miibus dev/mii/tdkphy.c optional miibus dev/mii/tlphy.c optional miibus dev/mii/ukphy.c optional miibus dev/mii/ukphy_subr.c optional miibus dev/mii/xmphy.c optional miibus dev/mii/lxtphy.c optional miibus dev/mii/qsphy.c optional miibus dev/mii/acphy.c optional miibus dev/mii/miibus_if.m optional miibus dev/mk48txx/mk48txx.c optional mk48txx dev/mlx/mlx.c optional mlx dev/mlx/mlx_disk.c optional mlx dev/mlx/mlx_pci.c optional mlx dev/mly/mly.c optional mly dev/my/if_my.c optional my dev/musycc/musycc.c optional musycc dev/nge/if_nge.c optional nge dev/null/null.c standard dev/nmdm/nmdm.c optional nmdm dev/pccard/card_if.m standard dev/pccard/pccard.c optional pccard dev/pccard/pccard_cis.c optional pccard dev/pccard/pccard_cis_quirks.c optional pccard dev/pccard/power_if.m standard dev/pccbb/pccbb.c optional pccbb dev/pci/eisa_pci.c optional pci dev/pci/fixup_pci.c optional pci dev/pci/ignore_pci.c optional pci dev/pci/isa_pci.c optional pci dev/pci/pci.c count pci dev/pci/pci_if.m standard dev/pci/pci_pci.c optional pci dev/pci/pci_user.c optional pci dev/pci/pcib_if.m standard dev/pcic/i82365.c optional pcic pccard dev/pcic/i82365_isa.c optional pcic pccard isa dev/pdq/if_fea.c optional fea eisa dev/pdq/if_fpa.c optional fpa pci dev/pdq/pdq.c optional fea eisa nowerror dev/pdq/pdq.c optional fpa pci nowerror dev/pdq/pdq_ifsubr.c optional fea eisa nowerror dev/pdq/pdq_ifsubr.c optional fpa pci nowerror dev/ppbus/ppbus_if.m optional ppbus dev/ppbus/if_plip.c optional plip dev/ppbus/immio.c optional vpo dev/ppbus/lpbb.c optional lpbb dev/ppbus/lpt.c optional lpt dev/ppbus/pcfclock.c optional pcfclock dev/ppbus/ppb_1284.c optional ppbus dev/ppbus/ppb_base.c optional ppbus dev/ppbus/ppb_msq.c optional ppbus dev/ppbus/ppbconf.c optional ppbus dev/ppbus/ppi.c optional ppi dev/ppbus/pps.c optional pps dev/ppbus/vpo.c optional vpo dev/ppbus/vpoio.c optional vpo dev/puc/puc.c optional puc pci dev/puc/pucdata.c optional puc pci dev/random/harvest.c standard dev/random/randomdev.c optional random dev/random/yarrow.c optional random dev/random/hash.c optional random crypto/rijndael/rijndael-alg-fst.c optional random crypto/rijndael/rijndael-api-fst.c optional random crypto/sha2/sha2.c optional random dev/ray/if_ray.c optional ray card dev/ray/if_ray.c optional ray pccard dev/rp/rp.c optional rp dev/rp/rp_isa.c optional rp isa dev/rp/rp_pci.c optional rp pci dev/se/se_console.c optional se ebus dev/si/si.c optional si dev/si/si2_z280.c optional si dev/si/si3_t225.c optional si dev/si/si_eisa.c optional si eisa dev/si/si_isa.c optional si isa dev/si/si_pci.c optional si pci dev/sio/sio_isa.c optional sio isa dev/sio/sio_pccard.c optional sio card dev/sio/sio_pccard.c optional sio pccard dev/sio/sio_pci.c optional sio pci dev/sio/sio_puc.c optional sio puc pci dev/smbus/smbus_if.m optional smbus dev/smbus/smb.c optional smb dev/smbus/smbconf.c optional smbus dev/smbus/smbus.c count smbus dev/sn/if_sn.c optional sn dev/sn/if_sn_isa.c optional sn isa dev/sn/if_sn_pccard.c optional sn card dev/sn/if_sn_pccard.c optional sn pccard dev/snp/snp.c optional snp dev/sound/isa/ad1816.c optional pcm isa dev/sound/isa/emu8000.c optional midi isa dev/sound/isa/es1888.c optional pcm isa dev/sound/isa/ess.c optional pcm isa dev/sound/isa/gusc.c optional gusc isa dev/sound/isa/gusc.c optional pcm isa dev/sound/isa/gusmidi.c optional midi isa dev/sound/isa/mpu.c optional midi isa dev/sound/isa/mss.c optional pcm isa dev/sound/isa/opl.c optional midi isa dev/sound/isa/sb16.c optional pcm isa dev/sound/isa/sb8.c optional pcm isa dev/sound/isa/sbc.c optional pcm isa dev/sound/isa/sbc.c optional sbc isa dev/sound/isa/uartsio.c optional midi isa dev/sound/midi/midi.c optional midi dev/sound/midi/midibuf.c optional midi dev/sound/midi/midisynth.c optional midi dev/sound/midi/sequencer.c optional seq midi dev/sound/midi/timer.c optional seq midi dev/sound/pci/als4000.c optional pcm pci dev/sound/pci/cmi.c optional pcm pci dev/sound/pci/cs4281.c optional pcm pci dev/sound/pci/csa.c optional csa pci dev/sound/pci/csa.c optional pcm pci dev/sound/pci/csamidi.c optional midi csa dev/sound/pci/csapcm.c optional pcm pci dev/sound/pci/ds1.c optional pcm pci dev/sound/pci/emu10k1.c optional pcm pci dev/sound/pci/es137x.c optional pcm pci dev/sound/pci/fm801.c optional pcm pci dev/sound/pci/ich.c optional pcm pci dev/sound/pci/maestro.c optional pcm pci dev/sound/pci/neomagic.c optional pcm pci dev/sound/pci/solo.c optional pcm pci dev/sound/pci/t4dwave.c optional pcm pci dev/sound/pci/via82c686.c optional pcm pci dev/sound/pci/vibes.c optional pcm pci #dev/sound/pci/vortex1.c optional pcm pci dev/sound/pcm/ac97.c optional pcm dev/sound/pcm/ac97_if.m optional pcm dev/sound/pcm/buffer.c optional pcm dev/sound/pcm/channel.c optional pcm dev/sound/pcm/channel_if.m optional pcm dev/sound/pcm/dsp.c optional pcm dev/sound/pcm/fake.c optional pcm dev/sound/pcm/feeder.c optional pcm dev/sound/pcm/feeder_if.m optional pcm dev/sound/pcm/feeder_fmt.c optional pcm dev/sound/pcm/feeder_rate.c optional pcm dev/sound/pcm/mixer.c optional pcm dev/sound/pcm/mixer_if.m optional pcm dev/sound/pcm/sndstat.c optional pcm dev/sound/pcm/sound.c optional pcm dev/sound/pcm/vchan.c optional pcm #dev/sound/usb/upcm.c optional pcm usb dev/sr/if_sr.c optional sr dev/sr/if_sr_pci.c optional sr pci dev/streams/streams.c optional streams dev/stg/tmc18c30.c optional stg dev/stg/tmc18c30_pccard.c optional stg card #dev/stg/tmc18c30_pccard.c optional stg pccard dev/stg/tmc18c30_isa.c optional stg isa dev/sym/sym_hipd.c optional sym \ dependency "$S/dev/sym/sym_{conf,defs}.h" dev/syscons/blank/blank_saver.c optional blank_saver dev/syscons/daemon/daemon_saver.c optional daemon_saver dev/syscons/fade/fade_saver.c optional fade_saver dev/syscons/fire/fire_saver.c optional fire_saver dev/syscons/green/green_saver.c optional green_saver dev/syscons/logo/logo_saver.c optional logo_saver dev/syscons/logo/logo.c optional logo_saver dev/syscons/rain/rain_saver.c optional rain_saver dev/syscons/star/star_saver.c optional star_saver dev/syscons/warp/warp_saver.c optional warp_saver dev/tdfx/tdfx_pci.c optional tdfx pci dev/twe/twe.c optional twe dev/twe/twe_freebsd.c optional twe dev/tx/if_tx.c optional tx dev/txp/if_txp.c optional txp # # USB support dev/usb/usb_if.m optional usb dev/usb/hid.c optional usb dev/usb/if_aue.c optional aue dev/usb/if_cue.c optional cue dev/usb/if_kue.c optional kue dev/usb/ohci.c optional ohci dev/usb/ucom.c optional ucom dev/usb/udbp.c optional udbp dev/usb/ufm.c optional ufm dev/usb/ugen.c optional ugen dev/usb/uhci.c optional uhci dev/usb/uhid.c optional uhid dev/usb/uhub.c optional usb dev/usb/ukbd.c optional ukbd dev/usb/ulpt.c optional ulpt dev/usb/umass.c optional umass dev/usb/umodem.c optional umodem dev/usb/ums.c optional ums dev/usb/uplcom.c optional uplcom ucom dev/usb/urio.c optional urio dev/usb/uscanner.c optional uscanner dev/usb/uvscom.c optional uvscom ucom dev/usb/usb.c optional usb dev/usb/usb_ethersubr.c optional usb #dev/usb/usb_mem.c optional usb dev/usb/usb_quirks.c optional usb dev/usb/usb_subr.c optional usb dev/usb/usbdi.c optional usb dev/usb/usbdi_util.c optional usb dev/vinum/vinum.c optional vinum dev/vinum/vinumconfig.c optional vinum dev/vinum/vinumdaemon.c optional vinum dev/vinum/vinuminterrupt.c optional vinum dev/vinum/vinumio.c optional vinum dev/vinum/vinumioctl.c optional vinum dev/vinum/vinumlock.c optional vinum dev/vinum/vinummemory.c optional vinum dev/vinum/vinumparser.c optional vinum dev/vinum/vinumraid5.c optional vinum dev/vinum/vinumrequest.c optional vinum dev/vinum/vinumrevive.c optional vinum dev/vinum/vinumstate.c optional vinum dev/vinum/vinumutil.c optional vinum dev/vx/if_vx.c optional vx dev/vx/if_vx_eisa.c optional vx eisa dev/vx/if_vx_pci.c optional vx pci #dev/wlp/if_wlp.c optional wlp card dev/wds/wd7000.c optional wds isa dev/wi/if_wi.c optional wi dev/wi/if_wi_pccard.c optional wi pccard dev/wi/if_wi_pccard.c optional wi card dev/wi/if_wi_pci.c optional wi pci dev/wi/wi_hostap.c optional wi dev/wl/if_wl.c optional wl isa dev/xe/if_xe.c optional xe dev/xe/if_xe_pccard.c optional xe card dev/xe/if_xe_pccard.c optional xe pccard fs/deadfs/dead_vnops.c standard fs/devfs/devfs_devs.c standard fs/devfs/devfs_rule.c standard fs/devfs/devfs_vfsops.c standard fs/devfs/devfs_vnops.c standard fs/fdescfs/fdesc_vfsops.c optional fdescfs fs/fdescfs/fdesc_vnops.c optional fdescfs fs/fifofs/fifo_vnops.c standard fs/hpfs/hpfs_alsubr.c optional hpfs fs/hpfs/hpfs_hash.c optional hpfs fs/hpfs/hpfs_lookup.c optional hpfs fs/hpfs/hpfs_subr.c optional hpfs fs/hpfs/hpfs_vfsops.c optional hpfs fs/hpfs/hpfs_vnops.c optional hpfs fs/msdosfs/msdosfs_conv.c optional msdosfs fs/msdosfs/msdosfs_denode.c optional msdosfs fs/msdosfs/msdosfs_fat.c optional msdosfs fs/msdosfs/msdosfs_lookup.c optional msdosfs fs/msdosfs/msdosfs_vfsops.c optional msdosfs fs/msdosfs/msdosfs_vnops.c optional msdosfs fs/ntfs/ntfs_compr.c optional ntfs fs/ntfs/ntfs_ihash.c optional ntfs fs/ntfs/ntfs_subr.c optional ntfs fs/ntfs/ntfs_vfsops.c optional ntfs fs/ntfs/ntfs_vnops.c optional ntfs fs/nullfs/null_subr.c optional nullfs fs/nullfs/null_vfsops.c optional nullfs fs/nullfs/null_vnops.c optional nullfs fs/nwfs/nwfs_io.c optional nwfs fs/nwfs/nwfs_ioctl.c optional nwfs fs/nwfs/nwfs_node.c optional nwfs fs/nwfs/nwfs_subr.c optional nwfs fs/nwfs/nwfs_vfsops.c optional nwfs fs/nwfs/nwfs_vnops.c optional nwfs fs/portalfs/portal_vfsops.c optional portalfs fs/portalfs/portal_vnops.c optional portalfs fs/procfs/procfs.c optional procfs fs/procfs/procfs_ctl.c optional procfs fs/procfs/procfs_dbregs.c optional procfs fs/procfs/procfs_fpregs.c optional procfs fs/procfs/procfs_ioctl.c optional procfs fs/procfs/procfs_map.c optional procfs fs/procfs/procfs_mem.c optional procfs fs/procfs/procfs_note.c optional procfs fs/procfs/procfs_regs.c optional procfs fs/procfs/procfs_rlimit.c optional procfs fs/procfs/procfs_status.c optional procfs fs/procfs/procfs_type.c optional procfs fs/pseudofs/pseudofs.c optional pseudofs fs/pseudofs/pseudofs_fileno.c optional pseudofs fs/pseudofs/pseudofs_vncache.c optional pseudofs fs/pseudofs/pseudofs_vnops.c optional pseudofs fs/smbfs/smbfs_io.c optional smbfs fs/smbfs/smbfs_node.c optional smbfs fs/smbfs/smbfs_smb.c optional smbfs fs/smbfs/smbfs_subr.c optional smbfs fs/smbfs/smbfs_vfsops.c optional smbfs fs/smbfs/smbfs_vnops.c optional smbfs fs/specfs/spec_vnops.c standard fs/udf/udf_vfsops.c optional udf fs/udf/udf_vnops.c optional udf fs/udf/osta.c optional udf fs/umapfs/umap_subr.c optional umapfs fs/umapfs/umap_vfsops.c optional umapfs fs/umapfs/umap_vnops.c optional umapfs fs/unionfs/union_subr.c optional unionfs fs/unionfs/union_vfsops.c optional unionfs fs/unionfs/union_vnops.c optional unionfs geom/geom_aes.c optional geom geom/geom_bsd.c optional geom geom/geom_dev.c optional geom geom/geom_disk.c optional geom geom/geom_dump.c optional geom geom/geom_enc.c optional geom geom/geom_event.c optional geom geom/geom_gpt.c optional geom geom/geom_io.c optional geom geom/geom_kern.c optional geom geom/geom_mbr.c optional geom geom/geom_pc98.c optional geom geom/geom_slice.c optional geom geom/geom_subr.c optional geom geom/geom_sunlabel.c optional geom gnu/ext2fs/ext2_alloc.c optional ext2fs \ warning "kernel contains GPL contaminated ext2fs filesystem" gnu/ext2fs/ext2_balloc.c optional ext2fs gnu/ext2fs/ext2_bmap.c optional ext2fs gnu/ext2fs/ext2_ihash.c optional ext2fs gnu/ext2fs/ext2_inode.c optional ext2fs gnu/ext2fs/ext2_inode_cnv.c optional ext2fs gnu/ext2fs/ext2_linux_balloc.c optional ext2fs gnu/ext2fs/ext2_linux_ialloc.c optional ext2fs gnu/ext2fs/ext2_lookup.c optional ext2fs gnu/ext2fs/ext2_subr.c optional ext2fs gnu/ext2fs/ext2_vfsops.c optional ext2fs gnu/ext2fs/ext2_vnops.c optional ext2fs # # isdn4bsd device drivers # i4b/driver/i4b_trace.c count i4btrc i4b/driver/i4b_rbch.c count i4brbch i4b/driver/i4b_tel.c count i4btel i4b/driver/i4b_ipr.c count i4bipr net/slcompress.c optional i4bipr i4b/driver/i4b_ctl.c count i4bctl i4b/driver/i4b_ing.c count i4bing i4b/driver/i4b_isppp.c count i4bisppp net/slcompress.c optional i4bisppp # # isdn4bsd CAPI driver # i4b/capi/capi_l4if.c count i4bcapi i4b/capi/capi_llif.c optional i4bcapi i4b/capi/capi_msgs.c optional i4bcapi # # isdn4bsd AVM B1/T1 CAPI driver # i4b/capi/iavc/iavc_pci.c count iavc pci i4b/capi/iavc/iavc_isa.c optional iavc i4b/capi/iavc/iavc_lli.c optional iavc i4b/capi/iavc/iavc_card.c optional iavc # # isdn4bsd support # i4b/layer2/i4b_mbuf.c optional i4btrc # # isdn4bsd Q.921 handler # i4b/layer2/i4b_l2.c count i4bq921 i4b/layer2/i4b_l2fsm.c optional i4bq921 i4b/layer2/i4b_uframe.c optional i4bq921 i4b/layer2/i4b_tei.c optional i4bq921 i4b/layer2/i4b_sframe.c optional i4bq921 i4b/layer2/i4b_iframe.c optional i4bq921 i4b/layer2/i4b_l2timer.c optional i4bq921 i4b/layer2/i4b_util.c optional i4bq921 i4b/layer2/i4b_lme.c optional i4bq921 # # isdn4bsd Q.931 handler # i4b/layer3/i4b_q931.c count i4bq931 i4b/layer3/i4b_l3fsm.c optional i4bq931 i4b/layer3/i4b_l3timer.c optional i4bq931 i4b/layer3/i4b_l2if.c optional i4bq931 i4b/layer3/i4b_l4if.c optional i4bq931 i4b/layer3/i4b_q932fac.c optional i4bq931 # # isdn4bsd control device driver, interface to isdnd # i4b/layer4/i4b_i4bdrv.c count i4b i4b/layer4/i4b_l4.c optional i4b i4b/layer4/i4b_l4mgmt.c optional i4b i4b/layer4/i4b_l4timer.c optional i4b # isa/isa_if.m standard isa/isa_common.c optional isa isa/isahint.c optional isa isa/orm.c optional isa isa/pnp.c optional isa isa/pnpparse.c optional isa isofs/cd9660/cd9660_bmap.c optional cd9660 isofs/cd9660/cd9660_lookup.c optional cd9660 isofs/cd9660/cd9660_node.c optional cd9660 isofs/cd9660/cd9660_rrip.c optional cd9660 isofs/cd9660/cd9660_util.c optional cd9660 isofs/cd9660/cd9660_vfsops.c optional cd9660 isofs/cd9660/cd9660_vnops.c optional cd9660 -kern/imgact_elf.c standard +kern/imgact_elf32.c standard +kern/imgact_elf64.c standard +kern/imgact_elfN.c standard kern/imgact_shell.c standard kern/inflate.c optional gzip kern/init_main.c standard kern/init_sysent.c standard kern/kern_acct.c standard kern/kern_acl.c standard kern/kern_clock.c standard kern/kern_condvar.c standard kern/kern_conf.c standard kern/kern_descrip.c standard kern/kern_poll.c optional device_polling kern/kern_environment.c standard kern/kern_event.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fork.c standard kern/kern_idle.c standard kern/kern_intr.c standard kern/kern_jail.c standard kern/kern_kthread.c standard kern/kern_ktr.c optional ktr kern/kern_ktrace.c standard kern/kern_linker.c standard kern/kern_lock.c standard kern/kern_lockf.c standard kern/kern_malloc.c standard kern/kern_mib.c standard kern/kern_module.c standard kern/kern_mutex.c standard kern/kern_mtxpool.c standard kern/kern_ntptime.c standard kern/kern_physio.c standard kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.c standard kern/kern_sema.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard kern/kern_subr.c standard kern/kern_switch.c standard kern/kern_sx.c standard kern/kern_synch.c standard kern/kern_syscalls.c standard kern/kern_sysctl.c standard kern/kern_tc.c standard kern/kern_thread.c standard kern/kern_time.c standard kern/kern_timeout.c standard kern/kern_uuid.c standard kern/kern_xxx.c standard kern/link_elf.c standard kern/md5c.c standard kern/subr_autoconf.c standard kern/subr_blist.c standard kern/subr_bus.c standard kern/subr_clock.c optional genclock kern/subr_devstat.c standard kern/subr_disk.c standard kern/subr_disklabel.c standard kern/subr_diskslice.c standard kern/subr_eventhandler.c standard kern/subr_hints.c standard kern/subr_kobj.c standard kern/subr_log.c standard kern/subr_mbuf.c standard kern/subr_mchain.c optional libmchain kern/subr_module.c standard kern/subr_param.c standard kern/subr_pcpu.c standard kern/subr_power.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rman.c standard kern/subr_sbuf.c standard kern/subr_scanf.c standard kern/subr_smp.c optional smp kern/subr_taskqueue.c standard kern/subr_trap.c standard kern/subr_witness.c optional witness kern/subr_xxx.c standard kern/sys_generic.c standard kern/sys_pipe.c standard kern/sys_process.c standard kern/sys_socket.c standard kern/syscalls.c optional witness kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem kern/sysv_shm.c optional sysvshm kern/tty.c standard kern/tty_compat.c standard kern/tty_conf.c standard kern/tty_cons.c standard kern/tty_pty.c optional pty kern/tty_subr.c standard kern/tty_tty.c standard kern/uipc_accf.c optional inet kern/uipc_cow.c optional zero_copy_sockets kern/uipc_domain.c standard kern/uipc_jumbo.c standard kern/uipc_mbuf.c standard kern/uipc_mbuf2.c standard kern/uipc_proto.c standard kern/uipc_socket.c standard kern/uipc_socket2.c standard kern/uipc_syscalls.c standard kern/uipc_usrreq.c standard kern/vfs_aio.c optional vfs_aio kern/vfs_bio.c standard kern/vfs_cache.c standard kern/vfs_cluster.c standard kern/vfs_default.c standard kern/vfs_export.c standard kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_mount.c standard kern/vfs_subr.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard # # These files in libkern/ are those needed by all architectures. Some # of the files in libkern/ are only needed on some architectures, e.g., # libkern/divdi3.c is needed by i386 but not alpha. Also, some of these # routines may be optimized for a particular platform. In either case, # the file should be moved to /conf/files. from here. # libkern/arc4random.c standard libkern/bcd.c standard libkern/bsearch.c standard libkern/iconv.c optional libiconv libkern/iconv_converter_if.m optional libiconv libkern/iconv_xlat.c optional libiconv libkern/index.c standard libkern/inet_ntoa.c standard libkern/mcount.c optional profiling-routine libkern/qsort.c standard libkern/random.c standard libkern/rindex.c standard libkern/scanc.c standard libkern/skpc.c standard libkern/strcat.c standard libkern/strcmp.c standard libkern/strcpy.c standard libkern/strlen.c standard libkern/strncmp.c standard libkern/strncpy.c standard libkern/strtol.c standard libkern/strtoq.c standard libkern/strtoul.c standard libkern/strtouq.c standard libkern/strvalid.c standard libkern/crc32.c standard net/bpf.c standard net/bpf_filter.c optional bpf bpf.h standard \ compile-with "echo '#define NBPF 1' > bpf.h" \ no-obj no-implicit-rule before-depend net/bridge.c optional bridge net/bsd_comp.c optional ppp_bsdcomp net/if.c standard net/if_arcsubr.c optional arcnet net/if_atmsubr.c optional atm net/if_disc.c optional disc net/if_ef.c optional ef net/if_ethersubr.c optional ether net/if_faith.c optional faith net/if_fddisubr.c optional fddi net/if_gif.c optional gif net/if_iso88025subr.c optional token net/if_loop.c optional loop net/if_media.c standard net/if_mib.c standard net/if_ppp.c count ppp net/if_sl.c optional sl net/if_spppsubr.c optional sppp net/if_spppsubr.c optional i4bisppp net/if_stf.c optional stf net/if_tun.c optional tun net/if_tap.c optional tap net/if_vlan.c optional vlan net/intrq.c standard net/net_osdep.c standard net/ppp_deflate.c optional ppp_deflate net/ppp_tty.c optional ppp net/pfil.c optional pfil_hooks net/pfil.c optional ipfilter net/radix.c standard net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rtsock.c standard net/slcompress.c optional ppp net/slcompress.c optional sl net/slcompress.c optional sppp net/zlib.c optional ppp_deflate net/zlib.c optional ipsec netatalk/aarp.c optional netatalk netatalk/at_control.c optional netatalk netatalk/at_proto.c optional netatalk netatalk/at_rmx.c optional netatalkdebug netatalk/ddp_input.c optional netatalk netatalk/ddp_output.c optional netatalk netatalk/ddp_usrreq.c optional netatalk netatm/atm_aal5.c optional atm_core netatm/atm_cm.c optional atm_core netatm/atm_device.c optional atm_core netatm/atm_if.c optional atm_core netatm/atm_proto.c optional atm_core netatm/atm_signal.c optional atm_core netatm/atm_socket.c optional atm_core netatm/atm_subr.c optional atm_core netatm/atm_usrreq.c optional atm_core netatm/ipatm/ipatm_event.c optional atm_ip atm_core netatm/ipatm/ipatm_if.c optional atm_ip atm_core netatm/ipatm/ipatm_input.c optional atm_ip atm_core netatm/ipatm/ipatm_load.c optional atm_ip atm_core netatm/ipatm/ipatm_output.c optional atm_ip atm_core netatm/ipatm/ipatm_usrreq.c optional atm_ip atm_core netatm/ipatm/ipatm_vcm.c optional atm_ip atm_core netatm/sigpvc/sigpvc_if.c optional atm_sigpvc atm_core netatm/sigpvc/sigpvc_subr.c optional atm_sigpvc atm_core netatm/spans/spans_arp.c optional atm_spans atm_core \ dependency "spans_xdr.h" netatm/spans/spans_cls.c optional atm_spans atm_core netatm/spans/spans_if.c optional atm_spans atm_core netatm/spans/spans_kxdr.c optional atm_spans atm_core netatm/spans/spans_msg.c optional atm_spans atm_core netatm/spans/spans_print.c optional atm_spans atm_core netatm/spans/spans_proto.c optional atm_spans atm_core netatm/spans/spans_subr.c optional atm_spans atm_core netatm/spans/spans_util.c optional atm_spans atm_core spans_xdr.h optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -h -C $S/netatm/spans/spans_xdr.x > spans_xdr.h" \ clean "spans_xdr.h" \ no-obj no-implicit-rule spans_xdr.c optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -c -C $S/netatm/spans/spans_xdr.x > spans_xdr.c" \ clean "spans_xdr.c" \ no-obj no-implicit-rule local spans_xdr.o optional atm_spans atm_core \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "${NORMAL_C}" \ no-implicit-rule local netatm/uni/q2110_sigaa.c optional atm_uni atm_core netatm/uni/q2110_sigcpcs.c optional atm_uni atm_core netatm/uni/q2110_subr.c optional atm_uni atm_core netatm/uni/qsaal1_sigaa.c optional atm_uni atm_core netatm/uni/qsaal1_sigcpcs.c optional atm_uni atm_core netatm/uni/qsaal1_subr.c optional atm_uni atm_core netatm/uni/sscf_uni.c optional atm_uni atm_core netatm/uni/sscf_uni_lower.c optional atm_uni atm_core netatm/uni/sscf_uni_upper.c optional atm_uni atm_core netatm/uni/sscop.c optional atm_uni atm_core netatm/uni/sscop_lower.c optional atm_uni atm_core netatm/uni/sscop_pdu.c optional atm_uni atm_core netatm/uni/sscop_sigaa.c optional atm_uni atm_core netatm/uni/sscop_sigcpcs.c optional atm_uni atm_core netatm/uni/sscop_subr.c optional atm_uni atm_core netatm/uni/sscop_timer.c optional atm_uni atm_core netatm/uni/sscop_upper.c optional atm_uni atm_core netatm/uni/uni_load.c optional atm_uni atm_core netatm/uni/uniarp.c optional atm_uni atm_core netatm/uni/uniarp_cache.c optional atm_uni atm_core netatm/uni/uniarp_input.c optional atm_uni atm_core netatm/uni/uniarp_output.c optional atm_uni atm_core netatm/uni/uniarp_timer.c optional atm_uni atm_core netatm/uni/uniarp_vcm.c optional atm_uni atm_core netatm/uni/uniip.c optional atm_uni atm_core netatm/uni/unisig_decode.c optional atm_uni atm_core netatm/uni/unisig_encode.c optional atm_uni atm_core netatm/uni/unisig_if.c optional atm_uni atm_core netatm/uni/unisig_mbuf.c optional atm_uni atm_core netatm/uni/unisig_msg.c optional atm_uni atm_core netatm/uni/unisig_print.c optional atm_uni atm_core netatm/uni/unisig_proto.c optional atm_uni atm_core netatm/uni/unisig_sigmgr_state.c optional atm_uni atm_core netatm/uni/unisig_subr.c optional atm_uni atm_core netatm/uni/unisig_util.c optional atm_uni atm_core netatm/uni/unisig_vc_state.c optional atm_uni atm_core netgraph/ng_UI.c optional netgraph_UI netgraph/ng_async.c optional netgraph_async netgraph/ng_base.c optional netgraph netgraph/ng_bpf.c optional netgraph_bpf net/bpf_filter.c optional netgraph_bpf netgraph/ng_bridge.c optional netgraph_bridge netgraph/ng_cisco.c optional netgraph_cisco netgraph/ng_device.c optional netgraph_device netgraph/ng_echo.c optional netgraph_echo netgraph/ng_ether.c optional netgraph_ether netgraph/ng_frame_relay.c optional netgraph_frame_relay netgraph/ng_gif.c optional netgraph_gif netgraph/ng_gif_demux.c optional netgraph_gif_demux netgraph/ng_hole.c optional netgraph_hole netgraph/ng_iface.c optional netgraph_iface netgraph/ng_ip_input.c optional netgraph_ip_input netgraph/ng_ksocket.c optional netgraph_ksocket netgraph/ng_lmi.c optional netgraph_lmi netgraph/ng_mppc.c optional netgraph_mppc_compression # The next two files (plus the header file net/mppc.h) are proprietary and # must be obtained elsewhere in order to enable NETGRAPH_MPPC_COMPRESSION net/mppcc.c optional netgraph_mppc_compression net/mppcd.c optional netgraph_mppc_compression netgraph/ng_mppc.c optional netgraph_mppc_encryption crypto/rc4/rc4.c optional awi crypto/rc4/rc4.c optional netgraph_mppc_encryption crypto/sha1.c optional netgraph_mppc_encryption netgraph/ng_one2many.c optional netgraph_one2many netgraph/ng_parse.c optional netgraph netgraph/ng_ppp.c optional netgraph_ppp netgraph/ng_pppoe.c optional netgraph_pppoe netgraph/ng_pptpgre.c optional netgraph_pptpgre netgraph/ng_rfc1490.c optional netgraph_rfc1490 netgraph/ng_socket.c optional netgraph_socket netgraph/ng_split.c optional netgraph_split netgraph/ng_tee.c optional netgraph_tee netgraph/ng_tty.c optional netgraph_tty netgraph/ng_vjc.c optional netgraph_vjc net/slcompress.c optional netgraph_vjc netinet/accf_data.c optional accept_filter_data netinet/accf_http.c optional accept_filter_http netinet/if_atm.c optional atm netinet/if_ether.c optional ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/in_gif.c optional gif inet netinet/ip_id.c optional inet netinet/in_pcb.c optional inet netinet/in_proto.c optional inet netinet/in_rmx.c optional inet netinet/ip_divert.c optional ipdivert netinet/ip_dummynet.c optional dummynet netinet/ip_ecn.c optional inet netinet/ip_ecn.c optional inet6 netinet/ip_encap.c optional inet netinet/ip_encap.c optional inet6 netinet/ip_flow.c optional inet netinet/ip_fw2.c optional ipfirewall netinet/ip_icmp.c optional inet netinet/ip_input.c optional inet netinet/ip_mroute.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/tcp_debug.c optional tcpdebug netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet netinet/tcp_subr.c optional inet netinet/tcp_syncache.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet netinet/udp_usrreq.c optional inet netinet6/ah_core.c optional ipsec netinet6/ah_input.c optional ipsec netinet6/ah_output.c optional ipsec netinet6/dest6.c optional inet6 netinet6/esp_core.c optional ipsec ipsec_esp netinet6/esp_input.c optional ipsec ipsec_esp netinet6/esp_output.c optional ipsec ipsec_esp netinet6/esp_rijndael.c optional ipsec ipsec_esp netinet6/frag6.c optional inet6 netinet6/icmp6.c optional inet6 netinet6/in6.c optional inet6 netinet6/in6_cksum.c optional inet6 netinet6/in6_gif.c optional gif inet6 netinet6/in6_ifattach.c optional inet6 netinet6/in6_pcb.c optional inet6 netinet6/in6_prefix.c optional inet6 netinet6/in6_proto.c optional inet6 netinet6/in6_rmx.c optional inet6 netinet6/in6_src.c optional inet6 netinet6/ip6_forward.c optional inet6 netinet6/ip6_fw.c optional inet6 ipv6firewall netinet6/ip6_input.c optional inet6 netinet6/ip6_mroute.c optional inet6 netinet6/ip6_output.c optional inet6 netinet6/ipcomp_core.c optional ipsec netinet6/ipcomp_input.c optional ipsec netinet6/ipcomp_output.c optional ipsec netinet6/ipsec.c optional ipsec netinet6/mld6.c optional inet6 netinet6/nd6.c optional inet6 netinet6/nd6_nbr.c optional inet6 netinet6/nd6_rtr.c optional inet6 netinet6/raw_ip6.c optional inet6 netinet6/route6.c optional inet6 netinet6/scope6.c optional inet6 netinet6/udp6_output.c optional inet6 netinet6/udp6_usrreq.c optional inet6 netipx/ipx.c optional ipx netipx/ipx_cksum.c optional ipx netipx/ipx_input.c optional ipx netipx/ipx_ip.c optional ipx netipx/ipx_outputfl.c optional ipx netipx/ipx_pcb.c optional ipx netipx/ipx_proto.c optional ipx netipx/ipx_tun.c optional ipx netipx/ipx_usrreq.c optional ipx netipx/spx_debug.c optional ipx netipx/spx_usrreq.c optional ipx netkey/key.c optional ipsec netkey/key_debug.c optional ipsec netkey/keydb.c optional ipsec netkey/keysock.c optional ipsec netnatm/natm.c optional natm netnatm/natm_pcb.c optional natm netnatm/natm_proto.c optional natm netncp/ncp_conn.c optional ncp netncp/ncp_crypt.c optional ncp netncp/ncp_login.c optional ncp netncp/ncp_mod.c optional ncp netncp/ncp_ncp.c optional ncp netncp/ncp_nls.c optional ncp netncp/ncp_rq.c optional ncp netncp/ncp_sock.c optional ncp netncp/ncp_subr.c optional ncp netns/idp_usrreq.c optional ns netns/ns.c optional ns netns/ns_error.c optional ns netns/ns_input.c optional ns netns/ns_ip.c optional ns netns/ns_output.c optional ns netns/ns_pcb.c optional ns netns/ns_proto.c optional ns netns/spp_debug.c optional ns netns/spp_usrreq.c optional ns nfs/nfs_common.c optional nfsclient nfs/nfs_common.c optional nfsserver nfsclient/bootp_subr.c optional bootp nfsclient nfsclient/krpc_subr.c optional bootp nfsclient nfsclient/nfs_bio.c optional nfsclient nfsclient/nfs_node.c optional nfsclient nfsclient/nfs_socket.c optional nfsclient nfsclient/nfs_subs.c optional nfsclient nfsclient/nfs_nfsiod.c optional nfsclient nfsclient/nfs_vfsops.c optional nfsclient nfsclient/nfs_vnops.c optional nfsclient nfsclient/nfs_lock.c optional nfsclient nfsserver/nfs_serv.c optional nfsserver nfsserver/nfs_srvsock.c optional nfsserver nfsserver/nfs_srvcache.c optional nfsserver nfsserver/nfs_srvsubs.c optional nfsserver nfsserver/nfs_syscalls.c optional nfsserver pccard/pccard.c count card pccard/pccard_beep.c optional card pccard/pccard_nbk.c optional card pccard/pcic.c optional pcic card pccard/pcic_isa.c optional pcic card isa pccard/pcic_pci.c optional pcic card pci pci/agp.c optional agp pci/agp_if.m optional agp pci/agp_intel.c optional agp pci/agp_via.c optional agp pci/agp_sis.c optional agp pci/agp_ali.c optional agp pci/agp_amd.c optional agp pci/agp_i810.c optional agp pci/alpm.c optional alpm pci/amd.c optional amd pci/amdpm.c optional amdpm pci/cy_pci.c optional cy pci pci/if_dc.c optional dc pci/if_de.c optional de pci/if_en_pci.c optional en pci pci/if_mn.c optional mn pci/if_pcn.c optional pcn pci/if_rl.c optional rl pci/if_sf.c optional sf pci/if_sis.c optional sis pci/if_sk.c optional sk pci/if_ste.c optional ste pci/if_ti.c optional ti pci/if_tl.c optional tl pci/if_vr.c optional vr pci/if_wb.c optional wb pci/if_xl.c optional xl pci/intpm.c optional intpm pci/meteor.c count meteor pci nowerror pci/ncr.c optional ncr pci/ohci_pci.c optional ohci pci/simos.c optional simos pci/uhci_pci.c optional uhci pci/viapm.c optional viapm pci/xrpu.c optional xrpu posix4/ksched.c optional _kposix_priority_scheduling posix4/p1003_1b.c standard posix4/posix4_mib.c standard ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_inode.c optional ffs ufs/ffs/ffs_snapshot.c optional ffs ufs/ffs/ffs_softdep.c optional softupdates ffs ufs/ffs/ffs_softdep_stub.c optional ffs ufs/ffs/ffs_subr.c optional ffs ufs/ffs/ffs_tables.c optional ffs ufs/ffs/ffs_vfsops.c optional ffs ufs/ffs/ffs_vnops.c optional ffs ufs/ufs/ufs_acl.c optional ffs ufs/ufs/ufs_bmap.c optional ffs ufs/ufs/ufs_dirhash.c optional ffs ufs/ufs/ufs_extattr.c optional ffs ufs/ufs/ufs_ihash.c optional ffs ufs/ufs/ufs_inode.c optional ffs ufs/ufs/ufs_lookup.c optional ffs ufs/ufs/ufs_quota.c optional ffs ufs/ufs/ufs_vfsops.c optional ffs ufs/ufs/ufs_vnops.c optional ffs vm/default_pager.c standard vm/device_pager.c standard vm/phys_pager.c standard vm/swap_pager.c standard vm/vm_fault.c standard vm/vm_glue.c standard vm/vm_init.c standard vm/vm_kern.c standard vm/vm_map.c standard vm/vm_meter.c standard vm/vm_mmap.c standard vm/vm_object.c standard vm/vm_page.c standard vm/vm_pageq.c standard vm/vm_contig.c standard vm/vm_zeroidle.c standard vm/vm_pageout.c standard vm/vm_pager.c standard vm/vm_swap.c standard vm/vm_unix.c standard vm/uma_core.c standard vm/uma_dbg.c standard vm/vnode_pager.c standard Index: head/sys/conf/files.ia64 =================================================================== --- head/sys/conf/files.ia64 (revision 100383) +++ head/sys/conf/files.ia64 (revision 100384) @@ -1,117 +1,118 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # # $FreeBSD$ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and # dependency lines other than the first are silently ignored. # # font8x16.o optional std8x16font \ compile-with "uudecode < /usr/share/syscons/fonts/${STD8X16FONT}-8x16.fnt && file2c 'unsigned char font_16[16*256] = {' '};' < ${STD8X16FONT}-8x16 > font8x16.c && ${CC} -c ${CFLAGS} font8x16.c" \ no-implicit-rule before-depend \ clean "${STD8X16FONT}-8x16 font8x16.c" # atkbdmap.h optional atkbd_dflt_keymap \ compile-with "/usr/sbin/kbdcontrol -L ${ATKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > atkbdmap.h" \ no-obj no-implicit-rule before-depend \ clean "atkbdmap.h" # ia64/acpica/acpi_machdep.c optional acpica ia64/acpica/acpi_wakeup.c optional acpica ia64/acpica/OsdEnvironment.c optional acpica ia64/acpica/madt.c optional acpica +ia64/ia32/ia32_misc.c optional ia32 ia64/ia32/ia32_sysent.c optional ia32 -ia64/ia32/imgact_ia32.c optional ia32 +ia64/ia32/ia32_sysvec.c optional ia32 ia64/ia64/ia64-gdbstub.c optional ddb ia64/ia64/autoconf.c standard ia64/ia64/busdma_machdep.c standard ia64/ia64/clock.c standard ia64/ia64/clock_if.m standard ia64/ia64/critical.c standard ia64/ia64/db_disasm.c optional ddb ia64/ia64/db_interface.c optional ddb ia64/ia64/db_trace.c optional ddb ia64/ia64/dump_machdep.c standard ia64/ia64/efi.c standard ia64/ia64/eficlock.c standard ia64/ia64/elf_machdep.c standard ia64/ia64/exception.s standard ia64/ia64/in_cksum.c optional inet ia64/ia64/interrupt.c standard # locore.s needs to be handled in Makefile to put it first. Otherwise it's # now normal. # ia64/ia64/locore.s standard ia64/ia64/machdep.c standard ia64/ia64/mca.c standard ia64/ia64/mem.c standard ia64/ia64/mountroot.c optional slice ia64/ia64/mp_machdep.c optional smp ia64/ia64/nexus.c standard ia64/ia64/pal.s standard ia64/ia64/pal_stub.s optional ski ia64/ia64/perfmon.c optional perfmon profiling-routine ia64/ia64/perfmon.c optional perfmon ia64/ia64/pmap.c standard ia64/ia64/sal.c standard ia64/ia64/sapic.c standard ia64/ia64/setjmp.s standard ia64/ia64/ski.c optional ski ia64/ia64/support.s standard ia64/ia64/ssc.c optional ski ia64/ia64/sscdisk.c optional ski ia64/ia64/swtch.s standard ia64/ia64/sys_machdep.c standard ia64/ia64/trap.c standard ia64/ia64/unaligned.c standard ia64/ia64/unwind.c optional ddb ia64/ia64/vm_machdep.c standard ia64/isa/isa.c optional isa ia64/isa/isa_dma.c optional isa ia64/pci/pci_cfgreg.c optional pci crypto/blowfish/bf_enc.c optional ipsec ipsec_esp crypto/des/des_enc.c optional ipsec ipsec_esp dev/advansys/adv_isa.c optional adv isa dev/aic/aic_isa.c optional aic isa dev/fb/fb.c optional fb dev/fb/fb.c optional vga dev/fb/splash.c optional splash dev/fb/vga.c optional vga dev/kbd/atkbd.c optional atkbd dev/kbd/atkbdc.c count atkbdc dev/kbd/kbd.c optional atkbd dev/kbd/kbd.c optional kbd dev/kbd/kbd.c optional sc dev/kbd/kbd.c optional ukbd dev/sio/sio.c optional sio dev/syscons/schistory.c count sc dev/syscons/scmouse.c optional sc dev/syscons/scterm.c optional sc dev/syscons/scterm-dumb.c optional sc dev/syscons/scterm-sc.c optional sc dev/syscons/scvgarndr.c optional sc vga dev/syscons/scvidctl.c optional sc dev/syscons/scvtb.c optional sc dev/syscons/syscons.c optional sc dev/syscons/sysmouse.c optional sc isa/atkbd_isa.c optional atkbd isa/atkbdc_isa.c optional atkbdc isa/fd.c optional fdc isa/ppc.c optional ppc isa/psm.c optional psm isa/syscons_isa.c optional sc isa/vga_isa.c optional vga kern/subr_diskmbr.c standard libkern/ia64/bswap16.S standard libkern/ia64/bswap32.S standard libkern/ia64/__divsi3.S standard libkern/ia64/__modsi3.S standard libkern/ia64/__udivsi3.S standard libkern/ia64/__umodsi3.S standard libkern/ia64/__divdi3.S standard libkern/ia64/__moddi3.S standard libkern/ia64/__udivdi3.S standard libkern/ia64/__umoddi3.S standard libkern/bcmp.c standard libkern/ffs.c standard Index: head/sys/i386/i386/elf_machdep.c =================================================================== --- head/sys/i386/i386/elf_machdep.c (revision 100383) +++ head/sys/i386/i386/elf_machdep.c (revision 100384) @@ -1,116 +1,156 @@ /*- * Copyright 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include +#include #include #include +#include +#include +#include +#include +#include #include +#include + +struct sysentvec elf32_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF32", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf32_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_386, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf32_freebsd_sysvec + }; + +SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &freebsd_brand_info); /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, const void *data, int type) { Elf_Addr relocbase = (Elf_Addr) lf->address; Elf_Addr *where; Elf_Addr addr; Elf_Addr addend; Elf_Word rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; switch (type) { case ELF_RELOC_REL: rel = (const Elf_Rel *)data; where = (Elf_Addr *) (relocbase + rel->r_offset); addend = *where; rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); break; case ELF_RELOC_RELA: rela = (const Elf_Rela *)data; where = (Elf_Addr *) (relocbase + rela->r_offset); addend = rela->r_addend; rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); break; default: panic("unknown reloc type %d\n", type); } switch (rtype) { case R_386_NONE: /* none */ break; case R_386_32: /* S + A */ addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; addr += addend; if (*where != addr) *where = addr; break; case R_386_PC32: /* S + A - P */ addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; addr += addend - (Elf_Addr)where; if (*where != addr) *where = addr; break; case R_386_COPY: /* none */ /* * There shouldn't be copy relocations in kernel * objects. */ printf("kldload: unexpected R_COPY relocation\n"); return -1; break; case R_386_GLOB_DAT: /* S */ addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; if (*where != addr) *where = addr; break; case R_386_RELATIVE: /* B + A */ addr = relocbase + addend; if (*where != addr) *where = addr; break; default: printf("kldload: unexpected relocation type %d\n", rtype); return -1; } return(0); } Index: head/sys/i386/ibcs2/imgact_coff.c =================================================================== --- head/sys/i386/ibcs2/imgact_coff.c (revision 100383) +++ head/sys/i386/ibcs2/imgact_coff.c (revision 100384) @@ -1,484 +1,484 @@ /*- * Copyright (c) 1994 Sean Eric Fagan * Copyright (c) 1994 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_DEPEND(coff, ibcs2, 1, 1, 1); extern struct sysentvec ibcs2_svr3_sysvec; static int coff_load_file(struct thread *td, char *name); static int exec_coff_imgact(struct image_params *imgp); static int load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot); static int load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) { size_t map_len; vm_offset_t map_offset; vm_offset_t map_addr; int error; unsigned char *data_buf = 0; size_t copy_len; map_offset = trunc_page(offset); map_addr = trunc_page((vm_offset_t)vmaddr); if (memsz > filsz) { /* * We have the stupid situation that * the section is longer than it is on file, * which means it has zero-filled areas, and * we have to work for it. Stupid iBCS! */ map_len = trunc_page(offset + filsz) - trunc_page(map_offset); } else { /* * The only stuff we care about is on disk, and we * don't care if we map in more than is really there. */ map_len = round_page(offset + filsz) - trunc_page(map_offset); } DPRINTF(("%s(%d): vm_mmap(&vmspace->vm_map, &0x%08lx, 0x%x, 0x%x, " "VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, vp, 0x%x)\n", __FILE__, __LINE__, map_addr, map_len, prot, map_offset)); if ((error = vm_mmap(&vmspace->vm_map, &map_addr, map_len, prot, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, (caddr_t) vp, map_offset)) != 0) return error; if (memsz == filsz) { /* We're done! */ return 0; } /* * Now we have screwball stuff, to accomodate stupid COFF. * We have to map the remaining bit of the file into the kernel's * memory map, allocate some anonymous memory, copy that last * bit into it, and then we're done. *sigh* * For clean-up reasons, we actally map in the file last. */ copy_len = (offset + filsz) - trunc_page(offset + filsz); map_addr = trunc_page((vm_offset_t)vmaddr + filsz); map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr; DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx,0x%x, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n", __FILE__, __LINE__, map_addr, map_len)); if (map_len != 0) { error = vm_map_find(&vmspace->vm_map, NULL, 0, &map_addr, map_len, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return error; } if ((error = vm_mmap(kernel_map, (vm_offset_t *) &data_buf, PAGE_SIZE, VM_PROT_READ, VM_PROT_READ, 0, (caddr_t) vp, trunc_page(offset + filsz))) != 0) return error; error = copyout(data_buf, (caddr_t) map_addr, copy_len); if (vm_map_remove(kernel_map, (vm_offset_t) data_buf, (vm_offset_t) data_buf + PAGE_SIZE)) panic("load_coff_section vm_map_remove failed"); return error; } static int coff_load_file(struct thread *td, char *name) { struct proc *p = td->td_proc; struct vmspace *vmspace = p->p_vmspace; int error; struct nameidata nd; struct vnode *vp; struct vattr attr; struct filehdr *fhdr; struct aouthdr *ahdr; struct scnhdr *scns; char *ptr = 0; int nscns; unsigned long text_offset = 0, text_address = 0, text_size = 0; unsigned long data_offset = 0, data_address = 0, data_size = 0; unsigned long bss_size = 0; int i; NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_SYSSPACE, name, td); error = namei(&nd); if (error) return error; vp = nd.ni_vp; if (vp == NULL) return ENOEXEC; if (vp->v_writecount) { error = ETXTBSY; goto fail; } if ((error = VOP_GETATTR(vp, &attr, td->td_ucred, td)) != 0) goto fail; if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) goto fail; if (attr.va_size == 0) { error = ENOEXEC; goto fail; } if ((error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td)) != 0) goto fail; if ((error = VOP_OPEN(vp, FREAD, td->td_ucred, td)) != 0) goto fail; /* * Lose the lock on the vnode. It's no longer needed, and must not * exist for the pagefault paging to work below. */ VOP_UNLOCK(vp, 0, td); if ((error = vm_mmap(kernel_map, (vm_offset_t *) &ptr, PAGE_SIZE, VM_PROT_READ, VM_PROT_READ, 0, (caddr_t) vp, 0)) != 0) goto unlocked_fail; fhdr = (struct filehdr *)ptr; if (fhdr->f_magic != I386_COFF) { error = ENOEXEC; goto dealloc_and_fail; } nscns = fhdr->f_nscns; if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) { /* * XXX -- just fail. I'm so lazy. */ error = ENOEXEC; goto dealloc_and_fail; } ahdr = (struct aouthdr*)(ptr + sizeof(struct filehdr)); scns = (struct scnhdr*)(ptr + sizeof(struct filehdr) + sizeof(struct aouthdr)); for (i = 0; i < nscns; i++) { if (scns[i].s_flags & STYP_NOLOAD) continue; else if (scns[i].s_flags & STYP_TEXT) { text_address = scns[i].s_vaddr; text_size = scns[i].s_size; text_offset = scns[i].s_scnptr; } else if (scns[i].s_flags & STYP_DATA) { data_address = scns[i].s_vaddr; data_size = scns[i].s_size; data_offset = scns[i].s_scnptr; } else if (scns[i].s_flags & STYP_BSS) { bss_size = scns[i].s_size; } } if ((error = load_coff_section(vmspace, vp, text_offset, (caddr_t)(void *)(uintptr_t)text_address, text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE)) != 0) { goto dealloc_and_fail; } if ((error = load_coff_section(vmspace, vp, data_offset, (caddr_t)(void *)(uintptr_t)data_address, data_size + bss_size, data_size, VM_PROT_ALL)) != 0) { goto dealloc_and_fail; } error = 0; dealloc_and_fail: if (vm_map_remove(kernel_map, (vm_offset_t) ptr, (vm_offset_t) ptr + PAGE_SIZE)) panic("%s vm_map_remove failed", __func__); fail: VOP_UNLOCK(vp, 0, td); unlocked_fail: NDFREE(&nd, NDF_ONLY_PNBUF); vrele(nd.ni_vp); return error; } static int exec_coff_imgact(imgp) struct image_params *imgp; { const struct filehdr *fhdr = (const struct filehdr*)imgp->image_header; const struct aouthdr *ahdr; const struct scnhdr *scns; int i; struct vmspace *vmspace; int nscns; int error; unsigned long text_offset = 0, text_address = 0, text_size = 0; unsigned long data_offset = 0, data_address = 0, data_size = 0; unsigned long bss_size = 0; caddr_t hole; if (fhdr->f_magic != I386_COFF || !(fhdr->f_flags & F_EXEC)) { DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__)); return -1; } nscns = fhdr->f_nscns; if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) { /* * For now, return an error -- need to be able to * read in all of the section structures. */ DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__)); return -1; } ahdr = (const struct aouthdr*) ((const char*)(imgp->image_header) + sizeof(struct filehdr)); imgp->entry_addr = ahdr->entry; scns = (const struct scnhdr*) ((const char*)(imgp->image_header) + sizeof(struct filehdr) + sizeof(struct aouthdr)); if ((error = exec_extract_strings(imgp)) != 0) { DPRINTF(("%s(%d): return %d\n", __FILE__, __LINE__, error)); return error; } - exec_new_vmspace(imgp); + exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); vmspace = imgp->proc->p_vmspace; for (i = 0; i < nscns; i++) { DPRINTF(("i = %d, scns[i].s_name = %s, scns[i].s_vaddr = %08lx, " "scns[i].s_scnptr = %d\n", i, scns[i].s_name, scns[i].s_vaddr, scns[i].s_scnptr)); if (scns[i].s_flags & STYP_NOLOAD) { /* * A section that is not loaded, for whatever * reason. It takes precedance over other flag * bits... */ continue; } else if (scns[i].s_flags & STYP_TEXT) { text_address = scns[i].s_vaddr; text_size = scns[i].s_size; text_offset = scns[i].s_scnptr; } else if (scns[i].s_flags & STYP_DATA) { /* .data section */ data_address = scns[i].s_vaddr; data_size = scns[i].s_size; data_offset = scns[i].s_scnptr; } else if (scns[i].s_flags & STYP_BSS) { /* .bss section */ bss_size = scns[i].s_size; } else if (scns[i].s_flags & STYP_LIB) { char *buf = 0; int foff = trunc_page(scns[i].s_scnptr); int off = scns[i].s_scnptr - foff; int len = round_page(scns[i].s_size + PAGE_SIZE); int j; if ((error = vm_mmap(kernel_map, (vm_offset_t *) &buf, len, VM_PROT_READ, VM_PROT_READ, 0, (caddr_t) imgp->vp, foff)) != 0) { return ENOEXEC; } if(scns[i].s_size) { char *libbuf; int emul_path_len = strlen(ibcs2_emul_path); libbuf = malloc(MAXPATHLEN + emul_path_len, M_TEMP, M_WAITOK); strcpy(libbuf, ibcs2_emul_path); for (j = off; j < scns[i].s_size + off; j++) { char *libname; libname = buf + j + 4 * *(long*)(buf + j + 4); j += 4* *(long*)(buf + j); DPRINTF(("%s(%d): shared library %s\n", __FILE__, __LINE__, libname)); strcpy(&libbuf[emul_path_len], libname); /* XXXKSE only 1:1 in coff */ error = coff_load_file( FIRST_THREAD_IN_PROC(imgp->proc), libbuf); if (error) error = coff_load_file( FIRST_THREAD_IN_PROC(imgp->proc), libname); if (error) break; } free(libbuf, M_TEMP); } if (vm_map_remove(kernel_map, (vm_offset_t) buf, (vm_offset_t) buf + len)) panic("exec_coff_imgact vm_map_remove failed"); if (error) return error; } } /* * Map in .text now */ DPRINTF(("%s(%d): load_coff_section(vmspace, " "imgp->vp, %08lx, %08lx, 0x%x, 0x%x, 0x%x)\n", __FILE__, __LINE__, text_offset, text_address, text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE)); if ((error = load_coff_section(vmspace, imgp->vp, text_offset, (caddr_t)(void *)(uintptr_t)text_address, text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE)) != 0) { DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error)); return error; } /* * Map in .data and .bss now */ DPRINTF(("%s(%d): load_coff_section(vmspace, " "imgp->vp, 0x%08lx, 0x%08lx, 0x%x, 0x%x, 0x%x)\n", __FILE__, __LINE__, data_offset, data_address, data_size + bss_size, data_size, VM_PROT_ALL)); if ((error = load_coff_section(vmspace, imgp->vp, data_offset, (caddr_t)(void *)(uintptr_t)data_address, data_size + bss_size, data_size, VM_PROT_ALL)) != 0) { DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error)); return error; } imgp->interpreted = 0; imgp->proc->p_sysent = &ibcs2_svr3_sysvec; vmspace->vm_tsize = round_page(text_size) >> PAGE_SHIFT; vmspace->vm_dsize = round_page(data_size + bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t)(void *)(uintptr_t)text_address; vmspace->vm_daddr = (caddr_t)(void *)(uintptr_t)data_address; hole = (caddr_t)trunc_page((vm_offset_t)vmspace->vm_daddr) + ctob(vmspace->vm_dsize); DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n", __FILE__, __LINE__, hole)); DPRINTF(("imgact: error = %d\n", error)); error = vm_map_find(&vmspace->vm_map, NULL, 0, (vm_offset_t *) &hole, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); DPRINTF(("IBCS2: start vm_dsize = 0x%x, vm_daddr = 0x%x end = 0x%x\n", ctob(vmspace->vm_dsize), vmspace->vm_daddr, ctob(vmspace->vm_dsize) + vmspace->vm_daddr )); DPRINTF(("%s(%d): returning successfully!\n", __FILE__, __LINE__)); /* Indicate that this file should not be modified */ imgp->vp->v_flag |= VTEXT; return 0; } /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw coff_execsw = { exec_coff_imgact, "coff" }; EXEC_SET(coff, coff_execsw); Index: head/sys/i386/linux/imgact_linux.c =================================================================== --- head/sys/i386/linux/imgact_linux.c (revision 100383) +++ head/sys/i386/linux/imgact_linux.c (revision 100384) @@ -1,239 +1,239 @@ /*- * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Based heavily on /sys/kern/imgact_aout.c which is: * Copyright (c) 1993, David Greenman * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int exec_linux_imgact(struct image_params *iparams); static int exec_linux_imgact(imgp) struct image_params *imgp; { const struct exec *a_out = (const struct exec *) imgp->image_header; struct vmspace *vmspace; vm_offset_t vmaddr; unsigned long virtual_offset, file_offset; vm_offset_t buffer; unsigned long bss_size; int error; if (((a_out->a_magic >> 16) & 0xff) != 0x64) return -1; /* * Set file/virtual offset based on a.out variant. */ switch ((int)(a_out->a_magic & 0xffff)) { case 0413: virtual_offset = 0; file_offset = 1024; break; case 0314: virtual_offset = 4096; file_offset = 0; break; default: return (-1); } bss_size = round_page(a_out->a_bss); #ifdef DEBUG printf("imgact: text: %08lx, data: %08lx, bss: %08lx\n", (u_long)a_out->a_text, (u_long)a_out->a_data, bss_size); #endif /* * Check various fields in header for validity/bounds. */ if (a_out->a_entry < virtual_offset || a_out->a_entry >= virtual_offset + a_out->a_text || a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) return (-1); /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > imgp->attr->va_size) return (EFAULT); /* * text/data/bss must not exceed limits */ mtx_assert(&Giant, MA_OWNED); if (a_out->a_text > maxtsiz || a_out->a_data + bss_size > imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) return (ENOMEM); /* copy in arguments and/or environment from old process */ error = exec_extract_strings(imgp); if (error) return (error); /* * Destroy old process VM and create a new one (with a new stack) */ - exec_new_vmspace(imgp); + exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); vmspace = imgp->proc->p_vmspace; /* * Check if file_offset page aligned,. * Currently we cannot handle misalinged file offsets, * and so we read in the entire image (what a waste). */ if (file_offset & PAGE_MASK) { #ifdef DEBUG printf("imgact: Non page aligned binary %lu\n", file_offset); #endif /* * Map text+data+bss read/write/execute */ vmaddr = virtual_offset; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, a_out->a_text + a_out->a_data + bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return error; error = vm_mmap(kernel_map, &buffer, round_page(a_out->a_text + a_out->a_data + file_offset), VM_PROT_READ, VM_PROT_READ, 0, (caddr_t) imgp->vp, trunc_page(file_offset)); if (error) return error; error = copyout((caddr_t)(void *)(uintptr_t)(buffer + file_offset), (caddr_t)vmaddr, a_out->a_text + a_out->a_data); vm_map_remove(kernel_map, buffer, buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); if (error) return error; /* * remove write enable on the 'text' part */ error = vm_map_protect(&vmspace->vm_map, vmaddr, vmaddr + a_out->a_text, VM_PROT_EXECUTE|VM_PROT_READ, TRUE); if (error) return error; } else { #ifdef DEBUG printf("imgact: Page aligned binary %lu\n", file_offset); #endif /* * Map text+data read/execute */ vmaddr = virtual_offset; error = vm_mmap(&vmspace->vm_map, &vmaddr, a_out->a_text + a_out->a_data, VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, (caddr_t)imgp->vp, file_offset); if (error) return (error); #ifdef DEBUG printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr, a_out->a_text + a_out->a_data); #endif /* * allow read/write of data */ error = vm_map_protect(&vmspace->vm_map, vmaddr + a_out->a_text, vmaddr + a_out->a_text + a_out->a_data, VM_PROT_ALL, FALSE); if (error) return (error); /* * Allocate anon demand-zeroed area for uninitialized data */ if (bss_size != 0) { vmaddr = virtual_offset + a_out->a_text + a_out->a_data; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return (error); #ifdef DEBUG printf("imgact: bssaddr=%08lx, length=%08lx\n", (u_long)vmaddr, bss_size); #endif } /* Indicate that this file should not be modified */ imgp->vp->v_flag |= VTEXT; } /* Fill in process VM information */ vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT; vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t)(void *)(uintptr_t)virtual_offset; vmspace->vm_daddr = (caddr_t)(void *)(uintptr_t) (virtual_offset + a_out->a_text); /* Fill in image_params */ imgp->interpreted = 0; imgp->entry_addr = a_out->a_entry; imgp->proc->p_sysent = &linux_sysvec; return (0); } /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw linux_execsw = { exec_linux_imgact, "linux a.out" }; EXEC_SET(linuxaout, linux_execsw); Index: head/sys/i386/linux/linux_sysvec.c =================================================================== --- head/sys/i386/linux/linux_sysvec.c (revision 100383) +++ head/sys/i386/linux/linux_sysvec.c (revision 100384) @@ -1,876 +1,878 @@ /*- * Copyright (c) 1994-1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ /* XXX we use functions that might not exist. */ #include "opt_compat.h" #ifndef COMPAT_43 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_VERSION(linux, 1); MODULE_DEPEND(linux, sysvmsg, 1, 1, 1); MODULE_DEPEND(linux, sysvsem, 1, 1, 1); MODULE_DEPEND(linux, sysvshm, 1, 1, 1); MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); #if BYTE_ORDER == LITTLE_ENDIAN #define SHELLMAGIC 0x2123 /* #! */ #else #define SHELLMAGIC 0x2321 #endif /* * Allow the sendsig functions to use the ldebug() facility * even though they are not syscalls themselves. Map them * to syscall 0. This is slightly less bogus than using * ldebug(sigreturn). */ #define LINUX_SYS_linux_rt_sendsig 0 #define LINUX_SYS_linux_sendsig 0 extern char linux_sigcode[]; extern int linux_szsigcode; extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); static int linux_fixup(register_t **stack_base, struct image_params *iparams); static int elf_linux_fixup(register_t **stack_base, struct image_params *iparams); static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params); static void linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); /* * Linux syscalls return negative errno's, we do positive and map them */ static int bsd_to_linux_errno[ELAST + 1] = { -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, -6, -6, -43, -42, -75, -6, -84 }; int bsd_to_linux_signal[LINUX_SIGTBLSZ] = { LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT, LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0, LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV, 0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM, LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT, LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO, LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF, LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2 }; int linux_to_bsd_signal[LINUX_SIGTBLSZ] = { SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGURG, 0 }; #define LINUX_T_UNKNOWN 255 static int _bsd_to_linux_trapcode[] = { LINUX_T_UNKNOWN, /* 0 */ 6, /* 1 T_PRIVINFLT */ LINUX_T_UNKNOWN, /* 2 */ 3, /* 3 T_BPTFLT */ LINUX_T_UNKNOWN, /* 4 */ LINUX_T_UNKNOWN, /* 5 */ 16, /* 6 T_ARITHTRAP */ 254, /* 7 T_ASTFLT */ LINUX_T_UNKNOWN, /* 8 */ 13, /* 9 T_PROTFLT */ 1, /* 10 T_TRCTRAP */ LINUX_T_UNKNOWN, /* 11 */ 14, /* 12 T_PAGEFLT */ LINUX_T_UNKNOWN, /* 13 */ 17, /* 14 T_ALIGNFLT */ LINUX_T_UNKNOWN, /* 15 */ LINUX_T_UNKNOWN, /* 16 */ LINUX_T_UNKNOWN, /* 17 */ 0, /* 18 T_DIVIDE */ 2, /* 19 T_NMI */ 4, /* 20 T_OFLOW */ 5, /* 21 T_BOUND */ 7, /* 22 T_DNA */ 8, /* 23 T_DOUBLEFLT */ 9, /* 24 T_FPOPFLT */ 10, /* 25 T_TSSFLT */ 11, /* 26 T_SEGNPFLT */ 12, /* 27 T_STKFLT */ 18, /* 28 T_MCHK */ 19, /* 29 T_XMMFLT */ 15 /* 30 T_RESERVED */ }; #define bsd_to_linux_trapcode(code) \ ((code)argc + 1); (*stack_base)--; **stack_base = (intptr_t)(void *)envp; (*stack_base)--; **stack_base = (intptr_t)(void *)argv; (*stack_base)--; **stack_base = imgp->argc; return 0; } static int elf_linux_fixup(register_t **stack_base, struct image_params *imgp) { Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; register_t *pos; pos = *stack_base + (imgp->argc + imgp->envc + 2); if (args->trace) { AUXARGS_ENTRY(pos, AT_DEBUG, 1); } if (args->execfd != -1) { AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); } AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); PROC_LOCK(imgp->proc); AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); PROC_UNLOCK(imgp->proc); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; **stack_base = (long)imgp->argc; return 0; } extern int _ucodesel, _udatasel; extern unsigned long linux_sznonrtsigcode; static void linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { register struct thread *td = curthread; register struct proc *p = td->td_proc; register struct trapframe *regs; struct l_rt_sigframe *fp, frame; int oonstack; PROC_LOCK_ASSERT(p, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); #ifdef DEBUG if (ldebug(rt_sendsig)) printf(ARGS(rt_sendsig, "%p, %d, %p, %lu"), catcher, sig, (void*)mask, code); #endif /* * Allocate space for the signal handler context. */ if ((p->p_flag & P_ALTSTACK) && !oonstack && SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) { fp = (struct l_rt_sigframe *)(p->p_sigstk.ss_sp + p->p_sigstk.ss_size - sizeof(struct l_rt_sigframe)); } else fp = (struct l_rt_sigframe *)regs->tf_esp - 1; PROC_UNLOCK(p); /* * Build the argument list for the signal handler. */ if (p->p_sysent->sv_sigtbl) if (sig <= p->p_sysent->sv_sigsize) sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; frame.sf_handler = catcher; frame.sf_sig = sig; frame.sf_siginfo = &fp->sf_si; frame.sf_ucontext = &fp->sf_sc; /* Fill siginfo structure. */ frame.sf_si.lsi_signo = sig; frame.sf_si.lsi_code = code; frame.sf_si.lsi_addr = (void *)regs->tf_err; /* * Build the signal context to be used by sigreturn. */ frame.sf_sc.uc_flags = 0; /* XXX ??? */ frame.sf_sc.uc_link = NULL; /* XXX ??? */ PROC_LOCK(p); frame.sf_sc.uc_stack.ss_sp = p->p_sigstk.ss_sp; frame.sf_sc.uc_stack.ss_size = p->p_sigstk.ss_size; frame.sf_sc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) ? ((oonstack) ? LINUX_SS_ONSTACK : 0) : LINUX_SS_DISABLE; PROC_UNLOCK(p); bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask); frame.sf_sc.uc_mcontext.sc_mask = frame.sf_sc.uc_sigmask.__bits[0]; frame.sf_sc.uc_mcontext.sc_gs = rgs(); frame.sf_sc.uc_mcontext.sc_fs = regs->tf_fs; frame.sf_sc.uc_mcontext.sc_es = regs->tf_es; frame.sf_sc.uc_mcontext.sc_ds = regs->tf_ds; frame.sf_sc.uc_mcontext.sc_edi = regs->tf_edi; frame.sf_sc.uc_mcontext.sc_esi = regs->tf_esi; frame.sf_sc.uc_mcontext.sc_ebp = regs->tf_ebp; frame.sf_sc.uc_mcontext.sc_ebx = regs->tf_ebx; frame.sf_sc.uc_mcontext.sc_edx = regs->tf_edx; frame.sf_sc.uc_mcontext.sc_ecx = regs->tf_ecx; frame.sf_sc.uc_mcontext.sc_eax = regs->tf_eax; frame.sf_sc.uc_mcontext.sc_eip = regs->tf_eip; frame.sf_sc.uc_mcontext.sc_cs = regs->tf_cs; frame.sf_sc.uc_mcontext.sc_eflags = regs->tf_eflags; frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_esp; frame.sf_sc.uc_mcontext.sc_ss = regs->tf_ss; frame.sf_sc.uc_mcontext.sc_err = regs->tf_err; frame.sf_sc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code); #ifdef DEBUG if (ldebug(rt_sendsig)) printf(LMSG("rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), frame.sf_sc.uc_stack.ss_flags, p->p_sigstk.ss_sp, p->p_sigstk.ss_size, frame.sf_sc.uc_mcontext.sc_mask); #endif if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG if (ldebug(rt_sendsig)) printf(LMSG("rt_sendsig: bad stack %p, oonstack=%x"), fp, oonstack); #endif PROC_LOCK(p); sigexit(td, SIGILL); } /* * Build context to run handler in. */ regs->tf_esp = (int)fp; regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode) + linux_sznonrtsigcode; regs->tf_eflags &= ~(PSL_T | PSL_VM); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); } /* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ static void linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { register struct thread *td = curthread; register struct proc *p = td->td_proc; register struct trapframe *regs; struct l_sigframe *fp, frame; l_sigset_t lmask; int oonstack, i; PROC_LOCK_ASSERT(p, MA_OWNED); if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ linux_rt_sendsig(catcher, sig, mask, code); return; } regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); #ifdef DEBUG if (ldebug(sendsig)) printf(ARGS(sendsig, "%p, %d, %p, %lu"), catcher, sig, (void*)mask, code); #endif /* * Allocate space for the signal handler context. */ if ((p->p_flag & P_ALTSTACK) && !oonstack && SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) { fp = (struct l_sigframe *)(p->p_sigstk.ss_sp + p->p_sigstk.ss_size - sizeof(struct l_sigframe)); } else fp = (struct l_sigframe *)regs->tf_esp - 1; PROC_UNLOCK(p); /* * Build the argument list for the signal handler. */ if (p->p_sysent->sv_sigtbl) if (sig <= p->p_sysent->sv_sigsize) sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; frame.sf_handler = catcher; frame.sf_sig = sig; bsd_to_linux_sigset(mask, &lmask); /* * Build the signal context to be used by sigreturn. */ frame.sf_sc.sc_mask = lmask.__bits[0]; frame.sf_sc.sc_gs = rgs(); frame.sf_sc.sc_fs = regs->tf_fs; frame.sf_sc.sc_es = regs->tf_es; frame.sf_sc.sc_ds = regs->tf_ds; frame.sf_sc.sc_edi = regs->tf_edi; frame.sf_sc.sc_esi = regs->tf_esi; frame.sf_sc.sc_ebp = regs->tf_ebp; frame.sf_sc.sc_ebx = regs->tf_ebx; frame.sf_sc.sc_edx = regs->tf_edx; frame.sf_sc.sc_ecx = regs->tf_ecx; frame.sf_sc.sc_eax = regs->tf_eax; frame.sf_sc.sc_eip = regs->tf_eip; frame.sf_sc.sc_cs = regs->tf_cs; frame.sf_sc.sc_eflags = regs->tf_eflags; frame.sf_sc.sc_esp_at_signal = regs->tf_esp; frame.sf_sc.sc_ss = regs->tf_ss; frame.sf_sc.sc_err = regs->tf_err; frame.sf_sc.sc_trapno = bsd_to_linux_trapcode(code); bzero(&frame.sf_fpstate, sizeof(struct l_fpstate)); for (i = 0; i < (LINUX_NSIG_WORDS-1); i++) frame.sf_extramask[i] = lmask.__bits[i+1]; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ PROC_LOCK(p); sigexit(td, SIGILL); } /* * Build context to run handler in. */ regs->tf_esp = (int)fp; regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); regs->tf_eflags &= ~(PSL_T | PSL_VM); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. */ int linux_sigreturn(td, args) struct thread *td; struct linux_sigreturn_args *args; { struct proc *p = td->td_proc; struct l_sigframe frame; register struct trapframe *regs; l_sigset_t lmask; int eflags, i; regs = td->td_frame; #ifdef DEBUG if (ldebug(sigreturn)) printf(ARGS(sigreturn, "%p"), (void *)args->sfp); #endif /* * The trampoline code hands us the sigframe. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ if (copyin((caddr_t)args->sfp, &frame, sizeof(frame)) != 0) return (EFAULT); /* * Check for security violations. */ #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) eflags = frame.sf_sc.sc_eflags; /* * XXX do allow users to change the privileged flag PSL_RF. The * cpu sets PSL_RF in tf_eflags for faults. Debuggers should * sometimes set it there too. tf_eflags is kept in the signal * context during signal handling and there is no other place * to remember it, so the PSL_RF bit may be corrupted by the * signal handler without us knowing. Corruption of the PSL_RF * bit at worst causes one more or one less debugger trap, so * allowing it is fairly harmless. */ if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { return(EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) if (!CS_SECURE(frame.sf_sc.sc_cs)) { trapsignal(p, SIGBUS, T_PROTFLT); return(EINVAL); } lmask.__bits[0] = frame.sf_sc.sc_mask; for (i = 0; i < (LINUX_NSIG_WORDS-1); i++) lmask.__bits[i+1] = frame.sf_extramask[i]; PROC_LOCK(p); linux_to_bsd_sigset(&lmask, &p->p_sigmask); SIG_CANTMASK(p->p_sigmask); signotify(p); PROC_UNLOCK(p); /* * Restore signal context. */ /* %gs was restored by the trampoline. */ regs->tf_fs = frame.sf_sc.sc_fs; regs->tf_es = frame.sf_sc.sc_es; regs->tf_ds = frame.sf_sc.sc_ds; regs->tf_edi = frame.sf_sc.sc_edi; regs->tf_esi = frame.sf_sc.sc_esi; regs->tf_ebp = frame.sf_sc.sc_ebp; regs->tf_ebx = frame.sf_sc.sc_ebx; regs->tf_edx = frame.sf_sc.sc_edx; regs->tf_ecx = frame.sf_sc.sc_ecx; regs->tf_eax = frame.sf_sc.sc_eax; regs->tf_eip = frame.sf_sc.sc_eip; regs->tf_cs = frame.sf_sc.sc_cs; regs->tf_eflags = eflags; regs->tf_esp = frame.sf_sc.sc_esp_at_signal; regs->tf_ss = frame.sf_sc.sc_ss; return (EJUSTRETURN); } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by rt_sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. */ int linux_rt_sigreturn(td, args) struct thread *td; struct linux_rt_sigreturn_args *args; { struct proc *p = td->td_proc; struct sigaltstack_args sasargs; struct l_ucontext uc; struct l_sigcontext *context; l_stack_t *lss; stack_t *ss; register struct trapframe *regs; int eflags; caddr_t sg = stackgap_init(); regs = td->td_frame; #ifdef DEBUG if (ldebug(rt_sigreturn)) printf(ARGS(rt_sigreturn, "%p"), (void *)args->ucp); #endif /* * The trampoline code hands us the ucontext. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ if (copyin((caddr_t)args->ucp, &uc, sizeof(uc)) != 0) return (EFAULT); context = &uc.uc_mcontext; /* * Check for security violations. */ #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) eflags = context->sc_eflags; /* * XXX do allow users to change the privileged flag PSL_RF. The * cpu sets PSL_RF in tf_eflags for faults. Debuggers should * sometimes set it there too. tf_eflags is kept in the signal * context during signal handling and there is no other place * to remember it, so the PSL_RF bit may be corrupted by the * signal handler without us knowing. Corruption of the PSL_RF * bit at worst causes one more or one less debugger trap, so * allowing it is fairly harmless. */ if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { return(EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) if (!CS_SECURE(context->sc_cs)) { trapsignal(p, SIGBUS, T_PROTFLT); return(EINVAL); } PROC_LOCK(p); linux_to_bsd_sigset(&uc.uc_sigmask, &p->p_sigmask); SIG_CANTMASK(p->p_sigmask); signotify(p); PROC_UNLOCK(p); /* * Restore signal context */ /* %gs was restored by the trampoline. */ regs->tf_fs = context->sc_fs; regs->tf_es = context->sc_es; regs->tf_ds = context->sc_ds; regs->tf_edi = context->sc_edi; regs->tf_esi = context->sc_esi; regs->tf_ebp = context->sc_ebp; regs->tf_ebx = context->sc_ebx; regs->tf_edx = context->sc_edx; regs->tf_ecx = context->sc_ecx; regs->tf_eax = context->sc_eax; regs->tf_eip = context->sc_eip; regs->tf_cs = context->sc_cs; regs->tf_eflags = eflags; regs->tf_esp = context->sc_esp_at_signal; regs->tf_ss = context->sc_ss; /* * call sigaltstack & ignore results.. */ ss = stackgap_alloc(&sg, sizeof(stack_t)); lss = &uc.uc_stack; ss->ss_sp = lss->ss_sp; ss->ss_size = lss->ss_size; ss->ss_flags = linux_to_bsd_sigaltstack(lss->ss_flags); #ifdef DEBUG if (ldebug(rt_sigreturn)) printf(LMSG("rt_sigret flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), ss->ss_flags, ss->ss_sp, ss->ss_size, context->sc_mask); #endif sasargs.ss = ss; sasargs.oss = NULL; (void) sigaltstack(td, &sasargs); return (EJUSTRETURN); } /* * MPSAFE */ static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params) { args[0] = tf->tf_ebx; args[1] = tf->tf_ecx; args[2] = tf->tf_edx; args[3] = tf->tf_esi; args[4] = tf->tf_edi; *params = NULL; /* no copyin */ } /* * If a linux binary is exec'ing something, try this image activator * first. We override standard shell script execution in order to * be able to modify the interpreter path. We only do this if a linux * binary is doing the exec, so we do not create an EXEC module for it. */ static int exec_linux_imgact_try(struct image_params *iparams); static int exec_linux_imgact_try(imgp) struct image_params *imgp; { const char *head = (const char *)imgp->image_header; int error = -1; /* * The interpreter for shell scripts run from a linux binary needs * to be located in /compat/linux if possible in order to recursively * maintain linux path emulation. */ if (((const short *)head)[0] == SHELLMAGIC) { /* * Run our normal shell image activator. If it succeeds attempt * to use the alternate path for the interpreter. If an alternate * path is found, use our stringspace to store it. */ if ((error = exec_shell_imgact(imgp)) == 0) { char *rpath = NULL; linux_emul_find(FIRST_THREAD_IN_PROC(imgp->proc), NULL, imgp->interpreter_name, &rpath, 0); if (rpath != imgp->interpreter_name) { int len = strlen(rpath) + 1; if (len <= MAXSHELLCMDLEN) { memcpy(imgp->interpreter_name, rpath, len); } free(rpath, M_TEMP); } } } return(error); } struct sysentvec linux_sysvec = { LINUX_SYS_MAXSYSCALL, linux_sysent, 0xff, LINUX_SIGTBLSZ, bsd_to_linux_signal, ELAST + 1, bsd_to_linux_errno, translate_traps, linux_fixup, linux_sendsig, linux_sigcode, &linux_szsigcode, linux_prepsyscall, "Linux a.out", aout_coredump, exec_linux_imgact_try, LINUX_MINSIGSTKSZ }; struct sysentvec elf_linux_sysvec = { LINUX_SYS_MAXSYSCALL, linux_sysent, 0xff, LINUX_SIGTBLSZ, bsd_to_linux_signal, ELAST + 1, bsd_to_linux_errno, translate_traps, elf_linux_fixup, linux_sendsig, linux_sigcode, &linux_szsigcode, linux_prepsyscall, "Linux ELF", - elf_coredump, + elf32_coredump, exec_linux_imgact_try, LINUX_MINSIGSTKSZ }; static Elf32_Brandinfo linux_brand = { ELFOSABI_LINUX, + EM_386, "Linux", "/compat/linux", "/lib/ld-linux.so.1", &elf_linux_sysvec }; static Elf32_Brandinfo linux_glibc2brand = { ELFOSABI_LINUX, + EM_386, "Linux", "/compat/linux", "/lib/ld-linux.so.2", &elf_linux_sysvec }; Elf32_Brandinfo *linux_brandlist[] = { &linux_brand, &linux_glibc2brand, NULL }; static int linux_elf_modevent(module_t mod, int type, void *data) { Elf32_Brandinfo **brandinfo; int error; struct linux_ioctl_handler **lihp; error = 0; switch(type) { case MOD_LOAD: for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) - if (elf_insert_brand_entry(*brandinfo) < 0) + if (elf32_insert_brand_entry(*brandinfo) < 0) error = EINVAL; if (error == 0) { SET_FOREACH(lihp, linux_ioctl_handler_set) linux_ioctl_register_handler(*lihp); if (bootverbose) printf("Linux ELF exec handler installed\n"); } else printf("cannot insert Linux ELF brand handler\n"); break; case MOD_UNLOAD: for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) - if (elf_brand_inuse(*brandinfo)) + if (elf32_brand_inuse(*brandinfo)) error = EBUSY; if (error == 0) { for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; ++brandinfo) - if (elf_remove_brand_entry(*brandinfo) < 0) + if (elf32_remove_brand_entry(*brandinfo) < 0) error = EINVAL; } if (error == 0) { SET_FOREACH(lihp, linux_ioctl_handler_set) linux_ioctl_unregister_handler(*lihp); if (bootverbose) printf("Linux ELF exec handler removed\n"); } else printf("Could not deinstall ELF interpreter entry\n"); break; default: break; } return error; } static moduledata_t linux_elf_mod = { "linuxelf", linux_elf_modevent, 0 }; DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); Index: head/sys/ia64/ia32/imgact_ia32.h =================================================================== --- head/sys/ia64/ia32/imgact_ia32.h (revision 100383) +++ head/sys/ia64/ia32/imgact_ia32.h (nonexistent) @@ -1,112 +0,0 @@ -/*- - * Copyright (c) 1995-1996 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _IA64_IA32_IMGACT_ELF_H_ -#define _IA64_IA32_IMGACT_ELF_H_ - -#include - -#ifdef _KERNEL - -#define AUXARGS_ENTRY(pos, id, val) {suword(pos++, id); suword(pos++, val);} - -#if ELF_TARG_CLASS == ELFCLASS32 - -/* - * Structure used to pass infomation from the loader to the - * stack fixup routine. - */ -typedef struct { - Elf32_Sword execfd; - Elf32_Word phdr; - Elf32_Word phent; - Elf32_Word phnum; - Elf32_Word pagesz; - Elf32_Word base; - Elf32_Word flags; - Elf32_Word entry; - Elf32_Word trace; -} Elf32_Auxargs; - -typedef struct { - int brand; - const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */ - const char *emul_path; - const char *interp_path; - struct sysentvec *sysvec; -} Elf32_Brandinfo; - -#define MAX_BRANDS 8 - -int elf_brand_inuse(Elf32_Brandinfo *entry); -int elf_insert_brand_entry(Elf32_Brandinfo *entry); -int elf_remove_brand_entry(Elf32_Brandinfo *entry); - -#else /* !(ELF_TARG_CLASS == ELFCLASS32) */ - -/* - * Structure used to pass infomation from the loader to the - * stack fixup routine. - */ -typedef struct { - Elf64_Sword execfd; - Elf64_Addr phdr; - Elf64_Word phent; - Elf64_Word phnum; - Elf64_Word pagesz; - Elf64_Addr base; - Elf64_Word flags; - Elf64_Addr entry; - Elf64_Word trace; -} Elf64_Auxargs; - -typedef struct { - int brand; - const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */ - const char *emul_path; - const char *interp_path; - struct sysentvec *sysvec; -} Elf64_Brandinfo; - -#define MAX_BRANDS 8 - -int elf_brand_inuse(Elf64_Brandinfo *entry); -int elf_insert_brand_entry(Elf64_Brandinfo *entry); -int elf_remove_brand_entry(Elf64_Brandinfo *entry); - -#endif /* ELF_TARG_CLASS == ELFCLASS32 */ - -struct thread; - -int elf_coredump(struct thread *, struct vnode *, off_t); - -#endif /* _KERNEL */ - -#endif /* !_IA64_IA32_IMGACT_ELF_H_ */ Property changes on: head/sys/ia64/ia32/imgact_ia32.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/ia64/ia32/imgact_ia32.c =================================================================== --- head/sys/ia64/ia32/imgact_ia32.c (revision 100383) +++ head/sys/ia64/ia32/imgact_ia32.c (nonexistent) @@ -1,1446 +0,0 @@ -/*- - * Copyright (c) 2000 David O'Brien - * Copyright (c) 1995-1996 Søren Schmidt - * Copyright (c) 1996 Peter Wemm - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define OLD_EI_BRAND 8 - -__ElfType(Brandinfo); -__ElfType(Auxargs); - -#define IA32_USRSTACK (3L*1024*1024*1024) -#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings)) - -static int elf32_check_header(const Elf32_Ehdr *hdr); -static int elf32_freebsd_fixup(register_t **stack_base, - struct image_params *imgp); -static int elf32_load_file(struct proc *p, const char *file, u_long *addr, - u_long *entry); -static int elf32_load_section(struct proc *p, - struct vmspace *vmspace, struct vnode *vp, - vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, - vm_prot_t prot); -static int exec_elf32_imgact(struct image_params *imgp); -static int elf32_coredump(struct thread *td, struct vnode *vp, off_t limit); -static register_t *elf32_copyout_strings(struct image_params *imgp); -static void elf32_setregs(struct thread *td, u_long entry, u_long stack, - u_long ps_strings); - -static int elf32_trace = 0; -SYSCTL_INT(_debug, OID_AUTO, elf32_trace, CTLFLAG_RW, &elf32_trace, 0, ""); - -extern struct sysent ia32_sysent[]; - -static char ia32_sigcode[] = { - 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */ - 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */ - 0x50, /* pushl %eax */ - 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */ - 0x75, 0x03, /* jne 9f */ - 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */ - 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */ - 0x50, /* pushl %eax */ - 0xcd, 0x80, /* int $0x80 */ - 0xeb, 0xfe, /* 0: jmp 0b */ - 0, 0, 0, 0 -}; -static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3; - -struct sysentvec elf32_freebsd_sysvec = { - SYS_MAXSYSCALL, - ia32_sysent, - 0, - 0, - 0, - 0, - 0, - 0, - elf32_freebsd_fixup, - sendsig, - ia32_sigcode, - &ia32_szsigcode, - 0, - "FreeBSD ELF", - elf32_coredump, - NULL, - MINSIGSTKSZ, - elf32_copyout_strings, - elf32_setregs -}; - -static Elf32_Brandinfo freebsd_brand_info = { - ELFOSABI_FREEBSD, - "FreeBSD", - "", - "/usr/libexec/ld-elf.so.1", - &elf32_freebsd_sysvec - }; -static Elf32_Brandinfo *elf32_brand_list[MAX_BRANDS] = { - &freebsd_brand_info, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL - }; - -#if 0 - -int -elf32_insert_brand_entry(Elf32_Brandinfo *entry) -{ - int i; - - for (i=1; ip_sysent == entry->sysvec) { - rval = TRUE; - break; - } - } - sx_sunlock(&allproc_lock); - - return (rval); -} - -#endif - -static int -elf32_check_header(const Elf32_Ehdr *hdr) -{ - if (!IS_ELF(*hdr) || - hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || - hdr->e_ident[EI_DATA] != ELF_TARG_DATA || - hdr->e_ident[EI_VERSION] != EV_CURRENT) - return ENOEXEC; - - if (!ELF_MACHINE_OK(hdr->e_machine)) - return ENOEXEC; - - if (hdr->e_version != ELF_TARG_VER) - return ENOEXEC; - - return 0; -} - -#define PAGE4K_SHIFT 12 -#define PAGE4K_MASK ((1 << PAGE4K_SHIFT)-1) -#define round_page4k(x) (((x) + PAGE4K_MASK) & ~(PAGE4K_MASK)) -#define trunc_page4k(x) ((x) & ~(PAGE4K_MASK)) - -static int -elf32_map_partial(vm_map_t map, vm_object_t object, vm_ooffset_t offset, - vm_offset_t start, vm_offset_t end, vm_prot_t prot, - vm_prot_t max) -{ - int error, rv; - vm_offset_t off; - vm_offset_t data_buf = 0; - - /* - * Create the page if it doesn't exist yet. Ignore errors. - */ - vm_map_lock(map); - vm_map_insert(map, NULL, 0, trunc_page(start), round_page(end), - max, max, 0); - vm_map_unlock(map); - - /* - * Find the page from the underlying object. - */ - if (object) { - vm_object_reference(object); - rv = vm_map_find(exec_map, - object, - trunc_page(offset), - &data_buf, - PAGE_SIZE, - TRUE, - VM_PROT_READ, - VM_PROT_ALL, - MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); - if (rv != KERN_SUCCESS) { - vm_object_deallocate(object); - return rv; - } - - off = offset - trunc_page(offset); - error = copyout((caddr_t)data_buf+off, (caddr_t)start, end - start); - vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE); - if (error) { - return KERN_FAILURE; - } - } - - return KERN_SUCCESS; -} - -static int -elf32_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset, - vm_offset_t start, vm_offset_t end, vm_prot_t prot, - vm_prot_t max, int cow) -{ - int rv; - - if (start != trunc_page(start)) { - rv = elf32_map_partial(map, object, offset, - start, round_page(start), prot, max); - if (rv) - return rv; - start = round_page(start); - offset = round_page(offset); - } - if (end != round_page(end)) { - rv = elf32_map_partial(map, object, offset, - trunc_page(end), end, prot, max); - if (rv) - return rv; - end = trunc_page(end); - } - if (end > start) { - vm_map_lock(map); - rv = vm_map_insert(map, object, offset, start, end, - prot, max, cow); - vm_map_unlock(map); - return rv; - } else { - return KERN_SUCCESS; - } -} - -static int -elf32_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) -{ - size_t map_len; - vm_offset_t map_addr; - int error, rv; - size_t copy_len; - vm_object_t object; - vm_offset_t file_addr; - vm_offset_t data_buf = 0; - - GIANT_REQUIRED; - - VOP_GETVOBJECT(vp, &object); - error = 0; - - /* - * It's necessary to fail if the filsz + offset taken from the - * header is greater than the actual file pager object's size. - * If we were to allow this, then the vm_map_find() below would - * walk right off the end of the file object and into the ether. - * - * While I'm here, might as well check for something else that - * is invalid: filsz cannot be greater than memsz. - */ - if ((off_t)filsz + offset > object->un_pager.vnp.vnp_size || - filsz > memsz) { - uprintf("elf32_load_section: truncated ELF file\n"); - return (ENOEXEC); - } - - map_addr = trunc_page4k((vm_offset_t)vmaddr); - file_addr = trunc_page4k(offset); - - /* - * We have two choices. We can either clear the data in the last page - * of an oversized mapping, or we can start the anon mapping a page - * early and copy the initialized data into that first page. We - * choose the second.. - */ - if (memsz > filsz) - map_len = trunc_page4k(offset+filsz) - file_addr; - else - map_len = round_page4k(offset+filsz) - file_addr; - - if (map_len != 0) { - vm_object_reference(object); - rv = elf32_map_insert(&vmspace->vm_map, - object, - file_addr, /* file offset */ - map_addr, /* virtual start */ - map_addr + map_len,/* virtual end */ - prot, - VM_PROT_ALL, - MAP_COPY_ON_WRITE | MAP_PREFAULT); - if (rv != KERN_SUCCESS) { - vm_object_deallocate(object); - return EINVAL; - } - - /* we can stop now if we've covered it all */ - if (memsz == filsz) { - return 0; - } - } - - - /* - * We have to get the remaining bit of the file into the first part - * of the oversized map segment. This is normally because the .data - * segment in the file is extended to provide bss. It's a neat idea - * to try and save a page, but it's a pain in the behind to implement. - */ - copy_len = (offset + filsz) - trunc_page4k(offset + filsz); - map_addr = trunc_page4k((vm_offset_t)vmaddr + filsz); - map_len = round_page4k((vm_offset_t)vmaddr + memsz) - map_addr; - - /* This had damn well better be true! */ - if (map_len != 0) { - rv = elf32_map_insert(&vmspace->vm_map, NULL, 0, - map_addr, map_addr + map_len, - VM_PROT_ALL, VM_PROT_ALL, 0); - if (rv != KERN_SUCCESS) { - return EINVAL; - } - } - - if (copy_len != 0) { - vm_offset_t off; - vm_object_reference(object); - rv = vm_map_find(exec_map, - object, - trunc_page(offset + filsz), - &data_buf, - PAGE_SIZE, - TRUE, - VM_PROT_READ, - VM_PROT_ALL, - MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); - if (rv != KERN_SUCCESS) { - vm_object_deallocate(object); - return EINVAL; - } - - /* send the page fragment to user space */ - off = trunc_page4k(offset + filsz) - trunc_page(offset + filsz); - error = copyout((caddr_t)data_buf+off, (caddr_t)map_addr, copy_len); - vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE); - if (error) { - return (error); - } - } - - /* - * set it to the specified protection - */ - vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot, - FALSE); - - return error; -} - -/* - * Load the file "file" into memory. It may be either a shared object - * or an executable. - * - * The "addr" reference parameter is in/out. On entry, it specifies - * the address where a shared object should be loaded. If the file is - * an executable, this value is ignored. On exit, "addr" specifies - * where the file was actually loaded. - * - * The "entry" reference parameter is out only. On exit, it specifies - * the entry point for the loaded file. - */ -static int -elf32_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry) -{ - struct { - struct nameidata nd; - struct vattr attr; - struct image_params image_params; - } *tempdata; - const Elf32_Ehdr *hdr = NULL; - const Elf32_Phdr *phdr = NULL; - struct nameidata *nd; - struct vmspace *vmspace = p->p_vmspace; - struct vattr *attr; - struct image_params *imgp; - vm_prot_t prot; - u_long rbase; - u_long base_addr = 0; - int error, i, numsegs; - - if (curthread->td_proc != p) - panic("elf32_load_file - thread"); /* XXXKSE DIAGNOSTIC */ - - tempdata = malloc(sizeof(*tempdata), M_TEMP, M_WAITOK); - nd = &tempdata->nd; - attr = &tempdata->attr; - imgp = &tempdata->image_params; - - /* - * Initialize part of the common data - */ - imgp->proc = p; - imgp->uap = NULL; - imgp->attr = attr; - imgp->firstpage = NULL; - imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE); - - if (imgp->image_header == NULL) { - nd->ni_vp = NULL; - error = ENOMEM; - goto fail; - } - - /* XXXKSE */ - NDINIT(nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, curthread); - - if ((error = namei(nd)) != 0) { - nd->ni_vp = NULL; - goto fail; - } - NDFREE(nd, NDF_ONLY_PNBUF); - imgp->vp = nd->ni_vp; - - /* - * Check permissions, modes, uid, etc on the file, and "open" it. - */ - error = exec_check_permissions(imgp); - if (error) { - VOP_UNLOCK(nd->ni_vp, 0, curthread); /* XXXKSE */ - goto fail; - } - - error = exec_map_first_page(imgp); - /* - * Also make certain that the interpreter stays the same, so set - * its VTEXT flag, too. - */ - if (error == 0) - nd->ni_vp->v_flag |= VTEXT; - VOP_UNLOCK(nd->ni_vp, 0, curthread); /* XXXKSE */ - if (error) - goto fail; - - hdr = (const Elf32_Ehdr *)imgp->image_header; - if ((error = elf32_check_header(hdr)) != 0) - goto fail; - if (hdr->e_type == ET_DYN) - rbase = *addr; - else if (hdr->e_type == ET_EXEC) - rbase = 0; - else { - error = ENOEXEC; - goto fail; - } - - /* Only support headers that fit within first page for now */ - if ((hdr->e_phoff > PAGE_SIZE) || - (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) { - error = ENOEXEC; - goto fail; - } - - phdr = (const Elf32_Phdr *)(imgp->image_header + hdr->e_phoff); - - for (i = 0, numsegs = 0; i < hdr->e_phnum; i++) { - if (phdr[i].p_type == PT_LOAD) { /* Loadable segment */ - prot = 0; - if (phdr[i].p_flags & PF_X) - prot |= VM_PROT_EXECUTE; - if (phdr[i].p_flags & PF_W) - prot |= VM_PROT_WRITE; - if (phdr[i].p_flags & PF_R) - prot |= VM_PROT_READ; - - if ((error = elf32_load_section(p, vmspace, nd->ni_vp, - phdr[i].p_offset, - (caddr_t)(uintptr_t)phdr[i].p_vaddr + - rbase, - phdr[i].p_memsz, - phdr[i].p_filesz, prot)) != 0) - goto fail; - /* - * Establish the base address if this is the - * first segment. - */ - if (numsegs == 0) - base_addr = trunc_page(phdr[i].p_vaddr + rbase); - numsegs++; - } - } - *addr = base_addr; - *entry=(unsigned long)hdr->e_entry + rbase; - -fail: - if (imgp->firstpage) - exec_unmap_first_page(imgp); - if (imgp->image_header) - kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header, - PAGE_SIZE); - if (nd->ni_vp) - vrele(nd->ni_vp); - - free(tempdata, M_TEMP); - - return error; -} - -/* - * non static, as it can be overridden by start_init() - */ -#ifdef __ia64__ -int fallback_elf32_brand = ELFOSABI_FREEBSD; -#else -int fallback_elf32_brand = -1; -#endif -SYSCTL_INT(_kern, OID_AUTO, fallback_elf32_brand, CTLFLAG_RW, - &fallback_elf32_brand, -1, - "ELF brand of last resort"); - -static int -exec_elf32_imgact(struct image_params *imgp) -{ - const Elf32_Ehdr *hdr = (const Elf32_Ehdr *) imgp->image_header; - const Elf32_Phdr *phdr; - Elf32_Auxargs *elf32_auxargs = NULL; - struct vmspace *vmspace; - vm_prot_t prot; - u_long text_size = 0, data_size = 0; - u_long text_addr = 0, data_addr = 0; - u_long addr, entry = 0, proghdr = 0; - int error, i; - const char *interp = NULL; - Elf32_Brandinfo *brand_info; - char *path; - - GIANT_REQUIRED; - - /* - * Do we have a valid ELF header ? - */ - if (elf32_check_header(hdr) != 0 || hdr->e_type != ET_EXEC) - return -1; - - /* - * From here on down, we return an errno, not -1, as we've - * detected an ELF file. - */ - - if ((hdr->e_phoff > PAGE_SIZE) || - (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) { - /* Only support headers in first page for now */ - return ENOEXEC; - } - phdr = (const Elf32_Phdr*)(imgp->image_header + hdr->e_phoff); - - /* - * From this point on, we may have resources that need to be freed. - */ - - /* - * Yeah, I'm paranoid. There is every reason in the world to get - * VTEXT now since from here on out, there are places we can have - * a context switch. Better safe than sorry; I really don't want - * the file to change while it's being loaded. - */ - mtx_lock(&imgp->vp->v_interlock); - imgp->vp->v_flag |= VTEXT; - mtx_unlock(&imgp->vp->v_interlock); - - if ((error = exec_extract_strings(imgp)) != 0) - goto fail; - - exec_new_vmspace(imgp, IA32_USRSTACK); - - vmspace = imgp->proc->p_vmspace; - - for (i = 0; i < hdr->e_phnum; i++) { - switch(phdr[i].p_type) { - - case PT_LOAD: /* Loadable segment */ - prot = 0; - if (phdr[i].p_flags & PF_X) - prot |= VM_PROT_EXECUTE; - if (phdr[i].p_flags & PF_W) - prot |= VM_PROT_WRITE; - if (phdr[i].p_flags & PF_R) - prot |= VM_PROT_READ; - - if ((error = elf32_load_section(imgp->proc, - vmspace, imgp->vp, - phdr[i].p_offset, - (caddr_t)(uintptr_t)phdr[i].p_vaddr, - phdr[i].p_memsz, - phdr[i].p_filesz, prot)) != 0) - goto fail; - - /* - * Is this .text or .data ?? - * - * We only handle one each of those yet XXX - */ - if (hdr->e_entry >= phdr[i].p_vaddr && - hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { - text_addr = trunc_page(phdr[i].p_vaddr); - text_size = round_page(phdr[i].p_memsz + - phdr[i].p_vaddr - - text_addr); - entry = (u_long)hdr->e_entry; - } else { - data_addr = trunc_page(phdr[i].p_vaddr); - data_size = round_page(phdr[i].p_memsz + - phdr[i].p_vaddr - - data_addr); - } - break; - case PT_INTERP: /* Path to interpreter */ - if (phdr[i].p_filesz > MAXPATHLEN || - phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) { - error = ENOEXEC; - goto fail; - } - interp = imgp->image_header + phdr[i].p_offset; - break; - case PT_PHDR: /* Program header table info */ - proghdr = phdr[i].p_vaddr; - break; - default: - break; - } - } - - vmspace->vm_tsize = text_size >> PAGE_SHIFT; - vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr; - vmspace->vm_dsize = data_size >> PAGE_SHIFT; - vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr; - - addr = ELF_RTLD_ADDR(vmspace); - - imgp->entry_addr = entry; - - brand_info = NULL; - - /* We support three types of branding -- (1) the ELF EI_OSABI field - * that SCO added to the ELF spec, (2) FreeBSD 3.x's traditional string - * branding w/in the ELF header, and (3) path of the `interp_path' - * field. We should also look for an ".note.ABI-tag" ELF section now - * in all Linux ELF binaries, FreeBSD 4.1+, and some NetBSD ones. - */ - - /* If the executable has a brand, search for it in the brand list. */ - if (brand_info == NULL) { - for (i = 0; i < MAX_BRANDS; i++) { - Elf32_Brandinfo *bi = elf32_brand_list[i]; - - if (bi != NULL && - (hdr->e_ident[EI_OSABI] == bi->brand - || 0 == - strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND], - bi->compat_3_brand, strlen(bi->compat_3_brand)))) { - brand_info = bi; - break; - } - } - } - - /* Lacking a known brand, search for a recognized interpreter. */ - if (brand_info == NULL && interp != NULL) { - for (i = 0; i < MAX_BRANDS; i++) { - Elf32_Brandinfo *bi = elf32_brand_list[i]; - - if (bi != NULL && - strcmp(interp, bi->interp_path) == 0) { - brand_info = bi; - break; - } - } - } - - /* Lacking a recognized interpreter, try the default brand */ - if (brand_info == NULL) { - for (i = 0; i < MAX_BRANDS; i++) { - Elf32_Brandinfo *bi = elf32_brand_list[i]; - - if (bi != NULL && fallback_elf32_brand == bi->brand) { - brand_info = bi; - break; - } - } - } - - if (brand_info == NULL) { - uprintf("ELF binary type \"%u\" not known.\n", - hdr->e_ident[EI_OSABI]); - error = ENOEXEC; - goto fail; - } - - imgp->proc->p_sysent = brand_info->sysvec; - if (interp != NULL) { - path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - snprintf(path, MAXPATHLEN, "%s%s", - brand_info->emul_path, interp); - if ((error = elf32_load_file(imgp->proc, path, &addr, - &imgp->entry_addr)) != 0) { - if ((error = elf32_load_file(imgp->proc, interp, &addr, - &imgp->entry_addr)) != 0) { - uprintf("ELF interpreter %s not found\n", path); - free(path, M_TEMP); - goto fail; - } - } - free(path, M_TEMP); - } - - /* - * Construct auxargs table (used by the fixup routine) - */ - elf32_auxargs = malloc(sizeof(Elf32_Auxargs), M_TEMP, M_WAITOK); - elf32_auxargs->execfd = -1; - elf32_auxargs->phdr = proghdr; - elf32_auxargs->phent = hdr->e_phentsize; - elf32_auxargs->phnum = hdr->e_phnum; - elf32_auxargs->pagesz = PAGE_SIZE; - elf32_auxargs->base = addr; - elf32_auxargs->flags = 0; - elf32_auxargs->entry = entry; - elf32_auxargs->trace = elf32_trace; - - imgp->auxargs = elf32_auxargs; - imgp->interpreted = 0; - -fail: - return error; -} - -#define AUXARGS32_ENTRY(pos, id, val) { \ - suword32(pos++, id); \ - suword32(pos++, val); \ -} - -static int -elf32_freebsd_fixup(register_t **stack_base, struct image_params *imgp) -{ - Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; - u_int32_t *pos; - - pos = *(u_int32_t **)stack_base + (imgp->argc + imgp->envc + 2); - - if (args->trace) { - AUXARGS32_ENTRY(pos, AT_DEBUG, 1); - } - if (args->execfd != -1) { - AUXARGS32_ENTRY(pos, AT_EXECFD, args->execfd); - } - AUXARGS32_ENTRY(pos, AT_PHDR, args->phdr); - AUXARGS32_ENTRY(pos, AT_PHENT, args->phent); - AUXARGS32_ENTRY(pos, AT_PHNUM, args->phnum); - AUXARGS32_ENTRY(pos, AT_PAGESZ, args->pagesz); - AUXARGS32_ENTRY(pos, AT_FLAGS, args->flags); - AUXARGS32_ENTRY(pos, AT_ENTRY, args->entry); - AUXARGS32_ENTRY(pos, AT_BASE, args->base); - AUXARGS32_ENTRY(pos, AT_NULL, 0); - - free(imgp->auxargs, M_TEMP); - imgp->auxargs = NULL; - - (*(u_int32_t **)stack_base)--; - suword32(*stack_base, (long) imgp->argc); - return 0; -} - -/* - * Code for generating ELF core dumps. - */ - -typedef void (*segment_callback)(vm_map_entry_t, void *); - -/* Closure for cb_put_phdr(). */ -struct phdr_closure { - Elf32_Phdr *phdr; /* Program header to fill in */ - Elf32_Off offset; /* Offset of segment in core file */ -}; - -/* Closure for cb_size_segment(). */ -struct sseg_closure { - int count; /* Count of writable segments. */ - size_t size; /* Total size of all writable segments. */ -}; - -static void cb_put_phdr(vm_map_entry_t, void *); -static void cb_size_segment(vm_map_entry_t, void *); -static void each_writable_segment(struct proc *, segment_callback, void *); -static int elf32_corehdr(struct thread *, struct vnode *, struct ucred *, - int, void *, size_t); -static void elf32_puthdr(struct proc *, void *, size_t *, - const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int); -static void elf32_putnote(void *, size_t *, const char *, int, - const void *, size_t); - -extern int osreldate; - -static int -elf32_coredump(td, vp, limit) - struct thread *td; - register struct vnode *vp; - off_t limit; -{ - register struct proc *p = td->td_proc; - register struct ucred *cred = td->td_ucred; - int error = 0; - struct sseg_closure seginfo; - void *hdr; - size_t hdrsize; - - /* Size the program segments. */ - seginfo.count = 0; - seginfo.size = 0; - each_writable_segment(p, cb_size_segment, &seginfo); - - /* - * Calculate the size of the core file header area by making - * a dry run of generating it. Nothing is written, but the - * size is calculated. - */ - hdrsize = 0; - elf32_puthdr((struct proc *)NULL, (void *)NULL, &hdrsize, - (const prstatus_t *)NULL, (const prfpregset_t *)NULL, - (const prpsinfo_t *)NULL, seginfo.count); - - if (hdrsize + seginfo.size >= limit) - return (EFAULT); - - /* - * Allocate memory for building the header, fill it up, - * and write it out. - */ - hdr = malloc(hdrsize, M_TEMP, M_WAITOK); - if (hdr == NULL) { - return EINVAL; - } - error = elf32_corehdr(td, vp, cred, seginfo.count, hdr, hdrsize); - - /* Write the contents of all of the writable segments. */ - if (error == 0) { - Elf32_Phdr *php; - off_t offset; - int i; - - php = (Elf32_Phdr *)((char *)hdr + sizeof(Elf32_Ehdr)) + 1; - offset = hdrsize; - for (i = 0; i < seginfo.count; i++) { - error = vn_rdwr_inchunks(UIO_WRITE, vp, - (caddr_t)(uintptr_t)php->p_vaddr, - php->p_filesz, offset, UIO_USERSPACE, - IO_UNIT | IO_DIRECT, cred, (int *)NULL, curthread); /* XXXKSE */ - if (error != 0) - break; - offset += php->p_filesz; - php++; - } - } - free(hdr, M_TEMP); - - return error; -} - -/* - * A callback for each_writable_segment() to write out the segment's - * program header entry. - */ -static void -cb_put_phdr(entry, closure) - vm_map_entry_t entry; - void *closure; -{ - struct phdr_closure *phc = (struct phdr_closure *)closure; - Elf32_Phdr *phdr = phc->phdr; - - phc->offset = round_page(phc->offset); - - phdr->p_type = PT_LOAD; - phdr->p_offset = phc->offset; - phdr->p_vaddr = entry->start; - phdr->p_paddr = 0; - phdr->p_filesz = phdr->p_memsz = entry->end - entry->start; - phdr->p_align = PAGE_SIZE; - phdr->p_flags = 0; - if (entry->protection & VM_PROT_READ) - phdr->p_flags |= PF_R; - if (entry->protection & VM_PROT_WRITE) - phdr->p_flags |= PF_W; - if (entry->protection & VM_PROT_EXECUTE) - phdr->p_flags |= PF_X; - - phc->offset += phdr->p_filesz; - phc->phdr++; -} - -/* - * A callback for each_writable_segment() to gather information about - * the number of segments and their total size. - */ -static void -cb_size_segment(entry, closure) - vm_map_entry_t entry; - void *closure; -{ - struct sseg_closure *ssc = (struct sseg_closure *)closure; - - ssc->count++; - ssc->size += entry->end - entry->start; -} - -/* - * For each writable segment in the process's memory map, call the given - * function with a pointer to the map entry and some arbitrary - * caller-supplied data. - */ -static void -each_writable_segment(p, func, closure) - struct proc *p; - segment_callback func; - void *closure; -{ - vm_map_t map = &p->p_vmspace->vm_map; - vm_map_entry_t entry; - - for (entry = map->header.next; entry != &map->header; - entry = entry->next) { - vm_object_t obj; - - if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) || - (entry->protection & (VM_PROT_READ|VM_PROT_WRITE)) != - (VM_PROT_READ|VM_PROT_WRITE)) - continue; - - /* - ** Dont include memory segment in the coredump if - ** MAP_NOCORE is set in mmap(2) or MADV_NOCORE in - ** madvise(2). - */ - if (entry->eflags & MAP_ENTRY_NOCOREDUMP) - continue; - - if ((obj = entry->object.vm_object) == NULL) - continue; - - /* Find the deepest backing object. */ - while (obj->backing_object != NULL) - obj = obj->backing_object; - - /* Ignore memory-mapped devices and such things. */ - if (obj->type != OBJT_DEFAULT && - obj->type != OBJT_SWAP && - obj->type != OBJT_VNODE) - continue; - - (*func)(entry, closure); - } -} - -/* - * Write the core file header to the file, including padding up to - * the page boundary. - */ -static int -elf32_corehdr(td, vp, cred, numsegs, hdr, hdrsize) - struct thread *td; - struct vnode *vp; - struct ucred *cred; - int numsegs; - size_t hdrsize; - void *hdr; -{ - struct { - prstatus_t status; - prfpregset_t fpregset; - prpsinfo_t psinfo; - } *tempdata; - struct proc *p = td->td_proc; - size_t off; - prstatus_t *status; - prfpregset_t *fpregset; - prpsinfo_t *psinfo; - - tempdata = malloc(sizeof(*tempdata), M_TEMP, M_ZERO | M_WAITOK); - status = &tempdata->status; - fpregset = &tempdata->fpregset; - psinfo = &tempdata->psinfo; - - /* Gather the information for the header. */ - status->pr_version = PRSTATUS_VERSION; - status->pr_statussz = sizeof(prstatus_t); - status->pr_gregsetsz = sizeof(gregset_t); - status->pr_fpregsetsz = sizeof(fpregset_t); - status->pr_osreldate = osreldate; - status->pr_cursig = p->p_sig; - status->pr_pid = p->p_pid; - fill_regs(td, &status->pr_reg); - - fill_fpregs(td, fpregset); - - psinfo->pr_version = PRPSINFO_VERSION; - psinfo->pr_psinfosz = sizeof(prpsinfo_t); - strncpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname) - 1); - - /* XXX - We don't fill in the command line arguments properly yet. */ - strncpy(psinfo->pr_psargs, p->p_comm, PRARGSZ); - - /* Fill in the header. */ - bzero(hdr, hdrsize); - off = 0; - elf32_puthdr(p, hdr, &off, status, fpregset, psinfo, numsegs); - - free(tempdata, M_TEMP); - - /* Write it to the core file. */ - return vn_rdwr_inchunks(UIO_WRITE, vp, hdr, hdrsize, (off_t)0, - UIO_SYSSPACE, IO_UNIT | IO_DIRECT, cred, NULL, td); /* XXXKSE */ -} - -static void -elf32_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status, - const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs) -{ - size_t ehoff; - size_t phoff; - size_t noteoff; - size_t notesz; - - ehoff = *off; - *off += sizeof(Elf32_Ehdr); - - phoff = *off; - *off += (numsegs + 1) * sizeof(Elf32_Phdr); - - noteoff = *off; - elf32_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status, - sizeof *status); - elf32_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset, - sizeof *fpregset); - elf32_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo, - sizeof *psinfo); - notesz = *off - noteoff; - - /* Align up to a page boundary for the program segments. */ - *off = round_page(*off); - - if (dst != NULL) { - Elf32_Ehdr *ehdr; - Elf32_Phdr *phdr; - struct phdr_closure phc; - - /* - * Fill in the ELF header. - */ - ehdr = (Elf32_Ehdr *)((char *)dst + ehoff); - ehdr->e_ident[EI_MAG0] = ELFMAG0; - ehdr->e_ident[EI_MAG1] = ELFMAG1; - ehdr->e_ident[EI_MAG2] = ELFMAG2; - ehdr->e_ident[EI_MAG3] = ELFMAG3; - ehdr->e_ident[EI_CLASS] = ELF_CLASS; - ehdr->e_ident[EI_DATA] = ELF_DATA; - ehdr->e_ident[EI_VERSION] = EV_CURRENT; - ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; - ehdr->e_ident[EI_ABIVERSION] = 0; - ehdr->e_ident[EI_PAD] = 0; - ehdr->e_type = ET_CORE; - ehdr->e_machine = ELF_ARCH; - ehdr->e_version = EV_CURRENT; - ehdr->e_entry = 0; - ehdr->e_phoff = phoff; - ehdr->e_flags = 0; - ehdr->e_ehsize = sizeof(Elf32_Ehdr); - ehdr->e_phentsize = sizeof(Elf32_Phdr); - ehdr->e_phnum = numsegs + 1; - ehdr->e_shentsize = sizeof(Elf32_Shdr); - ehdr->e_shnum = 0; - ehdr->e_shstrndx = SHN_UNDEF; - - /* - * Fill in the program header entries. - */ - phdr = (Elf32_Phdr *)((char *)dst + phoff); - - /* The note segement. */ - phdr->p_type = PT_NOTE; - phdr->p_offset = noteoff; - phdr->p_vaddr = 0; - phdr->p_paddr = 0; - phdr->p_filesz = notesz; - phdr->p_memsz = 0; - phdr->p_flags = 0; - phdr->p_align = 0; - phdr++; - - /* All the writable segments from the program. */ - phc.phdr = phdr; - phc.offset = *off; - each_writable_segment(p, cb_put_phdr, &phc); - } -} - -static void -elf32_putnote(void *dst, size_t *off, const char *name, int type, - const void *desc, size_t descsz) -{ - Elf_Note note; - - note.n_namesz = strlen(name) + 1; - note.n_descsz = descsz; - note.n_type = type; - if (dst != NULL) - bcopy(¬e, (char *)dst + *off, sizeof note); - *off += sizeof note; - if (dst != NULL) - bcopy(name, (char *)dst + *off, note.n_namesz); - *off += roundup2(note.n_namesz, sizeof(Elf32_Size)); - if (dst != NULL) - bcopy(desc, (char *)dst + *off, note.n_descsz); - *off += roundup2(note.n_descsz, sizeof(Elf32_Size)); -} - -struct ia32_ps_strings { - u_int32_t ps_argvstr; /* first of 0 or more argument strings */ - int ps_nargvstr; /* the number of argument strings */ - u_int32_t ps_envstr; /* first of 0 or more environment strings */ - int ps_nenvstr; /* the number of environment strings */ -}; - -static register_t * -elf32_copyout_strings(struct image_params *imgp) -{ - int argc, envc; - u_int32_t *vectp; - char *stringp, *destp; - u_int32_t *stack_base; - struct ia32_ps_strings *arginfo; - int szsigcode; - - /* - * Calculate string base and vector table pointers. - * Also deal with signal trampoline code for this exec type. - */ - arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS; - szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); - destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - - roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); - - /* - * install sigcode - */ - if (szsigcode) - copyout(imgp->proc->p_sysent->sv_sigcode, - ((caddr_t)arginfo - szsigcode), szsigcode); - - /* - * If we have a valid auxargs ptr, prepare some room - * on the stack. - */ - if (imgp->auxargs) { - /* - * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for - * lower compatibility. - */ - imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size - : (AT_COUNT * 2); - /* - * The '+ 2' is for the null pointers at the end of each of - * the arg and env vector sets,and imgp->auxarg_size is room - * for argument of Runtime loader. - */ - vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + - imgp->auxarg_size) * sizeof(u_int32_t)); - - } else - /* - * The '+ 2' is for the null pointers at the end of each of - * the arg and env vector sets - */ - vectp = (u_int32_t *) - (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); - - /* - * vectp also becomes our initial stack base - */ - stack_base = vectp; - - stringp = imgp->stringbase; - argc = imgp->argc; - envc = imgp->envc; - - /* - * Copy out strings - arguments and environment. - */ - copyout(stringp, destp, ARG_MAX - imgp->stringspace); - - /* - * Fill in "ps_strings" struct for ps, w, etc. - */ - suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); - suword32(&arginfo->ps_nargvstr, argc); - - /* - * Fill in argument portion of vector table. - */ - for (; argc > 0; --argc) { - suword32(vectp++, (u_int32_t)(intptr_t)destp); - while (*stringp++ != 0) - destp++; - destp++; - } - - /* a null vector table pointer separates the argp's from the envp's */ - suword32(vectp++, 0); - - suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); - suword32(&arginfo->ps_nenvstr, envc); - - /* - * Fill in environment portion of vector table. - */ - for (; envc > 0; --envc) { - suword32(vectp++, (u_int32_t)(intptr_t)destp); - while (*stringp++ != 0) - destp++; - destp++; - } - - /* end of vector table is a null pointer */ - suword32(vectp, 0); - - return ((register_t *)stack_base); -} - -static void -elf32_setregs(struct thread *td, u_long entry, u_long stack, - u_long ps_strings) -{ - struct trapframe *frame = td->td_frame; - vm_offset_t gdt, ldt; - u_int64_t codesel, datasel, ldtsel; - u_int64_t codeseg, dataseg, gdtseg, ldtseg; - struct segment_descriptor desc; - struct vmspace *vmspace = td->td_proc->p_vmspace; - - /* - * Make sure that we restore the entire trapframe after an - * execve. - */ - frame->tf_flags &= ~FRAME_SYSCALL; - - bzero(frame->tf_r, sizeof(frame->tf_r)); - bzero(frame->tf_f, sizeof(frame->tf_f)); - - frame->tf_cr_iip = entry; - frame->tf_cr_ipsr = (IA64_PSR_IC - | IA64_PSR_I - | IA64_PSR_IT - | IA64_PSR_DT - | IA64_PSR_RT - | IA64_PSR_IS - | IA64_PSR_BN - | IA64_PSR_CPL_USER); - frame->tf_r[FRAME_R12] = stack; - - codesel = LSEL(LUCODE_SEL, SEL_UPL); - datasel = LSEL(LUDATA_SEL, SEL_UPL); - ldtsel = GSEL(GLDT_SEL, SEL_UPL); - -#if 1 - frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32) - | (datasel << 16) | datasel; - frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel; -#else - frame->tf_r[FRAME_R16] = datasel; - frame->tf_r[FRAME_R17] = codesel; - frame->tf_r[FRAME_R18] = datasel; - frame->tf_r[FRAME_R19] = datasel; - frame->tf_r[FRAME_R20] = datasel; - frame->tf_r[FRAME_R21] = datasel; - frame->tf_r[FRAME_R22] = ldtsel; -#endif - - /* - * Build the GDT and LDT. - */ - gdt = IA32_USRSTACK; - vm_map_find(&vmspace->vm_map, 0, 0, - &gdt, PAGE_SIZE, 0, - VM_PROT_ALL, VM_PROT_ALL, 0); - ldt = gdt + 4096; - - desc.sd_lolimit = 8*NLDT-1; - desc.sd_lobase = ldt & 0xffffff; - desc.sd_type = SDT_SYSLDT; - desc.sd_dpl = SEL_UPL; - desc.sd_p = 1; - desc.sd_hilimit = 0; - desc.sd_def32 = 0; - desc.sd_gran = 0; - desc.sd_hibase = ldt >> 24; - copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc)); - - desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff; - desc.sd_lobase = 0; - desc.sd_type = SDT_MEMERA; - desc.sd_dpl = SEL_UPL; - desc.sd_p = 1; - desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16; - desc.sd_def32 = 1; - desc.sd_gran = 1; - desc.sd_hibase = 0; - copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc)); - desc.sd_type = SDT_MEMRWA; - copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc)); - - codeseg = 0 /* base */ - + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ - + ((long)SDT_MEMERA << 52) - + ((long)SEL_UPL << 57) - + (1L << 59) /* present */ - + (1L << 62) /* 32 bits */ - + (1L << 63); /* page granularity */ - dataseg = 0 /* base */ - + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ - + ((long)SDT_MEMRWA << 52) - + ((long)SEL_UPL << 57) - + (1L << 59) /* present */ - + (1L << 62) /* 32 bits */ - + (1L << 63); /* page granularity */ - ia64_set_csd(codeseg); - ia64_set_ssd(dataseg); - frame->tf_r[FRAME_R24] = dataseg; /* ESD */ - frame->tf_r[FRAME_R27] = dataseg; /* DSD */ - frame->tf_r[FRAME_R28] = dataseg; /* FSD */ - frame->tf_r[FRAME_R29] = dataseg; /* GSD */ - - gdtseg = gdt /* base */ - + ((8L*NGDT - 1) << 32) /* limit */ - + ((long)SDT_SYSNULL << 52) - + ((long)SEL_UPL << 57) - + (1L << 59) /* present */ - + (0L << 62) /* 16 bits */ - + (0L << 63); /* byte granularity */ - ldtseg = ldt /* base */ - + ((8L*NLDT - 1) << 32) /* limit */ - + ((long)SDT_SYSLDT << 52) - + ((long)SEL_UPL << 57) - + (1L << 59) /* present */ - + (0L << 62) /* 16 bits */ - + (0L << 63); /* byte granularity */ - frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */ - frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */ - - ia64_set_eflag(PSL_USER); - - /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ - frame->tf_r[FRAME_R11] = ps_strings; - - /* - * Set ia32 control registers. - */ - ia64_set_cflg((CR0_PE | CR0_PG) - | ((long)(CR4_XMM | CR4_FXSR) << 32)); - - /* - * XXX - Linux emulator - * Make sure sure edx is 0x0 on entry. Linux binaries depend - * on it. - */ - td->td_retval[1] = 0; -} - -/* - * Tell kern_execve.c about it, with a little help from the linker. - */ -static struct execsw elf32_execsw = {exec_elf32_imgact, "ELF32"}; -EXEC_SET(elf32, elf32_execsw); Property changes on: head/sys/ia64/ia32/imgact_ia32.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/sys/ia64/ia32/ia32.h =================================================================== --- head/sys/ia64/ia32/ia32.h (nonexistent) +++ head/sys/ia64/ia32/ia32.h (revision 100384) @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2001 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IA64_IA32_IA32_H_ +#define _IA64_IA32_IA32_H_ + +#define PTRIN(v) (void *)(uintptr_t) (v) +#define PTROUT(v) (u_int32_t)(uintptr_t) (v) + +#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0) +#define PTRIN_CP(src,dst,fld) \ + do { (dst).fld = PTRIN((src).fld); } while (0) +#define PTROUT_CP(src,dst,fld) \ + do { (dst).fld = PTROUT((src).fld); } while (0) + +struct timeval32 { + int32_t tv_sec; + int32_t tv_usec; +}; +#define TV_CP(src,dst,fld) do { \ + CP((src).fld,(dst).fld,tv_sec); \ + CP((src).fld,(dst).fld,tv_usec); \ +} while (0); + +struct timespec32 { + u_int32_t tv_sec; + u_int32_t tv_nsec; +}; +#define TS_CP(src,dst,fld) do { \ + CP((src).fld,(dst).fld,tv_sec); \ + CP((src).fld,(dst).fld,tv_nsec); \ +} while (0); + +struct rusage32 { + struct timeval32 ru_utime; + struct timeval32 ru_stime; + int32_t ru_maxrss; + int32_t ru_ixrss; + int32_t ru_idrss; + int32_t ru_isrss; + int32_t ru_minflt; + int32_t ru_majflt; + int32_t ru_nswap; + int32_t ru_inblock; + int32_t ru_oublock; + int32_t ru_msgsnd; + int32_t ru_msgrcv; + int32_t ru_nsignals; + int32_t ru_nvcsw; + int32_t ru_nivcsw; +}; + +struct statfs32 { + int32_t f_spare2; + int32_t f_bsize; + int32_t f_iosize; + int32_t f_blocks; + int32_t f_bfree; + int32_t f_bavail; + int32_t f_files; + int32_t f_ffree; + fsid_t f_fsid; + uid_t f_owner; + int32_t f_type; + int32_t f_flags; + int32_t f_syncwrites; + int32_t f_asyncwrites; + char f_fstypename[MFSNAMELEN]; + char f_mntonname[MNAMELEN]; + int32_t f_syncreads; + int32_t f_asyncreads; + int16_t f_spares1; + char f_mntfromname[MNAMELEN]; + int16_t f_spares2; + int32_t f_spare[2]; +}; + +#endif /* !_IA64_IA32_IA32_H_ */ Property changes on: head/sys/ia64/ia32/ia32.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/ia64/ia32/ia32_misc.c =================================================================== --- head/sys/ia64/ia32/ia32_misc.c (nonexistent) +++ head/sys/ia64/ia32/ia32_misc.c (revision 100384) @@ -0,0 +1,1339 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Must come after sys/malloc.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Must come after sys/selinfo.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static const char ia32_emul_path[] = "/compat/ia32"; +/* + * [ taken from the linux emulator ] + * Search an alternate path before passing pathname arguments on + * to system calls. Useful for keeping a separate 'emulation tree'. + * + * If cflag is set, we check if an attempt can be made to create + * the named file, i.e. we check if the directory it should + * be in exists. + */ +int +ia32_emul_find(td, sgp, prefix, path, pbuf, cflag) + struct thread *td; + caddr_t *sgp; /* Pointer to stackgap memory */ + const char *prefix; + char *path; + char **pbuf; + int cflag; +{ + int error; + size_t len, sz; + char *buf, *cp, *ptr; + struct ucred *ucred; + struct nameidata nd; + struct nameidata ndroot; + struct vattr vat; + struct vattr vatroot; + + buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + *pbuf = path; + + for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) + continue; + + sz = MAXPATHLEN - (ptr - buf); + + /* + * If sgp is not given then the path is already in kernel space + */ + if (sgp == NULL) + error = copystr(path, ptr, sz, &len); + else + error = copyinstr(path, ptr, sz, &len); + + if (error) { + free(buf, M_TEMP); + return error; + } + + if (*ptr != '/') { + free(buf, M_TEMP); + return EINVAL; + } + + /* + * We know that there is a / somewhere in this pathname. + * Search backwards for it, to find the file's parent dir + * to see if it exists in the alternate tree. If it does, + * and we want to create a file (cflag is set). We don't + * need to worry about the root comparison in this case. + */ + + if (cflag) { + for (cp = &ptr[len] - 1; *cp != '/'; cp--) + ; + *cp = '\0'; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + *cp = '/'; + } else { + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + /* + * We now compare the vnode of the ia32_root to the one + * vnode asked. If they resolve to be the same, then we + * ignore the match so that the real root gets used. + * This avoids the problem of traversing "../.." to find the + * root directory and never finding it, because "/" resolves + * to the emulation root directory. This is expensive :-( + */ + NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path, + td); + + if ((error = namei(&ndroot)) != 0) { + /* Cannot happen! */ + free(buf, M_TEMP); + vrele(nd.ni_vp); + return error; + } + + ucred = td->td_ucred; + if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) { + goto bad; + } + + if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred, + td)) != 0) { + goto bad; + } + + if (vat.va_fsid == vatroot.va_fsid && + vat.va_fileid == vatroot.va_fileid) { + error = ENOENT; + goto bad; + } + + } + if (sgp == NULL) + *pbuf = buf; + else { + sz = &ptr[len] - buf; + *pbuf = stackgap_alloc(sgp, sz + 1); + error = copyout(buf, *pbuf, sz); + free(buf, M_TEMP); + } + + vrele(nd.ni_vp); + if (!cflag) + vrele(ndroot.ni_vp); + + return error; + +bad: + vrele(ndroot.ni_vp); + vrele(nd.ni_vp); + free(buf, M_TEMP); + return error; +} + +int +ia32_open(struct thread *td, struct ia32_open_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return open(td, (struct open_args *) uap); +} + +int +ia32_wait4(struct thread *td, struct ia32_wait4_args *uap) +{ + int error; + caddr_t sg; + struct rusage32 *rusage32, ru32; + struct rusage *rusage = NULL, ru; + + rusage32 = SCARG(uap, rusage); + if (rusage32) { + sg = stackgap_init(); + rusage = stackgap_alloc(&sg, sizeof(struct rusage)); + SCARG(uap, rusage) = (struct rusage32 *)rusage; + } + error = wait4(td, (struct wait_args *)uap); + if (error) + return (error); + if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) { + TV_CP(ru, ru32, ru_utime); + TV_CP(ru, ru32, ru_stime); + CP(ru, ru32, ru_maxrss); + CP(ru, ru32, ru_ixrss); + CP(ru, ru32, ru_idrss); + CP(ru, ru32, ru_isrss); + CP(ru, ru32, ru_minflt); + CP(ru, ru32, ru_majflt); + CP(ru, ru32, ru_nswap); + CP(ru, ru32, ru_inblock); + CP(ru, ru32, ru_oublock); + CP(ru, ru32, ru_msgsnd); + CP(ru, ru32, ru_msgrcv); + CP(ru, ru32, ru_nsignals); + CP(ru, ru32, ru_nvcsw); + CP(ru, ru32, ru_nivcsw); + error = copyout(&ru32, rusage32, sizeof(ru32)); + } + return (error); +} + +static void +copy_statfs(struct statfs *in, struct statfs32 *out) +{ + CP(*in, *out, f_bsize); + CP(*in, *out, f_iosize); + CP(*in, *out, f_blocks); + CP(*in, *out, f_bfree); + CP(*in, *out, f_bavail); + CP(*in, *out, f_files); + CP(*in, *out, f_ffree); + CP(*in, *out, f_fsid); + CP(*in, *out, f_owner); + CP(*in, *out, f_type); + CP(*in, *out, f_flags); + CP(*in, *out, f_flags); + CP(*in, *out, f_syncwrites); + CP(*in, *out, f_asyncwrites); + bcopy(in->f_fstypename, + out->f_fstypename, MFSNAMELEN); + bcopy(in->f_mntonname, + out->f_mntonname, MNAMELEN); + CP(*in, *out, f_syncreads); + CP(*in, *out, f_asyncreads); + bcopy(in->f_mntfromname, + out->f_mntfromname, MNAMELEN); +} + +int +ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *sp32, stat32; + struct statfs *sp = NULL, stat; + int maxcount, count, i; + + sp32 = SCARG(uap, buf); + maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32); + + if (sp32) { + sg = stackgap_init(); + sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); + SCARG(uap, buf) = (struct statfs32 *)sp; + } + error = getfsstat(td, (struct getfsstat_args *) uap); + if (sp32 && !error) { + count = td->td_retval[0]; + for (i = 0; i < count; i++) { + error = copyin(&sp[i], &stat, sizeof(stat)); + if (error) + return (error); + copy_statfs(&stat, &stat32); + error = copyout(&stat32, &sp32[i], sizeof(stat32)); + if (error) + return (error); + } + } + return (error); +} + +int +ia32_access(struct thread *td, struct ia32_access_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return access(td, (struct access_args *)uap); +} + +int +ia32_chflags(struct thread *td, struct ia32_chflags_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return chflags(td, (struct chflags_args *)uap); +} + +struct sigaltstack32 { + u_int32_t ss_sp; + u_int32_t ss_size; + int ss_flags; +}; + +int +ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap) +{ + int error; + caddr_t sg; + struct sigaltstack32 *p32, *op32, s32; + struct sigaltstack *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, ss); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + SCARG(uap, ss) = (struct sigaltstack32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + PTRIN_CP(s32, s, ss_sp); + CP(s32, s, ss_size); + CP(s32, s, ss_flags); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oss); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + SCARG(uap, oss) = (struct sigaltstack32 *)op; + } + error = sigaltstack(td, (struct sigaltstack_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + PTROUT_CP(s, s32, ss_sp); + CP(s, s32, ss_size); + CP(s, s32, ss_flags); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_execve(struct thread *td, struct ia32_execve_args *uap) +{ + int error; + caddr_t sg; + struct execve_args ap; + u_int32_t *p32, arg; + char **p; + int count; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, fname)); + SCARG(&ap, fname) = SCARG(uap, fname); + + if (SCARG(uap, argv)) { + count = 0; + p32 = SCARG(uap, argv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + count++; + } while (arg != 0); + p = stackgap_alloc(&sg, count * sizeof(char *)); + SCARG(&ap, argv) = p; + p32 = SCARG(uap, argv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + *p++ = PTRIN(arg); + } while (arg != 0); + } + if (SCARG(uap, envv)) { + count = 0; + p32 = SCARG(uap, envv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + count++; + } while (arg != 0); + p = stackgap_alloc(&sg, count * sizeof(char *)); + SCARG(&ap, envv) = p; + p32 = SCARG(uap, envv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + *p++ = PTRIN(arg); + } while (arg != 0); + } + + return execve(td, &ap); +} + +static int +ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, + int prot, int fd, off_t pos) +{ + vm_map_t map; + vm_map_entry_t entry; + int rv; + + map = &td->td_proc->p_vmspace->vm_map; + if (fd != -1) + prot |= VM_PROT_WRITE; + + if (vm_map_lookup_entry(map, start, &entry)) { + if ((entry->protection & prot) != prot) { + rv = vm_map_protect(map, + trunc_page(start), + round_page(end), + entry->protection | prot, + FALSE); + if (rv != KERN_SUCCESS) + return (EINVAL); + } + } else { + vm_offset_t addr = trunc_page(start); + rv = vm_map_find(map, 0, 0, + &addr, PAGE_SIZE, FALSE, prot, + VM_PROT_ALL, 0); + if (rv != KERN_SUCCESS) + return (EINVAL); + } + + if (fd != -1) { + struct pread_args r; + SCARG(&r, fd) = fd; + SCARG(&r, buf) = (void *) start; + SCARG(&r, nbyte) = end - start; + SCARG(&r, offset) = pos; + return (pread(td, &r)); + } else { + while (start < end) { + subyte((void *) start, 0); + start++; + } + return (0); + } +} + +int +ia32_mmap(struct thread *td, struct ia32_mmap_args *uap) +{ + struct mmap_args ap; + vm_offset_t addr = (vm_offset_t) SCARG(uap, addr); + vm_size_t len = SCARG(uap, len); + int prot = SCARG(uap, prot); + int flags = SCARG(uap, flags); + int fd = SCARG(uap, fd); + off_t pos = (SCARG(uap, poslo) + | ((off_t)SCARG(uap, poshi) << 32)); + vm_size_t pageoff; + int error; + + /* + * Attempt to handle page size hassles. + */ + pageoff = (pos & PAGE_MASK); + if (flags & MAP_FIXED) { + vm_offset_t start, end; + start = addr; + end = addr + len; + + if (start != trunc_page(start)) { + error = ia32_mmap_partial(td, start, round_page(start), + prot, fd, pos); + if (fd != -1) + pos += round_page(start) - start; + start = round_page(start); + } + if (end != round_page(end)) { + vm_offset_t t = trunc_page(end); + error = ia32_mmap_partial(td, t, end, + prot, fd, + pos + t - start); + end = trunc_page(end); + } + if (end > start && fd != -1 && (pos & PAGE_MASK)) { + /* + * We can't map this region at all. The specified + * address doesn't have the same alignment as the file + * position. Fake the mapping by simply reading the + * entire region into memory. First we need to make + * sure the region exists. + */ + vm_map_t map; + struct pread_args r; + int rv; + + prot |= VM_PROT_WRITE; + map = &td->td_proc->p_vmspace->vm_map; + rv = vm_map_remove(map, start, end); + if (rv != KERN_SUCCESS) + return (EINVAL); + rv = vm_map_find(map, 0, 0, + &start, end - start, FALSE, + prot, VM_PROT_ALL, 0); + if (rv != KERN_SUCCESS) + return (EINVAL); + SCARG(&r, fd) = fd; + SCARG(&r, buf) = (void *) start; + SCARG(&r, nbyte) = end - start; + SCARG(&r, offset) = pos; + error = pread(td, &r); + if (error) + return (error); + + td->td_retval[0] = addr; + return (0); + } + if (end == start) { + /* + * After dealing with the ragged ends, there + * might be none left. + */ + td->td_retval[0] = addr; + return (0); + } + addr = start; + len = end - start; + } + + SCARG(&ap, addr) = (void *) addr; + SCARG(&ap, len) = len; + SCARG(&ap, prot) = prot; + SCARG(&ap, flags) = flags; + SCARG(&ap, fd) = fd; + SCARG(&ap, pos) = pos; + + return (mmap(td, &ap)); +} + +struct itimerval32 { + struct timeval32 it_interval; + struct timeval32 it_value; +}; + +int +ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap) +{ + int error; + caddr_t sg; + struct itimerval32 *p32, *op32, s32; + struct itimerval *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, itv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct itimerval)); + SCARG(uap, itv) = (struct itimerval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + TV_CP(s32, s, it_interval); + TV_CP(s32, s, it_value); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oitv); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct itimerval)); + SCARG(uap, oitv) = (struct itimerval32 *)op; + } + error = setitimer(td, (struct setitimer_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + TV_CP(s, s32, it_interval); + TV_CP(s, s32, it_value); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_select(struct thread *td, struct ia32_select_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tv) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + /* + * XXX big-endian needs to convert the fd_sets too. + */ + return (select(td, (struct select_args *) uap)); +} + +int +ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tp); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tp) = (struct timeval32 *)p; + } + error = gettimeofday(td, (struct gettimeofday_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + CP(s, s32, tv_sec); + CP(s, s32, tv_usec); + error = copyout(&s32, p32, sizeof(s32)); + if (error) + return (error); + } + return (error); +} + +int +ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap) +{ + int error; + caddr_t sg; + struct rusage32 *p32, s32; + struct rusage *p = NULL, s; + + p32 = SCARG(uap, rusage); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct rusage)); + SCARG(uap, rusage) = (struct rusage32 *)p; + } + error = getrusage(td, (struct getrusage_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + TV_CP(s, s32, ru_utime); + TV_CP(s, s32, ru_stime); + CP(s, s32, ru_maxrss); + CP(s, s32, ru_ixrss); + CP(s, s32, ru_idrss); + CP(s, s32, ru_isrss); + CP(s, s32, ru_minflt); + CP(s, s32, ru_majflt); + CP(s, s32, ru_nswap); + CP(s, s32, ru_inblock); + CP(s, s32, ru_oublock); + CP(s, s32, ru_msgsnd); + CP(s, s32, ru_msgrcv); + CP(s, s32, ru_nsignals); + CP(s, s32, ru_nvcsw); + CP(s, s32, ru_nivcsw); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +struct iovec32 { + u_int32_t iov_base; + int iov_len; +}; +#define STACKGAPLEN 400 + +int +ia32_readv(struct thread *td, struct ia32_readv_args *uap) +{ + int error, osize, nsize, i; + caddr_t sg; + struct readv_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ a; + struct iovec32 *oio; + struct iovec *nio; + + sg = stackgap_init(); + + if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec))) + return (EINVAL); + + osize = SCARG(uap, iovcnt) * sizeof (struct iovec32); + nsize = SCARG(uap, iovcnt) * sizeof (struct iovec); + + oio = malloc(osize, M_TEMP, M_WAITOK); + nio = malloc(nsize, M_TEMP, M_WAITOK); + + error = 0; + if ((error = copyin(SCARG(uap, iovp), oio, osize))) + goto punt; + for (i = 0; i < SCARG(uap, iovcnt); i++) { + nio[i].iov_base = PTRIN(oio[i].iov_base); + nio[i].iov_len = oio[i].iov_len; + } + + SCARG(&a, fd) = SCARG(uap, fd); + SCARG(&a, iovp) = stackgap_alloc(&sg, nsize); + SCARG(&a, iovcnt) = SCARG(uap, iovcnt); + + if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize))) + goto punt; + error = readv(td, &a); + +punt: + free(oio, M_TEMP); + free(nio, M_TEMP); + return (error); +} + +int +ia32_writev(struct thread *td, struct ia32_writev_args *uap) +{ + int error, i, nsize, osize; + caddr_t sg; + struct writev_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ a; + struct iovec32 *oio; + struct iovec *nio; + + sg = stackgap_init(); + + if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec))) + return (EINVAL); + + osize = SCARG(uap, iovcnt) * sizeof (struct iovec32); + nsize = SCARG(uap, iovcnt) * sizeof (struct iovec); + + oio = malloc(osize, M_TEMP, M_WAITOK); + nio = malloc(nsize, M_TEMP, M_WAITOK); + + error = 0; + if ((error = copyin(SCARG(uap, iovp), oio, osize))) + goto punt; + for (i = 0; i < SCARG(uap, iovcnt); i++) { + nio[i].iov_base = PTRIN(oio[i].iov_base); + nio[i].iov_len = oio[i].iov_len; + } + + SCARG(&a, fd) = SCARG(uap, fd); + SCARG(&a, iovp) = stackgap_alloc(&sg, nsize); + SCARG(&a, iovcnt) = SCARG(uap, iovcnt); + + if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize))) + goto punt; + error = writev(td, &a); + +punt: + free(oio, M_TEMP); + free(nio, M_TEMP); + return (error); +} + +int +ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tv) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + return (settimeofday(td, (struct settimeofday_args *) uap)); +} + +int +ia32_utimes(struct thread *td, struct ia32_utimes_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32[2]; + struct timeval *p = NULL, s[2]; + + p32 = SCARG(uap, tptr); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); + SCARG(uap, tptr) = (struct timeval32 *)p; + error = copyin(p32, s32, sizeof(s32)); + if (error) + return (error); + CP(s32[0], s[0], tv_sec); + CP(s32[0], s[0], tv_usec); + CP(s32[1], s[1], tv_sec); + CP(s32[1], s[1], tv_usec); + error = copyout(s, p, sizeof(s)); + if (error) + return (error); + } + return (utimes(td, (struct utimes_args *) uap)); +} + +int +ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, *op32, s32; + struct timeval *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, delta); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, delta) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, olddelta); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, olddelta) = (struct timeval32 *)op; + } + error = utimes(td, (struct utimes_args *) uap); + if (error) + return error; + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + CP(s, s32, tv_sec); + CP(s, s32, tv_usec); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_statfs(struct thread *td, struct ia32_statfs_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *p32, s32; + struct statfs *p = NULL, s; + + p32 = SCARG(uap, buf); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct statfs)); + SCARG(uap, buf) = (struct statfs32 *)p; + } + error = statfs(td, (struct statfs_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_statfs(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *p32, s32; + struct statfs *p = NULL, s; + + p32 = SCARG(uap, buf); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct statfs)); + SCARG(uap, buf) = (struct statfs32 *)p; + } + error = fstatfs(td, (struct fstatfs_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_statfs(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_semsys(struct thread *td, struct ia32_semsys_args *uap) +{ + /* + * Vector through to semsys if it is loaded. + */ + return sysent[169].sy_call(td, uap); +} + +int +ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap) +{ + /* + * Vector through to msgsys if it is loaded. + */ + return sysent[170].sy_call(td, uap); +} + +int +ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap) +{ + /* + * Vector through to shmsys if it is loaded. + */ + return sysent[171].sy_call(td, uap); +} + +int +ia32_pread(struct thread *td, struct ia32_pread_args *uap) +{ + struct pread_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, buf) = SCARG(uap, buf); + SCARG(&ap, nbyte) = SCARG(uap, nbyte); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + return (pread(td, &ap)); +} + +int +ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap) +{ + struct pwrite_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, buf) = SCARG(uap, buf); + SCARG(&ap, nbyte) = SCARG(uap, nbyte); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + return (pwrite(td, &ap)); +} + +int +ia32_lseek(struct thread *td, struct ia32_lseek_args *uap) +{ + int error; + struct lseek_args ap; + off_t pos; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + SCARG(&ap, whence) = SCARG(uap, whence); + error = lseek(td, &ap); + /* Expand the quad return into two parts for eax and edx */ + pos = *(off_t *)(td->td_retval); + td->td_retval[0] = pos & 0xffffffff; /* %eax */ + td->td_retval[1] = pos >> 32; /* %edx */ + return error; +} + +int +ia32_truncate(struct thread *td, struct ia32_truncate_args *uap) +{ + struct truncate_args ap; + + SCARG(&ap, path) = SCARG(uap, path); + SCARG(&ap, length) = (SCARG(uap, lengthlo) + | ((off_t)SCARG(uap, lengthhi) << 32)); + return (truncate(td, &ap)); +} + +int +ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap) +{ + struct ftruncate_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, length) = (SCARG(uap, lengthlo) + | ((off_t)SCARG(uap, lengthhi) << 32)); + return (ftruncate(td, &ap)); +} + +int +ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap) +{ + struct sendfile_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, s) = SCARG(uap, s); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + SCARG(&ap, nbytes) = SCARG(uap, nbytes); /* XXX check */ + SCARG(&ap, hdtr) = SCARG(uap, hdtr); /* XXX check */ + SCARG(&ap, sbytes) = SCARG(uap, sbytes); /* XXX FIXME!! */ + SCARG(&ap, flags) = SCARG(uap, flags); + return (sendfile(td, &ap)); +} + +struct stat32 { + udev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + udev_t st_rdev; + struct timespec32 st_atimespec; + struct timespec32 st_mtimespec; + struct timespec32 st_ctimespec; + off_t st_size; + int64_t st_blocks; + u_int32_t st_blksize; + u_int32_t st_flags; + u_int32_t st_gen; +}; + +static void +copy_stat( struct stat *in, struct stat32 *out) +{ + CP(*in, *out, st_dev); + CP(*in, *out, st_ino); + CP(*in, *out, st_mode); + CP(*in, *out, st_nlink); + CP(*in, *out, st_uid); + CP(*in, *out, st_gid); + CP(*in, *out, st_rdev); + TS_CP(*in, *out, st_atimespec); + TS_CP(*in, *out, st_mtimespec); + TS_CP(*in, *out, st_ctimespec); + CP(*in, *out, st_size); + CP(*in, *out, st_blocks); + CP(*in, *out, st_blksize); + CP(*in, *out, st_flags); + CP(*in, *out, st_gen); +} + +int +ia32_stat(struct thread *td, struct ia32_stat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = stat(td, (struct stat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_fstat(struct thread *td, struct ia32_fstat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = fstat(td, (struct fstat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_lstat(struct thread *td, struct ia32_lstat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = lstat(td, (struct lstat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +/* + * MPSAFE + */ +int +ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap) +{ + int error, name[CTL_MAXNAME]; + size_t j, oldlen; + + if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) + return (EINVAL); + + error = copyin(uap->name, &name, uap->namelen * sizeof(int)); + if (error) + return (error); + + mtx_lock(&Giant); + + if (uap->oldlenp) + oldlen = fuword32(uap->oldlenp); + else + oldlen = 0; + error = userland_sysctl(td, name, uap->namelen, + uap->old, &oldlen, 1, + uap->new, uap->newlen, &j); + if (error && error != ENOMEM) + goto done2; + if (uap->oldlenp) { + suword32(uap->oldlenp, j); + } +done2: + mtx_unlock(&Giant); + return (error); +} + +struct sigaction32 { + u_int32_t sa_u; + int sa_flags; + sigset_t sa_mask; +}; + +int +ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap) +{ + int error; + caddr_t sg; + struct sigaction32 *p32, *op32, s32; + struct sigaction *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, act); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(uap, act) = (struct sigaction32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + s.sa_handler = PTRIN(s32.sa_u); + CP(s32, s, sa_flags); + CP(s32, s, sa_mask); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oact); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(uap, oact) = (struct sigaction32 *)op; + } + error = sigaction(td, (struct sigaction_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + s32.sa_u = PTROUT(s.sa_handler); + CP(s, s32, sa_flags); + CP(s, s32, sa_mask); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +#if 0 + +int +ia32_xxx(struct thread *td, struct ia32_xxx_args *uap) +{ + int error; + caddr_t sg; + struct yyy32 *p32, s32; + struct yyy *p = NULL, s; + + p32 = SCARG(uap, zzz); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct yyy)); + SCARG(uap, zzz) = (struct yyy32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + /* translate in */ + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + error = xxx(td, (struct xxx_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + /* translate out */ + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +#endif Property changes on: head/sys/ia64/ia32/ia32_misc.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/ia64/ia32/ia32_signal.c =================================================================== --- head/sys/ia64/ia32/ia32_signal.c (nonexistent) +++ head/sys/ia64/ia32/ia32_signal.c (revision 100384) @@ -0,0 +1,365 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#define __ELF_WORD_SIZE 32 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static register_t *ia32_copyout_strings(struct image_params *imgp); +static void ia32_setregs(struct thread *td, u_long entry, u_long stack, + u_long ps_strings); + +extern struct sysent ia32_sysent[]; + +static char ia32_sigcode[] = { + 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */ + 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */ + 0x50, /* pushl %eax */ + 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */ + 0x75, 0x03, /* jne 9f */ + 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */ + 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */ + 0x50, /* pushl %eax */ + 0xcd, 0x80, /* int $0x80 */ + 0xeb, 0xfe, /* 0: jmp 0b */ + 0, 0, 0, 0 +}; +static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3; + +struct sysentvec ia32_freebsd_sysvec = { + SYS_MAXSYSCALL, + ia32_sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + ia32_sigcode, + &ia32_szsigcode, + 0, + "FreeBSD ELF", + elf32_coredump, + NULL, + MINSIGSTKSZ, + 4096, + IA32_USRSTACK, + IA32_USRSTACK, + ia32_copyout_strings, + ia32_setregs +}; + +static Elf32_Brandinfo ia32_brand_info = { + ELFOSABI_FREEBSD, + EM_386, + "FreeBSD", + "/compat/ia32", + "/usr/libexec/ld-elf.so.1", + &ia32_freebsd_sysvec + }; + +SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &ia32_brand_info); + +static register_t * +ia32_copyout_strings(struct image_params *imgp) +{ + int argc, envc; + u_int32_t *vectp; + char *stringp, *destp; + u_int32_t *stack_base; + struct ia32_ps_strings *arginfo; + int szsigcode; + + /* + * Calculate string base and vector table pointers. + * Also deal with signal trampoline code for this exec type. + */ + arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS; + szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); + destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - + roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + + /* + * install sigcode + */ + if (szsigcode) + copyout(imgp->proc->p_sysent->sv_sigcode, + ((caddr_t)arginfo - szsigcode), szsigcode); + + /* + * If we have a valid auxargs ptr, prepare some room + * on the stack. + */ + if (imgp->auxargs) { + /* + * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for + * lower compatibility. + */ + imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size + : (AT_COUNT * 2); + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets,and imgp->auxarg_size is room + * for argument of Runtime loader. + */ + vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + + imgp->auxarg_size) * sizeof(u_int32_t)); + + } else + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets + */ + vectp = (u_int32_t *) + (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); + + /* + * vectp also becomes our initial stack base + */ + stack_base = vectp; + + stringp = imgp->stringbase; + argc = imgp->argc; + envc = imgp->envc; + + /* + * Copy out strings - arguments and environment. + */ + copyout(stringp, destp, ARG_MAX - imgp->stringspace); + + /* + * Fill in "ps_strings" struct for ps, w, etc. + */ + suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nargvstr, argc); + + /* + * Fill in argument portion of vector table. + */ + for (; argc > 0; --argc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* a null vector table pointer separates the argp's from the envp's */ + suword32(vectp++, 0); + + suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nenvstr, envc); + + /* + * Fill in environment portion of vector table. + */ + for (; envc > 0; --envc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* end of vector table is a null pointer */ + suword32(vectp, 0); + + return ((register_t *)stack_base); +} + +static void +ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +{ + struct trapframe *frame = td->td_frame; + vm_offset_t gdt, ldt; + u_int64_t codesel, datasel, ldtsel; + u_int64_t codeseg, dataseg, gdtseg, ldtseg; + struct segment_descriptor desc; + struct vmspace *vmspace = td->td_proc->p_vmspace; + + /* + * Make sure that we restore the entire trapframe after an + * execve. + */ + frame->tf_flags &= ~FRAME_SYSCALL; + + bzero(frame->tf_r, sizeof(frame->tf_r)); + bzero(frame->tf_f, sizeof(frame->tf_f)); + + frame->tf_cr_iip = entry; + frame->tf_cr_ipsr = (IA64_PSR_IC + | IA64_PSR_I + | IA64_PSR_IT + | IA64_PSR_DT + | IA64_PSR_RT + | IA64_PSR_DFH + | IA64_PSR_IS + | IA64_PSR_BN + | IA64_PSR_CPL_USER); + frame->tf_r[FRAME_R12] = stack; + + codesel = LSEL(LUCODE_SEL, SEL_UPL); + datasel = LSEL(LUDATA_SEL, SEL_UPL); + ldtsel = GSEL(GLDT_SEL, SEL_UPL); + +#if 1 + frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32) + | (datasel << 16) | datasel; + frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel; +#else + frame->tf_r[FRAME_R16] = datasel; + frame->tf_r[FRAME_R17] = codesel; + frame->tf_r[FRAME_R18] = datasel; + frame->tf_r[FRAME_R19] = datasel; + frame->tf_r[FRAME_R20] = datasel; + frame->tf_r[FRAME_R21] = datasel; + frame->tf_r[FRAME_R22] = ldtsel; +#endif + + /* + * Build the GDT and LDT. + */ + gdt = IA32_USRSTACK; + vm_map_find(&vmspace->vm_map, 0, 0, + &gdt, PAGE_SIZE, 0, + VM_PROT_ALL, VM_PROT_ALL, 0); + ldt = gdt + 4096; + + desc.sd_lolimit = 8*NLDT-1; + desc.sd_lobase = ldt & 0xffffff; + desc.sd_type = SDT_SYSLDT; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = 0; + desc.sd_def32 = 0; + desc.sd_gran = 0; + desc.sd_hibase = ldt >> 24; + copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc)); + + desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff; + desc.sd_lobase = 0; + desc.sd_type = SDT_MEMERA; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16; + desc.sd_def32 = 1; + desc.sd_gran = 1; + desc.sd_hibase = 0; + copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc)); + desc.sd_type = SDT_MEMRWA; + copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc)); + + codeseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMERA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + dataseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMRWA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + ia64_set_csd(codeseg); + ia64_set_ssd(dataseg); + frame->tf_r[FRAME_R24] = dataseg; /* ESD */ + frame->tf_r[FRAME_R27] = dataseg; /* DSD */ + frame->tf_r[FRAME_R28] = dataseg; /* FSD */ + frame->tf_r[FRAME_R29] = dataseg; /* GSD */ + + gdtseg = gdt /* base */ + + ((8L*NGDT - 1) << 32) /* limit */ + + ((long)SDT_SYSNULL << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + ldtseg = ldt /* base */ + + ((8L*NLDT - 1) << 32) /* limit */ + + ((long)SDT_SYSLDT << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */ + frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */ + + ia64_set_eflag(PSL_USER); + + /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ + frame->tf_r[FRAME_R11] = IA32_PS_STRINGS; + + /* + * XXX - Linux emulator + * Make sure sure edx is 0x0 on entry. Linux binaries depend + * on it. + */ + td->td_retval[1] = 0; +} Property changes on: head/sys/ia64/ia32/ia32_signal.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/ia64/ia32/ia32_sysvec.c =================================================================== --- head/sys/ia64/ia32/ia32_sysvec.c (nonexistent) +++ head/sys/ia64/ia32/ia32_sysvec.c (revision 100384) @@ -0,0 +1,365 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#define __ELF_WORD_SIZE 32 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static register_t *ia32_copyout_strings(struct image_params *imgp); +static void ia32_setregs(struct thread *td, u_long entry, u_long stack, + u_long ps_strings); + +extern struct sysent ia32_sysent[]; + +static char ia32_sigcode[] = { + 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */ + 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */ + 0x50, /* pushl %eax */ + 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */ + 0x75, 0x03, /* jne 9f */ + 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */ + 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */ + 0x50, /* pushl %eax */ + 0xcd, 0x80, /* int $0x80 */ + 0xeb, 0xfe, /* 0: jmp 0b */ + 0, 0, 0, 0 +}; +static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3; + +struct sysentvec ia32_freebsd_sysvec = { + SYS_MAXSYSCALL, + ia32_sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + ia32_sigcode, + &ia32_szsigcode, + 0, + "FreeBSD ELF", + elf32_coredump, + NULL, + MINSIGSTKSZ, + 4096, + IA32_USRSTACK, + IA32_USRSTACK, + ia32_copyout_strings, + ia32_setregs +}; + +static Elf32_Brandinfo ia32_brand_info = { + ELFOSABI_FREEBSD, + EM_386, + "FreeBSD", + "/compat/ia32", + "/usr/libexec/ld-elf.so.1", + &ia32_freebsd_sysvec + }; + +SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &ia32_brand_info); + +static register_t * +ia32_copyout_strings(struct image_params *imgp) +{ + int argc, envc; + u_int32_t *vectp; + char *stringp, *destp; + u_int32_t *stack_base; + struct ia32_ps_strings *arginfo; + int szsigcode; + + /* + * Calculate string base and vector table pointers. + * Also deal with signal trampoline code for this exec type. + */ + arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS; + szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); + destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - + roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + + /* + * install sigcode + */ + if (szsigcode) + copyout(imgp->proc->p_sysent->sv_sigcode, + ((caddr_t)arginfo - szsigcode), szsigcode); + + /* + * If we have a valid auxargs ptr, prepare some room + * on the stack. + */ + if (imgp->auxargs) { + /* + * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for + * lower compatibility. + */ + imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size + : (AT_COUNT * 2); + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets,and imgp->auxarg_size is room + * for argument of Runtime loader. + */ + vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + + imgp->auxarg_size) * sizeof(u_int32_t)); + + } else + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets + */ + vectp = (u_int32_t *) + (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); + + /* + * vectp also becomes our initial stack base + */ + stack_base = vectp; + + stringp = imgp->stringbase; + argc = imgp->argc; + envc = imgp->envc; + + /* + * Copy out strings - arguments and environment. + */ + copyout(stringp, destp, ARG_MAX - imgp->stringspace); + + /* + * Fill in "ps_strings" struct for ps, w, etc. + */ + suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nargvstr, argc); + + /* + * Fill in argument portion of vector table. + */ + for (; argc > 0; --argc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* a null vector table pointer separates the argp's from the envp's */ + suword32(vectp++, 0); + + suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nenvstr, envc); + + /* + * Fill in environment portion of vector table. + */ + for (; envc > 0; --envc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* end of vector table is a null pointer */ + suword32(vectp, 0); + + return ((register_t *)stack_base); +} + +static void +ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +{ + struct trapframe *frame = td->td_frame; + vm_offset_t gdt, ldt; + u_int64_t codesel, datasel, ldtsel; + u_int64_t codeseg, dataseg, gdtseg, ldtseg; + struct segment_descriptor desc; + struct vmspace *vmspace = td->td_proc->p_vmspace; + + /* + * Make sure that we restore the entire trapframe after an + * execve. + */ + frame->tf_flags &= ~FRAME_SYSCALL; + + bzero(frame->tf_r, sizeof(frame->tf_r)); + bzero(frame->tf_f, sizeof(frame->tf_f)); + + frame->tf_cr_iip = entry; + frame->tf_cr_ipsr = (IA64_PSR_IC + | IA64_PSR_I + | IA64_PSR_IT + | IA64_PSR_DT + | IA64_PSR_RT + | IA64_PSR_DFH + | IA64_PSR_IS + | IA64_PSR_BN + | IA64_PSR_CPL_USER); + frame->tf_r[FRAME_R12] = stack; + + codesel = LSEL(LUCODE_SEL, SEL_UPL); + datasel = LSEL(LUDATA_SEL, SEL_UPL); + ldtsel = GSEL(GLDT_SEL, SEL_UPL); + +#if 1 + frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32) + | (datasel << 16) | datasel; + frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel; +#else + frame->tf_r[FRAME_R16] = datasel; + frame->tf_r[FRAME_R17] = codesel; + frame->tf_r[FRAME_R18] = datasel; + frame->tf_r[FRAME_R19] = datasel; + frame->tf_r[FRAME_R20] = datasel; + frame->tf_r[FRAME_R21] = datasel; + frame->tf_r[FRAME_R22] = ldtsel; +#endif + + /* + * Build the GDT and LDT. + */ + gdt = IA32_USRSTACK; + vm_map_find(&vmspace->vm_map, 0, 0, + &gdt, PAGE_SIZE, 0, + VM_PROT_ALL, VM_PROT_ALL, 0); + ldt = gdt + 4096; + + desc.sd_lolimit = 8*NLDT-1; + desc.sd_lobase = ldt & 0xffffff; + desc.sd_type = SDT_SYSLDT; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = 0; + desc.sd_def32 = 0; + desc.sd_gran = 0; + desc.sd_hibase = ldt >> 24; + copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc)); + + desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff; + desc.sd_lobase = 0; + desc.sd_type = SDT_MEMERA; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16; + desc.sd_def32 = 1; + desc.sd_gran = 1; + desc.sd_hibase = 0; + copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc)); + desc.sd_type = SDT_MEMRWA; + copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc)); + + codeseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMERA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + dataseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMRWA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + ia64_set_csd(codeseg); + ia64_set_ssd(dataseg); + frame->tf_r[FRAME_R24] = dataseg; /* ESD */ + frame->tf_r[FRAME_R27] = dataseg; /* DSD */ + frame->tf_r[FRAME_R28] = dataseg; /* FSD */ + frame->tf_r[FRAME_R29] = dataseg; /* GSD */ + + gdtseg = gdt /* base */ + + ((8L*NGDT - 1) << 32) /* limit */ + + ((long)SDT_SYSNULL << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + ldtseg = ldt /* base */ + + ((8L*NLDT - 1) << 32) /* limit */ + + ((long)SDT_SYSLDT << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */ + frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */ + + ia64_set_eflag(PSL_USER); + + /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ + frame->tf_r[FRAME_R11] = IA32_PS_STRINGS; + + /* + * XXX - Linux emulator + * Make sure sure edx is 0x0 on entry. Linux binaries depend + * on it. + */ + td->td_retval[1] = 0; +} Property changes on: head/sys/ia64/ia32/ia32_sysvec.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/ia64/ia32/ia32_util.h =================================================================== --- head/sys/ia64/ia32/ia32_util.h (nonexistent) +++ head/sys/ia64/ia32/ia32_util.h (revision 100384) @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 1998-1999 Andrew Gallatin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + + +#include +#include +#include + + +#ifndef SCARG +#define SCARG(p, x) (p)->x +#endif + +struct ia32_ps_strings { + u_int32_t ps_argvstr; /* first of 0 or more argument strings */ + int ps_nargvstr; /* the number of argument strings */ + u_int32_t ps_envstr; /* first of 0 or more environment strings */ + int ps_nenvstr; /* the number of environment strings */ +}; + +#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE) +#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings)) + +static __inline caddr_t stackgap_init(void); +static __inline void *stackgap_alloc(caddr_t *, size_t); + +static __inline caddr_t +stackgap_init() +{ +#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) + return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE); +#undef szsigcode +} + +static __inline void * +stackgap_alloc(sgp, sz) + caddr_t *sgp; + size_t sz; +{ + void *p; + + p = (void *) *sgp; + *sgp += ALIGN(sz); + return p; +} + + +extern const char ia32_emul_path[]; +int ia32_emul_find(struct thread *, caddr_t *, const char *, char *, + char **, int); + +#define CHECKALT(p, sgp, path, i) \ + do { \ + int _error; \ + \ + _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \ + &path, i); \ + if (_error == EFAULT) \ + return (_error); \ + } while (0) + +#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0) +#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1) Property changes on: head/sys/ia64/ia32/ia32_util.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/ia64/ia32/syscalls.master =================================================================== --- head/sys/ia64/ia32/syscalls.master (revision 100383) +++ head/sys/ia64/ia32/syscalls.master (revision 100384) @@ -1,562 +1,563 @@ $FreeBSD$ ; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94 ; from: src/sys/kern/syscalls.master 1.107 ; ; System call name/number master file. ; Processed to created init_sysent.c, syscalls.c and syscall.h. ; Columns: number [M]type nargs namespc name alt{name,tag,rtyp}/comments ; number system call number, must be in order ; type one of [M]STD, [M]OBSOL, [M]UNIMPL, [M]COMPAT, [M]CPT_NOA, ; [M]LIBCOMPAT, [M]NODEF, [M]NOARGS, [M]NOPROTO, [M]NOIMPL, ; [M]NOSTD ; namespc one of POSIX, BSD, NOHIDE ; name psuedo-prototype of syscall routine ; If one of the following alts is different, then all appear: ; altname name of system call if different ; alttag name of args struct tag if different from [o]`name'"_args" ; altrtyp return type if not int (bogus - syscalls always return int) ; for UNIMPL/OBSOL, name continues with comments ; types: ; [M] e.g. like MSTD -- means the system call is MP-safe. If no ; M prefix is used, the syscall wrapper will obtain the Giant ; lock for the syscall. ; STD always included ; COMPAT included on COMPAT #ifdef ; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h ; OBSOL obsolete, not included in system, only specifies name ; UNIMPL not implemented, placeholder only ; NOSTD implemented but as a lkm that can be statically ; compiled in sysent entry will be filled with lkmsys ; so the SYSCALL_MODULE macro works ; #ifdef's, etc. may be included, and are copied to the output files. #include #include #include +#include +#include +#include ; Reserved/unimplemented system calls in the range 0-150 inclusive ; are reserved for use in future Berkeley releases. ; Additional system calls implemented in vendor and other ; redistributions should be placed in the reserved range at the end ; of the current calls. -0 STD NOHIDE { int nosys(void); } syscall nosys_args int -1 MSTD NOHIDE { void sys_exit(int rval); } exit sys_exit_args void -2 MSTD POSIX { int fork(void); } -3 MSTD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); } -4 MSTD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); } -5 STD POSIX { int open(char *path, int flags, int mode); } +0 MNOPROTO NOHIDE { int nosys(void); } syscall nosys_args int +1 MNOPROTO NOHIDE { void sys_exit(int rval); } exit sys_exit_args void +2 MNOPROTO POSIX { int fork(void); } +3 MNOPROTO POSIX { ssize_t read(int fd, void *buf, size_t nbyte); } +4 MNOPROTO POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); } +5 STD POSIX { int ia32_open(char *path, int flags, int mode); } ; XXX should be { int open(const char *path, int flags, ...); } ; but we're not ready for `const' or varargs. ; XXX man page says `mode_t mode'. -6 MSTD POSIX { int close(int fd); } -7 MSTD BSD { int wait4(int pid, int *status, int options, \ - struct rusage *rusage); } wait4 wait_args int -8 COMPAT BSD { int creat(char *path, int mode); } -9 STD POSIX { int link(char *path, char *link); } -10 STD POSIX { int unlink(char *path); } +6 MNOPROTO POSIX { int close(int fd); } +7 MSTD BSD { int ia32_wait4(int pid, int *status, int options, \ + struct rusage32 *rusage); } +8 OBSOL BSD old creat +9 NOPROTO POSIX { int link(char *path, char *link); } +10 NOPROTO POSIX { int unlink(char *path); } 11 OBSOL NOHIDE execv -12 STD POSIX { int chdir(char *path); } -13 STD BSD { int fchdir(int fd); } -14 STD POSIX { int mknod(char *path, int mode, int dev); } -15 STD POSIX { int chmod(char *path, int mode); } -16 STD POSIX { int chown(char *path, int uid, int gid); } -17 MSTD BSD { int obreak(char *nsize); } break obreak_args int -18 STD BSD { int getfsstat(struct statfs *buf, long bufsize, \ - int flags); } -19 COMPAT POSIX { long lseek(int fd, long offset, int whence); } -20 MSTD POSIX { pid_t getpid(void); } -21 STD BSD { int mount(char *type, char *path, int flags, \ +12 NOPROTO POSIX { int chdir(char *path); } +13 NOPROTO BSD { int fchdir(int fd); } +14 NOPROTO POSIX { int mknod(char *path, int mode, int dev); } +15 NOPROTO POSIX { int chmod(char *path, int mode); } +16 NOPROTO POSIX { int chown(char *path, int uid, int gid); } +17 MNOPROTO BSD { int obreak(char *nsize); } break obreak_args int +18 STD BSD { int ia32_getfsstat(struct statfs32 *buf, \ + long bufsize, int flags); } +19 OBSOL POSIX olseek +20 MNOPROTO POSIX { pid_t getpid(void); } +21 NOPROTO BSD { int mount(char *type, char *path, int flags, \ caddr_t data); } ; XXX `path' should have type `const char *' but we're not ready for that. -22 STD BSD { int unmount(char *path, int flags); } -23 MSTD POSIX { int setuid(uid_t uid); } -24 MSTD POSIX { uid_t getuid(void); } -25 MSTD POSIX { uid_t geteuid(void); } -26 STD BSD { int ptrace(int req, pid_t pid, caddr_t addr, \ +22 NOPROTO BSD { int unmount(char *path, int flags); } +23 MNOPROTO POSIX { int setuid(uid_t uid); } +24 MNOPROTO POSIX { uid_t getuid(void); } +25 MNOPROTO POSIX { uid_t geteuid(void); } +26 NOPROTO BSD { int ptrace(int req, pid_t pid, caddr_t addr, \ int data); } -27 MSTD BSD { int recvmsg(int s, struct msghdr *msg, int flags); } -28 MSTD BSD { int sendmsg(int s, caddr_t msg, int flags); } -29 MSTD BSD { int recvfrom(int s, caddr_t buf, size_t len, \ +27 UNIMPL BSD recvmsg +28 MNOPROTO BSD { int sendmsg(int s, caddr_t msg, int flags); } +29 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \ int flags, caddr_t from, int *fromlenaddr); } -30 MSTD BSD { int accept(int s, caddr_t name, int *anamelen); } -31 MSTD BSD { int getpeername(int fdes, caddr_t asa, int *alen); } -32 MSTD BSD { int getsockname(int fdes, caddr_t asa, int *alen); } -33 STD POSIX { int access(char *path, int flags); } -34 STD BSD { int chflags(char *path, int flags); } -35 STD BSD { int fchflags(int fd, int flags); } -36 STD BSD { int sync(void); } -37 MSTD POSIX { int kill(int pid, int signum); } -38 COMPAT POSIX { int stat(char *path, struct ostat *ub); } -39 MSTD POSIX { pid_t getppid(void); } -40 COMPAT POSIX { int lstat(char *path, struct ostat *ub); } -41 STD POSIX { int dup(u_int fd); } -42 STD POSIX { int pipe(void); } -43 MSTD POSIX { gid_t getegid(void); } -44 MSTD BSD { int profil(caddr_t samples, size_t size, \ +30 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } +31 MNOPROTO BSD { int getpeername(int fdes, caddr_t asa, int *alen); } +32 MNOPROTO BSD { int getsockname(int fdes, caddr_t asa, int *alen); } +33 STD POSIX { int ia32_access(char *path, int flags); } +34 STD BSD { int ia32_chflags(char *path, int flags); } +35 NOPROTO BSD { int fchflags(int fd, int flags); } +36 NOPROTO BSD { int sync(void); } +37 MNOPROTO POSIX { int kill(int pid, int signum); } +38 UNIMPL POSIX ostat +39 MNOPROTO POSIX { pid_t getppid(void); } +40 UNIMPL POSIX olstat +41 NOPROTO POSIX { int dup(u_int fd); } +42 NOPROTO POSIX { int pipe(void); } +43 MNOPROTO POSIX { gid_t getegid(void); } +44 MNOPROTO BSD { int profil(caddr_t samples, size_t size, \ size_t offset, u_int scale); } -45 STD BSD { int ktrace(const char *fname, int ops, int facs, \ +45 NOPROTO BSD { int ktrace(const char *fname, int ops, int facs, \ int pid); } -46 MCOMPAT POSIX { int sigaction(int signum, struct osigaction *nsa, \ - struct osigaction *osa); } -47 MSTD POSIX { gid_t getgid(void); } -48 MCOMPAT POSIX { int sigprocmask(int how, osigset_t mask); } -; XXX note nonstandard (bogus) calling convention - the libc stub passes -; us the mask, not a pointer to it, and we return the old mask as the -; (int) return value. -49 MSTD BSD { int getlogin(char *namebuf, u_int namelen); } -50 MSTD BSD { int setlogin(char *namebuf); } -51 MSTD BSD { int acct(char *path); } -52 MCOMPAT POSIX { int sigpending(void); } -53 MSTD BSD { int sigaltstack(stack_t *ss, stack_t *oss); } -54 MSTD POSIX { int ioctl(int fd, u_long com, caddr_t data); } -55 MSTD BSD { int reboot(int opt); } -56 STD POSIX { int revoke(char *path); } -57 STD POSIX { int symlink(char *path, char *link); } -58 STD POSIX { int readlink(char *path, char *buf, int count); } -59 MSTD POSIX { int execve(char *fname, char **argv, char **envv); } -60 MSTD POSIX { int umask(int newmask); } umask umask_args int -61 STD BSD { int chroot(char *path); } -62 MCOMPAT POSIX { int fstat(int fd, struct ostat *sb); } -63 MCOMPAT BSD { int getkerninfo(int op, char *where, size_t *size, \ - int arg); } getkerninfo getkerninfo_args int -64 MCOMPAT BSD { int getpagesize(void); } \ - getpagesize getpagesize_args int -65 STD BSD { int msync(void *addr, size_t len, int flags); } -66 MSTD BSD { int vfork(void); } +46 UNIMPL POSIX osigaction +47 MNOPROTO POSIX { gid_t getgid(void); } +48 UNIMPL POSIX osigprocmask +49 MNOPROTO BSD { int getlogin(char *namebuf, u_int namelen); } +50 MNOPROTO BSD { int setlogin(char *namebuf); } +51 MNOPROTO BSD { int acct(char *path); } +52 MNOPROTO POSIX { int sigpending(void); } +53 STD BSD { int ia32_sigaltstack(struct sigaltstack32 *ss, struct sigaltstack32 *oss); } +54 MNOPROTO POSIX { int ioctl(int fd, u_long com, caddr_t data); } +55 MNOPROTO BSD { int reboot(int opt); } +56 NOPROTO POSIX { int revoke(char *path); } +57 NOPROTO POSIX { int symlink(char *path, char *link); } +58 NOPROTO POSIX { int readlink(char *path, char *buf, int count); } +59 STD POSIX { int ia32_execve(char *fname, u_int32_t *argv, u_int32_t *envv); } +60 MNOPROTO POSIX { int umask(int newmask); } umask umask_args int +61 NOPROTO BSD { int chroot(char *path); } +62 OBSOL POSIX ofstat +63 OBSOL BSD ogetkerninfo +64 OBSOL BSD ogetpagesize +65 OBSOL BSD omsync +66 OBSOL BSD ovfork 67 OBSOL NOHIDE vread 68 OBSOL NOHIDE vwrite -69 MSTD BSD { int sbrk(int incr); } -70 MSTD BSD { int sstk(int incr); } -71 MCOMPAT BSD { int mmap(void *addr, int len, int prot, \ - int flags, int fd, long pos); } -72 MSTD BSD { int ovadvise(int anom); } vadvise ovadvise_args int -73 MSTD BSD { int munmap(void *addr, size_t len); } -74 MSTD BSD { int mprotect(const void *addr, size_t len, int prot); } -75 MSTD BSD { int madvise(void *addr, size_t len, int behav); } +69 MNOPROTO BSD { int sbrk(int incr); } +70 MNOPROTO BSD { int sstk(int incr); } +71 OBSOL BSD ommap +72 MNOPROTO BSD { int ovadvise(int anom); } vadvise ovadvise_args int +73 MNOPROTO BSD { int munmap(void *addr, size_t len); } +74 MNOPROTO BSD { int mprotect(const void *addr, size_t len, int prot); } +75 MNOPROTO BSD { int madvise(void *addr, size_t len, int behav); } 76 OBSOL NOHIDE vhangup 77 OBSOL NOHIDE vlimit -78 MSTD BSD { int mincore(const void *addr, size_t len, \ +78 MNOPROTO BSD { int mincore(const void *addr, size_t len, \ char *vec); } -79 MSTD POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); } -80 MSTD POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); } -81 MSTD POSIX { int getpgrp(void); } -82 MSTD POSIX { int setpgid(int pid, int pgid); } -83 MSTD BSD { int setitimer(u_int which, struct itimerval *itv, \ - struct itimerval *oitv); } -84 MCOMPAT BSD { int wait(void); } -85 MSTD BSD { int swapon(char *name); } -86 MSTD BSD { int getitimer(u_int which, struct itimerval *itv); } -87 MCOMPAT BSD { int gethostname(char *hostname, u_int len); } \ - gethostname gethostname_args int -88 MCOMPAT BSD { int sethostname(char *hostname, u_int len); } \ - sethostname sethostname_args int -89 MSTD BSD { int getdtablesize(void); } -90 MSTD POSIX { int dup2(u_int from, u_int to); } +79 MNOPROTO POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); } +80 MNOPROTO POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); } +81 MNOPROTO POSIX { int getpgrp(void); } +82 MNOPROTO POSIX { int setpgid(int pid, int pgid); } +83 STD BSD { int ia32_setitimer(u_int which, \ + struct itimerval32 *itv, \ + struct itimerval32 *oitv); } +84 OBSOL BSD owait +85 OBSOL BSD oswapon +86 OBSOL BSD ogetitimer +87 OBSOL BSD ogethostname +88 OBSOL BSD osethostname +89 MNOPROTO BSD { int getdtablesize(void); } +90 MNOPROTO POSIX { int dup2(u_int from, u_int to); } 91 UNIMPL BSD getdopt -92 MSTD POSIX { int fcntl(int fd, int cmd, long arg); } +92 MNOPROTO POSIX { int fcntl(int fd, int cmd, long arg); } ; XXX should be { int fcntl(int fd, int cmd, ...); } ; but we're not ready for varargs. ; XXX man page says `int arg' too. -93 MSTD BSD { int select(int nd, fd_set *in, fd_set *ou, \ - fd_set *ex, struct timeval *tv); } +93 STD BSD { int ia32_select(int nd, fd_set *in, fd_set *ou, \ + fd_set *ex, struct timeval32 *tv); } +; XXX need to override for big-endian - little-endian should work fine. 94 UNIMPL BSD setdopt -95 STD POSIX { int fsync(int fd); } -96 MSTD BSD { int setpriority(int which, int who, int prio); } -97 MSTD BSD { int socket(int domain, int type, int protocol); } -98 MSTD BSD { int connect(int s, caddr_t name, int namelen); } -99 MCPT_NOA BSD { int accept(int s, caddr_t name, int *anamelen); } \ +95 NOPROTO POSIX { int fsync(int fd); } +96 MNOPROTO BSD { int setpriority(int which, int who, int prio); } +97 MNOPROTO BSD { int socket(int domain, int type, int protocol); } +98 MNOPROTO BSD { int connect(int s, caddr_t name, int namelen); } +99 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } \ accept accept_args int -100 MSTD BSD { int getpriority(int which, int who); } -101 MCOMPAT BSD { int send(int s, caddr_t buf, int len, int flags); } -102 MCOMPAT BSD { int recv(int s, caddr_t buf, int len, int flags); } -103 STD BSD { int osigreturn(struct osigcontext *sigcntxp); } -104 MSTD BSD { int bind(int s, caddr_t name, int namelen); } -105 MSTD BSD { int setsockopt(int s, int level, int name, \ +100 MNOPROTO BSD { int getpriority(int which, int who); } +101 OBSOL BSD osend +102 OBSOL BSD orecv +103 OBSOL BSD osigreturn +104 MNOPROTO BSD { int bind(int s, caddr_t name, int namelen); } +105 MNOPROTO BSD { int setsockopt(int s, int level, int name, \ caddr_t val, int valsize); } -106 MSTD BSD { int listen(int s, int backlog); } +106 MNOPROTO BSD { int listen(int s, int backlog); } 107 OBSOL NOHIDE vtimes -108 MCOMPAT BSD { int sigvec(int signum, struct sigvec *nsv, \ - struct sigvec *osv); } -109 MCOMPAT BSD { int sigblock(int mask); } -110 MCOMPAT BSD { int sigsetmask(int mask); } -111 MCOMPAT POSIX { int sigsuspend(osigset_t mask); } -; XXX note nonstandard (bogus) calling convention - the libc stub passes -; us the mask, not a pointer to it. -112 MCOMPAT BSD { int sigstack(struct sigstack *nss, \ - struct sigstack *oss); } -113 MCOMPAT BSD { int recvmsg(int s, struct omsghdr *msg, int flags); } -114 MCOMPAT BSD { int sendmsg(int s, caddr_t msg, int flags); } +108 OBSOL BSD osigvec +109 OBSOL BSD osigblock +110 OBSOL BSD osigsetmask +111 OBSOL POSIX osigsuspend +112 OBSOL BSD osigstack +113 OBSOL BSD orecvmsg +114 OBSOL BSD osendmsg 115 OBSOL NOHIDE vtrace -116 MSTD BSD { int gettimeofday(struct timeval *tp, \ +116 STD BSD { int ia32_gettimeofday(struct timeval32 *tp, \ struct timezone *tzp); } -117 MSTD BSD { int getrusage(int who, struct rusage *rusage); } -118 MSTD BSD { int getsockopt(int s, int level, int name, \ +117 STD BSD { int ia32_getrusage(int who, struct rusage32 *rusage); } +118 MNOPROTO BSD { int getsockopt(int s, int level, int name, \ caddr_t val, int *avalsize); } 119 UNIMPL NOHIDE resuba (BSD/OS 2.x) -120 MSTD BSD { int readv(int fd, struct iovec *iovp, u_int iovcnt); } -121 MSTD BSD { int writev(int fd, struct iovec *iovp, \ +120 STD BSD { int ia32_readv(int fd, struct iovec32 *iovp, u_int iovcnt); } +121 STD BSD { int ia32_writev(int fd, struct iovec32 *iovp, \ u_int iovcnt); } -122 MSTD BSD { int settimeofday(struct timeval *tv, \ +122 STD BSD { int ia32_settimeofday(struct timeval32 *tv, \ struct timezone *tzp); } -123 STD BSD { int fchown(int fd, int uid, int gid); } -124 STD BSD { int fchmod(int fd, int mode); } -125 MCPT_NOA BSD { int recvfrom(int s, caddr_t buf, size_t len, \ +123 NOPROTO BSD { int fchown(int fd, int uid, int gid); } +124 NOPROTO BSD { int fchmod(int fd, int mode); } +125 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \ int flags, caddr_t from, int *fromlenaddr); } \ recvfrom recvfrom_args int -126 MSTD BSD { int setreuid(int ruid, int euid); } -127 MSTD BSD { int setregid(int rgid, int egid); } -128 STD POSIX { int rename(char *from, char *to); } -129 COMPAT BSD { int truncate(char *path, long length); } -130 COMPAT BSD { int ftruncate(int fd, long length); } -131 MSTD BSD { int flock(int fd, int how); } -132 STD POSIX { int mkfifo(char *path, int mode); } -133 MSTD BSD { int sendto(int s, caddr_t buf, size_t len, \ +126 MNOPROTO BSD { int setreuid(int ruid, int euid); } +127 MNOPROTO BSD { int setregid(int rgid, int egid); } +128 NOPROTO POSIX { int rename(char *from, char *to); } +129 OBSOL BSD otruncate +130 OBSOL BSD ftruncate +131 MNOPROTO BSD { int flock(int fd, int how); } +132 NOPROTO POSIX { int mkfifo(char *path, int mode); } +133 MNOPROTO BSD { int sendto(int s, caddr_t buf, size_t len, \ int flags, caddr_t to, int tolen); } -134 MSTD BSD { int shutdown(int s, int how); } -135 MSTD BSD { int socketpair(int domain, int type, int protocol, \ +134 MNOPROTO BSD { int shutdown(int s, int how); } +135 MNOPROTO BSD { int socketpair(int domain, int type, int protocol, \ int *rsv); } -136 STD POSIX { int mkdir(char *path, int mode); } -137 STD POSIX { int rmdir(char *path); } -138 STD BSD { int utimes(char *path, struct timeval *tptr); } +136 NOPROTO POSIX { int mkdir(char *path, int mode); } +137 NOPROTO POSIX { int rmdir(char *path); } +138 STD BSD { int ia32_utimes(char *path, \ + struct timeval32 *tptr); } 139 OBSOL NOHIDE 4.2 sigreturn -140 MSTD BSD { int adjtime(struct timeval *delta, \ - struct timeval *olddelta); } -141 MCOMPAT BSD { int getpeername(int fdes, caddr_t asa, int *alen); } -142 MCOMPAT BSD { long gethostid(void); } -143 MCOMPAT BSD { int sethostid(long hostid); } -144 MCOMPAT BSD { int getrlimit(u_int which, struct orlimit *rlp); } -145 MCOMPAT BSD { int setrlimit(u_int which, struct orlimit *rlp); } -146 MCOMPAT BSD { int killpg(int pgid, int signum); } -147 MSTD POSIX { int setsid(void); } -148 STD BSD { int quotactl(char *path, int cmd, int uid, \ +140 STD BSD { int ia32_adjtime(struct timeval32 *delta, \ + struct timeval32 *olddelta); } +141 OBSOL BSD ogetpeername +142 OBSOL BSD ogethostid +143 OBSOL BSD sethostid +144 OBSOL BSD getrlimit +145 OBSOL BSD setrlimit +146 OBSOL BSD killpg +147 MNOPROTO POSIX { int setsid(void); } +148 NOPROTO BSD { int quotactl(char *path, int cmd, int uid, \ caddr_t arg); } -149 MCOMPAT BSD { int quota(void); } -150 MCPT_NOA BSD { int getsockname(int fdec, caddr_t asa, int *alen); }\ - getsockname getsockname_args int +149 OBSOL BSD oquota +150 OBSOL BSD ogetsockname ; Syscalls 151-180 inclusive are reserved for vendor-specific ; system calls. (This includes various calls added for compatibity ; with other Unix variants.) ; Some of these calls are now supported by BSD... 151 UNIMPL NOHIDE sem_lock (BSD/OS 2.x) 152 UNIMPL NOHIDE sem_wakeup (BSD/OS 2.x) 153 UNIMPL NOHIDE asyncdaemon (BSD/OS 2.x) 154 UNIMPL NOHIDE nosys ; 155 is initialized by the NFS code, if present. -155 MNOIMPL BSD { int nfssvc(int flag, caddr_t argp); } -156 COMPAT BSD { int getdirentries(int fd, char *buf, u_int count, \ +155 UNIMPL NOHIDE nfssvc +156 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \ long *basep); } -157 STD BSD { int statfs(char *path, struct statfs *buf); } -158 STD BSD { int fstatfs(int fd, struct statfs *buf); } +157 STD BSD { int ia32_statfs(char *path, struct statfs32 *buf); } +158 STD BSD { int ia32_fstatfs(int fd, struct statfs32 *buf); } 159 UNIMPL NOHIDE nosys 160 UNIMPL NOHIDE nosys -161 STD BSD { int getfh(char *fname, struct fhandle *fhp); } -162 MSTD BSD { int getdomainname(char *domainname, int len); } -163 MSTD BSD { int setdomainname(char *domainname, int len); } -164 MSTD BSD { int uname(struct utsname *name); } -165 STD BSD { int sysarch(int op, char *parms); } -166 MSTD BSD { int rtprio(int function, pid_t pid, \ +161 NOPROTO BSD { int getfh(char *fname, struct fhandle *fhp); } +162 MNOPROTO BSD { int getdomainname(char *domainname, int len); } +163 MNOPROTO BSD { int setdomainname(char *domainname, int len); } +164 MNOPROTO BSD { int uname(struct utsname *name); } +165 NOPROTO BSD { int sysarch(int op, char *parms); } +166 MNOPROTO BSD { int rtprio(int function, pid_t pid, \ struct rtprio *rtp); } 167 UNIMPL NOHIDE nosys 168 UNIMPL NOHIDE nosys -; 169 is initialized by the SYSVSEM code if present or loaded -169 MNOSTD BSD { int semsys(int which, int a2, int a3, int a4, \ +169 STD BSD { int ia32_semsys(int which, int a2, int a3, int a4, \ int a5); } -; 169 is initialized by the SYSVMSG code if present or loaded -; XXX should be { int semsys(int which, ...); } -170 MNOSTD BSD { int msgsys(int which, int a2, int a3, int a4, \ +170 STD BSD { int ia32_msgsys(int which, int a2, int a3, int a4, \ int a5, int a6); } -; 169 is initialized by the SYSVSHM code if present or loaded -; XXX should be { int msgsys(int which, ...); } -171 MNOSTD BSD { int shmsys(int which, int a2, int a3, int a4); } -; XXX should be { int shmsys(int which, ...); } +171 STD BSD { int ia32_shmsys(int which, int a2, int a3, int a4); } 172 UNIMPL NOHIDE nosys -173 MSTD POSIX { ssize_t pread(int fd, void *buf, size_t nbyte, \ - int pad, off_t offset); } -174 MSTD POSIX { ssize_t pwrite(int fd, const void *buf, \ - size_t nbyte, int pad, off_t offset); } +173 STD POSIX { ssize_t ia32_pread(int fd, void *buf, size_t nbyte, \ + int pad, u_int32_t offsetlo, u_int32_t offsethi); } +; XXX note - bigendian is different +174 STD POSIX { ssize_t ia32_pwrite(int fd, const void *buf, \ + size_t nbyte, int pad, u_int32_t offsetlo, \ + u_int32_t offsethi); } +; XXX note - bigendian is different 175 UNIMPL NOHIDE nosys -176 MSTD BSD { int ntp_adjtime(struct timex *tp); } +176 MNOPROTO BSD { int ntp_adjtime(struct timex *tp); } 177 UNIMPL NOHIDE sfork (BSD/OS 2.x) 178 UNIMPL NOHIDE getdescriptor (BSD/OS 2.x) 179 UNIMPL NOHIDE setdescriptor (BSD/OS 2.x) 180 UNIMPL NOHIDE nosys ; Syscalls 181-199 are used by/reserved for BSD -181 MSTD POSIX { int setgid(gid_t gid); } -182 MSTD BSD { int setegid(gid_t egid); } -183 MSTD BSD { int seteuid(uid_t euid); } +181 MNOPROTO POSIX { int setgid(gid_t gid); } +182 MNOPROTO BSD { int setegid(gid_t egid); } +183 MNOPROTO BSD { int seteuid(uid_t euid); } 184 UNIMPL BSD lfs_bmapv 185 UNIMPL BSD lfs_markv 186 UNIMPL BSD lfs_segclean 187 UNIMPL BSD lfs_segwait -188 STD POSIX { int stat(char *path, struct stat *ub); } -189 MSTD POSIX { int fstat(int fd, struct stat *sb); } -190 STD POSIX { int lstat(char *path, struct stat *ub); } -191 STD POSIX { int pathconf(char *path, int name); } -192 MSTD POSIX { int fpathconf(int fd, int name); } +188 STD POSIX { int ia32_stat(char *path, struct stat32 *ub); } +189 STD POSIX { int ia32_fstat(int fd, struct stat32 *ub); } +190 STD POSIX { int ia32_lstat(char *path, struct stat32 *ub); } +191 NOPROTO POSIX { int pathconf(char *path, int name); } +192 MNOPROTO POSIX { int fpathconf(int fd, int name); } 193 UNIMPL NOHIDE nosys -194 MSTD BSD { int getrlimit(u_int which, \ +194 MNOPROTO BSD { int getrlimit(u_int which, \ struct rlimit *rlp); } \ getrlimit __getrlimit_args int -195 MSTD BSD { int setrlimit(u_int which, \ +195 MNOPROTO BSD { int setrlimit(u_int which, \ struct rlimit *rlp); } \ setrlimit __setrlimit_args int -196 STD BSD { int getdirentries(int fd, char *buf, u_int count, \ +196 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \ long *basep); } -197 MSTD BSD { caddr_t mmap(caddr_t addr, size_t len, int prot, \ - int flags, int fd, int pad, off_t pos); } -198 STD NOHIDE { int nosys(void); } __syscall __syscall_args int -199 STD POSIX { off_t lseek(int fd, int pad, off_t offset, \ +197 STD BSD { caddr_t ia32_mmap(caddr_t addr, size_t len, \ + int prot, int flags, int fd, int pad, \ + u_int32_t poslo, u_int32_t poshi); } +198 NOPROTO NOHIDE { int nosys(void); } __syscall __syscall_args int +; XXX note - bigendian is different +199 STD POSIX { off_t ia32_lseek(int fd, int pad, \ + u_int32_t offsetlo, u_int32_t offsethi, \ int whence); } -200 STD BSD { int truncate(char *path, int pad, off_t length); } -201 STD BSD { int ftruncate(int fd, int pad, off_t length); } -202 MSTD BSD { int __sysctl(int *name, u_int namelen, void *old, \ - size_t *oldlenp, void *new, size_t newlen); } \ - __sysctl sysctl_args int -; properly, __sysctl should be a NOHIDE, but making an exception -; here allows to avoid one in libc/sys/Makefile.inc. -203 MSTD BSD { int mlock(const void *addr, size_t len); } -204 MSTD BSD { int munlock(const void *addr, size_t len); } -205 STD BSD { int undelete(char *path); } -206 STD BSD { int futimes(int fd, struct timeval *tptr); } -207 MSTD BSD { int getpgid(pid_t pid); } +; XXX note - bigendian is different +200 STD BSD { int ia32_truncate(char *path, int pad, \ + u_int32_t lengthlo, u_int32_t lengthhi); } +; XXX note - bigendian is different +201 STD BSD { int ia32_ftruncate(int fd, int pad, \ + u_int32_t lengthlo, u_int32_t lengthhi); } +202 MSTD BSD { int ia32_sysctl(int *name, u_int namelen, \ + void *old, u_int32_t *oldlenp, void *new, \ + u_int32_t newlen); } +203 MNOPROTO BSD { int mlock(const void *addr, size_t len); } +204 MNOPROTO BSD { int munlock(const void *addr, size_t len); } +205 NOPROTO BSD { int undelete(char *path); } +206 NOPROTO BSD { int futimes(int fd, struct timeval *tptr); } +207 MNOPROTO BSD { int getpgid(pid_t pid); } 208 UNIMPL NOHIDE newreboot (NetBSD) -209 MSTD BSD { int poll(struct pollfd *fds, u_int nfds, \ +209 MNOPROTO BSD { int poll(struct pollfd *fds, u_int nfds, \ int timeout); } ; ; The following are reserved for loadable syscalls ; -210 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -211 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -212 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -213 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -214 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -215 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -216 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -217 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -218 NODEF NOHIDE lkmnosys lkmnosys nosys_args int -219 NODEF NOHIDE lkmnosys lkmnosys nosys_args int +210 UNIMPL NOHIDE +211 UNIMPL NOHIDE +212 UNIMPL NOHIDE +213 UNIMPL NOHIDE +214 UNIMPL NOHIDE +215 UNIMPL NOHIDE +216 UNIMPL NOHIDE +217 UNIMPL NOHIDE +218 UNIMPL NOHIDE +219 UNIMPL NOHIDE ; ; The following were introduced with NetBSD/4.4Lite-2 ; They are initialized by thier respective modules/sysinits -220 MNOSTD BSD { int __semctl(int semid, int semnum, int cmd, \ +220 MNOPROTO BSD { int __semctl(int semid, int semnum, int cmd, \ union semun *arg); } -221 MNOSTD BSD { int semget(key_t key, int nsems, int semflg); } -222 MNOSTD BSD { int semop(int semid, struct sembuf *sops, \ +221 MNOPROTO BSD { int semget(key_t key, int nsems, int semflg); } +222 MNOPROTO BSD { int semop(int semid, struct sembuf *sops, \ u_int nsops); } 223 UNIMPL NOHIDE semconfig -224 MNOSTD BSD { int msgctl(int msqid, int cmd, \ +224 MNOPROTO BSD { int msgctl(int msqid, int cmd, \ struct msqid_ds *buf); } -225 MNOSTD BSD { int msgget(key_t key, int msgflg); } -226 MNOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ +225 MNOPROTO BSD { int msgget(key_t key, int msgflg); } +226 MNOPROTO BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ int msgflg); } -227 MNOSTD BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \ +227 MNOPROTO BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \ long msgtyp, int msgflg); } -228 MNOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); } -229 MNOSTD BSD { int shmctl(int shmid, int cmd, \ +228 MNOPROTO BSD { int shmat(int shmid, void *shmaddr, int shmflg); } +229 MNOPROTO BSD { int shmctl(int shmid, int cmd, \ struct shmid_ds *buf); } -230 MNOSTD BSD { int shmdt(void *shmaddr); } -231 MNOSTD BSD { int shmget(key_t key, int size, int shmflg); } +230 MNOPROTO BSD { int shmdt(void *shmaddr); } +231 MNOPROTO BSD { int shmget(key_t key, int size, int shmflg); } ; -232 MSTD POSIX { int clock_gettime(clockid_t clock_id, \ +232 MNOPROTO POSIX { int clock_gettime(clockid_t clock_id, \ struct timespec *tp); } -233 MSTD POSIX { int clock_settime(clockid_t clock_id, \ +233 MNOPROTO POSIX { int clock_settime(clockid_t clock_id, \ const struct timespec *tp); } -234 MSTD POSIX { int clock_getres(clockid_t clock_id, \ +234 MNOPROTO POSIX { int clock_getres(clockid_t clock_id, \ struct timespec *tp); } 235 UNIMPL NOHIDE timer_create 236 UNIMPL NOHIDE timer_delete 237 UNIMPL NOHIDE timer_settime 238 UNIMPL NOHIDE timer_gettime 239 UNIMPL NOHIDE timer_getoverrun -240 MSTD POSIX { int nanosleep(const struct timespec *rqtp, \ +240 MNOPROTO POSIX { int nanosleep(const struct timespec *rqtp, \ struct timespec *rmtp); } 241 UNIMPL NOHIDE nosys 242 UNIMPL NOHIDE nosys 243 UNIMPL NOHIDE nosys 244 UNIMPL NOHIDE nosys 245 UNIMPL NOHIDE nosys 246 UNIMPL NOHIDE nosys 247 UNIMPL NOHIDE nosys 248 UNIMPL NOHIDE nosys 249 UNIMPL NOHIDE nosys ; syscall numbers initially used in OpenBSD -250 MSTD BSD { int minherit(void *addr, size_t len, int inherit); } -251 MSTD BSD { int rfork(int flags); } -252 MSTD BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \ +250 MNOPROTO BSD { int minherit(void *addr, size_t len, int inherit); } +251 MNOPROTO BSD { int rfork(int flags); } +252 MNOPROTO BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \ int timeout); } -253 STD BSD { int issetugid(void); } -254 STD BSD { int lchown(char *path, int uid, int gid); } +253 NOPROTO BSD { int issetugid(void); } +254 NOPROTO BSD { int lchown(char *path, int uid, int gid); } 255 UNIMPL NOHIDE nosys 256 UNIMPL NOHIDE nosys 257 UNIMPL NOHIDE nosys 258 UNIMPL NOHIDE nosys 259 UNIMPL NOHIDE nosys 260 UNIMPL NOHIDE nosys 261 UNIMPL NOHIDE nosys 262 UNIMPL NOHIDE nosys 263 UNIMPL NOHIDE nosys 264 UNIMPL NOHIDE nosys 265 UNIMPL NOHIDE nosys 266 UNIMPL NOHIDE nosys 267 UNIMPL NOHIDE nosys 268 UNIMPL NOHIDE nosys 269 UNIMPL NOHIDE nosys 270 UNIMPL NOHIDE nosys 271 UNIMPL NOHIDE nosys -272 STD BSD { int getdents(int fd, char *buf, size_t count); } +272 NOPROTO BSD { int getdents(int fd, char *buf, size_t count); } 273 UNIMPL NOHIDE nosys -274 STD BSD { int lchmod(char *path, mode_t mode); } +274 NOPROTO BSD { int lchmod(char *path, mode_t mode); } 275 NOPROTO BSD { int lchown(char *path, uid_t uid, gid_t gid); } netbsd_lchown lchown_args int -276 STD BSD { int lutimes(char *path, struct timeval *tptr); } +276 NOPROTO BSD { int lutimes(char *path, struct timeval *tptr); } 277 MNOPROTO BSD { int msync(void *addr, size_t len, int flags); } netbsd_msync msync_args int -278 STD BSD { int nstat(char *path, struct nstat *ub); } -279 MSTD BSD { int nfstat(int fd, struct nstat *sb); } -280 STD BSD { int nlstat(char *path, struct nstat *ub); } +278 NOPROTO BSD { int nstat(char *path, struct nstat *ub); } +279 MNOPROTO BSD { int nfstat(int fd, struct nstat *sb); } +280 NOPROTO BSD { int nlstat(char *path, struct nstat *ub); } 281 UNIMPL NOHIDE nosys 282 UNIMPL NOHIDE nosys 283 UNIMPL NOHIDE nosys 284 UNIMPL NOHIDE nosys 285 UNIMPL NOHIDE nosys 286 UNIMPL NOHIDE nosys 287 UNIMPL NOHIDE nosys 288 UNIMPL NOHIDE nosys 289 UNIMPL NOHIDE nosys 290 UNIMPL NOHIDE nosys 291 UNIMPL NOHIDE nosys 292 UNIMPL NOHIDE nosys 293 UNIMPL NOHIDE nosys 294 UNIMPL NOHIDE nosys 295 UNIMPL NOHIDE nosys 296 UNIMPL NOHIDE nosys ; XXX 297 is 300 in NetBSD -297 STD BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } -298 STD BSD { int fhopen(const struct fhandle *u_fhp, int flags); } -299 STD BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } +297 NOPROTO BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } +298 NOPROTO BSD { int fhopen(const struct fhandle *u_fhp, int flags); } +299 NOPROTO BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } ; syscall numbers for FreeBSD -300 MSTD BSD { int modnext(int modid); } -301 MSTD BSD { int modstat(int modid, struct module_stat* stat); } -302 MSTD BSD { int modfnext(int modid); } -303 MSTD BSD { int modfind(const char *name); } -304 MSTD BSD { int kldload(const char *file); } -305 MSTD BSD { int kldunload(int fileid); } -306 MSTD BSD { int kldfind(const char *file); } -307 MSTD BSD { int kldnext(int fileid); } -308 MSTD BSD { int kldstat(int fileid, struct kld_file_stat* stat); } -309 MSTD BSD { int kldfirstmod(int fileid); } -310 MSTD BSD { int getsid(pid_t pid); } -311 MSTD BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } -312 MSTD BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } +300 MNOPROTO BSD { int modnext(int modid); } +301 MNOPROTO BSD { int modstat(int modid, struct module_stat* stat); } +302 MNOPROTO BSD { int modfnext(int modid); } +303 MNOPROTO BSD { int modfind(const char *name); } +304 MNOPROTO BSD { int kldload(const char *file); } +305 MNOPROTO BSD { int kldunload(int fileid); } +306 MNOPROTO BSD { int kldfind(const char *file); } +307 MNOPROTO BSD { int kldnext(int fileid); } +308 MNOPROTO BSD { int kldstat(int fileid, struct kld_file_stat* stat); } +309 MNOPROTO BSD { int kldfirstmod(int fileid); } +310 MNOPROTO BSD { int getsid(pid_t pid); } +311 MNOPROTO BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } +312 MNOPROTO BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } 313 OBSOL NOHIDE signanosleep -314 NOSTD BSD { int aio_return(struct aiocb *aiocbp); } -315 NOSTD BSD { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } -316 NOSTD BSD { int aio_cancel(int fd, struct aiocb *aiocbp); } -317 NOSTD BSD { int aio_error(struct aiocb *aiocbp); } -318 NOSTD BSD { int aio_read(struct aiocb *aiocbp); } -319 NOSTD BSD { int aio_write(struct aiocb *aiocbp); } -320 NOSTD BSD { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); } -321 MSTD BSD { int yield(void); } +314 UNIMPL NOHIDE aio_return +315 UNIMPL NOHIDE aio_suspend +316 UNIMPL NOHIDE aio_cancel +317 UNIMPL NOHIDE aio_error +318 UNIMPL NOHIDE aio_read +319 UNIMPL NOHIDE aio_write +320 UNIMPL NOHIDE lio_listio +321 MNOPROTO BSD { int yield(void); } 322 OBSOL NOHIDE thr_sleep 323 OBSOL NOHIDE thr_wakeup -324 MSTD BSD { int mlockall(int how); } -325 MSTD BSD { int munlockall(void); } -326 STD BSD { int __getcwd(u_char *buf, u_int buflen); } +324 MNOPROTO BSD { int mlockall(int how); } +325 MNOPROTO BSD { int munlockall(void); } +326 NOPROTO BSD { int __getcwd(u_char *buf, u_int buflen); } -327 MSTD POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); } -328 MSTD POSIX { int sched_getparam (pid_t pid, struct sched_param *param); } +327 MNOPROTO POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); } +328 MNOPROTO POSIX { int sched_getparam (pid_t pid, struct sched_param *param); } -329 MSTD POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } -330 MSTD POSIX { int sched_getscheduler (pid_t pid); } +329 MNOPROTO POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } +330 MNOPROTO POSIX { int sched_getscheduler (pid_t pid); } -331 MSTD POSIX { int sched_yield (void); } -332 MSTD POSIX { int sched_get_priority_max (int policy); } -333 MSTD POSIX { int sched_get_priority_min (int policy); } -334 MSTD POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); } -335 STD BSD { int utrace(const void *addr, size_t len); } -336 MSTD BSD { int sendfile(int fd, int s, off_t offset, size_t nbytes, \ - struct sf_hdtr *hdtr, off_t *sbytes, int flags); } -337 STD BSD { int kldsym(int fileid, int cmd, void *data); } -338 MSTD BSD { int jail(struct jail *jail); } +331 MNOPROTO POSIX { int sched_yield (void); } +332 MNOPROTO POSIX { int sched_get_priority_max (int policy); } +333 MNOPROTO POSIX { int sched_get_priority_min (int policy); } +334 MNOPROTO POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); } +335 NOPROTO BSD { int utrace(const void *addr, size_t len); } +; XXX note - bigendian is different +336 MSTD BSD { int ia32_sendfile(int fd, int s, u_int32_t offsetlo, \ + u_int32_t offsethi, size_t nbytes, \ + struct sf_hdtr *hdtr, off_t *sbytes, int flags); } +337 NOPROTO BSD { int kldsym(int fileid, int cmd, void *data); } +338 MNOPROTO BSD { int jail(struct jail *jail); } 339 UNIMPL BSD pioctl -340 MSTD POSIX { int sigprocmask(int how, const sigset_t *set, \ +340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \ sigset_t *oset); } -341 MSTD POSIX { int sigsuspend(const sigset_t *sigmask); } -342 MSTD POSIX { int sigaction(int sig, const struct sigaction *act, \ - struct sigaction *oact); } -343 MSTD POSIX { int sigpending(sigset_t *set); } -344 STD BSD { int sigreturn(const struct __ucontext *sigcntxp); } +341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); } +342 STD POSIX { int ia32_sigaction(int sig, \ + struct sigaction32 *act, \ + struct sigaction32 *oact); } +343 MNOPROTO POSIX { int sigpending(sigset_t *set); } +344 MNOPROTO BSD { int sigreturn(const struct __ucontext *sigcntxp); } 345 UNIMPL NOHIDE sigtimedwait 346 UNIMPL NOHIDE sigwaitinfo -347 MSTD BSD { int __acl_get_file(const char *path, \ +347 MNOPROTO BSD { int __acl_get_file(const char *path, \ acl_type_t type, struct acl *aclp); } -348 MSTD BSD { int __acl_set_file(const char *path, \ +348 MNOPROTO BSD { int __acl_set_file(const char *path, \ acl_type_t type, struct acl *aclp); } -349 MSTD BSD { int __acl_get_fd(int filedes, acl_type_t type, \ +349 MNOPROTO BSD { int __acl_get_fd(int filedes, acl_type_t type, \ struct acl *aclp); } -350 MSTD BSD { int __acl_set_fd(int filedes, acl_type_t type, \ +350 MNOPROTO BSD { int __acl_set_fd(int filedes, acl_type_t type, \ struct acl *aclp); } -351 MSTD BSD { int __acl_delete_file(const char *path, \ +351 MNOPROTO BSD { int __acl_delete_file(const char *path, \ acl_type_t type); } -352 MSTD BSD { int __acl_delete_fd(int filedes, acl_type_t type); } -353 MSTD BSD { int __acl_aclcheck_file(const char *path, \ +352 MNOPROTO BSD { int __acl_delete_fd(int filedes, acl_type_t type); } +353 MNOPROTO BSD { int __acl_aclcheck_file(const char *path, \ acl_type_t type, struct acl *aclp); } -354 MSTD BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \ +354 MNOPROTO BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \ struct acl *aclp); } -355 STD BSD { int extattrctl(const char *path, int cmd, \ +355 NOPROTO BSD { int extattrctl(const char *path, int cmd, \ const char *filename, int attrnamespace, \ const char *attrname); } -356 STD BSD { int extattr_set_file(const char *path, \ +356 NOPROTO BSD { int extattr_set_file(const char *path, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } -357 STD BSD { ssize_t extattr_get_file(const char *path, \ +357 NOPROTO BSD { ssize_t extattr_get_file(const char *path, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } -358 STD BSD { int extattr_delete_file(const char *path, \ +358 NOPROTO BSD { int extattr_delete_file(const char *path, \ int attrnamespace, const char *attrname); } -359 NOSTD BSD { int aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); } -360 MSTD BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } -361 MSTD BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } -362 MSTD BSD { int kqueue(void); } -363 MSTD BSD { int kevent(int fd, \ +359 UNIMPL NOHIDE aio_waitcomplete +360 MNOPROTO BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } +361 MNOPROTO BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } +362 MNOPROTO BSD { int kqueue(void); } +363 MNOPROTO BSD { int kevent(int fd, \ const struct kevent *changelist, int nchanges, \ struct kevent *eventlist, int nevents, \ const struct timespec *timeout); } -364 STD BSD { int __cap_get_proc(struct cap *cap_p); } -365 STD BSD { int __cap_set_proc(struct cap *cap_p); } -366 STD BSD { int __cap_get_fd(int fd, struct cap *cap_p); } -367 STD BSD { int __cap_get_file(const char *path_p, struct cap *cap_p); } -368 STD BSD { int __cap_set_fd(int fd, struct cap *cap_p); } -369 STD BSD { int __cap_set_file(const char *path_p, struct cap *cap_p); } -370 NODEF NOHIDE lkmressys lkmressys nosys_args int -371 STD BSD { int extattr_set_fd(int fd, int attrnamespace, \ +364 UNIMPL NOHIDE __cap_get_proc +365 UNIMPL NOHIDE __cap_set_proc +366 UNIMPL NOHIDE __cap_get_fd +367 UNIMPL NOHIDE __cap_get_file +368 UNIMPL NOHIDE __cap_set_fd +369 UNIMPL NOHIDE __cap_set_file +370 UNIMPL NOHIDE lkmressys +371 NOPROTO BSD { int extattr_set_fd(int fd, int attrnamespace, \ const char *attrname, void *data, \ size_t nbytes); } -372 STD BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \ +372 NOPROTO BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \ const char *attrname, void *data, size_t nbytes); } -373 STD BSD { int extattr_delete_fd(int fd, int attrnamespace, \ +373 NOPROTO BSD { int extattr_delete_fd(int fd, int attrnamespace, \ const char *attrname); } -374 MSTD BSD { int __setugid(int flag); } -375 NOIMPL BSD { int nfsclnt(int flag, caddr_t argp); } -376 STD BSD { int eaccess(char *path, int flags); } +374 MNOPROTO BSD { int __setugid(int flag); } +375 UNIMPL BSD nfsclnt +376 NOPROTO BSD { int eaccess(char *path, int flags); } 377 UNIMPL BSD afs_syscall -378 STD BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \ +378 NOPROTO BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \ int flags); } -379 STD BSD { int kse_exit(void); } -380 STD BSD { int kse_wakeup(void); } -381 STD BSD { int kse_new(struct kse_mailbox * mbx, \ +379 NOPROTO BSD { int kse_exit(void); } +380 NOPROTO BSD { int kse_wakeup(void); } +381 NOPROTO BSD { int kse_new(struct kse_mailbox * mbx, \ int new_grp_flag); } -382 STD BSD { int thread_wakeup(struct thread_mailbox *tmbx); } -383 STD BSD { int kse_yield(void); } +382 NOPROTO BSD { int thread_wakeup(struct thread_mailbox *tmbx); } +383 NOPROTO BSD { int kse_yield(void); } 384 UNIMPL BSD __mac_get_proc 385 UNIMPL BSD __mac_set_proc 386 UNIMPL BSD __mac_get_fd 387 UNIMPL BSD __mac_get_file 388 UNIMPL BSD __mac_set_fd 389 UNIMPL BSD __mac_set_file +390 NOPROTO BSD { int kenv(int what, const char *name, char *value, \ + int len); } +391 NOPROTO BSD { int lchflags(const char *path, int flags); } +392 NOPROTO BSD { int uuidgen(struct uuid *store, int count); } Index: head/sys/ia64/ia64/elf_machdep.c =================================================================== --- head/sys/ia64/ia64/elf_machdep.c (revision 100383) +++ head/sys/ia64/ia64/elf_machdep.c (revision 100384) @@ -1,158 +1,196 @@ /*- * Copyright 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include +#include +#include +#include +#include #include +#include + +struct sysentvec elf64_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf64_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF64", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf64_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_IA_64, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf64_freebsd_sysvec + }; + +SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf64_insert_brand_entry, + &freebsd_brand_info); Elf_Addr link_elf_get_gp(linker_file_t); extern Elf_Addr fptr_storage[]; static Elf_Addr lookup_fdesc(linker_file_t lf, Elf_Word symidx) { Elf_Addr addr; int i; static int eot = 0; addr = elf_lookup(lf, symidx, 0); if (addr == 0) { for (i = 0; i < lf->ndeps; i++) { addr = lookup_fdesc(lf->deps[i], symidx); if (addr != 0) return (addr); } return (0); } if (eot) return (0); /* * Lookup and/or construct OPD */ for (i = 0; i < 8192; i += 2) { if (fptr_storage[i] == addr) return (Elf_Addr)(fptr_storage + i); if (fptr_storage[i] == 0) { fptr_storage[i] = addr; fptr_storage[i+1] = link_elf_get_gp(lf); return (Elf_Addr)(fptr_storage + i); } } printf("%s: fptr table full\n", __func__); eot = 1; return (0); } /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, const void *data, int type) { Elf_Addr relocbase = (Elf_Addr)lf->address; Elf_Addr *where; Elf_Addr addend, addr; Elf_Word rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; switch (type) { case ELF_RELOC_REL: rel = (const Elf_Rel *)data; where = (Elf_Addr *)(relocbase + rel->r_offset); rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); switch (rtype) { case R_IA64_DIR64LSB: case R_IA64_FPTR64LSB: case R_IA64_REL64LSB: addend = *where; break; default: addend = 0; break; } break; case ELF_RELOC_RELA: rela = (const Elf_Rela *)data; where = (Elf_Addr *)(relocbase + rela->r_offset); rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); addend = rela->r_addend; break; default: panic("%s: invalid ELF relocation (0x%x)\n", __func__, type); } switch (rtype) { case R_IA64_NONE: break; case R_IA64_DIR64LSB: /* word64 LSB S + A */ addr = elf_lookup(lf, symidx, 1); if (addr == 0) return (-1); *where = addr + addend; break; case R_IA64_FPTR64LSB: /* word64 LSB @fptr(S + A) */ if (addend != 0) { printf("%s: addend ignored for OPD relocation\n", __func__); } addr = lookup_fdesc(lf, symidx); if (addr == 0) return (-1); *where = addr; break; case R_IA64_REL64LSB: /* word64 LSB BD + A */ *where = relocbase + addend; break; case R_IA64_IPLTLSB: addr = lookup_fdesc(lf, symidx); if (addr == 0) return (-1); where[0] = *((Elf_Addr*)addr) + addend; where[1] = *((Elf_Addr*)addr + 1); break; default: printf("%s: unknown relocation (0x%x)\n", __func__, (int)rtype); return -1; } return (0); } Index: head/sys/ia64/include/elf.h =================================================================== --- head/sys/ia64/include/elf.h (revision 100383) +++ head/sys/ia64/include/elf.h (revision 100384) @@ -1,218 +1,233 @@ /*- * Copyright (c) 1996-1997 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_ELF_H_ #define _MACHINE_ELF_H_ 1 /* * ELF definitions for the IA-64 architecture. */ +#ifndef __ELF_WORD_SIZE +#define __ELF_WORD_SIZE 64 +#endif + #include /* Definitions common to all 64 bit architectures. */ +#include /* Definitions common to all 32 bit architectures. */ -#define __ELF_WORD_SIZE 64 /* Used by */ #include #define ELF_ARCH EM_IA_64 #define ELF_MACHINE_OK(x) ((x) == EM_IA_64) /* * Auxiliary vector entries for passing information to the interpreter. * * The i386 supplement to the SVR4 ABI specification names this "auxv_t", * but POSIX lays claim to all symbols ending with "_t". */ typedef struct { /* Auxiliary vector entry on initial stack */ int a_type; /* Entry type. */ union { + int a_val; /* Integer value. */ + } a_un; +} Elf32_Auxinfo; + +typedef struct { /* Auxiliary vector entry on initial stack */ + int a_type; /* Entry type. */ + union { long a_val; /* Integer value. */ void *a_ptr; /* Address. */ void (*a_fcn)(void); /* Function pointer (not used). */ } a_un; } Elf64_Auxinfo; __ElfType(Auxinfo); /* Values for a_type. */ #define AT_NULL 0 /* Terminates the vector. */ #define AT_IGNORE 1 /* Ignored entry. */ #define AT_EXECFD 2 /* File descriptor of program to load. */ #define AT_PHDR 3 /* Program header of program already loaded. */ #define AT_PHENT 4 /* Size of each program header entry. */ #define AT_PHNUM 5 /* Number of program header entries. */ #define AT_PAGESZ 6 /* Page size in bytes. */ #define AT_BASE 7 /* Interpreter's base address. */ #define AT_FLAGS 8 /* Flags (unused for i386). */ #define AT_ENTRY 9 /* Where interpreter should transfer control. */ /* * The following non-standard values are used for passing information * from John Polstra's testbed program to the dynamic linker. These * are expected to go away soon. * * Unfortunately, these overlap the Linux non-standard values, so they * must not be used in the same context. */ #define AT_BRK 10 /* Starting point for sbrk and brk. */ #define AT_DEBUG 11 /* Debugging level. */ /* * The following non-standard values are used in Linux ELF binaries. */ #define AT_NOTELF 10 /* Program is not ELF ?? */ #define AT_UID 11 /* Real uid. */ #define AT_EUID 12 /* Effective uid. */ #define AT_GID 13 /* Real gid. */ #define AT_EGID 14 /* Effective gid. */ #define AT_COUNT 15 /* Count of defined aux entry types. */ /* * Values for e_flags. */ #define EF_IA_64_MASKOS 0x00ff000f #define EF_IA_64_ABI64 0x00000010 #define EF_IA_64_REDUCEDFP 0x00000020 #define EF_IA_64_CONS_GP 0x00000040 #define EF_IA_64_NOFUNCDESC_CONS_GP 0x00000080 #define EF_IA_64_ABSOLUTE 0x00000100 #define EF_IA_64_ARCH 0xff000000 /* * Segment types. */ #define PT_IA_64_ARCHEXT 0x70000000 #define PT_IA_64_UNWIND 0x70000001 /* * Segment attributes. */ #define PF_IA_64_NORECOV 0x80000000 /* * Section types. */ #define SHT_IA_64_EXT 0x70000000 #define SHT_IA_64_UNWIND 0x70000001 #define SHT_IA_64_LOPSREG 0x78000000 #define SHT_IA_64_HIPSREG 0x7fffffff /* * Section attribute flags. */ #define SHF_IA_64_SHORT 0x10000000 #define SHF_IA_64_NORECOV 0x20000000 /* * Relocation types. */ /* Name Value Field Calculation */ #define R_IA64_NONE 0 /* None */ #define R_IA64_IMM14 0x21 /* immediate14 S + A */ #define R_IA64_IMM22 0x22 /* immediate22 S + A */ #define R_IA64_IMM64 0x23 /* immediate64 S + A */ #define R_IA64_DIR32MSB 0x24 /* word32 MSB S + A */ #define R_IA64_DIR32LSB 0x25 /* word32 LSB S + A */ #define R_IA64_DIR64MSB 0x26 /* word64 MSB S + A */ #define R_IA64_DIR64LSB 0x27 /* word64 LSB S + A */ #define R_IA64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ #define R_IA64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ #define R_IA64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ #define R_IA64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ #define R_IA64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ #define R_IA64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ #define R_IA64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ #define R_IA64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ #define R_IA64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ #define R_IA64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ #define R_IA64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ #define R_IA64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ #define R_IA64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ #define R_IA64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ #define R_IA64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ #define R_IA64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ #define R_IA64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ #define R_IA64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ #define R_IA64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ #define R_IA64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ #define R_IA64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ #define R_IA64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ #define R_IA64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ #define R_IA64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ #define R_IA64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ #define R_IA64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ #define R_IA64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ #define R_IA64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ #define R_IA64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ #define R_IA64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ #define R_IA64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ #define R_IA64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ #define R_IA64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ #define R_IA64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ #define R_IA64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ #define R_IA64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ #define R_IA64_REL32MSB 0x6c /* word32 MSB BD + A */ #define R_IA64_REL32LSB 0x6d /* word32 LSB BD + A */ #define R_IA64_REL64MSB 0x6e /* word64 MSB BD + A */ #define R_IA64_REL64LSB 0x6f /* word64 LSB BD + A */ #define R_IA64_LTV32MSB 0x74 /* word32 MSB S + A */ #define R_IA64_LTV32LSB 0x75 /* word32 LSB S + A */ #define R_IA64_LTV64MSB 0x76 /* word64 MSB S + A */ #define R_IA64_LTV64LSB 0x77 /* word64 LSB S + A */ #define R_IA64_IPLTMSB 0x80 /* function descriptor MSB special */ #define R_IA64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ #define R_IA64_SUB 0x85 /* immediate64 A - S */ #define R_IA64_LTOFF22X 0x86 /* immediate22 special */ #define R_IA64_LDXMOV 0x87 /* immediate22 special */ /* Define "machine" characteristics */ +#if __ELF_WORD_SIZE == 32 +#define ELF_TARG_CLASS ELFCLASS32 +#else #define ELF_TARG_CLASS ELFCLASS64 +#endif #define ELF_TARG_DATA ELFDATA2LSB #define ELF_TARG_MACH EM_IA_64 #define ELF_TARG_VER 1 /* Processor specific dynmamic section tags. */ #define DT_IA64_PLT_RESERVE 0x70000000 #ifdef _KERNEL /* * On the ia64 we load the dynamic linker where a userland call * to mmap(0, ...) would put it. The rationale behind this * calculation is that it leaves room for the heap to grow to * its maximum allowed size. */ #define ELF_RTLD_ADDR(vmspace) \ (round_page((vm_offset_t)(vmspace)->vm_daddr + maxdsiz)) #endif /* _KERNEL */ #endif /* !_MACHINE_ELF_H_ */ Index: head/sys/kern/imgact_aout.c =================================================================== --- head/sys/kern/imgact_aout.c (revision 100383) +++ head/sys/kern/imgact_aout.c (revision 100384) @@ -1,289 +1,289 @@ /* * Copyright (c) 1993, David Greenman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include "opt_kstack_pages.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int exec_aout_imgact(struct image_params *imgp); struct sysentvec aout_sysvec = { SYS_MAXSYSCALL, sysent, 0, 0, 0, 0, 0, 0, 0, sendsig, sigcode, &szsigcode, 0, "FreeBSD a.out", aout_coredump, NULL, MINSIGSTKSZ }; static int exec_aout_imgact(imgp) struct image_params *imgp; { const struct exec *a_out = (const struct exec *) imgp->image_header; struct vmspace *vmspace; struct vnode *vp; vm_map_t map; vm_object_t object; vm_offset_t text_end, data_end; unsigned long virtual_offset; unsigned long file_offset; unsigned long bss_size; int error; GIANT_REQUIRED; /* * Linux and *BSD binaries look very much alike, * only the machine id is different: * 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI. * NetBSD is in network byte order.. ugh. */ if (((a_out->a_magic >> 16) & 0xff) != 0x86 && ((a_out->a_magic >> 16) & 0xff) != 0 && ((((int)ntohl(a_out->a_magic)) >> 16) & 0xff) != 0x86) return -1; /* * Set file/virtual offset based on a.out variant. * We do two cases: host byte order and network byte order * (for NetBSD compatibility) */ switch ((int)(a_out->a_magic & 0xffff)) { case ZMAGIC: virtual_offset = 0; if (a_out->a_text) { file_offset = PAGE_SIZE; } else { /* Bill's "screwball mode" */ file_offset = 0; } break; case QMAGIC: virtual_offset = PAGE_SIZE; file_offset = 0; /* Pass PS_STRINGS for BSD/OS binaries only. */ if (N_GETMID(*a_out) == MID_ZERO) imgp->ps_strings = PS_STRINGS; break; default: /* NetBSD compatibility */ switch ((int)(ntohl(a_out->a_magic) & 0xffff)) { case ZMAGIC: case QMAGIC: virtual_offset = PAGE_SIZE; file_offset = 0; break; default: return (-1); } } bss_size = roundup(a_out->a_bss, PAGE_SIZE); /* * Check various fields in header for validity/bounds. */ if (/* entry point must lay with text region */ a_out->a_entry < virtual_offset || a_out->a_entry >= virtual_offset + a_out->a_text || /* text and data size must each be page rounded */ a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) return (-1); /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > imgp->attr->va_size) return (EFAULT); /* * text/data/bss must not exceed limits */ mtx_assert(&Giant, MA_OWNED); if (/* text can't exceed maximum text size */ a_out->a_text > maxtsiz || /* data + bss can't exceed rlimit */ a_out->a_data + bss_size > imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) return (ENOMEM); /* copy in arguments and/or environment from old process */ error = exec_extract_strings(imgp); if (error) return (error); /* * Destroy old process VM and create a new one (with a new stack) */ - exec_new_vmspace(imgp); + exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); /* * The vm space can be changed by exec_new_vmspace */ vmspace = imgp->proc->p_vmspace; vp = imgp->vp; object = imgp->object; map = &vmspace->vm_map; vm_map_lock(map); vm_object_reference(object); text_end = virtual_offset + a_out->a_text; error = vm_map_insert(map, object, file_offset, virtual_offset, text_end, VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT); if (error) { vm_map_unlock(map); return (error); } data_end = text_end + a_out->a_data; if (a_out->a_data) { vm_object_reference(object); error = vm_map_insert(map, object, file_offset + a_out->a_text, text_end, data_end, VM_PROT_ALL, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT); if (error) { vm_map_unlock(map); return (error); } } if (bss_size) { error = vm_map_insert(map, NULL, 0, data_end, data_end + bss_size, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) { vm_map_unlock(map); return (error); } } vm_map_unlock(map); /* Fill in process VM information */ vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT; vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t) (uintptr_t) virtual_offset; vmspace->vm_daddr = (caddr_t) (uintptr_t) (virtual_offset + a_out->a_text); /* Fill in image_params */ imgp->interpreted = 0; imgp->entry_addr = a_out->a_entry; imgp->proc->p_sysent = &aout_sysvec; /* Indicate that this file should not be modified */ imgp->vp->v_flag |= VTEXT; return (0); } /* * Dump core, into a file named as described in the comments for * expand_name(), unless the process was setuid/setgid. */ int aout_coredump(td, vp, limit) register struct thread *td; register struct vnode *vp; off_t limit; { struct proc *p = td->td_proc; register struct ucred *cred = td->td_ucred; register struct vmspace *vm = p->p_vmspace; int error; if (ctob((UAREA_PAGES + KSTACK_PAGES) + vm->vm_dsize + vm->vm_ssize) >= limit) return (EFAULT); PROC_LOCK(p); fill_kinfo_proc(p, &p->p_uarea->u_kproc); PROC_UNLOCK(p); error = cpu_coredump(td, vp, cred); if (error == 0) error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr, (int)ctob(vm->vm_dsize), (off_t)ctob(UAREA_PAGES + KSTACK_PAGES), UIO_USERSPACE, IO_UNIT | IO_DIRECT, cred, (int *) NULL, td); if (error == 0) error = vn_rdwr_inchunks(UIO_WRITE, vp, (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)), round_page(ctob(vm->vm_ssize)), (off_t)ctob(UAREA_PAGES + KSTACK_PAGES) + ctob(vm->vm_dsize), UIO_USERSPACE, IO_UNIT | IO_DIRECT, cred, (int *) NULL, td); return (error); } /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw aout_execsw = { exec_aout_imgact, "a.out" }; EXEC_SET(aout, aout_execsw); Index: head/sys/kern/imgact_elf.c =================================================================== --- head/sys/kern/imgact_elf.c (revision 100383) +++ head/sys/kern/imgact_elf.c (revision 100384) @@ -1,1082 +1,1253 @@ /*- * Copyright (c) 2000 David O'Brien * Copyright (c) 1995-1996 Søren Schmidt * Copyright (c) 1996 Peter Wemm * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define OLD_EI_BRAND 8 __ElfType(Brandinfo); __ElfType(Auxargs); -static int elf_check_header(const Elf_Ehdr *hdr); -static int elf_freebsd_fixup(register_t **stack_base, - struct image_params *imgp); -static int elf_load_file(struct proc *p, const char *file, u_long *addr, - u_long *entry); -static int elf_load_section(struct proc *p, +static int __elfN(check_header)(const Elf_Ehdr *hdr); +static int __elfN(load_file)(struct proc *p, const char *file, u_long *addr, + u_long *entry, size_t pagesize); +static int __elfN(load_section)(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_object_t object, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, - vm_prot_t prot); -static int exec_elf_imgact(struct image_params *imgp); + vm_prot_t prot, size_t pagesize); +static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp); static int elf_trace = 0; -SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, ""); +#if __ELF_WORD_SIZE == 32 +SYSCTL_INT(_debug, OID_AUTO, elf32_trace, CTLFLAG_RW, &elf_trace, 0, ""); +#else +SYSCTL_INT(_debug, OID_AUTO, elf64_trace, CTLFLAG_RW, &elf_trace, 0, ""); +#endif -struct sysentvec elf_freebsd_sysvec = { - SYS_MAXSYSCALL, - sysent, - 0, - 0, - 0, - 0, - 0, - 0, - elf_freebsd_fixup, - sendsig, - sigcode, - &szsigcode, - 0, - "FreeBSD ELF", - elf_coredump, - NULL, - MINSIGSTKSZ -}; +static Elf_Brandinfo *elf_brand_list[MAX_BRANDS]; -static Elf_Brandinfo freebsd_brand_info = { - ELFOSABI_FREEBSD, - "FreeBSD", - "", - "/usr/libexec/ld-elf.so.1", - &elf_freebsd_sysvec - }; -static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = { - &freebsd_brand_info, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL - }; - int -elf_insert_brand_entry(Elf_Brandinfo *entry) +__elfN(insert_brand_entry)(Elf_Brandinfo *entry) { int i; - for (i=1; ip_sysent == entry->sysvec) { rval = TRUE; break; } } sx_sunlock(&allproc_lock); return (rval); } static int -elf_check_header(const Elf_Ehdr *hdr) +__elfN(check_header)(const Elf_Ehdr *hdr) { + int i; + if (!IS_ELF(*hdr) || hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || hdr->e_ident[EI_DATA] != ELF_TARG_DATA || hdr->e_ident[EI_VERSION] != EV_CURRENT) return ENOEXEC; - if (!ELF_MACHINE_OK(hdr->e_machine)) + /* + * Make sure we have at least one brand for this machine. + */ + + for (i=0; imachine == hdr->e_machine) + break; + } + if (i == MAX_BRANDS) return ENOEXEC; if (hdr->e_version != ELF_TARG_VER) return ENOEXEC; - + return 0; } static int -elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_object_t object, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) +__elfN(map_partial)(vm_map_t map, vm_object_t object, vm_ooffset_t offset, + vm_offset_t start, vm_offset_t end, vm_prot_t prot, + vm_prot_t max) { + int error, rv; + vm_offset_t off; + vm_offset_t data_buf = 0; + + /* + * Create the page if it doesn't exist yet. Ignore errors. + */ + vm_map_lock(map); + vm_map_insert(map, NULL, 0, trunc_page(start), round_page(end), + max, max, 0); + vm_map_unlock(map); + + /* + * Find the page from the underlying object. + */ + if (object) { + vm_object_reference(object); + rv = vm_map_find(exec_map, + object, + trunc_page(offset), + &data_buf, + PAGE_SIZE, + TRUE, + VM_PROT_READ, + VM_PROT_ALL, + MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); + if (rv != KERN_SUCCESS) { + vm_object_deallocate(object); + return rv; + } + + off = offset - trunc_page(offset); + error = copyout((caddr_t)data_buf+off, (caddr_t)start, end - start); + vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE); + if (error) { + return KERN_FAILURE; + } + } + + return KERN_SUCCESS; +} + +static int +__elfN(map_insert)(vm_map_t map, vm_object_t object, vm_ooffset_t offset, + vm_offset_t start, vm_offset_t end, vm_prot_t prot, + vm_prot_t max, int cow) +{ + int rv; + + if (start != trunc_page(start)) { + rv = __elfN(map_partial)(map, object, offset, + start, round_page(start), prot, max); + if (rv) + return rv; + offset += round_page(start) - start; + start = round_page(start); + } + if (end != round_page(end)) { + rv = __elfN(map_partial)(map, object, + offset + trunc_page(end) - start, + trunc_page(end), end, prot, max); + if (rv) + return rv; + end = trunc_page(end); + } + if (end > start) { + if (offset & PAGE_MASK) { + vm_offset_t data_buf, off; + vm_size_t sz; + int error; + + /* + * The mapping is not page aligned. This means we have + * to copy the data. Sigh. + */ + rv = vm_map_find(map, 0, 0, + &start, end - start, + FALSE, prot, max, 0); + if (rv) + return rv; + while (start < end) { + vm_object_reference(object); + rv = vm_map_find(exec_map, + object, + trunc_page(offset), + &data_buf, + 2*PAGE_SIZE, + TRUE, + VM_PROT_READ, + VM_PROT_ALL, + (MAP_COPY_ON_WRITE + | MAP_PREFAULT_PARTIAL)); + if (rv != KERN_SUCCESS) { + vm_object_deallocate(object); + return rv; + } + off = offset - trunc_page(offset); + sz = end - start; + if (sz > PAGE_SIZE) + sz = PAGE_SIZE; + error = copyout((caddr_t)data_buf+off, + (caddr_t)start, sz); + vm_map_remove(exec_map, data_buf, + data_buf + 2*PAGE_SIZE); + if (error) { + return KERN_FAILURE; + } + start += sz; + } + rv = KERN_SUCCESS; + } else { + vm_map_lock(map); + rv = vm_map_insert(map, object, offset, start, end, + prot, max, cow); + vm_map_unlock(map); + } + return rv; + } else { + return KERN_SUCCESS; + } +} + +static int +__elfN(load_section)(struct proc *p, struct vmspace *vmspace, + struct vnode *vp, vm_object_t object, vm_offset_t offset, + caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot, + size_t pagesize) +{ size_t map_len; vm_offset_t map_addr; int error, rv; size_t copy_len; vm_offset_t file_addr; vm_offset_t data_buf = 0; GIANT_REQUIRED; error = 0; /* * It's necessary to fail if the filsz + offset taken from the * header is greater than the actual file pager object's size. * If we were to allow this, then the vm_map_find() below would * walk right off the end of the file object and into the ether. * * While I'm here, might as well check for something else that * is invalid: filsz cannot be greater than memsz. */ if ((off_t)filsz + offset > object->un_pager.vnp.vnp_size || filsz > memsz) { uprintf("elf_load_section: truncated ELF file\n"); return (ENOEXEC); } - map_addr = trunc_page((vm_offset_t)vmaddr); - file_addr = trunc_page(offset); +#define trunc_page_ps(va, ps) ((va) & ~(ps - 1)) +#define round_page_ps(va, ps) (((va) + (ps - 1)) & ~(ps - 1)) + map_addr = trunc_page_ps((vm_offset_t)vmaddr, pagesize); + file_addr = trunc_page_ps(offset, pagesize); + /* * We have two choices. We can either clear the data in the last page * of an oversized mapping, or we can start the anon mapping a page * early and copy the initialized data into that first page. We * choose the second.. */ if (memsz > filsz) - map_len = trunc_page(offset+filsz) - file_addr; + map_len = trunc_page_ps(offset+filsz, pagesize) - file_addr; else - map_len = round_page(offset+filsz) - file_addr; + map_len = round_page_ps(offset+filsz, pagesize) - file_addr; if (map_len != 0) { vm_object_reference(object); - vm_map_lock(&vmspace->vm_map); - rv = vm_map_insert(&vmspace->vm_map, + rv = __elfN(map_insert)(&vmspace->vm_map, object, file_addr, /* file offset */ map_addr, /* virtual start */ map_addr + map_len,/* virtual end */ prot, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT); - vm_map_unlock(&vmspace->vm_map); if (rv != KERN_SUCCESS) { vm_object_deallocate(object); return EINVAL; } /* we can stop now if we've covered it all */ if (memsz == filsz) { return 0; } } /* * We have to get the remaining bit of the file into the first part * of the oversized map segment. This is normally because the .data * segment in the file is extended to provide bss. It's a neat idea * to try and save a page, but it's a pain in the behind to implement. */ - copy_len = (offset + filsz) - trunc_page(offset + filsz); - map_addr = trunc_page((vm_offset_t)vmaddr + filsz); - map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr; + copy_len = (offset + filsz) - trunc_page_ps(offset + filsz, pagesize); + map_addr = trunc_page_ps((vm_offset_t)vmaddr + filsz, pagesize); + map_len = round_page_ps((vm_offset_t)vmaddr + memsz, pagesize) - map_addr; /* This had damn well better be true! */ - if (map_len != 0) { - vm_map_lock(&vmspace->vm_map); - rv = vm_map_insert(&vmspace->vm_map, NULL, 0, - map_addr, map_addr + map_len, - VM_PROT_ALL, VM_PROT_ALL, 0); - vm_map_unlock(&vmspace->vm_map); + if (map_len != 0) { + rv = __elfN(map_insert)(&vmspace->vm_map, NULL, 0, + map_addr, map_addr + map_len, + VM_PROT_ALL, VM_PROT_ALL, 0); if (rv != KERN_SUCCESS) { - return EINVAL; + return EINVAL; } } if (copy_len != 0) { + vm_offset_t off; vm_object_reference(object); rv = vm_map_find(exec_map, - object, + object, trunc_page(offset + filsz), &data_buf, PAGE_SIZE, TRUE, VM_PROT_READ, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); if (rv != KERN_SUCCESS) { vm_object_deallocate(object); return EINVAL; } /* send the page fragment to user space */ - error = copyout((caddr_t)data_buf, (caddr_t)map_addr, copy_len); + off = trunc_page_ps(offset + filsz, pagesize) + - trunc_page(offset + filsz); + error = copyout((caddr_t)data_buf+off, (caddr_t)map_addr, + copy_len); vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE); if (error) { return (error); } } /* - * set it to the specified protection + * set it to the specified protection. + * XXX had better undo the damage from pasting over the cracks here! */ - vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot, - FALSE); + vm_map_protect(&vmspace->vm_map, trunc_page(map_addr), + round_page(map_addr + map_len), prot, FALSE); return error; } /* * Load the file "file" into memory. It may be either a shared object * or an executable. * * The "addr" reference parameter is in/out. On entry, it specifies * the address where a shared object should be loaded. If the file is * an executable, this value is ignored. On exit, "addr" specifies * where the file was actually loaded. * * The "entry" reference parameter is out only. On exit, it specifies * the entry point for the loaded file. */ static int -elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry) +__elfN(load_file)(struct proc *p, const char *file, u_long *addr, + u_long *entry, size_t pagesize) { struct { struct nameidata nd; struct vattr attr; struct image_params image_params; } *tempdata; const Elf_Ehdr *hdr = NULL; const Elf_Phdr *phdr = NULL; struct nameidata *nd; struct vmspace *vmspace = p->p_vmspace; struct vattr *attr; struct image_params *imgp; vm_prot_t prot; u_long rbase; u_long base_addr = 0; int error, i, numsegs; if (curthread->td_proc != p) panic("elf_load_file - thread"); /* XXXKSE DIAGNOSTIC */ tempdata = malloc(sizeof(*tempdata), M_TEMP, M_WAITOK); nd = &tempdata->nd; attr = &tempdata->attr; imgp = &tempdata->image_params; /* * Initialize part of the common data */ imgp->proc = p; imgp->uap = NULL; imgp->attr = attr; imgp->firstpage = NULL; imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE); imgp->object = NULL; if (imgp->image_header == NULL) { nd->ni_vp = NULL; error = ENOMEM; goto fail; } /* XXXKSE */ - NDINIT(nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, curthread); - + NDINIT(nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, curthread); + if ((error = namei(nd)) != 0) { nd->ni_vp = NULL; goto fail; } NDFREE(nd, NDF_ONLY_PNBUF); imgp->vp = nd->ni_vp; /* * Check permissions, modes, uid, etc on the file, and "open" it. */ error = exec_check_permissions(imgp); if (error) { VOP_UNLOCK(nd->ni_vp, 0, curthread); /* XXXKSE */ goto fail; } error = exec_map_first_page(imgp); /* * Also make certain that the interpreter stays the same, so set * its VTEXT flag, too. */ if (error == 0) nd->ni_vp->v_flag |= VTEXT; VOP_GETVOBJECT(nd->ni_vp, &imgp->object); vm_object_reference(imgp->object); VOP_UNLOCK(nd->ni_vp, 0, curthread); /* XXXKSE */ if (error) - goto fail; + goto fail; hdr = (const Elf_Ehdr *)imgp->image_header; - if ((error = elf_check_header(hdr)) != 0) + if ((error = __elfN(check_header)(hdr)) != 0) goto fail; if (hdr->e_type == ET_DYN) rbase = *addr; else if (hdr->e_type == ET_EXEC) rbase = 0; else { error = ENOEXEC; goto fail; } /* Only support headers that fit within first page for now */ if ((hdr->e_phoff > PAGE_SIZE) || (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) { error = ENOEXEC; goto fail; } phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); for (i = 0, numsegs = 0; i < hdr->e_phnum; i++) { if (phdr[i].p_type == PT_LOAD) { /* Loadable segment */ prot = 0; if (phdr[i].p_flags & PF_X) prot |= VM_PROT_EXECUTE; if (phdr[i].p_flags & PF_W) prot |= VM_PROT_WRITE; if (phdr[i].p_flags & PF_R) prot |= VM_PROT_READ; - if ((error = elf_load_section(p, vmspace, nd->ni_vp, - imgp->object, - phdr[i].p_offset, - (caddr_t)phdr[i].p_vaddr + - rbase, - phdr[i].p_memsz, - phdr[i].p_filesz, prot)) != 0) + if ((error = __elfN(load_section) + (p, vmspace, nd->ni_vp, + imgp->object, + phdr[i].p_offset, + (caddr_t)(uintptr_t)phdr[i].p_vaddr + + rbase, + phdr[i].p_memsz, + phdr[i].p_filesz, prot, pagesize)) != 0) goto fail; /* * Establish the base address if this is the * first segment. */ if (numsegs == 0) base_addr = trunc_page(phdr[i].p_vaddr + rbase); numsegs++; } } *addr = base_addr; *entry=(unsigned long)hdr->e_entry + rbase; fail: if (imgp->firstpage) exec_unmap_first_page(imgp); if (imgp->image_header) kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header, PAGE_SIZE); if (imgp->object) vm_object_deallocate(imgp->object); if (nd->ni_vp) vrele(nd->ni_vp); free(tempdata, M_TEMP); return error; } -/* - * non static, as it can be overridden by start_init() - */ -#ifdef __ia64__ -int fallback_elf_brand = ELFOSABI_FREEBSD; -#else -int fallback_elf_brand = -1; -#endif -SYSCTL_INT(_kern, OID_AUTO, fallback_elf_brand, CTLFLAG_RW, - &fallback_elf_brand, -1, - "ELF brand of last resort"); +extern int fallback_elf_brand; static int -exec_elf_imgact(struct image_params *imgp) +__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) { const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header; const Elf_Phdr *phdr; Elf_Auxargs *elf_auxargs = NULL; struct vmspace *vmspace; vm_prot_t prot; u_long text_size = 0, data_size = 0; u_long text_addr = 0, data_addr = 0; u_long addr, entry = 0, proghdr = 0; + vm_offset_t maxuser, usrstack, pagesize; int error, i; const char *interp = NULL; Elf_Brandinfo *brand_info; char *path; GIANT_REQUIRED; /* * Do we have a valid ELF header ? */ - if (elf_check_header(hdr) != 0 || hdr->e_type != ET_EXEC) + if (__elfN(check_header)(hdr) != 0 || hdr->e_type != ET_EXEC) return -1; /* * From here on down, we return an errno, not -1, as we've * detected an ELF file. */ if ((hdr->e_phoff > PAGE_SIZE) || (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) { /* Only support headers in first page for now */ return ENOEXEC; } phdr = (const Elf_Phdr*)(imgp->image_header + hdr->e_phoff); - + /* * From this point on, we may have resources that need to be freed. */ /* * Yeah, I'm paranoid. There is every reason in the world to get * VTEXT now since from here on out, there are places we can have * a context switch. Better safe than sorry; I really don't want * the file to change while it's being loaded. */ mtx_lock(&imgp->vp->v_interlock); imgp->vp->v_flag |= VTEXT; mtx_unlock(&imgp->vp->v_interlock); if ((error = exec_extract_strings(imgp)) != 0) goto fail; - exec_new_vmspace(imgp); + /* + * Tentatively identify the brand based on the machine so that + * we can figure out VM ranges and page sizes. + */ + brand_info = NULL; + for (i = 0; i < MAX_BRANDS; i++) { + Elf_Brandinfo *bi = elf_brand_list[i]; + if (bi != NULL && + hdr->e_machine == bi->machine && + (hdr->e_ident[EI_OSABI] == bi->brand + || 0 == + strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND], + bi->compat_3_brand, strlen(bi->compat_3_brand)))) { + brand_info = bi; + break; + } + } + + pagesize = PAGE_SIZE; + maxuser = VM_MAXUSER_ADDRESS; + usrstack = USRSTACK; + if (brand_info) { + if (brand_info->sysvec->sv_pagesize) + pagesize = brand_info->sysvec->sv_pagesize; + if (brand_info->sysvec->sv_maxuser) + maxuser = brand_info->sysvec->sv_maxuser; + if (brand_info->sysvec->sv_usrstack) + usrstack = brand_info->sysvec->sv_usrstack; + } + + exec_new_vmspace(imgp, VM_MIN_ADDRESS, maxuser, usrstack); + vmspace = imgp->proc->p_vmspace; for (i = 0; i < hdr->e_phnum; i++) { switch(phdr[i].p_type) { case PT_LOAD: /* Loadable segment */ prot = 0; if (phdr[i].p_flags & PF_X) prot |= VM_PROT_EXECUTE; if (phdr[i].p_flags & PF_W) prot |= VM_PROT_WRITE; if (phdr[i].p_flags & PF_R) prot |= VM_PROT_READ; - if ((error = elf_load_section(imgp->proc, - vmspace, imgp->vp, - imgp->object, - phdr[i].p_offset, - (caddr_t)phdr[i].p_vaddr, - phdr[i].p_memsz, - phdr[i].p_filesz, prot)) != 0) +#if defined(__ia64__) && __ELF_WORD_SIZE == 32 && defined(IA32_ME_HARDER) + /* + * Some x86 binaries assume read == executable, + * notably the M3 runtime and therefore cvsup + */ + if (prot & VM_PROT_READ) + prot |= VM_PROT_EXECUTE; +#endif + + if ((error = __elfN(load_section) + (imgp->proc, + vmspace, imgp->vp, + imgp->object, + phdr[i].p_offset, + (caddr_t)(uintptr_t)phdr[i].p_vaddr, + phdr[i].p_memsz, + phdr[i].p_filesz, prot, pagesize)) != 0) goto fail; /* * Is this .text or .data ?? * * We only handle one each of those yet XXX */ if (hdr->e_entry >= phdr[i].p_vaddr && hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { text_addr = trunc_page(phdr[i].p_vaddr); text_size = round_page(phdr[i].p_memsz + phdr[i].p_vaddr - text_addr); entry = (u_long)hdr->e_entry; } else { data_addr = trunc_page(phdr[i].p_vaddr); data_size = round_page(phdr[i].p_memsz + phdr[i].p_vaddr - data_addr); } break; case PT_INTERP: /* Path to interpreter */ if (phdr[i].p_filesz > MAXPATHLEN || phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) { error = ENOEXEC; goto fail; } interp = imgp->image_header + phdr[i].p_offset; break; case PT_PHDR: /* Program header table info */ proghdr = phdr[i].p_vaddr; break; default: break; } } vmspace->vm_tsize = text_size >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr; vmspace->vm_dsize = data_size >> PAGE_SHIFT; vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr; addr = ELF_RTLD_ADDR(vmspace); imgp->entry_addr = entry; brand_info = NULL; /* We support three types of branding -- (1) the ELF EI_OSABI field * that SCO added to the ELF spec, (2) FreeBSD 3.x's traditional string * branding w/in the ELF header, and (3) path of the `interp_path' * field. We should also look for an ".note.ABI-tag" ELF section now * in all Linux ELF binaries, FreeBSD 4.1+, and some NetBSD ones. */ /* If the executable has a brand, search for it in the brand list. */ if (brand_info == NULL) { for (i = 0; i < MAX_BRANDS; i++) { Elf_Brandinfo *bi = elf_brand_list[i]; - if (bi != NULL && + if (bi != NULL && + hdr->e_machine == bi->machine && (hdr->e_ident[EI_OSABI] == bi->brand - || 0 == - strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND], + || 0 == + strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND], bi->compat_3_brand, strlen(bi->compat_3_brand)))) { brand_info = bi; break; } } } /* Lacking a known brand, search for a recognized interpreter. */ if (brand_info == NULL && interp != NULL) { for (i = 0; i < MAX_BRANDS; i++) { Elf_Brandinfo *bi = elf_brand_list[i]; if (bi != NULL && + hdr->e_machine == bi->machine && strcmp(interp, bi->interp_path) == 0) { brand_info = bi; break; } } } /* Lacking a recognized interpreter, try the default brand */ if (brand_info == NULL) { for (i = 0; i < MAX_BRANDS; i++) { Elf_Brandinfo *bi = elf_brand_list[i]; - if (bi != NULL && fallback_elf_brand == bi->brand) { + if (bi != NULL && + hdr->e_machine == bi->machine && + fallback_elf_brand == bi->brand) { brand_info = bi; break; } } } if (brand_info == NULL) { uprintf("ELF binary type \"%u\" not known.\n", hdr->e_ident[EI_OSABI]); error = ENOEXEC; goto fail; } imgp->proc->p_sysent = brand_info->sysvec; if (interp != NULL) { path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - snprintf(path, MAXPATHLEN, "%s%s", + snprintf(path, MAXPATHLEN, "%s%s", brand_info->emul_path, interp); - if ((error = elf_load_file(imgp->proc, path, &addr, - &imgp->entry_addr)) != 0) { - if ((error = elf_load_file(imgp->proc, interp, &addr, - &imgp->entry_addr)) != 0) { - uprintf("ELF interpreter %s not found\n", path); + if ((error = __elfN(load_file)(imgp->proc, path, &addr, + &imgp->entry_addr, + pagesize)) != 0) { + if ((error = __elfN(load_file) + (imgp->proc, interp, &addr, + &imgp->entry_addr, pagesize)) != 0) { + uprintf("ELF interpreter %s not found\n", path); free(path, M_TEMP); goto fail; } - } + } free(path, M_TEMP); } /* * Construct auxargs table (used by the fixup routine) */ elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK); elf_auxargs->execfd = -1; elf_auxargs->phdr = proghdr; elf_auxargs->phent = hdr->e_phentsize; elf_auxargs->phnum = hdr->e_phnum; elf_auxargs->pagesz = PAGE_SIZE; elf_auxargs->base = addr; elf_auxargs->flags = 0; elf_auxargs->entry = entry; elf_auxargs->trace = elf_trace; imgp->auxargs = elf_auxargs; imgp->interpreted = 0; fail: return error; } -static int -elf_freebsd_fixup(register_t **stack_base, struct image_params *imgp) +#if __ELF_WORD_SIZE == 32 +#define suword suword32 +#define stacktype u_int32_t +#else +#define suword suword64 +#define stacktype u_int64_t +#endif + +int +__elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp) { Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; - register_t *pos; + stacktype *base; + stacktype *pos; - pos = *stack_base + (imgp->argc + imgp->envc + 2); + base = (stacktype *)*stack_base; + pos = base + (imgp->argc + imgp->envc + 2); if (args->trace) { AUXARGS_ENTRY(pos, AT_DEBUG, 1); } if (args->execfd != -1) { AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); } AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; - (*stack_base)--; - suword(*stack_base, (long) imgp->argc); + base--; + suword(base, (long) imgp->argc); + *stack_base = (register_t *)base; return 0; -} +} /* * Code for generating ELF core dumps. */ typedef void (*segment_callback)(vm_map_entry_t, void *); /* Closure for cb_put_phdr(). */ struct phdr_closure { Elf_Phdr *phdr; /* Program header to fill in */ Elf_Off offset; /* Offset of segment in core file */ }; /* Closure for cb_size_segment(). */ struct sseg_closure { int count; /* Count of writable segments. */ size_t size; /* Total size of all writable segments. */ }; static void cb_put_phdr(vm_map_entry_t, void *); static void cb_size_segment(vm_map_entry_t, void *); static void each_writable_segment(struct proc *, segment_callback, void *); -static int elf_corehdr(struct thread *, struct vnode *, struct ucred *, +static int __elfN(corehdr)(struct thread *, struct vnode *, struct ucred *, int, void *, size_t); -static void elf_puthdr(struct proc *, void *, size_t *, +static void __elfN(puthdr)(struct proc *, void *, size_t *, const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int); -static void elf_putnote(void *, size_t *, const char *, int, +static void __elfN(putnote)(void *, size_t *, const char *, int, const void *, size_t); extern int osreldate; int -elf_coredump(td, vp, limit) +__elfN(coredump)(td, vp, limit) struct thread *td; register struct vnode *vp; off_t limit; { register struct proc *p = td->td_proc; register struct ucred *cred = td->td_ucred; int error = 0; struct sseg_closure seginfo; void *hdr; size_t hdrsize; /* Size the program segments. */ seginfo.count = 0; seginfo.size = 0; each_writable_segment(p, cb_size_segment, &seginfo); /* * Calculate the size of the core file header area by making * a dry run of generating it. Nothing is written, but the * size is calculated. */ hdrsize = 0; - elf_puthdr((struct proc *)NULL, (void *)NULL, &hdrsize, + __elfN(puthdr)((struct proc *)NULL, (void *)NULL, &hdrsize, (const prstatus_t *)NULL, (const prfpregset_t *)NULL, (const prpsinfo_t *)NULL, seginfo.count); if (hdrsize + seginfo.size >= limit) return (EFAULT); /* * Allocate memory for building the header, fill it up, * and write it out. */ hdr = malloc(hdrsize, M_TEMP, M_WAITOK); if (hdr == NULL) { return EINVAL; } - error = elf_corehdr(td, vp, cred, seginfo.count, hdr, hdrsize); + error = __elfN(corehdr)(td, vp, cred, seginfo.count, hdr, hdrsize); /* Write the contents of all of the writable segments. */ if (error == 0) { Elf_Phdr *php; off_t offset; int i; php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; offset = hdrsize; for (i = 0; i < seginfo.count; i++) { - error = vn_rdwr_inchunks(UIO_WRITE, vp, - (caddr_t)php->p_vaddr, + error = vn_rdwr_inchunks(UIO_WRITE, vp, + (caddr_t)(uintptr_t)php->p_vaddr, php->p_filesz, offset, UIO_USERSPACE, IO_UNIT | IO_DIRECT, cred, (int *)NULL, curthread); /* XXXKSE */ if (error != 0) break; offset += php->p_filesz; php++; } } free(hdr, M_TEMP); - + return error; } /* * A callback for each_writable_segment() to write out the segment's * program header entry. */ static void cb_put_phdr(entry, closure) vm_map_entry_t entry; void *closure; { struct phdr_closure *phc = (struct phdr_closure *)closure; Elf_Phdr *phdr = phc->phdr; phc->offset = round_page(phc->offset); phdr->p_type = PT_LOAD; phdr->p_offset = phc->offset; phdr->p_vaddr = entry->start; phdr->p_paddr = 0; phdr->p_filesz = phdr->p_memsz = entry->end - entry->start; phdr->p_align = PAGE_SIZE; phdr->p_flags = 0; if (entry->protection & VM_PROT_READ) phdr->p_flags |= PF_R; if (entry->protection & VM_PROT_WRITE) phdr->p_flags |= PF_W; if (entry->protection & VM_PROT_EXECUTE) phdr->p_flags |= PF_X; phc->offset += phdr->p_filesz; phc->phdr++; } /* * A callback for each_writable_segment() to gather information about * the number of segments and their total size. */ static void cb_size_segment(entry, closure) vm_map_entry_t entry; void *closure; { struct sseg_closure *ssc = (struct sseg_closure *)closure; ssc->count++; ssc->size += entry->end - entry->start; } /* * For each writable segment in the process's memory map, call the given * function with a pointer to the map entry and some arbitrary * caller-supplied data. */ static void each_writable_segment(p, func, closure) struct proc *p; segment_callback func; void *closure; { vm_map_t map = &p->p_vmspace->vm_map; vm_map_entry_t entry; for (entry = map->header.next; entry != &map->header; entry = entry->next) { vm_object_t obj; if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) || (entry->protection & (VM_PROT_READ|VM_PROT_WRITE)) != (VM_PROT_READ|VM_PROT_WRITE)) continue; /* ** Dont include memory segment in the coredump if ** MAP_NOCORE is set in mmap(2) or MADV_NOCORE in ** madvise(2). */ if (entry->eflags & MAP_ENTRY_NOCOREDUMP) continue; if ((obj = entry->object.vm_object) == NULL) continue; /* Find the deepest backing object. */ while (obj->backing_object != NULL) obj = obj->backing_object; /* Ignore memory-mapped devices and such things. */ if (obj->type != OBJT_DEFAULT && obj->type != OBJT_SWAP && obj->type != OBJT_VNODE) continue; (*func)(entry, closure); } } /* * Write the core file header to the file, including padding up to * the page boundary. */ static int -elf_corehdr(td, vp, cred, numsegs, hdr, hdrsize) +__elfN(corehdr)(td, vp, cred, numsegs, hdr, hdrsize) struct thread *td; struct vnode *vp; struct ucred *cred; int numsegs; size_t hdrsize; void *hdr; { struct { prstatus_t status; prfpregset_t fpregset; prpsinfo_t psinfo; } *tempdata; struct proc *p = td->td_proc; size_t off; prstatus_t *status; prfpregset_t *fpregset; prpsinfo_t *psinfo; tempdata = malloc(sizeof(*tempdata), M_TEMP, M_ZERO | M_WAITOK); status = &tempdata->status; fpregset = &tempdata->fpregset; psinfo = &tempdata->psinfo; /* Gather the information for the header. */ status->pr_version = PRSTATUS_VERSION; status->pr_statussz = sizeof(prstatus_t); status->pr_gregsetsz = sizeof(gregset_t); status->pr_fpregsetsz = sizeof(fpregset_t); status->pr_osreldate = osreldate; status->pr_cursig = p->p_sig; status->pr_pid = p->p_pid; fill_regs(td, &status->pr_reg); fill_fpregs(td, fpregset); psinfo->pr_version = PRPSINFO_VERSION; psinfo->pr_psinfosz = sizeof(prpsinfo_t); strncpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname) - 1); /* XXX - We don't fill in the command line arguments properly yet. */ strncpy(psinfo->pr_psargs, p->p_comm, PRARGSZ); /* Fill in the header. */ bzero(hdr, hdrsize); off = 0; - elf_puthdr(p, hdr, &off, status, fpregset, psinfo, numsegs); + __elfN(puthdr)(p, hdr, &off, status, fpregset, psinfo, numsegs); free(tempdata, M_TEMP); /* Write it to the core file. */ return vn_rdwr_inchunks(UIO_WRITE, vp, hdr, hdrsize, (off_t)0, UIO_SYSSPACE, IO_UNIT | IO_DIRECT, cred, NULL, td); /* XXXKSE */ } static void -elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status, +__elfN(puthdr)(struct proc *p, void *dst, size_t *off, const prstatus_t *status, const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs) { size_t ehoff; size_t phoff; size_t noteoff; size_t notesz; ehoff = *off; *off += sizeof(Elf_Ehdr); phoff = *off; *off += (numsegs + 1) * sizeof(Elf_Phdr); noteoff = *off; - elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status, + __elfN(putnote)(dst, off, "FreeBSD", NT_PRSTATUS, status, sizeof *status); - elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset, + __elfN(putnote)(dst, off, "FreeBSD", NT_FPREGSET, fpregset, sizeof *fpregset); - elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo, + __elfN(putnote)(dst, off, "FreeBSD", NT_PRPSINFO, psinfo, sizeof *psinfo); notesz = *off - noteoff; /* Align up to a page boundary for the program segments. */ *off = round_page(*off); if (dst != NULL) { Elf_Ehdr *ehdr; Elf_Phdr *phdr; struct phdr_closure phc; /* * Fill in the ELF header. */ ehdr = (Elf_Ehdr *)((char *)dst + ehoff); ehdr->e_ident[EI_MAG0] = ELFMAG0; ehdr->e_ident[EI_MAG1] = ELFMAG1; ehdr->e_ident[EI_MAG2] = ELFMAG2; ehdr->e_ident[EI_MAG3] = ELFMAG3; ehdr->e_ident[EI_CLASS] = ELF_CLASS; ehdr->e_ident[EI_DATA] = ELF_DATA; ehdr->e_ident[EI_VERSION] = EV_CURRENT; ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; ehdr->e_ident[EI_ABIVERSION] = 0; ehdr->e_ident[EI_PAD] = 0; ehdr->e_type = ET_CORE; ehdr->e_machine = ELF_ARCH; ehdr->e_version = EV_CURRENT; ehdr->e_entry = 0; ehdr->e_phoff = phoff; ehdr->e_flags = 0; ehdr->e_ehsize = sizeof(Elf_Ehdr); ehdr->e_phentsize = sizeof(Elf_Phdr); ehdr->e_phnum = numsegs + 1; ehdr->e_shentsize = sizeof(Elf_Shdr); ehdr->e_shnum = 0; ehdr->e_shstrndx = SHN_UNDEF; /* * Fill in the program header entries. */ phdr = (Elf_Phdr *)((char *)dst + phoff); /* The note segement. */ phdr->p_type = PT_NOTE; phdr->p_offset = noteoff; phdr->p_vaddr = 0; phdr->p_paddr = 0; phdr->p_filesz = notesz; phdr->p_memsz = 0; phdr->p_flags = 0; phdr->p_align = 0; phdr++; /* All the writable segments from the program. */ phc.phdr = phdr; phc.offset = *off; each_writable_segment(p, cb_put_phdr, &phc); } } static void -elf_putnote(void *dst, size_t *off, const char *name, int type, +__elfN(putnote)(void *dst, size_t *off, const char *name, int type, const void *desc, size_t descsz) { Elf_Note note; note.n_namesz = strlen(name) + 1; note.n_descsz = descsz; note.n_type = type; if (dst != NULL) bcopy(¬e, (char *)dst + *off, sizeof note); *off += sizeof note; if (dst != NULL) bcopy(name, (char *)dst + *off, note.n_namesz); *off += roundup2(note.n_namesz, sizeof(Elf_Size)); if (dst != NULL) bcopy(desc, (char *)dst + *off, note.n_descsz); *off += roundup2(note.n_descsz, sizeof(Elf_Size)); } /* * Tell kern_execve.c about it, with a little help from the linker. */ -static struct execsw elf_execsw = {exec_elf_imgact, "ELF"}; -EXEC_SET(elf, elf_execsw); +#if __ELF_WORD_SIZE == 32 +static struct execsw elf_execsw = {exec_elf32_imgact, "ELF32"}; +EXEC_SET(elf32, elf_execsw); +#else +static struct execsw elf_execsw = {exec_elf64_imgact, "ELF64"}; +EXEC_SET(elf64, elf_execsw); +#endif Index: head/sys/kern/imgact_elf32.c =================================================================== --- head/sys/kern/imgact_elf32.c (nonexistent) +++ head/sys/kern/imgact_elf32.c (revision 100384) @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * There ought to be a better way of deciding this. + */ +#if defined(__i386__) || defined(__ia64__) || defined(__powerpc__) + +#define __ELF_WORD_SIZE 32 + +#include + +#endif Property changes on: head/sys/kern/imgact_elf32.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/kern/imgact_elf64.c =================================================================== --- head/sys/kern/imgact_elf64.c (nonexistent) +++ head/sys/kern/imgact_elf64.c (revision 100384) @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * There ought to be a better way of deciding this. + */ +#if defined(__alpha__) || defined(__ia64__) || defined(__sparc64__) + +#define __ELF_WORD_SIZE 64 + +#include + +#endif Property changes on: head/sys/kern/imgact_elf64.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/kern/imgact_elfN.c =================================================================== --- head/sys/kern/imgact_elfN.c (nonexistent) +++ head/sys/kern/imgact_elfN.c (revision 100384) @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2000 David O'Brien + * Copyright (c) 1995-1996 Søren Schmidt + * Copyright (c) 1996 Peter Wemm + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include +#include + +/* + * non static, as it can be overridden by start_init() + */ +#ifdef __ia64__ +int fallback_elf_brand = ELFOSABI_FREEBSD; +#else +int fallback_elf_brand = -1; +#endif +SYSCTL_INT(_kern, OID_AUTO, fallback_elf_brand, CTLFLAG_RW, + &fallback_elf_brand, -1, + "ELF brand of last resort"); + Property changes on: head/sys/kern/imgact_elfN.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/kern/imgact_gzip.c =================================================================== --- head/sys/kern/imgact_gzip.c (revision 100383) +++ head/sys/kern/imgact_gzip.c (revision 100384) @@ -1,385 +1,385 @@ /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * * $FreeBSD$ * * This module handles execution of a.out files which have been run through * "gzip". This saves diskspace, but wastes cpu-cycles and VM. * * TODO: * text-segments should be made R/O after being filled * is the vm-stuff safe ? * should handle the entire header of gzip'ed stuff. * inflate isn't quite reentrant yet... * error-handling is a mess... * so is the rest... * tidy up unnecesary includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct imgact_gzip { struct image_params *ip; struct exec a_out; int error; int gotheader; int where; u_char *inbuf; u_long offset; u_long output; u_long len; int idx; u_long virtual_offset, file_offset, file_end, bss_size; }; static int exec_gzip_imgact(struct image_params *imgp); static int NextByte(void *vp); static int do_aout_hdr(struct imgact_gzip *); static int Flush(void *vp, u_char *, u_long siz); static int exec_gzip_imgact(imgp) struct image_params *imgp; { int error, error2 = 0; const u_char *p = (const u_char *) imgp->image_header; struct imgact_gzip igz; struct inflate infl; struct vmspace *vmspace; /* If these four are not OK, it isn't a gzip file */ if (p[0] != 0x1f) return -1; /* 0 Simply magic */ if (p[1] != 0x8b) return -1; /* 1 Simply magic */ if (p[2] != 0x08) return -1; /* 2 Compression method */ if (p[9] != 0x03) return -1; /* 9 OS compressed on */ /* * If this one contains anything but a comment or a filename marker, * we don't want to chew on it */ if (p[3] & ~(0x18)) return ENOEXEC; /* 3 Flags */ /* These are of no use to us */ /* 4-7 Timestamp */ /* 8 Extra flags */ bzero(&igz, sizeof igz); bzero(&infl, sizeof infl); infl.gz_private = (void *) &igz; infl.gz_input = NextByte; infl.gz_output = Flush; igz.ip = imgp; igz.idx = 10; if (p[3] & 0x08) { /* skip a filename */ while (p[igz.idx++]) if (igz.idx >= PAGE_SIZE) return ENOEXEC; } if (p[3] & 0x10) { /* skip a comment */ while (p[igz.idx++]) if (igz.idx >= PAGE_SIZE) return ENOEXEC; } igz.len = imgp->attr->va_size; error = inflate(&infl); /* * The unzipped file may not even have been long enough to contain * a header giving Flush() a chance to return error. Check for this. */ if ( !igz.gotheader ) return ENOEXEC; if ( !error ) { vmspace = imgp->proc->p_vmspace; error = vm_map_protect(&vmspace->vm_map, (vm_offset_t) vmspace->vm_taddr, (vm_offset_t) (vmspace->vm_taddr + (vmspace->vm_tsize << PAGE_SHIFT)) , VM_PROT_READ|VM_PROT_EXECUTE,0); } if (igz.inbuf) { error2 = vm_map_remove(kernel_map, (vm_offset_t) igz.inbuf, (vm_offset_t) igz.inbuf + PAGE_SIZE); } if (igz.error || error || error2) { printf("Output=%lu ", igz.output); printf("Inflate_error=%d igz.error=%d error2=%d where=%d\n", error, igz.error, error2, igz.where); } if (igz.error) return igz.error; if (error) return ENOEXEC; if (error2) return error2; return 0; } static int do_aout_hdr(struct imgact_gzip * gz) { int error; struct vmspace *vmspace; vm_offset_t vmaddr; /* * Set file/virtual offset based on a.out variant. We do two cases: * host byte order and network byte order (for NetBSD compatibility) */ switch ((int) (gz->a_out.a_magic & 0xffff)) { case ZMAGIC: gz->virtual_offset = 0; if (gz->a_out.a_text) { gz->file_offset = PAGE_SIZE; } else { /* Bill's "screwball mode" */ gz->file_offset = 0; } break; case QMAGIC: gz->virtual_offset = PAGE_SIZE; gz->file_offset = 0; break; default: /* NetBSD compatibility */ switch ((int) (ntohl(gz->a_out.a_magic) & 0xffff)) { case ZMAGIC: case QMAGIC: gz->virtual_offset = PAGE_SIZE; gz->file_offset = 0; break; default: gz->where = __LINE__; return (-1); } } gz->bss_size = roundup(gz->a_out.a_bss, PAGE_SIZE); /* * Check various fields in header for validity/bounds. */ if ( /* entry point must lay with text region */ gz->a_out.a_entry < gz->virtual_offset || gz->a_out.a_entry >= gz->virtual_offset + gz->a_out.a_text || /* text and data size must each be page rounded */ gz->a_out.a_text & PAGE_MASK || gz->a_out.a_data & PAGE_MASK) { gz->where = __LINE__; return (-1); } /* * text/data/bss must not exceed limits */ mtx_assert(&Giant, MA_OWNED); if ( /* text can't exceed maximum text size */ gz->a_out.a_text > maxtsiz || /* data + bss can't exceed rlimit */ gz->a_out.a_data + gz->bss_size > gz->ip->proc->p_rlimit[RLIMIT_DATA].rlim_cur) { gz->where = __LINE__; return (ENOMEM); } /* Find out how far we should go */ gz->file_end = gz->file_offset + gz->a_out.a_text + gz->a_out.a_data; /* copy in arguments and/or environment from old process */ error = exec_extract_strings(gz->ip); if (error) { gz->where = __LINE__; return (error); } /* * Destroy old process VM and create a new one (with a new stack) */ - exec_new_vmspace(gz->ip); + exec_new_vmspace(gz->ip, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); vmspace = gz->ip->proc->p_vmspace; vmaddr = gz->virtual_offset; error = vm_mmap(&vmspace->vm_map, &vmaddr, gz->a_out.a_text + gz->a_out.a_data, VM_PROT_ALL, VM_PROT_ALL, MAP_ANON | MAP_FIXED, 0, 0); if (error) { gz->where = __LINE__; return (error); } if (gz->bss_size != 0) { /* * Allocate demand-zeroed area for uninitialized data. * "bss" = 'block started by symbol' - named after the * IBM 7090 instruction of the same name. */ vmaddr = gz->virtual_offset + gz->a_out.a_text + gz->a_out.a_data; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, gz->bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) { gz->where = __LINE__; return (error); } } /* Fill in process VM information */ vmspace->vm_tsize = gz->a_out.a_text >> PAGE_SHIFT; vmspace->vm_dsize = (gz->a_out.a_data + gz->bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t) (uintptr_t) gz->virtual_offset; vmspace->vm_daddr = (caddr_t) (uintptr_t) (gz->virtual_offset + gz->a_out.a_text); /* Fill in image_params */ gz->ip->interpreted = 0; gz->ip->entry_addr = gz->a_out.a_entry; gz->ip->proc->p_sysent = &aout_sysvec; return 0; } static int NextByte(void *vp) { int error; struct imgact_gzip *igz = (struct imgact_gzip *) vp; if (igz->idx >= igz->len) { igz->where = __LINE__; return GZ_EOF; } if (igz->inbuf && igz->idx < (igz->offset + PAGE_SIZE)) { return igz->inbuf[(igz->idx++) - igz->offset]; } if (igz->inbuf) { error = vm_map_remove(kernel_map, (vm_offset_t) igz->inbuf, (vm_offset_t) igz->inbuf + PAGE_SIZE); if (error) { igz->where = __LINE__; igz->error = error; return GZ_EOF; } } igz->offset = igz->idx & ~PAGE_MASK; error = vm_mmap(kernel_map, /* map */ (vm_offset_t *) & igz->inbuf, /* address */ PAGE_SIZE, /* size */ VM_PROT_READ, /* protection */ VM_PROT_READ, /* max protection */ 0, /* flags */ (caddr_t) igz->ip->vp, /* vnode */ igz->offset); /* offset */ if (error) { igz->where = __LINE__; igz->error = error; return GZ_EOF; } return igz->inbuf[(igz->idx++) - igz->offset]; } static int Flush(void *vp, u_char * ptr, u_long siz) { struct imgact_gzip *gz = (struct imgact_gzip *) vp; u_char *p = ptr, *q; int i; /* First, find a a.out-header */ if (gz->output < sizeof gz->a_out) { q = (u_char *) & gz->a_out; i = min(siz, sizeof gz->a_out - gz->output); bcopy(p, q + gz->output, i); gz->output += i; p += i; siz -= i; if (gz->output == sizeof gz->a_out) { gz->gotheader = 1; i = do_aout_hdr(gz); if (i == -1) { if (!gz->where) gz->where = __LINE__; gz->error = ENOEXEC; return ENOEXEC; } else if (i) { gz->where = __LINE__; gz->error = i; return ENOEXEC; } if (gz->file_offset == 0) { q = (u_char *) (uintptr_t) gz->virtual_offset; copyout(&gz->a_out, q, sizeof gz->a_out); } } } /* Skip over zero-padded first PAGE if needed */ if (gz->output < gz->file_offset && gz->output + siz > gz->file_offset) { i = min(siz, gz->file_offset - gz->output); gz->output += i; p += i; siz -= i; } if (gz->output >= gz->file_offset && gz->output < gz->file_end) { i = min(siz, gz->file_end - gz->output); q = (u_char *) (uintptr_t) (gz->virtual_offset + gz->output - gz->file_offset); copyout(p, q, i); gz->output += i; p += i; siz -= i; } gz->output += siz; return 0; } /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw gzip_execsw = {exec_gzip_imgact, "gzip"}; EXEC_SET(execgzip, gzip_execsw); Index: head/sys/kern/init_main.c =================================================================== --- head/sys/kern/init_main.c (revision 100383) +++ head/sys/kern/init_main.c (revision 100384) @@ -1,684 +1,683 @@ /* * Copyright (c) 1995 Terrence R. Lambert * All rights reserved. * * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)init_main.c 8.9 (Berkeley) 1/21/94 * $FreeBSD$ */ #include "opt_init_path.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void mi_startup(void); /* Should be elsewhere */ /* Components of the first process -- never freed. */ static struct session session0; static struct pgrp pgrp0; struct proc proc0; struct thread thread0; static struct procsig procsig0; static struct filedesc0 filedesc0; static struct plimit limit0; static struct vmspace vmspace0; struct proc *initproc; int cmask = CMASK; extern int fallback_elf_brand; struct vnode *rootvp; int boothowto = 0; /* initialized so that it can be patched */ SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, ""); int bootverbose; SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, ""); /* * This ensures that there is at least one entry so that the sysinit_set * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never * executed. */ SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL) /* * The sysinit table itself. Items are checked off as the are run. * If we want to register new sysinit types, add them to newsysinit. */ SET_DECLARE(sysinit_set, struct sysinit); struct sysinit **sysinit, **sysinit_end; struct sysinit **newsysinit, **newsysinit_end; /* * Merge a new sysinit set into the current set, reallocating it if * necessary. This can only be called after malloc is running. */ void sysinit_add(struct sysinit **set, struct sysinit **set_end) { struct sysinit **newset; struct sysinit **sipp; struct sysinit **xipp; int count; count = set_end - set; if (newsysinit) count += newsysinit_end - newsysinit; else count += sysinit_end - sysinit; newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT); if (newset == NULL) panic("cannot malloc for sysinit"); xipp = newset; if (newsysinit) for (sipp = newsysinit; sipp < newsysinit_end; sipp++) *xipp++ = *sipp; else for (sipp = sysinit; sipp < sysinit_end; sipp++) *xipp++ = *sipp; for (sipp = set; sipp < set_end; sipp++) *xipp++ = *sipp; if (newsysinit) free(newsysinit, M_TEMP); newsysinit = newset; newsysinit_end = newset + count; } /* * System startup; initialize the world, create process 0, mount root * filesystem, and fork to create init and pagedaemon. Most of the * hard work is done in the lower-level initialization routines including * startup(), which does memory initialization and autoconfiguration. * * This allows simple addition of new kernel subsystems that require * boot time initialization. It also allows substitution of subsystem * (for instance, a scheduler, kernel profiler, or VM system) by object * module. Finally, it allows for optional "kernel threads". */ void mi_startup(void) { register struct sysinit **sipp; /* system initialization*/ register struct sysinit **xipp; /* interior loop of sort*/ register struct sysinit *save; /* bubble*/ if (sysinit == NULL) { sysinit = SET_BEGIN(sysinit_set); sysinit_end = SET_LIMIT(sysinit_set); } restart: /* * Perform a bubble sort of the system initialization objects by * their subsystem (primary key) and order (secondary key). */ for (sipp = sysinit; sipp < sysinit_end; sipp++) { for (xipp = sipp + 1; xipp < sysinit_end; xipp++) { if ((*sipp)->subsystem < (*xipp)->subsystem || ((*sipp)->subsystem == (*xipp)->subsystem && (*sipp)->order <= (*xipp)->order)) continue; /* skip*/ save = *sipp; *sipp = *xipp; *xipp = save; } } /* * Traverse the (now) ordered list of system initialization tasks. * Perform each task, and continue on to the next task. * * The last item on the list is expected to be the scheduler, * which will not return. */ for (sipp = sysinit; sipp < sysinit_end; sipp++) { if ((*sipp)->subsystem == SI_SUB_DUMMY) continue; /* skip dummy task(s)*/ if ((*sipp)->subsystem == SI_SUB_DONE) continue; /* Call function */ (*((*sipp)->func))((*sipp)->udata); /* Check off the one we're just done */ (*sipp)->subsystem = SI_SUB_DONE; /* Check if we've installed more sysinit items via KLD */ if (newsysinit != NULL) { if (sysinit != SET_BEGIN(sysinit_set)) free(sysinit, M_TEMP); sysinit = newsysinit; sysinit_end = newsysinit_end; newsysinit = NULL; newsysinit_end = NULL; goto restart; } } panic("Shouldn't get here!"); /* NOTREACHED*/ } /* *************************************************************************** **** **** The following SYSINIT's belong elsewhere, but have not yet **** been moved. **** *************************************************************************** */ static void print_caddr_t(void *data __unused) { printf("%s", (char *)data); } SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright) SYSINIT(version, SI_SUB_COPYRIGHT, SI_ORDER_SECOND, print_caddr_t, version) static void set_boot_verbose(void *data __unused) { if (boothowto & RB_VERBOSE) bootverbose++; } SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL) +static struct sysentvec null_sysvec; + + /* *************************************************************************** **** **** The two following SYSINT's are proc0 specific glue code. I am not **** convinced that they can not be safely combined, but their order of **** operation has been maintained as the same as the original init_main.c **** for right now. **** **** These probably belong in init_proc.c or kern_proc.c, since they **** deal with proc0 (the fork template process). **** *************************************************************************** */ /* ARGSUSED*/ static void proc0_init(void *dummy __unused) { register struct proc *p; register struct filedesc0 *fdp; register unsigned i; struct thread *td; struct ksegrp *kg; struct kse *ke; GIANT_REQUIRED; p = &proc0; td = &thread0; /* * Initialize magic number. */ p->p_magic = P_MAGIC; /* * Initialize thread, process and pgrp structures. */ procinit(); threadinit(); /* * Initialize sleep queue hash table */ sleepinit(); /* * additional VM structures */ vm_init2(); /* * Create process 0 (the swapper). */ LIST_INSERT_HEAD(&allproc, p, p_list); LIST_INSERT_HEAD(PIDHASH(0), p, p_hash); mtx_init(&pgrp0.pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK); p->p_pgrp = &pgrp0; LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); LIST_INIT(&pgrp0.pg_members); LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); pgrp0.pg_session = &session0; mtx_init(&session0.s_mtx, "session", NULL, MTX_DEF); session0.s_count = 1; session0.s_leader = p; -#ifdef __ELF__ - p->p_sysent = &elf_freebsd_sysvec; -#else - p->p_sysent = &aout_sysvec; -#endif + p->p_sysent = &null_sysvec; /* * proc_linkup was already done in init_i386() or alphainit() etc. * because the earlier code needed to follow td->td_proc. Otherwise * I would have done it here.. maybe this means this should be * done earlier too. */ ke = &proc0.p_kse; /* XXXKSE */ kg = &proc0.p_ksegrp; /* XXXKSE */ p->p_flag = P_SYSTEM; p->p_sflag = PS_INMEM; p->p_state = PRS_NORMAL; td->td_state = TDS_RUNNING; kg->kg_nice = NZERO; kg->kg_pri_class = PRI_TIMESHARE; kg->kg_user_pri = PUSER; td->td_priority = PVM; td->td_base_pri = PUSER; td->td_kse = ke; /* XXXKSE */ ke->ke_oncpu = 0; ke->ke_state = KES_THREAD; ke->ke_thread = td; /* proc_linkup puts it in the idle queue, that's not what we want. */ TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist); kg->kg_idle_kses--; p->p_peers = 0; p->p_leader = p; KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self!")); bcopy("swapper", p->p_comm, sizeof ("swapper")); callout_init(&p->p_itcallout, 0); callout_init(&td->td_slpcallout, 1); /* Create credentials. */ p->p_ucred = crget(); p->p_ucred->cr_ngroups = 1; /* group 0 */ p->p_ucred->cr_uidinfo = uifind(0); p->p_ucred->cr_ruidinfo = uifind(0); p->p_ucred->cr_prison = NULL; /* Don't jail it. */ td->td_ucred = crhold(p->p_ucred); /* Create procsig. */ p->p_procsig = &procsig0; p->p_procsig->ps_refcnt = 1; /* Initialize signal state for process 0. */ siginit(&proc0); /* Create the file descriptor table. */ fdp = &filedesc0; p->p_fd = &fdp->fd_fd; mtx_init(&fdp->fd_fd.fd_mtx, FILEDESC_LOCK_DESC, NULL, MTX_DEF); fdp->fd_fd.fd_refcnt = 1; fdp->fd_fd.fd_cmask = cmask; fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; fdp->fd_fd.fd_nfiles = NDFILE; /* Create the limits structures. */ p->p_limit = &limit0; for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) limit0.pl_rlimit[i].rlim_cur = limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles; limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; i = ptoa(cnt.v_free_count); limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; limit0.p_cpulimit = RLIM_INFINITY; limit0.p_refcnt = 1; /* Allocate a prototype map so we have something to fork. */ pmap_pinit0(vmspace_pmap(&vmspace0)); p->p_vmspace = &vmspace0; vmspace0.vm_refcnt = 1; vm_map_init(&vmspace0.vm_map, round_page(VM_MIN_ADDRESS), trunc_page(VM_MAXUSER_ADDRESS)); vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0); /* * We continue to place resource usage info and signal * actions in the user struct so they're pageable. */ p->p_stats = &p->p_uarea->u_stats; p->p_sigacts = &p->p_uarea->u_sigacts; /* * Charge root for one process. */ (void)chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0); } SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) /* ARGSUSED*/ static void proc0_post(void *dummy __unused) { struct timespec ts; struct proc *p; /* * Now we can look at the time, having had a chance to verify the * time from the filesystem. Pretend that proc0 started now. */ sx_slock(&allproc_lock); LIST_FOREACH(p, &allproc, p_list) { microtime(&p->p_stats->p_start); p->p_runtime.sec = 0; p->p_runtime.frac = 0; } sx_sunlock(&allproc_lock); binuptime(PCPU_PTR(switchtime)); PCPU_SET(switchticks, ticks); /* * Give the ``random'' number generator a thump. */ nanotime(&ts); srandom(ts.tv_sec ^ ts.tv_nsec); } SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) /* *************************************************************************** **** **** The following SYSINIT's and glue code should be moved to the **** respective files on a per subsystem basis. **** *************************************************************************** */ /* *************************************************************************** **** **** The following code probably belongs in another file, like **** kern/init_init.c. **** *************************************************************************** */ /* * List of paths to try when searching for "init". */ static char init_path[MAXPATHLEN] = #ifdef INIT_PATH __XSTRING(INIT_PATH); #else "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall"; #endif SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, "Path used to search the init process"); /* * Start the initial user process; try exec'ing each pathname in init_path. * The program is invoked with one argument containing the boot flags. */ static void start_init(void *dummy) { vm_offset_t addr; struct execve_args args; int options, error; char *var, *path, *next, *s; char *ucp, **uap, *arg0, *arg1; struct thread *td; struct proc *p; int init_does_devfs = 0; mtx_lock(&Giant); GIANT_REQUIRED; td = curthread; p = td->td_proc; vfs_mountroot(); /* Get the vnode for '/'. Set p->p_fd->fd_cdir to reference it. */ if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode)) panic("cannot find root vnode"); FILEDESC_LOCK(p->p_fd); p->p_fd->fd_cdir = rootvnode; VREF(p->p_fd->fd_cdir); p->p_fd->fd_rdir = rootvnode; VREF(p->p_fd->fd_rdir); FILEDESC_UNLOCK(p->p_fd); VOP_UNLOCK(rootvnode, 0, td); if (devfs_present) { /* * For disk based systems, we probably cannot do this yet * since the fs will be read-only. But a NFS root * might be ok. It is worth a shot. */ error = vn_mkdir("/dev", 0700, UIO_SYSSPACE, td); if (error == EEXIST) error = 0; if (error == 0) error = kernel_vmount(0, "fstype", "devfs", "fspath", "/dev", NULL); if (error != 0) init_does_devfs = 1; } /* * Need just enough stack to hold the faked-up "execve()" arguments. */ addr = trunc_page(USRSTACK - PAGE_SIZE); if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) panic("init: couldn't allocate argument space"); p->p_vmspace->vm_maxsaddr = (caddr_t)addr; p->p_vmspace->vm_ssize = 1; if ((var = getenv("init_path")) != NULL) { strncpy(init_path, var, sizeof init_path); init_path[sizeof init_path - 1] = 0; freeenv(var); } if ((var = getenv("kern.fallback_elf_brand")) != NULL) { fallback_elf_brand = strtol(var, NULL, 0); freeenv(var); } for (path = init_path; *path != '\0'; path = next) { while (*path == ':') path++; if (*path == '\0') break; for (next = path; *next != '\0' && *next != ':'; next++) /* nothing */ ; if (bootverbose) printf("start_init: trying %.*s\n", (int)(next - path), path); /* * Move out the boot flag argument. */ options = 0; ucp = (char *)USRSTACK; (void)subyte(--ucp, 0); /* trailing zero */ if (boothowto & RB_SINGLE) { (void)subyte(--ucp, 's'); options = 1; } #ifdef notyet if (boothowto & RB_FASTBOOT) { (void)subyte(--ucp, 'f'); options = 1; } #endif #ifdef BOOTCDROM (void)subyte(--ucp, 'C'); options = 1; #endif if (init_does_devfs) { (void)subyte(--ucp, 'd'); options = 1; } if (options == 0) (void)subyte(--ucp, '-'); (void)subyte(--ucp, '-'); /* leading hyphen */ arg1 = ucp; /* * Move out the file name (also arg 0). */ (void)subyte(--ucp, 0); for (s = next - 1; s >= path; s--) (void)subyte(--ucp, *s); arg0 = ucp; /* * Move out the arg pointers. */ uap = (char **)((intptr_t)ucp & ~(sizeof(intptr_t)-1)); (void)suword((caddr_t)--uap, (long)0); /* terminator */ (void)suword((caddr_t)--uap, (long)(intptr_t)arg1); (void)suword((caddr_t)--uap, (long)(intptr_t)arg0); /* * Point at the arguments. */ args.fname = arg0; args.argv = uap; args.envv = NULL; /* * Now try to exec the program. If can't for any reason * other than it doesn't exist, complain. * * Otherwise, return via fork_trampoline() all the way * to user mode as init! */ if ((error = execve(td, &args)) == 0) { mtx_unlock(&Giant); return; } if (error != ENOENT) printf("exec %.*s: error %d\n", (int)(next - path), path, error); } printf("init: not found in path %s\n", init_path); panic("no init"); } /* * Like kthread_create(), but runs in it's own address space. * We do this early to reserve pid 1. * * Note special case - do not make it runnable yet. Other work * in progress will change this more. */ static void create_init(const void *udata __unused) { struct ucred *newcred, *oldcred; int error; error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, &initproc); if (error) panic("cannot fork init: %d\n", error); /* divorce init's credentials from the kernel's */ newcred = crget(); PROC_LOCK(initproc); initproc->p_flag |= P_SYSTEM; oldcred = initproc->p_ucred; crcopy(newcred, oldcred); initproc->p_ucred = newcred; PROC_UNLOCK(initproc); crfree(oldcred); mtx_lock_spin(&sched_lock); initproc->p_sflag |= PS_INMEM; mtx_unlock_spin(&sched_lock); cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL); } SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL) /* * Make it runnable now. */ static void kick_init(const void *udata __unused) { struct thread *td; td = FIRST_THREAD_IN_PROC(initproc); mtx_lock_spin(&sched_lock); setrunqueue(td); /* XXXKSE */ mtx_unlock_spin(&sched_lock); } SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL) Index: head/sys/kern/kern_exec.c =================================================================== --- head/sys/kern/kern_exec.c (revision 100383) +++ head/sys/kern/kern_exec.c (revision 100384) @@ -1,1040 +1,1051 @@ /* * Copyright (c) 1993, David Greenman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include "opt_ktrace.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef KTRACE #include #endif #include #include #include #include #include #include #include #include #include #include MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments"); static MALLOC_DEFINE(M_ATEXEC, "atexec", "atexec callback"); /* * callout list for things to do at exec time */ struct execlist { execlist_fn function; TAILQ_ENTRY(execlist) next; }; TAILQ_HEAD(exec_list_head, execlist); static struct exec_list_head exec_list = TAILQ_HEAD_INITIALIZER(exec_list); static register_t *exec_copyout_strings(struct image_params *); /* XXX This should be vm_size_t. */ static u_long ps_strings = PS_STRINGS; SYSCTL_ULONG(_kern, KERN_PS_STRINGS, ps_strings, CTLFLAG_RD, &ps_strings, 0, ""); /* XXX This should be vm_size_t. */ static u_long usrstack = USRSTACK; SYSCTL_ULONG(_kern, KERN_USRSTACK, usrstack, CTLFLAG_RD, &usrstack, 0, ""); u_long ps_arg_cache_limit = PAGE_SIZE / 16; SYSCTL_ULONG(_kern, OID_AUTO, ps_arg_cache_limit, CTLFLAG_RW, &ps_arg_cache_limit, 0, ""); int ps_argsopen = 1; SYSCTL_INT(_kern, OID_AUTO, ps_argsopen, CTLFLAG_RW, &ps_argsopen, 0, ""); #ifdef __ia64__ /* XXX HACK */ static int regstkpages = 256; SYSCTL_INT(_machdep, OID_AUTO, regstkpages, CTLFLAG_RW, ®stkpages, 0, ""); #endif /* * Each of the items is a pointer to a `const struct execsw', hence the * double pointer here. */ static const struct execsw **execsw; #ifndef _SYS_SYSPROTO_H_ struct execve_args { char *fname; char **argv; char **envv; }; #endif /* * execve() system call. * * MPSAFE */ int execve(td, uap) struct thread *td; register struct execve_args *uap; { struct proc *p = td->td_proc; struct nameidata nd, *ndp; struct ucred *newcred = NULL, *oldcred; struct uidinfo *euip; register_t *stack_base; int error, len, i; struct image_params image_params, *imgp; struct vattr attr; int (*img_first)(struct image_params *); struct pargs *oldargs = NULL, *newargs = NULL; struct procsig *oldprocsig, *newprocsig; #ifdef KTRACE struct vnode *tracevp = NULL; #endif struct vnode *textvp = NULL; imgp = &image_params; /* * Lock the process and set the P_INEXEC flag to indicate that * it should be left alone until we're done here. This is * necessary to avoid race conditions - e.g. in ptrace() - * that might allow a local user to illicitly obtain elevated * privileges. */ PROC_LOCK(p); KASSERT((p->p_flag & P_INEXEC) == 0, ("%s(): process already has P_INEXEC flag", __func__)); if ((p->p_flag & P_KSES) && thread_single(SNGLE_EXIT)) { PROC_UNLOCK(p); return (ERESTART); /* Try again later. */ } /* If we get here all other threads are dead. */ p->p_flag |= P_INEXEC; PROC_UNLOCK(p); /* * Initialize part of the common data */ imgp->proc = p; imgp->uap = uap; imgp->attr = &attr; imgp->argc = imgp->envc = 0; imgp->argv0 = NULL; imgp->entry_addr = 0; imgp->vmspace_destroyed = 0; imgp->interpreted = 0; imgp->interpreter_name[0] = '\0'; imgp->auxargs = NULL; imgp->vp = NULL; imgp->object = NULL; imgp->firstpage = NULL; imgp->ps_strings = 0; imgp->auxarg_size = 0; /* * Allocate temporary demand zeroed space for argument and * environment strings */ imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX + PAGE_SIZE); if (imgp->stringbase == NULL) { error = ENOMEM; mtx_lock(&Giant); goto exec_fail; } imgp->stringp = imgp->stringbase; imgp->stringspace = ARG_MAX; imgp->image_header = imgp->stringbase + ARG_MAX; /* * Translate the file name. namei() returns a vnode pointer * in ni_vp amoung other things. */ ndp = &nd; NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_USERSPACE, uap->fname, td); mtx_lock(&Giant); interpret: error = namei(ndp); if (error) { kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX + PAGE_SIZE); goto exec_fail; } imgp->vp = ndp->ni_vp; imgp->fname = uap->fname; /* * Check file permissions (also 'opens' file) */ error = exec_check_permissions(imgp); if (error) { VOP_UNLOCK(imgp->vp, 0, td); goto exec_fail_dealloc; } VOP_GETVOBJECT(imgp->vp, &imgp->object); vm_object_reference(imgp->object); error = exec_map_first_page(imgp); VOP_UNLOCK(imgp->vp, 0, td); if (error) goto exec_fail_dealloc; /* * If the current process has a special image activator it * wants to try first, call it. For example, emulating shell * scripts differently. */ error = -1; if ((img_first = imgp->proc->p_sysent->sv_imgact_try) != NULL) error = img_first(imgp); /* * Loop through the list of image activators, calling each one. * An activator returns -1 if there is no match, 0 on success, * and an error otherwise. */ for (i = 0; error == -1 && execsw[i]; ++i) { if (execsw[i]->ex_imgact == NULL || execsw[i]->ex_imgact == img_first) { continue; } error = (*execsw[i]->ex_imgact)(imgp); } if (error) { if (error == -1) error = ENOEXEC; goto exec_fail_dealloc; } /* * Special interpreter operation, cleanup and loop up to try to * activate the interpreter. */ if (imgp->interpreted) { exec_unmap_first_page(imgp); /* free name buffer and old vnode */ NDFREE(ndp, NDF_ONLY_PNBUF); vrele(ndp->ni_vp); vm_object_deallocate(imgp->object); imgp->object = NULL; /* set new name to that of the interpreter */ NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_SYSSPACE, imgp->interpreter_name, td); goto interpret; } /* * Copy out strings (args and env) and initialize stack base */ - stack_base = exec_copyout_strings(imgp); + if (p->p_sysent->sv_copyout_strings) + stack_base = (*p->p_sysent->sv_copyout_strings)(imgp); + else + stack_base = exec_copyout_strings(imgp); /* * If custom stack fixup routine present for this process * let it do the stack setup. * Else stuff argument count as first item on stack */ if (p->p_sysent->sv_fixup) (*p->p_sysent->sv_fixup)(&stack_base, imgp); else suword(--stack_base, imgp->argc); /* * For security and other reasons, the file descriptor table cannot * be shared after an exec. */ FILEDESC_LOCK(p->p_fd); if (p->p_fd->fd_refcnt > 1) { struct filedesc *tmp; tmp = fdcopy(td); FILEDESC_UNLOCK(p->p_fd); fdfree(td); p->p_fd = tmp; } else FILEDESC_UNLOCK(p->p_fd); /* * Malloc things before we need locks. */ newcred = crget(); euip = uifind(attr.va_uid); i = imgp->endargs - imgp->stringbase; if (ps_arg_cache_limit >= i + sizeof(struct pargs)) newargs = pargs_alloc(i); /* close files on exec */ fdcloseexec(td); /* * For security and other reasons, signal handlers cannot * be shared after an exec. The new process gets a copy of the old * handlers. In execsigs(), the new process will have its signals * reset. */ PROC_LOCK(p); mp_fixme("procsig needs a lock"); if (p->p_procsig->ps_refcnt > 1) { oldprocsig = p->p_procsig; PROC_UNLOCK(p); MALLOC(newprocsig, struct procsig *, sizeof(struct procsig), M_SUBPROC, M_WAITOK); bcopy(oldprocsig, newprocsig, sizeof(*newprocsig)); newprocsig->ps_refcnt = 1; oldprocsig->ps_refcnt--; PROC_LOCK(p); p->p_procsig = newprocsig; if (p->p_sigacts == &p->p_uarea->u_sigacts) panic("shared procsig but private sigacts?"); p->p_uarea->u_sigacts = *p->p_sigacts; p->p_sigacts = &p->p_uarea->u_sigacts; } /* Stop profiling */ stopprofclock(p); /* reset caught signals */ execsigs(p); /* name this process - nameiexec(p, ndp) */ len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN); bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len); p->p_comm[len] = 0; /* * mark as execed, wakeup the process that vforked (if any) and tell * it that it now has its own resources back */ p->p_flag |= P_EXEC; if (p->p_pptr && (p->p_flag & P_PPWAIT)) { p->p_flag &= ~P_PPWAIT; wakeup(p->p_pptr); } /* * Implement image setuid/setgid. * * Don't honor setuid/setgid if the filesystem prohibits it or if * the process is being traced. */ oldcred = p->p_ucred; if ((((attr.va_mode & VSUID) && oldcred->cr_uid != attr.va_uid) || ((attr.va_mode & VSGID) && oldcred->cr_gid != attr.va_gid)) && (imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 && (p->p_flag & P_TRACED) == 0) { /* * Turn off syscall tracing for set-id programs, except for * root. Record any set-id flags first to make sure that * we do not regain any tracing during a possible block. */ setsugid(p); #ifdef KTRACE if (p->p_tracep && suser_cred(oldcred, PRISON_ROOT)) { mtx_lock(&ktrace_mtx); p->p_traceflag = 0; tracevp = p->p_tracep; p->p_tracep = NULL; mtx_unlock(&ktrace_mtx); } #endif /* Make sure file descriptors 0..2 are in use. */ error = fdcheckstd(td); if (error != 0) goto done1; /* * Set the new credentials. */ crcopy(newcred, oldcred); if (attr.va_mode & VSUID) change_euid(newcred, euip); if (attr.va_mode & VSGID) change_egid(newcred, attr.va_gid); setugidsafety(td); /* * Implement correct POSIX saved-id behavior. */ change_svuid(newcred, newcred->cr_uid); change_svgid(newcred, newcred->cr_gid); p->p_ucred = newcred; newcred = NULL; } else { if (oldcred->cr_uid == oldcred->cr_ruid && oldcred->cr_gid == oldcred->cr_rgid) p->p_flag &= ~P_SUGID; /* * Implement correct POSIX saved-id behavior. * * XXX: It's not clear that the existing behavior is * POSIX-compliant. A number of sources indicate that the * saved uid/gid should only be updated if the new ruid is * not equal to the old ruid, or the new euid is not equal * to the old euid and the new euid is not equal to the old * ruid. The FreeBSD code always updates the saved uid/gid. * Also, this code uses the new (replaced) euid and egid as * the source, which may or may not be the right ones to use. */ if (oldcred->cr_svuid != oldcred->cr_uid || oldcred->cr_svgid != oldcred->cr_gid) { crcopy(newcred, oldcred); change_svuid(newcred, newcred->cr_uid); change_svgid(newcred, newcred->cr_gid); p->p_ucred = newcred; newcred = NULL; } } /* * Store the vp for use in procfs */ textvp = p->p_textvp; VREF(ndp->ni_vp); p->p_textvp = ndp->ni_vp; /* * Notify others that we exec'd, and clear the P_INEXEC flag * as we're now a bona fide freshly-execed process. */ KNOTE(&p->p_klist, NOTE_EXEC); p->p_flag &= ~P_INEXEC; /* * If tracing the process, trap to debugger so breakpoints * can be set before the program executes. */ _STOPEVENT(p, S_EXEC, 0); if (p->p_flag & P_TRACED) psignal(p, SIGTRAP); /* clear "fork but no exec" flag, as we _are_ execing */ p->p_acflag &= ~AFORK; /* Free any previous argument cache */ oldargs = p->p_args; p->p_args = NULL; /* Set values passed into the program in registers. */ - setregs(td, imgp->entry_addr, (u_long)(uintptr_t)stack_base, - imgp->ps_strings); + if (p->p_sysent->sv_setregs) + (*p->p_sysent->sv_setregs)(td, imgp->entry_addr, + (u_long)(uintptr_t)stack_base, imgp->ps_strings); + else + setregs(td, imgp->entry_addr, (u_long)(uintptr_t)stack_base, + imgp->ps_strings); /* Cache arguments if they fit inside our allowance */ if (ps_arg_cache_limit >= i + sizeof(struct pargs)) { bcopy(imgp->stringbase, newargs->ar_args, i); p->p_args = newargs; newargs = NULL; } done1: PROC_UNLOCK(p); /* * Free any resources malloc'd earlier that we didn't use. */ uifree(euip); if (newcred == NULL) crfree(oldcred); else crfree(newcred); /* * Handle deferred decrement of ref counts. */ if (textvp != NULL) vrele(textvp); #ifdef KTRACE if (tracevp != NULL) vrele(tracevp); #endif if (oldargs != NULL) pargs_drop(oldargs); if (newargs != NULL) pargs_drop(newargs); exec_fail_dealloc: /* * free various allocated resources */ if (imgp->firstpage) exec_unmap_first_page(imgp); if (imgp->stringbase != NULL) kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX + PAGE_SIZE); if (imgp->vp) { NDFREE(ndp, NDF_ONLY_PNBUF); vrele(imgp->vp); } if (imgp->object) vm_object_deallocate(imgp->object); if (error == 0) goto done2; exec_fail: /* we're done here, clear P_INEXEC */ PROC_LOCK(p); p->p_flag &= ~P_INEXEC; PROC_UNLOCK(p); if (imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ exit1(td, W_EXITCODE(0, SIGABRT)); /* NOT REACHED */ error = 0; } done2: mtx_unlock(&Giant); return (error); } int exec_map_first_page(imgp) struct image_params *imgp; { int rv, i; int initial_pagein; vm_page_t ma[VM_INITIAL_PAGEIN]; vm_object_t object; GIANT_REQUIRED; if (imgp->firstpage) { exec_unmap_first_page(imgp); } VOP_GETVOBJECT(imgp->vp, &object); ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); if ((ma[0]->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) { initial_pagein = VM_INITIAL_PAGEIN; if (initial_pagein > object->size) initial_pagein = object->size; for (i = 1; i < initial_pagein; i++) { if ((ma[i] = vm_page_lookup(object, i)) != NULL) { if ((ma[i]->flags & PG_BUSY) || ma[i]->busy) break; if (ma[i]->valid) break; vm_page_busy(ma[i]); } else { ma[i] = vm_page_alloc(object, i, VM_ALLOC_NORMAL); if (ma[i] == NULL) break; } } initial_pagein = i; rv = vm_pager_get_pages(object, ma, initial_pagein, 0); ma[0] = vm_page_lookup(object, 0); if ((rv != VM_PAGER_OK) || (ma[0] == NULL) || (ma[0]->valid == 0)) { if (ma[0]) { vm_page_lock_queues(); vm_page_protect(ma[0], VM_PROT_NONE); vm_page_free(ma[0]); vm_page_unlock_queues(); } return EIO; } } vm_page_lock_queues(); vm_page_wire(ma[0]); vm_page_wakeup(ma[0]); vm_page_unlock_queues(); pmap_qenter((vm_offset_t)imgp->image_header, ma, 1); imgp->firstpage = ma[0]; return 0; } void exec_unmap_first_page(imgp) struct image_params *imgp; { GIANT_REQUIRED; if (imgp->firstpage) { pmap_qremove((vm_offset_t)imgp->image_header, 1); vm_page_lock_queues(); vm_page_unwire(imgp->firstpage, 1); vm_page_unlock_queues(); imgp->firstpage = NULL; } } /* * Destroy old address space, and allocate a new stack * The new stack is only SGROWSIZ large because it is grown * automatically in trap.c. */ int -exec_new_vmspace(imgp) +exec_new_vmspace(imgp, minuser, maxuser, stack_addr) struct image_params *imgp; + vm_offset_t minuser, maxuser, stack_addr; { int error; struct execlist *ep; struct proc *p = imgp->proc; struct vmspace *vmspace = p->p_vmspace; - vm_offset_t stack_addr = USRSTACK - maxssiz; GIANT_REQUIRED; + stack_addr = stack_addr - maxssiz; + imgp->vmspace_destroyed = 1; /* * Perform functions registered with at_exec(). */ TAILQ_FOREACH(ep, &exec_list, next) (*ep->function)(p); /* * Blow away entire process VM, if address space not shared, * otherwise, create a new VM space so that other threads are * not disrupted */ - if (vmspace->vm_refcnt == 1) { + if (vmspace->vm_refcnt == 1 + && vm_map_min(&vmspace->vm_map) == minuser + && vm_map_max(&vmspace->vm_map) == maxuser) { if (vmspace->vm_shm) shmexit(p); - pmap_remove_pages(vmspace_pmap(vmspace), 0, VM_MAXUSER_ADDRESS); - vm_map_remove(&vmspace->vm_map, 0, VM_MAXUSER_ADDRESS); + pmap_remove_pages(vmspace_pmap(vmspace), minuser, maxuser); + vm_map_remove(&vmspace->vm_map, minuser, maxuser); } else { - vmspace_exec(p); + vmspace_exec(p, minuser, maxuser); vmspace = p->p_vmspace; } /* Allocate a new stack */ error = vm_map_stack(&vmspace->vm_map, stack_addr, (vm_size_t)maxssiz, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return (error); #ifdef __ia64__ { /* * Allocate backing store. We really need something * similar to vm_map_stack which can allow the backing * store to grow upwards. This will do for now. */ vm_offset_t bsaddr; bsaddr = USRSTACK - 2*maxssiz; error = vm_map_find(&vmspace->vm_map, 0, 0, &bsaddr, regstkpages * PAGE_SIZE, 0, VM_PROT_ALL, VM_PROT_ALL, 0); FIRST_THREAD_IN_PROC(p)->td_md.md_bspstore = bsaddr; } #endif /* vm_ssize and vm_maxsaddr are somewhat antiquated concepts in the * VM_STACK case, but they are still used to monitor the size of the * process stack so we can check the stack rlimit. */ vmspace->vm_ssize = sgrowsiz >> PAGE_SHIFT; vmspace->vm_maxsaddr = (char *)USRSTACK - maxssiz; return(0); } /* * Copy out argument and environment strings from the old process * address space into the temporary string buffer. */ int exec_extract_strings(imgp) struct image_params *imgp; { char **argv, **envv; char *argp, *envp; int error; size_t length; /* * extract arguments first */ argv = imgp->uap->argv; if (argv) { argp = (caddr_t) (intptr_t) fuword(argv); if (argp == (caddr_t) -1) return (EFAULT); if (argp) argv++; if (imgp->argv0) argp = imgp->argv0; if (argp) { do { if (argp == (caddr_t) -1) return (EFAULT); if ((error = copyinstr(argp, imgp->stringp, imgp->stringspace, &length))) { if (error == ENAMETOOLONG) return(E2BIG); return (error); } imgp->stringspace -= length; imgp->stringp += length; imgp->argc++; } while ((argp = (caddr_t) (intptr_t) fuword(argv++))); } } imgp->endargs = imgp->stringp; /* * extract environment strings */ envv = imgp->uap->envv; if (envv) { while ((envp = (caddr_t) (intptr_t) fuword(envv++))) { if (envp == (caddr_t) -1) return (EFAULT); if ((error = copyinstr(envp, imgp->stringp, imgp->stringspace, &length))) { if (error == ENAMETOOLONG) return(E2BIG); return (error); } imgp->stringspace -= length; imgp->stringp += length; imgp->envc++; } } return (0); } /* * Copy strings out to the new process address space, constructing * new arg and env vector tables. Return a pointer to the base * so that it can be used as the initial stack pointer. */ register_t * exec_copyout_strings(imgp) struct image_params *imgp; { int argc, envc; char **vectp; char *stringp, *destp; register_t *stack_base; struct ps_strings *arginfo; int szsigcode; /* * Calculate string base and vector table pointers. * Also deal with signal trampoline code for this exec type. */ arginfo = (struct ps_strings *)PS_STRINGS; szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); /* * install sigcode */ if (szsigcode) copyout(imgp->proc->p_sysent->sv_sigcode, ((caddr_t)arginfo - szsigcode), szsigcode); /* * If we have a valid auxargs ptr, prepare some room * on the stack. */ if (imgp->auxargs) { /* * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for * lower compatibility. */ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size : (AT_COUNT * 2); /* * The '+ 2' is for the null pointers at the end of each of * the arg and env vector sets,and imgp->auxarg_size is room * for argument of Runtime loader. */ vectp = (char **) (destp - (imgp->argc + imgp->envc + 2 + imgp->auxarg_size) * sizeof(char *)); } else /* * The '+ 2' is for the null pointers at the end of each of * the arg and env vector sets */ vectp = (char **) (destp - (imgp->argc + imgp->envc + 2) * sizeof(char *)); /* * vectp also becomes our initial stack base */ stack_base = (register_t *)vectp; stringp = imgp->stringbase; argc = imgp->argc; envc = imgp->envc; /* * Copy out strings - arguments and environment. */ copyout(stringp, destp, ARG_MAX - imgp->stringspace); /* * Fill in "ps_strings" struct for ps, w, etc. */ suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); suword(&arginfo->ps_nargvstr, argc); /* * Fill in argument portion of vector table. */ for (; argc > 0; --argc) { suword(vectp++, (long)(intptr_t)destp); while (*stringp++ != 0) destp++; destp++; } /* a null vector table pointer separates the argp's from the envp's */ suword(vectp++, 0); suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); suword(&arginfo->ps_nenvstr, envc); /* * Fill in environment portion of vector table. */ for (; envc > 0; --envc) { suword(vectp++, (long)(intptr_t)destp); while (*stringp++ != 0) destp++; destp++; } /* end of vector table is a null pointer */ suword(vectp, 0); return (stack_base); } /* * Check permissions of file to execute. * Called with imgp->vp locked. * Return 0 for success or error code on failure. */ int exec_check_permissions(imgp) struct image_params *imgp; { struct vnode *vp = imgp->vp; struct vattr *attr = imgp->attr; struct thread *td; int error; td = curthread; /* XXXKSE */ /* Get file attributes */ error = VOP_GETATTR(vp, attr, td->td_ucred, td); if (error) return (error); /* * 1) Check if file execution is disabled for the filesystem that this * file resides on. * 2) Insure that at least one execute bit is on - otherwise root * will always succeed, and we don't want to happen unless the * file really is executable. * 3) Insure that the file is a regular file. */ if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr->va_mode & 0111) == 0) || (attr->va_type != VREG)) return (EACCES); /* * Zero length files can't be exec'd */ if (attr->va_size == 0) return (ENOEXEC); /* * Check for execute permission to file based on current credentials. */ error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); if (error) return (error); /* * Check number of open-for-writes on the file and deny execution * if there are any. */ if (vp->v_writecount) return (ETXTBSY); /* * Call filesystem specific open routine (which does nothing in the * general case). */ error = VOP_OPEN(vp, FREAD, td->td_ucred, td); return (error); } /* * Exec handler registration */ int exec_register(execsw_arg) const struct execsw *execsw_arg; { const struct execsw **es, **xs, **newexecsw; int count = 2; /* New slot and trailing NULL */ if (execsw) for (es = execsw; *es; es++) count++; newexecsw = malloc(count * sizeof(*es), M_TEMP, M_WAITOK); if (newexecsw == NULL) return ENOMEM; xs = newexecsw; if (execsw) for (es = execsw; *es; es++) *xs++ = *es; *xs++ = execsw_arg; *xs = NULL; if (execsw) free(execsw, M_TEMP); execsw = newexecsw; return 0; } int exec_unregister(execsw_arg) const struct execsw *execsw_arg; { const struct execsw **es, **xs, **newexecsw; int count = 1; if (execsw == NULL) panic("unregister with no handlers left?\n"); for (es = execsw; *es; es++) { if (*es == execsw_arg) break; } if (*es == NULL) return ENOENT; for (es = execsw; *es; es++) if (*es != execsw_arg) count++; newexecsw = malloc(count * sizeof(*es), M_TEMP, M_WAITOK); if (newexecsw == NULL) return ENOMEM; xs = newexecsw; for (es = execsw; *es; es++) if (*es != execsw_arg) *xs++ = *es; *xs = NULL; if (execsw) free(execsw, M_TEMP); execsw = newexecsw; return 0; } int at_exec(function) execlist_fn function; { struct execlist *ep; #ifdef INVARIANTS /* Be noisy if the programmer has lost track of things */ if (rm_at_exec(function)) printf("WARNING: exec callout entry (%p) already present\n", function); #endif ep = malloc(sizeof(*ep), M_ATEXEC, M_NOWAIT); if (ep == NULL) return (ENOMEM); ep->function = function; TAILQ_INSERT_TAIL(&exec_list, ep, next); return (0); } /* * Scan the exec callout list for the given item and remove it. * Returns the number of items removed (0 or 1) */ int rm_at_exec(function) execlist_fn function; { struct execlist *ep; TAILQ_FOREACH(ep, &exec_list, next) { if (ep->function == function) { TAILQ_REMOVE(&exec_list, ep, next); free(ep, M_ATEXEC); return(1); } } return (0); } Index: head/sys/powerpc/powerpc/elf_machdep.c =================================================================== --- head/sys/powerpc/powerpc/elf_machdep.c (revision 100383) +++ head/sys/powerpc/powerpc/elf_machdep.c (revision 100384) @@ -1,113 +1,151 @@ /*- * Copyright 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include +#include +#include +#include +#include #include #include #include +#include +struct sysentvec elf32_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF32", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf32_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_PPC, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf32_freebsd_sysvec + }; + +SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &freebsd_brand_info); + /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, const void *data, int type) { Elf_Addr relocbase = (Elf_Addr) lf->address; Elf_Addr *where; Elf_Addr addr; Elf_Addr addend; Elf_Word rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; switch (type) { case ELF_RELOC_REL: rel = (const Elf_Rel *)data; where = (Elf_Addr *) (relocbase + rel->r_offset); addend = *where; rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); break; case ELF_RELOC_RELA: rela = (const Elf_Rela *)data; where = (Elf_Addr *) (relocbase + rela->r_offset); addend = rela->r_addend; rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); break; default: panic("elf_reloc: unknown relocation mode %d\n", type); } switch (rtype) { case R_PPC_NONE: break; case R_PPC_GLOB_DAT: addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; - addr += addend; + addr += addend; if (*where != addr) *where = addr; break; case R_PPC_JMP_SLOT: /* No point in lazy binding for kernel modules. */ addr = elf_lookup(lf, symidx, 1); if (addr == 0) return -1; if (*where != addr) *where = addr; break; case R_PPC_RELATIVE: addr = relocbase + addend + *where; if (*where != addr) *where = addr; break; case R_PPC_COPY: /* * There shouldn't be copy relocations in kernel * objects. */ printf("kldload: unexpected R_COPY relocation\n"); return -1; default: printf("kldload: unexpected relocation type %d\n", (int) rtype); return -1; } return(0); } Index: head/sys/sparc64/sparc64/elf_machdep.c =================================================================== --- head/sys/sparc64/sparc64/elf_machdep.c (revision 100383) +++ head/sys/sparc64/sparc64/elf_machdep.c (revision 100384) @@ -1,230 +1,270 @@ /*- * Copyright (c) 2001 Jake Burkholder. * Copyright (c) 2000 Eduardo Horvath. * Copyright (c) 1999 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: NetBSD: mdreloc.c,v 1.5 2001/04/25 12:24:51 kleink Exp * $FreeBSD$ */ #include +#include #include #include +#include +#include +#include +#include +#include #include +#include #include "linker_if.h" + +struct sysentvec elf64_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf64_freebsd_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD ELF64", + __elfN(coredump), + NULL, + MINSIGSTKSZ +}; + +static Elf64_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_SPARCV9, + "FreeBSD", + "", + "/usr/libexec/ld-elf.so.1", + &elf64_freebsd_sysvec + }; + +SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf64_insert_brand_entry, + &freebsd_brand_info); /* * The following table holds for each relocation type: * - the width in bits of the memory location the relocation * applies to (not currently used) * - the number of bits the relocation value must be shifted to the * right (i.e. discard least significant bits) to fit into * the appropriate field in the instruction word. * - flags indicating whether * * the relocation involves a symbol * * the relocation is relative to the current position * * the relocation is for a GOT entry * * the relocation is relative to the load address * */ #define _RF_S 0x80000000 /* Resolve symbol */ #define _RF_A 0x40000000 /* Use addend */ #define _RF_P 0x20000000 /* Location relative */ #define _RF_G 0x10000000 /* GOT offset */ #define _RF_B 0x08000000 /* Load address relative */ #define _RF_U 0x04000000 /* Unaligned */ #define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ #define _RF_RS(s) ( (s) & 0xff) /* right shift */ static int reloc_target_flags[] = { 0, /* NONE */ _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */ _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */ _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ _RF_A| _RF_B|_RF_SZ(32) | _RF_RS(10), /* HI22 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */ _RF_A| _RF_B|_RF_SZ(32) | _RF_RS(0), /* LO10 */ _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ _RF_SZ(32) | _RF_RS(0), /* COPY */ _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* GLOB_DAT */ _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ _RF_A| _RF_B|_RF_SZ(64) | _RF_RS(0), /* RELATIVE */ _RF_S|_RF_A| _RF_U|_RF_SZ(32) | _RF_RS(0), /* UA_32 */ _RF_A| _RF_SZ(32) | _RF_RS(0), /* PLT32 */ _RF_A| _RF_SZ(32) | _RF_RS(10), /* HIPLT22 */ _RF_A| _RF_SZ(32) | _RF_RS(0), /* LOPLT10 */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT32 */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PCPLT22 */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT10 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 10 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 11 */ _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* 64 */ _RF_S|_RF_A|/*extra*/ _RF_SZ(32) | _RF_RS(0), /* OLO10 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(42), /* HH22 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(32), /* HM10 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* LM22 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(42), /* PC_HH22 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(32), /* PC_HM10 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC_LM22 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP16 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP19 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_JMP */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 7 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 5 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 6 */ _RF_S|_RF_A|_RF_P| _RF_SZ(64) | _RF_RS(0), /* DISP64 */ _RF_A| _RF_SZ(64) | _RF_RS(0), /* PLT64 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HIX22 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LOX10 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(22), /* H44 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(12), /* M44 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* L44 */ _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* REGISTER */ _RF_S|_RF_A| _RF_U| _RF_SZ(64) | _RF_RS(0), /* UA64 */ _RF_S|_RF_A| _RF_U| _RF_SZ(16) | _RF_RS(0), /* UA16 */ }; #define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) #define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) #define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) #define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) #define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) #define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) #define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) static long reloc_target_bitmask[] = { #define _BM(x) (~(-(1ULL << (x)))) 0, /* NONE */ _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ _BM(30), _BM(22), /* WDISP30, WDISP22 */ _BM(22), _BM(22), /* HI22, _22 */ _BM(13), _BM(10), /* RELOC_13, _LO10 */ _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ _BM(10), _BM(22), /* _PC10, _PC22 */ _BM(30), 0, /* _WPLT30, _COPY */ _BM(32), _BM(32), _BM(32), /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ _BM(32), _BM(32), /* _UA32, PLT32 */ _BM(22), _BM(10), /* _HIPLT22, LOPLT10 */ _BM(32), _BM(22), _BM(10), /* _PCPLT32, _PCPLT22, _PCPLT10 */ _BM(10), _BM(11), -1, /* _10, _11, _64 */ _BM(10), _BM(22), /* _OLO10, _HH22 */ _BM(10), _BM(22), /* _HM10, _LM22 */ _BM(22), _BM(10), _BM(22), /* _PC_HH22, _PC_HM10, _PC_LM22 */ _BM(16), _BM(19), /* _WDISP16, _WDISP19 */ -1, /* GLOB_JMP */ _BM(7), _BM(5), _BM(6) /* _7, _5, _6 */ -1, -1, /* DISP64, PLT64 */ _BM(22), _BM(13), /* HIX22, LOX10 */ _BM(22), _BM(10), _BM(13), /* H44, M44, L44 */ -1, -1, _BM(16), /* REGISTER, UA64, UA16 */ #undef _BM }; #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, const void *data, int type) { const Elf_Rela *rela; Elf_Addr relocbase; Elf_Half *where32; Elf_Addr *where; Elf_Word rtype, symidx; Elf_Addr value; Elf_Addr mask; Elf_Addr addr; if (type != ELF_RELOC_RELA) return (-1); relocbase = (Elf_Addr)lf->address; rela = (const Elf_Rela *)data; where = (Elf_Addr *)(relocbase + rela->r_offset); where32 = (Elf_Half *)where; rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); if (rtype == R_SPARC_NONE) return (0); if (rtype == R_SPARC_JMP_SLOT || rtype == R_SPARC_COPY || rtype > R_SPARC_UA16) return (-1); if (RELOC_UNALIGNED(rtype)) return (-1); value = rela->r_addend; if (RELOC_RESOLVE_SYMBOL(rtype)) { addr = elf_lookup(lf, symidx, 1); if (addr == 0) return (-1); value += addr; } if (RELOC_PC_RELATIVE(rtype)) value -= (Elf_Addr)where; if (RELOC_BASE_RELATIVE(rtype)) value += relocbase; mask = RELOC_VALUE_BITMASK(rtype); value >>= RELOC_VALUE_RIGHTSHIFT(rtype); value &= mask; if (RELOC_TARGET_SIZE(rtype) > 32) { *where &= ~mask; *where |= value; } else { *where32 &= ~mask; *where32 |= value; } return (0); } Index: head/sys/sys/elf_generic.h =================================================================== --- head/sys/sys/elf_generic.h (revision 100383) +++ head/sys/sys/elf_generic.h (revision 100384) @@ -1,79 +1,80 @@ /*- * Copyright (c) 1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_ELF_GENERIC_H_ #define _SYS_ELF_GENERIC_H_ 1 #include /* * Definitions of generic ELF names which relieve applications from * needing to know the word size. */ #if __ELF_WORD_SIZE != 32 && __ELF_WORD_SIZE != 64 #error "__ELF_WORD_SIZE must be defined as 32 or 64" #endif #define ELF_CLASS __CONCAT(ELFCLASS,__ELF_WORD_SIZE) #if BYTE_ORDER == LITTLE_ENDIAN #define ELF_DATA ELFDATA2LSB #elif BYTE_ORDER == BIG_ENDIAN #define ELF_DATA ELFDATA2MSB #else #error "Unknown byte order" #endif +#define __elfN(x) __CONCAT(__CONCAT(__CONCAT(elf,__ELF_WORD_SIZE),_),x) #define __ElfN(x) __CONCAT(__CONCAT(__CONCAT(Elf,__ELF_WORD_SIZE),_),x) #define __ELFN(x) __CONCAT(__CONCAT(__CONCAT(ELF,__ELF_WORD_SIZE),_),x) #define __ElfType(x) typedef __ElfN(x) __CONCAT(Elf_,x) __ElfType(Addr); __ElfType(Half); __ElfType(Off); __ElfType(Sword); __ElfType(Word); __ElfType(Size); __ElfType(Hashelt); __ElfType(Ehdr); __ElfType(Shdr); __ElfType(Phdr); __ElfType(Dyn); __ElfType(Rel); __ElfType(Rela); __ElfType(Sym); #define ELF_R_SYM __ELFN(R_SYM) #define ELF_R_TYPE __ELFN(R_TYPE) #define ELF_R_INFO __ELFN(R_INFO) #define ELF_ST_BIND __ELFN(ST_BIND) #define ELF_ST_TYPE __ELFN(ST_TYPE) #define ELF_ST_INFO __ELFN(ST_INFO) #endif /* !_SYS_ELF_GENERIC_H_ */ Index: head/sys/sys/imgact.h =================================================================== --- head/sys/sys/imgact.h (revision 100383) +++ head/sys/sys/imgact.h (revision 100384) @@ -1,74 +1,75 @@ /*- * Copyright (c) 1993, David Greenman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_IMGACT_H_ #define _SYS_IMGACT_H_ #define MAXSHELLCMDLEN 128 struct vm_object; struct image_params { struct proc *proc; /* our process struct */ struct execve_args *uap; /* syscall arguments */ struct vnode *vp; /* pointer to vnode of file to exec */ struct vm_object *object; /* The vm object for this vp */ struct vattr *attr; /* attributes of file */ const char *image_header; /* head of file to exec */ char *stringbase; /* base address of tmp string storage */ char *stringp; /* current 'end' pointer of tmp strings */ char *endargs; /* end of argv vector */ int stringspace; /* space left in tmp string storage area */ int argc, envc; /* count of argument and environment strings */ char *argv0; /* Replacement for argv[0] when interpreting */ unsigned long entry_addr; /* entry address of target executable */ char vmspace_destroyed; /* flag - we've blown away original vm space */ char interpreted; /* flag - this executable is interpreted */ char interpreter_name[MAXSHELLCMDLEN]; /* name of the interpreter */ void *auxargs; /* ELF Auxinfo structure pointer */ struct vm_page *firstpage; /* first page that we mapped */ char *fname; /* pointer to filename of executable (user space) */ unsigned long ps_strings; /* PS_STRINGS for BSD/OS binaries */ size_t auxarg_size; }; #ifdef _KERNEL int exec_check_permissions(struct image_params *); int exec_extract_strings(struct image_params *); -int exec_new_vmspace(struct image_params *); +int exec_new_vmspace(struct image_params *, vm_offset_t, vm_offset_t, + vm_offset_t); int exec_shell_imgact(struct image_params *); #endif #endif /* !_SYS_IMGACT_H_ */ Index: head/sys/sys/imgact_elf.h =================================================================== --- head/sys/sys/imgact_elf.h (revision 100383) +++ head/sys/sys/imgact_elf.h (revision 100384) @@ -1,112 +1,116 @@ /*- * Copyright (c) 1995-1996 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_IMGACT_ELF_H_ #define _SYS_IMGACT_ELF_H_ #include #ifdef _KERNEL #define AUXARGS_ENTRY(pos, id, val) {suword(pos++, id); suword(pos++, val);} +struct thread; + #if ELF_TARG_CLASS == ELFCLASS32 /* * Structure used to pass infomation from the loader to the * stack fixup routine. */ typedef struct { Elf32_Sword execfd; Elf32_Word phdr; Elf32_Word phent; Elf32_Word phnum; Elf32_Word pagesz; Elf32_Word base; Elf32_Word flags; Elf32_Word entry; Elf32_Word trace; } Elf32_Auxargs; typedef struct { int brand; + int machine; const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */ const char *emul_path; const char *interp_path; struct sysentvec *sysvec; } Elf32_Brandinfo; #define MAX_BRANDS 8 -int elf_brand_inuse(Elf32_Brandinfo *entry); -int elf_insert_brand_entry(Elf32_Brandinfo *entry); -int elf_remove_brand_entry(Elf32_Brandinfo *entry); +int elf32_brand_inuse(Elf32_Brandinfo *entry); +int elf32_insert_brand_entry(Elf32_Brandinfo *entry); +int elf32_remove_brand_entry(Elf32_Brandinfo *entry); +int elf32_freebsd_fixup(register_t **, struct image_params *); +int elf32_coredump(struct thread *, struct vnode *, off_t); #else /* !(ELF_TARG_CLASS == ELFCLASS32) */ /* * Structure used to pass infomation from the loader to the * stack fixup routine. */ typedef struct { Elf64_Sword execfd; Elf64_Addr phdr; Elf64_Word phent; Elf64_Word phnum; Elf64_Word pagesz; Elf64_Addr base; Elf64_Word flags; Elf64_Addr entry; Elf64_Word trace; } Elf64_Auxargs; typedef struct { int brand; + int machine; const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */ const char *emul_path; const char *interp_path; struct sysentvec *sysvec; } Elf64_Brandinfo; #define MAX_BRANDS 8 -int elf_brand_inuse(Elf64_Brandinfo *entry); -int elf_insert_brand_entry(Elf64_Brandinfo *entry); -int elf_remove_brand_entry(Elf64_Brandinfo *entry); +int elf64_brand_inuse(Elf64_Brandinfo *entry); +int elf64_insert_brand_entry(Elf64_Brandinfo *entry); +int elf64_remove_brand_entry(Elf64_Brandinfo *entry); +int elf64_freebsd_fixup(register_t **, struct image_params *); +int elf64_coredump(struct thread *, struct vnode *, off_t); #endif /* ELF_TARG_CLASS == ELFCLASS32 */ - -struct thread; - -int elf_coredump(struct thread *, struct vnode *, off_t); #endif /* _KERNEL */ #endif /* !_SYS_IMGACT_ELF_H_ */ Index: head/sys/sys/sysent.h =================================================================== --- head/sys/sys/sysent.h (revision 100383) +++ head/sys/sys/sysent.h (revision 100384) @@ -1,131 +1,136 @@ /*- * Copyright (c) 1982, 1988, 1991 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_SYSENT_H_ #define _SYS_SYSENT_H_ struct thread; typedef int sy_call_t(struct thread *, void *); struct sysent { /* system call table */ int sy_narg; /* number of arguments */ sy_call_t *sy_call; /* implementing function */ }; #define SYF_ARGMASK 0x0000FFFF #define SYF_MPSAFE 0x00010000 #define SCARG(p,k) ((p)->k) /* get arg from args pointer */ /* placeholder till we integrate rest of lite2 syscallargs changes XXX */ struct image_params; struct __sigset; struct trapframe; struct vnode; struct sysentvec { int sv_size; /* number of entries */ struct sysent *sv_table; /* pointer to sysent */ u_int sv_mask; /* optional mask to index */ int sv_sigsize; /* size of signal translation table */ int *sv_sigtbl; /* signal translation table */ int sv_errsize; /* size of errno translation table */ int *sv_errtbl; /* errno translation table */ int (*sv_transtrap)(int, int); /* translate trap-to-signal mapping */ int (*sv_fixup)(register_t **, struct image_params *); /* stack fixup function */ void (*sv_sendsig)(void (*)(int), int, struct __sigset *, u_long); /* send signal */ char *sv_sigcode; /* start of sigtramp code */ int *sv_szsigcode; /* size of sigtramp code */ void (*sv_prepsyscall)(struct trapframe *, int *, u_int *, caddr_t *); char *sv_name; /* name of binary type */ int (*sv_coredump)(struct thread *, struct vnode *, off_t); /* function to dump core, or NULL */ int (*sv_imgact_try)(struct image_params *); int sv_minsigstksz; /* minimum signal stack size */ + int sv_pagesize; /* pagesize override */ + vm_offset_t sv_maxuser; /* VM_MAXUSER_ADDRESS override */ + vm_offset_t sv_usrstack; /* USRSTACK override */ + register_t *(*sv_copyout_strings)(struct image_params *); + void (*sv_setregs)(struct thread *, u_long, u_long, u_long); }; #ifdef _KERNEL extern struct sysentvec aout_sysvec; extern struct sysentvec elf_freebsd_sysvec; extern struct sysent sysent[]; #define NO_SYSCALL (-1) struct module; struct syscall_module_data { int (*chainevh)(struct module *, int, void *); /* next handler */ void *chainarg; /* arg for next event handler */ int *offset; /* offset into sysent */ struct sysent *new_sysent; /* new sysent */ struct sysent old_sysent; /* old sysent */ }; #define SYSCALL_MODULE(name, offset, new_sysent, evh, arg) \ static struct syscall_module_data name##_syscall_mod = { \ evh, arg, offset, new_sysent, { 0, NULL } \ }; \ \ static moduledata_t name##_mod = { \ #name, \ syscall_module_handler, \ &name##_syscall_mod \ }; \ DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE) #define SYSCALL_MODULE_HELPER(syscallname) \ static int syscallname##_syscall = SYS_##syscallname; \ static struct sysent syscallname##_sysent = { \ (sizeof(struct syscallname ## _args ) \ / sizeof(register_t)), \ (sy_call_t *)& syscallname \ }; \ SYSCALL_MODULE(syscallname, \ & syscallname##_syscall, & syscallname##_sysent, \ NULL, NULL); int syscall_register(int *offset, struct sysent *new_sysent, struct sysent *old_sysent); int syscall_deregister(int *offset, struct sysent *old_sysent); int syscall_module_handler(struct module *mod, int what, void *arg); #endif /* _KERNEL */ #endif /* !_SYS_SYSENT_H_ */ Index: head/sys/vm/vm_extern.h =================================================================== --- head/sys/vm/vm_extern.h (revision 100383) +++ head/sys/vm/vm_extern.h (revision 100384) @@ -1,101 +1,101 @@ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vm_extern.h 8.2 (Berkeley) 1/12/94 * $FreeBSD$ */ #ifndef _VM_EXTERN_H_ #define _VM_EXTERN_H_ struct buf; struct proc; struct vmspace; struct vmtotal; struct mount; struct vnode; #ifdef _KERNEL #ifdef TYPEDEF_FOR_UAP int getpagesize(struct thread *, void *, int *); int madvise(struct thread *, void *, int *); int mincore(struct thread *, void *, int *); int mprotect(struct thread *, void *, int *); int msync(struct thread *, void *, int *); int munmap(struct thread *, void *, int *); int obreak(struct thread *, void *, int *); int sbrk(struct thread *, void *, int *); int sstk(struct thread *, void *, int *); int swapon(struct thread *, void *, int *); #endif /* TYPEDEF_FOR_UAP */ int kernacc(caddr_t, int, int); vm_offset_t kmem_alloc(vm_map_t, vm_size_t); vm_offset_t kmem_alloc_nofault(vm_map_t, vm_size_t); vm_offset_t kmem_alloc_pageable(vm_map_t, vm_size_t); vm_offset_t kmem_alloc_wait(vm_map_t, vm_size_t); void kmem_free(vm_map_t, vm_offset_t, vm_size_t); void kmem_free_wakeup(vm_map_t, vm_offset_t, vm_size_t); void kmem_init(vm_offset_t, vm_offset_t); vm_offset_t kmem_malloc(vm_map_t, vm_size_t, boolean_t); vm_map_t kmem_suballoc(vm_map_t, vm_offset_t *, vm_offset_t *, vm_size_t); void munmapfd(struct thread *, int); int swaponvp(struct thread *, struct vnode *, dev_t , u_long); void swapout_procs(int); int useracc(caddr_t, int, int); int vm_fault(vm_map_t, vm_offset_t, vm_prot_t, int); void vm_fault_copy_entry(vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t); void vm_fault_unwire(vm_map_t, vm_offset_t, vm_offset_t); int vm_fault_wire(vm_map_t, vm_offset_t, vm_offset_t); int vm_fault_user_wire(vm_map_t, vm_offset_t, vm_offset_t); void vm_forkproc(struct thread *, struct proc *, struct thread *, int); void vm_waitproc(struct proc *); int vm_mmap(vm_map_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int, void *, vm_ooffset_t); vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, vm_offset_t, vm_offset_t); void vm_set_page_size(void); struct vmspace *vmspace_alloc(vm_offset_t, vm_offset_t); struct vmspace *vmspace_fork(struct vmspace *); -void vmspace_exec(struct proc *); +void vmspace_exec(struct proc *, vm_offset_t, vm_offset_t); void vmspace_unshare(struct proc *); void vmspace_free(struct vmspace *); void vmspace_exitfree(struct proc *); void vnode_pager_setsize(struct vnode *, vm_ooffset_t); void vslock(caddr_t, u_int); void vsunlock(caddr_t, u_int); void vm_object_print(/* db_expr_t */ long, boolean_t, /* db_expr_t */ long, char *); int vm_fault_quick(caddr_t v, int prot); void vm_proc_new(struct proc *p); void vm_proc_dispose(struct proc *p); #endif /* _KERNEL */ #endif /* !_VM_EXTERN_H_ */ Index: head/sys/vm/vm_map.c =================================================================== --- head/sys/vm/vm_map.c (revision 100383) +++ head/sys/vm/vm_map.c (revision 100384) @@ -1,3163 +1,3162 @@ /* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)vm_map.c 8.3 (Berkeley) 1/12/94 * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * * Authors: Avadis Tevanian, Jr., Michael Wayne Young * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * * $FreeBSD$ */ /* * Virtual memory mapping module. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Virtual memory maps provide for the mapping, protection, * and sharing of virtual memory objects. In addition, * this module provides for an efficient virtual copy of * memory from one map to another. * * Synchronization is required prior to most operations. * * Maps consist of an ordered doubly-linked list of simple * entries; a single hint is used to speed up lookups. * * Since portions of maps are specified by start/end addresses, * which may not align with existing map entries, all * routines merely "clip" entries to these start/end values. * [That is, an entry is split into two, bordering at a * start or end value.] Note that these clippings may not * always be necessary (as the two resulting entries are then * not changed); however, the clipping is done for convenience. * * As mentioned above, virtual copy operations are performed * by copying VM object references from one map to * another, and then marking both regions as copy-on-write. */ /* * vm_map_startup: * * Initialize the vm_map module. Must be called before * any other vm_map routines. * * Map and entry structures are allocated from the general * purpose memory pool with some exceptions: * * - The kernel map and kmem submap are allocated statically. * - Kernel map entries are allocated out of a static pool. * * These restrictions are necessary since malloc() uses the * maps and requires map entries. */ static uma_zone_t mapentzone; static uma_zone_t kmapentzone; static uma_zone_t mapzone; static uma_zone_t vmspace_zone; static struct vm_object kmapentobj; static void vmspace_zinit(void *mem, int size); static void vmspace_zfini(void *mem, int size); static void vm_map_zinit(void *mem, int size); static void vm_map_zfini(void *mem, int size); static void _vm_map_init(vm_map_t map, vm_offset_t min, vm_offset_t max); #ifdef INVARIANTS static void vm_map_zdtor(void *mem, int size, void *arg); static void vmspace_zdtor(void *mem, int size, void *arg); #endif void vm_map_startup(void) { mapzone = uma_zcreate("MAP", sizeof(struct vm_map), NULL, #ifdef INVARIANTS vm_map_zdtor, #else NULL, #endif vm_map_zinit, vm_map_zfini, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); uma_prealloc(mapzone, MAX_KMAP); kmapentzone = uma_zcreate("KMAP ENTRY", sizeof(struct vm_map_entry), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_MTXCLASS | UMA_ZONE_VM); uma_prealloc(kmapentzone, MAX_KMAPENT); mapentzone = uma_zcreate("MAP ENTRY", sizeof(struct vm_map_entry), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); uma_prealloc(mapentzone, MAX_MAPENT); } static void vmspace_zfini(void *mem, int size) { struct vmspace *vm; vm = (struct vmspace *)mem; vm_map_zfini(&vm->vm_map, sizeof(vm->vm_map)); } static void vmspace_zinit(void *mem, int size) { struct vmspace *vm; vm = (struct vmspace *)mem; vm_map_zinit(&vm->vm_map, sizeof(vm->vm_map)); } static void vm_map_zfini(void *mem, int size) { vm_map_t map; map = (vm_map_t)mem; lockdestroy(&map->lock); } static void vm_map_zinit(void *mem, int size) { vm_map_t map; map = (vm_map_t)mem; map->nentries = 0; map->size = 0; map->infork = 0; lockinit(&map->lock, PVM, "thrd_sleep", 0, LK_NOPAUSE); } #ifdef INVARIANTS static void vmspace_zdtor(void *mem, int size, void *arg) { struct vmspace *vm; vm = (struct vmspace *)mem; vm_map_zdtor(&vm->vm_map, sizeof(vm->vm_map), arg); } static void vm_map_zdtor(void *mem, int size, void *arg) { vm_map_t map; map = (vm_map_t)mem; KASSERT(map->nentries == 0, ("map %p nentries == %d on free.", map, map->nentries)); KASSERT(map->size == 0, ("map %p size == %lu on free.", map, (unsigned long)map->size)); KASSERT(map->infork == 0, ("map %p infork == %d on free.", map, map->infork)); } #endif /* INVARIANTS */ /* * Allocate a vmspace structure, including a vm_map and pmap, * and initialize those structures. The refcnt is set to 1. * The remaining fields must be initialized by the caller. */ struct vmspace * vmspace_alloc(min, max) vm_offset_t min, max; { struct vmspace *vm; GIANT_REQUIRED; vm = uma_zalloc(vmspace_zone, M_WAITOK); CTR1(KTR_VM, "vmspace_alloc: %p", vm); _vm_map_init(&vm->vm_map, min, max); pmap_pinit(vmspace_pmap(vm)); vm->vm_map.pmap = vmspace_pmap(vm); /* XXX */ vm->vm_refcnt = 1; vm->vm_shm = NULL; vm->vm_freer = NULL; return (vm); } void vm_init2(void) { uma_zone_set_obj(kmapentzone, &kmapentobj, lmin(cnt.v_page_count, (VM_MAX_KERNEL_ADDRESS - KERNBASE) / PAGE_SIZE) / 8); vmspace_zone = uma_zcreate("VMSPACE", sizeof(struct vmspace), NULL, #ifdef INVARIANTS vmspace_zdtor, #else NULL, #endif vmspace_zinit, vmspace_zfini, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); pmap_init2(); vm_object_init2(); } static __inline void vmspace_dofree(struct vmspace *vm) { CTR1(KTR_VM, "vmspace_free: %p", vm); /* * Lock the map, to wait out all other references to it. * Delete all of the mappings and pages they hold, then call * the pmap module to reclaim anything left. */ vm_map_lock(&vm->vm_map); (void) vm_map_delete(&vm->vm_map, vm->vm_map.min_offset, vm->vm_map.max_offset); vm_map_unlock(&vm->vm_map); pmap_release(vmspace_pmap(vm)); uma_zfree(vmspace_zone, vm); } void vmspace_free(struct vmspace *vm) { GIANT_REQUIRED; if (vm->vm_refcnt == 0) panic("vmspace_free: attempt to free already freed vmspace"); if (--vm->vm_refcnt == 0) vmspace_dofree(vm); } void vmspace_exitfree(struct proc *p) { struct vmspace *vm; GIANT_REQUIRED; if (p == p->p_vmspace->vm_freer) { vm = p->p_vmspace; p->p_vmspace = NULL; vmspace_dofree(vm); } } /* * vmspace_swap_count() - count the approximate swap useage in pages for a * vmspace. * * Swap useage is determined by taking the proportional swap used by * VM objects backing the VM map. To make up for fractional losses, * if the VM object has any swap use at all the associated map entries * count for at least 1 swap page. */ int vmspace_swap_count(struct vmspace *vmspace) { vm_map_t map = &vmspace->vm_map; vm_map_entry_t cur; int count = 0; vm_map_lock_read(map); for (cur = map->header.next; cur != &map->header; cur = cur->next) { vm_object_t object; if ((cur->eflags & MAP_ENTRY_IS_SUB_MAP) == 0 && (object = cur->object.vm_object) != NULL && object->type == OBJT_SWAP ) { int n = (cur->end - cur->start) / PAGE_SIZE; if (object->un_pager.swp.swp_bcount) { count += object->un_pager.swp.swp_bcount * SWAP_META_PAGES * n / object->size + 1; } } } vm_map_unlock_read(map); return (count); } void _vm_map_lock(vm_map_t map, const char *file, int line) { int error; if (map->system_map) GIANT_REQUIRED; error = lockmgr(&map->lock, LK_EXCLUSIVE, NULL, curthread); KASSERT(error == 0, ("%s: failed to get lock", __func__)); map->timestamp++; } void _vm_map_unlock(vm_map_t map, const char *file, int line) { lockmgr(&map->lock, LK_RELEASE, NULL, curthread); } void _vm_map_lock_read(vm_map_t map, const char *file, int line) { int error; if (map->system_map) GIANT_REQUIRED; error = lockmgr(&map->lock, LK_EXCLUSIVE, NULL, curthread); KASSERT(error == 0, ("%s: failed to get lock", __func__)); } void _vm_map_unlock_read(vm_map_t map, const char *file, int line) { lockmgr(&map->lock, LK_RELEASE, NULL, curthread); } int _vm_map_trylock(vm_map_t map, const char *file, int line) { int error; if (map->system_map) GIANT_REQUIRED; error = lockmgr(&map->lock, LK_EXCLUSIVE | LK_NOWAIT, NULL, curthread); return (error == 0); } int _vm_map_lock_upgrade(vm_map_t map, const char *file, int line) { KASSERT(lockstatus(&map->lock, curthread) == LK_EXCLUSIVE, ("%s: lock not held", __func__)); map->timestamp++; return (0); } void _vm_map_lock_downgrade(vm_map_t map, const char *file, int line) { KASSERT(lockstatus(&map->lock, curthread) == LK_EXCLUSIVE, ("%s: lock not held", __func__)); } /* * vm_map_unlock_and_wait: */ int vm_map_unlock_and_wait(vm_map_t map, boolean_t user_wait) { int retval; mtx_lock(&Giant); vm_map_unlock(map); retval = tsleep(&map->root, PVM, "vmmapw", 0); mtx_unlock(&Giant); return (retval); } /* * vm_map_wakeup: */ void vm_map_wakeup(vm_map_t map) { /* * Acquire and release Giant to prevent a wakeup() from being * performed (and lost) between the vm_map_unlock() and the * tsleep() in vm_map_unlock_and_wait(). */ mtx_lock(&Giant); mtx_unlock(&Giant); wakeup(&map->root); } long vmspace_resident_count(struct vmspace *vmspace) { return pmap_resident_count(vmspace_pmap(vmspace)); } /* * vm_map_create: * * Creates and returns a new empty VM map with * the given physical map structure, and having * the given lower and upper address bounds. */ vm_map_t vm_map_create(pmap_t pmap, vm_offset_t min, vm_offset_t max) { vm_map_t result; result = uma_zalloc(mapzone, M_WAITOK); CTR1(KTR_VM, "vm_map_create: %p", result); _vm_map_init(result, min, max); result->pmap = pmap; return (result); } /* * Initialize an existing vm_map structure * such as that in the vmspace structure. * The pmap is set elsewhere. */ static void _vm_map_init(vm_map_t map, vm_offset_t min, vm_offset_t max) { map->header.next = map->header.prev = &map->header; map->needs_wakeup = FALSE; map->system_map = 0; map->min_offset = min; map->max_offset = max; map->first_free = &map->header; map->root = NULL; map->timestamp = 0; } void vm_map_init(vm_map_t map, vm_offset_t min, vm_offset_t max) { _vm_map_init(map, min, max); lockinit(&map->lock, PVM, "thrd_sleep", 0, LK_NOPAUSE); } /* * vm_map_entry_dispose: [ internal use only ] * * Inverse of vm_map_entry_create. */ static void vm_map_entry_dispose(vm_map_t map, vm_map_entry_t entry) { uma_zfree(map->system_map ? kmapentzone : mapentzone, entry); } /* * vm_map_entry_create: [ internal use only ] * * Allocates a VM map entry for insertion. * No entry fields are filled in. */ static vm_map_entry_t vm_map_entry_create(vm_map_t map) { vm_map_entry_t new_entry; if (map->system_map) new_entry = uma_zalloc(kmapentzone, M_NOWAIT); else new_entry = uma_zalloc(mapentzone, M_WAITOK); if (new_entry == NULL) panic("vm_map_entry_create: kernel resources exhausted"); return (new_entry); } /* * vm_map_entry_set_behavior: * * Set the expected access behavior, either normal, random, or * sequential. */ static __inline void vm_map_entry_set_behavior(vm_map_entry_t entry, u_char behavior) { entry->eflags = (entry->eflags & ~MAP_ENTRY_BEHAV_MASK) | (behavior & MAP_ENTRY_BEHAV_MASK); } /* * vm_map_entry_splay: * * Implements Sleator and Tarjan's top-down splay algorithm. Returns * the vm_map_entry containing the given address. If, however, that * address is not found in the vm_map, returns a vm_map_entry that is * adjacent to the address, coming before or after it. */ static vm_map_entry_t vm_map_entry_splay(vm_offset_t address, vm_map_entry_t root) { struct vm_map_entry dummy; vm_map_entry_t lefttreemax, righttreemin, y; if (root == NULL) return (root); lefttreemax = righttreemin = &dummy; for (;; root = y) { if (address < root->start) { if ((y = root->left) == NULL) break; if (address < y->start) { /* Rotate right. */ root->left = y->right; y->right = root; root = y; if ((y = root->left) == NULL) break; } /* Link into the new root's right tree. */ righttreemin->left = root; righttreemin = root; } else if (address >= root->end) { if ((y = root->right) == NULL) break; if (address >= y->end) { /* Rotate left. */ root->right = y->left; y->left = root; root = y; if ((y = root->right) == NULL) break; } /* Link into the new root's left tree. */ lefttreemax->right = root; lefttreemax = root; } else break; } /* Assemble the new root. */ lefttreemax->right = root->left; righttreemin->left = root->right; root->left = dummy.right; root->right = dummy.left; return (root); } /* * vm_map_entry_{un,}link: * * Insert/remove entries from maps. */ static void vm_map_entry_link(vm_map_t map, vm_map_entry_t after_where, vm_map_entry_t entry) { CTR4(KTR_VM, "vm_map_entry_link: map %p, nentries %d, entry %p, after %p", map, map->nentries, entry, after_where); map->nentries++; entry->prev = after_where; entry->next = after_where->next; entry->next->prev = entry; after_where->next = entry; if (after_where != &map->header) { if (after_where != map->root) vm_map_entry_splay(after_where->start, map->root); entry->right = after_where->right; entry->left = after_where; after_where->right = NULL; } else { entry->right = map->root; entry->left = NULL; } map->root = entry; } static void vm_map_entry_unlink(vm_map_t map, vm_map_entry_t entry) { vm_map_entry_t next, prev, root; if (entry != map->root) vm_map_entry_splay(entry->start, map->root); if (entry->left == NULL) root = entry->right; else { root = vm_map_entry_splay(entry->start, entry->left); root->right = entry->right; } map->root = root; prev = entry->prev; next = entry->next; next->prev = prev; prev->next = next; map->nentries--; CTR3(KTR_VM, "vm_map_entry_unlink: map %p, nentries %d, entry %p", map, map->nentries, entry); } /* * vm_map_lookup_entry: [ internal use only ] * * Finds the map entry containing (or * immediately preceding) the specified address * in the given map; the entry is returned * in the "entry" parameter. The boolean * result indicates whether the address is * actually contained in the map. */ boolean_t vm_map_lookup_entry( vm_map_t map, vm_offset_t address, vm_map_entry_t *entry) /* OUT */ { vm_map_entry_t cur; cur = vm_map_entry_splay(address, map->root); if (cur == NULL) *entry = &map->header; else { map->root = cur; if (address >= cur->start) { *entry = cur; if (cur->end > address) return (TRUE); } else *entry = cur->prev; } return (FALSE); } /* * vm_map_insert: * * Inserts the given whole VM object into the target * map at the specified address range. The object's * size should match that of the address range. * * Requires that the map be locked, and leaves it so. * * If object is non-NULL, ref count must be bumped by caller * prior to making call to account for the new entry. */ int vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset, vm_offset_t start, vm_offset_t end, vm_prot_t prot, vm_prot_t max, int cow) { vm_map_entry_t new_entry; vm_map_entry_t prev_entry; vm_map_entry_t temp_entry; vm_eflags_t protoeflags; /* * Check that the start and end points are not bogus. */ if ((start < map->min_offset) || (end > map->max_offset) || (start >= end)) return (KERN_INVALID_ADDRESS); /* * Find the entry prior to the proposed starting address; if it's part * of an existing entry, this range is bogus. */ if (vm_map_lookup_entry(map, start, &temp_entry)) return (KERN_NO_SPACE); prev_entry = temp_entry; /* * Assert that the next entry doesn't overlap the end point. */ if ((prev_entry->next != &map->header) && (prev_entry->next->start < end)) return (KERN_NO_SPACE); protoeflags = 0; if (cow & MAP_COPY_ON_WRITE) protoeflags |= MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY; if (cow & MAP_NOFAULT) { protoeflags |= MAP_ENTRY_NOFAULT; KASSERT(object == NULL, ("vm_map_insert: paradoxical MAP_NOFAULT request")); } if (cow & MAP_DISABLE_SYNCER) protoeflags |= MAP_ENTRY_NOSYNC; if (cow & MAP_DISABLE_COREDUMP) protoeflags |= MAP_ENTRY_NOCOREDUMP; if (object) { /* * When object is non-NULL, it could be shared with another * process. We have to set or clear OBJ_ONEMAPPING * appropriately. */ mtx_lock(&Giant); if ((object->ref_count > 1) || (object->shadow_count != 0)) { vm_object_clear_flag(object, OBJ_ONEMAPPING); } mtx_unlock(&Giant); } else if ((prev_entry != &map->header) && (prev_entry->eflags == protoeflags) && (prev_entry->end == start) && (prev_entry->wired_count == 0) && ((prev_entry->object.vm_object == NULL) || vm_object_coalesce(prev_entry->object.vm_object, OFF_TO_IDX(prev_entry->offset), (vm_size_t)(prev_entry->end - prev_entry->start), (vm_size_t)(end - prev_entry->end)))) { /* * We were able to extend the object. Determine if we * can extend the previous map entry to include the * new range as well. */ if ((prev_entry->inheritance == VM_INHERIT_DEFAULT) && (prev_entry->protection == prot) && (prev_entry->max_protection == max)) { map->size += (end - prev_entry->end); prev_entry->end = end; vm_map_simplify_entry(map, prev_entry); return (KERN_SUCCESS); } /* * If we can extend the object but cannot extend the * map entry, we have to create a new map entry. We * must bump the ref count on the extended object to * account for it. object may be NULL. */ object = prev_entry->object.vm_object; offset = prev_entry->offset + (prev_entry->end - prev_entry->start); vm_object_reference(object); } /* * NOTE: if conditionals fail, object can be NULL here. This occurs * in things like the buffer map where we manage kva but do not manage * backing objects. */ /* * Create a new entry */ new_entry = vm_map_entry_create(map); new_entry->start = start; new_entry->end = end; new_entry->eflags = protoeflags; new_entry->object.vm_object = object; new_entry->offset = offset; new_entry->avail_ssize = 0; new_entry->inheritance = VM_INHERIT_DEFAULT; new_entry->protection = prot; new_entry->max_protection = max; new_entry->wired_count = 0; /* * Insert the new entry into the list */ vm_map_entry_link(map, prev_entry, new_entry); map->size += new_entry->end - new_entry->start; /* * Update the free space hint */ if ((map->first_free == prev_entry) && (prev_entry->end >= new_entry->start)) { map->first_free = new_entry; } #if 0 /* * Temporarily removed to avoid MAP_STACK panic, due to * MAP_STACK being a huge hack. Will be added back in * when MAP_STACK (and the user stack mapping) is fixed. */ /* * It may be possible to simplify the entry */ vm_map_simplify_entry(map, new_entry); #endif if (cow & (MAP_PREFAULT|MAP_PREFAULT_PARTIAL)) { mtx_lock(&Giant); pmap_object_init_pt(map->pmap, start, object, OFF_TO_IDX(offset), end - start, cow & MAP_PREFAULT_PARTIAL); mtx_unlock(&Giant); } return (KERN_SUCCESS); } /* * Find sufficient space for `length' bytes in the given map, starting at * `start'. The map must be locked. Returns 0 on success, 1 on no space. */ int vm_map_findspace( vm_map_t map, vm_offset_t start, vm_size_t length, vm_offset_t *addr) { vm_map_entry_t entry, next; vm_offset_t end; if (start < map->min_offset) start = map->min_offset; if (start > map->max_offset) return (1); /* * Look for the first possible address; if there's already something * at this address, we have to start after it. */ if (start == map->min_offset) { if ((entry = map->first_free) != &map->header) start = entry->end; } else { vm_map_entry_t tmp; if (vm_map_lookup_entry(map, start, &tmp)) start = tmp->end; entry = tmp; } /* * Look through the rest of the map, trying to fit a new region in the * gap between existing regions, or after the very last region. */ for (;; start = (entry = next)->end) { /* * Find the end of the proposed new region. Be sure we didn't * go beyond the end of the map, or wrap around the address; * if so, we lose. Otherwise, if this is the last entry, or * if the proposed new region fits before the next entry, we * win. */ end = start + length; if (end > map->max_offset || end < start) return (1); next = entry->next; if (next == &map->header || next->start >= end) break; } *addr = start; if (map == kernel_map) { vm_offset_t ksize; if ((ksize = round_page(start + length)) > kernel_vm_end) { mtx_lock(&Giant); pmap_growkernel(ksize); mtx_unlock(&Giant); } } return (0); } /* * vm_map_find finds an unallocated region in the target address * map with the given length. The search is defined to be * first-fit from the specified address; the region found is * returned in the same parameter. * * If object is non-NULL, ref count must be bumped by caller * prior to making call to account for the new entry. */ int vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset, vm_offset_t *addr, /* IN/OUT */ vm_size_t length, boolean_t find_space, vm_prot_t prot, vm_prot_t max, int cow) { vm_offset_t start; int result, s = 0; start = *addr; if (map == kmem_map) s = splvm(); vm_map_lock(map); if (find_space) { if (vm_map_findspace(map, start, length, addr)) { vm_map_unlock(map); if (map == kmem_map) splx(s); return (KERN_NO_SPACE); } start = *addr; } result = vm_map_insert(map, object, offset, start, start + length, prot, max, cow); vm_map_unlock(map); if (map == kmem_map) splx(s); return (result); } /* * vm_map_simplify_entry: * * Simplify the given map entry by merging with either neighbor. This * routine also has the ability to merge with both neighbors. * * The map must be locked. * * This routine guarentees that the passed entry remains valid (though * possibly extended). When merging, this routine may delete one or * both neighbors. */ void vm_map_simplify_entry(vm_map_t map, vm_map_entry_t entry) { vm_map_entry_t next, prev; vm_size_t prevsize, esize; if (entry->eflags & (MAP_ENTRY_IN_TRANSITION | MAP_ENTRY_IS_SUB_MAP)) return; prev = entry->prev; if (prev != &map->header) { prevsize = prev->end - prev->start; if ( (prev->end == entry->start) && (prev->object.vm_object == entry->object.vm_object) && (!prev->object.vm_object || (prev->offset + prevsize == entry->offset)) && (prev->eflags == entry->eflags) && (prev->protection == entry->protection) && (prev->max_protection == entry->max_protection) && (prev->inheritance == entry->inheritance) && (prev->wired_count == entry->wired_count)) { if (map->first_free == prev) map->first_free = entry; vm_map_entry_unlink(map, prev); entry->start = prev->start; entry->offset = prev->offset; if (prev->object.vm_object) vm_object_deallocate(prev->object.vm_object); vm_map_entry_dispose(map, prev); } } next = entry->next; if (next != &map->header) { esize = entry->end - entry->start; if ((entry->end == next->start) && (next->object.vm_object == entry->object.vm_object) && (!entry->object.vm_object || (entry->offset + esize == next->offset)) && (next->eflags == entry->eflags) && (next->protection == entry->protection) && (next->max_protection == entry->max_protection) && (next->inheritance == entry->inheritance) && (next->wired_count == entry->wired_count)) { if (map->first_free == next) map->first_free = entry; vm_map_entry_unlink(map, next); entry->end = next->end; if (next->object.vm_object) vm_object_deallocate(next->object.vm_object); vm_map_entry_dispose(map, next); } } } /* * vm_map_clip_start: [ internal use only ] * * Asserts that the given entry begins at or after * the specified address; if necessary, * it splits the entry into two. */ #define vm_map_clip_start(map, entry, startaddr) \ { \ if (startaddr > entry->start) \ _vm_map_clip_start(map, entry, startaddr); \ } /* * This routine is called only when it is known that * the entry must be split. */ static void _vm_map_clip_start(vm_map_t map, vm_map_entry_t entry, vm_offset_t start) { vm_map_entry_t new_entry; /* * Split off the front portion -- note that we must insert the new * entry BEFORE this one, so that this entry has the specified * starting address. */ vm_map_simplify_entry(map, entry); /* * If there is no object backing this entry, we might as well create * one now. If we defer it, an object can get created after the map * is clipped, and individual objects will be created for the split-up * map. This is a bit of a hack, but is also about the best place to * put this improvement. */ if (entry->object.vm_object == NULL && !map->system_map) { vm_object_t object; object = vm_object_allocate(OBJT_DEFAULT, atop(entry->end - entry->start)); entry->object.vm_object = object; entry->offset = 0; } new_entry = vm_map_entry_create(map); *new_entry = *entry; new_entry->end = start; entry->offset += (start - entry->start); entry->start = start; vm_map_entry_link(map, entry->prev, new_entry); if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { vm_object_reference(new_entry->object.vm_object); } } /* * vm_map_clip_end: [ internal use only ] * * Asserts that the given entry ends at or before * the specified address; if necessary, * it splits the entry into two. */ #define vm_map_clip_end(map, entry, endaddr) \ { \ if (endaddr < entry->end) \ _vm_map_clip_end(map, entry, endaddr); \ } /* * This routine is called only when it is known that * the entry must be split. */ static void _vm_map_clip_end(vm_map_t map, vm_map_entry_t entry, vm_offset_t end) { vm_map_entry_t new_entry; /* * If there is no object backing this entry, we might as well create * one now. If we defer it, an object can get created after the map * is clipped, and individual objects will be created for the split-up * map. This is a bit of a hack, but is also about the best place to * put this improvement. */ if (entry->object.vm_object == NULL && !map->system_map) { vm_object_t object; object = vm_object_allocate(OBJT_DEFAULT, atop(entry->end - entry->start)); entry->object.vm_object = object; entry->offset = 0; } /* * Create a new entry and insert it AFTER the specified entry */ new_entry = vm_map_entry_create(map); *new_entry = *entry; new_entry->start = entry->end = end; new_entry->offset += (end - entry->start); vm_map_entry_link(map, entry, new_entry); if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { vm_object_reference(new_entry->object.vm_object); } } /* * VM_MAP_RANGE_CHECK: [ internal use only ] * * Asserts that the starting and ending region * addresses fall within the valid range of the map. */ #define VM_MAP_RANGE_CHECK(map, start, end) \ { \ if (start < vm_map_min(map)) \ start = vm_map_min(map); \ if (end > vm_map_max(map)) \ end = vm_map_max(map); \ if (start > end) \ start = end; \ } /* * vm_map_submap: [ kernel use only ] * * Mark the given range as handled by a subordinate map. * * This range must have been created with vm_map_find, * and no other operations may have been performed on this * range prior to calling vm_map_submap. * * Only a limited number of operations can be performed * within this rage after calling vm_map_submap: * vm_fault * [Don't try vm_map_copy!] * * To remove a submapping, one must first remove the * range from the superior map, and then destroy the * submap (if desired). [Better yet, don't try it.] */ int vm_map_submap( vm_map_t map, vm_offset_t start, vm_offset_t end, vm_map_t submap) { vm_map_entry_t entry; int result = KERN_INVALID_ARGUMENT; vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); if (vm_map_lookup_entry(map, start, &entry)) { vm_map_clip_start(map, entry, start); } else entry = entry->next; vm_map_clip_end(map, entry, end); if ((entry->start == start) && (entry->end == end) && ((entry->eflags & MAP_ENTRY_COW) == 0) && (entry->object.vm_object == NULL)) { entry->object.sub_map = submap; entry->eflags |= MAP_ENTRY_IS_SUB_MAP; result = KERN_SUCCESS; } vm_map_unlock(map); return (result); } /* * vm_map_protect: * * Sets the protection of the specified address * region in the target map. If "set_max" is * specified, the maximum protection is to be set; * otherwise, only the current protection is affected. */ int vm_map_protect(vm_map_t map, vm_offset_t start, vm_offset_t end, vm_prot_t new_prot, boolean_t set_max) { vm_map_entry_t current; vm_map_entry_t entry; vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); if (vm_map_lookup_entry(map, start, &entry)) { vm_map_clip_start(map, entry, start); } else { entry = entry->next; } /* * Make a first pass to check for protection violations. */ current = entry; while ((current != &map->header) && (current->start < end)) { if (current->eflags & MAP_ENTRY_IS_SUB_MAP) { vm_map_unlock(map); return (KERN_INVALID_ARGUMENT); } if ((new_prot & current->max_protection) != new_prot) { vm_map_unlock(map); return (KERN_PROTECTION_FAILURE); } current = current->next; } /* * Go back and fix up protections. [Note that clipping is not * necessary the second time.] */ current = entry; while ((current != &map->header) && (current->start < end)) { vm_prot_t old_prot; vm_map_clip_end(map, current, end); old_prot = current->protection; if (set_max) current->protection = (current->max_protection = new_prot) & old_prot; else current->protection = new_prot; /* * Update physical map if necessary. Worry about copy-on-write * here -- CHECK THIS XXX */ if (current->protection != old_prot) { mtx_lock(&Giant); #define MASK(entry) (((entry)->eflags & MAP_ENTRY_COW) ? ~VM_PROT_WRITE : \ VM_PROT_ALL) pmap_protect(map->pmap, current->start, current->end, current->protection & MASK(current)); #undef MASK mtx_unlock(&Giant); } vm_map_simplify_entry(map, current); current = current->next; } vm_map_unlock(map); return (KERN_SUCCESS); } /* * vm_map_madvise: * * This routine traverses a processes map handling the madvise * system call. Advisories are classified as either those effecting * the vm_map_entry structure, or those effecting the underlying * objects. */ int vm_map_madvise( vm_map_t map, vm_offset_t start, vm_offset_t end, int behav) { vm_map_entry_t current, entry; int modify_map = 0; /* * Some madvise calls directly modify the vm_map_entry, in which case * we need to use an exclusive lock on the map and we need to perform * various clipping operations. Otherwise we only need a read-lock * on the map. */ switch(behav) { case MADV_NORMAL: case MADV_SEQUENTIAL: case MADV_RANDOM: case MADV_NOSYNC: case MADV_AUTOSYNC: case MADV_NOCORE: case MADV_CORE: modify_map = 1; vm_map_lock(map); break; case MADV_WILLNEED: case MADV_DONTNEED: case MADV_FREE: vm_map_lock_read(map); break; default: return (KERN_INVALID_ARGUMENT); } /* * Locate starting entry and clip if necessary. */ VM_MAP_RANGE_CHECK(map, start, end); if (vm_map_lookup_entry(map, start, &entry)) { if (modify_map) vm_map_clip_start(map, entry, start); } else { entry = entry->next; } if (modify_map) { /* * madvise behaviors that are implemented in the vm_map_entry. * * We clip the vm_map_entry so that behavioral changes are * limited to the specified address range. */ for (current = entry; (current != &map->header) && (current->start < end); current = current->next ) { if (current->eflags & MAP_ENTRY_IS_SUB_MAP) continue; vm_map_clip_end(map, current, end); switch (behav) { case MADV_NORMAL: vm_map_entry_set_behavior(current, MAP_ENTRY_BEHAV_NORMAL); break; case MADV_SEQUENTIAL: vm_map_entry_set_behavior(current, MAP_ENTRY_BEHAV_SEQUENTIAL); break; case MADV_RANDOM: vm_map_entry_set_behavior(current, MAP_ENTRY_BEHAV_RANDOM); break; case MADV_NOSYNC: current->eflags |= MAP_ENTRY_NOSYNC; break; case MADV_AUTOSYNC: current->eflags &= ~MAP_ENTRY_NOSYNC; break; case MADV_NOCORE: current->eflags |= MAP_ENTRY_NOCOREDUMP; break; case MADV_CORE: current->eflags &= ~MAP_ENTRY_NOCOREDUMP; break; default: break; } vm_map_simplify_entry(map, current); } vm_map_unlock(map); } else { vm_pindex_t pindex; int count; /* * madvise behaviors that are implemented in the underlying * vm_object. * * Since we don't clip the vm_map_entry, we have to clip * the vm_object pindex and count. */ for (current = entry; (current != &map->header) && (current->start < end); current = current->next ) { vm_offset_t useStart; if (current->eflags & MAP_ENTRY_IS_SUB_MAP) continue; pindex = OFF_TO_IDX(current->offset); count = atop(current->end - current->start); useStart = current->start; if (current->start < start) { pindex += atop(start - current->start); count -= atop(start - current->start); useStart = start; } if (current->end > end) count -= atop(current->end - end); if (count <= 0) continue; vm_object_madvise(current->object.vm_object, pindex, count, behav); if (behav == MADV_WILLNEED) { mtx_lock(&Giant); pmap_object_init_pt( map->pmap, useStart, current->object.vm_object, pindex, (count << PAGE_SHIFT), MAP_PREFAULT_MADVISE ); mtx_unlock(&Giant); } } vm_map_unlock_read(map); } return (0); } /* * vm_map_inherit: * * Sets the inheritance of the specified address * range in the target map. Inheritance * affects how the map will be shared with * child maps at the time of vm_map_fork. */ int vm_map_inherit(vm_map_t map, vm_offset_t start, vm_offset_t end, vm_inherit_t new_inheritance) { vm_map_entry_t entry; vm_map_entry_t temp_entry; switch (new_inheritance) { case VM_INHERIT_NONE: case VM_INHERIT_COPY: case VM_INHERIT_SHARE: break; default: return (KERN_INVALID_ARGUMENT); } vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); if (vm_map_lookup_entry(map, start, &temp_entry)) { entry = temp_entry; vm_map_clip_start(map, entry, start); } else entry = temp_entry->next; while ((entry != &map->header) && (entry->start < end)) { vm_map_clip_end(map, entry, end); entry->inheritance = new_inheritance; vm_map_simplify_entry(map, entry); entry = entry->next; } vm_map_unlock(map); return (KERN_SUCCESS); } /* * vm_map_unwire: * * Implements both kernel and user unwiring. */ int vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, boolean_t user_unwire) { vm_map_entry_t entry, first_entry, tmp_entry; vm_offset_t saved_start; unsigned int last_timestamp; int rv; boolean_t need_wakeup, result; vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); if (!vm_map_lookup_entry(map, start, &first_entry)) { vm_map_unlock(map); return (KERN_INVALID_ADDRESS); } last_timestamp = map->timestamp; entry = first_entry; while (entry != &map->header && entry->start < end) { if (entry->eflags & MAP_ENTRY_IN_TRANSITION) { /* * We have not yet clipped the entry. */ saved_start = (start >= entry->start) ? start : entry->start; entry->eflags |= MAP_ENTRY_NEEDS_WAKEUP; if (vm_map_unlock_and_wait(map, user_unwire)) { /* * Allow interruption of user unwiring? */ } vm_map_lock(map); if (last_timestamp+1 != map->timestamp) { /* * Look again for the entry because the map was * modified while it was unlocked. * Specifically, the entry may have been * clipped, merged, or deleted. */ if (!vm_map_lookup_entry(map, saved_start, &tmp_entry)) { if (saved_start == start) { /* * First_entry has been deleted. */ vm_map_unlock(map); return (KERN_INVALID_ADDRESS); } end = saved_start; rv = KERN_INVALID_ADDRESS; goto done; } if (entry == first_entry) first_entry = tmp_entry; else first_entry = NULL; entry = tmp_entry; } last_timestamp = map->timestamp; continue; } vm_map_clip_start(map, entry, start); vm_map_clip_end(map, entry, end); /* * Mark the entry in case the map lock is released. (See * above.) */ entry->eflags |= MAP_ENTRY_IN_TRANSITION; /* * Check the map for holes in the specified region. */ if (entry->end < end && (entry->next == &map->header || entry->next->start > entry->end)) { end = entry->end; rv = KERN_INVALID_ADDRESS; goto done; } /* * Require that the entry is wired. */ if (entry->wired_count == 0 || (user_unwire && (entry->eflags & MAP_ENTRY_USER_WIRED) == 0)) { end = entry->end; rv = KERN_INVALID_ARGUMENT; goto done; } entry = entry->next; } rv = KERN_SUCCESS; done: need_wakeup = FALSE; if (first_entry == NULL) { result = vm_map_lookup_entry(map, start, &first_entry); KASSERT(result, ("vm_map_unwire: lookup failed")); } entry = first_entry; while (entry != &map->header && entry->start < end) { if (rv == KERN_SUCCESS) { if (user_unwire) entry->eflags &= ~MAP_ENTRY_USER_WIRED; entry->wired_count--; if (entry->wired_count == 0) { /* * Retain the map lock. */ vm_fault_unwire(map, entry->start, entry->end); } } KASSERT(entry->eflags & MAP_ENTRY_IN_TRANSITION, ("vm_map_unwire: in-transition flag missing")); entry->eflags &= ~MAP_ENTRY_IN_TRANSITION; if (entry->eflags & MAP_ENTRY_NEEDS_WAKEUP) { entry->eflags &= ~MAP_ENTRY_NEEDS_WAKEUP; need_wakeup = TRUE; } vm_map_simplify_entry(map, entry); entry = entry->next; } vm_map_unlock(map); if (need_wakeup) vm_map_wakeup(map); return (rv); } /* * vm_map_wire: * * Implements both kernel and user wiring. */ int vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, boolean_t user_wire) { vm_map_entry_t entry, first_entry, tmp_entry; vm_offset_t saved_end, saved_start; unsigned int last_timestamp; int rv; boolean_t need_wakeup, result; vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); if (!vm_map_lookup_entry(map, start, &first_entry)) { vm_map_unlock(map); return (KERN_INVALID_ADDRESS); } last_timestamp = map->timestamp; entry = first_entry; while (entry != &map->header && entry->start < end) { if (entry->eflags & MAP_ENTRY_IN_TRANSITION) { /* * We have not yet clipped the entry. */ saved_start = (start >= entry->start) ? start : entry->start; entry->eflags |= MAP_ENTRY_NEEDS_WAKEUP; if (vm_map_unlock_and_wait(map, user_wire)) { /* * Allow interruption of user wiring? */ } vm_map_lock(map); if (last_timestamp + 1 != map->timestamp) { /* * Look again for the entry because the map was * modified while it was unlocked. * Specifically, the entry may have been * clipped, merged, or deleted. */ if (!vm_map_lookup_entry(map, saved_start, &tmp_entry)) { if (saved_start == start) { /* * first_entry has been deleted. */ vm_map_unlock(map); return (KERN_INVALID_ADDRESS); } end = saved_start; rv = KERN_INVALID_ADDRESS; goto done; } if (entry == first_entry) first_entry = tmp_entry; else first_entry = NULL; entry = tmp_entry; } last_timestamp = map->timestamp; continue; } vm_map_clip_start(map, entry, start); vm_map_clip_end(map, entry, end); /* * Mark the entry in case the map lock is released. (See * above.) */ entry->eflags |= MAP_ENTRY_IN_TRANSITION; /* * */ if (entry->wired_count == 0) { entry->wired_count++; saved_start = entry->start; saved_end = entry->end; /* * Release the map lock, relying on the in-transition * mark. */ vm_map_unlock(map); if (user_wire) rv = vm_fault_user_wire(map, saved_start, saved_end); else rv = vm_fault_wire(map, saved_start, saved_end); vm_map_lock(map); if (last_timestamp + 1 != map->timestamp) { /* * Look again for the entry because the map was * modified while it was unlocked. The entry * may have been clipped, but NOT merged or * deleted. */ result = vm_map_lookup_entry(map, saved_start, &tmp_entry); KASSERT(result, ("vm_map_wire: lookup failed")); if (entry == first_entry) first_entry = tmp_entry; else first_entry = NULL; entry = tmp_entry; while (entry->end < saved_end) { if (rv != KERN_SUCCESS) { KASSERT(entry->wired_count == 1, ("vm_map_wire: bad count")); entry->wired_count = -1; } entry = entry->next; } } last_timestamp = map->timestamp; if (rv != KERN_SUCCESS) { KASSERT(entry->wired_count == 1, ("vm_map_wire: bad count")); /* * Assign an out-of-range value to represent * the failure to wire this entry. */ entry->wired_count = -1; end = entry->end; goto done; } } else if (!user_wire || (entry->eflags & MAP_ENTRY_USER_WIRED) == 0) { entry->wired_count++; } /* * Check the map for holes in the specified region. */ if (entry->end < end && (entry->next == &map->header || entry->next->start > entry->end)) { end = entry->end; rv = KERN_INVALID_ADDRESS; goto done; } entry = entry->next; } rv = KERN_SUCCESS; done: need_wakeup = FALSE; if (first_entry == NULL) { result = vm_map_lookup_entry(map, start, &first_entry); KASSERT(result, ("vm_map_wire: lookup failed")); } entry = first_entry; while (entry != &map->header && entry->start < end) { if (rv == KERN_SUCCESS) { if (user_wire) entry->eflags |= MAP_ENTRY_USER_WIRED; } else if (entry->wired_count == -1) { /* * Wiring failed on this entry. Thus, unwiring is * unnecessary. */ entry->wired_count = 0; } else { if (!user_wire || (entry->wired_count == 1 && (entry->eflags & MAP_ENTRY_USER_WIRED) == 0)) entry->wired_count--; if (entry->wired_count == 0) { /* * Retain the map lock. */ vm_fault_unwire(map, entry->start, entry->end); } } KASSERT(entry->eflags & MAP_ENTRY_IN_TRANSITION, ("vm_map_wire: in-transition flag missing")); entry->eflags &= ~MAP_ENTRY_IN_TRANSITION; if (entry->eflags & MAP_ENTRY_NEEDS_WAKEUP) { entry->eflags &= ~MAP_ENTRY_NEEDS_WAKEUP; need_wakeup = TRUE; } vm_map_simplify_entry(map, entry); entry = entry->next; } vm_map_unlock(map); if (need_wakeup) vm_map_wakeup(map); return (rv); } /* * vm_map_clean * * Push any dirty cached pages in the address range to their pager. * If syncio is TRUE, dirty pages are written synchronously. * If invalidate is TRUE, any cached pages are freed as well. * * Returns an error if any part of the specified range is not mapped. */ int vm_map_clean( vm_map_t map, vm_offset_t start, vm_offset_t end, boolean_t syncio, boolean_t invalidate) { vm_map_entry_t current; vm_map_entry_t entry; vm_size_t size; vm_object_t object; vm_ooffset_t offset; GIANT_REQUIRED; vm_map_lock_read(map); VM_MAP_RANGE_CHECK(map, start, end); if (!vm_map_lookup_entry(map, start, &entry)) { vm_map_unlock_read(map); return (KERN_INVALID_ADDRESS); } /* * Make a first pass to check for holes. */ for (current = entry; current->start < end; current = current->next) { if (current->eflags & MAP_ENTRY_IS_SUB_MAP) { vm_map_unlock_read(map); return (KERN_INVALID_ARGUMENT); } if (end > current->end && (current->next == &map->header || current->end != current->next->start)) { vm_map_unlock_read(map); return (KERN_INVALID_ADDRESS); } } if (invalidate) pmap_remove(vm_map_pmap(map), start, end); /* * Make a second pass, cleaning/uncaching pages from the indicated * objects as we go. */ for (current = entry; current->start < end; current = current->next) { offset = current->offset + (start - current->start); size = (end <= current->end ? end : current->end) - start; if (current->eflags & MAP_ENTRY_IS_SUB_MAP) { vm_map_t smap; vm_map_entry_t tentry; vm_size_t tsize; smap = current->object.sub_map; vm_map_lock_read(smap); (void) vm_map_lookup_entry(smap, offset, &tentry); tsize = tentry->end - offset; if (tsize < size) size = tsize; object = tentry->object.vm_object; offset = tentry->offset + (offset - tentry->start); vm_map_unlock_read(smap); } else { object = current->object.vm_object; } /* * Note that there is absolutely no sense in writing out * anonymous objects, so we track down the vnode object * to write out. * We invalidate (remove) all pages from the address space * anyway, for semantic correctness. * * note: certain anonymous maps, such as MAP_NOSYNC maps, * may start out with a NULL object. */ while (object && object->backing_object) { object = object->backing_object; offset += object->backing_object_offset; if (object->size < OFF_TO_IDX(offset + size)) size = IDX_TO_OFF(object->size) - offset; } if (object && (object->type == OBJT_VNODE) && (current->protection & VM_PROT_WRITE)) { /* * Flush pages if writing is allowed, invalidate them * if invalidation requested. Pages undergoing I/O * will be ignored by vm_object_page_remove(). * * We cannot lock the vnode and then wait for paging * to complete without deadlocking against vm_fault. * Instead we simply call vm_object_page_remove() and * allow it to block internally on a page-by-page * basis when it encounters pages undergoing async * I/O. */ int flags; vm_object_reference(object); vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY, curthread); flags = (syncio || invalidate) ? OBJPC_SYNC : 0; flags |= invalidate ? OBJPC_INVAL : 0; vm_object_page_clean(object, OFF_TO_IDX(offset), OFF_TO_IDX(offset + size + PAGE_MASK), flags); if (invalidate) { /*vm_object_pip_wait(object, "objmcl");*/ vm_object_page_remove(object, OFF_TO_IDX(offset), OFF_TO_IDX(offset + size + PAGE_MASK), FALSE); } VOP_UNLOCK(object->handle, 0, curthread); vm_object_deallocate(object); } start += size; } vm_map_unlock_read(map); return (KERN_SUCCESS); } /* * vm_map_entry_unwire: [ internal use only ] * * Make the region specified by this entry pageable. * * The map in question should be locked. * [This is the reason for this routine's existence.] */ static void vm_map_entry_unwire(vm_map_t map, vm_map_entry_t entry) { vm_fault_unwire(map, entry->start, entry->end); entry->wired_count = 0; } /* * vm_map_entry_delete: [ internal use only ] * * Deallocate the given entry from the target map. */ static void vm_map_entry_delete(vm_map_t map, vm_map_entry_t entry) { vm_map_entry_unlink(map, entry); map->size -= entry->end - entry->start; if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { vm_object_deallocate(entry->object.vm_object); } vm_map_entry_dispose(map, entry); } /* * vm_map_delete: [ internal use only ] * * Deallocates the given address range from the target * map. */ int vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end) { vm_object_t object; vm_map_entry_t entry; vm_map_entry_t first_entry; /* * Find the start of the region, and clip it */ if (!vm_map_lookup_entry(map, start, &first_entry)) entry = first_entry->next; else { entry = first_entry; vm_map_clip_start(map, entry, start); } /* * Save the free space hint */ if (entry == &map->header) { map->first_free = &map->header; } else if (map->first_free->start >= start) { map->first_free = entry->prev; } /* * Step through all entries in this region */ while ((entry != &map->header) && (entry->start < end)) { vm_map_entry_t next; vm_offset_t s, e; vm_pindex_t offidxstart, offidxend, count; /* * Wait for wiring or unwiring of an entry to complete. */ if ((entry->eflags & MAP_ENTRY_IN_TRANSITION) != 0) { unsigned int last_timestamp; vm_offset_t saved_start; vm_map_entry_t tmp_entry; saved_start = entry->start; entry->eflags |= MAP_ENTRY_NEEDS_WAKEUP; last_timestamp = map->timestamp; (void) vm_map_unlock_and_wait(map, FALSE); vm_map_lock(map); if (last_timestamp + 1 != map->timestamp) { /* * Look again for the entry because the map was * modified while it was unlocked. * Specifically, the entry may have been * clipped, merged, or deleted. */ if (!vm_map_lookup_entry(map, saved_start, &tmp_entry)) entry = tmp_entry->next; else { entry = tmp_entry; vm_map_clip_start(map, entry, saved_start); } } continue; } vm_map_clip_end(map, entry, end); s = entry->start; e = entry->end; next = entry->next; offidxstart = OFF_TO_IDX(entry->offset); count = OFF_TO_IDX(e - s); object = entry->object.vm_object; /* * Unwire before removing addresses from the pmap; otherwise, * unwiring will put the entries back in the pmap. */ if (entry->wired_count != 0) { vm_map_entry_unwire(map, entry); } offidxend = offidxstart + count; if ((object == kernel_object) || (object == kmem_object)) { vm_object_page_remove(object, offidxstart, offidxend, FALSE); } else { mtx_lock(&Giant); pmap_remove(map->pmap, s, e); if (object != NULL && object->ref_count != 1 && (object->flags & (OBJ_NOSPLIT|OBJ_ONEMAPPING)) == OBJ_ONEMAPPING && (object->type == OBJT_DEFAULT || object->type == OBJT_SWAP)) { vm_object_collapse(object); vm_object_page_remove(object, offidxstart, offidxend, FALSE); if (object->type == OBJT_SWAP) { swap_pager_freespace(object, offidxstart, count); } if (offidxend >= object->size && offidxstart < object->size) { object->size = offidxstart; } } mtx_unlock(&Giant); } /* * Delete the entry (which may delete the object) only after * removing all pmap entries pointing to its pages. * (Otherwise, its page frames may be reallocated, and any * modify bits will be set in the wrong object!) */ vm_map_entry_delete(map, entry); entry = next; } return (KERN_SUCCESS); } /* * vm_map_remove: * * Remove the given address range from the target map. * This is the exported form of vm_map_delete. */ int vm_map_remove(vm_map_t map, vm_offset_t start, vm_offset_t end) { int result, s = 0; if (map == kmem_map) s = splvm(); vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); result = vm_map_delete(map, start, end); vm_map_unlock(map); if (map == kmem_map) splx(s); return (result); } /* * vm_map_check_protection: * * Assert that the target map allows the specified * privilege on the entire address region given. * The entire region must be allocated. */ boolean_t vm_map_check_protection(vm_map_t map, vm_offset_t start, vm_offset_t end, vm_prot_t protection) { vm_map_entry_t entry; vm_map_entry_t tmp_entry; vm_map_lock_read(map); if (!vm_map_lookup_entry(map, start, &tmp_entry)) { vm_map_unlock_read(map); return (FALSE); } entry = tmp_entry; while (start < end) { if (entry == &map->header) { vm_map_unlock_read(map); return (FALSE); } /* * No holes allowed! */ if (start < entry->start) { vm_map_unlock_read(map); return (FALSE); } /* * Check protection associated with entry. */ if ((entry->protection & protection) != protection) { vm_map_unlock_read(map); return (FALSE); } /* go to next entry */ start = entry->end; entry = entry->next; } vm_map_unlock_read(map); return (TRUE); } /* * vm_map_copy_entry: * * Copies the contents of the source entry to the destination * entry. The entries *must* be aligned properly. */ static void vm_map_copy_entry( vm_map_t src_map, vm_map_t dst_map, vm_map_entry_t src_entry, vm_map_entry_t dst_entry) { vm_object_t src_object; if ((dst_entry->eflags|src_entry->eflags) & MAP_ENTRY_IS_SUB_MAP) return; if (src_entry->wired_count == 0) { /* * If the source entry is marked needs_copy, it is already * write-protected. */ if ((src_entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) { pmap_protect(src_map->pmap, src_entry->start, src_entry->end, src_entry->protection & ~VM_PROT_WRITE); } /* * Make a copy of the object. */ if ((src_object = src_entry->object.vm_object) != NULL) { if ((src_object->handle == NULL) && (src_object->type == OBJT_DEFAULT || src_object->type == OBJT_SWAP)) { vm_object_collapse(src_object); if ((src_object->flags & (OBJ_NOSPLIT|OBJ_ONEMAPPING)) == OBJ_ONEMAPPING) { vm_object_split(src_entry); src_object = src_entry->object.vm_object; } } vm_object_reference(src_object); vm_object_clear_flag(src_object, OBJ_ONEMAPPING); dst_entry->object.vm_object = src_object; src_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY); dst_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY); dst_entry->offset = src_entry->offset; } else { dst_entry->object.vm_object = NULL; dst_entry->offset = 0; } pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->start, dst_entry->end - dst_entry->start, src_entry->start); } else { /* * Of course, wired down pages can't be set copy-on-write. * Cause wired pages to be copied into the new map by * simulating faults (the new pages are pageable) */ vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry); } } /* * vmspace_fork: * Create a new process vmspace structure and vm_map * based on those of an existing process. The new map * is based on the old map, according to the inheritance * values on the regions in that map. * * The source map must not be locked. */ struct vmspace * vmspace_fork(struct vmspace *vm1) { struct vmspace *vm2; vm_map_t old_map = &vm1->vm_map; vm_map_t new_map; vm_map_entry_t old_entry; vm_map_entry_t new_entry; vm_object_t object; GIANT_REQUIRED; vm_map_lock(old_map); old_map->infork = 1; vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset); bcopy(&vm1->vm_startcopy, &vm2->vm_startcopy, (caddr_t) &vm1->vm_endcopy - (caddr_t) &vm1->vm_startcopy); new_map = &vm2->vm_map; /* XXX */ new_map->timestamp = 1; old_entry = old_map->header.next; while (old_entry != &old_map->header) { if (old_entry->eflags & MAP_ENTRY_IS_SUB_MAP) panic("vm_map_fork: encountered a submap"); switch (old_entry->inheritance) { case VM_INHERIT_NONE: break; case VM_INHERIT_SHARE: /* * Clone the entry, creating the shared object if necessary. */ object = old_entry->object.vm_object; if (object == NULL) { object = vm_object_allocate(OBJT_DEFAULT, atop(old_entry->end - old_entry->start)); old_entry->object.vm_object = object; old_entry->offset = (vm_offset_t) 0; } /* * Add the reference before calling vm_object_shadow * to insure that a shadow object is created. */ vm_object_reference(object); if (old_entry->eflags & MAP_ENTRY_NEEDS_COPY) { vm_object_shadow(&old_entry->object.vm_object, &old_entry->offset, atop(old_entry->end - old_entry->start)); old_entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; /* Transfer the second reference too. */ vm_object_reference( old_entry->object.vm_object); vm_object_deallocate(object); object = old_entry->object.vm_object; } vm_object_clear_flag(object, OBJ_ONEMAPPING); /* * Clone the entry, referencing the shared object. */ new_entry = vm_map_entry_create(new_map); *new_entry = *old_entry; new_entry->eflags &= ~MAP_ENTRY_USER_WIRED; new_entry->wired_count = 0; /* * Insert the entry into the new map -- we know we're * inserting at the end of the new map. */ vm_map_entry_link(new_map, new_map->header.prev, new_entry); /* * Update the physical map */ pmap_copy(new_map->pmap, old_map->pmap, new_entry->start, (old_entry->end - old_entry->start), old_entry->start); break; case VM_INHERIT_COPY: /* * Clone the entry and link into the map. */ new_entry = vm_map_entry_create(new_map); *new_entry = *old_entry; new_entry->eflags &= ~MAP_ENTRY_USER_WIRED; new_entry->wired_count = 0; new_entry->object.vm_object = NULL; vm_map_entry_link(new_map, new_map->header.prev, new_entry); vm_map_copy_entry(old_map, new_map, old_entry, new_entry); break; } old_entry = old_entry->next; } new_map->size = old_map->size; old_map->infork = 0; vm_map_unlock(old_map); return (vm2); } int vm_map_stack (vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize, vm_prot_t prot, vm_prot_t max, int cow) { vm_map_entry_t prev_entry; vm_map_entry_t new_stack_entry; vm_size_t init_ssize; int rv; if (VM_MIN_ADDRESS > 0 && addrbos < VM_MIN_ADDRESS) return (KERN_NO_SPACE); if (max_ssize < sgrowsiz) init_ssize = max_ssize; else init_ssize = sgrowsiz; vm_map_lock(map); /* If addr is already mapped, no go */ if (vm_map_lookup_entry(map, addrbos, &prev_entry)) { vm_map_unlock(map); return (KERN_NO_SPACE); } /* If we would blow our VMEM resource limit, no go */ if (map->size + init_ssize > curthread->td_proc->p_rlimit[RLIMIT_VMEM].rlim_cur) { vm_map_unlock(map); return (KERN_NO_SPACE); } /* If we can't accomodate max_ssize in the current mapping, * no go. However, we need to be aware that subsequent user * mappings might map into the space we have reserved for * stack, and currently this space is not protected. * * Hopefully we will at least detect this condition * when we try to grow the stack. */ if ((prev_entry->next != &map->header) && (prev_entry->next->start < addrbos + max_ssize)) { vm_map_unlock(map); return (KERN_NO_SPACE); } /* We initially map a stack of only init_ssize. We will * grow as needed later. Since this is to be a grow * down stack, we map at the top of the range. * * Note: we would normally expect prot and max to be * VM_PROT_ALL, and cow to be 0. Possibly we should * eliminate these as input parameters, and just * pass these values here in the insert call. */ rv = vm_map_insert(map, NULL, 0, addrbos + max_ssize - init_ssize, addrbos + max_ssize, prot, max, cow); /* Now set the avail_ssize amount */ if (rv == KERN_SUCCESS){ if (prev_entry != &map->header) vm_map_clip_end(map, prev_entry, addrbos + max_ssize - init_ssize); new_stack_entry = prev_entry->next; if (new_stack_entry->end != addrbos + max_ssize || new_stack_entry->start != addrbos + max_ssize - init_ssize) panic ("Bad entry start/end for new stack entry"); else new_stack_entry->avail_ssize = max_ssize - init_ssize; } vm_map_unlock(map); return (rv); } /* Attempts to grow a vm stack entry. Returns KERN_SUCCESS if the * desired address is already mapped, or if we successfully grow * the stack. Also returns KERN_SUCCESS if addr is outside the * stack range (this is strange, but preserves compatibility with * the grow function in vm_machdep.c). */ int vm_map_growstack (struct proc *p, vm_offset_t addr) { vm_map_entry_t prev_entry; vm_map_entry_t stack_entry; vm_map_entry_t new_stack_entry; struct vmspace *vm = p->p_vmspace; vm_map_t map = &vm->vm_map; vm_offset_t end; int grow_amount; int rv; int is_procstack; GIANT_REQUIRED; Retry: vm_map_lock_read(map); /* If addr is already in the entry range, no need to grow.*/ if (vm_map_lookup_entry(map, addr, &prev_entry)) { vm_map_unlock_read(map); return (KERN_SUCCESS); } if ((stack_entry = prev_entry->next) == &map->header) { vm_map_unlock_read(map); return (KERN_SUCCESS); } if (prev_entry == &map->header) end = stack_entry->start - stack_entry->avail_ssize; else end = prev_entry->end; /* This next test mimics the old grow function in vm_machdep.c. * It really doesn't quite make sense, but we do it anyway * for compatibility. * * If not growable stack, return success. This signals the * caller to proceed as he would normally with normal vm. */ if (stack_entry->avail_ssize < 1 || addr >= stack_entry->start || addr < stack_entry->start - stack_entry->avail_ssize) { vm_map_unlock_read(map); return (KERN_SUCCESS); } /* Find the minimum grow amount */ grow_amount = roundup (stack_entry->start - addr, PAGE_SIZE); if (grow_amount > stack_entry->avail_ssize) { vm_map_unlock_read(map); return (KERN_NO_SPACE); } /* If there is no longer enough space between the entries * nogo, and adjust the available space. Note: this * should only happen if the user has mapped into the * stack area after the stack was created, and is * probably an error. * * This also effectively destroys any guard page the user * might have intended by limiting the stack size. */ if (grow_amount > stack_entry->start - end) { if (vm_map_lock_upgrade(map)) goto Retry; stack_entry->avail_ssize = stack_entry->start - end; vm_map_unlock(map); return (KERN_NO_SPACE); } is_procstack = addr >= (vm_offset_t)vm->vm_maxsaddr; /* If this is the main process stack, see if we're over the * stack limit. */ if (is_procstack && (ctob(vm->vm_ssize) + grow_amount > p->p_rlimit[RLIMIT_STACK].rlim_cur)) { vm_map_unlock_read(map); return (KERN_NO_SPACE); } /* Round up the grow amount modulo SGROWSIZ */ grow_amount = roundup (grow_amount, sgrowsiz); if (grow_amount > stack_entry->avail_ssize) { grow_amount = stack_entry->avail_ssize; } if (is_procstack && (ctob(vm->vm_ssize) + grow_amount > p->p_rlimit[RLIMIT_STACK].rlim_cur)) { grow_amount = p->p_rlimit[RLIMIT_STACK].rlim_cur - ctob(vm->vm_ssize); } /* If we would blow our VMEM resource limit, no go */ if (map->size + grow_amount > curthread->td_proc->p_rlimit[RLIMIT_VMEM].rlim_cur) { vm_map_unlock_read(map); return (KERN_NO_SPACE); } if (vm_map_lock_upgrade(map)) goto Retry; /* Get the preliminary new entry start value */ addr = stack_entry->start - grow_amount; /* If this puts us into the previous entry, cut back our growth * to the available space. Also, see the note above. */ if (addr < end) { stack_entry->avail_ssize = stack_entry->start - end; addr = end; } rv = vm_map_insert(map, NULL, 0, addr, stack_entry->start, VM_PROT_ALL, VM_PROT_ALL, 0); /* Adjust the available stack space by the amount we grew. */ if (rv == KERN_SUCCESS) { if (prev_entry != &map->header) vm_map_clip_end(map, prev_entry, addr); new_stack_entry = prev_entry->next; if (new_stack_entry->end != stack_entry->start || new_stack_entry->start != addr) panic ("Bad stack grow start/end in new stack entry"); else { new_stack_entry->avail_ssize = stack_entry->avail_ssize - (new_stack_entry->end - new_stack_entry->start); if (is_procstack) vm->vm_ssize += btoc(new_stack_entry->end - new_stack_entry->start); } } vm_map_unlock(map); return (rv); } /* * Unshare the specified VM space for exec. If other processes are * mapped to it, then create a new one. The new vmspace is null. */ void -vmspace_exec(struct proc *p) +vmspace_exec(struct proc *p, vm_offset_t minuser, vm_offset_t maxuser) { struct vmspace *oldvmspace = p->p_vmspace; struct vmspace *newvmspace; - vm_map_t map = &p->p_vmspace->vm_map; GIANT_REQUIRED; - newvmspace = vmspace_alloc(map->min_offset, map->max_offset); + newvmspace = vmspace_alloc(minuser, maxuser); bcopy(&oldvmspace->vm_startcopy, &newvmspace->vm_startcopy, (caddr_t) (newvmspace + 1) - (caddr_t) &newvmspace->vm_startcopy); /* * This code is written like this for prototype purposes. The * goal is to avoid running down the vmspace here, but let the * other process's that are still using the vmspace to finally * run it down. Even though there is little or no chance of blocking * here, it is a good idea to keep this form for future mods. */ p->p_vmspace = newvmspace; pmap_pinit2(vmspace_pmap(newvmspace)); vmspace_free(oldvmspace); if (p == curthread->td_proc) /* XXXKSE ? */ pmap_activate(curthread); } /* * Unshare the specified VM space for forcing COW. This * is called by rfork, for the (RFMEM|RFPROC) == 0 case. */ void vmspace_unshare(struct proc *p) { struct vmspace *oldvmspace = p->p_vmspace; struct vmspace *newvmspace; GIANT_REQUIRED; if (oldvmspace->vm_refcnt == 1) return; newvmspace = vmspace_fork(oldvmspace); p->p_vmspace = newvmspace; pmap_pinit2(vmspace_pmap(newvmspace)); vmspace_free(oldvmspace); if (p == curthread->td_proc) /* XXXKSE ? */ pmap_activate(curthread); } /* * vm_map_lookup: * * Finds the VM object, offset, and * protection for a given virtual address in the * specified map, assuming a page fault of the * type specified. * * Leaves the map in question locked for read; return * values are guaranteed until a vm_map_lookup_done * call is performed. Note that the map argument * is in/out; the returned map must be used in * the call to vm_map_lookup_done. * * A handle (out_entry) is returned for use in * vm_map_lookup_done, to make that fast. * * If a lookup is requested with "write protection" * specified, the map may be changed to perform virtual * copying operations, although the data referenced will * remain the same. */ int vm_map_lookup(vm_map_t *var_map, /* IN/OUT */ vm_offset_t vaddr, vm_prot_t fault_typea, vm_map_entry_t *out_entry, /* OUT */ vm_object_t *object, /* OUT */ vm_pindex_t *pindex, /* OUT */ vm_prot_t *out_prot, /* OUT */ boolean_t *wired) /* OUT */ { vm_map_entry_t entry; vm_map_t map = *var_map; vm_prot_t prot; vm_prot_t fault_type = fault_typea; RetryLookup:; /* * Lookup the faulting address. */ vm_map_lock_read(map); #define RETURN(why) \ { \ vm_map_unlock_read(map); \ return (why); \ } /* * If the map has an interesting hint, try it before calling full * blown lookup routine. */ entry = map->root; *out_entry = entry; if (entry == NULL || (vaddr < entry->start) || (vaddr >= entry->end)) { /* * Entry was either not a valid hint, or the vaddr was not * contained in the entry, so do a full lookup. */ if (!vm_map_lookup_entry(map, vaddr, out_entry)) RETURN(KERN_INVALID_ADDRESS); entry = *out_entry; } /* * Handle submaps. */ if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) { vm_map_t old_map = map; *var_map = map = entry->object.sub_map; vm_map_unlock_read(old_map); goto RetryLookup; } /* * Check whether this task is allowed to have this page. * Note the special case for MAP_ENTRY_COW * pages with an override. This is to implement a forced * COW for debuggers. */ if (fault_type & VM_PROT_OVERRIDE_WRITE) prot = entry->max_protection; else prot = entry->protection; fault_type &= (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); if ((fault_type & prot) != fault_type) { RETURN(KERN_PROTECTION_FAILURE); } if ((entry->eflags & MAP_ENTRY_USER_WIRED) && (entry->eflags & MAP_ENTRY_COW) && (fault_type & VM_PROT_WRITE) && (fault_typea & VM_PROT_OVERRIDE_WRITE) == 0) { RETURN(KERN_PROTECTION_FAILURE); } /* * If this page is not pageable, we have to get it for all possible * accesses. */ *wired = (entry->wired_count != 0); if (*wired) prot = fault_type = entry->protection; /* * If the entry was copy-on-write, we either ... */ if (entry->eflags & MAP_ENTRY_NEEDS_COPY) { /* * If we want to write the page, we may as well handle that * now since we've got the map locked. * * If we don't need to write the page, we just demote the * permissions allowed. */ if (fault_type & VM_PROT_WRITE) { /* * Make a new object, and place it in the object * chain. Note that no new references have appeared * -- one just moved from the map to the new * object. */ if (vm_map_lock_upgrade(map)) goto RetryLookup; vm_object_shadow( &entry->object.vm_object, &entry->offset, atop(entry->end - entry->start)); entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; vm_map_lock_downgrade(map); } else { /* * We're attempting to read a copy-on-write page -- * don't allow writes. */ prot &= ~VM_PROT_WRITE; } } /* * Create an object if necessary. */ if (entry->object.vm_object == NULL && !map->system_map) { if (vm_map_lock_upgrade(map)) goto RetryLookup; entry->object.vm_object = vm_object_allocate(OBJT_DEFAULT, atop(entry->end - entry->start)); entry->offset = 0; vm_map_lock_downgrade(map); } /* * Return the object/offset from this entry. If the entry was * copy-on-write or empty, it has been fixed up. */ *pindex = OFF_TO_IDX((vaddr - entry->start) + entry->offset); *object = entry->object.vm_object; /* * Return whether this is the only map sharing this data. */ *out_prot = prot; return (KERN_SUCCESS); #undef RETURN } /* * vm_map_lookup_done: * * Releases locks acquired by a vm_map_lookup * (according to the handle returned by that lookup). */ void vm_map_lookup_done(vm_map_t map, vm_map_entry_t entry) { /* * Unlock the main-level map */ vm_map_unlock_read(map); } #ifdef ENABLE_VFS_IOOPT /* * Experimental support for zero-copy I/O * * Implement uiomove with VM operations. This handles (and collateral changes) * support every combination of source object modification, and COW type * operations. */ int vm_uiomove( vm_map_t mapa, vm_object_t srcobject, off_t cp, int cnta, vm_offset_t uaddra, int *npages) { vm_map_t map; vm_object_t first_object, oldobject, object; vm_map_entry_t entry; vm_prot_t prot; boolean_t wired; int tcnt, rv; vm_offset_t uaddr, start, end, tend; vm_pindex_t first_pindex, oindex; vm_size_t osize; off_t ooffset; int cnt; GIANT_REQUIRED; if (npages) *npages = 0; cnt = cnta; uaddr = uaddra; while (cnt > 0) { map = mapa; if ((vm_map_lookup(&map, uaddr, VM_PROT_READ, &entry, &first_object, &first_pindex, &prot, &wired)) != KERN_SUCCESS) { return EFAULT; } vm_map_clip_start(map, entry, uaddr); tcnt = cnt; tend = uaddr + tcnt; if (tend > entry->end) { tcnt = entry->end - uaddr; tend = entry->end; } vm_map_clip_end(map, entry, tend); start = entry->start; end = entry->end; osize = atop(tcnt); oindex = OFF_TO_IDX(cp); if (npages) { vm_size_t idx; for (idx = 0; idx < osize; idx++) { vm_page_t m; if ((m = vm_page_lookup(srcobject, oindex + idx)) == NULL) { vm_map_lookup_done(map, entry); return 0; } /* * disallow busy or invalid pages, but allow * m->busy pages if they are entirely valid. */ if ((m->flags & PG_BUSY) || ((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL)) { vm_map_lookup_done(map, entry); return 0; } } } /* * If we are changing an existing map entry, just redirect * the object, and change mappings. */ if ((first_object->type == OBJT_VNODE) && ((oldobject = entry->object.vm_object) == first_object)) { if ((entry->offset != cp) || (oldobject != srcobject)) { /* * Remove old window into the file */ pmap_remove (map->pmap, uaddr, tend); /* * Force copy on write for mmaped regions */ vm_object_pmap_copy_1 (srcobject, oindex, oindex + osize); /* * Point the object appropriately */ if (oldobject != srcobject) { /* * Set the object optimization hint flag */ vm_object_set_flag(srcobject, OBJ_OPT); vm_object_reference(srcobject); entry->object.vm_object = srcobject; if (oldobject) { vm_object_deallocate(oldobject); } } entry->offset = cp; map->timestamp++; } else { pmap_remove (map->pmap, uaddr, tend); } } else if ((first_object->ref_count == 1) && (first_object->size == osize) && ((first_object->type == OBJT_DEFAULT) || (first_object->type == OBJT_SWAP)) ) { oldobject = first_object->backing_object; if ((first_object->backing_object_offset != cp) || (oldobject != srcobject)) { /* * Remove old window into the file */ pmap_remove (map->pmap, uaddr, tend); /* * Remove unneeded old pages */ vm_object_page_remove(first_object, 0, 0, 0); /* * Invalidate swap space */ if (first_object->type == OBJT_SWAP) { swap_pager_freespace(first_object, 0, first_object->size); } /* * Force copy on write for mmaped regions */ vm_object_pmap_copy_1 (srcobject, oindex, oindex + osize); /* * Point the object appropriately */ if (oldobject != srcobject) { /* * Set the object optimization hint flag */ vm_object_set_flag(srcobject, OBJ_OPT); vm_object_reference(srcobject); if (oldobject) { TAILQ_REMOVE(&oldobject->shadow_head, first_object, shadow_list); oldobject->shadow_count--; /* XXX bump generation? */ vm_object_deallocate(oldobject); } TAILQ_INSERT_TAIL(&srcobject->shadow_head, first_object, shadow_list); srcobject->shadow_count++; /* XXX bump generation? */ first_object->backing_object = srcobject; } first_object->backing_object_offset = cp; map->timestamp++; } else { pmap_remove (map->pmap, uaddr, tend); } /* * Otherwise, we have to do a logical mmap. */ } else { vm_object_set_flag(srcobject, OBJ_OPT); vm_object_reference(srcobject); pmap_remove (map->pmap, uaddr, tend); vm_object_pmap_copy_1 (srcobject, oindex, oindex + osize); vm_map_lock_upgrade(map); if (entry == &map->header) { map->first_free = &map->header; } else if (map->first_free->start >= start) { map->first_free = entry->prev; } vm_map_entry_delete(map, entry); object = srcobject; ooffset = cp; rv = vm_map_insert(map, object, ooffset, start, tend, VM_PROT_ALL, VM_PROT_ALL, MAP_COPY_ON_WRITE); if (rv != KERN_SUCCESS) panic("vm_uiomove: could not insert new entry: %d", rv); } /* * Map the window directly, if it is already in memory */ pmap_object_init_pt(map->pmap, uaddr, srcobject, oindex, tcnt, 0); map->timestamp++; vm_map_unlock(map); cnt -= tcnt; uaddr += tcnt; cp += tcnt; if (npages) *npages += osize; } return 0; } #endif #include "opt_ddb.h" #ifdef DDB #include #include /* * vm_map_print: [ debug ] */ DB_SHOW_COMMAND(map, vm_map_print) { static int nlines; /* XXX convert args. */ vm_map_t map = (vm_map_t)addr; boolean_t full = have_addr; vm_map_entry_t entry; db_iprintf("Task map %p: pmap=%p, nentries=%d, version=%u\n", (void *)map, (void *)map->pmap, map->nentries, map->timestamp); nlines++; if (!full && db_indent) return; db_indent += 2; for (entry = map->header.next; entry != &map->header; entry = entry->next) { db_iprintf("map entry %p: start=%p, end=%p\n", (void *)entry, (void *)entry->start, (void *)entry->end); nlines++; { static char *inheritance_name[4] = {"share", "copy", "none", "donate_copy"}; db_iprintf(" prot=%x/%x/%s", entry->protection, entry->max_protection, inheritance_name[(int)(unsigned char)entry->inheritance]); if (entry->wired_count != 0) db_printf(", wired"); } if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) { /* XXX no %qd in kernel. Truncate entry->offset. */ db_printf(", share=%p, offset=0x%lx\n", (void *)entry->object.sub_map, (long)entry->offset); nlines++; if ((entry->prev == &map->header) || (entry->prev->object.sub_map != entry->object.sub_map)) { db_indent += 2; vm_map_print((db_expr_t)(intptr_t) entry->object.sub_map, full, 0, (char *)0); db_indent -= 2; } } else { /* XXX no %qd in kernel. Truncate entry->offset. */ db_printf(", object=%p, offset=0x%lx", (void *)entry->object.vm_object, (long)entry->offset); if (entry->eflags & MAP_ENTRY_COW) db_printf(", copy (%s)", (entry->eflags & MAP_ENTRY_NEEDS_COPY) ? "needed" : "done"); db_printf("\n"); nlines++; if ((entry->prev == &map->header) || (entry->prev->object.vm_object != entry->object.vm_object)) { db_indent += 2; vm_object_print((db_expr_t)(intptr_t) entry->object.vm_object, full, 0, (char *)0); nlines += 4; db_indent -= 2; } } } db_indent -= 2; if (db_indent == 0) nlines = 0; } DB_SHOW_COMMAND(procvm, procvm) { struct proc *p; if (have_addr) { p = (struct proc *) addr; } else { p = curproc; } db_printf("p = %p, vmspace = %p, map = %p, pmap = %p\n", (void *)p, (void *)p->p_vmspace, (void *)&p->p_vmspace->vm_map, (void *)vmspace_pmap(p->p_vmspace)); vm_map_print((db_expr_t)(intptr_t)&p->p_vmspace->vm_map, 1, 0, NULL); } #endif /* DDB */