]> Zhao Yanbai Git Server - minix.git/commitdiff
ld.elf_so, grep, make: use mmap() 66/566/14
authorBen Gras <ben@minix3.org>
Sat, 16 Mar 2013 03:19:47 +0000 (03:19 +0000)
committerBen Gras <ben@minix3.org>
Fri, 31 May 2013 15:42:01 +0000 (15:42 +0000)
. let the dynamic linker use a real file mmap(), reverting
  most of the minix-specific changes
. except for a fallback mode for systems or filesystems that
  do not support mmap() on files
. make, grep: let them use mmap() too, with fallback

Change-Id: I11c0c9ad439d713917a6f5c2d196558f6c03eabd

commands/grep/file.c
commands/grep/mmfile.c
libexec/ld.elf_so/Makefile
libexec/ld.elf_so/map_object.c
libexec/ld.elf_so/map_object_fallback.c [new file with mode: 0644]
libexec/ld.elf_so/rtld.h
usr.bin/make/parse.c

index 9a6ae8ebcd420be3b74674b84eae8bb47266ddc9..3982f075cb90a4523e1b8fc796dda89254c27eb2 100644 (file)
@@ -42,9 +42,7 @@ static size_t  lnbuflen;
 #endif
 
 #define FILE_STDIO     0
-#ifndef __minix
 #define FILE_MMAP      1
-#endif
 #define FILE_GZIP      2
 
 struct file {
index 8cdfefe21918f0e25e722ad7c2c8a1ea45904193..14438b42e0f77ee69e504aed1854e295c82e92ac 100644 (file)
@@ -1,4 +1,3 @@
-#ifndef __minix
 /*     $OpenBSD: mmfile.c,v 1.11 2006/09/19 05:52:23 otto Exp $        */
 
 /*-
@@ -40,6 +39,9 @@
 
 #define MAX_MAP_LEN 1048576
 
+#define munmap minix_munmap
+#define mmap minix_mmap
+
 mmf_t *
 mmopen(char *fn, char *mode)
 {
@@ -87,7 +89,7 @@ mmclose(mmf_t *mmf)
 char *
 mmfgetln(mmf_t *mmf, size_t *l)
 {
-       static char *p;
+       static unsigned char *p;
        char *start = mmf->ptr;          /* Remove speed bump */
        char *end = mmf->end;            /* Remove speed bump */
 
@@ -101,4 +103,3 @@ mmfgetln(mmf_t *mmf, size_t *l)
        ++mmf->ptr;
        return p;
 }
-#endif
index 0ca15ffcd15e1a6813e3986dd6937c350c25c9f4..d0b8632767548a147d79b634c2bd2ed7b78c0e7b 100644 (file)
@@ -68,7 +68,7 @@ CLIBOBJ!=     cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR}
 
 SRCS+=         rtld.c reloc.c symbol.c xmalloc.c xprintf.c debug.c \
                map_object.c load.c search.c headers.c paths.c expand.c \
-               tls.c symver.c diagassert.c
+               tls.c symver.c diagassert.c map_object_fallback.c 
 
 .if ${USE_FORT} == "yes"
 .PATH.c: ${NETBSDSRCDIR}/lib/libc/misc
index 027deeca3dccc55366557e90cc4ae8277f99c879..fad5e426524d0f8da4db39e790a8dfecc3ee87c8 100644 (file)
@@ -51,6 +51,10 @@ __RCSID("$NetBSD: map_object.c,v 1.45 2012/10/13 21:13:07 dholland Exp $");
 
 #ifdef __minix
 #define munmap minix_munmap
+#define mmap minix_mmap
+#ifndef MAP_SHARED
+#define MAP_SHARED MAP_PRIVATE /* minix: MAP_SHARED should be MAP_PRIVATE */
+#endif
 #endif
 
 #define MINIXVERBOSE 0
@@ -63,19 +67,6 @@ static int protflags(int);   /* Elf flags -> mmap protection */
 
 #define EA_UNDEF               (~(Elf_Addr)0)
 
