]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Rationalise the mmap system call handling - after examining the kernel
authorTom Hughes <tom@compton.nu>
Fri, 30 Sep 2005 08:07:53 +0000 (08:07 +0000)
committerTom Hughes <tom@compton.nu>
Fri, 30 Sep 2005 08:07:53 +0000 (08:07 +0000)
source it turns out that there are five different versions of mmap for
the three platforms we currently support:

  - On x86-linux there is mmap (aka old_mmap) which takes the
    arguments in a memory block and the offset in bytes; and
    mmap2 (aka sys_mmap2) which takes the arguments in the normal
    way and the offset in pages.

  - On ppc32-linux there is mmap (aka sys_mmap) which takes the
    arguments in the normal way and the offset in bytes; and
    mmap2 (aka sys_mmap2) which takes the arguments in the normal
    way and the offset in pages.

  - On amd64-linux everything is simple and there is just the one
    call, mmap (aka sys_mmap)  which takes the arguments in the normal
    way and the offset in bytes.

To reconcile all this I have created a generic handler and then
written five platform specific wrappers which normalise all the
arguments and then call the generic handler.

I have also modified the address space manager to use mmap2 rather
than mmap on x86 and ppc32 so that large offsets can be correctly
handled.

There is still an issue of OffT truncating offsets as we go through
the address space manager that will need to be addressed.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4834

coregrind/m_aspacemgr/aspacemgr.c
coregrind/m_syswrap/priv_syswrap-generic.h
coregrind/m_syswrap/priv_syswrap-linux.h
coregrind/m_syswrap/syswrap-amd64-linux.c
coregrind/m_syswrap/syswrap-generic.c
coregrind/m_syswrap/syswrap-linux.c
coregrind/m_syswrap/syswrap-ppc32-linux.c
coregrind/m_syswrap/syswrap-x86-linux.c

index 9ec0b17a20a4120979cbc38085017075887b9d67..522f4ec48669e5d7ef46f9a1652028a229fe0f83 100644 (file)
@@ -228,23 +228,12 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr start, SizeT length, UInt prot,
                                   UInt flags, UInt fd, OffT offset)
 {
    SysRes res;
-#  if defined(VGP_x86_linux)
-   { 
-      UWord args[6];
-      args[0] = (UWord)start;
-      args[1] = length;
-      args[2] = prot;
-      args[3] = flags;
-      args[4] = fd;
-      args[5] = offset;
-      res = VG_(do_syscall1)(__NR_mmap, (UWord)args );
-   }
+#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
+   res = VG_(do_syscall6)(__NR_mmap2, (UWord)start, length,
+                          prot, flags, fd, offset / VKI_PAGE_SIZE));
 #  elif defined(VGP_amd64_linux)
    res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, 
                          prot, flags, fd, offset);
-#  elif defined(VGP_ppc32_linux)
-   res = VG_(do_syscall6)(__NR_mmap, (UWord)(start), (length),
-                          prot, flags, fd, offset);
 #  else
 #    error Unknown platform
 #  endif
index 8a5b6fc9c9aea238999434c3547b1f6c7ec25133..d99af6e398c832316bae69c5c6ff3a8b6f1a2ff3 100644 (file)
@@ -242,6 +242,8 @@ extern void   ML_(generic_POST_sys_shmdt)       ( TId, UW, UW );
 extern void   ML_(generic_PRE_sys_shmctl)       ( TId, UW, UW, UW );
 extern void   ML_(generic_POST_sys_shmctl)      ( TId, UW, UW, UW, UW );
 
+extern SysRes ML_(generic_PRE_sys_mmap)         ( TId, UW, UW, UW, UW, UW, UW );
+
 #undef TId
 #undef UW
 #undef SR
index 935037be4f4366271abc709e880b8aafba583077..d67937a4d6843b1ad1cc5c76673721bfdf0c8283 100644 (file)
@@ -66,7 +66,6 @@ DECL_TEMPLATE(linux, sys_prctl);
 DECL_TEMPLATE(linux, sys_sendfile);
 DECL_TEMPLATE(linux, sys_sendfile64);
 DECL_TEMPLATE(linux, sys_futex);
-DECL_TEMPLATE(linux, sys_mmap2);
 
 DECL_TEMPLATE(linux, sys_epoll_create);
 DECL_TEMPLATE(linux, sys_epoll_ctl);
