blob: 514063d308face130aaf6ba59cbc24e52b639c4d [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00003/*--- The address space manager: segment initialisation and ---*/
4/*--- tracking, stack operations ---*/
njn945ed2e2005-06-24 03:28:30 +00005/*--- m_aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00006/*--------------------------------------------------------------------*/
7
8/*
njnb9c427c2004-12-01 14:14:42 +00009 This file is part of Valgrind, a dynamic binary instrumentation
10 framework.
sewardjde4a1d02002-03-22 01:27:54 +000011
njn53612422005-03-12 16:22:54 +000012 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000013 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000014
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
njn25e49d8e72002-09-23 09:36:25 +000030 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000031*/
32
njnc7561b92005-06-19 01:24:32 +000033#include "pub_core_basics.h"
njnf6ec8ec2005-07-21 23:26:25 +000034#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr.h :(
sewardj55f9d1a2005-04-25 11:11:44 +000035#include "pub_core_aspacemgr.h"
njn97405b22005-06-02 03:39:33 +000036#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000037#include "pub_core_libcassert.h"
njn67741c62005-06-20 02:23:07 +000038#include "pub_core_libcfile.h" // For VG_(fstat), VG_(resolve_filename_nodup)
njn36a20fa2005-06-03 03:08:39 +000039#include "pub_core_libcprint.h"
njn9abd6082005-06-17 21:31:45 +000040#include "pub_core_syscall.h"
njn43b9a8a2005-05-10 04:37:01 +000041#include "pub_core_tooliface.h"
njn945ed2e2005-06-24 03:28:30 +000042#include "pub_core_transtab.h" // For VG_(discard_translations)
njn3c660b62005-05-13 22:18:47 +000043#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000044
sewardjde4a1d02002-03-22 01:27:54 +000045
sewardja4495682002-10-21 07:29:59 +000046/* Define to debug the memory-leak-detector. */
47/* #define VG_DEBUG_LEAKCHECK */
48
sewardje517b802005-02-16 01:58:51 +000049static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000050
51/*--------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +000052/*--- Basic globals about the address space. ---*/
53/*--------------------------------------------------------------*/
54
55/* Client address space, lowest to highest (see top of ume.c) */
56Addr VG_(client_base); /* client address space limits */
57Addr VG_(client_end);
58Addr VG_(client_mapbase);
njn04e16982005-05-31 00:23:43 +000059Addr VG_(clstk_base);
60Addr VG_(clstk_end);
rjwalsh0140af52005-06-04 20:42:33 +000061UWord VG_(clstk_id);
njn04e16982005-05-31 00:23:43 +000062
63Addr VG_(brk_base); /* start of brk */
64Addr VG_(brk_limit); /* current brk */
65
66Addr VG_(shadow_base); /* tool's shadow memory */
67Addr VG_(shadow_end);
68
69Addr VG_(valgrind_base); /* valgrind's address range */
70
71// Note that VG_(valgrind_last) names the last byte of the section, whereas
72// the VG_(*_end) vars name the byte one past the end of the section.
73Addr VG_(valgrind_last);
74
75/*--------------------------------------------------------------*/
njnb69f7c12005-06-24 22:17:38 +000076/*--- The raw mman syscalls ---*/
77/*--------------------------------------------------------------*/
78
79SysRes VG_(mmap_native)(void *start, SizeT length, UInt prot, UInt flags,
80 UInt fd, OffT offset)
81{
82 SysRes res;
83#if defined(VGP_x86_linux)
84 {
85 UWord args[6];
86 args[0] = (UWord)start;
87 args[1] = length;
88 args[2] = prot;
89 args[3] = flags;
90 args[4] = fd;
91 args[5] = offset;
92 res = VG_(do_syscall1)(__NR_mmap, (UWord)args );
93 }
94#elif defined(VGP_amd64_linux)
95 res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
96 prot, flags, fd, offset);
97#elif defined(VGP_ppc32_linux)
98 res = VG_(do_syscall6)(__NR_mmap, (UWord)(start), (length),
99 prot, flags, fd, offset);
100#else
101# error Unknown platform
102#endif
103 return res;
104}
105
106SysRes VG_(munmap_native)(void *start, SizeT length)
107{
108 return VG_(do_syscall2)(__NR_munmap, (UWord)start, length );
109}
110
111SysRes VG_(mprotect_native)( void *start, SizeT length, UInt prot )
112{
113 return VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot );
114}
115
116/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +0000117/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +0000118/*--------------------------------------------------------------*/
119
sewardj79048ce2005-02-18 08:28:32 +0000120/* Max number of segments we can track. */
121#define VG_N_SEGMENTS 1000
122
123/* Max number of segment file names we can track. */
124#define VG_N_SEGNAMES 200
125
126/* Max length of a segment file name. */
127#define VG_MAX_SEGNAMELEN 1000
128
129
130/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +0000131
132/* Array [0 .. segments_used-1] of all mappings. */
133/* Sorted by .addr field. */
134/* I: len may not be zero. */
135/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +0000136/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +0000137
138static Segment segments[VG_N_SEGMENTS];
139static Int segments_used = 0;
140
sewardj79048ce2005-02-18 08:28:32 +0000141typedef
142 struct {
143 Bool inUse;
144 Bool mark;
145 HChar fname[VG_MAX_SEGNAMELEN];
146 }
147 SegName;
148
149/* Filename table. _used is the high water mark; an entry is only
150 valid if its index >= 0, < _used, and its .inUse field == True.
151 The .mark field is used to garbage-collect dead entries.
152*/
153static SegName segnames[VG_N_SEGNAMES];
154static Int segnames_used = 0;
155
156
157/* ------ end of STATE for the address-space manager ------ */
158
159
160/* Searches the filename table to find an index for the given name.
161 If none is found, an index is allocated and the name stored. If no
162 space is available we just give up. If the string is too long to
163 store, return -1.
164*/
165static Int allocate_segname ( const HChar* name )
166{
167 Int i, j, len;
168
169 vg_assert(name);
170
njnf6ec8ec2005-07-21 23:26:25 +0000171 if (0) VG_(printf)("allocate_segname %s\n", name);
sewardj79048ce2005-02-18 08:28:32 +0000172
173 len = VG_(strlen)(name);
174 if (len >= VG_MAX_SEGNAMELEN-1) {
175 return -1;
176 }
177
178 /* first see if we already have the name. */
179 for (i = 0; i < segnames_used; i++) {
180 if (!segnames[i].inUse)
181 continue;
182 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
183 return i;
184 }
185 }
186
187 /* no we don't. So look for a free slot. */
188 for (i = 0; i < segnames_used; i++)
189 if (!segnames[i].inUse)
190 break;
191
192 if (i == segnames_used) {
193 /* no free slots .. advance the high-water mark. */
194 if (segnames_used+1 < VG_N_SEGNAMES) {
195 i = segnames_used;
196 segnames_used++;
197 } else {
198 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000199 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000200 " VG_N_SEGNAMES is too small: "
201 "increase it and rebuild Valgrind.\n"
202 );
203 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000204 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000205 " giving up now.\n\n"
206 );
207 VG_(exit)(0);
208 }
209 }
210
211 /* copy it in */
212 segnames[i].inUse = True;
213 for (j = 0; j < len; j++)
214 segnames[i].fname[j] = name[j];
215 vg_assert(len < VG_MAX_SEGNAMELEN);
216 segnames[i].fname[len] = 0;
217 return i;
218}
219
sewardj548be6d2005-02-16 01:31:37 +0000220
221/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
222 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000223 seg.
224*/
sewardj447f2a12005-07-07 13:52:53 +0000225static inline Int compare_addr_with_seg ( Addr a, Segment* seg )
sewardj548be6d2005-02-16 01:31:37 +0000226{
227 if (a < seg->addr)
228 return -1;
229 if (a >= seg->addr + seg->len)
230 return 1;
231 return 0;
232}
233
sewardj79048ce2005-02-18 08:28:32 +0000234
sewardj548be6d2005-02-16 01:31:37 +0000235/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000236 none.
237*/
sewardj548be6d2005-02-16 01:31:37 +0000238static Int find_segment ( Addr a )
239{
240 Int i;
241 for (i = 0; i < segments_used; i++) {
242 if (compare_addr_with_seg(a, &segments[i]) == 0)
243 return i;
244 }
245 return -1;
246}
247
248
249/* Assumes that 'a' is not in any segment. Finds the index of the
250 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
251 which is in fact in a segment is a checked error.
252*/
253static Int find_segment_above_unmapped ( Addr a )
254{
255 Int i, r;
256 for (i = 0; i < segments_used; i++) {
257 r = compare_addr_with_seg(a, &segments[i]);
258 vg_assert(r != 0); /* 'a' should not be in any segment. */
259 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000260 continue;
sewardj548be6d2005-02-16 01:31:37 +0000261 vg_assert(r == -1);
262 break;
263 }
264
265 if (i == segments_used)
266 return -1; /* not found */
267 else
268 return i;
269}
270
271
272/* Assumes that 'a' is in some segment. Finds the next segment along,
273 or NULL if none. Passing 'a' which is in fact not in a segment is
274 a checked error.
275*/
276static Int find_segment_above_mapped ( Addr a )
277{
278 Int i, r;
279 for (i = 0; i < segments_used; i++) {
280 r = compare_addr_with_seg(a, &segments[i]);
281 if (r == 1)
282 continue; /* not yet there */
283 if (r == 0)
284 break; /* found it */
285 vg_assert(0);
286 /* we shouldn't get here -- r == -1 and so it means we went past
287 'a' without seeing it -- it is therefore unmapped. */
288 /*NOTREACHED*/
289 }
290
291 vg_assert(i < segments_used);
292 if (i == segments_used-1)
293 return -1; /* not found */
294 else
295 return i+1;
296}
297
298
299/* Shift segments[i .. segments_used-1] up by one. */
300static void make_space_at ( Int i )
301{
302 Int j;
303 vg_assert(i >= 0 && i <= segments_used);
304 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000305 if (segments_used+1 == VG_N_SEGMENTS) {
306 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000307 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000308 " VG_N_SEGMENTS is too small: "
309 "increase it and rebuild Valgrind.\n"
310 );
311 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000312 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000313 " giving up now.\n\n"
314 );
315 VG_(exit)(0);
316 }
sewardj548be6d2005-02-16 01:31:37 +0000317 vg_assert(segments_used+1 < VG_N_SEGMENTS);
318 for (j = segments_used; j > i; j--)
319 segments[j] = segments[j-1];
320 segments_used++;
321}
322
njnf6ec8ec2005-07-21 23:26:25 +0000323// Forward declaration
324static void dealloc_seg_memory(Segment *s);
sewardj79048ce2005-02-18 08:28:32 +0000325
sewardj548be6d2005-02-16 01:31:37 +0000326/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000327 segments_used.
328*/
sewardj548be6d2005-02-16 01:31:37 +0000329static void delete_segment_at ( Int i )
330{
331 Int j;
332 vg_assert(i >= 0 && i < segments_used);
njnf6ec8ec2005-07-21 23:26:25 +0000333 dealloc_seg_memory(&segments[i]);
334 for (j = i+1; j < segments_used; j++) {
335 segments[j-1] = segments[j];
336 }
sewardj548be6d2005-02-16 01:31:37 +0000337 segments_used--;
338 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
339}
340
341
342/* Fill the i'th record all with zeroes. */
343static void zeroise_segment ( Int i )
344{
345 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000346 segments[i].prot = 0;
347 segments[i].flags = 0;
348 segments[i].addr = 0;
349 segments[i].len = 0;
350 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000351 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000352 segments[i].fnIdx = -1;
353 segments[i].dev = 0;
354 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000355 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000356}
357
sewardj79048ce2005-02-18 08:28:32 +0000358
sewardj548be6d2005-02-16 01:31:37 +0000359/* Create a segment to contain 'a', and return its index. Or -1 if
360 this failed because some other segment already contains 'a'. If
361 successful, fill in the segment's .addr field with 'a' but leave
362 all other fields alone.
363*/
364static Int create_segment ( Addr a )
365{
366 Int i, r;
367 for (i = 0; i < segments_used; i++) {
368 r = compare_addr_with_seg( a, &segments[i] );
369 if (r == 1)
370 continue; /* seg[i] precedes a */
371 if (r == 0)
372 return -1; /* seg[i] contains a. Give up */
373 vg_assert(r == -1);
374 break;
375 }
376 /* a precedes seg[i]. Shift segs at i and above up one, and use
377 this slot. */
378 make_space_at(i);
379 zeroise_segment(i);
380 segments[i].addr = a;
381 return i;
382}
383
sewardj79048ce2005-02-18 08:28:32 +0000384
385/* Print out the segment array (debugging only!). Note, this calls
386 VG_(printf), and I'm not 100% clear that that wouldn't require
387 dynamic memory allocation and hence more segments to be allocated.
388*/
389static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000390{
sewardj79048ce2005-02-18 08:28:32 +0000391 Int i;
392 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
393 who, segments_used, segnames_used);
394 for (i = 0; i < segnames_used; i++) {
395 if (!segnames[i].inUse)
396 continue;
397 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
398 }
399 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000400 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000401 "%3d: %08p-%08p %7llu pr=0x%x fl=0x%04x d=0x%03x i=%-7d o=%-7lld (%d)\n",
sewardj548be6d2005-02-16 01:31:37 +0000402 i,
sewardj79048ce2005-02-18 08:28:32 +0000403 segments[i].addr, segments[i].addr + segments[i].len,
404 (ULong)segments[i].len, segments[i].prot,
405 segments[i].flags, segments[i].dev, segments[i].ino,
406 (Long)segments[i].offset,
407 segments[i].fnIdx);
408 }
409 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000410}
sewardj79048ce2005-02-18 08:28:32 +0000411
sewardj548be6d2005-02-16 01:31:37 +0000412
413/* Find the segment containing 'a' and split it into two pieces at
414 'a'. Does nothing if no segment contains 'a', or if the split
415 would cause either of the pieces to have zero size.
416
417 If 'a' is not found, or if no splitting happens, -1 is returned.
418
419 If a value 'r' other than -1 is returned, this is the index of the
420 higher-addressed segment resulting from the split, and the index of
421 the lower-addressed segment is r-1.
422*/
423static Int split_segment ( Addr a )
424{
425 Int r;
426 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000427 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000428 r = find_segment(a);
429 if (r == -1)
430 /* not found */
431 return -1;
432 if (segments[r].addr == a)
433 /* segment starts at 'a', so splitting it would create a
434 zero-sized segment */
435 return -1;
436
437 /* copy original; make adjustments. */
438 vg_assert(a > segments[r].addr);
439 delta = a - segments[r].addr;
440 make_space_at(r);
njnf6ec8ec2005-07-21 23:26:25 +0000441
sewardj548be6d2005-02-16 01:31:37 +0000442 segments[r] = segments[r+1];
443 segments[r].len = delta;
njnf6ec8ec2005-07-21 23:26:25 +0000444 if (segments[r].seginfo)
445 VG_(seginfo_incref)(segments[r].seginfo);
446
sewardj548be6d2005-02-16 01:31:37 +0000447 segments[r+1].len -= delta;
448 segments[r+1].addr += delta;
449 segments[r+1].offset += delta;
450 return r+1;
451}
452
sewardj79048ce2005-02-18 08:28:32 +0000453
454/* Return true if two segments are adjacent and mergable (s1 is
455 assumed to have a lower ->addr than s2) */
456static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
457{
458 if (s1->addr+s1->len != s2->addr)
459 return False;
460
461 if (s1->flags != s2->flags)
462 return False;
463
464 if (s1->prot != s2->prot)
465 return False;
466
njn36ef6ba2005-05-14 18:42:26 +0000467 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000468 return False;
469
470 if (s1->flags & SF_FILE){
471 if ((s1->offset + s1->len) != s2->offset)
472 return False;
473 if (s1->dev != s2->dev)
474 return False;
475 if (s1->ino != s2->ino)
476 return False;
477 if (s1->fnIdx != s2->fnIdx)
478 return False;
479 }
480
481 return True;
482}
483
484
485/* Clean up and sanity check the segment array:
486 - check segments are in ascending order
487 - check segments do not overlap
488 - check no segment has zero size
489 - merge adjacent where possible
490 - perform checks on the filename table, and reclaim dead entries
491*/
492static void preen_segments ( void )
493{
494 Int i, j, rd, wr;
495 Segment *s, *s1;
496 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
497 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
498
499 if (0) show_segments("before preen");
500
501 /* clear string table mark bits */
502 for (i = 0; i < segnames_used; i++)
503 segnames[i].mark = False;
504
505 /* check for non-zero size, and set mark bits for any used strings */
506 for (i = 0; i < segments_used; i++) {
507 vg_assert(segments[i].len > 0);
508 j = segments[i].fnIdx;
509 vg_assert(j >= -1 && j < segnames_used);
510 if (j >= 0) {
511 vg_assert(segnames[j].inUse);
512 segnames[j].mark = True;
513 }
514 }
515
516 /* check ascendingness and non-overlap */
517 for (i = 0; i < segments_used-1; i++) {
518 s = &segments[i];
519 s1 = &segments[i+1];
520 vg_assert(s->addr < s1->addr);
521 vg_assert(s->addr + s->len <= s1->addr);
522 }
523
524 /* merge */
525 if (segments_used < 1)
526 return;
527
528 wr = 1;
529 for (rd = 1; rd < segments_used; rd++) {
530 s = &segments[wr-1];
531 s1 = &segments[rd];
532 if (segments_are_mergeable(s,s1)) {
533 if (0)
534 VG_(printf)("merge %p-%p with %p-%p\n",
535 s->addr, s->addr+s->len,
536 s1->addr, s1->addr+s1->len);
537 s->len += s1->len;
njnf6ec8ec2005-07-21 23:26:25 +0000538
539 vg_assert(s->seginfo == s1->seginfo);
540 dealloc_seg_memory(s1);
541
sewardj79048ce2005-02-18 08:28:32 +0000542 continue;
543 }
544 if (wr < rd)
545 segments[wr] = segments[rd];
546 wr++;
547 }
548 vg_assert(wr >= 0 && wr <= segments_used);
549 segments_used = wr;
550
551 /* Free up any strings which are no longer referenced. */
552 for (i = 0; i < segnames_used; i++) {
553 if (segnames[i].mark == False) {
554 segnames[i].inUse = False;
555 segnames[i].fname[0] = 0;
556 }
557 }
558
559 if (0) show_segments("after preen");
560}
561
562
sewardj548be6d2005-02-16 01:31:37 +0000563/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000564/*--- Maintain an ordered list of all the client's mappings ---*/
565/*--------------------------------------------------------------*/
566
nethercote8991d5a2004-11-03 17:07:46 +0000567Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000568{
569 Addr se = s->addr+s->len;
570 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000571 vg_assert(pe >= p);
572
573 return (p >= s->addr && pe <= se);
574}
575
nethercote8991d5a2004-11-03 17:07:46 +0000576Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000577{
578 Addr se = s->addr+s->len;
579 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000580 vg_assert(pe >= p);
581
582 return (p < se && pe > s->addr);
583}
584
fitzhardinge98abfc72003-12-16 02:05:15 +0000585/* When freeing a Segment, also clean up every one else's ideas of
586 what was going on in that range of memory */
njnf6ec8ec2005-07-21 23:26:25 +0000587static void dealloc_seg_memory(Segment *s)
fitzhardinge98abfc72003-12-16 02:05:15 +0000588{
njn36ef6ba2005-05-14 18:42:26 +0000589 if (s->seginfo != NULL) {
590 VG_(seginfo_decref)(s->seginfo, s->addr);
591 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000592 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000593}
sewardj1024cf72005-02-28 14:39:21 +0000594
595/* Get rid of any translations arising from s. */
596/* Note, this is not really the job of the low level memory manager.
597 When it comes time to rewrite this subsystem, clean this up. */
598static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000599{
sewardj1024cf72005-02-28 14:39:21 +0000600 if (s->flags & SF_CODE) {
601 VG_(discard_translations)(s->addr, s->len);
602 if (0)
603 VG_(printf)("dumping translations in %p .. %p\n",
604 s->addr, s->addr+s->len);
605 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000606}
607
sewardj1024cf72005-02-28 14:39:21 +0000608
fitzhardinge98abfc72003-12-16 02:05:15 +0000609/* This unmaps all the segments in the range [addr, addr+len); any
610 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000611void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000612{
tomc2bf09c2005-07-29 18:33:19 +0000613 const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000614 Segment* s;
615 Addr end, s_end;
616 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000617 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000618
619 if (len == 0)
620 return;
621
njn13bfd852005-06-02 03:52:53 +0000622 len = VG_PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000623
fitzhardinge98abfc72003-12-16 02:05:15 +0000624 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000625 VG_(printf)("unmap_range(%p, %llu)\n", addr, (ULong)len);
sewardj79048ce2005-02-18 08:28:32 +0000626 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000627 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000628
629 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000630 vg_assert(VG_IS_PAGE_ALIGNED(addr));
631 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000632
sewardj548be6d2005-02-16 01:31:37 +0000633 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000634
635 /* do not delete .. even though it looks stupid */
636 vg_assert(i >= 0);
637
638 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000639 s = &segments[i];
640 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000641
sewardj548be6d2005-02-16 01:31:37 +0000642 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000643 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000644 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000645
fitzhardinge1a303042003-12-22 08:48:50 +0000646 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000647 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000648 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000649 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000650 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000651
652 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000653 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000654 addr < s_end &&
655 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000656 /* this segment's tail is truncated by [addr, addr+len)
657 -> truncate tail
658 */
sewardj1024cf72005-02-28 14:39:21 +0000659 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000660 s->len = addr - s->addr;
661
662 if (debug)
tom9be7c982005-04-25 16:55:44 +0000663 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000664 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000665 /* this segment's head is truncated by [addr, addr+len)
666 -> truncate head
667 */
sewardj548be6d2005-02-16 01:31:37 +0000668 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000669
670 if (debug)
tom9be7c982005-04-25 16:55:44 +0000671 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000672 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000673
sewardj1024cf72005-02-28 14:39:21 +0000674 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000675 s->addr += delta;
676 s->offset += delta;
677 s->len -= delta;
678
679 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000680 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000681 /* this segment is completely contained within [addr, addr+len)
682 -> delete segment
683 */
sewardj1024cf72005-02-28 14:39:21 +0000684 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000685 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000686 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000687
688 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000689 VG_(printf)(" case 3: seg %d deleted\n", i);
690 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000691 /* [addr, addr+len) is contained within a single segment
692 -> split segment into 3, delete middle portion
693 */
sewardj1024cf72005-02-28 14:39:21 +0000694 Int i_middle;
695 dump_translations_from(s);
696 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000697 vg_assert(i_middle != -1);
698 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000699 vg_assert(segments[i_middle].addr == addr);
700 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000701 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000702
703 if (debug)
704 VG_(printf)(" case 4: subrange %p-%p deleted\n",
705 addr, addr+len);
706 }
sewardj47c98a72005-03-12 20:36:15 +0000707
708 /* If we deleted this segment (or any above), those above will
709 have been moved down to fill in the hole in the segment
710 array. In order that we don't miss them, we have to
711 re-consider this slot number; hence the i--. */
712 if (deleted)
713 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000714 }
sewardj79048ce2005-02-18 08:28:32 +0000715 preen_segments();
716 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000717}
718
sewardj548be6d2005-02-16 01:31:37 +0000719
720/* Add a binding of [addr,addr+len) to
721 (prot,flags,dev,ino,off,filename) in the segment array.
722 Delete/truncate any previous mapping(s) covering that range.
723*/
724void
725VG_(map_file_segment)( Addr addr, SizeT len,
726 UInt prot, UInt flags,
727 UInt dev, UInt ino, ULong off,
728 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000729{
tomc2bf09c2005-07-29 18:33:19 +0000730 const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000731 Segment* s;
732 Int idx;
njn6081fce2005-06-25 19:45:34 +0000733 HChar* stage2_suffix1 = "lib/valgrind/stage2";
734 HChar* stage2_suffix2 = "coregrind/stage2";
735 Bool is_stage2 = False;
736
737 is_stage2 = is_stage2 || ( VG_(strstr)(filename, stage2_suffix1) != NULL );
738 is_stage2 = is_stage2 || ( VG_(strstr)(filename, stage2_suffix2) != NULL );
fitzhardinge98abfc72003-12-16 02:05:15 +0000739
740 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000741 VG_(printf)(
742 "\n"
tom9be7c982005-04-25 16:55:44 +0000743 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000744 " dev=0x%4x ino=%d off=%ld\n"
745 " filename='%s')\n",
746 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000747
sewardja8d8e232005-06-07 20:04:56 +0000748 if (0) show_segments("before map_file_segment");
749
fitzhardinge98abfc72003-12-16 02:05:15 +0000750 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000751 vg_assert(VG_IS_PAGE_ALIGNED(addr));
njn13bfd852005-06-02 03:52:53 +0000752 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000753
sewardj548be6d2005-02-16 01:31:37 +0000754 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
755 VG_(unmap_range)(addr, len);
756
757 /* and now install this one */
758 idx = create_segment(addr);
759 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
760 vg_assert(idx != -1);
761 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000762
sewardj79048ce2005-02-18 08:28:32 +0000763 s = &segments[idx];
764 vg_assert(s->addr == addr);
765 s->prot = prot;
766 s->flags = flags;
767 s->len = len;
768 s->offset = off;
769 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
770 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
771 s->dev = dev;
772 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000773 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000774
sewardj79048ce2005-02-18 08:28:32 +0000775 /* Clean up right now */
776 preen_segments();
777 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000778
njnf6ec8ec2005-07-21 23:26:25 +0000779 /* If this mapping is at the beginning of a file, isn't part of
fitzhardinge98abfc72003-12-16 02:05:15 +0000780 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000781 file, then try reading symbols from it.
sewardj78164b92005-07-09 10:36:25 +0000782
783 Getting this heuristic right is critical. On x86-linux,
784 objects are typically mapped twice:
785
786 1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
787 1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
788
789 whereas ppc32-linux mysteriously does this:
790
791 118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
792 118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
793 118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
794
795 The third mapping should not be considered to have executable code in.
796 Therefore a test which works for both is: r and x and NOT w. Reading
797 symbols from the rwx segment -- which overlaps the r-x segment in the
798 file -- causes the redirection mechanism to redirect to addresses in
799 that third segment, which is wrong and causes crashes.
sewardj79048ce2005-02-18 08:28:32 +0000800 */
njn36ef6ba2005-05-14 18:42:26 +0000801 if (s->seginfo == NULL
sewardja8d8e232005-06-07 20:04:56 +0000802 && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
803 || is_stage2
804 )
njn88c51482005-06-25 20:49:33 +0000805 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP
njn88c51482005-06-25 20:49:33 +0000806 ) {
sewardj78164b92005-07-09 10:36:25 +0000807 if (off == 0
808 && s->fnIdx != -1
809 /* r, x are set */
810 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
811 /* w is clear */
812 && (prot & VKI_PROT_WRITE) == 0
813 /* other checks .. */
814 && len >= VKI_PAGE_SIZE
815 && VG_(is_object_file)((void *)addr) ) {
njn88c51482005-06-25 20:49:33 +0000816 s->seginfo = VG_(read_seg_symbols)(s->addr, s->len, s->offset,
817 s->filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000818 }
njnf6ec8ec2005-07-21 23:26:25 +0000819 else if (flags & SF_MMAP)
820 {
821 const SegInfo *si;
822
823 /* Otherwise see if an existing SegInfo applies to this Segment */
824 for (si = VG_(next_seginfo)(NULL);
825 si != NULL;
826 si = VG_(next_seginfo)(si))
827 {
828 if (VG_(seg_overlaps)(s, VG_(seginfo_start)(si),
829 VG_(seginfo_size)(si)))
830 {
831 s->seginfo = (SegInfo *)si;
832 VG_(seginfo_incref)((SegInfo *)si);
833 }
834 }
835 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000836 }
837
838 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000839 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000840}
841
nethercote8b5f40c2004-11-02 13:29:50 +0000842void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000843 Int fd, ULong off, const Char *filename)
844{
njnf845f8f2005-06-23 02:26:47 +0000845 Char buf[VKI_PATH_MAX];
fitzhardinge98abfc72003-12-16 02:05:15 +0000846 struct vki_stat st;
fitzhardinge98abfc72003-12-16 02:05:15 +0000847
848 st.st_dev = 0;
849 st.st_ino = 0;
850
851 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000852 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000853
854 if (VG_(fstat)(fd, &st) < 0)
855 flags &= ~SF_FILE;
856 }
857
sewardj79048ce2005-02-18 08:28:32 +0000858 if ((flags & SF_FILE) && filename == NULL && fd != -1)
njnf845f8f2005-06-23 02:26:47 +0000859 if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX))
860 filename = buf;
fitzhardinge98abfc72003-12-16 02:05:15 +0000861
sewardj79048ce2005-02-18 08:28:32 +0000862 VG_(map_file_segment)(addr, len, prot, flags,
863 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000864}
865
nethercote8b5f40c2004-11-02 13:29:50 +0000866void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000867{
868 flags &= ~SF_FILE;
869
870 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
871}
872
873/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000874void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000875{
sewardj79048ce2005-02-18 08:28:32 +0000876 Int r;
tomc2bf09c2005-07-29 18:33:19 +0000877 const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000878
879 if (debug)
tom9be7c982005-04-25 16:55:44 +0000880 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000881
882 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000883
884 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000885 vg_assert(VG_IS_PAGE_ALIGNED(a));
njn13bfd852005-06-02 03:52:53 +0000886 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000887
sewardj79048ce2005-02-18 08:28:32 +0000888 split_segment(a);
889 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000890
sewardj548be6d2005-02-16 01:31:37 +0000891 r = find_segment(a);
892 vg_assert(r != -1);
893 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000894
895 preen_segments();
896
sewardje517b802005-02-16 01:58:51 +0000897 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000898}
899
sewardj79048ce2005-02-18 08:28:32 +0000900
sewardj548be6d2005-02-16 01:31:37 +0000901/* Try to find a map space for [addr,addr+len). If addr==0, it means
902 the caller is prepared to accept a space at any location; if not,
903 we will try for addr, but fail if we can't get it. This mimics
904 mmap fixed vs mmap not-fixed.
905*/
nethercote8b5f40c2004-11-02 13:29:50 +0000906Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000907{
tomc2bf09c2005-07-29 18:33:19 +0000908 const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000909 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000910 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000911 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
912 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000913 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
914 Int i, i_any, i_fixed, i_final;
915 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000916
sewardj548be6d2005-02-16 01:31:37 +0000917 Bool fixed;
918
sewardje517b802005-02-16 01:58:51 +0000919 if (debug) {
920 VG_(printf)("\n\n");
sewardja8d8e232005-06-07 20:04:56 +0000921 VG_(printf)("find_map_space(%p, %llu, %d) ...\n",
922 addr, (ULong)len, for_client);
sewardje517b802005-02-16 01:58:51 +0000923 }
924
925 if (0) show_segments("find_map_space: start");
926
sewardj548be6d2005-02-16 01:31:37 +0000927 if (addr == 0) {
928 fixed = False;
929 } else {
930 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000931 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000932 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000933 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000934 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000935
936 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000937 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
njn13bfd852005-06-02 03:52:53 +0000938 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000939
nethercote73b526f2004-10-31 18:48:21 +0000940 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000941
sewardj548be6d2005-02-16 01:31:37 +0000942 /* Scan the segment list, looking for a hole which satisfies the
943 requirements. At each point i we ask the question "can we use
944 the hole in between segments[i-1] and segments[i] ?" */
945 i_any = i_fixed = -1;
946 hstart_any = hstart_fixed = 0;
947
948 hole_start = hole_end = 0;
949
950 /* Iterate over all possible holes, generating them into
951 hole_start/hole_end. Filter out invalid ones. Then see if any
952 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
953 */
954 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
955 if (i == 0) {
956 hole_start = 0;
957 hole_end = segments[0].addr-1;
958 }
959 else {
960 vg_assert(segments_used > 0);
961 if (i == segments_used) {
962 hole_start = segments[i-1].addr + segments[i-1].len;
963 hole_end = ~(Addr)0;
964 } else {
965 hole_start = segments[i-1].addr + segments[i-1].len;
966 hole_end = segments[i].addr - 1;
967 }
968 }
969
970 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
971
972 /* ignore zero-sized holes */
973 if (hole_start == hole_end+1)
974 continue;
975
njnbe91aae2005-03-27 01:42:41 +0000976 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
977 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000978
979 /* ignore holes which fall outside the allowable area */
980 if (!(hole_start >= base && hole_end <= limit))
981 continue;
982
983 vg_assert(hole_end > hole_start);
984 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000985 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000986
987 if (hole_len >= len && i_any == -1) {
988 /* It will at least fit in this hole. */
989 i_any = i;
990 hstart_any = hole_start;
991 }
992
sewardjb5f6f512005-03-10 23:59:00 +0000993 if (fixed && hole_start <= addr
994 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000995 /* We were asked for a fixed mapping, and this hole works.
996 Bag it -- and stop searching as further searching is
997 pointless. */
998 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000999 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +00001000 break;
1001 }
1002 }
1003
1004 /* Summarise the final decision into i_final/hstart_final. */
1005 i_final = -1;
1006 hstart_final = 0;
1007
1008 if (fixed) {
1009 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +00001010 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +00001011 } else {
1012 i_final = i_any;
1013 hstart_final = hstart_any;
1014 }
1015
1016
1017 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +00001018 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +00001019 else
1020 ret = 0; /* not found */
1021
1022 if (debug)
sewardja8d8e232005-06-07 20:04:56 +00001023 VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n",
1024 addr, (ULong)len, for_client, ret);
sewardj548be6d2005-02-16 01:31:37 +00001025
sewardjb5f6f512005-03-10 23:59:00 +00001026 if (fixed) {
1027 vg_assert(ret == 0 || ret == addrOrig);
1028 }
1029
sewardj548be6d2005-02-16 01:31:37 +00001030 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +00001031}
1032
sewardj79048ce2005-02-18 08:28:32 +00001033
sewardjb5f6f512005-03-10 23:59:00 +00001034/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +00001035 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +00001036 mapping over any part of the address space which is not covered
1037 by an entry in the segment list.
1038
1039 This is designed for use around system calls which allocate
1040 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +00001041 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +00001042 address with VG_(find_map_space) and then adding a segment for
1043 it and padding the address space valgrind can ensure that the
1044 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +00001045void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001046{
sewardj394790d2005-03-17 02:14:44 +00001047 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001048 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001049
1050 Int i = 0;
1051 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001052
nethercote820bd8c2004-09-07 23:04:49 +00001053 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001054 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +00001055 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +00001056 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1057 -1, 0);
tom32327ec2005-07-19 07:37:51 +00001058 vg_assert(!ret.isError);
thughes9aaebc32004-07-15 23:13:37 +00001059 }
thughes9aaebc32004-07-15 23:13:37 +00001060 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001061 i++;
1062 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001063 }
1064
nethercote820bd8c2004-09-07 23:04:49 +00001065 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001066 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001067 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1068 -1, 0);
tom32327ec2005-07-19 07:37:51 +00001069 vg_assert(!ret.isError);
thughes9aaebc32004-07-15 23:13:37 +00001070 }
thughes9aaebc32004-07-15 23:13:37 +00001071}
1072
thughesc70b8c62004-07-16 23:07:58 +00001073/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001074 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001075void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001076{
sewardj394790d2005-03-17 02:14:44 +00001077 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001078 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001079
1080 Int i = 0;
1081 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001082
nethercote820bd8c2004-09-07 23:04:49 +00001083 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001084 if (addr < s->addr) {
njnb69f7c12005-06-24 22:17:38 +00001085 //ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
njnca6fef02004-11-29 16:49:18 +00001086 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001087 }
thughes9aaebc32004-07-15 23:13:37 +00001088 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001089 i++;
1090 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001091 }
1092
nethercote820bd8c2004-09-07 23:04:49 +00001093 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001094 ret = VG_(do_syscall2)(__NR_munmap, addr,
1095 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001096 }
thughes9aaebc32004-07-15 23:13:37 +00001097}
1098
sewardj548be6d2005-02-16 01:31:37 +00001099/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001100Segment *VG_(find_segment)(Addr a)
1101{
sewardj548be6d2005-02-16 01:31:37 +00001102 Int r = find_segment(a);
1103 if (0) show_segments("find_segment");
1104 if (r == -1) return NULL;
1105 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001106}
1107
sewardj548be6d2005-02-16 01:31:37 +00001108/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1109 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1110 a segment is a checked error.
1111*/
1112Segment *VG_(find_segment_above_unmapped)(Addr a)
1113{
1114 Int r = find_segment_above_unmapped(a);
1115 if (0) show_segments("find_segment_above_unmapped");
1116 if (r == -1) return NULL;
1117 return &segments[r];
1118}
1119
1120/* Assumes that 'a' is in some segment. Finds the next segment along,
1121 or NULL if none. Passing 'a' which is in fact not in a segment is
1122 a checked error.
1123*/
1124Segment *VG_(find_segment_above_mapped)(Addr a)
1125{
1126 Int r = find_segment_above_mapped(a);
1127 if (0) show_segments("find_segment_above_mapped");
1128 if (r == -1) return NULL;
1129 return &segments[r];
1130}
1131
1132
jsgf855d93d2003-10-13 22:26:55 +00001133/*
sewardjb5f6f512005-03-10 23:59:00 +00001134 Test if a piece of memory is addressable with at least the "prot"
1135 protection permissions by examining the underlying segments.
1136
1137 Really this is a very stupid algorithm and we could do much
1138 better by iterating through the segment array instead of through
1139 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001140 */
sewardjb5f6f512005-03-10 23:59:00 +00001141Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001142{
sewardjb5f6f512005-03-10 23:59:00 +00001143 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001144
sewardjb5f6f512005-03-10 23:59:00 +00001145 if ((p + size) < p)
1146 return False; /* reject wraparounds */
1147 if (size == 0)
1148 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001149
njn13bfd852005-06-02 03:52:53 +00001150 p = VG_PGROUNDDN(p);
1151 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001152 vg_assert(VG_IS_PAGE_ALIGNED(p));
1153 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001154
sewardjb5f6f512005-03-10 23:59:00 +00001155 for (; size > 0; size -= VKI_PAGE_SIZE) {
1156 seg = VG_(find_segment)(p);
1157 if (!seg)
1158 return False;
1159 if ((seg->prot & prot) != prot)
1160 return False;
1161 p += VKI_PAGE_SIZE;
1162 }
jsgf855d93d2003-10-13 22:26:55 +00001163
sewardjb5f6f512005-03-10 23:59:00 +00001164 return True;
jsgf855d93d2003-10-13 22:26:55 +00001165}
1166
sewardjb5f6f512005-03-10 23:59:00 +00001167
sewardjde4a1d02002-03-22 01:27:54 +00001168/*--------------------------------------------------------------------*/
njn9260c782005-06-19 21:57:54 +00001169/*--- Random function that doesn't really belong here ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001170/*--------------------------------------------------------------------*/
1171
njn86f12dc2005-03-14 01:16:05 +00001172/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001173 range, which isn't SF_CORE, a root.
1174*/
njn86f12dc2005-03-14 01:16:05 +00001175void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1176{
sewardj882af5f2005-03-16 12:27:53 +00001177 Int i;
1178 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001179 Segment *s;
1180
sewardj882af5f2005-03-16 12:27:53 +00001181 for (i = 0; i < segments_used; i++) {
1182 s = &segments[i];
njnf253dac2005-06-28 22:38:24 +00001183 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND|SF_CORE|SF_STACK);
tom5912dd72005-07-18 09:40:29 +00001184 if (flags != SF_MMAP && flags != SF_STACK && flags != (SF_MMAP|SF_STACK))
njn86f12dc2005-03-14 01:16:05 +00001185 continue;
sewardj882af5f2005-03-16 12:27:53 +00001186 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1187 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001188 continue;
1189 if (!VG_(is_client_addr)(s->addr) ||
njnf253dac2005-06-28 22:38:24 +00001190 !VG_(is_client_addr)(s->addr+s->len-1))
njn86f12dc2005-03-14 01:16:05 +00001191 continue;
1192
1193 (*add_rootrange)(s->addr, s->len);
1194 }
njn86f12dc2005-03-14 01:16:05 +00001195}
1196
1197
nethercote88a90162004-07-10 16:59:25 +00001198/*--------------------------------------------------------------------*/
1199/*--- Querying memory layout ---*/
1200/*--------------------------------------------------------------------*/
1201
fitzhardinge98abfc72003-12-16 02:05:15 +00001202Bool VG_(is_client_addr)(Addr a)
1203{
1204 return a >= VG_(client_base) && a < VG_(client_end);
1205}
1206
1207Bool VG_(is_shadow_addr)(Addr a)
1208{
1209 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1210}
1211
sewardjfa8202f2005-04-24 11:05:55 +00001212
nethercote88a90162004-07-10 16:59:25 +00001213/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001214/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001215/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001216
fitzhardinge98abfc72003-12-16 02:05:15 +00001217void *VG_(shadow_alloc)(UInt size)
1218{
1219 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001220 Addr try_here;
njne9befc62005-06-11 15:51:30 +00001221 SysRes r;
sewardj79048ce2005-02-18 08:28:32 +00001222
1223 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001224
1225 vg_assert(VG_(needs).shadow_memory);
fitzhardinge98abfc72003-12-16 02:05:15 +00001226
njn13bfd852005-06-02 03:52:53 +00001227 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001228
1229 if (shadow_alloc == 0)
1230 shadow_alloc = VG_(shadow_base);
1231
1232 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001233 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001234
sewardj79048ce2005-02-18 08:28:32 +00001235 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001236 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1237 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001238 vg_assert(size > 0);
1239
1240 if (0)
1241 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1242
1243 /* this is big-bang allocated, so we don't expect to find a listed
1244 segment for it. */
1245 /* This is really an absolute disgrace. Sometimes the big-bang
1246 mapping is in the list (due to re-reads of /proc/self/maps,
1247 presumably) and sometimes it isn't. */
1248#if 0
1249 r = find_segment(try_here);
1250 vg_assert(r == -1);
1251 r = find_segment(try_here+size-1);
1252 vg_assert(r == -1);
1253#endif
1254
1255 r = VG_(mprotect_native)( (void*)try_here,
1256 size, VKI_PROT_READ|VKI_PROT_WRITE );
1257
njne9befc62005-06-11 15:51:30 +00001258 if (r.isError)
sewardj79048ce2005-02-18 08:28:32 +00001259 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001260
1261 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001262 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001263
sewardj79048ce2005-02-18 08:28:32 +00001264 failed:
1265 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001266 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001267 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001268 size
sewardj79048ce2005-02-18 08:28:32 +00001269 );
1270 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001271}
1272
njne3f06352005-06-01 03:48:33 +00001273/*------------------------------------------------------------*/
1274/*--- pointercheck ---*/
1275/*------------------------------------------------------------*/
1276
njnaf839f52005-06-23 03:27:57 +00001277Bool VG_(setup_pointercheck)(Addr client_base, Addr client_end)
njne3f06352005-06-01 03:48:33 +00001278{
1279 vg_assert(0 != client_end);
1280#if defined(VGP_x86_linux)
1281 /* Client address space segment limit descriptor entry */
1282 #define POINTERCHECK_SEGIDX 1
1283
1284 vki_modify_ldt_t ldt = {
1285 POINTERCHECK_SEGIDX, // entry_number
1286 client_base, // base_addr
1287 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1288 1, // seg_32bit
1289 0, // contents: data, RW, non-expanding
1290 0, // ! read_exec_only
1291 1, // limit_in_pages
1292 0, // ! seg not present
1293 1, // useable
1294 };
sewardja8d8e232005-06-07 20:04:56 +00001295 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1296 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001297 VG_(message)(Vg_UserMsg,
1298 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001299 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001300 return False;
1301 } else {
1302 return True;
1303 }
1304#elif defined(VGP_amd64_linux)
1305 if (0)
1306 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1307 return True;
cerion85665ca2005-06-20 15:51:07 +00001308#elif defined(VGP_ppc32_linux)
1309 if (0)
1310 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1311 return True;
njne3f06352005-06-01 03:48:33 +00001312#else
1313# error Unknown architecture
1314#endif
1315}
1316
fitzhardinge98abfc72003-12-16 02:05:15 +00001317/*--------------------------------------------------------------------*/
njn945ed2e2005-06-24 03:28:30 +00001318/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001319/*--------------------------------------------------------------------*/