blob: 4e609e02c1733eff45e5eb8cbccb401870909f08 [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 ---*/
5/*--- 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
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
sewardj55f9d1a2005-04-25 11:11:44 +000034#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000035#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000036#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000037#include "pub_core_transtab.h"
njn3c660b62005-05-13 22:18:47 +000038#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000039
sewardjde4a1d02002-03-22 01:27:54 +000040
sewardja4495682002-10-21 07:29:59 +000041/* Define to debug the memory-leak-detector. */
42/* #define VG_DEBUG_LEAKCHECK */
43
sewardje517b802005-02-16 01:58:51 +000044static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000045
46/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000047/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000048/*--------------------------------------------------------------*/
49
sewardj79048ce2005-02-18 08:28:32 +000050/* Max number of segments we can track. */
51#define VG_N_SEGMENTS 1000
52
53/* Max number of segment file names we can track. */
54#define VG_N_SEGNAMES 200
55
56/* Max length of a segment file name. */
57#define VG_MAX_SEGNAMELEN 1000
58
59
60/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000061
62/* Array [0 .. segments_used-1] of all mappings. */
63/* Sorted by .addr field. */
64/* I: len may not be zero. */
65/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000066/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000067
68static Segment segments[VG_N_SEGMENTS];
69static Int segments_used = 0;
70
sewardj79048ce2005-02-18 08:28:32 +000071typedef
72 struct {
73 Bool inUse;
74 Bool mark;
75 HChar fname[VG_MAX_SEGNAMELEN];
76 }
77 SegName;
78
79/* Filename table. _used is the high water mark; an entry is only
80 valid if its index >= 0, < _used, and its .inUse field == True.
81 The .mark field is used to garbage-collect dead entries.
82*/
83static SegName segnames[VG_N_SEGNAMES];
84static Int segnames_used = 0;
85
86
87/* ------ end of STATE for the address-space manager ------ */
88
89
90/* Searches the filename table to find an index for the given name.
91 If none is found, an index is allocated and the name stored. If no
92 space is available we just give up. If the string is too long to
93 store, return -1.
94*/
95static Int allocate_segname ( const HChar* name )
96{
97 Int i, j, len;
98
99 vg_assert(name);
100
101 if (0) VG_(printf)("alloc_segname %s\n", name);
102
103 len = VG_(strlen)(name);
104 if (len >= VG_MAX_SEGNAMELEN-1) {
105 return -1;
106 }
107
108 /* first see if we already have the name. */
109 for (i = 0; i < segnames_used; i++) {
110 if (!segnames[i].inUse)
111 continue;
112 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
113 return i;
114 }
115 }
116
117 /* no we don't. So look for a free slot. */
118 for (i = 0; i < segnames_used; i++)
119 if (!segnames[i].inUse)
120 break;
121
122 if (i == segnames_used) {
123 /* no free slots .. advance the high-water mark. */
124 if (segnames_used+1 < VG_N_SEGNAMES) {
125 i = segnames_used;
126 segnames_used++;
127 } else {
128 VG_(printf)(
129 "coregrind/vg_memory.c:\n"
130 " VG_N_SEGNAMES is too small: "
131 "increase it and rebuild Valgrind.\n"
132 );
133 VG_(printf)(
134 "coregrind/vg_memory.c:\n"
135 " giving up now.\n\n"
136 );
137 VG_(exit)(0);
138 }
139 }
140
141 /* copy it in */
142 segnames[i].inUse = True;
143 for (j = 0; j < len; j++)
144 segnames[i].fname[j] = name[j];
145 vg_assert(len < VG_MAX_SEGNAMELEN);
146 segnames[i].fname[len] = 0;
147 return i;
148}
149
sewardj548be6d2005-02-16 01:31:37 +0000150
151/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
152 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000153 seg.
154*/
sewardj548be6d2005-02-16 01:31:37 +0000155static Int compare_addr_with_seg ( Addr a, Segment* seg )
156{
157 if (a < seg->addr)
158 return -1;
159 if (a >= seg->addr + seg->len)
160 return 1;
161 return 0;
162}
163
sewardj79048ce2005-02-18 08:28:32 +0000164
sewardj548be6d2005-02-16 01:31:37 +0000165/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000166 none.
167*/
sewardj548be6d2005-02-16 01:31:37 +0000168static Int find_segment ( Addr a )
169{
170 Int i;
171 for (i = 0; i < segments_used; i++) {
172 if (compare_addr_with_seg(a, &segments[i]) == 0)
173 return i;
174 }
175 return -1;
176}
177
178
179/* Assumes that 'a' is not in any segment. Finds the index of the
180 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
181 which is in fact in a segment is a checked error.
182*/
183static Int find_segment_above_unmapped ( Addr a )
184{
185 Int i, r;
186 for (i = 0; i < segments_used; i++) {
187 r = compare_addr_with_seg(a, &segments[i]);
188 vg_assert(r != 0); /* 'a' should not be in any segment. */
189 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000190 continue;
sewardj548be6d2005-02-16 01:31:37 +0000191 vg_assert(r == -1);
192 break;
193 }
194
195 if (i == segments_used)
196 return -1; /* not found */
197 else
198 return i;
199}
200
201
202/* Assumes that 'a' is in some segment. Finds the next segment along,
203 or NULL if none. Passing 'a' which is in fact not in a segment is
204 a checked error.
205*/
206static Int find_segment_above_mapped ( Addr a )
207{
208 Int i, r;
209 for (i = 0; i < segments_used; i++) {
210 r = compare_addr_with_seg(a, &segments[i]);
211 if (r == 1)
212 continue; /* not yet there */
213 if (r == 0)
214 break; /* found it */
215 vg_assert(0);
216 /* we shouldn't get here -- r == -1 and so it means we went past
217 'a' without seeing it -- it is therefore unmapped. */
218 /*NOTREACHED*/
219 }
220
221 vg_assert(i < segments_used);
222 if (i == segments_used-1)
223 return -1; /* not found */
224 else
225 return i+1;
226}
227
228
229/* Shift segments[i .. segments_used-1] up by one. */
230static void make_space_at ( Int i )
231{
232 Int j;
233 vg_assert(i >= 0 && i <= segments_used);
234 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000235 if (segments_used+1 == VG_N_SEGMENTS) {
236 VG_(printf)(
237 "coregrind/vg_memory.c:\n"
238 " VG_N_SEGMENTS is too small: "
239 "increase it and rebuild Valgrind.\n"
240 );
241 VG_(printf)(
242 "coregrind/vg_memory.c:\n"
243 " giving up now.\n\n"
244 );
245 VG_(exit)(0);
246 }
sewardj548be6d2005-02-16 01:31:37 +0000247 vg_assert(segments_used+1 < VG_N_SEGMENTS);
248 for (j = segments_used; j > i; j--)
249 segments[j] = segments[j-1];
250 segments_used++;
251}
252
sewardj79048ce2005-02-18 08:28:32 +0000253
sewardj548be6d2005-02-16 01:31:37 +0000254/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000255 segments_used.
256*/
sewardj548be6d2005-02-16 01:31:37 +0000257static void delete_segment_at ( Int i )
258{
259 Int j;
260 vg_assert(i >= 0 && i < segments_used);
261 for (j = i+1; j < segments_used; j++)
262 segments[j-1] = segments[j];
263 segments_used--;
264 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
265}
266
267
268/* Fill the i'th record all with zeroes. */
269static void zeroise_segment ( Int i )
270{
271 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000272 segments[i].prot = 0;
273 segments[i].flags = 0;
274 segments[i].addr = 0;
275 segments[i].len = 0;
276 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000277 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000278 segments[i].fnIdx = -1;
279 segments[i].dev = 0;
280 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000281 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000282}
283
sewardj79048ce2005-02-18 08:28:32 +0000284
sewardj548be6d2005-02-16 01:31:37 +0000285/* Create a segment to contain 'a', and return its index. Or -1 if
286 this failed because some other segment already contains 'a'. If
287 successful, fill in the segment's .addr field with 'a' but leave
288 all other fields alone.
289*/
290static Int create_segment ( Addr a )
291{
292 Int i, r;
293 for (i = 0; i < segments_used; i++) {
294 r = compare_addr_with_seg( a, &segments[i] );
295 if (r == 1)
296 continue; /* seg[i] precedes a */
297 if (r == 0)
298 return -1; /* seg[i] contains a. Give up */
299 vg_assert(r == -1);
300 break;
301 }
302 /* a precedes seg[i]. Shift segs at i and above up one, and use
303 this slot. */
304 make_space_at(i);
305 zeroise_segment(i);
306 segments[i].addr = a;
307 return i;
308}
309
sewardj79048ce2005-02-18 08:28:32 +0000310
311/* Print out the segment array (debugging only!). Note, this calls
312 VG_(printf), and I'm not 100% clear that that wouldn't require
313 dynamic memory allocation and hence more segments to be allocated.
314*/
315static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000316{
sewardj79048ce2005-02-18 08:28:32 +0000317 Int i;
318 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
319 who, segments_used, segnames_used);
320 for (i = 0; i < segnames_used; i++) {
321 if (!segnames[i].inUse)
322 continue;
323 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
324 }
325 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000326 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000327 "%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 +0000328 i,
sewardj79048ce2005-02-18 08:28:32 +0000329 segments[i].addr, segments[i].addr + segments[i].len,
330 (ULong)segments[i].len, segments[i].prot,
331 segments[i].flags, segments[i].dev, segments[i].ino,
332 (Long)segments[i].offset,
333 segments[i].fnIdx);
334 }
335 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000336}
sewardj79048ce2005-02-18 08:28:32 +0000337
sewardj548be6d2005-02-16 01:31:37 +0000338
339/* Find the segment containing 'a' and split it into two pieces at
340 'a'. Does nothing if no segment contains 'a', or if the split
341 would cause either of the pieces to have zero size.
342
343 If 'a' is not found, or if no splitting happens, -1 is returned.
344
345 If a value 'r' other than -1 is returned, this is the index of the
346 higher-addressed segment resulting from the split, and the index of
347 the lower-addressed segment is r-1.
348*/
349static Int split_segment ( Addr a )
350{
351 Int r;
352 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000353 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000354 r = find_segment(a);
355 if (r == -1)
356 /* not found */
357 return -1;
358 if (segments[r].addr == a)
359 /* segment starts at 'a', so splitting it would create a
360 zero-sized segment */
361 return -1;
362
363 /* copy original; make adjustments. */
364 vg_assert(a > segments[r].addr);
365 delta = a - segments[r].addr;
366 make_space_at(r);
367 segments[r] = segments[r+1];
368 segments[r].len = delta;
369 segments[r+1].len -= delta;
370 segments[r+1].addr += delta;
371 segments[r+1].offset += delta;
372 return r+1;
373}
374
sewardj79048ce2005-02-18 08:28:32 +0000375
376/* Return true if two segments are adjacent and mergable (s1 is
377 assumed to have a lower ->addr than s2) */
378static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
379{
380 if (s1->addr+s1->len != s2->addr)
381 return False;
382
383 if (s1->flags != s2->flags)
384 return False;
385
386 if (s1->prot != s2->prot)
387 return False;
388
njn36ef6ba2005-05-14 18:42:26 +0000389 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000390 return False;
391
392 if (s1->flags & SF_FILE){
393 if ((s1->offset + s1->len) != s2->offset)
394 return False;
395 if (s1->dev != s2->dev)
396 return False;
397 if (s1->ino != s2->ino)
398 return False;
399 if (s1->fnIdx != s2->fnIdx)
400 return False;
401 }
402
403 return True;
404}
405
406
407/* Clean up and sanity check the segment array:
408 - check segments are in ascending order
409 - check segments do not overlap
410 - check no segment has zero size
411 - merge adjacent where possible
412 - perform checks on the filename table, and reclaim dead entries
413*/
414static void preen_segments ( void )
415{
416 Int i, j, rd, wr;
417 Segment *s, *s1;
418 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
419 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
420
421 if (0) show_segments("before preen");
422
423 /* clear string table mark bits */
424 for (i = 0; i < segnames_used; i++)
425 segnames[i].mark = False;
426
427 /* check for non-zero size, and set mark bits for any used strings */
428 for (i = 0; i < segments_used; i++) {
429 vg_assert(segments[i].len > 0);
430 j = segments[i].fnIdx;
431 vg_assert(j >= -1 && j < segnames_used);
432 if (j >= 0) {
433 vg_assert(segnames[j].inUse);
434 segnames[j].mark = True;
435 }
436 }
437
438 /* check ascendingness and non-overlap */
439 for (i = 0; i < segments_used-1; i++) {
440 s = &segments[i];
441 s1 = &segments[i+1];
442 vg_assert(s->addr < s1->addr);
443 vg_assert(s->addr + s->len <= s1->addr);
444 }
445
446 /* merge */
447 if (segments_used < 1)
448 return;
449
450 wr = 1;
451 for (rd = 1; rd < segments_used; rd++) {
452 s = &segments[wr-1];
453 s1 = &segments[rd];
454 if (segments_are_mergeable(s,s1)) {
455 if (0)
456 VG_(printf)("merge %p-%p with %p-%p\n",
457 s->addr, s->addr+s->len,
458 s1->addr, s1->addr+s1->len);
459 s->len += s1->len;
460 continue;
461 }
462 if (wr < rd)
463 segments[wr] = segments[rd];
464 wr++;
465 }
466 vg_assert(wr >= 0 && wr <= segments_used);
467 segments_used = wr;
468
469 /* Free up any strings which are no longer referenced. */
470 for (i = 0; i < segnames_used; i++) {
471 if (segnames[i].mark == False) {
472 segnames[i].inUse = False;
473 segnames[i].fname[0] = 0;
474 }
475 }
476
477 if (0) show_segments("after preen");
478}
479
480
sewardj548be6d2005-02-16 01:31:37 +0000481/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000482/*--- Maintain an ordered list of all the client's mappings ---*/
483/*--------------------------------------------------------------*/
484
nethercote8991d5a2004-11-03 17:07:46 +0000485Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000486{
487 Addr se = s->addr+s->len;
488 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000489 vg_assert(pe >= p);
490
491 return (p >= s->addr && pe <= se);
492}
493
nethercote8991d5a2004-11-03 17:07:46 +0000494Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000495{
496 Addr se = s->addr+s->len;
497 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000498 vg_assert(pe >= p);
499
500 return (p < se && pe > s->addr);
501}
502
sewardj1024cf72005-02-28 14:39:21 +0000503#if 0
504/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000505/* Prepare a Segment structure for recycling by freeing everything
506 hanging off it. */
507static void recycleseg(Segment *s)
508{
509 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000510 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000511
512 if (s->filename != NULL)
513 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
514
515 /* keep the SegInfo, if any - it probably still applies */
516}
517
518/* When freeing a Segment, also clean up every one else's ideas of
519 what was going on in that range of memory */
520static void freeseg(Segment *s)
521{
522 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000523 if (s->seginfo != NULL) {
524 VG_(seginfo_decref)(s->seginfo, s->addr);
525 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000526 }
527
528 VG_(SkipNode_Free)(&sk_segments, s);
529}
sewardj1024cf72005-02-28 14:39:21 +0000530#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000531
sewardj1024cf72005-02-28 14:39:21 +0000532
533/* Get rid of any translations arising from s. */
534/* Note, this is not really the job of the low level memory manager.
535 When it comes time to rewrite this subsystem, clean this up. */
536static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000537{
sewardj1024cf72005-02-28 14:39:21 +0000538 if (s->flags & SF_CODE) {
539 VG_(discard_translations)(s->addr, s->len);
540 if (0)
541 VG_(printf)("dumping translations in %p .. %p\n",
542 s->addr, s->addr+s->len);
543 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000544}
545
sewardj1024cf72005-02-28 14:39:21 +0000546
fitzhardinge98abfc72003-12-16 02:05:15 +0000547/* This unmaps all the segments in the range [addr, addr+len); any
548 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000549void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000550{
fitzhardingee3632c62003-12-22 10:58:06 +0000551 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000552 Segment* s;
553 Addr end, s_end;
554 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000555 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000556
557 if (len == 0)
558 return;
559
fitzhardinge1a4adf02003-12-22 10:42:59 +0000560 len = PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000561
fitzhardinge98abfc72003-12-16 02:05:15 +0000562 if (debug)
tom9be7c982005-04-25 16:55:44 +0000563 VG_(printf)("unmap_range(%p, %lu)\n", addr, len);
sewardj79048ce2005-02-18 08:28:32 +0000564 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000565 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000566
567 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000568 vg_assert(VG_IS_PAGE_ALIGNED(addr));
569 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000570
sewardj548be6d2005-02-16 01:31:37 +0000571 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000572
573 /* do not delete .. even though it looks stupid */
574 vg_assert(i >= 0);
575
576 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000577 s = &segments[i];
578 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000579
sewardj548be6d2005-02-16 01:31:37 +0000580 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000581 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000582 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000583
fitzhardinge1a303042003-12-22 08:48:50 +0000584 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000585 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000586 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000587 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000588 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000589
590 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000591 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000592 addr < s_end &&
593 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000594 /* this segment's tail is truncated by [addr, addr+len)
595 -> truncate tail
596 */
sewardj1024cf72005-02-28 14:39:21 +0000597 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000598 s->len = addr - s->addr;
599
600 if (debug)
tom9be7c982005-04-25 16:55:44 +0000601 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000602 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000603 /* this segment's head is truncated by [addr, addr+len)
604 -> truncate head
605 */
sewardj548be6d2005-02-16 01:31:37 +0000606 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000607
608 if (debug)
tom9be7c982005-04-25 16:55:44 +0000609 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000610 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000611
sewardj1024cf72005-02-28 14:39:21 +0000612 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000613 s->addr += delta;
614 s->offset += delta;
615 s->len -= delta;
616
617 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000618 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000619 /* this segment is completely contained within [addr, addr+len)
620 -> delete segment
621 */
sewardj1024cf72005-02-28 14:39:21 +0000622 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000623 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000624 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000625
626 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000627 VG_(printf)(" case 3: seg %d deleted\n", i);
628 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000629 /* [addr, addr+len) is contained within a single segment
630 -> split segment into 3, delete middle portion
631 */
sewardj1024cf72005-02-28 14:39:21 +0000632 Int i_middle;
633 dump_translations_from(s);
634 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000635 vg_assert(i_middle != -1);
636 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000637 vg_assert(segments[i_middle].addr == addr);
638 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000639 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000640
641 if (debug)
642 VG_(printf)(" case 4: subrange %p-%p deleted\n",
643 addr, addr+len);
644 }
sewardj47c98a72005-03-12 20:36:15 +0000645
646 /* If we deleted this segment (or any above), those above will
647 have been moved down to fill in the hole in the segment
648 array. In order that we don't miss them, we have to
649 re-consider this slot number; hence the i--. */
650 if (deleted)
651 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000652 }
sewardj79048ce2005-02-18 08:28:32 +0000653 preen_segments();
654 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000655}
656
sewardj548be6d2005-02-16 01:31:37 +0000657
658/* Add a binding of [addr,addr+len) to
659 (prot,flags,dev,ino,off,filename) in the segment array.
660 Delete/truncate any previous mapping(s) covering that range.
661*/
662void
663VG_(map_file_segment)( Addr addr, SizeT len,
664 UInt prot, UInt flags,
665 UInt dev, UInt ino, ULong off,
666 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000667{
fitzhardinge98abfc72003-12-16 02:05:15 +0000668 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000669 Segment* s;
670 Int idx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000671
672 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000673 VG_(printf)(
674 "\n"
tom9be7c982005-04-25 16:55:44 +0000675 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000676 " dev=0x%4x ino=%d off=%ld\n"
677 " filename='%s')\n",
678 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000679
680 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000681 vg_assert(VG_IS_PAGE_ALIGNED(addr));
fitzhardinge98abfc72003-12-16 02:05:15 +0000682 len = PGROUNDUP(len);
683
sewardj548be6d2005-02-16 01:31:37 +0000684 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
685 VG_(unmap_range)(addr, len);
686
687 /* and now install this one */
688 idx = create_segment(addr);
689 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
690 vg_assert(idx != -1);
691 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000692
sewardj79048ce2005-02-18 08:28:32 +0000693 s = &segments[idx];
694 vg_assert(s->addr == addr);
695 s->prot = prot;
696 s->flags = flags;
697 s->len = len;
698 s->offset = off;
699 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
700 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
701 s->dev = dev;
702 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000703 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000704
sewardj79048ce2005-02-18 08:28:32 +0000705 /* Clean up right now */
706 preen_segments();
707 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000708
709 /* If this mapping is of the beginning of a file, isn't part of
710 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000711 file, then try reading symbols from it.
712 */
njn36ef6ba2005-05-14 18:42:26 +0000713 if (s->seginfo == NULL
sewardjb71816c2005-03-14 19:11:10 +0000714 && (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
sewardj79048ce2005-02-18 08:28:32 +0000715 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
716 if (off == 0
717 && s->fnIdx != -1
718 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
719 && len >= VKI_PAGE_SIZE
720 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000721 s->seginfo = VG_(read_seg_symbols)(s);
722 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000723 s->flags |= SF_DYNLIB;
724 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000725 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000726#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000727 const SegInfo *info;
728
njn36ef6ba2005-05-14 18:42:26 +0000729 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000730 for(info = VG_(next_seginfo)(NULL);
731 info != NULL;
732 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000733 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
734 {
njn36ef6ba2005-05-14 18:42:26 +0000735 s->seginfo = (SegInfo *)info;
736 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000737 }
738 }
sewardj79048ce2005-02-18 08:28:32 +0000739#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000740 }
741 }
742
743 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000744 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000745}
746
nethercote8b5f40c2004-11-02 13:29:50 +0000747void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000748 Int fd, ULong off, const Char *filename)
749{
750 struct vki_stat st;
751 Char *name = NULL;
752
753 st.st_dev = 0;
754 st.st_ino = 0;
755
756 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000757 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000758
759 if (VG_(fstat)(fd, &st) < 0)
760 flags &= ~SF_FILE;
761 }
762
sewardj79048ce2005-02-18 08:28:32 +0000763 if ((flags & SF_FILE) && filename == NULL && fd != -1)
764 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000765
766 if (filename == NULL)
767 filename = name;
768
sewardj79048ce2005-02-18 08:28:32 +0000769 VG_(map_file_segment)(addr, len, prot, flags,
770 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000771}
772
nethercote8b5f40c2004-11-02 13:29:50 +0000773void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000774{
775 flags &= ~SF_FILE;
776
777 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
778}
779
780/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000781void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000782{
sewardj79048ce2005-02-18 08:28:32 +0000783 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000784 static const Bool debug = False || mem_debug;
785
786 if (debug)
tom9be7c982005-04-25 16:55:44 +0000787 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000788
789 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000790
791 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000792 vg_assert(VG_IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000793 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000794
sewardj79048ce2005-02-18 08:28:32 +0000795 split_segment(a);
796 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000797
sewardj548be6d2005-02-16 01:31:37 +0000798 r = find_segment(a);
799 vg_assert(r != -1);
800 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000801
802 preen_segments();
803
sewardje517b802005-02-16 01:58:51 +0000804 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000805}
806
sewardj79048ce2005-02-18 08:28:32 +0000807
sewardj548be6d2005-02-16 01:31:37 +0000808/* Try to find a map space for [addr,addr+len). If addr==0, it means
809 the caller is prepared to accept a space at any location; if not,
810 we will try for addr, but fail if we can't get it. This mimics
811 mmap fixed vs mmap not-fixed.
812*/
nethercote8b5f40c2004-11-02 13:29:50 +0000813Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000814{
fitzhardingee3632c62003-12-22 10:58:06 +0000815 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000816 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000817 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000818 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
819 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000820 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
821 Int i, i_any, i_fixed, i_final;
822 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000823
sewardj548be6d2005-02-16 01:31:37 +0000824 Bool fixed;
825
sewardje517b802005-02-16 01:58:51 +0000826 if (debug) {
827 VG_(printf)("\n\n");
tom9be7c982005-04-25 16:55:44 +0000828 VG_(printf)("find_map_space(%p, %lu, %d) ...\n",
sewardje517b802005-02-16 01:58:51 +0000829 addr, len, for_client);
830 }
831
832 if (0) show_segments("find_map_space: start");
833
sewardj548be6d2005-02-16 01:31:37 +0000834 if (addr == 0) {
835 fixed = False;
836 } else {
837 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000838 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000839 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000840 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000841 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000842
843 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000844 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000845 len = PGROUNDUP(len);
846
nethercote73b526f2004-10-31 18:48:21 +0000847 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000848
sewardj548be6d2005-02-16 01:31:37 +0000849 /* Scan the segment list, looking for a hole which satisfies the
850 requirements. At each point i we ask the question "can we use
851 the hole in between segments[i-1] and segments[i] ?" */
852 i_any = i_fixed = -1;
853 hstart_any = hstart_fixed = 0;
854
855 hole_start = hole_end = 0;
856
857 /* Iterate over all possible holes, generating them into
858 hole_start/hole_end. Filter out invalid ones. Then see if any
859 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
860 */
861 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
862 if (i == 0) {
863 hole_start = 0;
864 hole_end = segments[0].addr-1;
865 }
866 else {
867 vg_assert(segments_used > 0);
868 if (i == segments_used) {
869 hole_start = segments[i-1].addr + segments[i-1].len;
870 hole_end = ~(Addr)0;
871 } else {
872 hole_start = segments[i-1].addr + segments[i-1].len;
873 hole_end = segments[i].addr - 1;
874 }
875 }
876
877 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
878
879 /* ignore zero-sized holes */
880 if (hole_start == hole_end+1)
881 continue;
882
njnbe91aae2005-03-27 01:42:41 +0000883 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
884 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000885
886 /* ignore holes which fall outside the allowable area */
887 if (!(hole_start >= base && hole_end <= limit))
888 continue;
889
890 vg_assert(hole_end > hole_start);
891 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000892 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000893
894 if (hole_len >= len && i_any == -1) {
895 /* It will at least fit in this hole. */
896 i_any = i;
897 hstart_any = hole_start;
898 }
899
sewardjb5f6f512005-03-10 23:59:00 +0000900 if (fixed && hole_start <= addr
901 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000902 /* We were asked for a fixed mapping, and this hole works.
903 Bag it -- and stop searching as further searching is
904 pointless. */
905 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000906 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000907 break;
908 }
909 }
910
911 /* Summarise the final decision into i_final/hstart_final. */
912 i_final = -1;
913 hstart_final = 0;
914
915 if (fixed) {
916 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000917 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000918 } else {
919 i_final = i_any;
920 hstart_final = hstart_any;
921 }
922
923
924 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000925 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000926 else
927 ret = 0; /* not found */
928
929 if (debug)
tom9be7c982005-04-25 16:55:44 +0000930 VG_(printf)("find_map_space(%p, %lu, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000931 addr, len, for_client, ret);
932
sewardjb5f6f512005-03-10 23:59:00 +0000933 if (fixed) {
934 vg_assert(ret == 0 || ret == addrOrig);
935 }
936
sewardj548be6d2005-02-16 01:31:37 +0000937 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000938}
939
sewardj79048ce2005-02-18 08:28:32 +0000940
sewardjb5f6f512005-03-10 23:59:00 +0000941/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000942 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000943 mapping over any part of the address space which is not covered
944 by an entry in the segment list.
945
946 This is designed for use around system calls which allocate
947 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000948 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000949 address with VG_(find_map_space) and then adding a segment for
950 it and padding the address space valgrind can ensure that the
951 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000952void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000953{
sewardj394790d2005-03-17 02:14:44 +0000954 Addr addr = (start == 0) ? VG_(client_base) : start;
955 Addr ret;
956
957 Int i = 0;
958 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000959
nethercote820bd8c2004-09-07 23:04:49 +0000960 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000961 if (addr < s->addr) {
njnf6d228b2005-03-26 02:42:31 +0000962 VGP_DO_MMAP(ret, addr, s->addr - addr, 0,
963 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
964 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000965 }
thughes9aaebc32004-07-15 23:13:37 +0000966 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000967 i++;
968 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000969 }
970
nethercote820bd8c2004-09-07 23:04:49 +0000971 if (addr <= VG_(valgrind_last)) {
njnf6d228b2005-03-26 02:42:31 +0000972 VGP_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
973 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
974 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000975 }
thughes9aaebc32004-07-15 23:13:37 +0000976}
977
thughesc70b8c62004-07-16 23:07:58 +0000978/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000979 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +0000980void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000981{
sewardj394790d2005-03-17 02:14:44 +0000982 Addr addr = (start == 0) ? VG_(client_base) : start;
983 Int ret;
984
985 Int i = 0;
986 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000987
nethercote820bd8c2004-09-07 23:04:49 +0000988 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000989 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +0000990 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +0000991 }
thughes9aaebc32004-07-15 23:13:37 +0000992 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000993 i++;
994 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000995 }
996
nethercote820bd8c2004-09-07 23:04:49 +0000997 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +0000998 ret = VG_(do_syscall2)(__NR_munmap, addr,
999 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001000 }
thughes9aaebc32004-07-15 23:13:37 +00001001}
1002
sewardj548be6d2005-02-16 01:31:37 +00001003/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001004Segment *VG_(find_segment)(Addr a)
1005{
sewardj548be6d2005-02-16 01:31:37 +00001006 Int r = find_segment(a);
1007 if (0) show_segments("find_segment");
1008 if (r == -1) return NULL;
1009 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001010}
1011
sewardj548be6d2005-02-16 01:31:37 +00001012/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1013 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1014 a segment is a checked error.
1015*/
1016Segment *VG_(find_segment_above_unmapped)(Addr a)
1017{
1018 Int r = find_segment_above_unmapped(a);
1019 if (0) show_segments("find_segment_above_unmapped");
1020 if (r == -1) return NULL;
1021 return &segments[r];
1022}
1023
1024/* Assumes that 'a' is in some segment. Finds the next segment along,
1025 or NULL if none. Passing 'a' which is in fact not in a segment is
1026 a checked error.
1027*/
1028Segment *VG_(find_segment_above_mapped)(Addr a)
1029{
1030 Int r = find_segment_above_mapped(a);
1031 if (0) show_segments("find_segment_above_mapped");
1032 if (r == -1) return NULL;
1033 return &segments[r];
1034}
1035
1036
sewardjde4a1d02002-03-22 01:27:54 +00001037/*------------------------------------------------------------*/
1038/*--- Tracking permissions around %esp changes. ---*/
1039/*------------------------------------------------------------*/
1040
1041/*
1042 The stack
1043 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001044 The stack's segment seems to be dynamically extended downwards by
1045 the kernel as the stack pointer moves down. Initially, a 1-page
1046 (4k) stack is allocated. When SP moves below that for the first
1047 time, presumably a page fault occurs. The kernel detects that the
njna60a7c12005-05-08 17:49:37 +00001048 faulting address is in the range from SP - VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001049 upwards to the current valid stack. It then extends the stack
1050 segment downwards for enough to cover the faulting address, and
1051 resumes the process (invisibly). The process is unaware of any of
1052 this.
sewardjde4a1d02002-03-22 01:27:54 +00001053
sewardjfa8202f2005-04-24 11:05:55 +00001054 That means that Valgrind can't spot when the stack segment is being
1055 extended. Fortunately, we want to precisely and continuously
1056 update stack permissions around SP, so we need to spot all writes
1057 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001058
sewardjfa8202f2005-04-24 11:05:55 +00001059 The deal is: when SP is assigned a lower value, the stack is being
1060 extended. Create suitably-permissioned pages to fill in any holes
1061 between the old stack ptr and this one, if necessary. Then mark
1062 all bytes in the area just "uncovered" by this SP change as
1063 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001064
sewardjfa8202f2005-04-24 11:05:55 +00001065 When SP goes back up, mark the area receded over as unreadable and
1066 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001067
njna60a7c12005-05-08 17:49:37 +00001068 Just to record the SP boundary conditions somewhere convenient:
1069 SP - VGA_STACK_REDZONE_SZB always points to the lowest live byte in
1070 the stack. All addresses below SP - VGA_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001071 live; those at and above it are.
1072
njna60a7c12005-05-08 17:49:37 +00001073 We do not concern ourselves here with the VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001074 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001075*/
1076
njn9b007f62003-04-07 14:40:25 +00001077/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001078 tracked by the tool, and one of the specialised cases
1079 (eg. new_mem_stack_4) isn't used in preference.
1080*/
njn9fb73db2005-03-27 01:55:21 +00001081VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001082void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001083{
sewardj97724e52005-04-02 23:40:59 +00001084 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001085 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001086
sewardj97724e52005-04-02 23:40:59 +00001087 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1088 /* SP has changed by more than some threshold amount (by
1089 default, 2MB). We take this to mean that the application is
1090 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001091
1092 JRS 20021001: following discussions with John Regehr, if a stack
1093 switch happens, it seems best not to mess at all with memory
1094 permissions. Seems to work well with Netscape 4.X. Really the
1095 only remaining difficulty is knowing exactly when a stack switch is
1096 happening. */
sewardj97724e52005-04-02 23:40:59 +00001097 if (VG_(clo_verbosity) > 0 && moans > 0) {
1098 moans--;
1099 VG_(message)(Vg_UserMsg,
1100 "Warning: client switching stacks? "
1101 "SP change: %p --> %p", old_SP, new_SP);
1102 VG_(message)(Vg_UserMsg,
1103 " to suppress, use: --max-stackframe=%d or greater",
1104 (delta < 0 ? -delta : delta));
1105 if (moans == 0)
1106 VG_(message)(Vg_UserMsg,
1107 " further instances of this message "
1108 "will not be shown.");
1109 }
njn9b007f62003-04-07 14:40:25 +00001110 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001111 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001112
njn9b007f62003-04-07 14:40:25 +00001113 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001114 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001115 }
1116}
1117
jsgf855d93d2003-10-13 22:26:55 +00001118/*
sewardjb5f6f512005-03-10 23:59:00 +00001119 Test if a piece of memory is addressable with at least the "prot"
1120 protection permissions by examining the underlying segments.
1121
1122 Really this is a very stupid algorithm and we could do much
1123 better by iterating through the segment array instead of through
1124 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001125 */
sewardjb5f6f512005-03-10 23:59:00 +00001126Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001127{
sewardjb5f6f512005-03-10 23:59:00 +00001128 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001129
sewardjb5f6f512005-03-10 23:59:00 +00001130 if ((p + size) < p)
1131 return False; /* reject wraparounds */
1132 if (size == 0)
1133 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001134
sewardjb5f6f512005-03-10 23:59:00 +00001135 p = PGROUNDDN(p);
1136 size = PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001137 vg_assert(VG_IS_PAGE_ALIGNED(p));
1138 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001139
sewardjb5f6f512005-03-10 23:59:00 +00001140 for (; size > 0; size -= VKI_PAGE_SIZE) {
1141 seg = VG_(find_segment)(p);
1142 if (!seg)
1143 return False;
1144 if ((seg->prot & prot) != prot)
1145 return False;
1146 p += VKI_PAGE_SIZE;
1147 }
jsgf855d93d2003-10-13 22:26:55 +00001148
sewardjb5f6f512005-03-10 23:59:00 +00001149 return True;
jsgf855d93d2003-10-13 22:26:55 +00001150}
1151
sewardjb5f6f512005-03-10 23:59:00 +00001152
sewardjde4a1d02002-03-22 01:27:54 +00001153/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001154/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001155/*--------------------------------------------------------------------*/
1156
nethercote57e36b32004-07-10 14:56:28 +00001157// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001158Addr VG_(get_memory_from_mmap_for_client)
1159 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001160{
1161 len = PGROUNDUP(len);
1162
njnca82cc02004-11-22 17:18:48 +00001163 tl_assert(!(sf_flags & SF_FIXED));
1164 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001165
nethercote8e9eab02004-07-11 18:01:06 +00001166 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1167 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1168 sf_flags | SF_CORE, -1, 0);
1169 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001170 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001171 else
1172 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001173}
1174
fitzhardinge98abfc72003-12-16 02:05:15 +00001175
njn86f12dc2005-03-14 01:16:05 +00001176/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001177 range, which isn't SF_CORE, a root.
1178*/
njn86f12dc2005-03-14 01:16:05 +00001179void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1180{
sewardj882af5f2005-03-16 12:27:53 +00001181 Int i;
1182 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001183 Segment *s;
1184
sewardj882af5f2005-03-16 12:27:53 +00001185 for (i = 0; i < segments_used; i++) {
1186 s = &segments[i];
1187 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1188 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001189 if (flags != SF_MMAP && flags != SF_STACK)
1190 continue;
sewardj882af5f2005-03-16 12:27:53 +00001191 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1192 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001193 continue;
1194 if (!VG_(is_client_addr)(s->addr) ||
1195 !VG_(is_client_addr)(s->addr+s->len))
1196 continue;
1197
1198 (*add_rootrange)(s->addr, s->len);
1199 }
njn86f12dc2005-03-14 01:16:05 +00001200}
1201
1202
nethercote88a90162004-07-10 16:59:25 +00001203/*--------------------------------------------------------------------*/
1204/*--- Querying memory layout ---*/
1205/*--------------------------------------------------------------------*/
1206
fitzhardinge98abfc72003-12-16 02:05:15 +00001207Bool VG_(is_client_addr)(Addr a)
1208{
1209 return a >= VG_(client_base) && a < VG_(client_end);
1210}
1211
1212Bool VG_(is_shadow_addr)(Addr a)
1213{
1214 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1215}
1216
fitzhardinge98abfc72003-12-16 02:05:15 +00001217Addr VG_(get_shadow_size)(void)
1218{
1219 return VG_(shadow_end)-VG_(shadow_base);
1220}
1221
sewardjfa8202f2005-04-24 11:05:55 +00001222
nethercote88a90162004-07-10 16:59:25 +00001223/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001224/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001225/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001226
1227void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1228{
sewardj548be6d2005-02-16 01:31:37 +00001229vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001230 if (0)
1231 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1232
1233 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001234 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001235
1236 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1237 p = PGROUNDDN(p);
1238
1239 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1240
1241 if (call_init)
1242 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001243 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001244 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1245
nethercote73b526f2004-10-31 18:48:21 +00001246 p += VKI_PAGE_SIZE;
1247 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001248 }
1249}
1250
1251void *VG_(shadow_alloc)(UInt size)
1252{
1253 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001254 Addr try_here;
1255 Int r;
1256
1257 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001258
1259 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001260 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001261
1262 size = PGROUNDUP(size);
1263
1264 if (shadow_alloc == 0)
1265 shadow_alloc = VG_(shadow_base);
1266
1267 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001268 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001269
sewardj79048ce2005-02-18 08:28:32 +00001270 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001271 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1272 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001273 vg_assert(size > 0);
1274
1275 if (0)
1276 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1277
1278 /* this is big-bang allocated, so we don't expect to find a listed
1279 segment for it. */
1280 /* This is really an absolute disgrace. Sometimes the big-bang
1281 mapping is in the list (due to re-reads of /proc/self/maps,
1282 presumably) and sometimes it isn't. */
1283#if 0
1284 r = find_segment(try_here);
1285 vg_assert(r == -1);
1286 r = find_segment(try_here+size-1);
1287 vg_assert(r == -1);
1288#endif
1289
1290 r = VG_(mprotect_native)( (void*)try_here,
1291 size, VKI_PROT_READ|VKI_PROT_WRITE );
1292
1293 if (r != 0)
1294 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001295
1296 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001297 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001298
sewardj79048ce2005-02-18 08:28:32 +00001299 failed:
1300 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001301 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001302 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001303 size
sewardj79048ce2005-02-18 08:28:32 +00001304 );
1305 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001306}
1307
1308/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001309/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001310/*--------------------------------------------------------------------*/