index 81a4dbfdba4424111021584162f6be9645237889..c18cd42a37cd1f64f964ad11a6f20a1e40ddac53 100644 (file)
@@ -569,6 +569,7 @@ DECL_TEMPLATE(amd64_linux, sys_ptrace);
 DECL_TEMPLATE(amd64_linux, sys_pread64);
 DECL_TEMPLATE(amd64_linux, sys_pwrite64);
 DECL_TEMPLATE(amd64_linux, sys_fadvise64);
+DECL_TEMPLATE(amd64_linux, sys_mmap);
 
 
 PRE(sys_clone)
@@ -1136,6 +1137,21 @@ PRE(sys_fadvise64)
                  int, fd, vki_loff_t, offset, vki_size_t, len, int, advice);
 }
 
+PRE(sys_mmap)
+{
+   SysRes r;
+
+   PRINT("sys_mmap ( %p, %llu, %d, %d, %d, %d )",
+         ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
+   PRE_REG_READ6(long, "mmap",
+                 unsigned long, start, unsigned long, length,
+                 unsigned long, prot,  unsigned long, flags,
+                 unsigned long, fd,    unsigned long, offset);
+
+   r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
+   SET_STATUS_from_SysRes(r);
+}
+
 #undef PRE
 #undef POST
 
@@ -1167,7 +1183,7 @@ const SyscallTableEntry ML_(syscall_table)[] = {
    GENXY(__NR_lstat,             sys_newlstat),       // 6 
    GENXY(__NR_poll,              sys_poll),           // 7 
    LINX_(__NR_lseek,             sys_lseek),          // 8 
-   LINX_(__NR_mmap,              sys_mmap2),          // 9 
+   PLAX_(__NR_mmap,              sys_mmap),           // 9 
 
    GENXY(__NR_mprotect,          sys_mprotect),       // 10 
    GENXY(__NR_munmap,            sys_munmap),         // 11 
index 4b56818065c59f75b9b96f138193c99e05d9c3aa..13453a34cd8b6916e2356647dce1356f8efae16b 100644 (file)
@@ -1709,6 +1709,79 @@ ML_(generic_POST_sys_shmctl) ( ThreadId tid,
 }
 
 
+/* ---------------------------------------------------------------------
+   Generic handler for mmap
+   ------------------------------------------------------------------ */
+
+SysRes
+ML_(generic_PRE_sys_mmap) ( ThreadId tid,
+                            UWord arg1, UWord arg2, UWord arg3,
+                            UWord arg4, UWord arg5, UWord arg6 )
+{
+   Addr       advised;
+   SysRes     sres;
+   MapRequest mreq;
+   Bool       mreq_ok;
+
+   if (arg2 == 0) {
+      /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
+         shall be established. */
+      return VG_(mk_SysRes_Error)( VKI_EINVAL );
+   }
+
+   if (!VG_IS_PAGE_ALIGNED(arg1)) {
+      /* zap any misaligned addresses. */
+      /* SuSV3 says misaligned addresses only cause the MAP_FIXED case
+         to fail.   Here, we catch them all. */
+      return VG_(mk_SysRes_Error)( VKI_EINVAL );
+   }
+
+   /* Figure out what kind of allocation constraints there are
+      (fixed/hint/any), and ask aspacem what we should do. */
+   mreq.start = arg1;
+   mreq.len   = arg2;
+   if (arg4 & VKI_MAP_FIXED) {
+      mreq.rkind = MFixed;
+   } else
+   if (arg1 != 0) {
+      mreq.rkind = MHint;
+   } else {
+      mreq.rkind = MAny;
+   }
+
+   /* Enquire ... */
+   advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
+   if (!mreq_ok) {
+      /* Our request was bounced, so we'd better fail. */
+      return VG_(mk_SysRes_Error)( VKI_EINVAL );
+   }
+
+   /* Otherwise we're OK (so far).  Install aspacem's choice of
+      address, and let the mmap go through.  */
+   sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
+                                    arg4 | VKI_MAP_FIXED,
+                                    arg5, arg6);
+
+   if (!sres.isError) {
+      /* Notify aspacem and the tool. */
+      ML_(notify_aspacem_and_tool_of_mmap)( 
+         (Addr)sres.val, /* addr kernel actually assigned */
+         arg2, arg3, 
+         arg4, /* the original flags value */
+         arg5, arg6 
+      );
+      /* Load symbols? */
+      VG_(di_notify_mmap)( (Addr)sres.val );
+   }
+
+   /* Stay sane */
+   if (!sres.isError && (arg4 & VKI_MAP_FIXED))
+      vg_assert(sres.val == arg1);
+
+   return sres;
+}
+
+
 /* ---------------------------------------------------------------------
    The Main Entertainment ... syscall wrappers
    ------------------------------------------------------------------ */
index 33e9879aa4b0c551ed9bce8ebc1c3c79fda3a72d..a9d81ba988390d65e2aca4eac7b88fbdc5a55a19 100644 (file)
@@ -548,97 +548,6 @@ POST(sys_futex)
    }
 }
 
