blob: 797aec7a18ea46f367f81eaf316bcd7b4d889d8e [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/*--------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +000048/*--- Basic globals about the address space. ---*/
49/*--------------------------------------------------------------*/
50
51/* Client address space, lowest to highest (see top of ume.c) */
52Addr VG_(client_base); /* client address space limits */
53Addr VG_(client_end);
54Addr VG_(client_mapbase);
55Addr VG_(client_trampoline_code);
56Addr VG_(clstk_base);
57Addr VG_(clstk_end);
58
59Addr VG_(brk_base); /* start of brk */
60Addr VG_(brk_limit); /* current brk */
61
62Addr VG_(shadow_base); /* tool's shadow memory */
63Addr VG_(shadow_end);
64
65Addr VG_(valgrind_base); /* valgrind's address range */
66
67// Note that VG_(valgrind_last) names the last byte of the section, whereas
68// the VG_(*_end) vars name the byte one past the end of the section.
69Addr VG_(valgrind_last);
70
71/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000072/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000073/*--------------------------------------------------------------*/
74
sewardj79048ce2005-02-18 08:28:32 +000075/* Max number of segments we can track. */
76#define VG_N_SEGMENTS 1000
77
78/* Max number of segment file names we can track. */
79#define VG_N_SEGNAMES 200
80
81/* Max length of a segment file name. */
82#define VG_MAX_SEGNAMELEN 1000
83
84
85/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000086
87/* Array [0 .. segments_used-1] of all mappings. */
88/* Sorted by .addr field. */
89/* I: len may not be zero. */
90/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000091/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000092
93static Segment segments[VG_N_SEGMENTS];
94static Int segments_used = 0;
95
sewardj79048ce2005-02-18 08:28:32 +000096typedef
97 struct {
98 Bool inUse;
99 Bool mark;
100 HChar fname[VG_MAX_SEGNAMELEN];
101 }
102 SegName;
103
104/* Filename table. _used is the high water mark; an entry is only
105 valid if its index >= 0, < _used, and its .inUse field == True.
106 The .mark field is used to garbage-collect dead entries.
107*/
108static SegName segnames[VG_N_SEGNAMES];
109static Int segnames_used = 0;
110
111
112/* ------ end of STATE for the address-space manager ------ */
113
114
115/* Searches the filename table to find an index for the given name.
116 If none is found, an index is allocated and the name stored. If no
117 space is available we just give up. If the string is too long to
118 store, return -1.
119*/
120static Int allocate_segname ( const HChar* name )
121{
122 Int i, j, len;
123
124 vg_assert(name);
125
126 if (0) VG_(printf)("alloc_segname %s\n", name);
127
128 len = VG_(strlen)(name);
129 if (len >= VG_MAX_SEGNAMELEN-1) {
130 return -1;
131 }
132
133 /* first see if we already have the name. */
134 for (i = 0; i < segnames_used; i++) {
135 if (!segnames[i].inUse)
136 continue;
137 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
138 return i;
139 }
140 }
141
142 /* no we don't. So look for a free slot. */
143 for (i = 0; i < segnames_used; i++)
144 if (!segnames[i].inUse)
145 break;
146
147 if (i == segnames_used) {
148 /* no free slots .. advance the high-water mark. */
149 if (segnames_used+1 < VG_N_SEGNAMES) {
150 i = segnames_used;
151 segnames_used++;
152 } else {
153 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000154 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000155 " VG_N_SEGNAMES is too small: "
156 "increase it and rebuild Valgrind.\n"
157 );
158 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000159 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000160 " giving up now.\n\n"
161 );
162 VG_(exit)(0);
163 }
164 }
165
166 /* copy it in */
167 segnames[i].inUse = True;
168 for (j = 0; j < len; j++)
169 segnames[i].fname[j] = name[j];
170 vg_assert(len < VG_MAX_SEGNAMELEN);
171 segnames[i].fname[len] = 0;
172 return i;
173}
174
sewardj548be6d2005-02-16 01:31:37 +0000175
176/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
177 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000178 seg.
179*/
sewardj548be6d2005-02-16 01:31:37 +0000180static Int compare_addr_with_seg ( Addr a, Segment* seg )
181{
182 if (a < seg->addr)
183 return -1;
184 if (a >= seg->addr + seg->len)
185 return 1;
186 return 0;
187}
188
sewardj79048ce2005-02-18 08:28:32 +0000189
sewardj548be6d2005-02-16 01:31:37 +0000190/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000191 none.
192*/
sewardj548be6d2005-02-16 01:31:37 +0000193static Int find_segment ( Addr a )
194{
195 Int i;
196 for (i = 0; i < segments_used; i++) {
197 if (compare_addr_with_seg(a, &segments[i]) == 0)
198 return i;
199 }
200 return -1;
201}
202
203
204/* Assumes that 'a' is not in any segment. Finds the index of the
205 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
206 which is in fact in a segment is a checked error.
207*/
208static Int find_segment_above_unmapped ( Addr a )
209{
210 Int i, r;
211 for (i = 0; i < segments_used; i++) {
212 r = compare_addr_with_seg(a, &segments[i]);
213 vg_assert(r != 0); /* 'a' should not be in any segment. */
214 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000215 continue;
sewardj548be6d2005-02-16 01:31:37 +0000216 vg_assert(r == -1);
217 break;
218 }
219
220 if (i == segments_used)
221 return -1; /* not found */
222 else
223 return i;
224}
225
226
227/* Assumes that 'a' is in some segment. Finds the next segment along,
228 or NULL if none. Passing 'a' which is in fact not in a segment is
229 a checked error.
230*/
231static Int find_segment_above_mapped ( Addr a )
232{
233 Int i, r;
234 for (i = 0; i < segments_used; i++) {
235 r = compare_addr_with_seg(a, &segments[i]);
236 if (r == 1)
237 continue; /* not yet there */
238 if (r == 0)
239 break; /* found it */
240 vg_assert(0);
241 /* we shouldn't get here -- r == -1 and so it means we went past
242 'a' without seeing it -- it is therefore unmapped. */
243 /*NOTREACHED*/
244 }
245
246 vg_assert(i < segments_used);
247 if (i == segments_used-1)
248 return -1; /* not found */
249 else
250 return i+1;
251}
252
253
254/* Shift segments[i .. segments_used-1] up by one. */
255static void make_space_at ( Int i )
256{
257 Int j;
258 vg_assert(i >= 0 && i <= segments_used);
259 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000260 if (segments_used+1 == VG_N_SEGMENTS) {
261 VG_(printf)(
262 "coregrind/vg_memory.c:\n"
263 " VG_N_SEGMENTS is too small: "
264 "increase it and rebuild Valgrind.\n"
265 );
266 VG_(printf)(
267 "coregrind/vg_memory.c:\n"
268 " giving up now.\n\n"
269 );
270 VG_(exit)(0);
271 }
sewardj548be6d2005-02-16 01:31:37 +0000272 vg_assert(segments_used+1 < VG_N_SEGMENTS);
273 for (j = segments_used; j > i; j--)
274 segments[j] = segments[j-1];
275 segments_used++;
276}
277
sewardj79048ce2005-02-18 08:28:32 +0000278
sewardj548be6d2005-02-16 01:31:37 +0000279/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000280 segments_used.
281*/
sewardj548be6d2005-02-16 01:31:37 +0000282static void delete_segment_at ( Int i )
283{
284 Int j;
285 vg_assert(i >= 0 && i < segments_used);
286 for (j = i+1; j < segments_used; j++)
287 segments[j-1] = segments[j];
288 segments_used--;
289 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
290}
291
292
293/* Fill the i'th record all with zeroes. */
294static void zeroise_segment ( Int i )
295{
296 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000297 segments[i].prot = 0;
298 segments[i].flags = 0;
299 segments[i].addr = 0;
300 segments[i].len = 0;
301 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000302 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000303 segments[i].fnIdx = -1;
304 segments[i].dev = 0;
305 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000306 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000307}
308
sewardj79048ce2005-02-18 08:28:32 +0000309
sewardj548be6d2005-02-16 01:31:37 +0000310/* Create a segment to contain 'a', and return its index. Or -1 if
311 this failed because some other segment already contains 'a'. If
312 successful, fill in the segment's .addr field with 'a' but leave
313 all other fields alone.
314*/
315static Int create_segment ( Addr a )
316{
317 Int i, r;
318 for (i = 0; i < segments_used; i++) {
319 r = compare_addr_with_seg( a, &segments[i] );
320 if (r == 1)
321 continue; /* seg[i] precedes a */
322 if (r == 0)
323 return -1; /* seg[i] contains a. Give up */
324 vg_assert(r == -1);
325 break;
326 }
327 /* a precedes seg[i]. Shift segs at i and above up one, and use
328 this slot. */
329 make_space_at(i);
330 zeroise_segment(i);
331 segments[i].addr = a;
332 return i;
333}
334
sewardj79048ce2005-02-18 08:28:32 +0000335
336/* Print out the segment array (debugging only!). Note, this calls
337 VG_(printf), and I'm not 100% clear that that wouldn't require
338 dynamic memory allocation and hence more segments to be allocated.
339*/
340static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000341{
sewardj79048ce2005-02-18 08:28:32 +0000342 Int i;
343 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
344 who, segments_used, segnames_used);
345 for (i = 0; i < segnames_used; i++) {
346 if (!segnames[i].inUse)
347 continue;
348 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
349 }
350 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000351 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000352 "%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 +0000353 i,
sewardj79048ce2005-02-18 08:28:32 +0000354 segments[i].addr, segments[i].addr + segments[i].len,
355 (ULong)segments[i].len, segments[i].prot,
356 segments[i].flags, segments[i].dev, segments[i].ino,
357 (Long)segments[i].offset,
358 segments[i].fnIdx);
359 }
360 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000361}
sewardj79048ce2005-02-18 08:28:32 +0000362
sewardj548be6d2005-02-16 01:31:37 +0000363
364/* Find the segment containing 'a' and split it into two pieces at
365 'a'. Does nothing if no segment contains 'a', or if the split
366 would cause either of the pieces to have zero size.
367
368 If 'a' is not found, or if no splitting happens, -1 is returned.
369
370 If a value 'r' other than -1 is returned, this is the index of the
371 higher-addressed segment resulting from the split, and the index of
372 the lower-addressed segment is r-1.
373*/
374static Int split_segment ( Addr a )
375{
376 Int r;
377 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000378 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000379 r = find_segment(a);
380 if (r == -1)
381 /* not found */
382 return -1;
383 if (segments[r].addr == a)
384 /* segment starts at 'a', so splitting it would create a
385 zero-sized segment */
386 return -1;
387
388 /* copy original; make adjustments. */
389 vg_assert(a > segments[r].addr);
390 delta = a - segments[r].addr;
391 make_space_at(r);
392 segments[r] = segments[r+1];
393 segments[r].len = delta;
394 segments[r+1].len -= delta;
395 segments[r+1].addr += delta;
396 segments[r+1].offset += delta;
397 return r+1;
398}
399
sewardj79048ce2005-02-18 08:28:32 +0000400
401/* Return true if two segments are adjacent and mergable (s1 is
402 assumed to have a lower ->addr than s2) */
403static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
404{
405 if (s1->addr+s1->len != s2->addr)
406 return False;
407
408 if (s1->flags != s2->flags)
409 return False;
410
411 if (s1->prot != s2->prot)
412 return False;
413
njn36ef6ba2005-05-14 18:42:26 +0000414 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000415 return False;
416
417 if (s1->flags & SF_FILE){
418 if ((s1->offset + s1->len) != s2->offset)
419 return False;
420 if (s1->dev != s2->dev)
421 return False;
422 if (s1->ino != s2->ino)
423 return False;
424 if (s1->fnIdx != s2->fnIdx)
425 return False;
426 }
427
428 return True;
429}
430
431
432/* Clean up and sanity check the segment array:
433 - check segments are in ascending order
434 - check segments do not overlap
435 - check no segment has zero size
436 - merge adjacent where possible
437 - perform checks on the filename table, and reclaim dead entries
438*/
439static void preen_segments ( void )
440{
441 Int i, j, rd, wr;
442 Segment *s, *s1;
443 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
444 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
445
446 if (0) show_segments("before preen");
447
448 /* clear string table mark bits */
449 for (i = 0; i < segnames_used; i++)
450 segnames[i].mark = False;
451
452 /* check for non-zero size, and set mark bits for any used strings */
453 for (i = 0; i < segments_used; i++) {
454 vg_assert(segments[i].len > 0);
455 j = segments[i].fnIdx;
456 vg_assert(j >= -1 && j < segnames_used);
457 if (j >= 0) {
458 vg_assert(segnames[j].inUse);
459 segnames[j].mark = True;
460 }
461 }
462
463 /* check ascendingness and non-overlap */
464 for (i = 0; i < segments_used-1; i++) {
465 s = &segments[i];
466 s1 = &segments[i+1];
467 vg_assert(s->addr < s1->addr);
468 vg_assert(s->addr + s->len <= s1->addr);
469 }
470
471 /* merge */
472 if (segments_used < 1)
473 return;
474
475 wr = 1;
476 for (rd = 1; rd < segments_used; rd++) {
477 s = &segments[wr-1];
478 s1 = &segments[rd];
479 if (segments_are_mergeable(s,s1)) {
480 if (0)
481 VG_(printf)("merge %p-%p with %p-%p\n",
482 s->addr, s->addr+s->len,
483 s1->addr, s1->addr+s1->len);
484 s->len += s1->len;
485 continue;
486 }
487 if (wr < rd)
488 segments[wr] = segments[rd];
489 wr++;
490 }
491 vg_assert(wr >= 0 && wr <= segments_used);
492 segments_used = wr;
493
494 /* Free up any strings which are no longer referenced. */
495 for (i = 0; i < segnames_used; i++) {
496 if (segnames[i].mark == False) {
497 segnames[i].inUse = False;
498 segnames[i].fname[0] = 0;
499 }
500 }
501
502 if (0) show_segments("after preen");
503}
504
505
sewardj548be6d2005-02-16 01:31:37 +0000506/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000507/*--- Maintain an ordered list of all the client's mappings ---*/
508/*--------------------------------------------------------------*/
509
nethercote8991d5a2004-11-03 17:07:46 +0000510Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000511{
512 Addr se = s->addr+s->len;
513 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000514 vg_assert(pe >= p);
515
516 return (p >= s->addr && pe <= se);
517}
518
nethercote8991d5a2004-11-03 17:07:46 +0000519Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000520{
521 Addr se = s->addr+s->len;
522 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000523 vg_assert(pe >= p);
524
525 return (p < se && pe > s->addr);
526}
527
sewardj1024cf72005-02-28 14:39:21 +0000528#if 0
529/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000530/* Prepare a Segment structure for recycling by freeing everything
531 hanging off it. */
532static void recycleseg(Segment *s)
533{
534 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000535 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000536
537 if (s->filename != NULL)
538 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
539
540 /* keep the SegInfo, if any - it probably still applies */
541}
542
543/* When freeing a Segment, also clean up every one else's ideas of
544 what was going on in that range of memory */
545static void freeseg(Segment *s)
546{
547 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000548 if (s->seginfo != NULL) {
549 VG_(seginfo_decref)(s->seginfo, s->addr);
550 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000551 }
552
553 VG_(SkipNode_Free)(&sk_segments, s);
554}
sewardj1024cf72005-02-28 14:39:21 +0000555#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000556
sewardj1024cf72005-02-28 14:39:21 +0000557
558/* Get rid of any translations arising from s. */
559/* Note, this is not really the job of the low level memory manager.
560 When it comes time to rewrite this subsystem, clean this up. */
561static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000562{
sewardj1024cf72005-02-28 14:39:21 +0000563 if (s->flags & SF_CODE) {
564 VG_(discard_translations)(s->addr, s->len);
565 if (0)
566 VG_(printf)("dumping translations in %p .. %p\n",
567 s->addr, s->addr+s->len);
568 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000569}
570
sewardj1024cf72005-02-28 14:39:21 +0000571
fitzhardinge98abfc72003-12-16 02:05:15 +0000572/* This unmaps all the segments in the range [addr, addr+len); any
573 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000574void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000575{
fitzhardingee3632c62003-12-22 10:58:06 +0000576 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000577 Segment* s;
578 Addr end, s_end;
579 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000580 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000581
582 if (len == 0)
583 return;
584
fitzhardinge1a4adf02003-12-22 10:42:59 +0000585 len = PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000586
fitzhardinge98abfc72003-12-16 02:05:15 +0000587 if (debug)
tom9be7c982005-04-25 16:55:44 +0000588 VG_(printf)("unmap_range(%p, %lu)\n", addr, len);
sewardj79048ce2005-02-18 08:28:32 +0000589 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000590 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000591
592 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000593 vg_assert(VG_IS_PAGE_ALIGNED(addr));
594 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000595
sewardj548be6d2005-02-16 01:31:37 +0000596 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000597
598 /* do not delete .. even though it looks stupid */
599 vg_assert(i >= 0);
600
601 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000602 s = &segments[i];
603 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000604
sewardj548be6d2005-02-16 01:31:37 +0000605 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000606 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000607 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000608
fitzhardinge1a303042003-12-22 08:48:50 +0000609 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000610 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000611 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000612 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000613 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000614
615 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000616 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000617 addr < s_end &&
618 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000619 /* this segment's tail is truncated by [addr, addr+len)
620 -> truncate tail
621 */
sewardj1024cf72005-02-28 14:39:21 +0000622 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000623 s->len = addr - s->addr;
624
625 if (debug)
tom9be7c982005-04-25 16:55:44 +0000626 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000627 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000628 /* this segment's head is truncated by [addr, addr+len)
629 -> truncate head
630 */
sewardj548be6d2005-02-16 01:31:37 +0000631 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000632
633 if (debug)
tom9be7c982005-04-25 16:55:44 +0000634 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000635 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000636
sewardj1024cf72005-02-28 14:39:21 +0000637 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000638 s->addr += delta;
639 s->offset += delta;
640 s->len -= delta;
641
642 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000643 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000644 /* this segment is completely contained within [addr, addr+len)
645 -> delete segment
646 */
sewardj1024cf72005-02-28 14:39:21 +0000647 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000648 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000649 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000650
651 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000652 VG_(printf)(" case 3: seg %d deleted\n", i);
653 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000654 /* [addr, addr+len) is contained within a single segment
655 -> split segment into 3, delete middle portion
656 */
sewardj1024cf72005-02-28 14:39:21 +0000657 Int i_middle;
658 dump_translations_from(s);
659 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000660 vg_assert(i_middle != -1);
661 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000662 vg_assert(segments[i_middle].addr == addr);
663 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000664 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000665
666 if (debug)
667 VG_(printf)(" case 4: subrange %p-%p deleted\n",
668 addr, addr+len);
669 }
sewardj47c98a72005-03-12 20:36:15 +0000670
671 /* If we deleted this segment (or any above), those above will
672 have been moved down to fill in the hole in the segment
673 array. In order that we don't miss them, we have to
674 re-consider this slot number; hence the i--. */
675 if (deleted)
676 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000677 }
sewardj79048ce2005-02-18 08:28:32 +0000678 preen_segments();
679 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000680}
681
sewardj548be6d2005-02-16 01:31:37 +0000682
683/* Add a binding of [addr,addr+len) to
684 (prot,flags,dev,ino,off,filename) in the segment array.
685 Delete/truncate any previous mapping(s) covering that range.
686*/
687void
688VG_(map_file_segment)( Addr addr, SizeT len,
689 UInt prot, UInt flags,
690 UInt dev, UInt ino, ULong off,
691 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000692{
fitzhardinge98abfc72003-12-16 02:05:15 +0000693 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000694 Segment* s;
695 Int idx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000696
697 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000698 VG_(printf)(
699 "\n"
tom9be7c982005-04-25 16:55:44 +0000700 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000701 " dev=0x%4x ino=%d off=%ld\n"
702 " filename='%s')\n",
703 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000704
705 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000706 vg_assert(VG_IS_PAGE_ALIGNED(addr));
fitzhardinge98abfc72003-12-16 02:05:15 +0000707 len = PGROUNDUP(len);
708
sewardj548be6d2005-02-16 01:31:37 +0000709 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
710 VG_(unmap_range)(addr, len);
711
712 /* and now install this one */
713 idx = create_segment(addr);
714 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
715 vg_assert(idx != -1);
716 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000717
sewardj79048ce2005-02-18 08:28:32 +0000718 s = &segments[idx];
719 vg_assert(s->addr == addr);
720 s->prot = prot;
721 s->flags = flags;
722 s->len = len;
723 s->offset = off;
724 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
725 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
726 s->dev = dev;
727 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000728 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000729
sewardj79048ce2005-02-18 08:28:32 +0000730 /* Clean up right now */
731 preen_segments();
732 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000733
734 /* If this mapping is of the beginning of a file, isn't part of
735 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000736 file, then try reading symbols from it.
737 */
njn36ef6ba2005-05-14 18:42:26 +0000738 if (s->seginfo == NULL
sewardjb71816c2005-03-14 19:11:10 +0000739 && (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
sewardj79048ce2005-02-18 08:28:32 +0000740 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
741 if (off == 0
742 && s->fnIdx != -1
743 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
744 && len >= VKI_PAGE_SIZE
745 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000746 s->seginfo = VG_(read_seg_symbols)(s);
747 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000748 s->flags |= SF_DYNLIB;
749 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000750 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000751#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000752 const SegInfo *info;
753
njn36ef6ba2005-05-14 18:42:26 +0000754 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000755 for(info = VG_(next_seginfo)(NULL);
756 info != NULL;
757 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000758 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
759 {
njn36ef6ba2005-05-14 18:42:26 +0000760 s->seginfo = (SegInfo *)info;
761 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000762 }
763 }
sewardj79048ce2005-02-18 08:28:32 +0000764#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000765 }
766 }
767
768 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000769 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000770}
771
nethercote8b5f40c2004-11-02 13:29:50 +0000772void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000773 Int fd, ULong off, const Char *filename)
774{
775 struct vki_stat st;
776 Char *name = NULL;
777
778 st.st_dev = 0;
779 st.st_ino = 0;
780
781 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000782 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000783
784 if (VG_(fstat)(fd, &st) < 0)
785 flags &= ~SF_FILE;
786 }
787
sewardj79048ce2005-02-18 08:28:32 +0000788 if ((flags & SF_FILE) && filename == NULL && fd != -1)
789 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000790
791 if (filename == NULL)
792 filename = name;
793
sewardj79048ce2005-02-18 08:28:32 +0000794 VG_(map_file_segment)(addr, len, prot, flags,
795 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000796}
797
nethercote8b5f40c2004-11-02 13:29:50 +0000798void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000799{
800 flags &= ~SF_FILE;
801
802 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
803}
804
805/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000806void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000807{
sewardj79048ce2005-02-18 08:28:32 +0000808 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000809 static const Bool debug = False || mem_debug;
810
811 if (debug)
tom9be7c982005-04-25 16:55:44 +0000812 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000813
814 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000815
816 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000817 vg_assert(VG_IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000818 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000819
sewardj79048ce2005-02-18 08:28:32 +0000820 split_segment(a);
821 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000822
sewardj548be6d2005-02-16 01:31:37 +0000823 r = find_segment(a);
824 vg_assert(r != -1);
825 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000826
827 preen_segments();
828
sewardje517b802005-02-16 01:58:51 +0000829 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000830}
831
sewardj79048ce2005-02-18 08:28:32 +0000832
sewardj548be6d2005-02-16 01:31:37 +0000833/* Try to find a map space for [addr,addr+len). If addr==0, it means
834 the caller is prepared to accept a space at any location; if not,
835 we will try for addr, but fail if we can't get it. This mimics
836 mmap fixed vs mmap not-fixed.
837*/
nethercote8b5f40c2004-11-02 13:29:50 +0000838Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000839{
fitzhardingee3632c62003-12-22 10:58:06 +0000840 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000841 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000842 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000843 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
844 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000845 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
846 Int i, i_any, i_fixed, i_final;
847 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000848
sewardj548be6d2005-02-16 01:31:37 +0000849 Bool fixed;
850
sewardje517b802005-02-16 01:58:51 +0000851 if (debug) {
852 VG_(printf)("\n\n");
tom9be7c982005-04-25 16:55:44 +0000853 VG_(printf)("find_map_space(%p, %lu, %d) ...\n",
sewardje517b802005-02-16 01:58:51 +0000854 addr, len, for_client);
855 }
856
857 if (0) show_segments("find_map_space: start");
858
sewardj548be6d2005-02-16 01:31:37 +0000859 if (addr == 0) {
860 fixed = False;
861 } else {
862 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000863 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000864 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000865 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000866 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000867
868 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000869 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000870 len = PGROUNDUP(len);
871
nethercote73b526f2004-10-31 18:48:21 +0000872 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000873
sewardj548be6d2005-02-16 01:31:37 +0000874 /* Scan the segment list, looking for a hole which satisfies the
875 requirements. At each point i we ask the question "can we use
876 the hole in between segments[i-1] and segments[i] ?" */
877 i_any = i_fixed = -1;
878 hstart_any = hstart_fixed = 0;
879
880 hole_start = hole_end = 0;
881
882 /* Iterate over all possible holes, generating them into
883 hole_start/hole_end. Filter out invalid ones. Then see if any
884 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
885 */
886 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
887 if (i == 0) {
888 hole_start = 0;
889 hole_end = segments[0].addr-1;
890 }
891 else {
892 vg_assert(segments_used > 0);
893 if (i == segments_used) {
894 hole_start = segments[i-1].addr + segments[i-1].len;
895 hole_end = ~(Addr)0;
896 } else {
897 hole_start = segments[i-1].addr + segments[i-1].len;
898 hole_end = segments[i].addr - 1;
899 }
900 }
901
902 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
903
904 /* ignore zero-sized holes */
905 if (hole_start == hole_end+1)
906 continue;
907
njnbe91aae2005-03-27 01:42:41 +0000908 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
909 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000910
911 /* ignore holes which fall outside the allowable area */
912 if (!(hole_start >= base && hole_end <= limit))
913 continue;
914
915 vg_assert(hole_end > hole_start);
916 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000917 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000918
919 if (hole_len >= len && i_any == -1) {
920 /* It will at least fit in this hole. */
921 i_any = i;
922 hstart_any = hole_start;
923 }
924
sewardjb5f6f512005-03-10 23:59:00 +0000925 if (fixed && hole_start <= addr
926 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000927 /* We were asked for a fixed mapping, and this hole works.
928 Bag it -- and stop searching as further searching is
929 pointless. */
930 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000931 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000932 break;
933 }
934 }
935
936 /* Summarise the final decision into i_final/hstart_final. */
937 i_final = -1;
938 hstart_final = 0;
939
940 if (fixed) {
941 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000942 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000943 } else {
944 i_final = i_any;
945 hstart_final = hstart_any;
946 }
947
948
949 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000950 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000951 else
952 ret = 0; /* not found */
953
954 if (debug)
tom9be7c982005-04-25 16:55:44 +0000955 VG_(printf)("find_map_space(%p, %lu, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000956 addr, len, for_client, ret);
957
sewardjb5f6f512005-03-10 23:59:00 +0000958 if (fixed) {
959 vg_assert(ret == 0 || ret == addrOrig);
960 }
961
sewardj548be6d2005-02-16 01:31:37 +0000962 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000963}
964
sewardj79048ce2005-02-18 08:28:32 +0000965
sewardjb5f6f512005-03-10 23:59:00 +0000966/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000967 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000968 mapping over any part of the address space which is not covered
969 by an entry in the segment list.
970
971 This is designed for use around system calls which allocate
972 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000973 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000974 address with VG_(find_map_space) and then adding a segment for
975 it and padding the address space valgrind can ensure that the
976 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000977void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000978{
sewardj394790d2005-03-17 02:14:44 +0000979 Addr addr = (start == 0) ? VG_(client_base) : start;
njn7df470b2005-05-29 18:46:38 +0000980 void* ret;
sewardj394790d2005-03-17 02:14:44 +0000981
982 Int i = 0;
983 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000984
nethercote820bd8c2004-09-07 23:04:49 +0000985 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000986 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +0000987 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +0000988 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
989 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000990 }
thughes9aaebc32004-07-15 23:13:37 +0000991 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000992 i++;
993 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000994 }
995
nethercote820bd8c2004-09-07 23:04:49 +0000996 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +0000997 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +0000998 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
999 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001000 }
thughes9aaebc32004-07-15 23:13:37 +00001001}
1002
thughesc70b8c62004-07-16 23:07:58 +00001003/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001004 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001005void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001006{
sewardj394790d2005-03-17 02:14:44 +00001007 Addr addr = (start == 0) ? VG_(client_base) : start;
1008 Int ret;
1009
1010 Int i = 0;
1011 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001012
nethercote820bd8c2004-09-07 23:04:49 +00001013 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001014 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +00001015 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001016 }
thughes9aaebc32004-07-15 23:13:37 +00001017 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001018 i++;
1019 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001020 }
1021
nethercote820bd8c2004-09-07 23:04:49 +00001022 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001023 ret = VG_(do_syscall2)(__NR_munmap, addr,
1024 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001025 }
thughes9aaebc32004-07-15 23:13:37 +00001026}
1027
sewardj548be6d2005-02-16 01:31:37 +00001028/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001029Segment *VG_(find_segment)(Addr a)
1030{
sewardj548be6d2005-02-16 01:31:37 +00001031 Int r = find_segment(a);
1032 if (0) show_segments("find_segment");
1033 if (r == -1) return NULL;
1034 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001035}
1036
sewardj548be6d2005-02-16 01:31:37 +00001037/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1038 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1039 a segment is a checked error.
1040*/
1041Segment *VG_(find_segment_above_unmapped)(Addr a)
1042{
1043 Int r = find_segment_above_unmapped(a);
1044 if (0) show_segments("find_segment_above_unmapped");
1045 if (r == -1) return NULL;
1046 return &segments[r];
1047}
1048
1049/* Assumes that 'a' is in some segment. Finds the next segment along,
1050 or NULL if none. Passing 'a' which is in fact not in a segment is
1051 a checked error.
1052*/
1053Segment *VG_(find_segment_above_mapped)(Addr a)
1054{
1055 Int r = find_segment_above_mapped(a);
1056 if (0) show_segments("find_segment_above_mapped");
1057 if (r == -1) return NULL;
1058 return &segments[r];
1059}
1060
1061
sewardjde4a1d02002-03-22 01:27:54 +00001062/*------------------------------------------------------------*/
1063/*--- Tracking permissions around %esp changes. ---*/
1064/*------------------------------------------------------------*/
1065
1066/*
1067 The stack
1068 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001069 The stack's segment seems to be dynamically extended downwards by
1070 the kernel as the stack pointer moves down. Initially, a 1-page
1071 (4k) stack is allocated. When SP moves below that for the first
1072 time, presumably a page fault occurs. The kernel detects that the
njna60a7c12005-05-08 17:49:37 +00001073 faulting address is in the range from SP - VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001074 upwards to the current valid stack. It then extends the stack
1075 segment downwards for enough to cover the faulting address, and
1076 resumes the process (invisibly). The process is unaware of any of
1077 this.
sewardjde4a1d02002-03-22 01:27:54 +00001078
sewardjfa8202f2005-04-24 11:05:55 +00001079 That means that Valgrind can't spot when the stack segment is being
1080 extended. Fortunately, we want to precisely and continuously
1081 update stack permissions around SP, so we need to spot all writes
1082 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001083
sewardjfa8202f2005-04-24 11:05:55 +00001084 The deal is: when SP is assigned a lower value, the stack is being
1085 extended. Create suitably-permissioned pages to fill in any holes
1086 between the old stack ptr and this one, if necessary. Then mark
1087 all bytes in the area just "uncovered" by this SP change as
1088 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001089
sewardjfa8202f2005-04-24 11:05:55 +00001090 When SP goes back up, mark the area receded over as unreadable and
1091 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001092
njna60a7c12005-05-08 17:49:37 +00001093 Just to record the SP boundary conditions somewhere convenient:
1094 SP - VGA_STACK_REDZONE_SZB always points to the lowest live byte in
1095 the stack. All addresses below SP - VGA_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001096 live; those at and above it are.
1097
njna60a7c12005-05-08 17:49:37 +00001098 We do not concern ourselves here with the VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001099 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001100*/
1101
njn9b007f62003-04-07 14:40:25 +00001102/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001103 tracked by the tool, and one of the specialised cases
1104 (eg. new_mem_stack_4) isn't used in preference.
1105*/
njn9fb73db2005-03-27 01:55:21 +00001106VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001107void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001108{
sewardj97724e52005-04-02 23:40:59 +00001109 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001110 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001111
sewardj97724e52005-04-02 23:40:59 +00001112 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1113 /* SP has changed by more than some threshold amount (by
1114 default, 2MB). We take this to mean that the application is
1115 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001116
1117 JRS 20021001: following discussions with John Regehr, if a stack
1118 switch happens, it seems best not to mess at all with memory
1119 permissions. Seems to work well with Netscape 4.X. Really the
1120 only remaining difficulty is knowing exactly when a stack switch is
1121 happening. */
sewardj97724e52005-04-02 23:40:59 +00001122 if (VG_(clo_verbosity) > 0 && moans > 0) {
1123 moans--;
1124 VG_(message)(Vg_UserMsg,
1125 "Warning: client switching stacks? "
1126 "SP change: %p --> %p", old_SP, new_SP);
1127 VG_(message)(Vg_UserMsg,
1128 " to suppress, use: --max-stackframe=%d or greater",
1129 (delta < 0 ? -delta : delta));
1130 if (moans == 0)
1131 VG_(message)(Vg_UserMsg,
1132 " further instances of this message "
1133 "will not be shown.");
1134 }
njn9b007f62003-04-07 14:40:25 +00001135 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001136 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001137
njn9b007f62003-04-07 14:40:25 +00001138 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001139 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001140 }
1141}
1142
jsgf855d93d2003-10-13 22:26:55 +00001143/*
sewardjb5f6f512005-03-10 23:59:00 +00001144 Test if a piece of memory is addressable with at least the "prot"
1145 protection permissions by examining the underlying segments.
1146
1147 Really this is a very stupid algorithm and we could do much
1148 better by iterating through the segment array instead of through
1149 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001150 */
sewardjb5f6f512005-03-10 23:59:00 +00001151Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001152{
sewardjb5f6f512005-03-10 23:59:00 +00001153 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001154
sewardjb5f6f512005-03-10 23:59:00 +00001155 if ((p + size) < p)
1156 return False; /* reject wraparounds */
1157 if (size == 0)
1158 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001159
sewardjb5f6f512005-03-10 23:59:00 +00001160 p = PGROUNDDN(p);
1161 size = PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001162 vg_assert(VG_IS_PAGE_ALIGNED(p));
1163 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001164
sewardjb5f6f512005-03-10 23:59:00 +00001165 for (; size > 0; size -= VKI_PAGE_SIZE) {
1166 seg = VG_(find_segment)(p);
1167 if (!seg)
1168 return False;
1169 if ((seg->prot & prot) != prot)
1170 return False;
1171 p += VKI_PAGE_SIZE;
1172 }
jsgf855d93d2003-10-13 22:26:55 +00001173
sewardjb5f6f512005-03-10 23:59:00 +00001174 return True;
jsgf855d93d2003-10-13 22:26:55 +00001175}
1176
sewardjb5f6f512005-03-10 23:59:00 +00001177
sewardjde4a1d02002-03-22 01:27:54 +00001178/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001179/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001180/*--------------------------------------------------------------------*/
1181
nethercote57e36b32004-07-10 14:56:28 +00001182// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001183Addr VG_(get_memory_from_mmap_for_client)
1184 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001185{
1186 len = PGROUNDUP(len);
1187
njnca82cc02004-11-22 17:18:48 +00001188 tl_assert(!(sf_flags & SF_FIXED));
1189 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001190
nethercote8e9eab02004-07-11 18:01:06 +00001191 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1192 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1193 sf_flags | SF_CORE, -1, 0);
1194 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001195 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001196 else
1197 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001198}
1199
fitzhardinge98abfc72003-12-16 02:05:15 +00001200
njn86f12dc2005-03-14 01:16:05 +00001201/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001202 range, which isn't SF_CORE, a root.
1203*/
njn86f12dc2005-03-14 01:16:05 +00001204void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1205{
sewardj882af5f2005-03-16 12:27:53 +00001206 Int i;
1207 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001208 Segment *s;
1209
sewardj882af5f2005-03-16 12:27:53 +00001210 for (i = 0; i < segments_used; i++) {
1211 s = &segments[i];
1212 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1213 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001214 if (flags != SF_MMAP && flags != SF_STACK)
1215 continue;
sewardj882af5f2005-03-16 12:27:53 +00001216 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1217 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001218 continue;
1219 if (!VG_(is_client_addr)(s->addr) ||
1220 !VG_(is_client_addr)(s->addr+s->len))
1221 continue;
1222
1223 (*add_rootrange)(s->addr, s->len);
1224 }
njn86f12dc2005-03-14 01:16:05 +00001225}
1226
1227
nethercote88a90162004-07-10 16:59:25 +00001228/*--------------------------------------------------------------------*/
1229/*--- Querying memory layout ---*/
1230/*--------------------------------------------------------------------*/
1231
fitzhardinge98abfc72003-12-16 02:05:15 +00001232Bool VG_(is_client_addr)(Addr a)
1233{
1234 return a >= VG_(client_base) && a < VG_(client_end);
1235}
1236
1237Bool VG_(is_shadow_addr)(Addr a)
1238{
1239 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1240}
1241
fitzhardinge98abfc72003-12-16 02:05:15 +00001242Addr VG_(get_shadow_size)(void)
1243{
1244 return VG_(shadow_end)-VG_(shadow_base);
1245}
1246
sewardjfa8202f2005-04-24 11:05:55 +00001247
nethercote88a90162004-07-10 16:59:25 +00001248/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001249/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001250/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001251
1252void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1253{
sewardj548be6d2005-02-16 01:31:37 +00001254vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001255 if (0)
1256 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1257
1258 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001259 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001260
1261 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1262 p = PGROUNDDN(p);
1263
1264 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1265
1266 if (call_init)
1267 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001268 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001269 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1270
nethercote73b526f2004-10-31 18:48:21 +00001271 p += VKI_PAGE_SIZE;
1272 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001273 }
1274}
1275
1276void *VG_(shadow_alloc)(UInt size)
1277{
1278 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001279 Addr try_here;
1280 Int r;
1281
1282 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001283
1284 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001285 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001286
1287 size = PGROUNDUP(size);
1288
1289 if (shadow_alloc == 0)
1290 shadow_alloc = VG_(shadow_base);
1291
1292 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001293 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001294
sewardj79048ce2005-02-18 08:28:32 +00001295 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001296 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1297 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001298 vg_assert(size > 0);
1299
1300 if (0)
1301 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1302
1303 /* this is big-bang allocated, so we don't expect to find a listed
1304 segment for it. */
1305 /* This is really an absolute disgrace. Sometimes the big-bang
1306 mapping is in the list (due to re-reads of /proc/self/maps,
1307 presumably) and sometimes it isn't. */
1308#if 0
1309 r = find_segment(try_here);
1310 vg_assert(r == -1);
1311 r = find_segment(try_here+size-1);
1312 vg_assert(r == -1);
1313#endif
1314
1315 r = VG_(mprotect_native)( (void*)try_here,
1316 size, VKI_PROT_READ|VKI_PROT_WRITE );
1317
1318 if (r != 0)
1319 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001320
1321 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001322 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001323
sewardj79048ce2005-02-18 08:28:32 +00001324 failed:
1325 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001326 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001327 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001328 size
sewardj79048ce2005-02-18 08:28:32 +00001329 );
1330 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001331}
1332
1333/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001334/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001335/*--------------------------------------------------------------------*/