Modularised the libc low-level memory management stuff (mmap, etc).


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3891 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_libcmman.c b/coregrind/m_libcmman.c
new file mode 100644
index 0000000..c8536a8
--- /dev/null
+++ b/coregrind/m_libcmman.c
@@ -0,0 +1,170 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Memory management libc stuff.                   m_libcmman.c ---*/
+/*--------------------------------------------------------------------*/
+ 
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "core.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcmman.h"
+#include "pub_core_libcprint.h"
+#include "vki_unistd.h"
+
+SysRes VG_(mmap_native)(void *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 );
+   }
+#  elif defined(VGP_amd64_linux)
+   res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, 
+                         prot, flags, fd, offset);
+#  else
+#    error Unknown platform
+#  endif
+   return res;
+}
+
+/* Returns -1 on failure. */
+void* VG_(mmap)( void* start, SizeT length,
+                 UInt prot, UInt flags, UInt sf_flags, UInt fd, OffT offset)
+{
+   SysRes res;
+
+   if (!(flags & VKI_MAP_FIXED)) {
+      start = (void *)VG_(find_map_space)((Addr)start, length, !!(flags & VKI_MAP_CLIENT));
+
+      flags |= VKI_MAP_FIXED;
+   }
+   if (start == 0)
+      return (void *)-1;
+
+   res = VG_(mmap_native)(start, length, prot, 
+                          flags & ~(VKI_MAP_NOSYMS | VKI_MAP_CLIENT),
+                          fd, offset);
+
+   // Check it ended up in the right place.
+   if (!res.isError) {
+      if (flags & VKI_MAP_CLIENT) {
+         vg_assert(VG_(client_base) <= res.val 
+                   && res.val+length <= VG_(client_end));
+      } else {
+         vg_assert(VG_(valgrind_base) <= res.val 
+                   && res.val+length-1 <= VG_(valgrind_last));
+      }
+
+      sf_flags |= SF_MMAP;
+      if (  flags & VKI_MAP_FIXED)      sf_flags |= SF_FIXED;
+      if (  flags & VKI_MAP_SHARED)     sf_flags |= SF_SHARED;
+      if (!(flags & VKI_MAP_ANONYMOUS)) sf_flags |= SF_FILE;
+      if (!(flags & VKI_MAP_CLIENT))    sf_flags |= SF_VALGRIND;
+      if (  flags & VKI_MAP_NOSYMS)     sf_flags |= SF_NOSYMS;
+
+      VG_(map_fd_segment)(res.val, length, prot, sf_flags, fd, offset, NULL);
+   }
+
+   return res.isError ? (void*)-1 : (void*)res.val;
+}
+
+static SysRes munmap_native(void *start, SizeT length)
+{
+   return VG_(do_syscall2)(__NR_munmap, (UWord)start, length );
+}
+
+/* Returns -1 on failure. */
+Int VG_(munmap)( void* start, SizeT length )
+{
+   SysRes res = munmap_native(start, length);
+   if (!res.isError) {
+      VG_(unmap_range)((Addr)start, length);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+
+SysRes VG_(mprotect_native)( void *start, SizeT length, UInt prot )
+{
+   return VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot );
+}
+
+Int VG_(mprotect)( void *start, SizeT length, UInt prot )
+{
+   SysRes res = VG_(mprotect_native)(start, length, prot);
+   if (!res.isError) {
+      VG_(mprotect_range)((Addr)start, length, prot);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+
+void* VG_(get_memory_from_mmap) ( SizeT nBytes, Char* who )
+{
+   static SizeT tot_alloc = 0;
+   void* p;
+   p = VG_(mmap)(0, nBytes,
+                 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
+                 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, -1, 0);
+
+   if (p != ((void*)(-1))) {
+      vg_assert((void*)VG_(valgrind_base) <= p && p <= (void*)VG_(valgrind_last));
+      tot_alloc += nBytes;
+      if (0)
+         VG_(printf)(
+            "get_memory_from_mmap: %llu tot, %llu req = %p .. %p, caller %s\n",
+            (ULong)tot_alloc, (ULong)nBytes, p, ((char*)p) + nBytes - 1, who );
+      return p;
+   }
+
+   VG_(printf)("\n");
+   VG_(printf)("VG_(get_memory_from_mmap): %s's request for %llu bytes failed.\n",
+               who, (ULong)nBytes);
+   VG_(printf)("VG_(get_memory_from_mmap): %llu bytes already allocated.\n", 
+               (ULong)tot_alloc);
+   VG_(printf)("\n");
+   VG_(printf)("Sorry.  You could try using a tool that uses less memory;\n");
+   VG_(printf)("eg. addrcheck instead of memcheck.\n");
+   VG_(printf)("\n");
+   VG_(exit)(1);
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
+