-PRE(sys_mmap2)
-{
-   Addr       advised;
-   SysRes     sres;
-   OffT       offset;
-   MapRequest mreq;
-   Bool       mreq_ok;
-
-   // Exactly like old_mmap() in x86-linux except:
-   //  - all 6 args are passed in regs, rather than in a memory-block.
-   //  - on x86-linux, the file offset is specified in pagesize units
-   //    rather than bytes, so that it can be used for files bigger 
-   //    than 2^32 bytes.  On amd64-linux and ppc32-linux it appears
-   //    to be in bytes.
-   PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )",
-         ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
-   PRE_REG_READ6(long, "mmap2",
-                 unsigned long, start, unsigned long, length,
-                 unsigned long, prot,  unsigned long, flags,
-                 unsigned long, fd,    unsigned long, offset);
-
-   if (ARG2 == 0) {
-      /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
-         shall be established. */
-      SET_STATUS_Failure( VKI_EINVAL );
-      return;
-   }
-
-   if (!VG_IS_PAGE_ALIGNED(ARG1)) {
-      /* zap any misaligned addresses. */
-      /* SuSV3 says misaligned addresses only cause the MAP_FIXED case
-         to fail.   Here, we catch them all. */
-      SET_STATUS_Failure( VKI_EINVAL );
-      return;
-   }
-
-   /* Figure out what kind of allocation constraints there are
-      (fixed/hint/any), and ask aspacem what we should do. */
-   mreq.start = ARG1;
-   mreq.len   = ARG2;
-   if (ARG4 & VKI_MAP_FIXED) {
-      mreq.rkind = MFixed;
-   } else
-   if (ARG1 != 0) {
-      mreq.rkind = MHint;
-   } else {
-      mreq.rkind = MAny;
-   }
-
-   /* Enquire ... */
-   advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
-   if (!mreq_ok) {
-      /* Our request was bounced, so we'd better fail. */
-      SET_STATUS_Failure( VKI_EINVAL );
-      return;
-   }
-
-   vg_assert(! FAILURE);
-
-#  if defined(VGP_x86_linux)
-   offset = ARG6 * VKI_PAGE_SIZE;
-#  elif defined(VGP_amd64_linux) || defined(VGP_ppc32_linux)
-   offset = ARG6;
-#  else
-#    error Unknown platform
-#  endif
-
-   /* Otherwise we're OK (so far).  Install aspacem's choice of
-      address, and let the mmap go through.  */
-   sres = VG_(am_do_mmap_NO_NOTIFY)(advised, ARG2, ARG3,
-                                    ARG4 | VKI_MAP_FIXED,
-                                    ARG5, offset);
-   SET_STATUS_from_SysRes(sres);
-
-   if (!sres.isError) {
-      /* Notify aspacem and the tool. */
-      ML_(notify_aspacem_and_tool_of_mmap)( 
-         (Addr)sres.val, /* addr kernel actually assigned */
-         ARG2, ARG3, 
-         ARG4, /* the original flags value */
-         ARG5, offset
-      );
-      /* Load symbols? */
-      VG_(di_notify_mmap)( (Addr)sres.val );
-   }
-
-   /* Stay sane */
-   if (SUCCESS && (ARG4 & VKI_MAP_FIXED))
-      vg_assert(RES == ARG1);
-}
-
 
 /* ---------------------------------------------------------------------
    epoll_* wrappers
index 03e0d13cce4a1ae0e8f599ae314f6085d7a123c6..4c7d051f4c4bb40bb1d5b0a3d4d98cd3cc39135d 100644 (file)
@@ -592,6 +592,8 @@ void setup_child ( /*OUT*/ ThreadArchState *child,
    magic. */
 
 DECL_TEMPLATE(ppc32_linux, sys_socketcall);
