blob: e10a83992f78e47043a8185c77ba34ae4c5c473f [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/*--------------------------------------------------------------*/
479/*--- ---*/
480/*--------------------------------------------------------------*/
481
fitzhardinge98abfc72003-12-16 02:05:15 +0000482
483static Int addrcmp(const void *ap, const void *bp)
484{
485 Addr a = *(Addr *)ap;
486 Addr b = *(Addr *)bp;
487 Int ret;
488
489 if (a == b)
490 ret = 0;
491 else
492 ret = (a < b) ? -1 : 1;
493
494 return ret;
495}
496
497static Char *straddr(void *p)
498{
499 static Char buf[16];
500
501 VG_(sprintf)(buf, "%p", *(Addr *)p);
502
503 return buf;
504}
505
506static SkipList sk_segments = SKIPLIST_INIT(Segment, addr, addrcmp, straddr, VG_AR_CORE);
507
508/*--------------------------------------------------------------*/
509/*--- Maintain an ordered list of all the client's mappings ---*/
510/*--------------------------------------------------------------*/
511
nethercote8991d5a2004-11-03 17:07:46 +0000512Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000513{
514 Addr se = s->addr+s->len;
515 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000516 vg_assert(pe >= p);
517
518 return (p >= s->addr && pe <= se);
519}
520
nethercote8991d5a2004-11-03 17:07:46 +0000521Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000522{
523 Addr se = s->addr+s->len;
524 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000525 vg_assert(pe >= p);
526
527 return (p < se && pe > s->addr);
528}
529
sewardj1024cf72005-02-28 14:39:21 +0000530#if 0
531/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000532/* Prepare a Segment structure for recycling by freeing everything
533 hanging off it. */
534static void recycleseg(Segment *s)
535{
536 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000537 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000538
539 if (s->filename != NULL)
540 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
541
542 /* keep the SegInfo, if any - it probably still applies */
543}
544
545/* When freeing a Segment, also clean up every one else's ideas of
546 what was going on in that range of memory */
547static void freeseg(Segment *s)
548{
549 recycleseg(s);
550 if (s->symtab != NULL) {
nethercote8991d5a2004-11-03 17:07:46 +0000551 VG_(symtab_decref)(s->symtab, s->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000552 s->symtab = NULL;
553 }
554
555 VG_(SkipNode_Free)(&sk_segments, s);
556}
sewardj1024cf72005-02-28 14:39:21 +0000557#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000558
sewardj1024cf72005-02-28 14:39:21 +0000559
560/* Get rid of any translations arising from s. */
561/* Note, this is not really the job of the low level memory manager.
562 When it comes time to rewrite this subsystem, clean this up. */
563static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000564{
sewardj1024cf72005-02-28 14:39:21 +0000565 if (s->flags & SF_CODE) {
566 VG_(discard_translations)(s->addr, s->len);
567 if (0)
568 VG_(printf)("dumping translations in %p .. %p\n",
569 s->addr, s->addr+s->len);
570 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000571}
572
sewardj1024cf72005-02-28 14:39:21 +0000573
fitzhardinge98abfc72003-12-16 02:05:15 +0000574/* This unmaps all the segments in the range [addr, addr+len); any
575 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000576void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000577{
fitzhardingee3632c62003-12-22 10:58:06 +0000578 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000579 Segment* s;
580 Addr end, s_end;
581 Int i;
fitzhardinge98abfc72003-12-16 02:05:15 +0000582
583 if (len == 0)
584 return;
585
fitzhardinge1a4adf02003-12-22 10:42:59 +0000586 len = PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000587
fitzhardinge98abfc72003-12-16 02:05:15 +0000588 if (debug)
589 VG_(printf)("unmap_range(%p, %d)\n", addr, len);
sewardj79048ce2005-02-18 08:28:32 +0000590 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000591 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000592
593 /* Everything must be page-aligned */
sewardj548be6d2005-02-16 01:31:37 +0000594 vg_assert(IS_PAGE_ALIGNED(addr));
595 vg_assert(IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000596
sewardj548be6d2005-02-16 01:31:37 +0000597 for (i = 0; i < segments_used; i++) {
598 s = &segments[i];
599 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000600
sewardj548be6d2005-02-16 01:31:37 +0000601 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000602 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000603 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000604
fitzhardinge1a303042003-12-22 08:48:50 +0000605 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000606 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000607 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000608 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000609 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000610
611 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000612 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000613 addr < s_end &&
614 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000615 /* this segment's tail is truncated by [addr, addr+len)
616 -> truncate tail
617 */
sewardj1024cf72005-02-28 14:39:21 +0000618 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000619 s->len = addr - s->addr;
620
621 if (debug)
622 VG_(printf)(" case 1: s->len=%d\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000623 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000624 /* this segment's head is truncated by [addr, addr+len)
625 -> truncate head
626 */
sewardj548be6d2005-02-16 01:31:37 +0000627 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000628
629 if (debug)
sewardj79048ce2005-02-18 08:28:32 +0000630 VG_(printf)(" case 2: s->addr=%p s->len=%d delta=%d\n",
631 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000632
sewardj1024cf72005-02-28 14:39:21 +0000633 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000634 s->addr += delta;
635 s->offset += delta;
636 s->len -= delta;
637
638 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000639 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000640 /* this segment is completely contained within [addr, addr+len)
641 -> delete segment
642 */
sewardj1024cf72005-02-28 14:39:21 +0000643 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000644 delete_segment_at(i);
fitzhardinge98abfc72003-12-16 02:05:15 +0000645
646 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000647 VG_(printf)(" case 3: seg %d deleted\n", i);
648 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000649 /* [addr, addr+len) is contained within a single segment
650 -> split segment into 3, delete middle portion
651 */
sewardj1024cf72005-02-28 14:39:21 +0000652 Int i_middle;
653 dump_translations_from(s);
654 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000655 vg_assert(i_middle != -1);
656 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000657 vg_assert(segments[i_middle].addr == addr);
658 delete_segment_at(i_middle);
fitzhardinge98abfc72003-12-16 02:05:15 +0000659
660 if (debug)
661 VG_(printf)(" case 4: subrange %p-%p deleted\n",
662 addr, addr+len);
663 }
664 }
sewardj79048ce2005-02-18 08:28:32 +0000665 preen_segments();
666 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000667}
668
sewardj548be6d2005-02-16 01:31:37 +0000669
670/* Add a binding of [addr,addr+len) to
671 (prot,flags,dev,ino,off,filename) in the segment array.
672 Delete/truncate any previous mapping(s) covering that range.
673*/
674void
675VG_(map_file_segment)( Addr addr, SizeT len,
676 UInt prot, UInt flags,
677 UInt dev, UInt ino, ULong off,
678 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000679{
fitzhardinge98abfc72003-12-16 02:05:15 +0000680 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000681 Segment* s;
682 Int idx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000683
684 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000685 VG_(printf)(
686 "\n"
687 "map_file_segment(addr=%p len=%llu prot=0x%x flags=0x%x\n"
688 " dev=0x%4x ino=%d off=%ld\n"
689 " filename='%s')\n",
690 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000691
692 /* Everything must be page-aligned */
sewardj548be6d2005-02-16 01:31:37 +0000693 vg_assert(IS_PAGE_ALIGNED(addr));
fitzhardinge98abfc72003-12-16 02:05:15 +0000694 len = PGROUNDUP(len);
695
sewardj548be6d2005-02-16 01:31:37 +0000696 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
697 VG_(unmap_range)(addr, len);
698
699 /* and now install this one */
700 idx = create_segment(addr);
701 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
702 vg_assert(idx != -1);
703 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000704
sewardj79048ce2005-02-18 08:28:32 +0000705 s = &segments[idx];
706 vg_assert(s->addr == addr);
707 s->prot = prot;
708 s->flags = flags;
709 s->len = len;
710 s->offset = off;
711 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
712 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
713 s->dev = dev;
714 s->ino = ino;
715 s->symtab = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000716
sewardj79048ce2005-02-18 08:28:32 +0000717 /* Clean up right now */
718 preen_segments();
719 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000720
721 /* If this mapping is of the beginning of a file, isn't part of
722 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000723 file, then try reading symbols from it.
724 */
725 if (s->symtab == NULL
726 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
727 if (off == 0
728 && s->fnIdx != -1
729 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
730 && len >= VKI_PAGE_SIZE
731 && VG_(is_object_file)((void *)addr)) {
nethercote71980f02004-01-24 18:18:54 +0000732 s->symtab = VG_(read_seg_symbols)(s);
nethercote71980f02004-01-24 18:18:54 +0000733 if (s->symtab != NULL) {
734 s->flags |= SF_DYNLIB;
735 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000736 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000737#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000738 const SegInfo *info;
739
740 /* Otherwise see if an existing symtab applies to this Segment */
741 for(info = VG_(next_seginfo)(NULL);
742 info != NULL;
743 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000744 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
745 {
fitzhardinge98abfc72003-12-16 02:05:15 +0000746 s->symtab = (SegInfo *)info;
747 VG_(symtab_incref)((SegInfo *)info);
748 }
749 }
sewardj79048ce2005-02-18 08:28:32 +0000750#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000751 }
752 }
753
754 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000755 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000756}
757
nethercote8b5f40c2004-11-02 13:29:50 +0000758void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000759 Int fd, ULong off, const Char *filename)
760{
761 struct vki_stat st;
762 Char *name = NULL;
763
764 st.st_dev = 0;
765 st.st_ino = 0;
766
767 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000768 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000769
770 if (VG_(fstat)(fd, &st) < 0)
771 flags &= ~SF_FILE;
772 }
773
sewardj79048ce2005-02-18 08:28:32 +0000774 if ((flags & SF_FILE) && filename == NULL && fd != -1)
775 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000776
777 if (filename == NULL)
778 filename = name;
779
sewardj79048ce2005-02-18 08:28:32 +0000780 VG_(map_file_segment)(addr, len, prot, flags,
781 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000782}
783
nethercote8b5f40c2004-11-02 13:29:50 +0000784void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000785{
786 flags &= ~SF_FILE;
787
788 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
789}
790
791/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000792void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000793{
sewardj79048ce2005-02-18 08:28:32 +0000794 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000795 static const Bool debug = False || mem_debug;
796
797 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000798 VG_(printf)("\nmprotect_range(%p, %d, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000799
800 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000801
802 /* Everything must be page-aligned */
sewardj79048ce2005-02-18 08:28:32 +0000803 vg_assert(IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000804 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000805
sewardj79048ce2005-02-18 08:28:32 +0000806 split_segment(a);
807 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000808
sewardj548be6d2005-02-16 01:31:37 +0000809 r = find_segment(a);
810 vg_assert(r != -1);
811 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000812
813 preen_segments();
814
sewardje517b802005-02-16 01:58:51 +0000815 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000816}
817
sewardj79048ce2005-02-18 08:28:32 +0000818
sewardj548be6d2005-02-16 01:31:37 +0000819/* Try to find a map space for [addr,addr+len). If addr==0, it means
820 the caller is prepared to accept a space at any location; if not,
821 we will try for addr, but fail if we can't get it. This mimics
822 mmap fixed vs mmap not-fixed.
823*/
nethercote8b5f40c2004-11-02 13:29:50 +0000824Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000825{
fitzhardingee3632c62003-12-22 10:58:06 +0000826 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000827 Addr ret;
nethercotea8bc3802004-10-19 17:54:02 +0000828 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
829 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000830 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
831 Int i, i_any, i_fixed, i_final;
832 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000833
sewardj548be6d2005-02-16 01:31:37 +0000834 Bool fixed;
835
sewardje517b802005-02-16 01:58:51 +0000836 if (debug) {
837 VG_(printf)("\n\n");
838 VG_(printf)("find_map_space(%p, %d, %d) ...\n",
839 addr, len, for_client);
840 }
841
842 if (0) show_segments("find_map_space: start");
843
sewardj548be6d2005-02-16 01:31:37 +0000844 if (addr == 0) {
845 fixed = False;
846 } else {
847 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000848 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000849 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000850 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000851 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000852
853 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000854 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000855 len = PGROUNDUP(len);
856
nethercote73b526f2004-10-31 18:48:21 +0000857 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000858
sewardj548be6d2005-02-16 01:31:37 +0000859 /* Scan the segment list, looking for a hole which satisfies the
860 requirements. At each point i we ask the question "can we use
861 the hole in between segments[i-1] and segments[i] ?" */
862 i_any = i_fixed = -1;
863 hstart_any = hstart_fixed = 0;
864
865 hole_start = hole_end = 0;
866
867 /* Iterate over all possible holes, generating them into
868 hole_start/hole_end. Filter out invalid ones. Then see if any
869 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
870 */
871 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
872 if (i == 0) {
873 hole_start = 0;
874 hole_end = segments[0].addr-1;
875 }
876 else {
877 vg_assert(segments_used > 0);
878 if (i == segments_used) {
879 hole_start = segments[i-1].addr + segments[i-1].len;
880 hole_end = ~(Addr)0;
881 } else {
882 hole_start = segments[i-1].addr + segments[i-1].len;
883 hole_end = segments[i].addr - 1;
884 }
885 }
886
887 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
888
889 /* ignore zero-sized holes */
890 if (hole_start == hole_end+1)
891 continue;
892
893 vg_assert(IS_PAGE_ALIGNED(hole_start));
894 vg_assert(IS_PAGE_ALIGNED(hole_end+1));
895
896 /* ignore holes which fall outside the allowable area */
897 if (!(hole_start >= base && hole_end <= limit))
898 continue;
899
900 vg_assert(hole_end > hole_start);
901 hole_len = hole_end - hole_start + 1;
902
903 if (hole_len >= len && i_any == -1) {
904 /* It will at least fit in this hole. */
905 i_any = i;
906 hstart_any = hole_start;
907 }
908
909 if (fixed && hole_start <= addr && hole_len >= len) {
910 /* We were asked for a fixed mapping, and this hole works.
911 Bag it -- and stop searching as further searching is
912 pointless. */
913 i_fixed = i;
914 hstart_fixed = hole_start;
915 break;
916 }
917 }
918
919 /* Summarise the final decision into i_final/hstart_final. */
920 i_final = -1;
921 hstart_final = 0;
922
923 if (fixed) {
924 i_final = i_fixed;
925 hstart_final = hstart_fixed;
926 } else {
927 i_final = i_any;
928 hstart_final = hstart_any;
929 }
930
931
932 if (i_final != -1)
933 ret = hstart_final + VKI_PAGE_SIZE; /* skip leading redzone */
934 else
935 ret = 0; /* not found */
936
937 if (debug)
sewardje517b802005-02-16 01:58:51 +0000938 VG_(printf)("find_map_space(%p, %d, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000939 addr, len, for_client, ret);
940
941 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000942}
943
sewardj79048ce2005-02-18 08:28:32 +0000944
thughes646c6aa2004-07-16 15:36:45 +0000945/* Pad the entire process address space, from VG_(client_base)
nethercote820bd8c2004-09-07 23:04:49 +0000946 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000947 mapping over any part of the address space which is not covered
948 by an entry in the segment list.
949
950 This is designed for use around system calls which allocate
951 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000952 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000953 address with VG_(find_map_space) and then adding a segment for
954 it and padding the address space valgrind can ensure that the
955 kernel has no choice but to put the memory where we want it. */
thughes9aaebc32004-07-15 23:13:37 +0000956void VG_(pad_address_space)(void)
957{
958 Addr addr = VG_(client_base);
959 Segment *s = VG_(SkipNode_First)(&sk_segments);
thughes9aaebc32004-07-15 23:13:37 +0000960 Addr ret;
sewardj548be6d2005-02-16 01:31:37 +0000961vg_assert(0);
thughes9aaebc32004-07-15 23:13:37 +0000962
nethercote820bd8c2004-09-07 23:04:49 +0000963 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000964 if (addr < s->addr) {
nethercotef18ca392004-11-04 18:45:22 +0000965 PLATFORM_DO_MMAP(ret, addr, s->addr - addr, 0,
966 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
967 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000968 }
969
970 addr = s->addr + s->len;
971 s = VG_(SkipNode_Next)(&sk_segments, s);
972 }
973
nethercote820bd8c2004-09-07 23:04:49 +0000974 if (addr <= VG_(valgrind_last)) {
nethercotef18ca392004-11-04 18:45:22 +0000975 PLATFORM_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
976 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
977 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000978 }
979
980 return;
981}
982
thughesc70b8c62004-07-16 23:07:58 +0000983/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000984 by removing any mappings that it created. */
thughes9aaebc32004-07-15 23:13:37 +0000985void VG_(unpad_address_space)(void)
986{
987 Addr addr = VG_(client_base);
988 Segment *s = VG_(SkipNode_First)(&sk_segments);
989 Int ret;
sewardj548be6d2005-02-16 01:31:37 +0000990vg_assert(0);
thughes9aaebc32004-07-15 23:13:37 +0000991
nethercote820bd8c2004-09-07 23:04:49 +0000992 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000993 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +0000994 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +0000995 }
996
997 addr = s->addr + s->len;
998 s = VG_(SkipNode_Next)(&sk_segments, s);
999 }
1000
nethercote820bd8c2004-09-07 23:04:49 +00001001 if (addr <= VG_(valgrind_last)) {
njnca6fef02004-11-29 16:49:18 +00001002 ret = VG_(do_syscall2)(__NR_munmap, addr, (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001003 }
1004
1005 return;
1006}
1007
sewardj548be6d2005-02-16 01:31:37 +00001008/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001009Segment *VG_(find_segment)(Addr a)
1010{
sewardj548be6d2005-02-16 01:31:37 +00001011 Int r = find_segment(a);
1012 if (0) show_segments("find_segment");
1013 if (r == -1) return NULL;
1014 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001015}
1016
sewardj548be6d2005-02-16 01:31:37 +00001017/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1018 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1019 a segment is a checked error.
1020*/
1021Segment *VG_(find_segment_above_unmapped)(Addr a)
1022{
1023 Int r = find_segment_above_unmapped(a);
1024 if (0) show_segments("find_segment_above_unmapped");
1025 if (r == -1) return NULL;
1026 return &segments[r];
1027}
1028
1029/* Assumes that 'a' is in some segment. Finds the next segment along,
1030 or NULL if none. Passing 'a' which is in fact not in a segment is
1031 a checked error.
1032*/
1033Segment *VG_(find_segment_above_mapped)(Addr a)
1034{
1035 Int r = find_segment_above_mapped(a);
1036 if (0) show_segments("find_segment_above_mapped");
1037 if (r == -1) return NULL;
1038 return &segments[r];
1039}
1040
1041
sewardjde4a1d02002-03-22 01:27:54 +00001042/*------------------------------------------------------------*/
1043/*--- Tracking permissions around %esp changes. ---*/
1044/*------------------------------------------------------------*/
1045
1046/*
1047 The stack
1048 ~~~~~~~~~
1049 The stack's segment seems to be dynamically extended downwards
1050 by the kernel as the stack pointer moves down. Initially, a
1051 1-page (4k) stack is allocated. When %esp moves below that for
1052 the first time, presumably a page fault occurs. The kernel
1053 detects that the faulting address is in the range from %esp upwards
1054 to the current valid stack. It then extends the stack segment
1055 downwards for enough to cover the faulting address, and resumes
1056 the process (invisibly). The process is unaware of any of this.
1057
1058 That means that Valgrind can't spot when the stack segment is
1059 being extended. Fortunately, we want to precisely and continuously
1060 update stack permissions around %esp, so we need to spot all
1061 writes to %esp anyway.
1062
1063 The deal is: when %esp is assigned a lower value, the stack is
1064 being extended. Create a secondary maps to fill in any holes
1065 between the old stack ptr and this one, if necessary. Then
1066 mark all bytes in the area just "uncovered" by this %esp change
1067 as write-only.
1068
1069 When %esp goes back up, mark the area receded over as unreadable
1070 and unwritable.
1071
1072 Just to record the %esp boundary conditions somewhere convenient:
1073 %esp always points to the lowest live byte in the stack. All
1074 addresses below %esp are not live; those at and above it are.
1075*/
1076
sewardjde4a1d02002-03-22 01:27:54 +00001077/* Kludgey ... how much does %esp have to change before we reckon that
1078 the application is switching stacks ? */
njn9b007f62003-04-07 14:40:25 +00001079#define VG_PLAUSIBLE_STACK_SIZE 8000000
1080#define VG_HUGE_DELTA (VG_PLAUSIBLE_STACK_SIZE / 4)
sewardjde4a1d02002-03-22 01:27:54 +00001081
njn9b007f62003-04-07 14:40:25 +00001082/* This function gets called if new_mem_stack and/or die_mem_stack are
nethercote996901a2004-08-03 13:29:09 +00001083 tracked by the tool, and one of the specialised cases (eg. new_mem_stack_4)
njn9b007f62003-04-07 14:40:25 +00001084 isn't used in preference */
sewardj2a99cf62004-11-24 10:44:19 +00001085REGPARM(2)
1086void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001087{
nethercotefc646ee2004-11-04 19:29:06 +00001088 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001089
njn9b007f62003-04-07 14:40:25 +00001090 if (delta < -(VG_HUGE_DELTA) || VG_HUGE_DELTA < delta) {
1091 /* %esp has changed by more than HUGE_DELTA. We take this to mean
1092 that the application is switching to a new stack, for whatever
1093 reason.
1094
1095 JRS 20021001: following discussions with John Regehr, if a stack
1096 switch happens, it seems best not to mess at all with memory
1097 permissions. Seems to work well with Netscape 4.X. Really the
1098 only remaining difficulty is knowing exactly when a stack switch is
1099 happening. */
1100 if (VG_(clo_verbosity) > 1)
1101 VG_(message)(Vg_UserMsg, "Warning: client switching stacks? "
nethercote15218bd2004-09-11 15:11:47 +00001102 "%%esp: %p --> %p", old_SP, new_SP);
njn9b007f62003-04-07 14:40:25 +00001103 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001104 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001105
njn9b007f62003-04-07 14:40:25 +00001106 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001107 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001108 }
1109}
1110
jsgf855d93d2003-10-13 22:26:55 +00001111static jmp_buf segv_jmpbuf;
1112
1113static void segv_handler(Int seg)
1114{
1115 __builtin_longjmp(segv_jmpbuf, 1);
1116 VG_(core_panic)("longjmp failed");
1117}
1118
1119/*
1120 Test if a piece of memory is addressable by setting up a temporary
1121 SIGSEGV handler, then try to touch the memory. No signal = good,
1122 signal = bad.
1123 */
nethercote928a5f72004-11-03 18:10:37 +00001124Bool VG_(is_addressable)(Addr p, SizeT size)
jsgf855d93d2003-10-13 22:26:55 +00001125{
1126 volatile Char * volatile cp = (volatile Char *)p;
1127 volatile Bool ret;
nethercote73b526f2004-10-31 18:48:21 +00001128 struct vki_sigaction sa, origsa;
1129 vki_sigset_t mask;
jsgf855d93d2003-10-13 22:26:55 +00001130
jsgf855d93d2003-10-13 22:26:55 +00001131 sa.ksa_handler = segv_handler;
nethercote73b526f2004-10-31 18:48:21 +00001132 sa.sa_flags = 0;
1133 VG_(sigfillset)(&sa.sa_mask);
1134 VG_(sigaction)(VKI_SIGSEGV, &sa, &origsa);
1135 VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &mask);
jsgf855d93d2003-10-13 22:26:55 +00001136
1137 if (__builtin_setjmp(&segv_jmpbuf) == 0) {
1138 while(size--)
1139 *cp++;
1140 ret = True;
1141 } else
1142 ret = False;
1143
nethercote73b526f2004-10-31 18:48:21 +00001144 VG_(sigaction)(VKI_SIGSEGV, &origsa, NULL);
1145 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, NULL);
jsgf855d93d2003-10-13 22:26:55 +00001146
1147 return ret;
1148}
1149
sewardjde4a1d02002-03-22 01:27:54 +00001150/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001151/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001152/*--------------------------------------------------------------------*/
1153
nethercote57e36b32004-07-10 14:56:28 +00001154// Returns 0 on failure.
nethercote928a5f72004-11-03 18:10:37 +00001155Addr VG_(client_alloc)(Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001156{
1157 len = PGROUNDUP(len);
1158
njnca82cc02004-11-22 17:18:48 +00001159 tl_assert(!(sf_flags & SF_FIXED));
1160 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001161
nethercote8e9eab02004-07-11 18:01:06 +00001162 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1163 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1164 sf_flags | SF_CORE, -1, 0);
1165 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001166 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001167 else
1168 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001169}
1170
1171void VG_(client_free)(Addr addr)
1172{
1173 Segment *s = VG_(find_segment)(addr);
1174
sewardj548be6d2005-02-16 01:31:37 +00001175vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001176 if (s == NULL || s->addr != addr || !(s->flags & SF_CORE)) {
1177 VG_(message)(Vg_DebugMsg, "VG_(client_free)(%p) - no CORE memory found there", addr);
1178 return;
1179 }
1180
1181 VG_(munmap)((void *)s->addr, s->len);
1182}
1183
nethercote88a90162004-07-10 16:59:25 +00001184/*--------------------------------------------------------------------*/
1185/*--- Querying memory layout ---*/
1186/*--------------------------------------------------------------------*/
1187
fitzhardinge98abfc72003-12-16 02:05:15 +00001188Bool VG_(is_client_addr)(Addr a)
1189{
1190 return a >= VG_(client_base) && a < VG_(client_end);
1191}
1192
1193Bool VG_(is_shadow_addr)(Addr a)
1194{
sewardj548be6d2005-02-16 01:31:37 +00001195vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001196 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1197}
1198
1199Bool VG_(is_valgrind_addr)(Addr a)
1200{
sewardj548be6d2005-02-16 01:31:37 +00001201vg_assert(0);
nethercote820bd8c2004-09-07 23:04:49 +00001202 return a >= VG_(valgrind_base) && a <= VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +00001203}
1204
1205Addr VG_(get_client_base)(void)
1206{
sewardj548be6d2005-02-16 01:31:37 +00001207vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001208 return VG_(client_base);
1209}
1210
1211Addr VG_(get_client_end)(void)
1212{
sewardj548be6d2005-02-16 01:31:37 +00001213vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001214 return VG_(client_end);
1215}
1216
1217Addr VG_(get_client_size)(void)
1218{
sewardj548be6d2005-02-16 01:31:37 +00001219vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001220 return VG_(client_end)-VG_(client_base);
1221}
1222
1223Addr VG_(get_shadow_base)(void)
1224{
sewardj548be6d2005-02-16 01:31:37 +00001225vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001226 return VG_(shadow_base);
1227}
1228
1229Addr VG_(get_shadow_end)(void)
1230{
sewardj548be6d2005-02-16 01:31:37 +00001231vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001232 return VG_(shadow_end);
1233}
1234
1235Addr VG_(get_shadow_size)(void)
1236{
1237 return VG_(shadow_end)-VG_(shadow_base);
1238}
1239
nethercote88a90162004-07-10 16:59:25 +00001240/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001241/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001242/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001243
1244void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1245{
sewardj548be6d2005-02-16 01:31:37 +00001246vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001247 if (0)
1248 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1249
1250 vg_assert(VG_(needs).shadow_memory);
1251 vg_assert(VG_(defined_init_shadow_page)());
1252
1253 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1254 p = PGROUNDDN(p);
1255
1256 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1257
1258 if (call_init)
1259 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001260 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001261 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1262
nethercote73b526f2004-10-31 18:48:21 +00001263 p += VKI_PAGE_SIZE;
1264 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001265 }
1266}
1267
1268void *VG_(shadow_alloc)(UInt size)
1269{
1270 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001271 Addr try_here;
1272 Int r;
1273
1274 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001275
1276 vg_assert(VG_(needs).shadow_memory);
1277 vg_assert(!VG_(defined_init_shadow_page)());
1278
1279 size = PGROUNDUP(size);
1280
1281 if (shadow_alloc == 0)
1282 shadow_alloc = VG_(shadow_base);
1283
1284 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001285 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001286
sewardj79048ce2005-02-18 08:28:32 +00001287 try_here = shadow_alloc;
1288 vg_assert(IS_PAGE_ALIGNED(try_here));
1289 vg_assert(IS_PAGE_ALIGNED(size));
1290 vg_assert(size > 0);
1291
1292 if (0)
1293 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1294
1295 /* this is big-bang allocated, so we don't expect to find a listed
1296 segment for it. */
1297 /* This is really an absolute disgrace. Sometimes the big-bang
1298 mapping is in the list (due to re-reads of /proc/self/maps,
1299 presumably) and sometimes it isn't. */
1300#if 0
1301 r = find_segment(try_here);
1302 vg_assert(r == -1);
1303 r = find_segment(try_here+size-1);
1304 vg_assert(r == -1);
1305#endif
1306
1307 r = VG_(mprotect_native)( (void*)try_here,
1308 size, VKI_PROT_READ|VKI_PROT_WRITE );
1309
1310 if (r != 0)
1311 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001312
1313 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001314 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001315
sewardj79048ce2005-02-18 08:28:32 +00001316 failed:
1317 VG_(printf)(
1318 "valgrind: Could not allocate address space (%p bytes)\n"
1319 "valgrind: for shadow memory chunk.\n",
1320 (void*)size
1321 );
1322 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001323}
1324
1325/*--------------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +00001326/*--- end vg_memory.c ---*/
1327/*--------------------------------------------------------------------*/