blob: 2a05966517e168364e851c32c1c892db48d777cb [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
711 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
712 if (off == 0
713 && s->fnIdx != -1
714 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
715 && len >= VKI_PAGE_SIZE
716 && VG_(is_object_file)((void *)addr)) {
nethercote71980f02004-01-24 18:18:54 +0000717 s->symtab = VG_(read_seg_symbols)(s);
nethercote71980f02004-01-24 18:18:54 +0000718 if (s->symtab != NULL) {
719 s->flags |= SF_DYNLIB;
720 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000721 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000722#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000723 const SegInfo *info;
724
725 /* Otherwise see if an existing symtab applies to this Segment */
726 for(info = VG_(next_seginfo)(NULL);
727 info != NULL;
728 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000729 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
730 {
fitzhardinge98abfc72003-12-16 02:05:15 +0000731 s->symtab = (SegInfo *)info;
732 VG_(symtab_incref)((SegInfo *)info);
733 }
734 }
sewardj79048ce2005-02-18 08:28:32 +0000735#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000736 }
737 }
738
739 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000740 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000741}
742
nethercote8b5f40c2004-11-02 13:29:50 +0000743void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000744 Int fd, ULong off, const Char *filename)
745{
746 struct vki_stat st;
747 Char *name = NULL;
748
749 st.st_dev = 0;
750 st.st_ino = 0;
751
752 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000753 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000754
755 if (VG_(fstat)(fd, &st) < 0)
756 flags &= ~SF_FILE;
757 }
758
sewardj79048ce2005-02-18 08:28:32 +0000759 if ((flags & SF_FILE) && filename == NULL && fd != -1)
760 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000761
762 if (filename == NULL)
763 filename = name;
764
sewardj79048ce2005-02-18 08:28:32 +0000765 VG_(map_file_segment)(addr, len, prot, flags,
766 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000767}
768
nethercote8b5f40c2004-11-02 13:29:50 +0000769void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000770{
771 flags &= ~SF_FILE;
772
773 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
774}
775
776/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000777void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000778{
sewardj79048ce2005-02-18 08:28:32 +0000779 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000780 static const Bool debug = False || mem_debug;
781
782 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000783 VG_(printf)("\nmprotect_range(%p, %d, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000784
785 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000786
787 /* Everything must be page-aligned */
sewardj79048ce2005-02-18 08:28:32 +0000788 vg_assert(IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000789 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000790
sewardj79048ce2005-02-18 08:28:32 +0000791 split_segment(a);
792 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000793
sewardj548be6d2005-02-16 01:31:37 +0000794 r = find_segment(a);
795 vg_assert(r != -1);
796 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000797
798 preen_segments();
799
sewardje517b802005-02-16 01:58:51 +0000800 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000801}
802
sewardj79048ce2005-02-18 08:28:32 +0000803
sewardj548be6d2005-02-16 01:31:37 +0000804/* Try to find a map space for [addr,addr+len). If addr==0, it means
805 the caller is prepared to accept a space at any location; if not,
806 we will try for addr, but fail if we can't get it. This mimics
807 mmap fixed vs mmap not-fixed.
808*/
nethercote8b5f40c2004-11-02 13:29:50 +0000809Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000810{
fitzhardingee3632c62003-12-22 10:58:06 +0000811 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000812 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000813 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000814 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
815 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000816 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
817 Int i, i_any, i_fixed, i_final;
818 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000819
sewardj548be6d2005-02-16 01:31:37 +0000820 Bool fixed;
821
sewardje517b802005-02-16 01:58:51 +0000822 if (debug) {
823 VG_(printf)("\n\n");
824 VG_(printf)("find_map_space(%p, %d, %d) ...\n",
825 addr, len, for_client);
826 }
827
828 if (0) show_segments("find_map_space: start");
829
sewardj548be6d2005-02-16 01:31:37 +0000830 if (addr == 0) {
831 fixed = False;
832 } else {
833 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000834 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000835 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000836 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000837 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000838
839 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000840 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000841 len = PGROUNDUP(len);
842
nethercote73b526f2004-10-31 18:48:21 +0000843 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000844
sewardj548be6d2005-02-16 01:31:37 +0000845 /* Scan the segment list, looking for a hole which satisfies the
846 requirements. At each point i we ask the question "can we use
847 the hole in between segments[i-1] and segments[i] ?" */
848 i_any = i_fixed = -1;
849 hstart_any = hstart_fixed = 0;
850
851 hole_start = hole_end = 0;
852
853 /* Iterate over all possible holes, generating them into
854 hole_start/hole_end. Filter out invalid ones. Then see if any
855 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
856 */
857 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
858 if (i == 0) {
859 hole_start = 0;
860 hole_end = segments[0].addr-1;
861 }
862 else {
863 vg_assert(segments_used > 0);
864 if (i == segments_used) {
865 hole_start = segments[i-1].addr + segments[i-1].len;
866 hole_end = ~(Addr)0;
867 } else {
868 hole_start = segments[i-1].addr + segments[i-1].len;
869 hole_end = segments[i].addr - 1;
870 }
871 }
872
873 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
874
875 /* ignore zero-sized holes */
876 if (hole_start == hole_end+1)
877 continue;
878
879 vg_assert(IS_PAGE_ALIGNED(hole_start));
880 vg_assert(IS_PAGE_ALIGNED(hole_end+1));
881
882 /* ignore holes which fall outside the allowable area */
883 if (!(hole_start >= base && hole_end <= limit))
884 continue;
885
886 vg_assert(hole_end > hole_start);
887 hole_len = hole_end - hole_start + 1;
sewardjb5f6f512005-03-10 23:59:00 +0000888 vg_assert(IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000889
890 if (hole_len >= len && i_any == -1) {
891 /* It will at least fit in this hole. */
892 i_any = i;
893 hstart_any = hole_start;
894 }
895
sewardjb5f6f512005-03-10 23:59:00 +0000896 if (fixed && hole_start <= addr
897 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000898 /* We were asked for a fixed mapping, and this hole works.
899 Bag it -- and stop searching as further searching is
900 pointless. */
901 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000902 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000903 break;
904 }
905 }
906
907 /* Summarise the final decision into i_final/hstart_final. */
908 i_final = -1;
909 hstart_final = 0;
910
911 if (fixed) {
912 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000913 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000914 } else {
915 i_final = i_any;
916 hstart_final = hstart_any;
917 }
918
919
920 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000921 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000922 else
923 ret = 0; /* not found */
924
925 if (debug)
sewardje517b802005-02-16 01:58:51 +0000926 VG_(printf)("find_map_space(%p, %d, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000927 addr, len, for_client, ret);
928
sewardjb5f6f512005-03-10 23:59:00 +0000929 if (fixed) {
930 vg_assert(ret == 0 || ret == addrOrig);
931 }
932
sewardj548be6d2005-02-16 01:31:37 +0000933 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000934}
935
sewardj79048ce2005-02-18 08:28:32 +0000936
sewardjb5f6f512005-03-10 23:59:00 +0000937/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000938 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000939 mapping over any part of the address space which is not covered
940 by an entry in the segment list.
941
942 This is designed for use around system calls which allocate
943 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000944 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000945 address with VG_(find_map_space) and then adding a segment for
946 it and padding the address space valgrind can ensure that the
947 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000948void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000949{
sewardjb5f6f512005-03-10 23:59:00 +0000950 vg_assert(0);
951#if 0
952 Addr addr = (start == 0) ? VG_(client_base) : start;
thughes9aaebc32004-07-15 23:13:37 +0000953 Segment *s = VG_(SkipNode_First)(&sk_segments);
thughes9aaebc32004-07-15 23:13:37 +0000954 Addr ret;
955
nethercote820bd8c2004-09-07 23:04:49 +0000956 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000957 if (addr < s->addr) {
nethercotef18ca392004-11-04 18:45:22 +0000958 PLATFORM_DO_MMAP(ret, addr, s->addr - addr, 0,
959 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
960 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000961 }
962
963 addr = s->addr + s->len;
964 s = VG_(SkipNode_Next)(&sk_segments, s);
965 }
966
nethercote820bd8c2004-09-07 23:04:49 +0000967 if (addr <= VG_(valgrind_last)) {
nethercotef18ca392004-11-04 18:45:22 +0000968 PLATFORM_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
969 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
970 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000971 }
972
973 return;
sewardjb5f6f512005-03-10 23:59:00 +0000974#endif
thughes9aaebc32004-07-15 23:13:37 +0000975}
976
thughesc70b8c62004-07-16 23:07:58 +0000977/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000978 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +0000979void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000980{
sewardjb5f6f512005-03-10 23:59:00 +0000981vg_assert(0);
982#if 0
983 Addr addr = (start == 0) ? VG_(client_base) : start;
thughes9aaebc32004-07-15 23:13:37 +0000984 Segment *s = VG_(SkipNode_First)(&sk_segments);
985 Int ret;
986
nethercote820bd8c2004-09-07 23:04:49 +0000987 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000988 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +0000989 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +0000990 }
991
992 addr = s->addr + s->len;
993 s = VG_(SkipNode_Next)(&sk_segments, s);
994 }
995
nethercote820bd8c2004-09-07 23:04:49 +0000996 if (addr <= VG_(valgrind_last)) {
njnca6fef02004-11-29 16:49:18 +0000997 ret = VG_(do_syscall2)(__NR_munmap, addr, (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +0000998 }
999
1000 return;
sewardjb5f6f512005-03-10 23:59:00 +00001001#endif
thughes9aaebc32004-07-15 23:13:37 +00001002}
1003
sewardj548be6d2005-02-16 01:31:37 +00001004/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001005Segment *VG_(find_segment)(Addr a)
1006{
sewardj548be6d2005-02-16 01:31:37 +00001007 Int r = find_segment(a);
1008 if (0) show_segments("find_segment");
1009 if (r == -1) return NULL;
1010 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001011}
1012
sewardj548be6d2005-02-16 01:31:37 +00001013/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1014 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1015 a segment is a checked error.
1016*/
1017Segment *VG_(find_segment_above_unmapped)(Addr a)
1018{
1019 Int r = find_segment_above_unmapped(a);
1020 if (0) show_segments("find_segment_above_unmapped");
1021 if (r == -1) return NULL;
1022 return &segments[r];
1023}
1024
1025/* Assumes that 'a' is in some segment. Finds the next segment along,
1026 or NULL if none. Passing 'a' which is in fact not in a segment is
1027 a checked error.
1028*/
1029Segment *VG_(find_segment_above_mapped)(Addr a)
1030{
1031 Int r = find_segment_above_mapped(a);
1032 if (0) show_segments("find_segment_above_mapped");
1033 if (r == -1) return NULL;
1034 return &segments[r];
1035}
1036
1037
sewardjde4a1d02002-03-22 01:27:54 +00001038/*------------------------------------------------------------*/
1039/*--- Tracking permissions around %esp changes. ---*/
1040/*------------------------------------------------------------*/
1041
1042/*
1043 The stack
1044 ~~~~~~~~~
1045 The stack's segment seems to be dynamically extended downwards
1046 by the kernel as the stack pointer moves down. Initially, a
1047 1-page (4k) stack is allocated. When %esp moves below that for
1048 the first time, presumably a page fault occurs. The kernel
1049 detects that the faulting address is in the range from %esp upwards
1050 to the current valid stack. It then extends the stack segment
1051 downwards for enough to cover the faulting address, and resumes
1052 the process (invisibly). The process is unaware of any of this.
1053
1054 That means that Valgrind can't spot when the stack segment is
1055 being extended. Fortunately, we want to precisely and continuously
1056 update stack permissions around %esp, so we need to spot all
1057 writes to %esp anyway.
1058
1059 The deal is: when %esp is assigned a lower value, the stack is
1060 being extended. Create a secondary maps to fill in any holes
1061 between the old stack ptr and this one, if necessary. Then
1062 mark all bytes in the area just "uncovered" by this %esp change
1063 as write-only.
1064
1065 When %esp goes back up, mark the area receded over as unreadable
1066 and unwritable.
1067
1068 Just to record the %esp boundary conditions somewhere convenient:
1069 %esp always points to the lowest live byte in the stack. All
1070 addresses below %esp are not live; those at and above it are.
1071*/
1072
sewardjde4a1d02002-03-22 01:27:54 +00001073/* Kludgey ... how much does %esp have to change before we reckon that
1074 the application is switching stacks ? */
njn9b007f62003-04-07 14:40:25 +00001075#define VG_PLAUSIBLE_STACK_SIZE 8000000
1076#define VG_HUGE_DELTA (VG_PLAUSIBLE_STACK_SIZE / 4)
sewardjde4a1d02002-03-22 01:27:54 +00001077
njn9b007f62003-04-07 14:40:25 +00001078/* This function gets called if new_mem_stack and/or die_mem_stack are
nethercote996901a2004-08-03 13:29:09 +00001079 tracked by the tool, and one of the specialised cases (eg. new_mem_stack_4)
njn9b007f62003-04-07 14:40:25 +00001080 isn't used in preference */
sewardj2a99cf62004-11-24 10:44:19 +00001081REGPARM(2)
1082void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001083{
nethercotefc646ee2004-11-04 19:29:06 +00001084 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001085
njn9b007f62003-04-07 14:40:25 +00001086 if (delta < -(VG_HUGE_DELTA) || VG_HUGE_DELTA < delta) {
1087 /* %esp has changed by more than HUGE_DELTA. We take this to mean
1088 that the application is switching to a new stack, for whatever
1089 reason.
1090
1091 JRS 20021001: following discussions with John Regehr, if a stack
1092 switch happens, it seems best not to mess at all with memory
1093 permissions. Seems to work well with Netscape 4.X. Really the
1094 only remaining difficulty is knowing exactly when a stack switch is
1095 happening. */
1096 if (VG_(clo_verbosity) > 1)
1097 VG_(message)(Vg_UserMsg, "Warning: client switching stacks? "
nethercote15218bd2004-09-11 15:11:47 +00001098 "%%esp: %p --> %p", old_SP, new_SP);
njn9b007f62003-04-07 14:40:25 +00001099 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001100 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001101
njn9b007f62003-04-07 14:40:25 +00001102 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001103 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001104 }
1105}
1106
jsgf855d93d2003-10-13 22:26:55 +00001107/*
sewardjb5f6f512005-03-10 23:59:00 +00001108 Test if a piece of memory is addressable with at least the "prot"
1109 protection permissions by examining the underlying segments.
1110
1111 Really this is a very stupid algorithm and we could do much
1112 better by iterating through the segment array instead of through
1113 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001114 */
sewardjb5f6f512005-03-10 23:59:00 +00001115Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001116{
sewardjb5f6f512005-03-10 23:59:00 +00001117 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001118
sewardjb5f6f512005-03-10 23:59:00 +00001119 if ((p + size) < p)
1120 return False; /* reject wraparounds */
1121 if (size == 0)
1122 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001123
sewardjb5f6f512005-03-10 23:59:00 +00001124 p = PGROUNDDN(p);
1125 size = PGROUNDUP(size);
1126 vg_assert(IS_PAGE_ALIGNED(p));
1127 vg_assert(IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001128
sewardjb5f6f512005-03-10 23:59:00 +00001129 for (; size > 0; size -= VKI_PAGE_SIZE) {
1130 seg = VG_(find_segment)(p);
1131 if (!seg)
1132 return False;
1133 if ((seg->prot & prot) != prot)
1134 return False;
1135 p += VKI_PAGE_SIZE;
1136 }
jsgf855d93d2003-10-13 22:26:55 +00001137
sewardjb5f6f512005-03-10 23:59:00 +00001138 return True;
jsgf855d93d2003-10-13 22:26:55 +00001139}
1140
sewardjb5f6f512005-03-10 23:59:00 +00001141
sewardjde4a1d02002-03-22 01:27:54 +00001142/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001143/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001144/*--------------------------------------------------------------------*/
1145
nethercote57e36b32004-07-10 14:56:28 +00001146// Returns 0 on failure.
nethercote928a5f72004-11-03 18:10:37 +00001147Addr VG_(client_alloc)(Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001148{
1149 len = PGROUNDUP(len);
1150
njnca82cc02004-11-22 17:18:48 +00001151 tl_assert(!(sf_flags & SF_FIXED));
1152 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001153
nethercote8e9eab02004-07-11 18:01:06 +00001154 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1155 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1156 sf_flags | SF_CORE, -1, 0);
1157 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001158 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001159 else
1160 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001161}
1162
1163void VG_(client_free)(Addr addr)
1164{
1165 Segment *s = VG_(find_segment)(addr);
1166
sewardj548be6d2005-02-16 01:31:37 +00001167vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001168 if (s == NULL || s->addr != addr || !(s->flags & SF_CORE)) {
1169 VG_(message)(Vg_DebugMsg, "VG_(client_free)(%p) - no CORE memory found there", addr);
1170 return;
1171 }
1172
1173 VG_(munmap)((void *)s->addr, s->len);
1174}
1175
njn86f12dc2005-03-14 01:16:05 +00001176/* We'll call any RW mmaped memory segment, within the client address
1177 range, which isn't SF_CORE, a root. */
1178void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1179{
1180 //VG_(message)(Vg_UserMsg, "Warning: VG_(find_root_memory) -- doing nothing");
1181 //VG_(message)(Vg_UserMsg, "leak checking probably won't work as a result");
1182#if 0
1183 Segment *s;
1184
1185 for(s = VG_(first_segment)(); s != NULL; s = VG_(next_segment)(s)) {
1186 UInt flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND|SF_CORE|SF_STACK|SF
1187_DEVICE);
1188 if (flags != SF_MMAP && flags != SF_STACK)
1189 continue;
1190 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE)) != (VKI_PROT_READ|VKI_PROT_
1191WRITE))
1192 continue;
1193 if (!VG_(is_client_addr)(s->addr) ||
1194 !VG_(is_client_addr)(s->addr+s->len))
1195 continue;
1196
1197 (*add_rootrange)(s->addr, s->len);
1198 }
1199#endif
1200}
1201
1202
nethercote88a90162004-07-10 16:59:25 +00001203/*--------------------------------------------------------------------*/
1204/*--- Querying memory layout ---*/
1205/*--------------------------------------------------------------------*/
1206
fitzhardinge98abfc72003-12-16 02:05:15 +00001207Bool VG_(is_client_addr)(Addr a)
1208{
1209 return a >= VG_(client_base) && a < VG_(client_end);
1210}
1211
1212Bool VG_(is_shadow_addr)(Addr a)
1213{
1214 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1215}
1216
1217Bool VG_(is_valgrind_addr)(Addr a)
1218{
sewardj548be6d2005-02-16 01:31:37 +00001219vg_assert(0);
nethercote820bd8c2004-09-07 23:04:49 +00001220 return a >= VG_(valgrind_base) && a <= VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +00001221}
1222
1223Addr VG_(get_client_base)(void)
1224{
sewardj548be6d2005-02-16 01:31:37 +00001225vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001226 return VG_(client_base);
1227}
1228
1229Addr VG_(get_client_end)(void)
1230{
sewardj548be6d2005-02-16 01:31:37 +00001231vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001232 return VG_(client_end);
1233}
1234
1235Addr VG_(get_client_size)(void)
1236{
sewardj548be6d2005-02-16 01:31:37 +00001237vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001238 return VG_(client_end)-VG_(client_base);
1239}
1240
1241Addr VG_(get_shadow_base)(void)
1242{
sewardj548be6d2005-02-16 01:31:37 +00001243vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001244 return VG_(shadow_base);
1245}
1246
1247Addr VG_(get_shadow_end)(void)
1248{
sewardj548be6d2005-02-16 01:31:37 +00001249vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001250 return VG_(shadow_end);
1251}
1252
1253Addr VG_(get_shadow_size)(void)
1254{
1255 return VG_(shadow_end)-VG_(shadow_base);
1256}
1257
nethercote88a90162004-07-10 16:59:25 +00001258/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001259/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001260/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001261
1262void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1263{
sewardj548be6d2005-02-16 01:31:37 +00001264vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001265 if (0)
1266 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1267
1268 vg_assert(VG_(needs).shadow_memory);
1269 vg_assert(VG_(defined_init_shadow_page)());
1270
1271 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1272 p = PGROUNDDN(p);
1273
1274 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1275
1276 if (call_init)
1277 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001278 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001279 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1280
nethercote73b526f2004-10-31 18:48:21 +00001281 p += VKI_PAGE_SIZE;
1282 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001283 }
1284}
1285
1286void *VG_(shadow_alloc)(UInt size)
1287{
1288 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001289 Addr try_here;
1290 Int r;
1291
1292 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001293
1294 vg_assert(VG_(needs).shadow_memory);
1295 vg_assert(!VG_(defined_init_shadow_page)());
1296
1297 size = PGROUNDUP(size);
1298
1299 if (shadow_alloc == 0)
1300 shadow_alloc = VG_(shadow_base);
1301
1302 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001303 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001304
sewardj79048ce2005-02-18 08:28:32 +00001305 try_here = shadow_alloc;
1306 vg_assert(IS_PAGE_ALIGNED(try_here));
1307 vg_assert(IS_PAGE_ALIGNED(size));
1308 vg_assert(size > 0);
1309
1310 if (0)
1311 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1312
1313 /* this is big-bang allocated, so we don't expect to find a listed
1314 segment for it. */
1315 /* This is really an absolute disgrace. Sometimes the big-bang
1316 mapping is in the list (due to re-reads of /proc/self/maps,
1317 presumably) and sometimes it isn't. */
1318#if 0
1319 r = find_segment(try_here);
1320 vg_assert(r == -1);
1321 r = find_segment(try_here+size-1);
1322 vg_assert(r == -1);
1323#endif
1324
1325 r = VG_(mprotect_native)( (void*)try_here,
1326 size, VKI_PROT_READ|VKI_PROT_WRITE );
1327
1328 if (r != 0)
1329 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001330
1331 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001332 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001333
sewardj79048ce2005-02-18 08:28:32 +00001334 failed:
1335 VG_(printf)(
1336 "valgrind: Could not allocate address space (%p bytes)\n"
1337 "valgrind: for shadow memory chunk.\n",
1338 (void*)size
1339 );
1340 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001341}
1342
1343/*--------------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +00001344/*--- end vg_memory.c ---*/
1345/*--------------------------------------------------------------------*/