blob: 4bd4ce8d867337a68c3f6d2eea07ab7b646ae792 [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"
njn899ce732005-06-21 00:28:11 +000034#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
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)
njne9befc62005-06-11 15:51:30 +000039#include "pub_core_libcmman.h"
njn36a20fa2005-06-03 03:08:39 +000040#include "pub_core_libcprint.h"
njn9abd6082005-06-17 21:31:45 +000041#include "pub_core_syscall.h"
njn43b9a8a2005-05-10 04:37:01 +000042#include "pub_core_tooliface.h"
njn945ed2e2005-06-24 03:28:30 +000043#include "pub_core_transtab.h" // For VG_(discard_translations)
njn3c660b62005-05-13 22:18:47 +000044#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000045
sewardjde4a1d02002-03-22 01:27:54 +000046
sewardja4495682002-10-21 07:29:59 +000047/* Define to debug the memory-leak-detector. */
48/* #define VG_DEBUG_LEAKCHECK */
49
sewardje517b802005-02-16 01:58:51 +000050static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000051
52/*--------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +000053/*--- Basic globals about the address space. ---*/
54/*--------------------------------------------------------------*/
55
56/* Client address space, lowest to highest (see top of ume.c) */
57Addr VG_(client_base); /* client address space limits */
58Addr VG_(client_end);
59Addr VG_(client_mapbase);
njn04e16982005-05-31 00:23:43 +000060Addr VG_(clstk_base);
61Addr VG_(clstk_end);
rjwalsh0140af52005-06-04 20:42:33 +000062UWord VG_(clstk_id);
njn04e16982005-05-31 00:23:43 +000063
64Addr VG_(brk_base); /* start of brk */
65Addr VG_(brk_limit); /* current brk */
66
67Addr VG_(shadow_base); /* tool's shadow memory */
68Addr VG_(shadow_end);
69
70Addr VG_(valgrind_base); /* valgrind's address range */
71
72// Note that VG_(valgrind_last) names the last byte of the section, whereas
73// the VG_(*_end) vars name the byte one past the end of the section.
74Addr VG_(valgrind_last);
75
76/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000077/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000078/*--------------------------------------------------------------*/
79
sewardj79048ce2005-02-18 08:28:32 +000080/* Max number of segments we can track. */
81#define VG_N_SEGMENTS 1000
82
83/* Max number of segment file names we can track. */
84#define VG_N_SEGNAMES 200
85
86/* Max length of a segment file name. */
87#define VG_MAX_SEGNAMELEN 1000
88
89
90/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000091
92/* Array [0 .. segments_used-1] of all mappings. */
93/* Sorted by .addr field. */
94/* I: len may not be zero. */
95/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000096/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000097
98static Segment segments[VG_N_SEGMENTS];
99static Int segments_used = 0;
100
sewardj79048ce2005-02-18 08:28:32 +0000101typedef
102 struct {
103 Bool inUse;
104 Bool mark;
105 HChar fname[VG_MAX_SEGNAMELEN];
106 }
107 SegName;
108
109/* Filename table. _used is the high water mark; an entry is only
110 valid if its index >= 0, < _used, and its .inUse field == True.
111 The .mark field is used to garbage-collect dead entries.
112*/
113static SegName segnames[VG_N_SEGNAMES];
114static Int segnames_used = 0;
115
116
117/* ------ end of STATE for the address-space manager ------ */
118
119
120/* Searches the filename table to find an index for the given name.
121 If none is found, an index is allocated and the name stored. If no
122 space is available we just give up. If the string is too long to
123 store, return -1.
124*/
125static Int allocate_segname ( const HChar* name )
126{
127 Int i, j, len;
128
129 vg_assert(name);
130
131 if (0) VG_(printf)("alloc_segname %s\n", name);
132
133 len = VG_(strlen)(name);
134 if (len >= VG_MAX_SEGNAMELEN-1) {
135 return -1;
136 }
137
138 /* first see if we already have the name. */
139 for (i = 0; i < segnames_used; i++) {
140 if (!segnames[i].inUse)
141 continue;
142 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
143 return i;
144 }
145 }
146
147 /* no we don't. So look for a free slot. */
148 for (i = 0; i < segnames_used; i++)
149 if (!segnames[i].inUse)
150 break;
151
152 if (i == segnames_used) {
153 /* no free slots .. advance the high-water mark. */
154 if (segnames_used+1 < VG_N_SEGNAMES) {
155 i = segnames_used;
156 segnames_used++;
157 } else {
158 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000159 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000160 " VG_N_SEGNAMES is too small: "
161 "increase it and rebuild Valgrind.\n"
162 );
163 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000164 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000165 " giving up now.\n\n"
166 );
167 VG_(exit)(0);
168 }
169 }
170
171 /* copy it in */
172 segnames[i].inUse = True;
173 for (j = 0; j < len; j++)
174 segnames[i].fname[j] = name[j];
175 vg_assert(len < VG_MAX_SEGNAMELEN);
176 segnames[i].fname[len] = 0;
177 return i;
178}
179
sewardj548be6d2005-02-16 01:31:37 +0000180
181/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
182 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000183 seg.
184*/
sewardj548be6d2005-02-16 01:31:37 +0000185static Int compare_addr_with_seg ( Addr a, Segment* seg )
186{
187 if (a < seg->addr)
188 return -1;
189 if (a >= seg->addr + seg->len)
190 return 1;
191 return 0;
192}
193
sewardj79048ce2005-02-18 08:28:32 +0000194
sewardj548be6d2005-02-16 01:31:37 +0000195/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000196 none.
197*/
sewardj548be6d2005-02-16 01:31:37 +0000198static Int find_segment ( Addr a )
199{
200 Int i;
201 for (i = 0; i < segments_used; i++) {
202 if (compare_addr_with_seg(a, &segments[i]) == 0)
203 return i;
204 }
205 return -1;
206}
207
208
209/* Assumes that 'a' is not in any segment. Finds the index of the
210 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
211 which is in fact in a segment is a checked error.
212*/
213static Int find_segment_above_unmapped ( Addr a )
214{
215 Int i, r;
216 for (i = 0; i < segments_used; i++) {
217 r = compare_addr_with_seg(a, &segments[i]);
218 vg_assert(r != 0); /* 'a' should not be in any segment. */
219 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000220 continue;
sewardj548be6d2005-02-16 01:31:37 +0000221 vg_assert(r == -1);
222 break;
223 }
224
225 if (i == segments_used)
226 return -1; /* not found */
227 else
228 return i;
229}
230
231
232/* Assumes that 'a' is in some segment. Finds the next segment along,
233 or NULL if none. Passing 'a' which is in fact not in a segment is
234 a checked error.
235*/
236static Int find_segment_above_mapped ( Addr a )
237{
238 Int i, r;
239 for (i = 0; i < segments_used; i++) {
240 r = compare_addr_with_seg(a, &segments[i]);
241 if (r == 1)
242 continue; /* not yet there */
243 if (r == 0)
244 break; /* found it */
245 vg_assert(0);
246 /* we shouldn't get here -- r == -1 and so it means we went past
247 'a' without seeing it -- it is therefore unmapped. */
248 /*NOTREACHED*/
249 }
250
251 vg_assert(i < segments_used);
252 if (i == segments_used-1)
253 return -1; /* not found */
254 else
255 return i+1;
256}
257
258
259/* Shift segments[i .. segments_used-1] up by one. */
260static void make_space_at ( Int i )
261{
262 Int j;
263 vg_assert(i >= 0 && i <= segments_used);
264 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000265 if (segments_used+1 == VG_N_SEGMENTS) {
266 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000267 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000268 " VG_N_SEGMENTS is too small: "
269 "increase it and rebuild Valgrind.\n"
270 );
271 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000272 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000273 " giving up now.\n\n"
274 );
275 VG_(exit)(0);
276 }
sewardj548be6d2005-02-16 01:31:37 +0000277 vg_assert(segments_used+1 < VG_N_SEGMENTS);
278 for (j = segments_used; j > i; j--)
279 segments[j] = segments[j-1];
280 segments_used++;
281}
282
sewardj79048ce2005-02-18 08:28:32 +0000283
sewardj548be6d2005-02-16 01:31:37 +0000284/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000285 segments_used.
286*/
sewardj548be6d2005-02-16 01:31:37 +0000287static void delete_segment_at ( Int i )
288{
289 Int j;
290 vg_assert(i >= 0 && i < segments_used);
291 for (j = i+1; j < segments_used; j++)
292 segments[j-1] = segments[j];
293 segments_used--;
294 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
295}
296
297
298/* Fill the i'th record all with zeroes. */
299static void zeroise_segment ( Int i )
300{
301 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000302 segments[i].prot = 0;
303 segments[i].flags = 0;
304 segments[i].addr = 0;
305 segments[i].len = 0;
306 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000307 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000308 segments[i].fnIdx = -1;
309 segments[i].dev = 0;
310 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000311 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000312}
313
sewardj79048ce2005-02-18 08:28:32 +0000314
sewardj548be6d2005-02-16 01:31:37 +0000315/* Create a segment to contain 'a', and return its index. Or -1 if
316 this failed because some other segment already contains 'a'. If
317 successful, fill in the segment's .addr field with 'a' but leave
318 all other fields alone.
319*/
320static Int create_segment ( Addr a )
321{
322 Int i, r;
323 for (i = 0; i < segments_used; i++) {
324 r = compare_addr_with_seg( a, &segments[i] );
325 if (r == 1)
326 continue; /* seg[i] precedes a */
327 if (r == 0)
328 return -1; /* seg[i] contains a. Give up */
329 vg_assert(r == -1);
330 break;
331 }
332 /* a precedes seg[i]. Shift segs at i and above up one, and use
333 this slot. */
334 make_space_at(i);
335 zeroise_segment(i);
336 segments[i].addr = a;
337 return i;
338}
339
sewardj79048ce2005-02-18 08:28:32 +0000340
341/* Print out the segment array (debugging only!). Note, this calls
342 VG_(printf), and I'm not 100% clear that that wouldn't require
343 dynamic memory allocation and hence more segments to be allocated.
344*/
345static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000346{
sewardj79048ce2005-02-18 08:28:32 +0000347 Int i;
348 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
349 who, segments_used, segnames_used);
350 for (i = 0; i < segnames_used; i++) {
351 if (!segnames[i].inUse)
352 continue;
353 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
354 }
355 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000356 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000357 "%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 +0000358 i,
sewardj79048ce2005-02-18 08:28:32 +0000359 segments[i].addr, segments[i].addr + segments[i].len,
360 (ULong)segments[i].len, segments[i].prot,
361 segments[i].flags, segments[i].dev, segments[i].ino,
362 (Long)segments[i].offset,
363 segments[i].fnIdx);
364 }
365 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000366}
sewardj79048ce2005-02-18 08:28:32 +0000367
sewardj548be6d2005-02-16 01:31:37 +0000368
369/* Find the segment containing 'a' and split it into two pieces at
370 'a'. Does nothing if no segment contains 'a', or if the split
371 would cause either of the pieces to have zero size.
372
373 If 'a' is not found, or if no splitting happens, -1 is returned.
374
375 If a value 'r' other than -1 is returned, this is the index of the
376 higher-addressed segment resulting from the split, and the index of
377 the lower-addressed segment is r-1.
378*/
379static Int split_segment ( Addr a )
380{
381 Int r;
382 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000383 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000384 r = find_segment(a);
385 if (r == -1)
386 /* not found */
387 return -1;
388 if (segments[r].addr == a)
389 /* segment starts at 'a', so splitting it would create a
390 zero-sized segment */
391 return -1;
392
393 /* copy original; make adjustments. */
394 vg_assert(a > segments[r].addr);
395 delta = a - segments[r].addr;
396 make_space_at(r);
397 segments[r] = segments[r+1];
398 segments[r].len = delta;
399 segments[r+1].len -= delta;
400 segments[r+1].addr += delta;
401 segments[r+1].offset += delta;
402 return r+1;
403}
404
sewardj79048ce2005-02-18 08:28:32 +0000405
406/* Return true if two segments are adjacent and mergable (s1 is
407 assumed to have a lower ->addr than s2) */
408static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
409{
410 if (s1->addr+s1->len != s2->addr)
411 return False;
412
413 if (s1->flags != s2->flags)
414 return False;
415
416 if (s1->prot != s2->prot)
417 return False;
418
njn36ef6ba2005-05-14 18:42:26 +0000419 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000420 return False;
421
422 if (s1->flags & SF_FILE){
423 if ((s1->offset + s1->len) != s2->offset)
424 return False;
425 if (s1->dev != s2->dev)
426 return False;
427 if (s1->ino != s2->ino)
428 return False;
429 if (s1->fnIdx != s2->fnIdx)
430 return False;
431 }
432
433 return True;
434}
435
436
437/* Clean up and sanity check the segment array:
438 - check segments are in ascending order
439 - check segments do not overlap
440 - check no segment has zero size
441 - merge adjacent where possible
442 - perform checks on the filename table, and reclaim dead entries
443*/
444static void preen_segments ( void )
445{
446 Int i, j, rd, wr;
447 Segment *s, *s1;
448 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
449 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
450
451 if (0) show_segments("before preen");
452
453 /* clear string table mark bits */
454 for (i = 0; i < segnames_used; i++)
455 segnames[i].mark = False;
456
457 /* check for non-zero size, and set mark bits for any used strings */
458 for (i = 0; i < segments_used; i++) {
459 vg_assert(segments[i].len > 0);
460 j = segments[i].fnIdx;
461 vg_assert(j >= -1 && j < segnames_used);
462 if (j >= 0) {
463 vg_assert(segnames[j].inUse);
464 segnames[j].mark = True;
465 }
466 }
467
468 /* check ascendingness and non-overlap */
469 for (i = 0; i < segments_used-1; i++) {
470 s = &segments[i];
471 s1 = &segments[i+1];
472 vg_assert(s->addr < s1->addr);
473 vg_assert(s->addr + s->len <= s1->addr);
474 }
475
476 /* merge */
477 if (segments_used < 1)
478 return;
479
480 wr = 1;
481 for (rd = 1; rd < segments_used; rd++) {
482 s = &segments[wr-1];
483 s1 = &segments[rd];
484 if (segments_are_mergeable(s,s1)) {
485 if (0)
486 VG_(printf)("merge %p-%p with %p-%p\n",
487 s->addr, s->addr+s->len,
488 s1->addr, s1->addr+s1->len);
489 s->len += s1->len;
490 continue;
491 }
492 if (wr < rd)
493 segments[wr] = segments[rd];
494 wr++;
495 }
496 vg_assert(wr >= 0 && wr <= segments_used);
497 segments_used = wr;
498
499 /* Free up any strings which are no longer referenced. */
500 for (i = 0; i < segnames_used; i++) {
501 if (segnames[i].mark == False) {
502 segnames[i].inUse = False;
503 segnames[i].fname[0] = 0;
504 }
505 }
506
507 if (0) show_segments("after preen");
508}
509
510
sewardj548be6d2005-02-16 01:31:37 +0000511/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000512/*--- Maintain an ordered list of all the client's mappings ---*/
513/*--------------------------------------------------------------*/
514
nethercote8991d5a2004-11-03 17:07:46 +0000515Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000516{
517 Addr se = s->addr+s->len;
518 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000519 vg_assert(pe >= p);
520
521 return (p >= s->addr && pe <= se);
522}
523
nethercote8991d5a2004-11-03 17:07:46 +0000524Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000525{
526 Addr se = s->addr+s->len;
527 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000528 vg_assert(pe >= p);
529
530 return (p < se && pe > s->addr);
531}
532
sewardj1024cf72005-02-28 14:39:21 +0000533#if 0
534/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000535/* Prepare a Segment structure for recycling by freeing everything
536 hanging off it. */
537static void recycleseg(Segment *s)
538{
539 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000540 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000541
542 if (s->filename != NULL)
543 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
544
545 /* keep the SegInfo, if any - it probably still applies */
546}
547
548/* When freeing a Segment, also clean up every one else's ideas of
549 what was going on in that range of memory */
550static void freeseg(Segment *s)
551{
552 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000553 if (s->seginfo != NULL) {
554 VG_(seginfo_decref)(s->seginfo, s->addr);
555 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000556 }
557
558 VG_(SkipNode_Free)(&sk_segments, s);
559}
sewardj1024cf72005-02-28 14:39:21 +0000560#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000561
sewardj1024cf72005-02-28 14:39:21 +0000562
563/* Get rid of any translations arising from s. */
564/* Note, this is not really the job of the low level memory manager.
565 When it comes time to rewrite this subsystem, clean this up. */
566static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000567{
sewardj1024cf72005-02-28 14:39:21 +0000568 if (s->flags & SF_CODE) {
569 VG_(discard_translations)(s->addr, s->len);
570 if (0)
571 VG_(printf)("dumping translations in %p .. %p\n",
572 s->addr, s->addr+s->len);
573 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000574}
575
sewardj1024cf72005-02-28 14:39:21 +0000576
fitzhardinge98abfc72003-12-16 02:05:15 +0000577/* This unmaps all the segments in the range [addr, addr+len); any
578 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000579void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000580{
fitzhardingee3632c62003-12-22 10:58:06 +0000581 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000582 Segment* s;
583 Addr end, s_end;
584 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000585 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000586
587 if (len == 0)
588 return;
589
njn13bfd852005-06-02 03:52:53 +0000590 len = VG_PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000591
fitzhardinge98abfc72003-12-16 02:05:15 +0000592 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000593 VG_(printf)("unmap_range(%p, %llu)\n", addr, (ULong)len);
sewardj79048ce2005-02-18 08:28:32 +0000594 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000595 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000596
597 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000598 vg_assert(VG_IS_PAGE_ALIGNED(addr));
599 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000600
sewardj548be6d2005-02-16 01:31:37 +0000601 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000602
603 /* do not delete .. even though it looks stupid */
604 vg_assert(i >= 0);
605
606 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000607 s = &segments[i];
608 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000609
sewardj548be6d2005-02-16 01:31:37 +0000610 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000611 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000612 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000613
fitzhardinge1a303042003-12-22 08:48:50 +0000614 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000615 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000616 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000617 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000618 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000619
620 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000621 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000622 addr < s_end &&
623 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000624 /* this segment's tail is truncated by [addr, addr+len)
625 -> truncate tail
626 */
sewardj1024cf72005-02-28 14:39:21 +0000627 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000628 s->len = addr - s->addr;
629
630 if (debug)
tom9be7c982005-04-25 16:55:44 +0000631 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000632 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000633 /* this segment's head is truncated by [addr, addr+len)
634 -> truncate head
635 */
sewardj548be6d2005-02-16 01:31:37 +0000636 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000637
638 if (debug)
tom9be7c982005-04-25 16:55:44 +0000639 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000640 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000641
sewardj1024cf72005-02-28 14:39:21 +0000642 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000643 s->addr += delta;
644 s->offset += delta;
645 s->len -= delta;
646
647 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000648 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000649 /* this segment is completely contained within [addr, addr+len)
650 -> delete segment
651 */
sewardj1024cf72005-02-28 14:39:21 +0000652 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000653 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000654 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000655
656 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000657 VG_(printf)(" case 3: seg %d deleted\n", i);
658 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000659 /* [addr, addr+len) is contained within a single segment
660 -> split segment into 3, delete middle portion
661 */
sewardj1024cf72005-02-28 14:39:21 +0000662 Int i_middle;
663 dump_translations_from(s);
664 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000665 vg_assert(i_middle != -1);
666 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000667 vg_assert(segments[i_middle].addr == addr);
668 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000669 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000670
671 if (debug)
672 VG_(printf)(" case 4: subrange %p-%p deleted\n",
673 addr, addr+len);
674 }
sewardj47c98a72005-03-12 20:36:15 +0000675
676 /* If we deleted this segment (or any above), those above will
677 have been moved down to fill in the hole in the segment
678 array. In order that we don't miss them, we have to
679 re-consider this slot number; hence the i--. */
680 if (deleted)
681 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000682 }
sewardj79048ce2005-02-18 08:28:32 +0000683 preen_segments();
684 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000685}
686
sewardj548be6d2005-02-16 01:31:37 +0000687
688/* Add a binding of [addr,addr+len) to
689 (prot,flags,dev,ino,off,filename) in the segment array.
690 Delete/truncate any previous mapping(s) covering that range.
691*/
692void
693VG_(map_file_segment)( Addr addr, SizeT len,
694 UInt prot, UInt flags,
695 UInt dev, UInt ino, ULong off,
696 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000697{
fitzhardinge98abfc72003-12-16 02:05:15 +0000698 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000699 Segment* s;
700 Int idx;
sewardja8d8e232005-06-07 20:04:56 +0000701 HChar* stage2_suffix = "lib/valgrind/stage2";
702 Bool is_stage2 = VG_(strstr)(filename, stage2_suffix) != NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000703
704 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000705 VG_(printf)(
706 "\n"
tom9be7c982005-04-25 16:55:44 +0000707 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000708 " dev=0x%4x ino=%d off=%ld\n"
709 " filename='%s')\n",
710 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000711
sewardja8d8e232005-06-07 20:04:56 +0000712 if (0) show_segments("before map_file_segment");
713
fitzhardinge98abfc72003-12-16 02:05:15 +0000714 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000715 vg_assert(VG_IS_PAGE_ALIGNED(addr));
njn13bfd852005-06-02 03:52:53 +0000716 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000717
sewardj548be6d2005-02-16 01:31:37 +0000718 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
719 VG_(unmap_range)(addr, len);
720
721 /* and now install this one */
722 idx = create_segment(addr);
723 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
724 vg_assert(idx != -1);
725 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000726
sewardj79048ce2005-02-18 08:28:32 +0000727 s = &segments[idx];
728 vg_assert(s->addr == addr);
729 s->prot = prot;
730 s->flags = flags;
731 s->len = len;
732 s->offset = off;
733 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
734 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
735 s->dev = dev;
736 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000737 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000738
sewardj79048ce2005-02-18 08:28:32 +0000739 /* Clean up right now */
740 preen_segments();
741 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000742
743 /* If this mapping is of the beginning of a file, isn't part of
744 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000745 file, then try reading symbols from it.
746 */
njn36ef6ba2005-05-14 18:42:26 +0000747 if (s->seginfo == NULL
sewardja8d8e232005-06-07 20:04:56 +0000748 && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
749 || is_stage2
750 )
sewardj79048ce2005-02-18 08:28:32 +0000751 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
752 if (off == 0
753 && s->fnIdx != -1
754 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
755 && len >= VKI_PAGE_SIZE
756 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000757 s->seginfo = VG_(read_seg_symbols)(s);
758 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000759 s->flags |= SF_DYNLIB;
760 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000761 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000762#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000763 const SegInfo *info;
764
njn36ef6ba2005-05-14 18:42:26 +0000765 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000766 for(info = VG_(next_seginfo)(NULL);
767 info != NULL;
768 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000769 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
770 {
njn36ef6ba2005-05-14 18:42:26 +0000771 s->seginfo = (SegInfo *)info;
772 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000773 }
774 }
sewardj79048ce2005-02-18 08:28:32 +0000775#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000776 }
777 }
778
779 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000780 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000781}
782
nethercote8b5f40c2004-11-02 13:29:50 +0000783void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000784 Int fd, ULong off, const Char *filename)
785{
njnf845f8f2005-06-23 02:26:47 +0000786 Char buf[VKI_PATH_MAX];
fitzhardinge98abfc72003-12-16 02:05:15 +0000787 struct vki_stat st;
fitzhardinge98abfc72003-12-16 02:05:15 +0000788
789 st.st_dev = 0;
790 st.st_ino = 0;
791
792 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000793 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000794
795 if (VG_(fstat)(fd, &st) < 0)
796 flags &= ~SF_FILE;
797 }
798
sewardj79048ce2005-02-18 08:28:32 +0000799 if ((flags & SF_FILE) && filename == NULL && fd != -1)
njnf845f8f2005-06-23 02:26:47 +0000800 if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX))
801 filename = buf;
fitzhardinge98abfc72003-12-16 02:05:15 +0000802
sewardj79048ce2005-02-18 08:28:32 +0000803 VG_(map_file_segment)(addr, len, prot, flags,
804 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000805}
806
nethercote8b5f40c2004-11-02 13:29:50 +0000807void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000808{
809 flags &= ~SF_FILE;
810
811 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
812}
813
814/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000815void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000816{
sewardj79048ce2005-02-18 08:28:32 +0000817 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000818 static const Bool debug = False || mem_debug;
819
820 if (debug)
tom9be7c982005-04-25 16:55:44 +0000821 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000822
823 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000824
825 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000826 vg_assert(VG_IS_PAGE_ALIGNED(a));
njn13bfd852005-06-02 03:52:53 +0000827 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000828
sewardj79048ce2005-02-18 08:28:32 +0000829 split_segment(a);
830 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000831
sewardj548be6d2005-02-16 01:31:37 +0000832 r = find_segment(a);
833 vg_assert(r != -1);
834 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000835
836 preen_segments();
837
sewardje517b802005-02-16 01:58:51 +0000838 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000839}
840
sewardj79048ce2005-02-18 08:28:32 +0000841
sewardj548be6d2005-02-16 01:31:37 +0000842/* Try to find a map space for [addr,addr+len). If addr==0, it means
843 the caller is prepared to accept a space at any location; if not,
844 we will try for addr, but fail if we can't get it. This mimics
845 mmap fixed vs mmap not-fixed.
846*/
nethercote8b5f40c2004-11-02 13:29:50 +0000847Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000848{
fitzhardingee3632c62003-12-22 10:58:06 +0000849 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000850 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000851 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000852 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
853 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000854 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
855 Int i, i_any, i_fixed, i_final;
856 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000857
sewardj548be6d2005-02-16 01:31:37 +0000858 Bool fixed;
859
sewardje517b802005-02-16 01:58:51 +0000860 if (debug) {
861 VG_(printf)("\n\n");
sewardja8d8e232005-06-07 20:04:56 +0000862 VG_(printf)("find_map_space(%p, %llu, %d) ...\n",
863 addr, (ULong)len, for_client);
sewardje517b802005-02-16 01:58:51 +0000864 }
865
866 if (0) show_segments("find_map_space: start");
867
sewardj548be6d2005-02-16 01:31:37 +0000868 if (addr == 0) {
869 fixed = False;
870 } else {
871 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000872 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000873 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000874 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000875 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000876
877 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000878 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
njn13bfd852005-06-02 03:52:53 +0000879 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000880
nethercote73b526f2004-10-31 18:48:21 +0000881 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000882
sewardj548be6d2005-02-16 01:31:37 +0000883 /* Scan the segment list, looking for a hole which satisfies the
884 requirements. At each point i we ask the question "can we use
885 the hole in between segments[i-1] and segments[i] ?" */
886 i_any = i_fixed = -1;
887 hstart_any = hstart_fixed = 0;
888
889 hole_start = hole_end = 0;
890
891 /* Iterate over all possible holes, generating them into
892 hole_start/hole_end. Filter out invalid ones. Then see if any
893 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
894 */
895 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
896 if (i == 0) {
897 hole_start = 0;
898 hole_end = segments[0].addr-1;
899 }
900 else {
901 vg_assert(segments_used > 0);
902 if (i == segments_used) {
903 hole_start = segments[i-1].addr + segments[i-1].len;
904 hole_end = ~(Addr)0;
905 } else {
906 hole_start = segments[i-1].addr + segments[i-1].len;
907 hole_end = segments[i].addr - 1;
908 }
909 }
910
911 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
912
913 /* ignore zero-sized holes */
914 if (hole_start == hole_end+1)
915 continue;
916
njnbe91aae2005-03-27 01:42:41 +0000917 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
918 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000919
920 /* ignore holes which fall outside the allowable area */
921 if (!(hole_start >= base && hole_end <= limit))
922 continue;
923
924 vg_assert(hole_end > hole_start);
925 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000926 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000927
928 if (hole_len >= len && i_any == -1) {
929 /* It will at least fit in this hole. */
930 i_any = i;
931 hstart_any = hole_start;
932 }
933
sewardjb5f6f512005-03-10 23:59:00 +0000934 if (fixed && hole_start <= addr
935 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000936 /* We were asked for a fixed mapping, and this hole works.
937 Bag it -- and stop searching as further searching is
938 pointless. */
939 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000940 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000941 break;
942 }
943 }
944
945 /* Summarise the final decision into i_final/hstart_final. */
946 i_final = -1;
947 hstart_final = 0;
948
949 if (fixed) {
950 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000951 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000952 } else {
953 i_final = i_any;
954 hstart_final = hstart_any;
955 }
956
957
958 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000959 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000960 else
961 ret = 0; /* not found */
962
963 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000964 VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n",
965 addr, (ULong)len, for_client, ret);
sewardj548be6d2005-02-16 01:31:37 +0000966
sewardjb5f6f512005-03-10 23:59:00 +0000967 if (fixed) {
968 vg_assert(ret == 0 || ret == addrOrig);
969 }
970
sewardj548be6d2005-02-16 01:31:37 +0000971 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000972}
973
sewardj79048ce2005-02-18 08:28:32 +0000974
sewardjb5f6f512005-03-10 23:59:00 +0000975/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000976 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000977 mapping over any part of the address space which is not covered
978 by an entry in the segment list.
979
980 This is designed for use around system calls which allocate
981 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000982 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000983 address with VG_(find_map_space) and then adding a segment for
984 it and padding the address space valgrind can ensure that the
985 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000986void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000987{
sewardj394790d2005-03-17 02:14:44 +0000988 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +0000989 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +0000990
991 Int i = 0;
992 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000993
nethercote820bd8c2004-09-07 23:04:49 +0000994 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000995 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +0000996 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +0000997 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
998 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000999 }
thughes9aaebc32004-07-15 23:13:37 +00001000 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001001 i++;
1002 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001003 }
1004
nethercote820bd8c2004-09-07 23:04:49 +00001005 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001006 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001007 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1008 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001009 }
thughes9aaebc32004-07-15 23:13:37 +00001010}
1011
thughesc70b8c62004-07-16 23:07:58 +00001012/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001013 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001014void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001015{
sewardj394790d2005-03-17 02:14:44 +00001016 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001017 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001018
1019 Int i = 0;
1020 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001021
nethercote820bd8c2004-09-07 23:04:49 +00001022 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001023 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +00001024 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001025 }
thughes9aaebc32004-07-15 23:13:37 +00001026 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001027 i++;
1028 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001029 }
1030
nethercote820bd8c2004-09-07 23:04:49 +00001031 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001032 ret = VG_(do_syscall2)(__NR_munmap, addr,
1033 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001034 }
thughes9aaebc32004-07-15 23:13:37 +00001035}
1036
sewardj548be6d2005-02-16 01:31:37 +00001037/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001038Segment *VG_(find_segment)(Addr a)
1039{
sewardj548be6d2005-02-16 01:31:37 +00001040 Int r = find_segment(a);
1041 if (0) show_segments("find_segment");
1042 if (r == -1) return NULL;
1043 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001044}
1045
sewardj548be6d2005-02-16 01:31:37 +00001046/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1047 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1048 a segment is a checked error.
1049*/
1050Segment *VG_(find_segment_above_unmapped)(Addr a)
1051{
1052 Int r = find_segment_above_unmapped(a);
1053 if (0) show_segments("find_segment_above_unmapped");
1054 if (r == -1) return NULL;
1055 return &segments[r];
1056}
1057
1058/* Assumes that 'a' is in some segment. Finds the next segment along,
1059 or NULL if none. Passing 'a' which is in fact not in a segment is
1060 a checked error.
1061*/
1062Segment *VG_(find_segment_above_mapped)(Addr a)
1063{
1064 Int r = find_segment_above_mapped(a);
1065 if (0) show_segments("find_segment_above_mapped");
1066 if (r == -1) return NULL;
1067 return &segments[r];
1068}
1069
1070
jsgf855d93d2003-10-13 22:26:55 +00001071/*
sewardjb5f6f512005-03-10 23:59:00 +00001072 Test if a piece of memory is addressable with at least the "prot"
1073 protection permissions by examining the underlying segments.
1074
1075 Really this is a very stupid algorithm and we could do much
1076 better by iterating through the segment array instead of through
1077 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001078 */
sewardjb5f6f512005-03-10 23:59:00 +00001079Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001080{
sewardjb5f6f512005-03-10 23:59:00 +00001081 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001082
sewardjb5f6f512005-03-10 23:59:00 +00001083 if ((p + size) < p)
1084 return False; /* reject wraparounds */
1085 if (size == 0)
1086 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001087
njn13bfd852005-06-02 03:52:53 +00001088 p = VG_PGROUNDDN(p);
1089 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001090 vg_assert(VG_IS_PAGE_ALIGNED(p));
1091 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001092
sewardjb5f6f512005-03-10 23:59:00 +00001093 for (; size > 0; size -= VKI_PAGE_SIZE) {
1094 seg = VG_(find_segment)(p);
1095 if (!seg)
1096 return False;
1097 if ((seg->prot & prot) != prot)
1098 return False;
1099 p += VKI_PAGE_SIZE;
1100 }
jsgf855d93d2003-10-13 22:26:55 +00001101
sewardjb5f6f512005-03-10 23:59:00 +00001102 return True;
jsgf855d93d2003-10-13 22:26:55 +00001103}
1104
sewardjb5f6f512005-03-10 23:59:00 +00001105
sewardjde4a1d02002-03-22 01:27:54 +00001106/*--------------------------------------------------------------------*/
njn9260c782005-06-19 21:57:54 +00001107/*--- Random function that doesn't really belong here ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001108/*--------------------------------------------------------------------*/
1109
njn86f12dc2005-03-14 01:16:05 +00001110/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001111 range, which isn't SF_CORE, a root.
1112*/
njn86f12dc2005-03-14 01:16:05 +00001113void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1114{
sewardj882af5f2005-03-16 12:27:53 +00001115 Int i;
1116 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001117 Segment *s;
1118
sewardj882af5f2005-03-16 12:27:53 +00001119 for (i = 0; i < segments_used; i++) {
1120 s = &segments[i];
1121 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1122 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001123 if (flags != SF_MMAP && flags != SF_STACK)
1124 continue;
sewardj882af5f2005-03-16 12:27:53 +00001125 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1126 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001127 continue;
1128 if (!VG_(is_client_addr)(s->addr) ||
1129 !VG_(is_client_addr)(s->addr+s->len))
1130 continue;
1131
1132 (*add_rootrange)(s->addr, s->len);
1133 }
njn86f12dc2005-03-14 01:16:05 +00001134}
1135
1136
nethercote88a90162004-07-10 16:59:25 +00001137/*--------------------------------------------------------------------*/
1138/*--- Querying memory layout ---*/
1139/*--------------------------------------------------------------------*/
1140
fitzhardinge98abfc72003-12-16 02:05:15 +00001141Bool VG_(is_client_addr)(Addr a)
1142{
1143 return a >= VG_(client_base) && a < VG_(client_end);
1144}
1145
1146Bool VG_(is_shadow_addr)(Addr a)
1147{
1148 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1149}
1150
sewardjfa8202f2005-04-24 11:05:55 +00001151
nethercote88a90162004-07-10 16:59:25 +00001152/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001153/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001154/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001155
1156void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1157{
sewardj548be6d2005-02-16 01:31:37 +00001158vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001159 if (0)
1160 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1161
1162 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001163 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001164
njn13bfd852005-06-02 03:52:53 +00001165 sz = VG_PGROUNDUP(p+sz) - VG_PGROUNDDN(p);
1166 p = VG_PGROUNDDN(p);
fitzhardinge98abfc72003-12-16 02:05:15 +00001167
1168 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1169
1170 if (call_init)
1171 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001172 /* ask the tool to initialize each page */
njn13bfd852005-06-02 03:52:53 +00001173 VG_TRACK( init_shadow_page, VG_PGROUNDDN(p) );
fitzhardinge98abfc72003-12-16 02:05:15 +00001174
nethercote73b526f2004-10-31 18:48:21 +00001175 p += VKI_PAGE_SIZE;
1176 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001177 }
1178}
1179
1180void *VG_(shadow_alloc)(UInt size)
1181{
1182 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001183 Addr try_here;
njne9befc62005-06-11 15:51:30 +00001184 SysRes r;
sewardj79048ce2005-02-18 08:28:32 +00001185
1186 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001187
1188 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001189 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001190
njn13bfd852005-06-02 03:52:53 +00001191 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001192
1193 if (shadow_alloc == 0)
1194 shadow_alloc = VG_(shadow_base);
1195
1196 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001197 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001198
sewardj79048ce2005-02-18 08:28:32 +00001199 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001200 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1201 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001202 vg_assert(size > 0);
1203
1204 if (0)
1205 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1206
1207 /* this is big-bang allocated, so we don't expect to find a listed
1208 segment for it. */
1209 /* This is really an absolute disgrace. Sometimes the big-bang
1210 mapping is in the list (due to re-reads of /proc/self/maps,
1211 presumably) and sometimes it isn't. */
1212#if 0
1213 r = find_segment(try_here);
1214 vg_assert(r == -1);
1215 r = find_segment(try_here+size-1);
1216 vg_assert(r == -1);
1217#endif
1218
1219 r = VG_(mprotect_native)( (void*)try_here,
1220 size, VKI_PROT_READ|VKI_PROT_WRITE );
1221
njne9befc62005-06-11 15:51:30 +00001222 if (r.isError)
sewardj79048ce2005-02-18 08:28:32 +00001223 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001224
1225 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001226 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001227
sewardj79048ce2005-02-18 08:28:32 +00001228 failed:
1229 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001230 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001231 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001232 size
sewardj79048ce2005-02-18 08:28:32 +00001233 );
1234 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001235}
1236
njne3f06352005-06-01 03:48:33 +00001237/*------------------------------------------------------------*/
1238/*--- pointercheck ---*/
1239/*------------------------------------------------------------*/
1240
njnaf839f52005-06-23 03:27:57 +00001241Bool VG_(setup_pointercheck)(Addr client_base, Addr client_end)
njne3f06352005-06-01 03:48:33 +00001242{
1243 vg_assert(0 != client_end);
1244#if defined(VGP_x86_linux)
1245 /* Client address space segment limit descriptor entry */
1246 #define POINTERCHECK_SEGIDX 1
1247
1248 vki_modify_ldt_t ldt = {
1249 POINTERCHECK_SEGIDX, // entry_number
1250 client_base, // base_addr
1251 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1252 1, // seg_32bit
1253 0, // contents: data, RW, non-expanding
1254 0, // ! read_exec_only
1255 1, // limit_in_pages
1256 0, // ! seg not present
1257 1, // useable
1258 };
sewardja8d8e232005-06-07 20:04:56 +00001259 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1260 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001261 VG_(message)(Vg_UserMsg,
1262 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001263 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001264 return False;
1265 } else {
1266 return True;
1267 }
1268#elif defined(VGP_amd64_linux)
1269 if (0)
1270 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1271 return True;
cerion85665ca2005-06-20 15:51:07 +00001272#elif defined(VGP_ppc32_linux)
1273 if (0)
1274 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1275 return True;
njne3f06352005-06-01 03:48:33 +00001276#else
1277# error Unknown architecture
1278#endif
1279}
1280
fitzhardinge98abfc72003-12-16 02:05:15 +00001281/*--------------------------------------------------------------------*/
njn945ed2e2005-06-24 03:28:30 +00001282/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001283/*--------------------------------------------------------------------*/