blob: c8536a8f70b81601cb07efaa59a439c2b6e18966 [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
31#include "core.h"
32#include "pub_core_aspacemgr.h"
33#include "pub_core_libcbase.h"
34#include "pub_core_libcassert.h"
35#include "pub_core_libcmman.h"
36#include "pub_core_libcprint.h"
37#include "vki_unistd.h"
38
39SysRes VG_(mmap_native)(void *start, SizeT length, UInt prot, UInt flags,
40 UInt fd, OffT offset)
41{
42 SysRes res;
43# if defined(VGP_x86_linux)
44 {
45 UWord args[6];
46 args[0] = (UWord)start;
47 args[1] = length;
48 args[2] = prot;
49 args[3] = flags;
50 args[4] = fd;
51 args[5] = offset;
52 res = VG_(do_syscall1)(__NR_mmap, (UWord)args );
53 }
54# elif defined(VGP_amd64_linux)
55 res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
56 prot, flags, fd, offset);
57# else
58# error Unknown platform
59# endif
60 return res;
61}
62
63/* Returns -1 on failure. */
64void* VG_(mmap)( void* start, SizeT length,
65 UInt prot, UInt flags, UInt sf_flags, UInt fd, OffT offset)
66{
67 SysRes res;
68
69 if (!(flags & VKI_MAP_FIXED)) {
70 start = (void *)VG_(find_map_space)((Addr)start, length, !!(flags & VKI_MAP_CLIENT));
71
72 flags |= VKI_MAP_FIXED;
73 }
74 if (start == 0)
75 return (void *)-1;
76
77 res = VG_(mmap_native)(start, length, prot,
78 flags & ~(VKI_MAP_NOSYMS | VKI_MAP_CLIENT),
79 fd, offset);
80
81 // Check it ended up in the right place.
82 if (!res.isError) {
83 if (flags & VKI_MAP_CLIENT) {
84 vg_assert(VG_(client_base) <= res.val
85 && res.val+length <= VG_(client_end));
86 } else {
87 vg_assert(VG_(valgrind_base) <= res.val
88 && res.val+length-1 <= VG_(valgrind_last));
89 }
90
91 sf_flags |= SF_MMAP;
92 if ( flags & VKI_MAP_FIXED) sf_flags |= SF_FIXED;
93 if ( flags & VKI_MAP_SHARED) sf_flags |= SF_SHARED;
94 if (!(flags & VKI_MAP_ANONYMOUS)) sf_flags |= SF_FILE;
95 if (!(flags & VKI_MAP_CLIENT)) sf_flags |= SF_VALGRIND;
96 if ( flags & VKI_MAP_NOSYMS) sf_flags |= SF_NOSYMS;
97
98 VG_(map_fd_segment)(res.val, length, prot, sf_flags, fd, offset, NULL);
99 }
100
101 return res.isError ? (void*)-1 : (void*)res.val;
102}
103
104static SysRes munmap_native(void *start, SizeT length)
105{
106 return VG_(do_syscall2)(__NR_munmap, (UWord)start, length );
107}
108
109/* Returns -1 on failure. */
110Int VG_(munmap)( void* start, SizeT length )
111{
112 SysRes res = munmap_native(start, length);
113 if (!res.isError) {
114 VG_(unmap_range)((Addr)start, length);
115 return 0;
116 } else {
117 return -1;
118 }
119}
120
121SysRes VG_(mprotect_native)( void *start, SizeT length, UInt prot )
122{
123 return VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot );
124}
125
126Int VG_(mprotect)( void *start, SizeT length, UInt prot )
127{
128 SysRes res = VG_(mprotect_native)(start, length, prot);
129 if (!res.isError) {
130 VG_(mprotect_range)((Addr)start, length, prot);
131 return 0;
132 } else {
133 return -1;
134 }
135}
136
137void* VG_(get_memory_from_mmap) ( SizeT nBytes, Char* who )
138{
139 static SizeT tot_alloc = 0;
140 void* p;
141 p = VG_(mmap)(0, nBytes,
142 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
143 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, -1, 0);
144
145 if (p != ((void*)(-1))) {
146 vg_assert((void*)VG_(valgrind_base) <= p && p <= (void*)VG_(valgrind_last));
147 tot_alloc += nBytes;
148 if (0)
149 VG_(printf)(
150 "get_memory_from_mmap: %llu tot, %llu req = %p .. %p, caller %s\n",
151 (ULong)tot_alloc, (ULong)nBytes, p, ((char*)p) + nBytes - 1, who );
152 return p;
153 }
154
155 VG_(printf)("\n");
156 VG_(printf)("VG_(get_memory_from_mmap): %s's request for %llu bytes failed.\n",
157 who, (ULong)nBytes);
158 VG_(printf)("VG_(get_memory_from_mmap): %llu bytes already allocated.\n",
159 (ULong)tot_alloc);
160 VG_(printf)("\n");
161 VG_(printf)("Sorry. You could try using a tool that uses less memory;\n");
162 VG_(printf)("eg. addrcheck instead of memcheck.\n");
163 VG_(printf)("\n");
164 VG_(exit)(1);
165}
166
167/*--------------------------------------------------------------------*/
168/*--- end ---*/
169/*--------------------------------------------------------------------*/
170