-static void Pread(void *addr, size_t size, int fd, off_t off)
-{
-       int s;
-       if((s=pread(fd,addr, size, off)) < 0) {
-               _rtld_error("pread failed");
-               exit(1);
-       }
-
-#if MINIXVERBOSE
-       fprintf(stderr, "read 0x%lx bytes from offset 0x%lx to addr 0x%lx\n", size, off, addr);
-#endif
-}
-
 /*
  * Map a shared object into memory.  The argument is a file descriptor,
  * which must be open on the object and positioned at its beginning.
@@ -128,6 +119,7 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
        caddr_t          clear_addr;
        size_t           nclear;
 #endif
+       size_t          bsslen;
 
        if (sb != NULL && sb->st_size < (off_t)sizeof (Elf_Ehdr)) {
                _rtld_error("%s: not ELF file (too short)", path);
@@ -142,21 +134,16 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
                obj->ino = sb->st_ino;
        }
 
-#ifdef __minix
-       ehdr = minix_mmap(NULL, _rtld_pagesz, PROT_READ|PROT_WRITE,
-               MAP_PREALLOC|MAP_ANON, -1, (off_t)0);
-       Pread(ehdr, _rtld_pagesz, fd, 0);
-#if MINIXVERBOSE
-       fprintf(stderr, "minix mmap for header: 0x%lx\n", ehdr);
-#endif
-#else
        ehdr = mmap(NULL, _rtld_pagesz, PROT_READ, MAP_FILE | MAP_SHARED, fd,
            (off_t)0);
-#endif
        obj->ehdr = ehdr;
        if (ehdr == MAP_FAILED) {
+#if defined(__minix) && defined(RTLD_LOADER)
+               return _rtld_map_object_fallback(path, fd, sb);
+#else
                _rtld_error("%s: read error: %s", path, xstrerror(errno));
                goto bad;
+#endif
        }
        /* Make sure the file is valid */
        if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0) {
@@ -346,6 +333,8 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
 
        /* Unmap header if it overlaps the first load section. */
        if (base_offset < _rtld_pagesz) {
+               dbg(("error; base_offset = 0x%lx, pagesize 0x%lx\n",
+                       base_offset, _rtld_pagesz));
                munmap(ehdr, _rtld_pagesz);
                obj->ehdr = MAP_FAILED;
        }
@@ -370,17 +359,9 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
 #endif
        mapsize = base_vlimit - base_vaddr;
 
-#ifndef __minix
        mapbase = mmap(base_addr, mapsize, text_flags,
            mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset);
-#else
-       mapbase = minix_mmap(base_addr, mapsize, PROT_READ|PROT_WRITE,
-           MAP_ANON | MAP_PREALLOC, -1, 0);
-#if MINIXVERBOSE
-       fprintf(stderr, "minix mmap for whole block: 0x%lx-0x%lx\n", mapbase, mapbase+mapsize);
-#endif
-       Pread(mapbase, obj->textsize, fd, 0);
-#endif
+
        if (mapbase == MAP_FAILED) {
                _rtld_error("mmap of entire address space failed: %s",
                    xstrerror(errno));
@@ -389,9 +370,7 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
 
        /* Overlay the data segment onto the proper region. */
        data_addr = mapbase + (data_vaddr - base_vaddr);
-#ifdef __minix
-       Pread(data_addr, data_vlimit - data_vaddr, fd, data_offset);
-#else
+
        if (mmap(data_addr, data_vlimit - data_vaddr, data_flags,
            MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, data_offset) ==
            MAP_FAILED) {
@@ -400,7 +379,13 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
        }
 
        /* Overlay the bss segment onto the proper region. */
+#ifdef __minix
+       bsslen = base_vlimit - data_vlimit;
+       if (bsslen > 0 &&
+               mmap(mapbase + data_vlimit - base_vaddr, bsslen,
+#else
        if (mmap(mapbase + data_vlimit - base_vaddr, base_vlimit - data_vlimit,
+#endif
            data_flags, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) ==
            MAP_FAILED) {
                _rtld_error("mmap of bss failed: %s", xstrerror(errno));
@@ -408,6 +393,7 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
        }
 
        /* Unmap the gap between the text and data. */
+#ifndef __minix
        gap_addr = mapbase + round_up(text_vlimit - base_vaddr);
        gap_size = data_addr - gap_addr;
        if (gap_size != 0 && mprotect(gap_addr, gap_size, PROT_NONE) == -1) {
@@ -514,5 +500,11 @@ protflags(int elfflags)
 #endif
        if (elfflags & PF_X)
                prot |= PROT_EXEC;
+#ifdef __minix
+       /* Minix has to map it writable so we can do relocations
+        * as we don't have mprotect() yet.
+        */
+       prot |= PROT_WRITE;
+#endif
        return prot;
 }
diff --git a/libexec/ld.elf_so/map_object_fallback.c b/libexec/ld.elf_so/map_object_fallback.c
new file mode 100644 (file)
index 0000000..49b7286
--- /dev/null
@@ -0,0 +1,470 @@
+/*     $NetBSD: map_object.c,v 1.45 2012/10/13 21:13:07 dholland Exp $  */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * Copyright 2002 Charles M. Hannum <root@ihack.net>
+ * 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 John Polstra.
+ * 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 <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: map_object.c,v 1.45 2012/10/13 21:13:07 dholland Exp $");
+#endif /* not lint */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+#ifdef __minix
+#define munmap minix_munmap
+#endif
+
+#define MINIXVERBOSE 0
+
+#if MINIXVERBOSE
+#include <stdio.h>
+#endif
+
+static int protflags(int);     /* Elf flags -> mmap protection */
+
+#define EA_UNDEF               (~(Elf_Addr)0)
+
+static void Pread(void *addr, size_t size, int fd, off_t off)
+{
+       int s;
+       if((s=pread(fd,addr, size, off)) < 0) {
+               _rtld_error("pread failed");
+               exit(1);
+       }
+
+#if MINIXVERBOSE
+       fprintf(stderr, "read 0x%lx bytes from offset 0x%lx to addr 0x%lx\n", size, off, addr);
+#endif
+}
+
+/* minix-without-mmap version of _rtld_map_object() */
+Obj_Entry *
+_rtld_map_object_fallback(const char *path, int fd, const struct stat *sb)
+{
+       Obj_Entry       *obj;
+       Elf_Ehdr        *ehdr;
+       Elf_Phdr        *phdr;
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+       Elf_Phdr        *phtls;
+#endif
+       size_t           phsize;
+       Elf_Phdr        *phlimit;
+       Elf_Phdr        *segs[2];
+       int              nsegs;
+       caddr_t          mapbase = MAP_FAILED;
+       size_t           mapsize = 0;
+       int              mapflags;
+       Elf_Off          base_offset;
+#ifdef MAP_ALIGNED
+       Elf_Addr         base_alignment;
+#endif
+       Elf_Addr         base_vaddr;
+       Elf_Addr         base_vlimit;
+       Elf_Addr         text_vlimit;
+       int              text_flags;
+       caddr_t          base_addr;
+       Elf_Off          data_offset;
+       Elf_Addr         data_vaddr;
+       Elf_Addr         data_vlimit;
+       int              data_flags;
+       caddr_t          data_addr;
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+       Elf_Addr         tls_vaddr = 0; /* Noise GCC */
+#endif
+       Elf_Addr         phdr_vaddr;
+       size_t           phdr_memsz;
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+       caddr_t          gap_addr;
+       size_t           gap_size;
+#endif
+       int i;
+#ifdef RTLD_LOADER
+       Elf_Addr         clear_vaddr;
+       caddr_t          clear_addr;
+       size_t           nclear;
+#endif
+
+       if (sb != NULL && sb->st_size < (off_t)sizeof (Elf_Ehdr)) {
+               _rtld_error("%s: not ELF file (too short)", path);
+               return NULL;
+       }
+
+       obj = _rtld_obj_new();
+       obj->path = xstrdup(path);
+       obj->pathlen = strlen(path);
+       if (sb != NULL) {
+               obj->dev = sb->st_dev;
+               obj->ino = sb->st_ino;
+       }
+
+#ifdef __minix
+       ehdr = minix_mmap(NULL, _rtld_pagesz, PROT_READ|PROT_WRITE,
+               MAP_PREALLOC|MAP_ANON, -1, (off_t)0);
+       Pread(ehdr, _rtld_pagesz, fd, 0);
+#if MINIXVERBOSE
+       fprintf(stderr, "minix mmap for header: 0x%lx\n", ehdr);
+#endif
+#else
+       ehdr = mmap(NULL, _rtld_pagesz, PROT_READ, MAP_FILE | MAP_SHARED, fd,
+           (off_t)0);
+#endif
+       obj->ehdr = ehdr;
+       if (ehdr == MAP_FAILED) {
+               _rtld_error("%s: read error: %s", path, xstrerror(errno));
+               goto bad;
+       }
+       /* Make sure the file is valid */
+       if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0) {
+               _rtld_error("%s: not ELF file (magic number bad)", path);
+               goto bad;
+       }
+       if (ehdr->e_ident[EI_CLASS] != ELFCLASS) {
+               _rtld_error("%s: invalid ELF class %x; expected %x", path,
+                   ehdr->e_ident[EI_CLASS], ELFCLASS);
+               goto bad;
+       }
+       /* Elf_e_ident includes class */
+       if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
+           ehdr->e_version != EV_CURRENT ||
+           ehdr->e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) {
+               _rtld_error("%s: unsupported file version", path);
+               goto bad;
+       }
+       if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
+               _rtld_error("%s: unsupported file type", path);
+               goto bad;
+       }
+       switch (ehdr->e_machine) {
+               ELFDEFNNAME(MACHDEP_ID_CASES)
+       default:
+               _rtld_error("%s: unsupported machine", path);
+               goto bad;
+       }
+
+       /*
+         * We rely on the program header being in the first page.  This is
+         * not strictly required by the ABI specification, but it seems to
+         * always true in practice.  And, it simplifies things considerably.
+         */
+       assert(ehdr->e_phentsize == sizeof(Elf_Phdr));
+       assert(ehdr->e_phoff + ehdr->e_phnum * sizeof(Elf_Phdr) <=
+           _rtld_pagesz);
+
+       /*
+         * Scan the program header entries, and save key information.
+         *
+         * We rely on there being exactly two load segments, text and data,
+         * in that order.
+         */
+       phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff);
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+       phtls = NULL;
+#endif
+       phsize = ehdr->e_phnum * sizeof(phdr[0]);
+       obj->phdr = NULL;
+       phdr_vaddr = EA_UNDEF;
+       phdr_memsz = 0;
+       phlimit = phdr + ehdr->e_phnum;
+       nsegs = 0;
+       while (phdr < phlimit) {
+               switch (phdr->p_type) {
+               case PT_INTERP:
+                       obj->interp = (void *)(uintptr_t)phdr->p_vaddr;
+                       dbg(("%s: PT_INTERP %p", obj->path, obj->interp));
+                       break;
+
+               case PT_LOAD:
+                       if (nsegs < 2)
+                               segs[nsegs] = phdr;
+                       ++nsegs;
+
+#if ELFSIZE == 64
+#define        PRImemsz        PRIu64
+#else
+#define PRImemsz       PRIu32
+#endif
+                       dbg(("%s: %s %p phsize %" PRImemsz, obj->path, "PT_LOAD",
+                           (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz));
+                       break;
+
+               case PT_PHDR:
+                       phdr_vaddr = phdr->p_vaddr;
+                       phdr_memsz = phdr->p_memsz;
+                       dbg(("%s: %s %p phsize %" PRImemsz, obj->path, "PT_PHDR",
+                           (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz));
+                       break;
+               
+               case PT_DYNAMIC:
+                       obj->dynamic = (void *)(uintptr_t)phdr->p_vaddr;
+                       dbg(("%s: %s %p phsize %" PRImemsz, obj->path, "PT_DYNAMIC",
+                           (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz));
+                       break;
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+               case PT_TLS:
+                       phtls = phdr;
+                       dbg(("%s: %s %p phsize %" PRImemsz, obj->path, "PT_TLS",
+                           (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz));
+                       break;
+#endif
+               }
+
+               ++phdr;
+       }
+       phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff);
+       obj->entry = (void *)(uintptr_t)ehdr->e_entry;
+       if (!obj->dynamic) {
+               _rtld_error("%s: not dynamically linked", path);
+               goto bad;
+       }
+       if (nsegs != 2) {
+               _rtld_error("%s: wrong number of segments (%d != 2)", path,
+                   nsegs);
+               goto bad;
+       }
+
+       /*
+        * Map the entire address space of the object as a file
+        * region to stake out our contiguous region and establish a
+        * base for relocation.  We use a file mapping so that
+        * the kernel will give us whatever alignment is appropriate
+        * for the platform we're running on.
+        *
+        * We map it using the text protection, map the data segment
+        * into the right place, then map an anon segment for the bss
+        * and unmap the gaps left by padding to alignment.
+        */
+
+#ifdef MAP_ALIGNED
+       base_alignment = segs[0]->p_align;
+#endif
+       base_offset = round_down(segs[0]->p_offset);
+       base_vaddr = round_down(segs[0]->p_vaddr);
+       base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz);
+       text_vlimit = round_up(segs[0]->p_vaddr + segs[0]->p_memsz);
+       text_flags = protflags(segs[0]->p_flags);
+       data_offset = round_down(segs[1]->p_offset);
+       data_vaddr = round_down(segs[1]->p_vaddr);
+       data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz);
+       data_flags = protflags(segs[1]->p_flags);
+#ifdef RTLD_LOADER
+       clear_vaddr = segs[1]->p_vaddr + segs[1]->p_filesz;
+#endif
+
+       obj->textsize = text_vlimit - base_vaddr;
+       obj->vaddrbase = base_vaddr;
+       obj->isdynamic = ehdr->e_type == ET_DYN;
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+       if (phtls != NULL) {
+               ++_rtld_tls_dtv_generation;
+               obj->tlsindex = ++_rtld_tls_max_index;
+               obj->tlssize = phtls->p_memsz;
+               obj->tlsalign = phtls->p_align;
+               obj->tlsinitsize = phtls->p_filesz;
+               tls_vaddr = phtls->p_vaddr;
+       }
+#endif
+
+       obj->phdr_loaded = false;
+       for (i = 0; i < nsegs; i++) {
+               if (phdr_vaddr != EA_UNDEF &&
+                   segs[i]->p_vaddr <= phdr_vaddr &&
+                   segs[i]->p_memsz >= phdr_memsz) {
+                       obj->phdr_loaded = true;
+                       break;
+               }
+               if (segs[i]->p_offset <= ehdr->e_phoff &&
+                   segs[i]->p_memsz >= phsize) {
+                       phdr_vaddr = segs[i]->p_vaddr + ehdr->e_phoff;
+                       phdr_memsz = phsize;
+                       obj->phdr_loaded = true;
+                       break;
+               }
+       }
+       if (obj->phdr_loaded) {
+               obj->phdr = (void *)(uintptr_t)phdr_vaddr;
+               obj->phsize = phdr_memsz;
+       } else {
+               Elf_Phdr *buf;
+               buf = xmalloc(phsize);
+               if (buf == NULL) {
+                       _rtld_error("%s: cannot allocate program header", path);
+                       goto bad;
+               }
+               memcpy(buf, phdr, phsize);
+               obj->phdr = buf;
+               obj->phsize = phsize;
+       }
+       dbg(("%s: phdr %p phsize %zu (%s)", obj->path, obj->phdr, obj->phsize,
+            obj->phdr_loaded ? "loaded" : "allocated"));
+
+       /* Unmap header if it overlaps the first load section. */
+       if (base_offset < _rtld_pagesz) {
+               munmap(ehdr, _rtld_pagesz);
+               obj->ehdr = MAP_FAILED;
+       }
+
+       /*
+        * Calculate log2 of the base section alignment.
+        */
+       mapflags = 0;
+#ifdef MAP_ALIGNED
+       if (base_alignment > _rtld_pagesz) {
+               unsigned int log2 = 0;
+               for (; base_alignment > 1; base_alignment >>= 1)
+                       log2++;
+               mapflags = MAP_ALIGNED(log2);
+       }
+#endif
+
+#ifdef RTLD_LOADER
+       base_addr = obj->isdynamic ? NULL : (caddr_t)base_vaddr;
+#else
+       base_addr = NULL;
+#endif
+       mapsize = base_vlimit - base_vaddr;
+
+#ifndef __minix
+       mapbase = mmap(base_addr, mapsize, text_flags,
+           mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset);
+#else
+       mapbase = minix_mmap(base_addr, mapsize, PROT_READ|PROT_WRITE,
+           MAP_ANON | MAP_PREALLOC, -1, 0);
+#if MINIXVERBOSE
+       fprintf(stderr, "minix mmap for whole block: 0x%lx-0x%lx\n", mapbase, mapbase+mapsize);
+#endif
+       Pread(mapbase, obj->textsize, fd, 0);
+#endif
+       if (mapbase == MAP_FAILED) {
+               _rtld_error("mmap of entire address space failed: %s",
+                   xstrerror(errno));
+               goto bad;
+       }
+
+       /* Overlay the data segment onto the proper region. */
+       data_addr = mapbase + (data_vaddr - base_vaddr);
+#ifdef __minix
+       Pread(data_addr, data_vlimit - data_vaddr, fd, data_offset);
+#else
+       if (mmap(data_addr, data_vlimit - data_vaddr, data_flags,
+           MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, data_offset) ==
+           MAP_FAILED) {
+               _rtld_error("mmap of data failed: %s", xstrerror(errno));
+               goto bad;
+       }
+
+       /* Overlay the bss segment onto the proper region. */
+       if (mmap(mapbase + data_vlimit - base_vaddr, base_vlimit - data_vlimit,
+           data_flags, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) ==
+           MAP_FAILED) {
+               _rtld_error("mmap of bss failed: %s", xstrerror(errno));
+               goto bad;
+       }
+
+       /* Unmap the gap between the text and data. */
+       gap_addr = mapbase + round_up(text_vlimit - base_vaddr);
+       gap_size = data_addr - gap_addr;
+       if (gap_size != 0 && mprotect(gap_addr, gap_size, PROT_NONE) == -1) {
+               _rtld_error("mprotect of text -> data gap failed: %s",
+                   xstrerror(errno));
+               goto bad;
+       }
+#endif
+
+#ifdef RTLD_LOADER
+       /* Clear any BSS in the last page of the data segment. */
+       clear_addr = mapbase + (clear_vaddr - base_vaddr);
+       if ((nclear = data_vlimit - clear_vaddr) > 0)
+               memset(clear_addr, 0, nclear);
+
+       /* Non-file portion of BSS mapped above. */
+#endif
+
+#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
+       if (phtls != NULL)
+               obj->tlsinit = mapbase + tls_vaddr;
+#endif
+
+       obj->mapbase = mapbase;
+       obj->mapsize = mapsize;
+       obj->relocbase = mapbase - base_vaddr;
+
+       if (obj->dynamic)
+               obj->dynamic = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->dynamic);
+       if (obj->entry)
+               obj->entry = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->entry);
+       if (obj->interp)
+               obj->interp = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->interp);
+       if (obj->phdr_loaded)
+               obj->phdr =  (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->phdr);
+
+       return obj;
+
+bad:
+       if (obj->ehdr != MAP_FAILED)
+               munmap(obj->ehdr, _rtld_pagesz);
+       if (mapbase != MAP_FAILED)
+               munmap(mapbase, mapsize);
+       _rtld_obj_free(obj);
+       return NULL;
+}
+
+/*
+ * Given a set of ELF protection flags, return the corresponding protection
+ * flags for MMAP.
+ */
+static int
+protflags(int elfflags)
+{
+       int prot = 0;
+
+       if (elfflags & PF_R)
+               prot |= PROT_READ;
+#ifdef RTLD_LOADER
+       if (elfflags & PF_W)
+               prot |= PROT_WRITE;
+#endif
+       if (elfflags & PF_X)
+               prot |= PROT_EXEC;
+       return prot;
+}
index 0d3253dc9d2e9883d4cf42a66026e0552f61fd6f..77d2ef010740fb5878864c7ef48b24e5eef6ce3d 100644 (file)
@@ -451,6 +451,7 @@ __dso_public extern void *___tls_get_addr(void *)
 /* map_object.c */
 struct stat;
 Obj_Entry *_rtld_map_object(const char *, int, const struct stat *);
