/*--------------------------------------------------------------------*/ /*--- 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 "pub_core_basics.h" #include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :( #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" /* 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)); } if (start == 0) return (void *)-1; res = VG_(mmap_native)(start, length, prot, (flags | VKI_MAP_FIXED) & ~(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_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; } /* Returns -1 on failure. */ Int VG_(munmap)( void* start, SizeT length ) { SysRes res = VG_(munmap_native)(start, length); if (!res.isError) { VG_(unmap_range)((Addr)start, length); return 0; } else { return -1; } } 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, SF_VALGRIND, -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); } // Returns 0 on failure. Addr VG_(get_memory_from_mmap_for_client) (SizeT len) { Addr addr; len = VG_PGROUNDUP(len); addr = (Addr)VG_(mmap)(NULL, len, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_CLIENT, SF_CORE, -1, 0); if ((Addr)-1 != addr) return addr; else return 0; } /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/