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


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

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/linux_vdso.c

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

    1 /*-
    2  * Copyright (c) 2013-2021 Dmitry Chagin <dchagin@FreeBSD.org>
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer
    9  *    in this position and unchanged.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  */
   25 
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD$");
   28 
   29 #include "opt_compat.h"
   30 
   31 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
   32 #define __ELF_WORD_SIZE 32
   33 #else
   34 #define __ELF_WORD_SIZE 64
   35 #endif
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/elf.h>
   40 #include <sys/imgact.h>
   41 #include <sys/kernel.h>
   42 #include <sys/proc.h>
   43 #include <sys/rwlock.h>
   44 #include <sys/queue.h>
   45 #include <sys/sysent.h>
   46 
   47 #include <vm/vm_param.h>
   48 #include <vm/pmap.h>
   49 #include <vm/vm_extern.h>
   50 #include <vm/vm_map.h>
   51 #include <vm/vm_object.h>
   52 #include <vm/vm_page.h>
   53 #include <vm/vm_pager.h>
   54 
   55 #include <compat/linux/linux_vdso.h>
   56 
   57 SLIST_HEAD(, linux_vdso_sym) __elfN(linux_vdso_syms) =
   58     SLIST_HEAD_INITIALIZER(__elfN(linux_vdso_syms));
   59 
   60 void
   61 __elfN(linux_vdso_sym_init)(struct linux_vdso_sym *s)
   62 {
   63 
   64         SLIST_INSERT_HEAD(&__elfN(linux_vdso_syms), s, sym);
   65 }
   66 
   67 vm_object_t
   68 __elfN(linux_shared_page_init)(char **mapping, vm_size_t size)
   69 {
   70         vm_page_t m;
   71         vm_object_t obj;
   72         vm_offset_t addr;
   73         size_t n, pages;
   74 
   75         pages = size / PAGE_SIZE;
   76 
   77         addr = kva_alloc(size);
   78         obj = vm_pager_allocate(OBJT_PHYS, 0, size,
   79             VM_PROT_DEFAULT, 0, NULL);
   80         VM_OBJECT_WLOCK(obj);
   81         for (n = 0; n < pages; n++) {
   82                 m = vm_page_grab(obj, n,
   83                     VM_ALLOC_ZERO);
   84                 vm_page_valid(m);
   85                 vm_page_xunbusy(m);
   86                 pmap_qenter(addr + n * PAGE_SIZE, &m, 1);
   87         }
   88         VM_OBJECT_WUNLOCK(obj);
   89         *mapping = (char *)addr;
   90         return (obj);
   91 }
   92 
   93 void
   94 __elfN(linux_shared_page_fini)(vm_object_t obj, void *mapping,
   95     vm_size_t size)
   96 {
   97         vm_offset_t va;
   98 
   99         va = (vm_offset_t)mapping;
  100         pmap_qremove(va, size / PAGE_SIZE);
  101         kva_free(va, size);
  102         vm_object_deallocate(obj);
  103 }
  104 
  105 void
  106 __elfN(linux_vdso_fixup)(char *base, vm_offset_t offset)
  107 {
  108         struct linux_vdso_sym *lsym;
  109         const Elf_Shdr *shdr;
  110         Elf_Ehdr *ehdr;
  111         Elf_Sym *dsym, *sym;
  112         char *strtab, *symname;
  113         int i, symcnt;
  114 
  115         ehdr = (Elf_Ehdr *)base;
  116 
  117         MPASS(IS_ELF(*ehdr));
  118         MPASS(ehdr->e_ident[EI_CLASS] == ELF_TARG_CLASS);
  119         MPASS(ehdr->e_ident[EI_DATA] == ELF_TARG_DATA);
  120         MPASS(ehdr->e_ident[EI_VERSION] == EV_CURRENT);
  121         MPASS(ehdr->e_shentsize == sizeof(Elf_Shdr));
  122         MPASS(ehdr->e_shoff != 0);
  123         MPASS(ehdr->e_type == ET_DYN);
  124 
  125         shdr = (const Elf_Shdr *)(base + ehdr->e_shoff);
  126 
  127         dsym = NULL;
  128         for (i = 0; i < ehdr->e_shnum; i++) {
  129                 if (shdr[i].sh_size == 0)
  130                         continue;
  131                 if (shdr[i].sh_type == SHT_DYNSYM) {
  132                         dsym = (Elf_Sym *)(base + shdr[i].sh_offset);
  133                         strtab = base + shdr[shdr[i].sh_link].sh_offset;
  134                         symcnt = shdr[i].sh_size / sizeof(*dsym);
  135                         break;
  136                 }
  137         }
  138         MPASS(dsym != NULL);
  139 
  140         ehdr->e_ident[EI_OSABI] = ELFOSABI_LINUX;
  141 
  142         /*
  143          * VDSO is readonly mapped to the process VA and
  144          * can't be relocated by rtld.
  145          */
  146         SLIST_FOREACH(lsym, &__elfN(linux_vdso_syms), sym) {
  147                 for (i = 0, sym = dsym; i < symcnt; i++, sym++) {
  148                         symname = strtab + sym->st_name;
  149                         if (strncmp(lsym->symname, symname, lsym->size) == 0) {
  150                                 sym->st_value += offset;
  151                                 *lsym->ptr = sym->st_value;
  152                                 break;
  153 
  154                         }
  155                 }
  156         }
  157 }
  158 
  159 int
  160 linux_map_vdso(struct proc *p, vm_object_t obj, vm_offset_t base,
  161     vm_offset_t size, struct image_params *imgp)
  162 {
  163         struct vmspace *vmspace;
  164         vm_map_t map;
  165         int error;
  166 
  167         MPASS((imgp->sysent->sv_flags & SV_ABI_MASK) == SV_ABI_LINUX);
  168         MPASS(obj != NULL);
  169 
  170         vmspace = p->p_vmspace;
  171         map = &vmspace->vm_map;
  172 
  173         vm_object_reference(obj);
  174         error = vm_map_fixed(map, obj, 0, base, size,
  175             VM_PROT_READ | VM_PROT_EXECUTE,
  176             VM_PROT_READ | VM_PROT_EXECUTE,
  177             MAP_INHERIT_SHARE | MAP_ACC_NO_CHARGE);
  178         if (error != KERN_SUCCESS) {
  179                 vm_object_deallocate(obj);
  180                 return (vm_mmap_to_errno(error));
  181         }
  182         return (0);
  183 }

Cache object: b964f309eee741afbcb67ca63c43432c


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


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