+Obj_Entry *_rtld_map_object_fallback(const char *, int, const struct stat *);
 void _rtld_obj_free(Obj_Entry *);
 Obj_Entry *_rtld_obj_new(void);
 
index d6dc1e85f8a7c69df6d303588c29d61a27807a40..3bc751e6d8aae5ac4c1ad758827ab5bfa9cf3c7e 100644 (file)
  * SUCH DAMAGE.
  */
 
+
+#ifdef __minix
+#define mmap minix_mmap
+#define munmap minix_munmap
+#ifndef MAP_COPY
+#define MAP_COPY MAP_PRIVATE
+#endif
+#endif
+
 #ifndef MAKE_NATIVE
 static char rcsid[] = "$NetBSD: parse.c,v 1.185 2012/06/12 19:21:51 joerg Exp $";
 #else
@@ -133,9 +142,6 @@ __RCSID("$NetBSD: parse.c,v 1.185 2012/06/12 19:21:51 joerg Exp $");
 #include <stdarg.h>
 #include <stdio.h>
 
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
 #ifndef MAP_COPY
 #define MAP_COPY MAP_PRIVATE
 #endif
@@ -403,9 +409,7 @@ loadedfile_destroy(struct loadedfile *lf)
 {
        if (lf->buf != NULL) {
                if (lf->maplen > 0) {
-#ifndef __minix
                        munmap(lf->buf, lf->maplen);
-#endif
                } else {
                        free(lf->buf);
                }
@@ -430,7 +434,6 @@ loadedfile_nextbuf(void *x, size_t *len)
        return lf->buf;
 }
 
-#ifndef __minix
 /*
  * Try to get the size of a file.
  */
@@ -463,7 +466,6 @@ load_getsize(int fd, size_t *ret)
        *ret = (size_t) st.st_size;
        return SUCCESS;
 }
