blob: 908d4f9ad28888792fe8770ca1574cc4561bc335 [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
nethercotebb1c9912004-01-04 16:43:23 +000012 Copyright (C) 2000-2004 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;
fitzhardinge98abfc72003-12-16 02:05:15 +0000552
553 if (len == 0)
554 return;
555
fitzhardinge1a4adf02003-12-22 10:42:59 +0000556 len = PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000557
fitzhardinge98abfc72003-12-16 02:05:15 +0000558 if (debug)
559 VG_(printf)("unmap_range(%p, %d)\n", addr, len);
sewardj79048ce2005-02-18 08:28:32 +0000560 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000561 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000562
563 /* Everything must be page-aligned */
sewardj548be6d2005-02-16 01:31:37 +0000564 vg_assert(IS_PAGE_ALIGNED(addr));
565 vg_assert(IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000566
sewardj548be6d2005-02-16 01:31:37 +0000567 for (i = 0; i < segments_used; i++) {
568 s = &segments[i];
569 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000570
sewardj548be6d2005-02-16 01:31:37 +0000571 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000572 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000573 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000574
fitzhardinge1a303042003-12-22 08:48:50 +0000575 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000576 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000577 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000578 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000579 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000580
581 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000582 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000583 addr < s_end &&
584 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000585 /* this segment's tail is truncated by [addr, addr+len)
586 -> truncate tail
587 */
sewardj1024cf72005-02-28 14:39:21 +0000588 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000589 s->len = addr - s->addr;
590
591 if (debug)
592 VG_(printf)(" case 1: s->len=%d\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000593 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000594 /* this segment's head is truncated by [addr, addr+len)
595 -> truncate head
596 */
sewardj548be6d2005-02-16 01:31:37 +0000597 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000598
599 if (debug)
sewardj79048ce2005-02-18 08:28:32 +0000600 VG_(printf)(" case 2: s->addr=%p s->len=%d delta=%d\n",
601 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000602
sewardj1024cf72005-02-28 14:39:21 +0000603 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000604 s->addr += delta;
605 s->offset += delta;
606 s->len -= delta;
607
608 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000609 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000610 /* this segment is completely contained within [addr, addr+len)
611 -> delete segment
612 */
sewardj1024cf72005-02-28 14:39:21 +0000613 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000614 delete_segment_at(i);
fitzhardinge98abfc72003-12-16 02:05:15 +0000615
616 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000617 VG_(printf)(" case 3: seg %d deleted\n", i);
618 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000619 /* [addr, addr+len) is contained within a single segment
620 -> split segment into 3, delete middle portion
621 */
sewardj1024cf72005-02-28 14:39:21 +0000622 Int i_middle;
623 dump_translations_from(s);
624 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000625 vg_assert(i_middle != -1);
626 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000627 vg_assert(segments[i_middle].addr == addr);
628 delete_segment_at(i_middle);
fitzhardinge98abfc72003-12-16 02:05:15 +0000629
630 if (debug)
631 VG_(printf)(" case 4: subrange %p-%p deleted\n",
632 addr, addr+len);
633 }
634 }
sewardj79048ce2005-02-18 08:28:32 +0000635 preen_segments();
636 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000637}
638
sewardj548be6d2005-02-16 01:31:37 +0000639
640/* Add a binding of [addr,addr+len) to
641 (prot,flags,dev,ino,off,filename) in the segment array.
642 Delete/truncate any previous mapping(s) covering that range.
643*/
644void
645VG_(map_file_segment)( Addr addr, SizeT len,
646 UInt prot, UInt flags,
647 UInt dev, UInt ino, ULong off,
648 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000649{
fitzhardinge98abfc72003-12-16 02:05:15 +0000650 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000651 Segment* s;
652 Int idx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000653
654 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000655 VG_(printf)(
656 "\n"
657 "map_file_segment(addr=%p len=%llu prot=0x%x flags=0x%x\n"
658 " dev=0x%4x ino=%d off=%ld\n"
659 " filename='%s')\n",
660 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000661
662 /* Everything must be page-aligned */
sewardj548be6d2005-02-16 01:31:37 +0000663 vg_assert(IS_PAGE_ALIGNED(addr));
fitzhardinge98abfc72003-12-16 02:05:15 +0000664 len = PGROUNDUP(len);
665
sewardj548be6d2005-02-16 01:31:37 +0000666 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
667 VG_(unmap_range)(addr, len);
668
669 /* and now install this one */
670 idx = create_segment(addr);
671 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
672 vg_assert(idx != -1);
673 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000674
sewardj79048ce2005-02-18 08:28:32 +0000675 s = &segments[idx];
676 vg_assert(s->addr == addr);
677 s->prot = prot;
678 s->flags = flags;
679 s->len = len;
680 s->offset = off;
681 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
682 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
683 s->dev = dev;
684 s->ino = ino;
685 s->symtab = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000686
sewardj79048ce2005-02-18 08:28:32 +0000687 /* Clean up right now */
688 preen_segments();
689 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000690
691 /* If this mapping is of the beginning of a file, isn't part of
692 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000693 file, then try reading symbols from it.
694 */
695 if (s->symtab == NULL
696 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
697 if (off == 0
698 && s->fnIdx != -1
699 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
700 && len >= VKI_PAGE_SIZE
701 && VG_(is_object_file)((void *)addr)) {
nethercote71980f02004-01-24 18:18:54 +0000702 s->symtab = VG_(read_seg_symbols)(s);
nethercote71980f02004-01-24 18:18:54 +0000703 if (s->symtab != NULL) {
704 s->flags |= SF_DYNLIB;
705 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000706 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000707#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000708 const SegInfo *info;
709
710 /* Otherwise see if an existing symtab applies to this Segment */
711 for(info = VG_(next_seginfo)(NULL);
712 info != NULL;
713 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000714 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
715 {
fitzhardinge98abfc72003-12-16 02:05:15 +0000716 s->symtab = (SegInfo *)info;
717 VG_(symtab_incref)((SegInfo *)info);
718 }
719 }
sewardj79048ce2005-02-18 08:28:32 +0000720#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000721 }
722 }
723
724 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000725 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000726}
727
nethercote8b5f40c2004-11-02 13:29:50 +0000728void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000729 Int fd, ULong off, const Char *filename)
730{
731 struct vki_stat st;
732 Char *name = NULL;
733
734 st.st_dev = 0;
735 st.st_ino = 0;
736
737 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000738 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000739
740 if (VG_(fstat)(fd, &st) < 0)
741 flags &= ~SF_FILE;
742 }
743
sewardj79048ce2005-02-18 08:28:32 +0000744 if ((flags & SF_FILE) && filename == NULL && fd != -1)
745 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000746
747 if (filename == NULL)
748 filename = name;
749
sewardj79048ce2005-02-18 08:28:32 +0000750 VG_(map_file_segment)(addr, len, prot, flags,
751 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000752}
753
nethercote8b5f40c2004-11-02 13:29:50 +0000754void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000755{
756 flags &= ~SF_FILE;
757
758 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
759}
760
761/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000762void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000763{
sewardj79048ce2005-02-18 08:28:32 +0000764 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000765 static const Bool debug = False || mem_debug;
766
767 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000768 VG_(printf)("\nmprotect_range(%p, %d, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000769
770 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000771
772 /* Everything must be page-aligned */
sewardj79048ce2005-02-18 08:28:32 +0000773 vg_assert(IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000774 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000775
sewardj79048ce2005-02-18 08:28:32 +0000776 split_segment(a);
777 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000778
sewardj548be6d2005-02-16 01:31:37 +0000779 r = find_segment(a);
780 vg_assert(r != -1);
781 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000782
783 preen_segments();
784
sewardje517b802005-02-16 01:58:51 +0000785 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000786}
787
sewardj79048ce2005-02-18 08:28:32 +0000788
sewardj548be6d2005-02-16 01:31:37 +0000789/* Try to find a map space for [addr,addr+len). If addr==0, it means
790 the caller is prepared to accept a space at any location; if not,
791 we will try for addr, but fail if we can't get it. This mimics
792 mmap fixed vs mmap not-fixed.
793*/
nethercote8b5f40c2004-11-02 13:29:50 +0000794Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000795{
fitzhardingee3632c62003-12-22 10:58:06 +0000796 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000797 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000798 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000799 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
800 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000801 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
802 Int i, i_any, i_fixed, i_final;
803 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000804
sewardj548be6d2005-02-16 01:31:37 +0000805 Bool fixed;
806
sewardje517b802005-02-16 01:58:51 +0000807 if (debug) {
808 VG_(printf)("\n\n");
809 VG_(printf)("find_map_space(%p, %d, %d) ...\n",
810 addr, len, for_client);
811 }
812
813 if (0) show_segments("find_map_space: start");
814
sewardj548be6d2005-02-16 01:31:37 +0000815 if (addr == 0) {
816 fixed = False;
817 } else {
818 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000819 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000820 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000821 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000822 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000823
824 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000825 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000826 len = PGROUNDUP(len);
827
nethercote73b526f2004-10-31 18:48:21 +0000828 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000829
sewardj548be6d2005-02-16 01:31:37 +0000830 /* Scan the segment list, looking for a hole which satisfies the
831 requirements. At each point i we ask the question "can we use
832 the hole in between segments[i-1] and segments[i] ?" */
833 i_any = i_fixed = -1;
834 hstart_any = hstart_fixed = 0;
835
836 hole_start = hole_end = 0;
837
838 /* Iterate over all possible holes, generating them into
839 hole_start/hole_end. Filter out invalid ones. Then see if any
840 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
841 */
842 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
843 if (i == 0) {
844 hole_start = 0;
845 hole_end = segments[0].addr-1;
846 }
847 else {
848 vg_assert(segments_used > 0);
849 if (i == segments_used) {
850 hole_start = segments[i-1].addr + segments[i-1].len;
851 hole_end = ~(Addr)0;
852 } else {
853 hole_start = segments[i-1].addr + segments[i-1].len;
854 hole_end = segments[i].addr - 1;
855 }
856 }
857
858 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
859
860 /* ignore zero-sized holes */
861 if (hole_start == hole_end+1)
862 continue;
863
864 vg_assert(IS_PAGE_ALIGNED(hole_start));
865 vg_assert(IS_PAGE_ALIGNED(hole_end+1));
866
867 /* ignore holes which fall outside the allowable area */
868 if (!(hole_start >= base && hole_end <= limit))
869 continue;
870
871 vg_assert(hole_end > hole_start);
872 hole_len = hole_end - hole_start + 1;
sewardjb5f6f512005-03-10 23:59:00 +0000873 vg_assert(IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000874
875 if (hole_len >= len && i_any == -1) {
876 /* It will at least fit in this hole. */
877 i_any = i;
878 hstart_any = hole_start;
879 }
880
sewardjb5f6f512005-03-10 23:59:00 +0000881 if (fixed && hole_start <= addr
882 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000883 /* We were asked for a fixed mapping, and this hole works.
884 Bag it -- and stop searching as further searching is
885 pointless. */
886 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000887 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000888 break;
889 }
890 }
891
892 /* Summarise the final decision into i_final/hstart_final. */
893 i_final = -1;
894 hstart_final = 0;
895
896 if (fixed) {
897 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000898 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000899 } else {
900 i_final = i_any;
901 hstart_final = hstart_any;
902 }
903
904
905 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000906 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000907 else
908 ret = 0; /* not found */
909
910 if (debug)
sewardje517b802005-02-16 01:58:51 +0000911 VG_(printf)("find_map_space(%p, %d, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000912 addr, len, for_client, ret);
913
sewardjb5f6f512005-03-10 23:59:00 +0000914 if (fixed) {
915 vg_assert(ret == 0 || ret == addrOrig);
916 }
917
sewardj548be6d2005-02-16 01:31:37 +0000918 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000919}
920
sewardj79048ce2005-02-18 08:28:32 +0000921
sewardjb5f6f512005-03-10 23:59:00 +0000922/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000923 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000924 mapping over any part of the address space which is not covered
925 by an entry in the segment list.
926
927 This is designed for use around system calls which allocate
928 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000929 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000930 address with VG_(find_map_space) and then adding a segment for
931 it and padding the address space valgrind can ensure that the
932 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000933void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000934{
sewardjb5f6f512005-03-10 23:59:00 +0000935 vg_assert(0);
936#if 0
937 Addr addr = (start == 0) ? VG_(client_base) : start;
thughes9aaebc32004-07-15 23:13:37 +0000938 Segment *s = VG_(SkipNode_First)(&sk_segments);
thughes9aaebc32004-07-15 23:13:37 +0000939 Addr ret;
940
nethercote820bd8c2004-09-07 23:04:49 +0000941 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000942 if (addr < s->addr) {
nethercotef18ca392004-11-04 18:45:22 +0000943 PLATFORM_DO_MMAP(ret, addr, s->addr - addr, 0,
944 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
945 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000946 }
947
948 addr = s->addr + s->len;
949 s = VG_(SkipNode_Next)(&sk_segments, s);
950 }
951
nethercote820bd8c2004-09-07 23:04:49 +0000952 if (addr <= VG_(valgrind_last)) {
nethercotef18ca392004-11-04 18:45:22 +0000953 PLATFORM_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
954 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
955 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000956 }
957
958 return;
sewardjb5f6f512005-03-10 23:59:00 +0000959#endif
thughes9aaebc32004-07-15 23:13:37 +0000960}
961
thughesc70b8c62004-07-16 23:07:58 +0000962/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000963 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +0000964void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000965{
sewardjb5f6f512005-03-10 23:59:00 +0000966vg_assert(0);
967#if 0
968 Addr addr = (start == 0) ? VG_(client_base) : start;
thughes9aaebc32004-07-15 23:13:37 +0000969 Segment *s = VG_(SkipNode_First)(&sk_segments);
970 Int ret;
971
nethercote820bd8c2004-09-07 23:04:49 +0000972 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000973 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +0000974 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +0000975 }
976
977 addr = s->addr + s->len;
978 s = VG_(SkipNode_Next)(&sk_segments, s);
979 }
980
nethercote820bd8c2004-09-07 23:04:49 +0000981 if (addr <= VG_(valgrind_last)) {
njnca6fef02004-11-29 16:49:18 +0000982 ret = VG_(do_syscall2)(__NR_munmap, addr, (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +0000983 }
984
985 return;
sewardjb5f6f512005-03-10 23:59:00 +0000986#endif
thughes9aaebc32004-07-15 23:13:37 +0000987}
988
sewardj548be6d2005-02-16 01:31:37 +0000989/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000990Segment *VG_(find_segment)(Addr a)
991{
sewardj548be6d2005-02-16 01:31:37 +0000992 Int r = find_segment(a);
993 if (0) show_segments("find_segment");
994 if (r == -1) return NULL;
995 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +0000996}
997
sewardj548be6d2005-02-16 01:31:37 +0000998/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
999 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1000 a segment is a checked error.
1001*/
1002Segment *VG_(find_segment_above_unmapped)(Addr a)
1003{
1004 Int r = find_segment_above_unmapped(a);
1005 if (0) show_segments("find_segment_above_unmapped");
1006 if (r == -1) return NULL;
1007 return &segments[r];
1008}
1009
1010/* Assumes that 'a' is in some segment. Finds the next segment along,
1011 or NULL if none. Passing 'a' which is in fact not in a segment is
1012 a checked error.
1013*/
1014Segment *VG_(find_segment_above_mapped)(Addr a)
1015{
1016 Int r = find_segment_above_mapped(a);
1017 if (0) show_segments("find_segment_above_mapped");
1018 if (r == -1) return NULL;
1019 return &segments[r];
1020}
1021
1022
sewardjde4a1d02002-03-22 01:27:54 +00001023/*------------------------------------------------------------*/
1024/*--- Tracking permissions around %esp changes. ---*/
1025/*------------------------------------------------------------*/
1026
1027/*
1028 The stack
1029 ~~~~~~~~~
1030 The stack's segment seems to be dynamically extended downwards
1031 by the kernel as the stack pointer moves down. Initially, a
1032 1-page (4k) stack is allocated. When %esp moves below that for
1033 the first time, presumably a page fault occurs. The kernel
1034 detects that the faulting address is in the range from %esp upwards
1035 to the current valid stack. It then extends the stack segment
1036 downwards for enough to cover the faulting address, and resumes
1037 the process (invisibly). The process is unaware of any of this.
1038
1039 That means that Valgrind can't spot when the stack segment is
1040 being extended. Fortunately, we want to precisely and continuously
1041 update stack permissions around %esp, so we need to spot all
1042 writes to %esp anyway.
1043
1044 The deal is: when %esp is assigned a lower value, the stack is
1045 being extended. Create a secondary maps to fill in any holes
1046 between the old stack ptr and this one, if necessary. Then
1047 mark all bytes in the area just "uncovered" by this %esp change
1048 as write-only.
1049
1050 When %esp goes back up, mark the area receded over as unreadable
1051 and unwritable.
1052
1053 Just to record the %esp boundary conditions somewhere convenient:
1054 %esp always points to the lowest live byte in the stack. All
1055 addresses below %esp are not live; those at and above it are.
1056*/
1057
sewardjde4a1d02002-03-22 01:27:54 +00001058/* Kludgey ... how much does %esp have to change before we reckon that
1059 the application is switching stacks ? */
njn9b007f62003-04-07 14:40:25 +00001060#define VG_PLAUSIBLE_STACK_SIZE 8000000
1061#define VG_HUGE_DELTA (VG_PLAUSIBLE_STACK_SIZE / 4)
sewardjde4a1d02002-03-22 01:27:54 +00001062
njn9b007f62003-04-07 14:40:25 +00001063/* This function gets called if new_mem_stack and/or die_mem_stack are
nethercote996901a2004-08-03 13:29:09 +00001064 tracked by the tool, and one of the specialised cases (eg. new_mem_stack_4)
njn9b007f62003-04-07 14:40:25 +00001065 isn't used in preference */
sewardj2a99cf62004-11-24 10:44:19 +00001066REGPARM(2)
1067void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001068{
nethercotefc646ee2004-11-04 19:29:06 +00001069 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001070
njn9b007f62003-04-07 14:40:25 +00001071 if (delta < -(VG_HUGE_DELTA) || VG_HUGE_DELTA < delta) {
1072 /* %esp has changed by more than HUGE_DELTA. We take this to mean
1073 that the application is switching to a new stack, for whatever
1074 reason.
1075
1076 JRS 20021001: following discussions with John Regehr, if a stack
1077 switch happens, it seems best not to mess at all with memory
1078 permissions. Seems to work well with Netscape 4.X. Really the
1079 only remaining difficulty is knowing exactly when a stack switch is
1080 happening. */
1081 if (VG_(clo_verbosity) > 1)
1082 VG_(message)(Vg_UserMsg, "Warning: client switching stacks? "
nethercote15218bd2004-09-11 15:11:47 +00001083 "%%esp: %p --> %p", old_SP, new_SP);
njn9b007f62003-04-07 14:40:25 +00001084 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001085 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001086
njn9b007f62003-04-07 14:40:25 +00001087 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001088 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001089 }
1090}
1091
jsgf855d93d2003-10-13 22:26:55 +00001092static jmp_buf segv_jmpbuf;
1093
1094static void segv_handler(Int seg)
1095{
1096 __builtin_longjmp(segv_jmpbuf, 1);
1097 VG_(core_panic)("longjmp failed");
1098}
1099
1100/*
sewardjb5f6f512005-03-10 23:59:00 +00001101 Test if a piece of memory is addressable with at least the "prot"
1102 protection permissions by examining the underlying segments.
1103
1104 Really this is a very stupid algorithm and we could do much
1105 better by iterating through the segment array instead of through
1106 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001107 */
sewardjb5f6f512005-03-10 23:59:00 +00001108Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001109{
sewardjb5f6f512005-03-10 23:59:00 +00001110 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001111
sewardjb5f6f512005-03-10 23:59:00 +00001112 if ((p + size) < p)
1113 return False; /* reject wraparounds */
1114 if (size == 0)
1115 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001116
sewardjb5f6f512005-03-10 23:59:00 +00001117 p = PGROUNDDN(p);
1118 size = PGROUNDUP(size);
1119 vg_assert(IS_PAGE_ALIGNED(p));
1120 vg_assert(IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001121
sewardjb5f6f512005-03-10 23:59:00 +00001122 for (; size > 0; size -= VKI_PAGE_SIZE) {
1123 seg = VG_(find_segment)(p);
1124 if (!seg)
1125 return False;
1126 if ((seg->prot & prot) != prot)
1127 return False;
1128 p += VKI_PAGE_SIZE;
1129 }
jsgf855d93d2003-10-13 22:26:55 +00001130
sewardjb5f6f512005-03-10 23:59:00 +00001131 return True;
jsgf855d93d2003-10-13 22:26:55 +00001132}
1133
sewardjb5f6f512005-03-10 23:59:00 +00001134
sewardjde4a1d02002-03-22 01:27:54 +00001135/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001136/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001137/*--------------------------------------------------------------------*/
1138
nethercote57e36b32004-07-10 14:56:28 +00001139// Returns 0 on failure.
nethercote928a5f72004-11-03 18:10:37 +00001140Addr VG_(client_alloc)(Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001141{
1142 len = PGROUNDUP(len);
1143
njnca82cc02004-11-22 17:18:48 +00001144 tl_assert(!(sf_flags & SF_FIXED));
1145 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001146
nethercote8e9eab02004-07-11 18:01:06 +00001147 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1148 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1149 sf_flags | SF_CORE, -1, 0);
1150 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001151 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001152 else
1153 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001154}
1155
1156void VG_(client_free)(Addr addr)
1157{
1158 Segment *s = VG_(find_segment)(addr);
1159
sewardj548be6d2005-02-16 01:31:37 +00001160vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001161 if (s == NULL || s->addr != addr || !(s->flags & SF_CORE)) {
1162 VG_(message)(Vg_DebugMsg, "VG_(client_free)(%p) - no CORE memory found there", addr);
1163 return;
1164 }
1165
1166 VG_(munmap)((void *)s->addr, s->len);
1167}
1168
nethercote88a90162004-07-10 16:59:25 +00001169/*--------------------------------------------------------------------*/
1170/*--- Querying memory layout ---*/
1171/*--------------------------------------------------------------------*/
1172
fitzhardinge98abfc72003-12-16 02:05:15 +00001173Bool VG_(is_client_addr)(Addr a)
1174{
1175 return a >= VG_(client_base) && a < VG_(client_end);
1176}
1177
1178Bool VG_(is_shadow_addr)(Addr a)
1179{
sewardj548be6d2005-02-16 01:31:37 +00001180vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001181 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1182}
1183
1184Bool VG_(is_valgrind_addr)(Addr a)
1185{
sewardj548be6d2005-02-16 01:31:37 +00001186vg_assert(0);
nethercote820bd8c2004-09-07 23:04:49 +00001187 return a >= VG_(valgrind_base) && a <= VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +00001188}
1189
1190Addr VG_(get_client_base)(void)
1191{
sewardj548be6d2005-02-16 01:31:37 +00001192vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001193 return VG_(client_base);
1194}
1195
1196Addr VG_(get_client_end)(void)
1197{
sewardj548be6d2005-02-16 01:31:37 +00001198vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001199 return VG_(client_end);
1200}
1201
1202Addr VG_(get_client_size)(void)
1203{
sewardj548be6d2005-02-16 01:31:37 +00001204vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001205 return VG_(client_end)-VG_(client_base);
1206}
1207
1208Addr VG_(get_shadow_base)(void)
1209{
sewardj548be6d2005-02-16 01:31:37 +00001210vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001211 return VG_(shadow_base);
1212}
1213
1214Addr VG_(get_shadow_end)(void)
1215{
sewardj548be6d2005-02-16 01:31:37 +00001216vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001217 return VG_(shadow_end);
1218}
1219
1220Addr VG_(get_shadow_size)(void)
1221{
1222 return VG_(shadow_end)-VG_(shadow_base);
1223}
1224
nethercote88a90162004-07-10 16:59:25 +00001225/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001226/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001227/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001228
1229void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1230{
sewardj548be6d2005-02-16 01:31:37 +00001231vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001232 if (0)
1233 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1234
1235 vg_assert(VG_(needs).shadow_memory);
1236 vg_assert(VG_(defined_init_shadow_page)());
1237
1238 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1239 p = PGROUNDDN(p);
1240
1241 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1242
1243 if (call_init)
1244 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001245 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001246 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1247
nethercote73b526f2004-10-31 18:48:21 +00001248 p += VKI_PAGE_SIZE;
1249 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001250 }
1251}
1252
1253void *VG_(shadow_alloc)(UInt size)
1254{
1255 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001256 Addr try_here;
1257 Int r;
1258
1259 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001260
1261 vg_assert(VG_(needs).shadow_memory);
1262 vg_assert(!VG_(defined_init_shadow_page)());
1263
1264 size = PGROUNDUP(size);
1265
1266 if (shadow_alloc == 0)
1267 shadow_alloc = VG_(shadow_base);
1268
1269 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001270 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001271
sewardj79048ce2005-02-18 08:28:32 +00001272 try_here = shadow_alloc;
1273 vg_assert(IS_PAGE_ALIGNED(try_here));
1274 vg_assert(IS_PAGE_ALIGNED(size));
1275 vg_assert(size > 0);
1276
1277 if (0)
1278 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1279
1280 /* this is big-bang allocated, so we don't expect to find a listed
1281 segment for it. */
1282 /* This is really an absolute disgrace. Sometimes the big-bang
1283 mapping is in the list (due to re-reads of /proc/self/maps,
1284 presumably) and sometimes it isn't. */
1285#if 0
1286 r = find_segment(try_here);
1287 vg_assert(r == -1);
1288 r = find_segment(try_here+size-1);
1289 vg_assert(r == -1);
1290#endif
1291
1292 r = VG_(mprotect_native)( (void*)try_here,
1293 size, VKI_PROT_READ|VKI_PROT_WRITE );
1294
1295 if (r != 0)
1296 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001297
1298 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001299 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001300
sewardj79048ce2005-02-18 08:28:32 +00001301 failed:
1302 VG_(printf)(
1303 "valgrind: Could not allocate address space (%p bytes)\n"
1304 "valgrind: for shadow memory chunk.\n",
1305 (void*)size
1306 );
1307 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001308}
1309
1310/*--------------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +00001311/*--- end vg_memory.c ---*/
1312/*--------------------------------------------------------------------*/