blob: a2265d35ec996307b20deb298baf621ee67a5f08 [file] [log] [blame]
njne9befc62005-06-11 15:51:30 +00001
2/*--------------------------------------------------------------------*/
3/*--- Memory management libc stuff. m_libcmman.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2005 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
njn899ce732005-06-21 00:28:11 +000032#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
njne9befc62005-06-11 15:51:30 +000033#include "pub_core_aspacemgr.h"
34#include "pub_core_libcbase.h"
35#include "pub_core_libcassert.h"
36#include "pub_core_libcmman.h"
37#include "pub_core_libcprint.h"
njn9abd6082005-06-17 21:31:45 +000038#include "pub_core_syscall.h"
njne9befc62005-06-11 15:51:30 +000039#include "vki_unistd.h"
40
41SysRes VG_(mmap_native)(void *start, SizeT length, UInt prot, UInt flags,
42 UInt fd, OffT offset)
43{
44 SysRes res;
cerion85665ca2005-06-20 15:51:07 +000045#if defined(VGP_x86_linux)
njne9befc62005-06-11 15:51:30 +000046 {
47 UWord args[6];
48 args[0] = (UWord)start;
49 args[1] = length;
50 args[2] = prot;
51 args[3] = flags;
52 args[4] = fd;
53 args[5] = offset;
54 res = VG_(do_syscall1)(__NR_mmap, (UWord)args );
55 }
cerion85665ca2005-06-20 15:51:07 +000056#elif defined(VGP_amd64_linux)
njne9befc62005-06-11 15:51:30 +000057 res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
58 prot, flags, fd, offset);
cerion85665ca2005-06-20 15:51:07 +000059#elif defined(VGP_ppc32_linux)
60 res = VG_(do_syscall6)(__NR_mmap, (UWord)(start), (length),
61 prot, flags, fd, offset);
62#else
63# error Unknown platform
64#endif
njne9befc62005-06-11 15:51:30 +000065 return res;
66}
67
68/* Returns -1 on failure. */
69void* VG_(mmap)( void* start, SizeT length,
70 UInt prot, UInt flags, UInt sf_flags, UInt fd, OffT offset)
71{
72 SysRes res;
73
74 if (!(flags & VKI_MAP_FIXED)) {
75 start = (void *)VG_(find_map_space)((Addr)start, length, !!(flags & VKI_MAP_CLIENT));
76
77 flags |= VKI_MAP_FIXED;
78 }
79 if (start == 0)
80 return (void *)-1;
81
82 res = VG_(mmap_native)(start, length, prot,
83 flags & ~(VKI_MAP_NOSYMS | VKI_MAP_CLIENT),
84 fd, offset);
85
86 // Check it ended up in the right place.
87 if (!res.isError) {
88 if (flags & VKI_MAP_CLIENT) {
89 vg_assert(VG_(client_base) <= res.val
90 && res.val+length <= VG_(client_end));
91 } else {
92 vg_assert(VG_(valgrind_base) <= res.val
93 && res.val+length-1 <= VG_(valgrind_last));
94 }
95
96 sf_flags |= SF_MMAP;
97 if ( flags & VKI_MAP_FIXED) sf_flags |= SF_FIXED;
98 if ( flags & VKI_MAP_SHARED) sf_flags |= SF_SHARED;
99 if (!(flags & VKI_MAP_ANONYMOUS)) sf_flags |= SF_FILE;
100 if (!(flags & VKI_MAP_CLIENT)) sf_flags |= SF_VALGRIND;
101 if ( flags & VKI_MAP_NOSYMS) sf_flags |= SF_NOSYMS;
102
103 VG_(map_fd_segment)(res.val, length, prot, sf_flags, fd, offset, NULL);
104 }
105
106 return res.isError ? (void*)-1 : (void*)res.val;
107}
108
njn83407492005-06-19 16:10:47 +0000109SysRes VG_(munmap_native)(void *start, SizeT length)
njne9befc62005-06-11 15:51:30 +0000110{
111 return VG_(do_syscall2)(__NR_munmap, (UWord)start, length );
112}
113
114/* Returns -1 on failure. */
115Int VG_(munmap)( void* start, SizeT length )
116{
njn83407492005-06-19 16:10:47 +0000117 SysRes res = VG_(munmap_native)(start, length);
njne9befc62005-06-11 15:51:30 +0000118 if (!res.isError) {
119 VG_(unmap_range)((Addr)start, length);
120 return 0;
121 } else {
122 return -1;
123 }
124}
125
126SysRes VG_(mprotect_native)( void *start, SizeT length, UInt prot )
127{
128 return VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot );
129}
130
131Int VG_(mprotect)( void *start, SizeT length, UInt prot )
132{
133 SysRes res = VG_(mprotect_native)(start, length, prot);
134 if (!res.isError) {
135 VG_(mprotect_range)((Addr)start, length, prot);
136 return 0;
137 } else {
138 return -1;
139 }
140}
141
142void* VG_(get_memory_from_mmap) ( SizeT nBytes, Char* who )
143{
144 static SizeT tot_alloc = 0;
145 void* p;
146 p = VG_(mmap)(0, nBytes,
147 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
148 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, -1, 0);
149
150 if (p != ((void*)(-1))) {
151 vg_assert((void*)VG_(valgrind_base) <= p && p <= (void*)VG_(valgrind_last));
152 tot_alloc += nBytes;
153 if (0)
154 VG_(printf)(
155 "get_memory_from_mmap: %llu tot, %llu req = %p .. %p, caller %s\n",
156 (ULong)tot_alloc, (ULong)nBytes, p, ((char*)p) + nBytes - 1, who );
157 return p;
158 }
159
160 VG_(printf)("\n");
161 VG_(printf)("VG_(get_memory_from_mmap): %s's request for %llu bytes failed.\n",
162 who, (ULong)nBytes);
163 VG_(printf)("VG_(get_memory_from_mmap): %llu bytes already allocated.\n",
164 (ULong)tot_alloc);
165 VG_(printf)("\n");
166 VG_(printf)("Sorry. You could try using a tool that uses less memory;\n");
167 VG_(printf)("eg. addrcheck instead of memcheck.\n");
168 VG_(printf)("\n");
169 VG_(exit)(1);
170}
171
njn9260c782005-06-19 21:57:54 +0000172// Returns 0 on failure.
173Addr VG_(get_memory_from_mmap_for_client)
174 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
175{
176 len = VG_PGROUNDUP(len);
177
178 tl_assert(!(sf_flags & SF_FIXED));
179 tl_assert(0 == addr);
180
181 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
182 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
183 sf_flags | SF_CORE, -1, 0);
184 if ((Addr)-1 != addr)
185 return addr;
186 else
187 return 0;
188}
189
190
njne9befc62005-06-11 15:51:30 +0000191/*--------------------------------------------------------------------*/
192/*--- end ---*/
193/*--------------------------------------------------------------------*/
194