-#endif /* ndef __minix */
 
 /*
  * Read in a file.
@@ -479,9 +481,7 @@ static struct loadedfile *
 loadfile(const char *path, int fd)
 {
        struct loadedfile *lf;
-#ifndef __minix
        long pagesize;
-#endif
        ssize_t result;
        size_t bufpos;
 
@@ -501,7 +501,6 @@ loadfile(const char *path, int fd)
 #endif
        }
 
-#ifndef __minix
        if (load_getsize(fd, &lf->len) == SUCCESS) {
                /* found a size, try mmap */
                pagesize = sysconf(_SC_PAGESIZE);
@@ -524,6 +523,7 @@ loadfile(const char *path, int fd)
                 * FUTURE: remove PROT_WRITE when the parser no longer
                 * needs to scribble on the input.
                 */
+
                lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE,
                               MAP_FILE|MAP_COPY, fd, 0);
                if (lf->buf != MAP_FAILED) {
@@ -539,7 +539,6 @@ loadfile(const char *path, int fd)
                        goto done;
                }
        }
-#endif
 
        /* cannot mmap; load the traditional way */
 
@@ -572,9 +571,7 @@ loadfile(const char *path, int fd)
                lf->buf = bmake_realloc(lf->buf, lf->len);
        }
 
-#ifndef __minix
 done:
-#endif /* !defined(__minix) */
        if (path != NULL) {
                close(fd);
        }