+DECL_TEMPLATE(ppc32_linux, sys_mmap);
+DECL_TEMPLATE(ppc32_linux, sys_mmap2);
 DECL_TEMPLATE(ppc32_linux, sys_stat64);
 DECL_TEMPLATE(ppc32_linux, sys_lstat64);
 DECL_TEMPLATE(ppc32_linux, sys_fstat64);
@@ -856,6 +858,39 @@ POST(sys_socketcall)
 #  undef ARG2_5
 }
 
+PRE(sys_mmap)
+{
+   SysRes r;
+
+   PRINT("sys_mmap ( %p, %llu, %d, %d, %d, %d )",
+         ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
+   PRE_REG_READ6(long, "mmap",
+                 unsigned long, start, unsigned long, length,
+                 unsigned long, prot,  unsigned long, flags,
+                 unsigned long, fd,    unsigned long, offset);
+
+   r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
+   SET_STATUS_from_SysRes(r);
+}
+
+PRE(sys_mmap2)
+{
+   SysRes r;
+
+   // Exactly like old_mmap() except:
+   //  - the file offset is specified in pagesize units rather than bytes,
+   //    so that it can be used for files bigger than 2^32 bytes.
+   PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )",
+         ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
+   PRE_REG_READ6(long, "mmap2",
+                 unsigned long, start, unsigned long, length,
+                 unsigned long, prot,  unsigned long, flags,
+                 unsigned long, fd,    unsigned long, offset);
+
+   r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 * VKI_PAGE_SIZE );
+   SET_STATUS_from_SysRes(r);
+}
+
 // XXX: lstat64/fstat64/stat64 are generic, but not necessarily
 // applicable to every architecture -- I think only to 32-bit archs.
 // We're going to need something like linux/core_os32.h for such
@@ -1725,7 +1760,7 @@ const SyscallTableEntry ML_(syscall_table)[] = {
 //..    //   (__NR_reboot,            sys_reboot),            // 88 */Linux
 //..    //   (__NR_readdir,           old_readdir),           // 89 -- superseded
 
-   LINX_(__NR_mmap,              sys_mmap2),                  // 90
+   PLAX_(__NR_mmap,              sys_mmap),                   // 90
    GENXY(__NR_munmap,            sys_munmap),                 // 91
 //..    GENX_(__NR_truncate,          sys_truncate),          // 92
    GENX_(__NR_ftruncate,         sys_ftruncate),         // 93
@@ -1851,7 +1886,7 @@ const SyscallTableEntry ML_(syscall_table)[] = {
    GENX_(__NR_vfork,             sys_fork),              // 189
    GENXY(__NR_ugetrlimit,        sys_getrlimit),         // 190
 //__NR_readahead      // 191 ppc/Linux only?
-   LINX_(__NR_mmap2,             sys_mmap2),             // 192
+   PLAX_(__NR_mmap2,             sys_mmap2),             // 192
 //..    GENX_(__NR_truncate64,        sys_truncate64),        // 193
 //..    GENX_(__NR_ftruncate64,       sys_ftruncate64),       // 194
 //..    
index 89a0af47244710a63be240e8f98ef0ce0812e65d..797e257516a562b1d18bed062e6575eaf7deb1c2 100644 (file)
@@ -966,6 +966,7 @@ DECL_TEMPLATE(x86_linux, sys_fstat64);
 DECL_TEMPLATE(x86_linux, sys_lstat64);
 DECL_TEMPLATE(x86_linux, sys_clone);
 DECL_TEMPLATE(x86_linux, old_mmap);
+DECL_TEMPLATE(x86_linux, sys_mmap2);
 DECL_TEMPLATE(x86_linux, sys_sigreturn);
 DECL_TEMPLATE(x86_linux, sys_ipc);
 DECL_TEMPLATE(x86_linux, sys_rt_sigreturn);
@@ -1466,10 +1467,7 @@ PRE(old_mmap)
          unsigned long offset;
    }; */
    UWord a1, a2, a3, a4, a5, a6;
-   Addr       advised;
-   SysRes     sres;
-   MapRequest mreq;
-   Bool       mreq_ok;
+   SysRes r;
 
    UWord* args = (UWord*)ARG1;
    PRE_REG_READ1(long, "old_mmap", struct mmap_arg_struct *, args);
@@ -1485,65 +1483,27 @@ PRE(old_mmap)
    PRINT("old_mmap ( %p, %llu, %d, %d, %d, %d )",
          a1, (ULong)a2, a3, a4, a5, a6 );
 
-   if (a2 == 0) {
-      /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
-         shall be established. */
-      SET_STATUS_Failure( VKI_EINVAL );
-      return;
-   }
-
-   if (!VG_IS_PAGE_ALIGNED(a1)) {
-      /* zap any misaligned addresses. */
-      SET_STATUS_Failure( VKI_EINVAL );
-      return;
-   }
-
-   /* Figure out what kind of allocation constraints there are
-      (fixed/hint/any), and ask aspacem what we should do. */
-   mreq.start = a1;
-   mreq.len   = a2;
-   if (a4 & VKI_MAP_FIXED) {
-      mreq.rkind = MFixed;
-   } else
-   if (a1 != 0) {
-      mreq.rkind = MHint;
-   } else {
-      mreq.rkind = MAny;
-   }
-
-   /* Enquire ... */
-   advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
-   if (!mreq_ok) {
-      /* Our request was bounced, so we'd better fail. */
-      SET_STATUS_Failure( VKI_EINVAL );
-      return;
-   }
+   r = ML_(generic_PRE_sys_mmap)( tid, a1, a2, a3, a4, a5, a6 );
+   SET_STATUS_from_SysRes(r);
+}
 
