blob: eaaffb00094dd0f7bf46127ca74c7022d7880ca6 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00003/*--- Memory-related stuff: segment initialisation and tracking, ---*/
4/*--- stack operations ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005/*--- vg_memory.c ---*/
6/*--------------------------------------------------------------------*/
7
8/*
njnb9c427c2004-12-01 14:14:42 +00009 This file is part of Valgrind, a dynamic binary instrumentation
10 framework.
sewardjde4a1d02002-03-22 01:27:54 +000011
njn53612422005-03-12 16:22:54 +000012 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000013 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000014
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
njn25e49d8e72002-09-23 09:36:25 +000030 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000031*/
32
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
sewardjde4a1d02002-03-22 01:27:54 +000034
sewardja4495682002-10-21 07:29:59 +000035/* Define to debug the memory-leak-detector. */
36/* #define VG_DEBUG_LEAKCHECK */
37
sewardje517b802005-02-16 01:58:51 +000038static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000039
40/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000041/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000042/*--------------------------------------------------------------*/
43
sewardj79048ce2005-02-18 08:28:32 +000044/* Max number of segments we can track. */
45#define VG_N_SEGMENTS 1000
46
47/* Max number of segment file names we can track. */
48#define VG_N_SEGNAMES 200
49
50/* Max length of a segment file name. */
51#define VG_MAX_SEGNAMELEN 1000
52
53
54/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000055
56/* Array [0 .. segments_used-1] of all mappings. */
57/* Sorted by .addr field. */
58/* I: len may not be zero. */
59/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000060/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000061
62static Segment segments[VG_N_SEGMENTS];
63static Int segments_used = 0;
64
sewardj79048ce2005-02-18 08:28:32 +000065typedef
66 struct {
67 Bool inUse;
68 Bool mark;
69 HChar fname[VG_MAX_SEGNAMELEN];
70 }
71 SegName;
72
73/* Filename table. _used is the high water mark; an entry is only
74 valid if its index >= 0, < _used, and its .inUse field == True.
75 The .mark field is used to garbage-collect dead entries.
76*/
77static SegName segnames[VG_N_SEGNAMES];
78static Int segnames_used = 0;
79
80
81/* ------ end of STATE for the address-space manager ------ */
82
83
84/* Searches the filename table to find an index for the given name.
85 If none is found, an index is allocated and the name stored. If no
86 space is available we just give up. If the string is too long to
87 store, return -1.
88*/
89static Int allocate_segname ( const HChar* name )
90{
91 Int i, j, len;
92
93 vg_assert(name);
94
95 if (0) VG_(printf)("alloc_segname %s\n", name);
96
97 len = VG_(strlen)(name);
98 if (len >= VG_MAX_SEGNAMELEN-1) {
99 return -1;
100 }
101
102 /* first see if we already have the name. */
103 for (i = 0; i < segnames_used; i++) {
104 if (!segnames[i].inUse)
105 continue;
106 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
107 return i;
108 }
109 }
110
111 /* no we don't. So look for a free slot. */
112 for (i = 0; i < segnames_used; i++)
113 if (!segnames[i].inUse)
114 break;
115
116 if (i == segnames_used) {
117 /* no free slots .. advance the high-water mark. */
118 if (segnames_used+1 < VG_N_SEGNAMES) {
119 i = segnames_used;
120 segnames_used++;
121 } else {
122 VG_(printf)(
123 "coregrind/vg_memory.c:\n"
124 " VG_N_SEGNAMES is too small: "
125 "increase it and rebuild Valgrind.\n"
126 );
127 VG_(printf)(
128 "coregrind/vg_memory.c:\n"
129 " giving up now.\n\n"
130 );
131 VG_(exit)(0);
132 }
133 }
134
135 /* copy it in */
136 segnames[i].inUse = True;
137 for (j = 0; j < len; j++)
138 segnames[i].fname[j] = name[j];
139 vg_assert(len < VG_MAX_SEGNAMELEN);
140 segnames[i].fname[len] = 0;
141 return i;
142}
143
sewardj548be6d2005-02-16 01:31:37 +0000144
145/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
146 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000147 seg.
148*/
sewardj548be6d2005-02-16 01:31:37 +0000149static Int compare_addr_with_seg ( Addr a, Segment* seg )
150{
151 if (a < seg->addr)
152 return -1;
153 if (a >= seg->addr + seg->len)
154 return 1;
155 return 0;
156}
157
sewardj79048ce2005-02-18 08:28:32 +0000158
sewardj548be6d2005-02-16 01:31:37 +0000159/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000160 none.
161*/
sewardj548be6d2005-02-16 01:31:37 +0000162static Int find_segment ( Addr a )
163{
164 Int i;
165 for (i = 0; i < segments_used; i++) {
166 if (compare_addr_with_seg(a, &segments[i]) == 0)
167 return i;
168 }
169 return -1;
170}
171
172
173/* Assumes that 'a' is not in any segment. Finds the index of the
174 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
175 which is in fact in a segment is a checked error.
176*/
177static Int find_segment_above_unmapped ( Addr a )
178{
179 Int i, r;
180 for (i = 0; i < segments_used; i++) {
181 r = compare_addr_with_seg(a, &segments[i]);
182 vg_assert(r != 0); /* 'a' should not be in any segment. */
183 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000184 continue;
sewardj548be6d2005-02-16 01:31:37 +0000185 vg_assert(r == -1);
186 break;
187 }
188
189 if (i == segments_used)
190 return -1; /* not found */
191 else
192 return i;
193}
194
195
196/* Assumes that 'a' is in some segment. Finds the next segment along,
197 or NULL if none. Passing 'a' which is in fact not in a segment is
198 a checked error.
199*/
200static Int find_segment_above_mapped ( Addr a )
201{
202 Int i, r;
203 for (i = 0; i < segments_used; i++) {
204 r = compare_addr_with_seg(a, &segments[i]);
205 if (r == 1)
206 continue; /* not yet there */
207 if (r == 0)
208 break; /* found it */
209 vg_assert(0);
210 /* we shouldn't get here -- r == -1 and so it means we went past
211 'a' without seeing it -- it is therefore unmapped. */
212 /*NOTREACHED*/
213 }
214
215 vg_assert(i < segments_used);
216 if (i == segments_used-1)
217 return -1; /* not found */
218 else
219 return i+1;
220}
221
222
223/* Shift segments[i .. segments_used-1] up by one. */
224static void make_space_at ( Int i )
225{
226 Int j;
227 vg_assert(i >= 0 && i <= segments_used);
228 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000229 if (segments_used+1 == VG_N_SEGMENTS) {
230 VG_(printf)(
231 "coregrind/vg_memory.c:\n"
232 " VG_N_SEGMENTS is too small: "
233 "increase it and rebuild Valgrind.\n"
234 );
235 VG_(printf)(
236 "coregrind/vg_memory.c:\n"
237 " giving up now.\n\n"
238 );
239 VG_(exit)(0);
240 }
sewardj548be6d2005-02-16 01:31:37 +0000241 vg_assert(segments_used+1 < VG_N_SEGMENTS);
242 for (j = segments_used; j > i; j--)
243 segments[j] = segments[j-1];
244 segments_used++;
245}
246
sewardj79048ce2005-02-18 08:28:32 +0000247
sewardj548be6d2005-02-16 01:31:37 +0000248/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000249 segments_used.
250*/
sewardj548be6d2005-02-16 01:31:37 +0000251static void delete_segment_at ( Int i )
252{
253 Int j;
254 vg_assert(i >= 0 && i < segments_used);
255 for (j = i+1; j < segments_used; j++)
256 segments[j-1] = segments[j];
257 segments_used--;
258 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
259}
260
261
262/* Fill the i'th record all with zeroes. */
263static void zeroise_segment ( Int i )
264{
265 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000266 segments[i].prot = 0;
267 segments[i].flags = 0;
268 segments[i].addr = 0;
269 segments[i].len = 0;
270 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000271 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000272 segments[i].fnIdx = -1;
273 segments[i].dev = 0;
274 segments[i].ino = 0;
275 segments[i].symtab = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000276}
277
sewardj79048ce2005-02-18 08:28:32 +0000278
sewardj548be6d2005-02-16 01:31:37 +0000279/* Create a segment to contain 'a', and return its index. Or -1 if
280 this failed because some other segment already contains 'a'. If
281 successful, fill in the segment's .addr field with 'a' but leave
282 all other fields alone.
283*/
284static Int create_segment ( Addr a )
285{
286 Int i, r;
287 for (i = 0; i < segments_used; i++) {
288 r = compare_addr_with_seg( a, &segments[i] );
289 if (r == 1)
290 continue; /* seg[i] precedes a */
291 if (r == 0)
292 return -1; /* seg[i] contains a. Give up */
293 vg_assert(r == -1);
294 break;
295 }
296 /* a precedes seg[i]. Shift segs at i and above up one, and use
297 this slot. */
298 make_space_at(i);
299 zeroise_segment(i);
300 segments[i].addr = a;
301 return i;
302}
303
sewardj79048ce2005-02-18 08:28:32 +0000304
305/* Print out the segment array (debugging only!). Note, this calls
306 VG_(printf), and I'm not 100% clear that that wouldn't require
307 dynamic memory allocation and hence more segments to be allocated.
308*/
309static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000310{
sewardj79048ce2005-02-18 08:28:32 +0000311 Int i;
312 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
313 who, segments_used, segnames_used);
314 for (i = 0; i < segnames_used; i++) {
315 if (!segnames[i].inUse)
316 continue;
317 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
318 }
319 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000320 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000321 "%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 +0000322 i,
sewardj79048ce2005-02-18 08:28:32 +0000323 segments[i].addr, segments[i].addr + segments[i].len,
324 (ULong)segments[i].len, segments[i].prot,
325 segments[i].flags, segments[i].dev, segments[i].ino,
326 (Long)segments[i].offset,
327 segments[i].fnIdx);
328 }
329 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000330}
sewardj79048ce2005-02-18 08:28:32 +0000331
sewardj548be6d2005-02-16 01:31:37 +0000332
333/* Find the segment containing 'a' and split it into two pieces at
334 'a'. Does nothing if no segment contains 'a', or if the split
335 would cause either of the pieces to have zero size.
336
337 If 'a' is not found, or if no splitting happens, -1 is returned.
338
339 If a value 'r' other than -1 is returned, this is the index of the
340 higher-addressed segment resulting from the split, and the index of
341 the lower-addressed segment is r-1.
342*/
343static Int split_segment ( Addr a )
344{
345 Int r;
346 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000347 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000348 r = find_segment(a);
349 if (r == -1)
350 /* not found */
351 return -1;
352 if (segments[r].addr == a)
353 /* segment starts at 'a', so splitting it would create a
354 zero-sized segment */
355 return -1;
356
357 /* copy original; make adjustments. */
358 vg_assert(a > segments[r].addr);
359 delta = a - segments[r].addr;
360 make_space_at(r);
361 segments[r] = segments[r+1];
362 segments[r].len = delta;
363 segments[r+1].len -= delta;
364 segments[r+1].addr += delta;
365 segments[r+1].offset += delta;
366 return r+1;
367}
368
sewardj79048ce2005-02-18 08:28:32 +0000369
370/* Return true if two segments are adjacent and mergable (s1 is
371 assumed to have a lower ->addr than s2) */
372static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
373{
374 if (s1->addr+s1->len != s2->addr)
375 return False;
376
377 if (s1->flags != s2->flags)
378 return False;
379
380 if (s1->prot != s2->prot)
381 return False;
382
383 if (s1->symtab != s2->symtab)
384 return False;
385
386 if (s1->flags & SF_FILE){
387 if ((s1->offset + s1->len) != s2->offset)
388 return False;
389 if (s1->dev != s2->dev)
390 return False;
391 if (s1->ino != s2->ino)
392 return False;
393 if (s1->fnIdx != s2->fnIdx)
394 return False;
395 }
396
397 return True;
398}
399
400
401/* Clean up and sanity check the segment array:
402 - check segments are in ascending order
403 - check segments do not overlap
404 - check no segment has zero size
405 - merge adjacent where possible
406 - perform checks on the filename table, and reclaim dead entries
407*/
408static void preen_segments ( void )
409{
410 Int i, j, rd, wr;
411 Segment *s, *s1;
412 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
413 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
414
415 if (0) show_segments("before preen");
416
417 /* clear string table mark bits */
418 for (i = 0; i < segnames_used; i++)
419 segnames[i].mark = False;
420
421 /* check for non-zero size, and set mark bits for any used strings */
422 for (i = 0; i < segments_used; i++) {
423 vg_assert(segments[i].len > 0);
424 j = segments[i].fnIdx;
425 vg_assert(j >= -1 && j < segnames_used);
426 if (j >= 0) {
427 vg_assert(segnames[j].inUse);
428 segnames[j].mark = True;
429 }
430 }
431
432 /* check ascendingness and non-overlap */
433 for (i = 0; i < segments_used-1; i++) {
434 s = &segments[i];
435 s1 = &segments[i+1];
436 vg_assert(s->addr < s1->addr);
437 vg_assert(s->addr + s->len <= s1->addr);
438 }
439
440 /* merge */
441 if (segments_used < 1)
442 return;
443
444 wr = 1;
445 for (rd = 1; rd < segments_used; rd++) {
446 s = &segments[wr-1];
447 s1 = &segments[rd];
448 if (segments_are_mergeable(s,s1)) {
449 if (0)
450 VG_(printf)("merge %p-%p with %p-%p\n",
451 s->addr, s->addr+s->len,
452 s1->addr, s1->addr+s1->len);
453 s->len += s1->len;
454 continue;
455 }
456 if (wr < rd)
457 segments[wr] = segments[rd];
458 wr++;
459 }
460 vg_assert(wr >= 0 && wr <= segments_used);
461 segments_used = wr;
462
463 /* Free up any strings which are no longer referenced. */
464 for (i = 0; i < segnames_used; i++) {
465 if (segnames[i].mark == False) {
466 segnames[i].inUse = False;
467 segnames[i].fname[0] = 0;
468 }
469 }
470
471 if (0) show_segments("after preen");
472}
473
474
sewardj548be6d2005-02-16 01:31:37 +0000475/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000476/*--- Maintain an ordered list of all the client's mappings ---*/
477/*--------------------------------------------------------------*/
478
nethercote8991d5a2004-11-03 17:07:46 +0000479Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000480{
481 Addr se = s->addr+s->len;
482 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000483 vg_assert(pe >= p);
484
485 return (p >= s->addr && pe <= se);
486}
487
nethercote8991d5a2004-11-03 17:07:46 +0000488Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000489{
490 Addr se = s->addr+s->len;
491 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000492 vg_assert(pe >= p);
493
494 return (p < se && pe > s->addr);
495}
496
sewardj1024cf72005-02-28 14:39:21 +0000497#if 0
498/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000499/* Prepare a Segment structure for recycling by freeing everything
500 hanging off it. */
501static void recycleseg(Segment *s)
502{
503 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000504 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000505
506 if (s->filename != NULL)
507 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
508
509 /* keep the SegInfo, if any - it probably still applies */
510}
511
512/* When freeing a Segment, also clean up every one else's ideas of
513 what was going on in that range of memory */
514static void freeseg(Segment *s)
515{
516 recycleseg(s);
517 if (s->symtab != NULL) {
nethercote8991d5a2004-11-03 17:07:46 +0000518 VG_(symtab_decref)(s->symtab, s->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000519 s->symtab = NULL;
520 }
521
522 VG_(SkipNode_Free)(&sk_segments, s);
523}
sewardj1024cf72005-02-28 14:39:21 +0000524#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000525
sewardj1024cf72005-02-28 14:39:21 +0000526
527/* Get rid of any translations arising from s. */
528/* Note, this is not really the job of the low level memory manager.
529 When it comes time to rewrite this subsystem, clean this up. */
530static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000531{
sewardj1024cf72005-02-28 14:39:21 +0000532 if (s->flags & SF_CODE) {
533 VG_(discard_translations)(s->addr, s->len);
534 if (0)
535 VG_(printf)("dumping translations in %p .. %p\n",
536 s->addr, s->addr+s->len);
537 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000538}
539
sewardj1024cf72005-02-28 14:39:21 +0000540
fitzhardinge98abfc72003-12-16 02:05:15 +0000541/* This unmaps all the segments in the range [addr, addr+len); any
542 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000543void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000544{
fitzhardingee3632c62003-12-22 10:58:06 +0000545 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000546 Segment* s;
547 Addr end, s_end;
548 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000549 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000550
551 if (len == 0)
552 return;
553
fitzhardinge1a4adf02003-12-22 10:42:59 +0000554 len = PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000555
fitzhardinge98abfc72003-12-16 02:05:15 +0000556 if (debug)
557 VG_(printf)("unmap_range(%p, %d)\n", addr, len);
sewardj79048ce2005-02-18 08:28:32 +0000558 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000559 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000560
561 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000562 vg_assert(VG_IS_PAGE_ALIGNED(addr));
563 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000564
sewardj548be6d2005-02-16 01:31:37 +0000565 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000566
567 /* do not delete .. even though it looks stupid */
568 vg_assert(i >= 0);
569
570 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000571 s = &segments[i];
572 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000573
sewardj548be6d2005-02-16 01:31:37 +0000574 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000575 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000576 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000577
fitzhardinge1a303042003-12-22 08:48:50 +0000578 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000579 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000580 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000581 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000582 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000583
584 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000585 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000586 addr < s_end &&
587 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000588 /* this segment's tail is truncated by [addr, addr+len)
589 -> truncate tail
590 */
sewardj1024cf72005-02-28 14:39:21 +0000591 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000592 s->len = addr - s->addr;
593
594 if (debug)
595 VG_(printf)(" case 1: s->len=%d\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000596 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000597 /* this segment's head is truncated by [addr, addr+len)
598 -> truncate head
599 */
sewardj548be6d2005-02-16 01:31:37 +0000600 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000601
602 if (debug)
sewardj79048ce2005-02-18 08:28:32 +0000603 VG_(printf)(" case 2: s->addr=%p s->len=%d delta=%d\n",
604 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000605
sewardj1024cf72005-02-28 14:39:21 +0000606 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000607 s->addr += delta;
608 s->offset += delta;
609 s->len -= delta;
610
611 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000612 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000613 /* this segment is completely contained within [addr, addr+len)
614 -> delete segment
615 */
sewardj1024cf72005-02-28 14:39:21 +0000616 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000617 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000618 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000619
620 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000621 VG_(printf)(" case 3: seg %d deleted\n", i);
622 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000623 /* [addr, addr+len) is contained within a single segment
624 -> split segment into 3, delete middle portion
625 */
sewardj1024cf72005-02-28 14:39:21 +0000626 Int i_middle;
627 dump_translations_from(s);
628 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000629 vg_assert(i_middle != -1);
630 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000631 vg_assert(segments[i_middle].addr == addr);
632 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000633 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000634
635 if (debug)
636 VG_(printf)(" case 4: subrange %p-%p deleted\n",
637 addr, addr+len);
638 }
sewardj47c98a72005-03-12 20:36:15 +0000639
640 /* If we deleted this segment (or any above), those above will
641 have been moved down to fill in the hole in the segment
642 array. In order that we don't miss them, we have to
643 re-consider this slot number; hence the i--. */
644 if (deleted)
645 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000646 }
sewardj79048ce2005-02-18 08:28:32 +0000647 preen_segments();
648 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000649}
650
sewardj548be6d2005-02-16 01:31:37 +0000651
652/* Add a binding of [addr,addr+len) to
653 (prot,flags,dev,ino,off,filename) in the segment array.
654 Delete/truncate any previous mapping(s) covering that range.
655*/
656void
657VG_(map_file_segment)( Addr addr, SizeT len,
658 UInt prot, UInt flags,
659 UInt dev, UInt ino, ULong off,
660 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000661{
fitzhardinge98abfc72003-12-16 02:05:15 +0000662 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000663 Segment* s;
664 Int idx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000665
666 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000667 VG_(printf)(
668 "\n"
669 "map_file_segment(addr=%p len=%llu prot=0x%x flags=0x%x\n"
670 " dev=0x%4x ino=%d off=%ld\n"
671 " filename='%s')\n",
672 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000673
674 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000675 vg_assert(VG_IS_PAGE_ALIGNED(addr));
fitzhardinge98abfc72003-12-16 02:05:15 +0000676 len = PGROUNDUP(len);
677
sewardj548be6d2005-02-16 01:31:37 +0000678 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
679 VG_(unmap_range)(addr, len);
680
681 /* and now install this one */
682 idx = create_segment(addr);
683 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
684 vg_assert(idx != -1);
685 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000686
sewardj79048ce2005-02-18 08:28:32 +0000687 s = &segments[idx];
688 vg_assert(s->addr == addr);
689 s->prot = prot;
690 s->flags = flags;
691 s->len = len;
692 s->offset = off;
693 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
694 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
695 s->dev = dev;
696 s->ino = ino;
697 s->symtab = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000698
sewardj79048ce2005-02-18 08:28:32 +0000699 /* Clean up right now */
700 preen_segments();
701 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000702
703 /* If this mapping is of the beginning of a file, isn't part of
704 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000705 file, then try reading symbols from it.
706 */
707 if (s->symtab == NULL
sewardjb71816c2005-03-14 19:11:10 +0000708 && (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
sewardj79048ce2005-02-18 08:28:32 +0000709 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
710 if (off == 0
711 && s->fnIdx != -1
712 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
713 && len >= VKI_PAGE_SIZE
714 && VG_(is_object_file)((void *)addr)) {
nethercote71980f02004-01-24 18:18:54 +0000715 s->symtab = VG_(read_seg_symbols)(s);
nethercote71980f02004-01-24 18:18:54 +0000716 if (s->symtab != NULL) {
717 s->flags |= SF_DYNLIB;
718 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000719 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000720#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000721 const SegInfo *info;
722
723 /* Otherwise see if an existing symtab applies to this Segment */
724 for(info = VG_(next_seginfo)(NULL);
725 info != NULL;
726 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000727 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
728 {
fitzhardinge98abfc72003-12-16 02:05:15 +0000729 s->symtab = (SegInfo *)info;
730 VG_(symtab_incref)((SegInfo *)info);
731 }
732 }
sewardj79048ce2005-02-18 08:28:32 +0000733#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000734 }
735 }
736
737 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000738 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000739}
740
nethercote8b5f40c2004-11-02 13:29:50 +0000741void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000742 Int fd, ULong off, const Char *filename)
743{
744 struct vki_stat st;
745 Char *name = NULL;
746
747 st.st_dev = 0;
748 st.st_ino = 0;
749
750 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000751 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000752
753 if (VG_(fstat)(fd, &st) < 0)
754 flags &= ~SF_FILE;
755 }
756
sewardj79048ce2005-02-18 08:28:32 +0000757 if ((flags & SF_FILE) && filename == NULL && fd != -1)
758 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000759
760 if (filename == NULL)
761 filename = name;
762
sewardj79048ce2005-02-18 08:28:32 +0000763 VG_(map_file_segment)(addr, len, prot, flags,
764 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000765}
766
nethercote8b5f40c2004-11-02 13:29:50 +0000767void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000768{
769 flags &= ~SF_FILE;
770
771 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
772}
773
774/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000775void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000776{
sewardj79048ce2005-02-18 08:28:32 +0000777 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000778 static const Bool debug = False || mem_debug;
779
780 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000781 VG_(printf)("\nmprotect_range(%p, %d, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000782
783 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000784
785 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000786 vg_assert(VG_IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000787 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000788
sewardj79048ce2005-02-18 08:28:32 +0000789 split_segment(a);
790 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000791
sewardj548be6d2005-02-16 01:31:37 +0000792 r = find_segment(a);
793 vg_assert(r != -1);
794 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000795
796 preen_segments();
797
sewardje517b802005-02-16 01:58:51 +0000798 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000799}
800
sewardj79048ce2005-02-18 08:28:32 +0000801
sewardj548be6d2005-02-16 01:31:37 +0000802/* Try to find a map space for [addr,addr+len). If addr==0, it means
803 the caller is prepared to accept a space at any location; if not,
804 we will try for addr, but fail if we can't get it. This mimics
805 mmap fixed vs mmap not-fixed.
806*/
nethercote8b5f40c2004-11-02 13:29:50 +0000807Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000808{
fitzhardingee3632c62003-12-22 10:58:06 +0000809 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000810 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000811 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000812 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
813 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000814 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
815 Int i, i_any, i_fixed, i_final;
816 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000817
sewardj548be6d2005-02-16 01:31:37 +0000818 Bool fixed;
819
sewardje517b802005-02-16 01:58:51 +0000820 if (debug) {
821 VG_(printf)("\n\n");
822 VG_(printf)("find_map_space(%p, %d, %d) ...\n",
823 addr, len, for_client);
824 }
825
826 if (0) show_segments("find_map_space: start");
827
sewardj548be6d2005-02-16 01:31:37 +0000828 if (addr == 0) {
829 fixed = False;
830 } else {
831 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000832 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000833 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000834 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000835 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000836
837 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000838 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000839 len = PGROUNDUP(len);
840
nethercote73b526f2004-10-31 18:48:21 +0000841 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000842
sewardj548be6d2005-02-16 01:31:37 +0000843 /* Scan the segment list, looking for a hole which satisfies the
844 requirements. At each point i we ask the question "can we use
845 the hole in between segments[i-1] and segments[i] ?" */
846 i_any = i_fixed = -1;
847 hstart_any = hstart_fixed = 0;
848
849 hole_start = hole_end = 0;
850
851 /* Iterate over all possible holes, generating them into
852 hole_start/hole_end. Filter out invalid ones. Then see if any
853 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
854 */
855 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
856 if (i == 0) {
857 hole_start = 0;
858 hole_end = segments[0].addr-1;
859 }
860 else {
861 vg_assert(segments_used > 0);
862 if (i == segments_used) {
863 hole_start = segments[i-1].addr + segments[i-1].len;
864 hole_end = ~(Addr)0;
865 } else {
866 hole_start = segments[i-1].addr + segments[i-1].len;
867 hole_end = segments[i].addr - 1;
868 }
869 }
870
871 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
872
873 /* ignore zero-sized holes */
874 if (hole_start == hole_end+1)
875 continue;
876
njnbe91aae2005-03-27 01:42:41 +0000877 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
878 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000879
880 /* ignore holes which fall outside the allowable area */
881 if (!(hole_start >= base && hole_end <= limit))
882 continue;
883
884 vg_assert(hole_end > hole_start);
885 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000886 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000887
888 if (hole_len >= len && i_any == -1) {
889 /* It will at least fit in this hole. */
890 i_any = i;
891 hstart_any = hole_start;
892 }
893
sewardjb5f6f512005-03-10 23:59:00 +0000894 if (fixed && hole_start <= addr
895 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000896 /* We were asked for a fixed mapping, and this hole works.
897 Bag it -- and stop searching as further searching is
898 pointless. */
899 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000900 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000901 break;
902 }
903 }
904
905 /* Summarise the final decision into i_final/hstart_final. */
906 i_final = -1;
907 hstart_final = 0;
908
909 if (fixed) {
910 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000911 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000912 } else {
913 i_final = i_any;
914 hstart_final = hstart_any;
915 }
916
917
918 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000919 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000920 else
921 ret = 0; /* not found */
922
923 if (debug)
sewardje517b802005-02-16 01:58:51 +0000924 VG_(printf)("find_map_space(%p, %d, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000925 addr, len, for_client, ret);
926
sewardjb5f6f512005-03-10 23:59:00 +0000927 if (fixed) {
928 vg_assert(ret == 0 || ret == addrOrig);
929 }
930
sewardj548be6d2005-02-16 01:31:37 +0000931 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000932}
933
sewardj79048ce2005-02-18 08:28:32 +0000934
sewardjb5f6f512005-03-10 23:59:00 +0000935/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000936 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000937 mapping over any part of the address space which is not covered
938 by an entry in the segment list.
939
940 This is designed for use around system calls which allocate
941 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000942 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000943 address with VG_(find_map_space) and then adding a segment for
944 it and padding the address space valgrind can ensure that the
945 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000946void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000947{
sewardj394790d2005-03-17 02:14:44 +0000948 Addr addr = (start == 0) ? VG_(client_base) : start;
949 Addr ret;
950
951 Int i = 0;
952 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000953
nethercote820bd8c2004-09-07 23:04:49 +0000954 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000955 if (addr < s->addr) {
njnf6d228b2005-03-26 02:42:31 +0000956 VGP_DO_MMAP(ret, addr, s->addr - addr, 0,
957 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
958 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000959 }
thughes9aaebc32004-07-15 23:13:37 +0000960 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000961 i++;
962 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000963 }
964
nethercote820bd8c2004-09-07 23:04:49 +0000965 if (addr <= VG_(valgrind_last)) {
njnf6d228b2005-03-26 02:42:31 +0000966 VGP_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
967 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
968 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000969 }
thughes9aaebc32004-07-15 23:13:37 +0000970}
971
thughesc70b8c62004-07-16 23:07:58 +0000972/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000973 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +0000974void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000975{
sewardj394790d2005-03-17 02:14:44 +0000976 Addr addr = (start == 0) ? VG_(client_base) : start;
977 Int ret;
978
979 Int i = 0;
980 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000981
nethercote820bd8c2004-09-07 23:04:49 +0000982 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000983 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +0000984 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +0000985 }
thughes9aaebc32004-07-15 23:13:37 +0000986 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000987 i++;
988 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000989 }
990
nethercote820bd8c2004-09-07 23:04:49 +0000991 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +0000992 ret = VG_(do_syscall2)(__NR_munmap, addr,
993 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +0000994 }
thughes9aaebc32004-07-15 23:13:37 +0000995}
996
sewardj548be6d2005-02-16 01:31:37 +0000997/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000998Segment *VG_(find_segment)(Addr a)
999{
sewardj548be6d2005-02-16 01:31:37 +00001000 Int r = find_segment(a);
1001 if (0) show_segments("find_segment");
1002 if (r == -1) return NULL;
1003 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001004}
1005
sewardj548be6d2005-02-16 01:31:37 +00001006/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1007 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1008 a segment is a checked error.
1009*/
1010Segment *VG_(find_segment_above_unmapped)(Addr a)
1011{
1012 Int r = find_segment_above_unmapped(a);
1013 if (0) show_segments("find_segment_above_unmapped");
1014 if (r == -1) return NULL;
1015 return &segments[r];
1016}
1017
1018/* Assumes that 'a' is in some segment. Finds the next segment along,
1019 or NULL if none. Passing 'a' which is in fact not in a segment is
1020 a checked error.
1021*/
1022Segment *VG_(find_segment_above_mapped)(Addr a)
1023{
1024 Int r = find_segment_above_mapped(a);
1025 if (0) show_segments("find_segment_above_mapped");
1026 if (r == -1) return NULL;
1027 return &segments[r];
1028}
1029
1030
sewardjde4a1d02002-03-22 01:27:54 +00001031/*------------------------------------------------------------*/
1032/*--- Tracking permissions around %esp changes. ---*/
1033/*------------------------------------------------------------*/
1034
1035/*
1036 The stack
1037 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001038 The stack's segment seems to be dynamically extended downwards by
1039 the kernel as the stack pointer moves down. Initially, a 1-page
1040 (4k) stack is allocated. When SP moves below that for the first
1041 time, presumably a page fault occurs. The kernel detects that the
1042 faulting address is in the range from SP - VGA_STACK_REDZONE_SIZE
1043 upwards to the current valid stack. It then extends the stack
1044 segment downwards for enough to cover the faulting address, and
1045 resumes the process (invisibly). The process is unaware of any of
1046 this.
sewardjde4a1d02002-03-22 01:27:54 +00001047
sewardjfa8202f2005-04-24 11:05:55 +00001048 That means that Valgrind can't spot when the stack segment is being
1049 extended. Fortunately, we want to precisely and continuously
1050 update stack permissions around SP, so we need to spot all writes
1051 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001052
sewardjfa8202f2005-04-24 11:05:55 +00001053 The deal is: when SP is assigned a lower value, the stack is being
1054 extended. Create suitably-permissioned pages to fill in any holes
1055 between the old stack ptr and this one, if necessary. Then mark
1056 all bytes in the area just "uncovered" by this SP change as
1057 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001058
sewardjfa8202f2005-04-24 11:05:55 +00001059 When SP goes back up, mark the area receded over as unreadable and
1060 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001061
sewardjfa8202f2005-04-24 11:05:55 +00001062 Just to record the SP boundary conditions somewhere convenient: SP
1063 - VGA_STACK_REDZONE_SIZE always points to the lowest live byte in
1064 the stack. All addresses below SP - VGA_STACK_REDZONE_SIZE are not
1065 live; those at and above it are.
1066
1067 We do not concern ourselves here with the VGA_STACK_REDZONE_SIZE
1068 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001069*/
1070
njn9b007f62003-04-07 14:40:25 +00001071/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001072 tracked by the tool, and one of the specialised cases
1073 (eg. new_mem_stack_4) isn't used in preference.
1074*/
njn9fb73db2005-03-27 01:55:21 +00001075VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001076void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001077{
sewardj97724e52005-04-02 23:40:59 +00001078 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001079 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001080
sewardj97724e52005-04-02 23:40:59 +00001081 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1082 /* SP has changed by more than some threshold amount (by
1083 default, 2MB). We take this to mean that the application is
1084 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001085
1086 JRS 20021001: following discussions with John Regehr, if a stack
1087 switch happens, it seems best not to mess at all with memory
1088 permissions. Seems to work well with Netscape 4.X. Really the
1089 only remaining difficulty is knowing exactly when a stack switch is
1090 happening. */
sewardj97724e52005-04-02 23:40:59 +00001091 if (VG_(clo_verbosity) > 0 && moans > 0) {
1092 moans--;
1093 VG_(message)(Vg_UserMsg,
1094 "Warning: client switching stacks? "
1095 "SP change: %p --> %p", old_SP, new_SP);
1096 VG_(message)(Vg_UserMsg,
1097 " to suppress, use: --max-stackframe=%d or greater",
1098 (delta < 0 ? -delta : delta));
1099 if (moans == 0)
1100 VG_(message)(Vg_UserMsg,
1101 " further instances of this message "
1102 "will not be shown.");
1103 }
njn9b007f62003-04-07 14:40:25 +00001104 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001105 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001106
njn9b007f62003-04-07 14:40:25 +00001107 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001108 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001109 }
1110}
1111
jsgf855d93d2003-10-13 22:26:55 +00001112/*
sewardjb5f6f512005-03-10 23:59:00 +00001113 Test if a piece of memory is addressable with at least the "prot"
1114 protection permissions by examining the underlying segments.
1115
1116 Really this is a very stupid algorithm and we could do much
1117 better by iterating through the segment array instead of through
1118 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001119 */
sewardjb5f6f512005-03-10 23:59:00 +00001120Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001121{
sewardjb5f6f512005-03-10 23:59:00 +00001122 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001123
sewardjb5f6f512005-03-10 23:59:00 +00001124 if ((p + size) < p)
1125 return False; /* reject wraparounds */
1126 if (size == 0)
1127 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001128
sewardjb5f6f512005-03-10 23:59:00 +00001129 p = PGROUNDDN(p);
1130 size = PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001131 vg_assert(VG_IS_PAGE_ALIGNED(p));
1132 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001133
sewardjb5f6f512005-03-10 23:59:00 +00001134 for (; size > 0; size -= VKI_PAGE_SIZE) {
1135 seg = VG_(find_segment)(p);
1136 if (!seg)
1137 return False;
1138 if ((seg->prot & prot) != prot)
1139 return False;
1140 p += VKI_PAGE_SIZE;
1141 }
jsgf855d93d2003-10-13 22:26:55 +00001142
sewardjb5f6f512005-03-10 23:59:00 +00001143 return True;
jsgf855d93d2003-10-13 22:26:55 +00001144}
1145
sewardjb5f6f512005-03-10 23:59:00 +00001146
sewardjde4a1d02002-03-22 01:27:54 +00001147/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001148/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001149/*--------------------------------------------------------------------*/
1150
nethercote57e36b32004-07-10 14:56:28 +00001151// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001152Addr VG_(get_memory_from_mmap_for_client)
1153 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001154{
1155 len = PGROUNDUP(len);
1156
njnca82cc02004-11-22 17:18:48 +00001157 tl_assert(!(sf_flags & SF_FIXED));
1158 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001159
nethercote8e9eab02004-07-11 18:01:06 +00001160 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1161 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1162 sf_flags | SF_CORE, -1, 0);
1163 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001164 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001165 else
1166 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001167}
1168
fitzhardinge98abfc72003-12-16 02:05:15 +00001169
njn86f12dc2005-03-14 01:16:05 +00001170/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001171 range, which isn't SF_CORE, a root.
1172*/
njn86f12dc2005-03-14 01:16:05 +00001173void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1174{
sewardj882af5f2005-03-16 12:27:53 +00001175 Int i;
1176 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001177 Segment *s;
1178
sewardj882af5f2005-03-16 12:27:53 +00001179 for (i = 0; i < segments_used; i++) {
1180 s = &segments[i];
1181 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1182 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001183 if (flags != SF_MMAP && flags != SF_STACK)
1184 continue;
sewardj882af5f2005-03-16 12:27:53 +00001185 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1186 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001187 continue;
1188 if (!VG_(is_client_addr)(s->addr) ||
1189 !VG_(is_client_addr)(s->addr+s->len))
1190 continue;
1191
1192 (*add_rootrange)(s->addr, s->len);
1193 }
njn86f12dc2005-03-14 01:16:05 +00001194}
1195
1196
nethercote88a90162004-07-10 16:59:25 +00001197/*--------------------------------------------------------------------*/
1198/*--- Querying memory layout ---*/
1199/*--------------------------------------------------------------------*/
1200
fitzhardinge98abfc72003-12-16 02:05:15 +00001201Bool VG_(is_client_addr)(Addr a)
1202{
1203 return a >= VG_(client_base) && a < VG_(client_end);
1204}
1205
1206Bool VG_(is_shadow_addr)(Addr a)
1207{
1208 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1209}
1210
fitzhardinge98abfc72003-12-16 02:05:15 +00001211Addr VG_(get_shadow_size)(void)
1212{
1213 return VG_(shadow_end)-VG_(shadow_base);
1214}
1215
sewardjfa8202f2005-04-24 11:05:55 +00001216
nethercote88a90162004-07-10 16:59:25 +00001217/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001218/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001219/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001220
1221void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1222{
sewardj548be6d2005-02-16 01:31:37 +00001223vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001224 if (0)
1225 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1226
1227 vg_assert(VG_(needs).shadow_memory);
1228 vg_assert(VG_(defined_init_shadow_page)());
1229
1230 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1231 p = PGROUNDDN(p);
1232
1233 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1234
1235 if (call_init)
1236 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001237 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001238 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1239
nethercote73b526f2004-10-31 18:48:21 +00001240 p += VKI_PAGE_SIZE;
1241 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001242 }
1243}
1244
1245void *VG_(shadow_alloc)(UInt size)
1246{
1247 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001248 Addr try_here;
1249 Int r;
1250
1251 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001252
1253 vg_assert(VG_(needs).shadow_memory);
1254 vg_assert(!VG_(defined_init_shadow_page)());
1255
1256 size = PGROUNDUP(size);
1257
1258 if (shadow_alloc == 0)
1259 shadow_alloc = VG_(shadow_base);
1260
1261 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001262 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001263
sewardj79048ce2005-02-18 08:28:32 +00001264 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001265 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1266 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001267 vg_assert(size > 0);
1268
1269 if (0)
1270 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1271
1272 /* this is big-bang allocated, so we don't expect to find a listed
1273 segment for it. */
1274 /* This is really an absolute disgrace. Sometimes the big-bang
1275 mapping is in the list (due to re-reads of /proc/self/maps,
1276 presumably) and sometimes it isn't. */
1277#if 0
1278 r = find_segment(try_here);
1279 vg_assert(r == -1);
1280 r = find_segment(try_here+size-1);
1281 vg_assert(r == -1);
1282#endif
1283
1284 r = VG_(mprotect_native)( (void*)try_here,
1285 size, VKI_PROT_READ|VKI_PROT_WRITE );
1286
1287 if (r != 0)
1288 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001289
1290 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001291 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001292
sewardj79048ce2005-02-18 08:28:32 +00001293 failed:
1294 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001295 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001296 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001297 size
sewardj79048ce2005-02-18 08:28:32 +00001298 );
1299 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001300}
1301
1302/*--------------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +00001303/*--- end vg_memory.c ---*/
1304/*--------------------------------------------------------------------*/