blob: 680c3decb0cb92bdd5dc03a6b0037c47736d5224 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00003/*--- Memory-related stuff: segment initialisation and tracking, ---*/
4/*--- stack operations ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005/*--- vg_memory.c ---*/
6/*--------------------------------------------------------------------*/
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"
sewardjde4a1d02002-03-22 01:27:54 +000034
sewardja4495682002-10-21 07:29:59 +000035/* Define to debug the memory-leak-detector. */
36/* #define VG_DEBUG_LEAKCHECK */
37
sewardje517b802005-02-16 01:58:51 +000038static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000039
sewardj79048ce2005-02-18 08:28:32 +000040#define IS_PAGE_ALIGNED(_aa) (((_aa) & (VKI_PAGE_SIZE-1)) == 0)
41
42
sewardj548be6d2005-02-16 01:31:37 +000043/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000044/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000045/*--------------------------------------------------------------*/
46
sewardj79048ce2005-02-18 08:28:32 +000047/* Max number of segments we can track. */
48#define VG_N_SEGMENTS 1000
49
50/* Max number of segment file names we can track. */
51#define VG_N_SEGNAMES 200
52
53/* Max length of a segment file name. */
54#define VG_MAX_SEGNAMELEN 1000
55
56
57/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000058
59/* Array [0 .. segments_used-1] of all mappings. */
60/* Sorted by .addr field. */
61/* I: len may not be zero. */
62/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000063/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000064
65static Segment segments[VG_N_SEGMENTS];
66static Int segments_used = 0;
67
sewardj79048ce2005-02-18 08:28:32 +000068typedef
69 struct {
70 Bool inUse;
71 Bool mark;
72 HChar fname[VG_MAX_SEGNAMELEN];
73 }
74 SegName;
75
76/* Filename table. _used is the high water mark; an entry is only
77 valid if its index >= 0, < _used, and its .inUse field == True.
78 The .mark field is used to garbage-collect dead entries.
79*/
80static SegName segnames[VG_N_SEGNAMES];
81static Int segnames_used = 0;
82
83
84/* ------ end of STATE for the address-space manager ------ */
85
86
87/* Searches the filename table to find an index for the given name.
88 If none is found, an index is allocated and the name stored. If no
89 space is available we just give up. If the string is too long to
90 store, return -1.
91*/
92static Int allocate_segname ( const HChar* name )
93{
94 Int i, j, len;
95
96 vg_assert(name);
97
98 if (0) VG_(printf)("alloc_segname %s\n", name);
99
100 len = VG_(strlen)(name);
101 if (len >= VG_MAX_SEGNAMELEN-1) {
102 return -1;
103 }
104
105 /* first see if we already have the name. */
106 for (i = 0; i < segnames_used; i++) {
107 if (!segnames[i].inUse)
108 continue;
109 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
110 return i;
111 }
112 }
113
114 /* no we don't. So look for a free slot. */
115 for (i = 0; i < segnames_used; i++)
116 if (!segnames[i].inUse)
117 break;
118
119 if (i == segnames_used) {
120 /* no free slots .. advance the high-water mark. */
121 if (segnames_used+1 < VG_N_SEGNAMES) {
122 i = segnames_used;
123 segnames_used++;
124 } else {
125 VG_(printf)(
126 "coregrind/vg_memory.c:\n"
127 " VG_N_SEGNAMES is too small: "
128 "increase it and rebuild Valgrind.\n"
129 );
130 VG_(printf)(
131 "coregrind/vg_memory.c:\n"
132 " giving up now.\n\n"
133 );
134 VG_(exit)(0);
135 }
136 }
137
138 /* copy it in */
139 segnames[i].inUse = True;
140 for (j = 0; j < len; j++)
141 segnames[i].fname[j] = name[j];
142 vg_assert(len < VG_MAX_SEGNAMELEN);
143 segnames[i].fname[len] = 0;
144 return i;
145}
146
sewardj548be6d2005-02-16 01:31:37 +0000147
148/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
149 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000150 seg.
151*/
sewardj548be6d2005-02-16 01:31:37 +0000152static Int compare_addr_with_seg ( Addr a, Segment* seg )
153{
154 if (a < seg->addr)
155 return -1;
156 if (a >= seg->addr + seg->len)
157 return 1;
158 return 0;
159}
160
sewardj79048ce2005-02-18 08:28:32 +0000161
sewardj548be6d2005-02-16 01:31:37 +0000162/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000163 none.
164*/
sewardj548be6d2005-02-16 01:31:37 +0000165static Int find_segment ( Addr a )
166{
167 Int i;
168 for (i = 0; i < segments_used; i++) {
169 if (compare_addr_with_seg(a, &segments[i]) == 0)
170 return i;
171 }
172 return -1;
173}
174
175
176/* Assumes that 'a' is not in any segment. Finds the index of the
177 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
178 which is in fact in a segment is a checked error.
179*/
180static Int find_segment_above_unmapped ( Addr a )
181{
182 Int i, r;
183 for (i = 0; i < segments_used; i++) {
184 r = compare_addr_with_seg(a, &segments[i]);
185 vg_assert(r != 0); /* 'a' should not be in any segment. */
186 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000187 continue;
sewardj548be6d2005-02-16 01:31:37 +0000188 vg_assert(r == -1);
189 break;
190 }
191
192 if (i == segments_used)
193 return -1; /* not found */
194 else
195 return i;
196}
197
198
199/* Assumes that 'a' is in some segment. Finds the next segment along,
200 or NULL if none. Passing 'a' which is in fact not in a segment is
201 a checked error.
202*/
203static Int find_segment_above_mapped ( Addr a )
204{
205 Int i, r;
206 for (i = 0; i < segments_used; i++) {
207 r = compare_addr_with_seg(a, &segments[i]);
208 if (r == 1)
209 continue; /* not yet there */
210 if (r == 0)
211 break; /* found it */
212 vg_assert(0);
213 /* we shouldn't get here -- r == -1 and so it means we went past
214 'a' without seeing it -- it is therefore unmapped. */
215 /*NOTREACHED*/
216 }
217
218 vg_assert(i < segments_used);
219 if (i == segments_used-1)
220 return -1; /* not found */
221 else
222 return i+1;
223}
224
225
226/* Shift segments[i .. segments_used-1] up by one. */
227static void make_space_at ( Int i )
228{
229 Int j;
230 vg_assert(i >= 0 && i <= segments_used);
231 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000232 if (segments_used+1 == VG_N_SEGMENTS) {
233 VG_(printf)(
234 "coregrind/vg_memory.c:\n"
235 " VG_N_SEGMENTS is too small: "
236 "increase it and rebuild Valgrind.\n"
237 );
238 VG_(printf)(
239 "coregrind/vg_memory.c:\n"
240 " giving up now.\n\n"
241 );
242 VG_(exit)(0);
243 }
sewardj548be6d2005-02-16 01:31:37 +0000244 vg_assert(segments_used+1 < VG_N_SEGMENTS);
245 for (j = segments_used; j > i; j--)
246 segments[j] = segments[j-1];
247 segments_used++;
248}
249
sewardj79048ce2005-02-18 08:28:32 +0000250
sewardj548be6d2005-02-16 01:31:37 +0000251/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000252 segments_used.
253*/
sewardj548be6d2005-02-16 01:31:37 +0000254static void delete_segment_at ( Int i )
255{
256 Int j;
257 vg_assert(i >= 0 && i < segments_used);
258 for (j = i+1; j < segments_used; j++)
259 segments[j-1] = segments[j];
260 segments_used--;
261 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
262}
263
264
265/* Fill the i'th record all with zeroes. */
266static void zeroise_segment ( Int i )
267{
268 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000269 segments[i].prot = 0;
270 segments[i].flags = 0;
271 segments[i].addr = 0;
272 segments[i].len = 0;
273 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000274 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000275 segments[i].fnIdx = -1;
276 segments[i].dev = 0;
277 segments[i].ino = 0;
278 segments[i].symtab = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000279}
280
sewardj79048ce2005-02-18 08:28:32 +0000281
sewardj548be6d2005-02-16 01:31:37 +0000282/* Create a segment to contain 'a', and return its index. Or -1 if
283 this failed because some other segment already contains 'a'. If
284 successful, fill in the segment's .addr field with 'a' but leave
285 all other fields alone.
286*/
287static Int create_segment ( Addr a )
288{
289 Int i, r;
290 for (i = 0; i < segments_used; i++) {
291 r = compare_addr_with_seg( a, &segments[i] );
292 if (r == 1)
293 continue; /* seg[i] precedes a */
294 if (r == 0)
295 return -1; /* seg[i] contains a. Give up */
296 vg_assert(r == -1);
297 break;
298 }
299 /* a precedes seg[i]. Shift segs at i and above up one, and use
300 this slot. */
301 make_space_at(i);
302 zeroise_segment(i);
303 segments[i].addr = a;
304 return i;
305}
306
sewardj79048ce2005-02-18 08:28:32 +0000307
308/* Print out the segment array (debugging only!). Note, this calls
309 VG_(printf), and I'm not 100% clear that that wouldn't require
310 dynamic memory allocation and hence more segments to be allocated.
311*/
312static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000313{
sewardj79048ce2005-02-18 08:28:32 +0000314 Int i;
315 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
316 who, segments_used, segnames_used);
317 for (i = 0; i < segnames_used; i++) {
318 if (!segnames[i].inUse)
319 continue;
320 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
321 }
322 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000323 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000324 "%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 +0000325 i,
sewardj79048ce2005-02-18 08:28:32 +0000326 segments[i].addr, segments[i].addr + segments[i].len,
327 (ULong)segments[i].len, segments[i].prot,
328 segments[i].flags, segments[i].dev, segments[i].ino,
329 (Long)segments[i].offset,
330 segments[i].fnIdx);
331 }
332 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000333}
sewardj79048ce2005-02-18 08:28:32 +0000334
sewardj548be6d2005-02-16 01:31:37 +0000335
336/* Find the segment containing 'a' and split it into two pieces at
337 'a'. Does nothing if no segment contains 'a', or if the split
338 would cause either of the pieces to have zero size.
339
340 If 'a' is not found, or if no splitting happens, -1 is returned.
341
342 If a value 'r' other than -1 is returned, this is the index of the
343 higher-addressed segment resulting from the split, and the index of
344 the lower-addressed segment is r-1.
345*/
346static Int split_segment ( Addr a )
347{
348 Int r;
349 HWord delta;
sewardj79048ce2005-02-18 08:28:32 +0000350 vg_assert(IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000351 r = find_segment(a);
352 if (r == -1)
353 /* not found */
354 return -1;
355 if (segments[r].addr == a)
356 /* segment starts at 'a', so splitting it would create a
357 zero-sized segment */
358 return -1;
359
360 /* copy original; make adjustments. */
361 vg_assert(a > segments[r].addr);
362 delta = a - segments[r].addr;
363 make_space_at(r);
364 segments[r] = segments[r+1];
365 segments[r].len = delta;
366 segments[r+1].len -= delta;
367 segments[r+1].addr += delta;
368 segments[r+1].offset += delta;
369 return r+1;
370}
371
sewardj79048ce2005-02-18 08:28:32 +0000372
373/* Return true if two segments are adjacent and mergable (s1 is
374 assumed to have a lower ->addr than s2) */
375static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
376{
377 if (s1->addr+s1->len != s2->addr)
378 return False;
379
380 if (s1->flags != s2->flags)
381 return False;
382
383 if (s1->prot != s2->prot)
384 return False;
385
386 if (s1->symtab != s2->symtab)
387 return False;
388
389 if (s1->flags & SF_FILE){
390 if ((s1->offset + s1->len) != s2->offset)
391 return False;
392 if (s1->dev != s2->dev)
393 return False;
394 if (s1->ino != s2->ino)
395 return False;
396 if (s1->fnIdx != s2->fnIdx)
397 return False;
398 }
399
400 return True;
401}
402
403
404/* Clean up and sanity check the segment array:
405 - check segments are in ascending order
406 - check segments do not overlap
407 - check no segment has zero size
408 - merge adjacent where possible
409 - perform checks on the filename table, and reclaim dead entries
410*/
411static void preen_segments ( void )
412{
413 Int i, j, rd, wr;
414 Segment *s, *s1;
415 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
416 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
417
418 if (0) show_segments("before preen");
419
420 /* clear string table mark bits */
421 for (i = 0; i < segnames_used; i++)
422 segnames[i].mark = False;
423
424 /* check for non-zero size, and set mark bits for any used strings */
425 for (i = 0; i < segments_used; i++) {
426 vg_assert(segments[i].len > 0);
427 j = segments[i].fnIdx;
428 vg_assert(j >= -1 && j < segnames_used);
429 if (j >= 0) {
430 vg_assert(segnames[j].inUse);
431 segnames[j].mark = True;
432 }
433 }
434
435 /* check ascendingness and non-overlap */
436 for (i = 0; i < segments_used-1; i++) {
437 s = &segments[i];
438 s1 = &segments[i+1];
439 vg_assert(s->addr < s1->addr);
440 vg_assert(s->addr + s->len <= s1->addr);
441 }
442
443 /* merge */
444 if (segments_used < 1)
445 return;
446
447 wr = 1;
448 for (rd = 1; rd < segments_used; rd++) {
449 s = &segments[wr-1];
450 s1 = &segments[rd];
451 if (segments_are_mergeable(s,s1)) {
452 if (0)
453 VG_(printf)("merge %p-%p with %p-%p\n",
454 s->addr, s->addr+s->len,
455 s1->addr, s1->addr+s1->len);
456 s->len += s1->len;
457 continue;
458 }
459 if (wr < rd)
460 segments[wr] = segments[rd];
461 wr++;
462 }
463 vg_assert(wr >= 0 && wr <= segments_used);
464 segments_used = wr;
465
466 /* Free up any strings which are no longer referenced. */
467 for (i = 0; i < segnames_used; i++) {
468 if (segnames[i].mark == False) {
469 segnames[i].inUse = False;
470 segnames[i].fname[0] = 0;
471 }
472 }
473
474 if (0) show_segments("after preen");
475}
476
477
sewardj548be6d2005-02-16 01:31:37 +0000478/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000479/*--- Maintain an ordered list of all the client's mappings ---*/
480/*--------------------------------------------------------------*/
481
nethercote8991d5a2004-11-03 17:07:46 +0000482Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000483{
484 Addr se = s->addr+s->len;
485 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000486 vg_assert(pe >= p);
487
488 return (p >= s->addr && pe <= se);
489}
490
nethercote8991d5a2004-11-03 17:07:46 +0000491Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000492{
493 Addr se = s->addr+s->len;
494 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000495 vg_assert(pe >= p);
496
497 return (p < se && pe > s->addr);
498}
499
sewardj1024cf72005-02-28 14:39:21 +0000500#if 0
501/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000502/* Prepare a Segment structure for recycling by freeing everything
503 hanging off it. */
504static void recycleseg(Segment *s)
505{
506 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000507 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000508
509 if (s->filename != NULL)
510 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
511
512 /* keep the SegInfo, if any - it probably still applies */
513}
514
515/* When freeing a Segment, also clean up every one else's ideas of
516 what was going on in that range of memory */
517static void freeseg(Segment *s)
518{
519 recycleseg(s);
520 if (s->symtab != NULL) {
nethercote8991d5a2004-11-03 17:07:46 +0000521 VG_(symtab_decref)(s->symtab, s->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000522 s->symtab = NULL;
523 }
524
525 VG_(SkipNode_Free)(&sk_segments, s);
526}
sewardj1024cf72005-02-28 14:39:21 +0000527#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000528
sewardj1024cf72005-02-28 14:39:21 +0000529
530/* Get rid of any translations arising from s. */
531/* Note, this is not really the job of the low level memory manager.
532 When it comes time to rewrite this subsystem, clean this up. */
533static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000534{
sewardj1024cf72005-02-28 14:39:21 +0000535 if (s->flags & SF_CODE) {
536 VG_(discard_translations)(s->addr, s->len);
537 if (0)
538 VG_(printf)("dumping translations in %p .. %p\n",
539 s->addr, s->addr+s->len);
540 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000541}
542
sewardj1024cf72005-02-28 14:39:21 +0000543
fitzhardinge98abfc72003-12-16 02:05:15 +0000544/* This unmaps all the segments in the range [addr, addr+len); any
545 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000546void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000547{
fitzhardingee3632c62003-12-22 10:58:06 +0000548 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000549 Segment* s;
550 Addr end, s_end;
551 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000552 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000553
554 if (len == 0)
555 return;
556
fitzhardinge1a4adf02003-12-22 10:42:59 +0000557 len = PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000558
fitzhardinge98abfc72003-12-16 02:05:15 +0000559 if (debug)
560 VG_(printf)("unmap_range(%p, %d)\n", addr, len);
sewardj79048ce2005-02-18 08:28:32 +0000561 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000562 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000563
564 /* Everything must be page-aligned */
sewardj548be6d2005-02-16 01:31:37 +0000565 vg_assert(IS_PAGE_ALIGNED(addr));
566 vg_assert(IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000567
sewardj548be6d2005-02-16 01:31:37 +0000568 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000569
570 /* do not delete .. even though it looks stupid */
571 vg_assert(i >= 0);
572
573 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000574 s = &segments[i];
575 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000576
sewardj548be6d2005-02-16 01:31:37 +0000577 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000578 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000579 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000580
fitzhardinge1a303042003-12-22 08:48:50 +0000581 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000582 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000583 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000584 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000585 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000586
587 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000588 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000589 addr < s_end &&
590 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000591 /* this segment's tail is truncated by [addr, addr+len)
592 -> truncate tail
593 */
sewardj1024cf72005-02-28 14:39:21 +0000594 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000595 s->len = addr - s->addr;
596
597 if (debug)
598 VG_(printf)(" case 1: s->len=%d\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000599 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000600 /* this segment's head is truncated by [addr, addr+len)
601 -> truncate head
602 */
sewardj548be6d2005-02-16 01:31:37 +0000603 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000604
605 if (debug)
sewardj79048ce2005-02-18 08:28:32 +0000606 VG_(printf)(" case 2: s->addr=%p s->len=%d delta=%d\n",
607 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000608
sewardj1024cf72005-02-28 14:39:21 +0000609 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000610 s->addr += delta;
611 s->offset += delta;
612 s->len -= delta;
613
614 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000615 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000616 /* this segment is completely contained within [addr, addr+len)
617 -> delete segment
618 */
sewardj1024cf72005-02-28 14:39:21 +0000619 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000620 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000621 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000622
623 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000624 VG_(printf)(" case 3: seg %d deleted\n", i);
625 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000626 /* [addr, addr+len) is contained within a single segment
627 -> split segment into 3, delete middle portion
628 */
sewardj1024cf72005-02-28 14:39:21 +0000629 Int i_middle;
630 dump_translations_from(s);
631 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000632 vg_assert(i_middle != -1);
633 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000634 vg_assert(segments[i_middle].addr == addr);
635 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000636 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000637
638 if (debug)
639 VG_(printf)(" case 4: subrange %p-%p deleted\n",
640 addr, addr+len);
641 }
sewardj47c98a72005-03-12 20:36:15 +0000642
643 /* If we deleted this segment (or any above), those above will
644 have been moved down to fill in the hole in the segment
645 array. In order that we don't miss them, we have to
646 re-consider this slot number; hence the i--. */
647 if (deleted)
648 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000649 }
sewardj79048ce2005-02-18 08:28:32 +0000650 preen_segments();
651 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000652}
653
sewardj548be6d2005-02-16 01:31:37 +0000654
655/* Add a binding of [addr,addr+len) to
656 (prot,flags,dev,ino,off,filename) in the segment array.
657 Delete/truncate any previous mapping(s) covering that range.
658*/
659void
660VG_(map_file_segment)( Addr addr, SizeT len,
661 UInt prot, UInt flags,
662 UInt dev, UInt ino, ULong off,
663 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000664{
fitzhardinge98abfc72003-12-16 02:05:15 +0000665 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000666 Segment* s;
667 Int idx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000668
669 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000670 VG_(printf)(
671 "\n"
672 "map_file_segment(addr=%p len=%llu prot=0x%x flags=0x%x\n"
673 " dev=0x%4x ino=%d off=%ld\n"
674 " filename='%s')\n",
675 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000676
677 /* Everything must be page-aligned */
sewardj548be6d2005-02-16 01:31:37 +0000678 vg_assert(IS_PAGE_ALIGNED(addr));
fitzhardinge98abfc72003-12-16 02:05:15 +0000679 len = PGROUNDUP(len);
680
sewardj548be6d2005-02-16 01:31:37 +0000681 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
682 VG_(unmap_range)(addr, len);
683
684 /* and now install this one */
685 idx = create_segment(addr);
686 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
687 vg_assert(idx != -1);
688 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000689
sewardj79048ce2005-02-18 08:28:32 +0000690 s = &segments[idx];
691 vg_assert(s->addr == addr);
692 s->prot = prot;
693 s->flags = flags;
694 s->len = len;
695 s->offset = off;
696 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
697 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
698 s->dev = dev;
699 s->ino = ino;
700 s->symtab = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000701
sewardj79048ce2005-02-18 08:28:32 +0000702 /* Clean up right now */
703 preen_segments();
704 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000705
706 /* If this mapping is of the beginning of a file, isn't part of
707 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000708 file, then try reading symbols from it.
709 */
710 if (s->symtab == NULL
sewardjb71816c2005-03-14 19:11:10 +0000711 && (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
sewardj79048ce2005-02-18 08:28:32 +0000712 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
713 if (off == 0
714 && s->fnIdx != -1
715 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
716 && len >= VKI_PAGE_SIZE
717 && VG_(is_object_file)((void *)addr)) {
nethercote71980f02004-01-24 18:18:54 +0000718 s->symtab = VG_(read_seg_symbols)(s);
nethercote71980f02004-01-24 18:18:54 +0000719 if (s->symtab != NULL) {
720 s->flags |= SF_DYNLIB;
721 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000722 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000723#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000724 const SegInfo *info;
725
726 /* Otherwise see if an existing symtab applies to this Segment */
727 for(info = VG_(next_seginfo)(NULL);
728 info != NULL;
729 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000730 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
731 {
fitzhardinge98abfc72003-12-16 02:05:15 +0000732 s->symtab = (SegInfo *)info;
733 VG_(symtab_incref)((SegInfo *)info);
734 }
735 }
sewardj79048ce2005-02-18 08:28:32 +0000736#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000737 }
738 }
739
740 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000741 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000742}
743
nethercote8b5f40c2004-11-02 13:29:50 +0000744void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000745 Int fd, ULong off, const Char *filename)
746{
747 struct vki_stat st;
748 Char *name = NULL;
749
750 st.st_dev = 0;
751 st.st_ino = 0;
752
753 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000754 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000755
756 if (VG_(fstat)(fd, &st) < 0)
757 flags &= ~SF_FILE;
758 }
759
sewardj79048ce2005-02-18 08:28:32 +0000760 if ((flags & SF_FILE) && filename == NULL && fd != -1)
761 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000762
763 if (filename == NULL)
764 filename = name;
765
sewardj79048ce2005-02-18 08:28:32 +0000766 VG_(map_file_segment)(addr, len, prot, flags,
767 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000768}
769
nethercote8b5f40c2004-11-02 13:29:50 +0000770void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000771{
772 flags &= ~SF_FILE;
773
774 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
775}
776
777/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000778void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000779{
sewardj79048ce2005-02-18 08:28:32 +0000780 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000781 static const Bool debug = False || mem_debug;
782
783 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000784 VG_(printf)("\nmprotect_range(%p, %d, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000785
786 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000787
788 /* Everything must be page-aligned */
sewardj79048ce2005-02-18 08:28:32 +0000789 vg_assert(IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000790 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000791
sewardj79048ce2005-02-18 08:28:32 +0000792 split_segment(a);
793 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000794
sewardj548be6d2005-02-16 01:31:37 +0000795 r = find_segment(a);
796 vg_assert(r != -1);
797 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000798
799 preen_segments();
800
sewardje517b802005-02-16 01:58:51 +0000801 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000802}
803
sewardj79048ce2005-02-18 08:28:32 +0000804
sewardj548be6d2005-02-16 01:31:37 +0000805/* Try to find a map space for [addr,addr+len). If addr==0, it means
806 the caller is prepared to accept a space at any location; if not,
807 we will try for addr, but fail if we can't get it. This mimics
808 mmap fixed vs mmap not-fixed.
809*/
nethercote8b5f40c2004-11-02 13:29:50 +0000810Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000811{
fitzhardingee3632c62003-12-22 10:58:06 +0000812 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000813 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000814 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000815 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
816 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000817 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
818 Int i, i_any, i_fixed, i_final;
819 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000820
sewardj548be6d2005-02-16 01:31:37 +0000821 Bool fixed;
822
sewardje517b802005-02-16 01:58:51 +0000823 if (debug) {
824 VG_(printf)("\n\n");
825 VG_(printf)("find_map_space(%p, %d, %d) ...\n",
826 addr, len, for_client);
827 }
828
829 if (0) show_segments("find_map_space: start");
830
sewardj548be6d2005-02-16 01:31:37 +0000831 if (addr == 0) {
832 fixed = False;
833 } else {
834 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000835 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000836 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000837 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000838 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000839
840 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000841 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000842 len = PGROUNDUP(len);
843
nethercote73b526f2004-10-31 18:48:21 +0000844 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000845
sewardj548be6d2005-02-16 01:31:37 +0000846 /* Scan the segment list, looking for a hole which satisfies the
847 requirements. At each point i we ask the question "can we use
848 the hole in between segments[i-1] and segments[i] ?" */
849 i_any = i_fixed = -1;
850 hstart_any = hstart_fixed = 0;
851
852 hole_start = hole_end = 0;
853
854 /* Iterate over all possible holes, generating them into
855 hole_start/hole_end. Filter out invalid ones. Then see if any
856 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
857 */
858 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
859 if (i == 0) {
860 hole_start = 0;
861 hole_end = segments[0].addr-1;
862 }
863 else {
864 vg_assert(segments_used > 0);
865 if (i == segments_used) {
866 hole_start = segments[i-1].addr + segments[i-1].len;
867 hole_end = ~(Addr)0;
868 } else {
869 hole_start = segments[i-1].addr + segments[i-1].len;
870 hole_end = segments[i].addr - 1;
871 }
872 }
873
874 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
875
876 /* ignore zero-sized holes */
877 if (hole_start == hole_end+1)
878 continue;
879
880 vg_assert(IS_PAGE_ALIGNED(hole_start));
881 vg_assert(IS_PAGE_ALIGNED(hole_end+1));
882
883 /* ignore holes which fall outside the allowable area */
884 if (!(hole_start >= base && hole_end <= limit))
885 continue;
886
887 vg_assert(hole_end > hole_start);
888 hole_len = hole_end - hole_start + 1;
sewardjb5f6f512005-03-10 23:59:00 +0000889 vg_assert(IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000890
891 if (hole_len >= len && i_any == -1) {
892 /* It will at least fit in this hole. */
893 i_any = i;
894 hstart_any = hole_start;
895 }
896
sewardjb5f6f512005-03-10 23:59:00 +0000897 if (fixed && hole_start <= addr
898 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000899 /* We were asked for a fixed mapping, and this hole works.
900 Bag it -- and stop searching as further searching is
901 pointless. */
902 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000903 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000904 break;
905 }
906 }
907
908 /* Summarise the final decision into i_final/hstart_final. */
909 i_final = -1;
910 hstart_final = 0;
911
912 if (fixed) {
913 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000914 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000915 } else {
916 i_final = i_any;
917 hstart_final = hstart_any;
918 }
919
920
921 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000922 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000923 else
924 ret = 0; /* not found */
925
926 if (debug)
sewardje517b802005-02-16 01:58:51 +0000927 VG_(printf)("find_map_space(%p, %d, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000928 addr, len, for_client, ret);
929
sewardjb5f6f512005-03-10 23:59:00 +0000930 if (fixed) {
931 vg_assert(ret == 0 || ret == addrOrig);
932 }
933
sewardj548be6d2005-02-16 01:31:37 +0000934 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000935}
936
sewardj79048ce2005-02-18 08:28:32 +0000937
sewardjb5f6f512005-03-10 23:59:00 +0000938/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000939 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000940 mapping over any part of the address space which is not covered
941 by an entry in the segment list.
942
943 This is designed for use around system calls which allocate
944 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000945 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000946 address with VG_(find_map_space) and then adding a segment for
947 it and padding the address space valgrind can ensure that the
948 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000949void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000950{
sewardj394790d2005-03-17 02:14:44 +0000951 Addr addr = (start == 0) ? VG_(client_base) : start;
952 Addr ret;
953
954 Int i = 0;
955 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000956
nethercote820bd8c2004-09-07 23:04:49 +0000957 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000958 if (addr < s->addr) {
nethercotef18ca392004-11-04 18:45:22 +0000959 PLATFORM_DO_MMAP(ret, addr, s->addr - addr, 0,
960 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
961 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000962 }
thughes9aaebc32004-07-15 23:13:37 +0000963 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000964 i++;
965 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000966 }
967
nethercote820bd8c2004-09-07 23:04:49 +0000968 if (addr <= VG_(valgrind_last)) {
nethercotef18ca392004-11-04 18:45:22 +0000969 PLATFORM_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
970 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
971 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000972 }
thughes9aaebc32004-07-15 23:13:37 +0000973}
974
thughesc70b8c62004-07-16 23:07:58 +0000975/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000976 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +0000977void VG_(unpad_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;
980 Int ret;
981
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) {
njnca6fef02004-11-29 16:49:18 +0000987 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +0000988 }
thughes9aaebc32004-07-15 23:13:37 +0000989 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000990 i++;
991 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000992 }
993
nethercote820bd8c2004-09-07 23:04:49 +0000994 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +0000995 ret = VG_(do_syscall2)(__NR_munmap, addr,
996 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +0000997 }
thughes9aaebc32004-07-15 23:13:37 +0000998}
999
sewardj548be6d2005-02-16 01:31:37 +00001000/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001001Segment *VG_(find_segment)(Addr a)
1002{
sewardj548be6d2005-02-16 01:31:37 +00001003 Int r = find_segment(a);
1004 if (0) show_segments("find_segment");
1005 if (r == -1) return NULL;
1006 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001007}
1008
sewardj548be6d2005-02-16 01:31:37 +00001009/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1010 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1011 a segment is a checked error.
1012*/
1013Segment *VG_(find_segment_above_unmapped)(Addr a)
1014{
1015 Int r = find_segment_above_unmapped(a);
1016 if (0) show_segments("find_segment_above_unmapped");
1017 if (r == -1) return NULL;
1018 return &segments[r];
1019}
1020
1021/* Assumes that 'a' is in some segment. Finds the next segment along,
1022 or NULL if none. Passing 'a' which is in fact not in a segment is
1023 a checked error.
1024*/
1025Segment *VG_(find_segment_above_mapped)(Addr a)
1026{
1027 Int r = find_segment_above_mapped(a);
1028 if (0) show_segments("find_segment_above_mapped");
1029 if (r == -1) return NULL;
1030 return &segments[r];
1031}
1032
1033
sewardjde4a1d02002-03-22 01:27:54 +00001034/*------------------------------------------------------------*/
1035/*--- Tracking permissions around %esp changes. ---*/
1036/*------------------------------------------------------------*/
1037
1038/*
1039 The stack
1040 ~~~~~~~~~
1041 The stack's segment seems to be dynamically extended downwards
1042 by the kernel as the stack pointer moves down. Initially, a
1043 1-page (4k) stack is allocated. When %esp moves below that for
1044 the first time, presumably a page fault occurs. The kernel
1045 detects that the faulting address is in the range from %esp upwards
1046 to the current valid stack. It then extends the stack segment
1047 downwards for enough to cover the faulting address, and resumes
1048 the process (invisibly). The process is unaware of any of this.
1049
1050 That means that Valgrind can't spot when the stack segment is
1051 being extended. Fortunately, we want to precisely and continuously
1052 update stack permissions around %esp, so we need to spot all
1053 writes to %esp anyway.
1054
1055 The deal is: when %esp is assigned a lower value, the stack is
1056 being extended. Create a secondary maps to fill in any holes
1057 between the old stack ptr and this one, if necessary. Then
1058 mark all bytes in the area just "uncovered" by this %esp change
1059 as write-only.
1060
1061 When %esp goes back up, mark the area receded over as unreadable
1062 and unwritable.
1063
1064 Just to record the %esp boundary conditions somewhere convenient:
1065 %esp always points to the lowest live byte in the stack. All
1066 addresses below %esp are not live; those at and above it are.
1067*/
1068
sewardjde4a1d02002-03-22 01:27:54 +00001069/* Kludgey ... how much does %esp have to change before we reckon that
1070 the application is switching stacks ? */
njn9b007f62003-04-07 14:40:25 +00001071#define VG_PLAUSIBLE_STACK_SIZE 8000000
1072#define VG_HUGE_DELTA (VG_PLAUSIBLE_STACK_SIZE / 4)
sewardjde4a1d02002-03-22 01:27:54 +00001073
njn9b007f62003-04-07 14:40:25 +00001074/* This function gets called if new_mem_stack and/or die_mem_stack are
nethercote996901a2004-08-03 13:29:09 +00001075 tracked by the tool, and one of the specialised cases (eg. new_mem_stack_4)
njn9b007f62003-04-07 14:40:25 +00001076 isn't used in preference */
sewardj2a99cf62004-11-24 10:44:19 +00001077REGPARM(2)
1078void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001079{
nethercotefc646ee2004-11-04 19:29:06 +00001080 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001081
njn9b007f62003-04-07 14:40:25 +00001082 if (delta < -(VG_HUGE_DELTA) || VG_HUGE_DELTA < delta) {
1083 /* %esp has changed by more than HUGE_DELTA. We take this to mean
1084 that the application is switching to a new stack, for whatever
1085 reason.
1086
1087 JRS 20021001: following discussions with John Regehr, if a stack
1088 switch happens, it seems best not to mess at all with memory
1089 permissions. Seems to work well with Netscape 4.X. Really the
1090 only remaining difficulty is knowing exactly when a stack switch is
1091 happening. */
1092 if (VG_(clo_verbosity) > 1)
1093 VG_(message)(Vg_UserMsg, "Warning: client switching stacks? "
nethercote15218bd2004-09-11 15:11:47 +00001094 "%%esp: %p --> %p", old_SP, new_SP);
njn9b007f62003-04-07 14:40:25 +00001095 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001096 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001097
njn9b007f62003-04-07 14:40:25 +00001098 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001099 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001100 }
1101}
1102
jsgf855d93d2003-10-13 22:26:55 +00001103/*
sewardjb5f6f512005-03-10 23:59:00 +00001104 Test if a piece of memory is addressable with at least the "prot"
1105 protection permissions by examining the underlying segments.
1106
1107 Really this is a very stupid algorithm and we could do much
1108 better by iterating through the segment array instead of through
1109 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001110 */
sewardjb5f6f512005-03-10 23:59:00 +00001111Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001112{
sewardjb5f6f512005-03-10 23:59:00 +00001113 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001114
sewardjb5f6f512005-03-10 23:59:00 +00001115 if ((p + size) < p)
1116 return False; /* reject wraparounds */
1117 if (size == 0)
1118 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001119
sewardjb5f6f512005-03-10 23:59:00 +00001120 p = PGROUNDDN(p);
1121 size = PGROUNDUP(size);
1122 vg_assert(IS_PAGE_ALIGNED(p));
1123 vg_assert(IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001124
sewardjb5f6f512005-03-10 23:59:00 +00001125 for (; size > 0; size -= VKI_PAGE_SIZE) {
1126 seg = VG_(find_segment)(p);
1127 if (!seg)
1128 return False;
1129 if ((seg->prot & prot) != prot)
1130 return False;
1131 p += VKI_PAGE_SIZE;
1132 }
jsgf855d93d2003-10-13 22:26:55 +00001133
sewardjb5f6f512005-03-10 23:59:00 +00001134 return True;
jsgf855d93d2003-10-13 22:26:55 +00001135}
1136
sewardjb5f6f512005-03-10 23:59:00 +00001137
sewardjde4a1d02002-03-22 01:27:54 +00001138/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001139/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001140/*--------------------------------------------------------------------*/
1141
nethercote57e36b32004-07-10 14:56:28 +00001142// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001143Addr VG_(get_memory_from_mmap_for_client)
1144 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001145{
1146 len = PGROUNDUP(len);
1147
njnca82cc02004-11-22 17:18:48 +00001148 tl_assert(!(sf_flags & SF_FIXED));
1149 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001150
nethercote8e9eab02004-07-11 18:01:06 +00001151 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1152 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1153 sf_flags | SF_CORE, -1, 0);
1154 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001155 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001156 else
1157 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001158}
1159
fitzhardinge98abfc72003-12-16 02:05:15 +00001160
njn86f12dc2005-03-14 01:16:05 +00001161/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001162 range, which isn't SF_CORE, a root.
1163*/
njn86f12dc2005-03-14 01:16:05 +00001164void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1165{
sewardj882af5f2005-03-16 12:27:53 +00001166 Int i;
1167 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001168 Segment *s;
1169
sewardj882af5f2005-03-16 12:27:53 +00001170 for (i = 0; i < segments_used; i++) {
1171 s = &segments[i];
1172 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1173 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001174 if (flags != SF_MMAP && flags != SF_STACK)
1175 continue;
sewardj882af5f2005-03-16 12:27:53 +00001176 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1177 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001178 continue;
1179 if (!VG_(is_client_addr)(s->addr) ||
1180 !VG_(is_client_addr)(s->addr+s->len))
1181 continue;
1182
1183 (*add_rootrange)(s->addr, s->len);
1184 }
njn86f12dc2005-03-14 01:16:05 +00001185}
1186
1187
nethercote88a90162004-07-10 16:59:25 +00001188/*--------------------------------------------------------------------*/
1189/*--- Querying memory layout ---*/
1190/*--------------------------------------------------------------------*/
1191
fitzhardinge98abfc72003-12-16 02:05:15 +00001192Bool VG_(is_client_addr)(Addr a)
1193{
1194 return a >= VG_(client_base) && a < VG_(client_end);
1195}
1196
1197Bool VG_(is_shadow_addr)(Addr a)
1198{
1199 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1200}
1201
1202Bool VG_(is_valgrind_addr)(Addr a)
1203{
sewardj548be6d2005-02-16 01:31:37 +00001204vg_assert(0);
nethercote820bd8c2004-09-07 23:04:49 +00001205 return a >= VG_(valgrind_base) && a <= VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +00001206}
1207
1208Addr VG_(get_client_base)(void)
1209{
sewardj548be6d2005-02-16 01:31:37 +00001210vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001211 return VG_(client_base);
1212}
1213
1214Addr VG_(get_client_end)(void)
1215{
sewardj548be6d2005-02-16 01:31:37 +00001216vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001217 return VG_(client_end);
1218}
1219
1220Addr VG_(get_client_size)(void)
1221{
sewardj548be6d2005-02-16 01:31:37 +00001222vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001223 return VG_(client_end)-VG_(client_base);
1224}
1225
1226Addr VG_(get_shadow_base)(void)
1227{
sewardj548be6d2005-02-16 01:31:37 +00001228vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001229 return VG_(shadow_base);
1230}
1231
1232Addr VG_(get_shadow_end)(void)
1233{
sewardj548be6d2005-02-16 01:31:37 +00001234vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001235 return VG_(shadow_end);
1236}
1237
1238Addr VG_(get_shadow_size)(void)
1239{
1240 return VG_(shadow_end)-VG_(shadow_base);
1241}
1242
nethercote88a90162004-07-10 16:59:25 +00001243/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001244/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001245/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001246
1247void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1248{
sewardj548be6d2005-02-16 01:31:37 +00001249vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001250 if (0)
1251 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1252
1253 vg_assert(VG_(needs).shadow_memory);
1254 vg_assert(VG_(defined_init_shadow_page)());
1255
1256 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1257 p = PGROUNDDN(p);
1258
1259 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1260
1261 if (call_init)
1262 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001263 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001264 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1265
nethercote73b526f2004-10-31 18:48:21 +00001266 p += VKI_PAGE_SIZE;
1267 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001268 }
1269}
1270
1271void *VG_(shadow_alloc)(UInt size)
1272{
1273 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001274 Addr try_here;
1275 Int r;
1276
1277 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001278
1279 vg_assert(VG_(needs).shadow_memory);
1280 vg_assert(!VG_(defined_init_shadow_page)());
1281
1282 size = PGROUNDUP(size);
1283
1284 if (shadow_alloc == 0)
1285 shadow_alloc = VG_(shadow_base);
1286
1287 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001288 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001289
sewardj79048ce2005-02-18 08:28:32 +00001290 try_here = shadow_alloc;
1291 vg_assert(IS_PAGE_ALIGNED(try_here));
1292 vg_assert(IS_PAGE_ALIGNED(size));
1293 vg_assert(size > 0);
1294
1295 if (0)
1296 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1297
1298 /* this is big-bang allocated, so we don't expect to find a listed
1299 segment for it. */
1300 /* This is really an absolute disgrace. Sometimes the big-bang
1301 mapping is in the list (due to re-reads of /proc/self/maps,
1302 presumably) and sometimes it isn't. */
1303#if 0
1304 r = find_segment(try_here);
1305 vg_assert(r == -1);
1306 r = find_segment(try_here+size-1);
1307 vg_assert(r == -1);
1308#endif
1309
1310 r = VG_(mprotect_native)( (void*)try_here,
1311 size, VKI_PROT_READ|VKI_PROT_WRITE );
1312
1313 if (r != 0)
1314 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001315
1316 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001317 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001318
sewardj79048ce2005-02-18 08:28:32 +00001319 failed:
1320 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001321 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001322 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001323 size
sewardj79048ce2005-02-18 08:28:32 +00001324 );
1325 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001326}
1327
1328/*--------------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +00001329/*--- end vg_memory.c ---*/
1330/*--------------------------------------------------------------------*/