blob: 26a969d3173ec04094fc76f9d6f30b0a48e7a66a [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"
njn20242342005-05-16 23:31:24 +000035#include "pub_core_options.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000037#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000038#include "pub_core_transtab.h"
njn3c660b62005-05-13 22:18:47 +000039#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000040
sewardjde4a1d02002-03-22 01:27:54 +000041
sewardja4495682002-10-21 07:29:59 +000042/* Define to debug the memory-leak-detector. */
43/* #define VG_DEBUG_LEAKCHECK */
44
sewardje517b802005-02-16 01:58:51 +000045static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000046
47/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000048/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000049/*--------------------------------------------------------------*/
50
sewardj79048ce2005-02-18 08:28:32 +000051/* Max number of segments we can track. */
52#define VG_N_SEGMENTS 1000
53
54/* Max number of segment file names we can track. */
55#define VG_N_SEGNAMES 200
56
57/* Max length of a segment file name. */
58#define VG_MAX_SEGNAMELEN 1000
59
60
61/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000062
63/* Array [0 .. segments_used-1] of all mappings. */
64/* Sorted by .addr field. */
65/* I: len may not be zero. */
66/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000067/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000068
69static Segment segments[VG_N_SEGMENTS];
70static Int segments_used = 0;
71
sewardj79048ce2005-02-18 08:28:32 +000072typedef
73 struct {
74 Bool inUse;
75 Bool mark;
76 HChar fname[VG_MAX_SEGNAMELEN];
77 }
78 SegName;
79
80/* Filename table. _used is the high water mark; an entry is only
81 valid if its index >= 0, < _used, and its .inUse field == True.
82 The .mark field is used to garbage-collect dead entries.
83*/
84static SegName segnames[VG_N_SEGNAMES];
85static Int segnames_used = 0;
86
87
88/* ------ end of STATE for the address-space manager ------ */
89
90
91/* Searches the filename table to find an index for the given name.
92 If none is found, an index is allocated and the name stored. If no
93 space is available we just give up. If the string is too long to
94 store, return -1.
95*/
96static Int allocate_segname ( const HChar* name )
97{
98 Int i, j, len;
99
100 vg_assert(name);
101
102 if (0) VG_(printf)("alloc_segname %s\n", name);
103
104 len = VG_(strlen)(name);
105 if (len >= VG_MAX_SEGNAMELEN-1) {
106 return -1;
107 }
108
109 /* first see if we already have the name. */
110 for (i = 0; i < segnames_used; i++) {
111 if (!segnames[i].inUse)
112 continue;
113 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
114 return i;
115 }
116 }
117
118 /* no we don't. So look for a free slot. */
119 for (i = 0; i < segnames_used; i++)
120 if (!segnames[i].inUse)
121 break;
122
123 if (i == segnames_used) {
124 /* no free slots .. advance the high-water mark. */
125 if (segnames_used+1 < VG_N_SEGNAMES) {
126 i = segnames_used;
127 segnames_used++;
128 } else {
129 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000130 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000131 " VG_N_SEGNAMES is too small: "
132 "increase it and rebuild Valgrind.\n"
133 );
134 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000135 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000136 " giving up now.\n\n"
137 );
138 VG_(exit)(0);
139 }
140 }
141
142 /* copy it in */
143 segnames[i].inUse = True;
144 for (j = 0; j < len; j++)
145 segnames[i].fname[j] = name[j];
146 vg_assert(len < VG_MAX_SEGNAMELEN);
147 segnames[i].fname[len] = 0;
148 return i;
149}
150
sewardj548be6d2005-02-16 01:31:37 +0000151
152/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
153 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000154 seg.
155*/
sewardj548be6d2005-02-16 01:31:37 +0000156static Int compare_addr_with_seg ( Addr a, Segment* seg )
157{
158 if (a < seg->addr)
159 return -1;
160 if (a >= seg->addr + seg->len)
161 return 1;
162 return 0;
163}
164
sewardj79048ce2005-02-18 08:28:32 +0000165
sewardj548be6d2005-02-16 01:31:37 +0000166/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000167 none.
168*/
sewardj548be6d2005-02-16 01:31:37 +0000169static Int find_segment ( Addr a )
170{
171 Int i;
172 for (i = 0; i < segments_used; i++) {
173 if (compare_addr_with_seg(a, &segments[i]) == 0)
174 return i;
175 }
176 return -1;
177}
178
179
180/* Assumes that 'a' is not in any segment. Finds the index of the
181 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
182 which is in fact in a segment is a checked error.
183*/
184static Int find_segment_above_unmapped ( Addr a )
185{
186 Int i, r;
187 for (i = 0; i < segments_used; i++) {
188 r = compare_addr_with_seg(a, &segments[i]);
189 vg_assert(r != 0); /* 'a' should not be in any segment. */
190 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000191 continue;
sewardj548be6d2005-02-16 01:31:37 +0000192 vg_assert(r == -1);
193 break;
194 }
195
196 if (i == segments_used)
197 return -1; /* not found */
198 else
199 return i;
200}
201
202
203/* Assumes that 'a' is in some segment. Finds the next segment along,
204 or NULL if none. Passing 'a' which is in fact not in a segment is
205 a checked error.
206*/
207static Int find_segment_above_mapped ( Addr a )
208{
209 Int i, r;
210 for (i = 0; i < segments_used; i++) {
211 r = compare_addr_with_seg(a, &segments[i]);
212 if (r == 1)
213 continue; /* not yet there */
214 if (r == 0)
215 break; /* found it */
216 vg_assert(0);
217 /* we shouldn't get here -- r == -1 and so it means we went past
218 'a' without seeing it -- it is therefore unmapped. */
219 /*NOTREACHED*/
220 }
221
222 vg_assert(i < segments_used);
223 if (i == segments_used-1)
224 return -1; /* not found */
225 else
226 return i+1;
227}
228
229
230/* Shift segments[i .. segments_used-1] up by one. */
231static void make_space_at ( Int i )
232{
233 Int j;
234 vg_assert(i >= 0 && i <= segments_used);
235 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000236 if (segments_used+1 == VG_N_SEGMENTS) {
237 VG_(printf)(
238 "coregrind/vg_memory.c:\n"
239 " VG_N_SEGMENTS is too small: "
240 "increase it and rebuild Valgrind.\n"
241 );
242 VG_(printf)(
243 "coregrind/vg_memory.c:\n"
244 " giving up now.\n\n"
245 );
246 VG_(exit)(0);
247 }
sewardj548be6d2005-02-16 01:31:37 +0000248 vg_assert(segments_used+1 < VG_N_SEGMENTS);
249 for (j = segments_used; j > i; j--)
250 segments[j] = segments[j-1];
251 segments_used++;
252}
253
sewardj79048ce2005-02-18 08:28:32 +0000254
sewardj548be6d2005-02-16 01:31:37 +0000255/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000256 segments_used.
257*/
sewardj548be6d2005-02-16 01:31:37 +0000258static void delete_segment_at ( Int i )
259{
260 Int j;
261 vg_assert(i >= 0 && i < segments_used);
262 for (j = i+1; j < segments_used; j++)
263 segments[j-1] = segments[j];
264 segments_used--;
265 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
266}
267
268
269/* Fill the i'th record all with zeroes. */
270static void zeroise_segment ( Int i )
271{
272 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000273 segments[i].prot = 0;
274 segments[i].flags = 0;
275 segments[i].addr = 0;
276 segments[i].len = 0;
277 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000278 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000279 segments[i].fnIdx = -1;
280 segments[i].dev = 0;
281 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000282 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000283}
284
sewardj79048ce2005-02-18 08:28:32 +0000285
sewardj548be6d2005-02-16 01:31:37 +0000286/* Create a segment to contain 'a', and return its index. Or -1 if
287 this failed because some other segment already contains 'a'. If
288 successful, fill in the segment's .addr field with 'a' but leave
289 all other fields alone.
290*/
291static Int create_segment ( Addr a )
292{
293 Int i, r;
294 for (i = 0; i < segments_used; i++) {
295 r = compare_addr_with_seg( a, &segments[i] );
296 if (r == 1)
297 continue; /* seg[i] precedes a */
298 if (r == 0)
299 return -1; /* seg[i] contains a. Give up */
300 vg_assert(r == -1);
301 break;
302 }
303 /* a precedes seg[i]. Shift segs at i and above up one, and use
304 this slot. */
305 make_space_at(i);
306 zeroise_segment(i);
307 segments[i].addr = a;
308 return i;
309}
310
sewardj79048ce2005-02-18 08:28:32 +0000311
312/* Print out the segment array (debugging only!). Note, this calls
313 VG_(printf), and I'm not 100% clear that that wouldn't require
314 dynamic memory allocation and hence more segments to be allocated.
315*/
316static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000317{
sewardj79048ce2005-02-18 08:28:32 +0000318 Int i;
319 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
320 who, segments_used, segnames_used);
321 for (i = 0; i < segnames_used; i++) {
322 if (!segnames[i].inUse)
323 continue;
324 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
325 }
326 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000327 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000328 "%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 +0000329 i,
sewardj79048ce2005-02-18 08:28:32 +0000330 segments[i].addr, segments[i].addr + segments[i].len,
331 (ULong)segments[i].len, segments[i].prot,
332 segments[i].flags, segments[i].dev, segments[i].ino,
333 (Long)segments[i].offset,
334 segments[i].fnIdx);
335 }
336 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000337}
sewardj79048ce2005-02-18 08:28:32 +0000338
sewardj548be6d2005-02-16 01:31:37 +0000339
340/* Find the segment containing 'a' and split it into two pieces at
341 'a'. Does nothing if no segment contains 'a', or if the split
342 would cause either of the pieces to have zero size.
343
344 If 'a' is not found, or if no splitting happens, -1 is returned.
345
346 If a value 'r' other than -1 is returned, this is the index of the
347 higher-addressed segment resulting from the split, and the index of
348 the lower-addressed segment is r-1.
349*/
350static Int split_segment ( Addr a )
351{
352 Int r;
353 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000354 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000355 r = find_segment(a);
356 if (r == -1)
357 /* not found */
358 return -1;
359 if (segments[r].addr == a)
360 /* segment starts at 'a', so splitting it would create a
361 zero-sized segment */
362 return -1;
363
364 /* copy original; make adjustments. */
365 vg_assert(a > segments[r].addr);
366 delta = a - segments[r].addr;
367 make_space_at(r);
368 segments[r] = segments[r+1];
369 segments[r].len = delta;
370 segments[r+1].len -= delta;
371 segments[r+1].addr += delta;
372 segments[r+1].offset += delta;
373 return r+1;
374}
375
sewardj79048ce2005-02-18 08:28:32 +0000376
377/* Return true if two segments are adjacent and mergable (s1 is
378 assumed to have a lower ->addr than s2) */
379static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
380{
381 if (s1->addr+s1->len != s2->addr)
382 return False;
383
384 if (s1->flags != s2->flags)
385 return False;
386
387 if (s1->prot != s2->prot)
388 return False;
389
njn36ef6ba2005-05-14 18:42:26 +0000390 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000391 return False;
392
393 if (s1->flags & SF_FILE){
394 if ((s1->offset + s1->len) != s2->offset)
395 return False;
396 if (s1->dev != s2->dev)
397 return False;
398 if (s1->ino != s2->ino)
399 return False;
400 if (s1->fnIdx != s2->fnIdx)
401 return False;
402 }
403
404 return True;
405}
406
407
408/* Clean up and sanity check the segment array:
409 - check segments are in ascending order
410 - check segments do not overlap
411 - check no segment has zero size
412 - merge adjacent where possible
413 - perform checks on the filename table, and reclaim dead entries
414*/
415static void preen_segments ( void )
416{
417 Int i, j, rd, wr;
418 Segment *s, *s1;
419 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
420 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
421
422 if (0) show_segments("before preen");
423
424 /* clear string table mark bits */
425 for (i = 0; i < segnames_used; i++)
426 segnames[i].mark = False;
427
428 /* check for non-zero size, and set mark bits for any used strings */
429 for (i = 0; i < segments_used; i++) {
430 vg_assert(segments[i].len > 0);
431 j = segments[i].fnIdx;
432 vg_assert(j >= -1 && j < segnames_used);
433 if (j >= 0) {
434 vg_assert(segnames[j].inUse);
435 segnames[j].mark = True;
436 }
437 }
438
439 /* check ascendingness and non-overlap */
440 for (i = 0; i < segments_used-1; i++) {
441 s = &segments[i];
442 s1 = &segments[i+1];
443 vg_assert(s->addr < s1->addr);
444 vg_assert(s->addr + s->len <= s1->addr);
445 }
446
447 /* merge */
448 if (segments_used < 1)
449 return;
450
451 wr = 1;
452 for (rd = 1; rd < segments_used; rd++) {
453 s = &segments[wr-1];
454 s1 = &segments[rd];
455 if (segments_are_mergeable(s,s1)) {
456 if (0)
457 VG_(printf)("merge %p-%p with %p-%p\n",
458 s->addr, s->addr+s->len,
459 s1->addr, s1->addr+s1->len);
460 s->len += s1->len;
461 continue;
462 }
463 if (wr < rd)
464 segments[wr] = segments[rd];
465 wr++;
466 }
467 vg_assert(wr >= 0 && wr <= segments_used);
468 segments_used = wr;
469
470 /* Free up any strings which are no longer referenced. */
471 for (i = 0; i < segnames_used; i++) {
472 if (segnames[i].mark == False) {
473 segnames[i].inUse = False;
474 segnames[i].fname[0] = 0;
475 }
476 }
477
478 if (0) show_segments("after preen");
479}
480
481
sewardj548be6d2005-02-16 01:31:37 +0000482/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000483/*--- Maintain an ordered list of all the client's mappings ---*/
484/*--------------------------------------------------------------*/
485
nethercote8991d5a2004-11-03 17:07:46 +0000486Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000487{
488 Addr se = s->addr+s->len;
489 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000490 vg_assert(pe >= p);
491
492 return (p >= s->addr && pe <= se);
493}
494
nethercote8991d5a2004-11-03 17:07:46 +0000495Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000496{
497 Addr se = s->addr+s->len;
498 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000499 vg_assert(pe >= p);
500
501 return (p < se && pe > s->addr);
502}
503
sewardj1024cf72005-02-28 14:39:21 +0000504#if 0
505/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000506/* Prepare a Segment structure for recycling by freeing everything
507 hanging off it. */
508static void recycleseg(Segment *s)
509{
510 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000511 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000512
513 if (s->filename != NULL)
514 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
515
516 /* keep the SegInfo, if any - it probably still applies */
517}
518
519/* When freeing a Segment, also clean up every one else's ideas of
520 what was going on in that range of memory */
521static void freeseg(Segment *s)
522{
523 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000524 if (s->seginfo != NULL) {
525 VG_(seginfo_decref)(s->seginfo, s->addr);
526 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000527 }
528
529 VG_(SkipNode_Free)(&sk_segments, s);
530}
sewardj1024cf72005-02-28 14:39:21 +0000531#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000532
sewardj1024cf72005-02-28 14:39:21 +0000533
534/* Get rid of any translations arising from s. */
535/* Note, this is not really the job of the low level memory manager.
536 When it comes time to rewrite this subsystem, clean this up. */
537static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000538{
sewardj1024cf72005-02-28 14:39:21 +0000539 if (s->flags & SF_CODE) {
540 VG_(discard_translations)(s->addr, s->len);
541 if (0)
542 VG_(printf)("dumping translations in %p .. %p\n",
543 s->addr, s->addr+s->len);
544 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000545}
546
sewardj1024cf72005-02-28 14:39:21 +0000547
fitzhardinge98abfc72003-12-16 02:05:15 +0000548/* This unmaps all the segments in the range [addr, addr+len); any
549 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000550void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000551{
fitzhardingee3632c62003-12-22 10:58:06 +0000552 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000553 Segment* s;
554 Addr end, s_end;
555 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000556 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000557
558 if (len == 0)
559 return;
560
fitzhardinge1a4adf02003-12-22 10:42:59 +0000561 len = PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000562
fitzhardinge98abfc72003-12-16 02:05:15 +0000563 if (debug)
tom9be7c982005-04-25 16:55:44 +0000564 VG_(printf)("unmap_range(%p, %lu)\n", addr, len);
sewardj79048ce2005-02-18 08:28:32 +0000565 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000566 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000567
568 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000569 vg_assert(VG_IS_PAGE_ALIGNED(addr));
570 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000571
sewardj548be6d2005-02-16 01:31:37 +0000572 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000573
574 /* do not delete .. even though it looks stupid */
575 vg_assert(i >= 0);
576
577 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000578 s = &segments[i];
579 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000580
sewardj548be6d2005-02-16 01:31:37 +0000581 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000582 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000583 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000584
fitzhardinge1a303042003-12-22 08:48:50 +0000585 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000586 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000587 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000588 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000589 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000590
591 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000592 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000593 addr < s_end &&
594 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000595 /* this segment's tail is truncated by [addr, addr+len)
596 -> truncate tail
597 */
sewardj1024cf72005-02-28 14:39:21 +0000598 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000599 s->len = addr - s->addr;
600
601 if (debug)
tom9be7c982005-04-25 16:55:44 +0000602 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000603 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000604 /* this segment's head is truncated by [addr, addr+len)
605 -> truncate head
606 */
sewardj548be6d2005-02-16 01:31:37 +0000607 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000608
609 if (debug)
tom9be7c982005-04-25 16:55:44 +0000610 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000611 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000612
sewardj1024cf72005-02-28 14:39:21 +0000613 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000614 s->addr += delta;
615 s->offset += delta;
616 s->len -= delta;
617
618 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000619 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000620 /* this segment is completely contained within [addr, addr+len)
621 -> delete segment
622 */
sewardj1024cf72005-02-28 14:39:21 +0000623 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000624 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000625 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000626
627 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000628 VG_(printf)(" case 3: seg %d deleted\n", i);
629 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000630 /* [addr, addr+len) is contained within a single segment
631 -> split segment into 3, delete middle portion
632 */
sewardj1024cf72005-02-28 14:39:21 +0000633 Int i_middle;
634 dump_translations_from(s);
635 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000636 vg_assert(i_middle != -1);
637 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000638 vg_assert(segments[i_middle].addr == addr);
639 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000640 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000641
642 if (debug)
643 VG_(printf)(" case 4: subrange %p-%p deleted\n",
644 addr, addr+len);
645 }
sewardj47c98a72005-03-12 20:36:15 +0000646
647 /* If we deleted this segment (or any above), those above will
648 have been moved down to fill in the hole in the segment
649 array. In order that we don't miss them, we have to
650 re-consider this slot number; hence the i--. */
651 if (deleted)
652 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000653 }
sewardj79048ce2005-02-18 08:28:32 +0000654 preen_segments();
655 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000656}
657
sewardj548be6d2005-02-16 01:31:37 +0000658
659/* Add a binding of [addr,addr+len) to
660 (prot,flags,dev,ino,off,filename) in the segment array.
661 Delete/truncate any previous mapping(s) covering that range.
662*/
663void
664VG_(map_file_segment)( Addr addr, SizeT len,
665 UInt prot, UInt flags,
666 UInt dev, UInt ino, ULong off,
667 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000668{
fitzhardinge98abfc72003-12-16 02:05:15 +0000669 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000670 Segment* s;
671 Int idx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000672
673 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000674 VG_(printf)(
675 "\n"
tom9be7c982005-04-25 16:55:44 +0000676 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000677 " dev=0x%4x ino=%d off=%ld\n"
678 " filename='%s')\n",
679 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000680
681 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000682 vg_assert(VG_IS_PAGE_ALIGNED(addr));
fitzhardinge98abfc72003-12-16 02:05:15 +0000683 len = PGROUNDUP(len);
684
sewardj548be6d2005-02-16 01:31:37 +0000685 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
686 VG_(unmap_range)(addr, len);
687
688 /* and now install this one */
689 idx = create_segment(addr);
690 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
691 vg_assert(idx != -1);
692 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000693
sewardj79048ce2005-02-18 08:28:32 +0000694 s = &segments[idx];
695 vg_assert(s->addr == addr);
696 s->prot = prot;
697 s->flags = flags;
698 s->len = len;
699 s->offset = off;
700 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
701 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
702 s->dev = dev;
703 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000704 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000705
sewardj79048ce2005-02-18 08:28:32 +0000706 /* Clean up right now */
707 preen_segments();
708 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000709
710 /* If this mapping is of the beginning of a file, isn't part of
711 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000712 file, then try reading symbols from it.
713 */
njn36ef6ba2005-05-14 18:42:26 +0000714 if (s->seginfo == NULL
sewardjb71816c2005-03-14 19:11:10 +0000715 && (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
sewardj79048ce2005-02-18 08:28:32 +0000716 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
717 if (off == 0
718 && s->fnIdx != -1
719 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
720 && len >= VKI_PAGE_SIZE
721 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000722 s->seginfo = VG_(read_seg_symbols)(s);
723 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000724 s->flags |= SF_DYNLIB;
725 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000726 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000727#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000728 const SegInfo *info;
729
njn36ef6ba2005-05-14 18:42:26 +0000730 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000731 for(info = VG_(next_seginfo)(NULL);
732 info != NULL;
733 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000734 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
735 {
njn36ef6ba2005-05-14 18:42:26 +0000736 s->seginfo = (SegInfo *)info;
737 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000738 }
739 }
sewardj79048ce2005-02-18 08:28:32 +0000740#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000741 }
742 }
743
744 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000745 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000746}
747
nethercote8b5f40c2004-11-02 13:29:50 +0000748void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000749 Int fd, ULong off, const Char *filename)
750{
751 struct vki_stat st;
752 Char *name = NULL;
753
754 st.st_dev = 0;
755 st.st_ino = 0;
756
757 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000758 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000759
760 if (VG_(fstat)(fd, &st) < 0)
761 flags &= ~SF_FILE;
762 }
763
sewardj79048ce2005-02-18 08:28:32 +0000764 if ((flags & SF_FILE) && filename == NULL && fd != -1)
765 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000766
767 if (filename == NULL)
768 filename = name;
769
sewardj79048ce2005-02-18 08:28:32 +0000770 VG_(map_file_segment)(addr, len, prot, flags,
771 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000772}
773
nethercote8b5f40c2004-11-02 13:29:50 +0000774void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000775{
776 flags &= ~SF_FILE;
777
778 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
779}
780
781/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000782void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000783{
sewardj79048ce2005-02-18 08:28:32 +0000784 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000785 static const Bool debug = False || mem_debug;
786
787 if (debug)
tom9be7c982005-04-25 16:55:44 +0000788 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000789
790 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000791
792 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000793 vg_assert(VG_IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000794 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000795
sewardj79048ce2005-02-18 08:28:32 +0000796 split_segment(a);
797 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000798
sewardj548be6d2005-02-16 01:31:37 +0000799 r = find_segment(a);
800 vg_assert(r != -1);
801 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000802
803 preen_segments();
804
sewardje517b802005-02-16 01:58:51 +0000805 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000806}
807
sewardj79048ce2005-02-18 08:28:32 +0000808
sewardj548be6d2005-02-16 01:31:37 +0000809/* Try to find a map space for [addr,addr+len). If addr==0, it means
810 the caller is prepared to accept a space at any location; if not,
811 we will try for addr, but fail if we can't get it. This mimics
812 mmap fixed vs mmap not-fixed.
813*/
nethercote8b5f40c2004-11-02 13:29:50 +0000814Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000815{
fitzhardingee3632c62003-12-22 10:58:06 +0000816 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000817 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000818 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000819 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
820 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000821 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
822 Int i, i_any, i_fixed, i_final;
823 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000824
sewardj548be6d2005-02-16 01:31:37 +0000825 Bool fixed;
826
sewardje517b802005-02-16 01:58:51 +0000827 if (debug) {
828 VG_(printf)("\n\n");
tom9be7c982005-04-25 16:55:44 +0000829 VG_(printf)("find_map_space(%p, %lu, %d) ...\n",
sewardje517b802005-02-16 01:58:51 +0000830 addr, len, for_client);
831 }
832
833 if (0) show_segments("find_map_space: start");
834
sewardj548be6d2005-02-16 01:31:37 +0000835 if (addr == 0) {
836 fixed = False;
837 } else {
838 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000839 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000840 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000841 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000842 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000843
844 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000845 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000846 len = PGROUNDUP(len);
847
nethercote73b526f2004-10-31 18:48:21 +0000848 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000849
sewardj548be6d2005-02-16 01:31:37 +0000850 /* Scan the segment list, looking for a hole which satisfies the
851 requirements. At each point i we ask the question "can we use
852 the hole in between segments[i-1] and segments[i] ?" */
853 i_any = i_fixed = -1;
854 hstart_any = hstart_fixed = 0;
855
856 hole_start = hole_end = 0;
857
858 /* Iterate over all possible holes, generating them into
859 hole_start/hole_end. Filter out invalid ones. Then see if any
860 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
861 */
862 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
863 if (i == 0) {
864 hole_start = 0;
865 hole_end = segments[0].addr-1;
866 }
867 else {
868 vg_assert(segments_used > 0);
869 if (i == segments_used) {
870 hole_start = segments[i-1].addr + segments[i-1].len;
871 hole_end = ~(Addr)0;
872 } else {
873 hole_start = segments[i-1].addr + segments[i-1].len;
874 hole_end = segments[i].addr - 1;
875 }
876 }
877
878 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
879
880 /* ignore zero-sized holes */
881 if (hole_start == hole_end+1)
882 continue;
883
njnbe91aae2005-03-27 01:42:41 +0000884 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
885 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000886
887 /* ignore holes which fall outside the allowable area */
888 if (!(hole_start >= base && hole_end <= limit))
889 continue;
890
891 vg_assert(hole_end > hole_start);
892 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000893 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000894
895 if (hole_len >= len && i_any == -1) {
896 /* It will at least fit in this hole. */
897 i_any = i;
898 hstart_any = hole_start;
899 }
900
sewardjb5f6f512005-03-10 23:59:00 +0000901 if (fixed && hole_start <= addr
902 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000903 /* We were asked for a fixed mapping, and this hole works.
904 Bag it -- and stop searching as further searching is
905 pointless. */
906 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000907 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000908 break;
909 }
910 }
911
912 /* Summarise the final decision into i_final/hstart_final. */
913 i_final = -1;
914 hstart_final = 0;
915
916 if (fixed) {
917 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000918 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000919 } else {
920 i_final = i_any;
921 hstart_final = hstart_any;
922 }
923
924
925 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000926 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000927 else
928 ret = 0; /* not found */
929
930 if (debug)
tom9be7c982005-04-25 16:55:44 +0000931 VG_(printf)("find_map_space(%p, %lu, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000932 addr, len, for_client, ret);
933
sewardjb5f6f512005-03-10 23:59:00 +0000934 if (fixed) {
935 vg_assert(ret == 0 || ret == addrOrig);
936 }
937
sewardj548be6d2005-02-16 01:31:37 +0000938 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000939}
940
sewardj79048ce2005-02-18 08:28:32 +0000941
sewardjb5f6f512005-03-10 23:59:00 +0000942/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000943 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000944 mapping over any part of the address space which is not covered
945 by an entry in the segment list.
946
947 This is designed for use around system calls which allocate
948 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000949 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000950 address with VG_(find_map_space) and then adding a segment for
951 it and padding the address space valgrind can ensure that the
952 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000953void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000954{
sewardj394790d2005-03-17 02:14:44 +0000955 Addr addr = (start == 0) ? VG_(client_base) : start;
956 Addr ret;
957
958 Int i = 0;
959 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000960
nethercote820bd8c2004-09-07 23:04:49 +0000961 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000962 if (addr < s->addr) {
njnf6d228b2005-03-26 02:42:31 +0000963 VGP_DO_MMAP(ret, addr, s->addr - addr, 0,
964 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
965 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000966 }
thughes9aaebc32004-07-15 23:13:37 +0000967 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000968 i++;
969 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000970 }
971
nethercote820bd8c2004-09-07 23:04:49 +0000972 if (addr <= VG_(valgrind_last)) {
njnf6d228b2005-03-26 02:42:31 +0000973 VGP_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
974 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
975 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000976 }
thughes9aaebc32004-07-15 23:13:37 +0000977}
978
thughesc70b8c62004-07-16 23:07:58 +0000979/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000980 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +0000981void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000982{
sewardj394790d2005-03-17 02:14:44 +0000983 Addr addr = (start == 0) ? VG_(client_base) : start;
984 Int ret;
985
986 Int i = 0;
987 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000988
nethercote820bd8c2004-09-07 23:04:49 +0000989 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000990 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +0000991 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +0000992 }
thughes9aaebc32004-07-15 23:13:37 +0000993 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000994 i++;
995 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000996 }
997
nethercote820bd8c2004-09-07 23:04:49 +0000998 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +0000999 ret = VG_(do_syscall2)(__NR_munmap, addr,
1000 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001001 }
thughes9aaebc32004-07-15 23:13:37 +00001002}
1003
sewardj548be6d2005-02-16 01:31:37 +00001004/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001005Segment *VG_(find_segment)(Addr a)
1006{
sewardj548be6d2005-02-16 01:31:37 +00001007 Int r = find_segment(a);
1008 if (0) show_segments("find_segment");
1009 if (r == -1) return NULL;
1010 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001011}
1012
sewardj548be6d2005-02-16 01:31:37 +00001013/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1014 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1015 a segment is a checked error.
1016*/
1017Segment *VG_(find_segment_above_unmapped)(Addr a)
1018{
1019 Int r = find_segment_above_unmapped(a);
1020 if (0) show_segments("find_segment_above_unmapped");
1021 if (r == -1) return NULL;
1022 return &segments[r];
1023}
1024
1025/* Assumes that 'a' is in some segment. Finds the next segment along,
1026 or NULL if none. Passing 'a' which is in fact not in a segment is
1027 a checked error.
1028*/
1029Segment *VG_(find_segment_above_mapped)(Addr a)
1030{
1031 Int r = find_segment_above_mapped(a);
1032 if (0) show_segments("find_segment_above_mapped");
1033 if (r == -1) return NULL;
1034 return &segments[r];
1035}
1036
1037
sewardjde4a1d02002-03-22 01:27:54 +00001038/*------------------------------------------------------------*/
1039/*--- Tracking permissions around %esp changes. ---*/
1040/*------------------------------------------------------------*/
1041
1042/*
1043 The stack
1044 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001045 The stack's segment seems to be dynamically extended downwards by
1046 the kernel as the stack pointer moves down. Initially, a 1-page
1047 (4k) stack is allocated. When SP moves below that for the first
1048 time, presumably a page fault occurs. The kernel detects that the
njna60a7c12005-05-08 17:49:37 +00001049 faulting address is in the range from SP - VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001050 upwards to the current valid stack. It then extends the stack
1051 segment downwards for enough to cover the faulting address, and
1052 resumes the process (invisibly). The process is unaware of any of
1053 this.
sewardjde4a1d02002-03-22 01:27:54 +00001054
sewardjfa8202f2005-04-24 11:05:55 +00001055 That means that Valgrind can't spot when the stack segment is being
1056 extended. Fortunately, we want to precisely and continuously
1057 update stack permissions around SP, so we need to spot all writes
1058 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001059
sewardjfa8202f2005-04-24 11:05:55 +00001060 The deal is: when SP is assigned a lower value, the stack is being
1061 extended. Create suitably-permissioned pages to fill in any holes
1062 between the old stack ptr and this one, if necessary. Then mark
1063 all bytes in the area just "uncovered" by this SP change as
1064 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001065
sewardjfa8202f2005-04-24 11:05:55 +00001066 When SP goes back up, mark the area receded over as unreadable and
1067 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001068
njna60a7c12005-05-08 17:49:37 +00001069 Just to record the SP boundary conditions somewhere convenient:
1070 SP - VGA_STACK_REDZONE_SZB always points to the lowest live byte in
1071 the stack. All addresses below SP - VGA_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001072 live; those at and above it are.
1073
njna60a7c12005-05-08 17:49:37 +00001074 We do not concern ourselves here with the VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001075 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001076*/
1077
njn9b007f62003-04-07 14:40:25 +00001078/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001079 tracked by the tool, and one of the specialised cases
1080 (eg. new_mem_stack_4) isn't used in preference.
1081*/
njn9fb73db2005-03-27 01:55:21 +00001082VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001083void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001084{
sewardj97724e52005-04-02 23:40:59 +00001085 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001086 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001087
sewardj97724e52005-04-02 23:40:59 +00001088 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1089 /* SP has changed by more than some threshold amount (by
1090 default, 2MB). We take this to mean that the application is
1091 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001092
1093 JRS 20021001: following discussions with John Regehr, if a stack
1094 switch happens, it seems best not to mess at all with memory
1095 permissions. Seems to work well with Netscape 4.X. Really the
1096 only remaining difficulty is knowing exactly when a stack switch is
1097 happening. */
sewardj97724e52005-04-02 23:40:59 +00001098 if (VG_(clo_verbosity) > 0 && moans > 0) {
1099 moans--;
1100 VG_(message)(Vg_UserMsg,
1101 "Warning: client switching stacks? "
1102 "SP change: %p --> %p", old_SP, new_SP);
1103 VG_(message)(Vg_UserMsg,
1104 " to suppress, use: --max-stackframe=%d or greater",
1105 (delta < 0 ? -delta : delta));
1106 if (moans == 0)
1107 VG_(message)(Vg_UserMsg,
1108 " further instances of this message "
1109 "will not be shown.");
1110 }
njn9b007f62003-04-07 14:40:25 +00001111 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001112 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001113
njn9b007f62003-04-07 14:40:25 +00001114 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001115 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001116 }
1117}
1118
jsgf855d93d2003-10-13 22:26:55 +00001119/*
sewardjb5f6f512005-03-10 23:59:00 +00001120 Test if a piece of memory is addressable with at least the "prot"
1121 protection permissions by examining the underlying segments.
1122
1123 Really this is a very stupid algorithm and we could do much
1124 better by iterating through the segment array instead of through
1125 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001126 */
sewardjb5f6f512005-03-10 23:59:00 +00001127Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001128{
sewardjb5f6f512005-03-10 23:59:00 +00001129 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001130
sewardjb5f6f512005-03-10 23:59:00 +00001131 if ((p + size) < p)
1132 return False; /* reject wraparounds */
1133 if (size == 0)
1134 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001135
sewardjb5f6f512005-03-10 23:59:00 +00001136 p = PGROUNDDN(p);
1137 size = PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001138 vg_assert(VG_IS_PAGE_ALIGNED(p));
1139 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001140
sewardjb5f6f512005-03-10 23:59:00 +00001141 for (; size > 0; size -= VKI_PAGE_SIZE) {
1142 seg = VG_(find_segment)(p);
1143 if (!seg)
1144 return False;
1145 if ((seg->prot & prot) != prot)
1146 return False;
1147 p += VKI_PAGE_SIZE;
1148 }
jsgf855d93d2003-10-13 22:26:55 +00001149
sewardjb5f6f512005-03-10 23:59:00 +00001150 return True;
jsgf855d93d2003-10-13 22:26:55 +00001151}
1152
sewardjb5f6f512005-03-10 23:59:00 +00001153
sewardjde4a1d02002-03-22 01:27:54 +00001154/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001155/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001156/*--------------------------------------------------------------------*/
1157
nethercote57e36b32004-07-10 14:56:28 +00001158// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001159Addr VG_(get_memory_from_mmap_for_client)
1160 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001161{
1162 len = PGROUNDUP(len);
1163
njnca82cc02004-11-22 17:18:48 +00001164 tl_assert(!(sf_flags & SF_FIXED));
1165 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001166
nethercote8e9eab02004-07-11 18:01:06 +00001167 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1168 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1169 sf_flags | SF_CORE, -1, 0);
1170 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001171 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001172 else
1173 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001174}
1175
fitzhardinge98abfc72003-12-16 02:05:15 +00001176
njn86f12dc2005-03-14 01:16:05 +00001177/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001178 range, which isn't SF_CORE, a root.
1179*/
njn86f12dc2005-03-14 01:16:05 +00001180void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1181{
sewardj882af5f2005-03-16 12:27:53 +00001182 Int i;
1183 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001184 Segment *s;
1185
sewardj882af5f2005-03-16 12:27:53 +00001186 for (i = 0; i < segments_used; i++) {
1187 s = &segments[i];
1188 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1189 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001190 if (flags != SF_MMAP && flags != SF_STACK)
1191 continue;
sewardj882af5f2005-03-16 12:27:53 +00001192 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1193 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001194 continue;
1195 if (!VG_(is_client_addr)(s->addr) ||
1196 !VG_(is_client_addr)(s->addr+s->len))
1197 continue;
1198
1199 (*add_rootrange)(s->addr, s->len);
1200 }
njn86f12dc2005-03-14 01:16:05 +00001201}
1202
1203
nethercote88a90162004-07-10 16:59:25 +00001204/*--------------------------------------------------------------------*/
1205/*--- Querying memory layout ---*/
1206/*--------------------------------------------------------------------*/
1207
fitzhardinge98abfc72003-12-16 02:05:15 +00001208Bool VG_(is_client_addr)(Addr a)
1209{
1210 return a >= VG_(client_base) && a < VG_(client_end);
1211}
1212
1213Bool VG_(is_shadow_addr)(Addr a)
1214{
1215 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1216}
1217
fitzhardinge98abfc72003-12-16 02:05:15 +00001218Addr VG_(get_shadow_size)(void)
1219{
1220 return VG_(shadow_end)-VG_(shadow_base);
1221}
1222
sewardjfa8202f2005-04-24 11:05:55 +00001223
nethercote88a90162004-07-10 16:59:25 +00001224/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001225/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001226/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001227
1228void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1229{
sewardj548be6d2005-02-16 01:31:37 +00001230vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001231 if (0)
1232 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1233
1234 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001235 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001236
1237 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1238 p = PGROUNDDN(p);
1239
1240 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1241
1242 if (call_init)
1243 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001244 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001245 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1246
nethercote73b526f2004-10-31 18:48:21 +00001247 p += VKI_PAGE_SIZE;
1248 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001249 }
1250}
1251
1252void *VG_(shadow_alloc)(UInt size)
1253{
1254 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001255 Addr try_here;
1256 Int r;
1257
1258 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001259
1260 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001261 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001262
1263 size = PGROUNDUP(size);
1264
1265 if (shadow_alloc == 0)
1266 shadow_alloc = VG_(shadow_base);
1267
1268 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001269 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001270
sewardj79048ce2005-02-18 08:28:32 +00001271 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001272 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1273 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001274 vg_assert(size > 0);
1275
1276 if (0)
1277 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1278
1279 /* this is big-bang allocated, so we don't expect to find a listed
1280 segment for it. */
1281 /* This is really an absolute disgrace. Sometimes the big-bang
1282 mapping is in the list (due to re-reads of /proc/self/maps,
1283 presumably) and sometimes it isn't. */
1284#if 0
1285 r = find_segment(try_here);
1286 vg_assert(r == -1);
1287 r = find_segment(try_here+size-1);
1288 vg_assert(r == -1);
1289#endif
1290
1291 r = VG_(mprotect_native)( (void*)try_here,
1292 size, VKI_PROT_READ|VKI_PROT_WRITE );
1293
1294 if (r != 0)
1295 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001296
1297 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001298 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001299
sewardj79048ce2005-02-18 08:28:32 +00001300 failed:
1301 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001302 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001303 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001304 size
sewardj79048ce2005-02-18 08:28:32 +00001305 );
1306 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001307}
1308
1309/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001310/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001311/*--------------------------------------------------------------------*/