]> Zhao Yanbai Git Server - minix.git/commitdiff
ld.so: be more mmap()-behaviour-independent
authorBen Gras <ben@minix3.org>
Fri, 22 Jun 2012 09:55:11 +0000 (11:55 +0200)
committerBen Gras <ben@minix3.org>
Mon, 25 Jun 2012 12:13:07 +0000 (14:13 +0200)
. if the layout of virtual address regions as returned
  by mmap() without a location hint changes, ld.so could
  trip itself up (under minix). this change allocates
  the full size it needs for every object that's loaded
  so that if that succeeds, it's sure there's virtual address
  space for the whole thing no matter what other bits happen
  to be there already.

. this fix exposed a bug in the test; at atexit() execution
  time the loaded object is unmapped, so that part of the
  test is removed.

libexec/ld.elf_so/map_object.c
test/mod.c

index 7f6d0bb87bdf4caff8cd6f4c732566b016c8b764..409cf51c916c35151e04661bcf8f42a7d842800d 100644 (file)
@@ -38,6 +38,7 @@ __RCSID("$NetBSD: map_object.c,v 1.41 2010/10/16 10:27:07 skrll Exp $");
 #endif /* not lint */
 
 #include <errno.h>
+#include <stdio.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
@@ -49,55 +50,27 @@ __RCSID("$NetBSD: map_object.c,v 1.41 2010/10/16 10:27:07 skrll Exp $");
 #include "debug.h"
 #include "rtld.h"
 
-static int protflags(int);     /* Elf flags -> mmap protection */
-
-#define EA_UNDEF               (~(Elf_Addr)0)
-
 #ifdef __minix
-#define mmap   minix_mmap_emulator
-#define munmap minix_munmap
-
-/* for minix, ignore MAP_SHARED and MAP_FILE for now. */
-#define MAP_SHARED 0
-#define MAP_FILE 0
+#define munmap minix_munmap
 #endif
 
-#undef MINIXVERBOSE
-
-static void * minix_mmap_emulator(void *addrhint, size_t size, int prot, int flags, int fd, off_t off)
-{
-       void *ret;
-       int mapflags;
-       size_t s;
-
-       mapflags = flags & (MAP_FIXED);
+#define MINIXVERBOSE 0
 
-#ifdef MINIXVERBOSE
-       if(addrhint) {
-               fprintf(stderr, "0x%lx-0x%lx requested\n", addrhint,
-                       (char *) addrhint + size);
-       }
-#endif
+static int protflags(int);     /* Elf flags -> mmap protection */
 
-       if((ret = minix_mmap(addrhint, size, PROT_READ|PROT_WRITE,
-               MAP_ANON|MAP_PRIVATE|MAP_PREALLOC|mapflags, -1, 0)) == MAP_FAILED) {
-               return ret;
-       }
+#define EA_UNDEF               (~(Elf_Addr)0)
 
-       if(!(mapflags & MAP_ANON)) {
-               if((s=pread(fd, ret, size, off)) <= 0) {
-                       munmap(ret, size);
-                       return MAP_FAILED;
-               }
+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);
        }
 
-#ifdef MINIXVERBOSE
-       fprintf(stderr, "0x%lx-0x%lx mapped\n",
-               ret, (char *) ret + size);
-
+#if MINIXVERBOSE
+       fprintf(stderr, "read 0x%lx bytes from offset 0x%lx to addr 0x%lx\n", size, off, addr);
 #endif
-
-       return ret;
 }
 
 /*
@@ -159,8 +132,17 @@ _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) {
                _rtld_error("%s: read error: %s", path, xstrerror(errno));
@@ -349,9 +331,12 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
        mapbase = mmap(base_addr, mapsize, text_flags,
            mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset);
 #else
-       /* minix doesn't want overlapping mmap()s */
-       mapbase = mmap(base_addr, obj->textsize, text_flags,
-           mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset);
+       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",
@@ -361,13 +346,18 @@ _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) {
                _rtld_error("mmap of data failed: %s", xstrerror(errno));
                goto bad;
        }
+#endif
 
+#ifndef __minix
        bsssize= base_vlimit - data_vlimit;
    if(bsssize > 0) {
        /* Overlay the bss segment onto the proper region. */
@@ -384,7 +374,6 @@ _rtld_map_object(const char *path, int fd, const struct stat *sb)
        gap_addr = mapbase + round_up(text_vlimit - base_vaddr);
        gap_size = data_addr - gap_addr;
 
-#ifndef __minix
        if (gap_size != 0 && mprotect(gap_addr, gap_size, PROT_NONE) == -1) {
                _rtld_error("mprotect of text -> data gap failed: %s",
                    xstrerror(errno));
index 1cc168c96eaa59baaa1e8028928bc5f39af3985f..0226c990994a7fd50aa976b8d1a07154d4864380 100644 (file)
@@ -18,7 +18,6 @@ long modfunction(long v1, long *argcookie, long v2) {
   }
   *argcookie = MAGIC3;
   cookie = MAGIC2;
-  atexit(exithandler);
   return MAGIC1;
 }