-   /* Otherwise we're OK (so far).  Install aspacem's choice of
-      address, and let the mmap go through.  */
-   a1 = advised;
-   a4 |= VKI_MAP_FIXED;
-
-   vg_assert(! FAILURE);
-
-   sres = VG_(am_do_mmap_NO_NOTIFY)(a1, a2, a3, a4, a5, a6);
-   SET_STATUS_from_SysRes(sres);
-
-   if (!sres.isError) {
-      /* Notify aspacem and the tool. */
-      ML_(notify_aspacem_and_tool_of_mmap)( 
-         (Addr)sres.val, /* addr kernel actually assigned */
-         a2, a3, 
-         args[4-1], /* the original flags value */
-         a5, a6 
-      );
-      /* Load symbols? */
-      VG_(di_notify_mmap)( (Addr)sres.val );
-   }
+PRE(sys_mmap2)
+{
+   SysRes r;
 
-   /* Stay sane */
-   if (SUCCESS && (args[4-1] & VKI_MAP_FIXED))
-      vg_assert(RES == args[0]);
+   // Exactly like old_mmap() except:
+   //  - all 6 args are passed in regs, rather than in a memory-block.
+   //  - the file offset is specified in pagesize units rather than bytes,
+   //    so that it can be used for files bigger than 2^32 bytes.
+   PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )",
+         ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
+   PRE_REG_READ6(long, "mmap2",
+                 unsigned long, start, unsigned long, length,
+                 unsigned long, prot,  unsigned long, flags,
+                 unsigned long, fd,    unsigned long, offset);
+
+   r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 * VKI_PAGE_SIZE );
+   SET_STATUS_from_SysRes(r);
 }
 
 // XXX: lstat64/fstat64/stat64 are generic, but not necessarily
@@ -2170,7 +2130,7 @@ const SyscallTableEntry ML_(syscall_table)[] = {
    // Nb: we treat vfork as fork
    GENX_(__NR_vfork,             sys_fork),           // 190
    GENXY(__NR_ugetrlimit,        sys_getrlimit),      // 191
-   LINX_(__NR_mmap2,             sys_mmap2),          // 192
+   PLAX_(__NR_mmap2,             sys_mmap2),          // 192
    GENX_(__NR_truncate64,        sys_truncate64),     // 193
    GENX_(__NR_ftruncate64,       sys_ftruncate64),    // 194