blob: eb70990d693d779235a5582539ddb1eefa8fd294 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00003/*--- The address space manager: segment initialisation and ---*/
4/*--- tracking, stack operations ---*/
5/*--- aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00006/*--------------------------------------------------------------------*/
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"
sewardj55f9d1a2005-04-25 11:11:44 +000034#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000035#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000036#include "pub_core_tooliface.h"
sewardj55f9d1a2005-04-25 11:11:44 +000037
sewardjde4a1d02002-03-22 01:27:54 +000038
sewardja4495682002-10-21 07:29:59 +000039/* Define to debug the memory-leak-detector. */
40/* #define VG_DEBUG_LEAKCHECK */
41
sewardje517b802005-02-16 01:58:51 +000042static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000043
44/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000045/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000046/*--------------------------------------------------------------*/
47
sewardj79048ce2005-02-18 08:28:32 +000048/* Max number of segments we can track. */
49#define VG_N_SEGMENTS 1000
50
51/* Max number of segment file names we can track. */
52#define VG_N_SEGNAMES 200
53
54/* Max length of a segment file name. */
55#define VG_MAX_SEGNAMELEN 1000
56
57
58/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000059
60/* Array [0 .. segments_used-1] of all mappings. */
61/* Sorted by .addr field. */
62/* I: len may not be zero. */
63/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000064/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000065
66static Segment segments[VG_N_SEGMENTS];
67static Int segments_used = 0;
68
sewardj79048ce2005-02-18 08:28:32 +000069typedef
70 struct {
71 Bool inUse;
72 Bool mark;
73 HChar fname[VG_MAX_SEGNAMELEN];
74 }
75 SegName;
76
77/* Filename table. _used is the high water mark; an entry is only
78 valid if its index >= 0, < _used, and its .inUse field == True.
79 The .mark field is used to garbage-collect dead entries.
80*/
81static SegName segnames[VG_N_SEGNAMES];
82static Int segnames_used = 0;
83
84
85/* ------ end of STATE for the address-space manager ------ */
86
87
88/* Searches the filename table to find an index for the given name.
89 If none is found, an index is allocated and the name stored. If no
90 space is available we just give up. If the string is too long to
91 store, return -1.
92*/
93static Int allocate_segname ( const HChar* name )
94{
95 Int i, j, len;
96
97 vg_assert(name);
98
99 if (0) VG_(printf)("alloc_segname %s\n", name);
100
101 len = VG_(strlen)(name);
102 if (len >= VG_MAX_SEGNAMELEN-1) {
103 return -1;
104 }
105
106 /* first see if we already have the name. */
107 for (i = 0; i < segnames_used; i++) {
108 if (!segnames[i].inUse)
109 continue;
110 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
111 return i;
112 }
113 }
114
115 /* no we don't. So look for a free slot. */
116 for (i = 0; i < segnames_used; i++)
117 if (!segnames[i].inUse)
118 break;
119
120 if (i == segnames_used) {
121 /* no free slots .. advance the high-water mark. */
122 if (segnames_used+1 < VG_N_SEGNAMES) {
123 i = segnames_used;
124 segnames_used++;
125 } else {
126 VG_(printf)(
127 "coregrind/vg_memory.c:\n"
128 " VG_N_SEGNAMES is too small: "
129 "increase it and rebuild Valgrind.\n"
130 );
131 VG_(printf)(
132 "coregrind/vg_memory.c:\n"
133 " giving up now.\n\n"
134 );
135 VG_(exit)(0);
136 }
137 }
138
139 /* copy it in */
140 segnames[i].inUse = True;
141 for (j = 0; j < len; j++)
142 segnames[i].fname[j] = name[j];
143 vg_assert(len < VG_MAX_SEGNAMELEN);
144 segnames[i].fname[len] = 0;
145 return i;
146}
147
sewardj548be6d2005-02-16 01:31:37 +0000148
149/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
150 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000151 seg.
152*/
sewardj548be6d2005-02-16 01:31:37 +0000153static Int compare_addr_with_seg ( Addr a, Segment* seg )
154{
155 if (a < seg->addr)
156 return -1;
157 if (a >= seg->addr + seg->len)
158 return 1;
159 return 0;
160}
161
sewardj79048ce2005-02-18 08:28:32 +0000162
sewardj548be6d2005-02-16 01:31:37 +0000163/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000164 none.
165*/
sewardj548be6d2005-02-16 01:31:37 +0000166static Int find_segment ( Addr a )
167{
168 Int i;
169 for (i = 0; i < segments_used; i++) {
170 if (compare_addr_with_seg(a, &segments[i]) == 0)
171 return i;
172 }
173 return -1;
174}
175
176
177/* Assumes that 'a' is not in any segment. Finds the index of the
178 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
179 which is in fact in a segment is a checked error.
180*/
181static Int find_segment_above_unmapped ( Addr a )
182{
183 Int i, r;
184 for (i = 0; i < segments_used; i++) {
185 r = compare_addr_with_seg(a, &segments[i]);
186 vg_assert(r != 0); /* 'a' should not be in any segment. */
187 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000188 continue;
sewardj548be6d2005-02-16 01:31:37 +0000189 vg_assert(r == -1);
190 break;
191 }
192
193 if (i == segments_used)
194 return -1; /* not found */
195 else
196 return i;
197}
198
199
200/* Assumes that 'a' is in some segment. Finds the next segment along,
201 or NULL if none. Passing 'a' which is in fact not in a segment is
202 a checked error.
203*/
204static Int find_segment_above_mapped ( Addr a )
205{
206 Int i, r;
207 for (i = 0; i < segments_used; i++) {
208 r = compare_addr_with_seg(a, &segments[i]);
209 if (r == 1)
210 continue; /* not yet there */
211 if (r == 0)
212 break; /* found it */
213 vg_assert(0);
214 /* we shouldn't get here -- r == -1 and so it means we went past
215 'a' without seeing it -- it is therefore unmapped. */
216 /*NOTREACHED*/
217 }
218
219 vg_assert(i < segments_used);
220 if (i == segments_used-1)
221 return -1; /* not found */
222 else
223 return i+1;
224}
225
226
227/* Shift segments[i .. segments_used-1] up by one. */
228static void make_space_at ( Int i )
229{
230 Int j;
231 vg_assert(i >= 0 && i <= segments_used);
232 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000233 if (segments_used+1 == VG_N_SEGMENTS) {
234 VG_(printf)(
235 "coregrind/vg_memory.c:\n"
236 " VG_N_SEGMENTS is too small: "
237 "increase it and rebuild Valgrind.\n"
238 );
239 VG_(printf)(
240 "coregrind/vg_memory.c:\n"
241 " giving up now.\n\n"
242 );
243 VG_(exit)(0);
244 }
sewardj548be6d2005-02-16 01:31:37 +0000245 vg_assert(segments_used+1 < VG_N_SEGMENTS);
246 for (j = segments_used; j > i; j--)
247 segments[j] = segments[j-1];
248 segments_used++;
249}
250
sewardj79048ce2005-02-18 08:28:32 +0000251
sewardj548be6d2005-02-16 01:31:37 +0000252/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000253 segments_used.
254*/
sewardj548be6d2005-02-16 01:31:37 +0000255static void delete_segment_at ( Int i )
256{
257 Int j;
258 vg_assert(i >= 0 && i < segments_used);
259 for (j = i+1; j < segments_used; j++)
260 segments[j-1] = segments[j];
261 segments_used--;
262 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
263}
264
265
266/* Fill the i'th record all with zeroes. */
267static void zeroise_segment ( Int i )
268{
269 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000270 segments[i].prot = 0;
271 segments[i].flags = 0;
272 segments[i].addr = 0;
273 segments[i].len = 0;
274 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000275 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000276 segments[i].fnIdx = -1;
277 segments[i].dev = 0;
278 segments[i].ino = 0;
279 segments[i].symtab = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000280}
281
sewardj79048ce2005-02-18 08:28:32 +0000282
sewardj548be6d2005-02-16 01:31:37 +0000283/* Create a segment to contain 'a', and return its index. Or -1 if
284 this failed because some other segment already contains 'a'. If
285 successful, fill in the segment's .addr field with 'a' but leave
286 all other fields alone.
287*/
288static Int create_segment ( Addr a )
289{
290 Int i, r;
291 for (i = 0; i < segments_used; i++) {
292 r = compare_addr_with_seg( a, &segments[i] );
293 if (r == 1)
294 continue; /* seg[i] precedes a */
295 if (r == 0)
296 return -1; /* seg[i] contains a. Give up */
297 vg_assert(r == -1);
298 break;
299 }
300 /* a precedes seg[i]. Shift segs at i and above up one, and use
301 this slot. */
302 make_space_at(i);
303 zeroise_segment(i);
304 segments[i].addr = a;
305 return i;
306}
307
sewardj79048ce2005-02-18 08:28:32 +0000308
309/* Print out the segment array (debugging only!). Note, this calls
310 VG_(printf), and I'm not 100% clear that that wouldn't require
311 dynamic memory allocation and hence more segments to be allocated.
312*/
313static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000314{
sewardj79048ce2005-02-18 08:28:32 +0000315 Int i;
316 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
317 who, segments_used, segnames_used);
318 for (i = 0; i < segnames_used; i++) {
319 if (!segnames[i].inUse)
320 continue;
321 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
322 }
323 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000324 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000325 "%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 +0000326 i,
sewardj79048ce2005-02-18 08:28:32 +0000327 segments[i].addr, segments[i].addr + segments[i].len,
328 (ULong)segments[i].len, segments[i].prot,
329 segments[i].flags, segments[i].dev, segments[i].ino,
330 (Long)segments[i].offset,
331 segments[i].fnIdx);
332 }
333 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000334}
sewardj79048ce2005-02-18 08:28:32 +0000335
sewardj548be6d2005-02-16 01:31:37 +0000336
337/* Find the segment containing 'a' and split it into two pieces at
338 'a'. Does nothing if no segment contains 'a', or if the split
339 would cause either of the pieces to have zero size.
340
341 If 'a' is not found, or if no splitting happens, -1 is returned.
342
343 If a value 'r' other than -1 is returned, this is the index of the
344 higher-addressed segment resulting from the split, and the index of
345 the lower-addressed segment is r-1.
346*/
347static Int split_segment ( Addr a )
348{
349 Int r;
350 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000351 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000352 r = find_segment(a);
353 if (r == -1)
354 /* not found */
355 return -1;
356 if (segments[r].addr == a)
357 /* segment starts at 'a', so splitting it would create a
358 zero-sized segment */
359 return -1;
360
361 /* copy original; make adjustments. */
362 vg_assert(a > segments[r].addr);
363 delta = a - segments[r].addr;
364 make_space_at(r);
365 segments[r] = segments[r+1];
366 segments[r].len = delta;
367 segments[r+1].len -= delta;
368 segments[r+1].addr += delta;
369 segments[r+1].offset += delta;
370 return r+1;
371}
372
sewardj79048ce2005-02-18 08:28:32 +0000373
374/* Return true if two segments are adjacent and mergable (s1 is
375 assumed to have a lower ->addr than s2) */
376static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
377{
378 if (s1->addr+s1->len != s2->addr)
379 return False;
380
381 if (s1->flags != s2->flags)
382 return False;
383
384 if (s1->prot != s2->prot)
385 return False;
386
387 if (s1->symtab != s2->symtab)
388 return False;
389
390 if (s1->flags & SF_FILE){
391 if ((s1->offset + s1->len) != s2->offset)
392 return False;
393 if (s1->dev != s2->dev)
394 return False;
395 if (s1->ino != s2->ino)
396 return False;
397 if (s1->fnIdx != s2->fnIdx)
398 return False;
399 }
400
401 return True;
402}
403
404
405/* Clean up and sanity check the segment array:
406 - check segments are in ascending order
407 - check segments do not overlap
408 - check no segment has zero size
409 - merge adjacent where possible
410 - perform checks on the filename table, and reclaim dead entries
411*/
412static void preen_segments ( void )
413{
414 Int i, j, rd, wr;
415 Segment *s, *s1;
416 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
417 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
418
419 if (0) show_segments("before preen");
420
421 /* clear string table mark bits */
422 for (i = 0; i < segnames_used; i++)
423 segnames[i].mark = False;
424
425 /* check for non-zero size, and set mark bits for any used strings */
426 for (i = 0; i < segments_used; i++) {
427 vg_assert(segments[i].len > 0);
428 j = segments[i].fnIdx;
429 vg_assert(j >= -1 && j < segnames_used);
430 if (j >= 0) {
431 vg_assert(segnames[j].inUse);
432 segnames[j].mark = True;
433 }
434 }
435
436 /* check ascendingness and non-overlap */
437 for (i = 0; i < segments_used-1; i++) {
438 s = &segments[i];
439 s1 = &segments[i+1];
440 vg_assert(s->addr < s1->addr);
441 vg_assert(s->addr + s->len <= s1->addr);
442 }
443
444 /* merge */
445 if (segments_used < 1)
446 return;
447
448 wr = 1;
449 for (rd = 1; rd < segments_used; rd++) {
450 s = &segments[wr-1];
451 s1 = &segments[rd];
452 if (segments_are_mergeable(s,s1)) {
453 if (0)
454 VG_(printf)("merge %p-%p with %p-%p\n",
455 s->addr, s->addr+s->len,
456 s1->addr, s1->addr+s1->len);
457 s->len += s1->len;
458 continue;
459 }
460 if (wr < rd)
461 segments[wr] = segments[rd];
462 wr++;
463 }
464 vg_assert(wr >= 0 && wr <= segments_used);
465 segments_used = wr;
466
467 /* Free up any strings which are no longer referenced. */
468 for (i = 0; i < segnames_used; i++) {
469 if (segnames[i].mark == False) {
470 segnames[i].inUse = False;
471 segnames[i].fname[0] = 0;
472 }
473 }
474
475 if (0) show_segments("after preen");
476}
477
478
sewardj548be6d2005-02-16 01:31:37 +0000479/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000480/*--- Maintain an ordered list of all the client's mappings ---*/
481/*--------------------------------------------------------------*/
482
nethercote8991d5a2004-11-03 17:07:46 +0000483Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000484{
485 Addr se = s->addr+s->len;
486 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000487 vg_assert(pe >= p);
488
489 return (p >= s->addr && pe <= se);
490}
491
nethercote8991d5a2004-11-03 17:07:46 +0000492Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000493{
494 Addr se = s->addr+s->len;
495 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000496 vg_assert(pe >= p);
497
498 return (p < se && pe > s->addr);
499}
500
sewardj1024cf72005-02-28 14:39:21 +0000501#if 0
502/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000503/* Prepare a Segment structure for recycling by freeing everything
504 hanging off it. */
505static void recycleseg(Segment *s)
506{
507 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000508 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000509
510 if (s->filename != NULL)
511 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
512
513 /* keep the SegInfo, if any - it probably still applies */
514}
515
516/* When freeing a Segment, also clean up every one else's ideas of
517 what was going on in that range of memory */
518static void freeseg(Segment *s)
519{
520 recycleseg(s);
521 if (s->symtab != NULL) {
nethercote8991d5a2004-11-03 17:07:46 +0000522 VG_(symtab_decref)(s->symtab, s->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000523 s->symtab = NULL;
524 }
525
526 VG_(SkipNode_Free)(&sk_segments, s);
527}
sewardj1024cf72005-02-28 14:39:21 +0000528#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000529
sewardj1024cf72005-02-28 14:39:21 +0000530
531/* Get rid of any translations arising from s. */
532/* Note, this is not really the job of the low level memory manager.
533 When it comes time to rewrite this subsystem, clean this up. */
534static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000535{
sewardj1024cf72005-02-28 14:39:21 +0000536 if (s->flags & SF_CODE) {
537 VG_(discard_translations)(s->addr, s->len);
538 if (0)
539 VG_(printf)("dumping translations in %p .. %p\n",
540 s->addr, s->addr+s->len);
541 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000542}
543
sewardj1024cf72005-02-28 14:39:21 +0000544
fitzhardinge98abfc72003-12-16 02:05:15 +0000545/* This unmaps all the segments in the range [addr, addr+len); any
546 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000547void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000548{
fitzhardingee3632c62003-12-22 10:58:06 +0000549 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000550 Segment* s;
551 Addr end, s_end;
552 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000553 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000554
555 if (len == 0)
556 return;
557
fitzhardinge1a4adf02003-12-22 10:42:59 +0000558 len = PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000559
fitzhardinge98abfc72003-12-16 02:05:15 +0000560 if (debug)
tom9be7c982005-04-25 16:55:44 +0000561 VG_(printf)("unmap_range(%p, %lu)\n", addr, len);
sewardj79048ce2005-02-18 08:28:32 +0000562 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000563 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000564
565 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000566 vg_assert(VG_IS_PAGE_ALIGNED(addr));
567 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000568
sewardj548be6d2005-02-16 01:31:37 +0000569 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000570
571 /* do not delete .. even though it looks stupid */
572 vg_assert(i >= 0);
573
574 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000575 s = &segments[i];
576 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000577
sewardj548be6d2005-02-16 01:31:37 +0000578 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000579 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000580 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000581
fitzhardinge1a303042003-12-22 08:48:50 +0000582 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000583 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000584 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000585 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000586 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000587
588 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000589 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000590 addr < s_end &&
591 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000592 /* this segment's tail is truncated by [addr, addr+len)
593 -> truncate tail
594 */
sewardj1024cf72005-02-28 14:39:21 +0000595 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000596 s->len = addr - s->addr;
597
598 if (debug)
tom9be7c982005-04-25 16:55:44 +0000599 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000600 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000601 /* this segment's head is truncated by [addr, addr+len)
602 -> truncate head
603 */
sewardj548be6d2005-02-16 01:31:37 +0000604 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000605
606 if (debug)
tom9be7c982005-04-25 16:55:44 +0000607 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000608 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000609
sewardj1024cf72005-02-28 14:39:21 +0000610 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000611 s->addr += delta;
612 s->offset += delta;
613 s->len -= delta;
614
615 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000616 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000617 /* this segment is completely contained within [addr, addr+len)
618 -> delete segment
619 */
sewardj1024cf72005-02-28 14:39:21 +0000620 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000621 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000622 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000623
624 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000625 VG_(printf)(" case 3: seg %d deleted\n", i);
626 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000627 /* [addr, addr+len) is contained within a single segment
628 -> split segment into 3, delete middle portion
629 */
sewardj1024cf72005-02-28 14:39:21 +0000630 Int i_middle;
631 dump_translations_from(s);
632 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000633 vg_assert(i_middle != -1);
634 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000635 vg_assert(segments[i_middle].addr == addr);
636 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000637 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000638
639 if (debug)
640 VG_(printf)(" case 4: subrange %p-%p deleted\n",
641 addr, addr+len);
642 }
sewardj47c98a72005-03-12 20:36:15 +0000643
644 /* If we deleted this segment (or any above), those above will
645 have been moved down to fill in the hole in the segment
646 array. In order that we don't miss them, we have to
647 re-consider this slot number; hence the i--. */
648 if (deleted)
649 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000650 }
sewardj79048ce2005-02-18 08:28:32 +0000651 preen_segments();
652 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000653}
654
sewardj548be6d2005-02-16 01:31:37 +0000655
656/* Add a binding of [addr,addr+len) to
657 (prot,flags,dev,ino,off,filename) in the segment array.
658 Delete/truncate any previous mapping(s) covering that range.
659*/
660void
661VG_(map_file_segment)( Addr addr, SizeT len,
662 UInt prot, UInt flags,
663 UInt dev, UInt ino, ULong off,
664 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000665{
fitzhardinge98abfc72003-12-16 02:05:15 +0000666 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000667 Segment* s;
668 Int idx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000669
670 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000671 VG_(printf)(
672 "\n"
tom9be7c982005-04-25 16:55:44 +0000673 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000674 " dev=0x%4x ino=%d off=%ld\n"
675 " filename='%s')\n",
676 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000677
678 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000679 vg_assert(VG_IS_PAGE_ALIGNED(addr));
fitzhardinge98abfc72003-12-16 02:05:15 +0000680 len = PGROUNDUP(len);
681
sewardj548be6d2005-02-16 01:31:37 +0000682 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
683 VG_(unmap_range)(addr, len);
684
685 /* and now install this one */
686 idx = create_segment(addr);
687 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
688 vg_assert(idx != -1);
689 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000690
sewardj79048ce2005-02-18 08:28:32 +0000691 s = &segments[idx];
692 vg_assert(s->addr == addr);
693 s->prot = prot;
694 s->flags = flags;
695 s->len = len;
696 s->offset = off;
697 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
698 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
699 s->dev = dev;
700 s->ino = ino;
701 s->symtab = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000702
sewardj79048ce2005-02-18 08:28:32 +0000703 /* Clean up right now */
704 preen_segments();
705 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000706
707 /* If this mapping is of the beginning of a file, isn't part of
708 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000709 file, then try reading symbols from it.
710 */
711 if (s->symtab == NULL
sewardjb71816c2005-03-14 19:11:10 +0000712 && (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
sewardj79048ce2005-02-18 08:28:32 +0000713 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
714 if (off == 0
715 && s->fnIdx != -1
716 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
717 && len >= VKI_PAGE_SIZE
718 && VG_(is_object_file)((void *)addr)) {
nethercote71980f02004-01-24 18:18:54 +0000719 s->symtab = VG_(read_seg_symbols)(s);
nethercote71980f02004-01-24 18:18:54 +0000720 if (s->symtab != NULL) {
721 s->flags |= SF_DYNLIB;
722 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000723 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000724#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000725 const SegInfo *info;
726
727 /* Otherwise see if an existing symtab applies to this Segment */
728 for(info = VG_(next_seginfo)(NULL);
729 info != NULL;
730 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000731 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
732 {
fitzhardinge98abfc72003-12-16 02:05:15 +0000733 s->symtab = (SegInfo *)info;
734 VG_(symtab_incref)((SegInfo *)info);
735 }
736 }
sewardj79048ce2005-02-18 08:28:32 +0000737#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000738 }
739 }
740
741 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000742 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000743}
744
nethercote8b5f40c2004-11-02 13:29:50 +0000745void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000746 Int fd, ULong off, const Char *filename)
747{
748 struct vki_stat st;
749 Char *name = NULL;
750
751 st.st_dev = 0;
752 st.st_ino = 0;
753
754 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000755 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000756
757 if (VG_(fstat)(fd, &st) < 0)
758 flags &= ~SF_FILE;
759 }
760
sewardj79048ce2005-02-18 08:28:32 +0000761 if ((flags & SF_FILE) && filename == NULL && fd != -1)
762 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000763
764 if (filename == NULL)
765 filename = name;
766
sewardj79048ce2005-02-18 08:28:32 +0000767 VG_(map_file_segment)(addr, len, prot, flags,
768 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000769}
770
nethercote8b5f40c2004-11-02 13:29:50 +0000771void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000772{
773 flags &= ~SF_FILE;
774
775 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
776}
777
778/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000779void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000780{
sewardj79048ce2005-02-18 08:28:32 +0000781 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000782 static const Bool debug = False || mem_debug;
783
784 if (debug)
tom9be7c982005-04-25 16:55:44 +0000785 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000786
787 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000788
789 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000790 vg_assert(VG_IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000791 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000792
sewardj79048ce2005-02-18 08:28:32 +0000793 split_segment(a);
794 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000795
sewardj548be6d2005-02-16 01:31:37 +0000796 r = find_segment(a);
797 vg_assert(r != -1);
798 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000799
800 preen_segments();
801
sewardje517b802005-02-16 01:58:51 +0000802 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000803}
804
sewardj79048ce2005-02-18 08:28:32 +0000805
sewardj548be6d2005-02-16 01:31:37 +0000806/* Try to find a map space for [addr,addr+len). If addr==0, it means
807 the caller is prepared to accept a space at any location; if not,
808 we will try for addr, but fail if we can't get it. This mimics
809 mmap fixed vs mmap not-fixed.
810*/
nethercote8b5f40c2004-11-02 13:29:50 +0000811Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000812{
fitzhardingee3632c62003-12-22 10:58:06 +0000813 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000814 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000815 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000816 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
817 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000818 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
819 Int i, i_any, i_fixed, i_final;
820 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000821
sewardj548be6d2005-02-16 01:31:37 +0000822 Bool fixed;
823
sewardje517b802005-02-16 01:58:51 +0000824 if (debug) {
825 VG_(printf)("\n\n");
tom9be7c982005-04-25 16:55:44 +0000826 VG_(printf)("find_map_space(%p, %lu, %d) ...\n",
sewardje517b802005-02-16 01:58:51 +0000827 addr, len, for_client);
828 }
829
830 if (0) show_segments("find_map_space: start");
831
sewardj548be6d2005-02-16 01:31:37 +0000832 if (addr == 0) {
833 fixed = False;
834 } else {
835 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000836 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000837 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000838 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000839 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000840
841 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000842 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000843 len = PGROUNDUP(len);
844
nethercote73b526f2004-10-31 18:48:21 +0000845 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000846
sewardj548be6d2005-02-16 01:31:37 +0000847 /* Scan the segment list, looking for a hole which satisfies the
848 requirements. At each point i we ask the question "can we use
849 the hole in between segments[i-1] and segments[i] ?" */
850 i_any = i_fixed = -1;
851 hstart_any = hstart_fixed = 0;
852
853 hole_start = hole_end = 0;
854
855 /* Iterate over all possible holes, generating them into
856 hole_start/hole_end. Filter out invalid ones. Then see if any
857 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
858 */
859 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
860 if (i == 0) {
861 hole_start = 0;
862 hole_end = segments[0].addr-1;
863 }
864 else {
865 vg_assert(segments_used > 0);
866 if (i == segments_used) {
867 hole_start = segments[i-1].addr + segments[i-1].len;
868 hole_end = ~(Addr)0;
869 } else {
870 hole_start = segments[i-1].addr + segments[i-1].len;
871 hole_end = segments[i].addr - 1;
872 }
873 }
874
875 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
876
877 /* ignore zero-sized holes */
878 if (hole_start == hole_end+1)
879 continue;
880
njnbe91aae2005-03-27 01:42:41 +0000881 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
882 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000883
884 /* ignore holes which fall outside the allowable area */
885 if (!(hole_start >= base && hole_end <= limit))
886 continue;
887
888 vg_assert(hole_end > hole_start);
889 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000890 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000891
892 if (hole_len >= len && i_any == -1) {
893 /* It will at least fit in this hole. */
894 i_any = i;
895 hstart_any = hole_start;
896 }
897
sewardjb5f6f512005-03-10 23:59:00 +0000898 if (fixed && hole_start <= addr
899 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000900 /* We were asked for a fixed mapping, and this hole works.
901 Bag it -- and stop searching as further searching is
902 pointless. */
903 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000904 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000905 break;
906 }
907 }
908
909 /* Summarise the final decision into i_final/hstart_final. */
910 i_final = -1;
911 hstart_final = 0;
912
913 if (fixed) {
914 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000915 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000916 } else {
917 i_final = i_any;
918 hstart_final = hstart_any;
919 }
920
921
922 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000923 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000924 else
925 ret = 0; /* not found */
926
927 if (debug)
tom9be7c982005-04-25 16:55:44 +0000928 VG_(printf)("find_map_space(%p, %lu, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000929 addr, len, for_client, ret);
930
sewardjb5f6f512005-03-10 23:59:00 +0000931 if (fixed) {
932 vg_assert(ret == 0 || ret == addrOrig);
933 }
934
sewardj548be6d2005-02-16 01:31:37 +0000935 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000936}
937
sewardj79048ce2005-02-18 08:28:32 +0000938
sewardjb5f6f512005-03-10 23:59:00 +0000939/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000940 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000941 mapping over any part of the address space which is not covered
942 by an entry in the segment list.
943
944 This is designed for use around system calls which allocate
945 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000946 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000947 address with VG_(find_map_space) and then adding a segment for
948 it and padding the address space valgrind can ensure that the
949 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000950void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000951{
sewardj394790d2005-03-17 02:14:44 +0000952 Addr addr = (start == 0) ? VG_(client_base) : start;
953 Addr ret;
954
955 Int i = 0;
956 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000957
nethercote820bd8c2004-09-07 23:04:49 +0000958 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000959 if (addr < s->addr) {
njnf6d228b2005-03-26 02:42:31 +0000960 VGP_DO_MMAP(ret, addr, s->addr - addr, 0,
961 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
962 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000963 }
thughes9aaebc32004-07-15 23:13:37 +0000964 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000965 i++;
966 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000967 }
968
nethercote820bd8c2004-09-07 23:04:49 +0000969 if (addr <= VG_(valgrind_last)) {
njnf6d228b2005-03-26 02:42:31 +0000970 VGP_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
971 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
972 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000973 }
thughes9aaebc32004-07-15 23:13:37 +0000974}
975
thughesc70b8c62004-07-16 23:07:58 +0000976/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000977 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +0000978void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000979{
sewardj394790d2005-03-17 02:14:44 +0000980 Addr addr = (start == 0) ? VG_(client_base) : start;
981 Int ret;
982
983 Int i = 0;
984 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000985
nethercote820bd8c2004-09-07 23:04:49 +0000986 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000987 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +0000988 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +0000989 }
thughes9aaebc32004-07-15 23:13:37 +0000990 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000991 i++;
992 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000993 }
994
nethercote820bd8c2004-09-07 23:04:49 +0000995 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +0000996 ret = VG_(do_syscall2)(__NR_munmap, addr,
997 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +0000998 }
thughes9aaebc32004-07-15 23:13:37 +0000999}
1000
sewardj548be6d2005-02-16 01:31:37 +00001001/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001002Segment *VG_(find_segment)(Addr a)
1003{
sewardj548be6d2005-02-16 01:31:37 +00001004 Int r = find_segment(a);
1005 if (0) show_segments("find_segment");
1006 if (r == -1) return NULL;
1007 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001008}
1009
sewardj548be6d2005-02-16 01:31:37 +00001010/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1011 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1012 a segment is a checked error.
1013*/
1014Segment *VG_(find_segment_above_unmapped)(Addr a)
1015{
1016 Int r = find_segment_above_unmapped(a);
1017 if (0) show_segments("find_segment_above_unmapped");
1018 if (r == -1) return NULL;
1019 return &segments[r];
1020}
1021
1022/* Assumes that 'a' is in some segment. Finds the next segment along,
1023 or NULL if none. Passing 'a' which is in fact not in a segment is
1024 a checked error.
1025*/
1026Segment *VG_(find_segment_above_mapped)(Addr a)
1027{
1028 Int r = find_segment_above_mapped(a);
1029 if (0) show_segments("find_segment_above_mapped");
1030 if (r == -1) return NULL;
1031 return &segments[r];
1032}
1033
1034
sewardjde4a1d02002-03-22 01:27:54 +00001035/*------------------------------------------------------------*/
1036/*--- Tracking permissions around %esp changes. ---*/
1037/*------------------------------------------------------------*/
1038
1039/*
1040 The stack
1041 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001042 The stack's segment seems to be dynamically extended downwards by
1043 the kernel as the stack pointer moves down. Initially, a 1-page
1044 (4k) stack is allocated. When SP moves below that for the first
1045 time, presumably a page fault occurs. The kernel detects that the
njna60a7c12005-05-08 17:49:37 +00001046 faulting address is in the range from SP - VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001047 upwards to the current valid stack. It then extends the stack
1048 segment downwards for enough to cover the faulting address, and
1049 resumes the process (invisibly). The process is unaware of any of
1050 this.
sewardjde4a1d02002-03-22 01:27:54 +00001051
sewardjfa8202f2005-04-24 11:05:55 +00001052 That means that Valgrind can't spot when the stack segment is being
1053 extended. Fortunately, we want to precisely and continuously
1054 update stack permissions around SP, so we need to spot all writes
1055 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001056
sewardjfa8202f2005-04-24 11:05:55 +00001057 The deal is: when SP is assigned a lower value, the stack is being
1058 extended. Create suitably-permissioned pages to fill in any holes
1059 between the old stack ptr and this one, if necessary. Then mark
1060 all bytes in the area just "uncovered" by this SP change as
1061 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001062
sewardjfa8202f2005-04-24 11:05:55 +00001063 When SP goes back up, mark the area receded over as unreadable and
1064 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001065
njna60a7c12005-05-08 17:49:37 +00001066 Just to record the SP boundary conditions somewhere convenient:
1067 SP - VGA_STACK_REDZONE_SZB always points to the lowest live byte in
1068 the stack. All addresses below SP - VGA_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001069 live; those at and above it are.
1070
njna60a7c12005-05-08 17:49:37 +00001071 We do not concern ourselves here with the VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001072 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001073*/
1074
njn9b007f62003-04-07 14:40:25 +00001075/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001076 tracked by the tool, and one of the specialised cases
1077 (eg. new_mem_stack_4) isn't used in preference.
1078*/
njn9fb73db2005-03-27 01:55:21 +00001079VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001080void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001081{
sewardj97724e52005-04-02 23:40:59 +00001082 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001083 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001084
sewardj97724e52005-04-02 23:40:59 +00001085 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1086 /* SP has changed by more than some threshold amount (by
1087 default, 2MB). We take this to mean that the application is
1088 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001089
1090 JRS 20021001: following discussions with John Regehr, if a stack
1091 switch happens, it seems best not to mess at all with memory
1092 permissions. Seems to work well with Netscape 4.X. Really the
1093 only remaining difficulty is knowing exactly when a stack switch is
1094 happening. */
sewardj97724e52005-04-02 23:40:59 +00001095 if (VG_(clo_verbosity) > 0 && moans > 0) {
1096 moans--;
1097 VG_(message)(Vg_UserMsg,
1098 "Warning: client switching stacks? "
1099 "SP change: %p --> %p", old_SP, new_SP);
1100 VG_(message)(Vg_UserMsg,
1101 " to suppress, use: --max-stackframe=%d or greater",
1102 (delta < 0 ? -delta : delta));
1103 if (moans == 0)
1104 VG_(message)(Vg_UserMsg,
1105 " further instances of this message "
1106 "will not be shown.");
1107 }
njn9b007f62003-04-07 14:40:25 +00001108 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001109 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001110
njn9b007f62003-04-07 14:40:25 +00001111 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001112 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001113 }
1114}
1115
jsgf855d93d2003-10-13 22:26:55 +00001116/*
sewardjb5f6f512005-03-10 23:59:00 +00001117 Test if a piece of memory is addressable with at least the "prot"
1118 protection permissions by examining the underlying segments.
1119
1120 Really this is a very stupid algorithm and we could do much
1121 better by iterating through the segment array instead of through
1122 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001123 */
sewardjb5f6f512005-03-10 23:59:00 +00001124Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001125{
sewardjb5f6f512005-03-10 23:59:00 +00001126 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001127
sewardjb5f6f512005-03-10 23:59:00 +00001128 if ((p + size) < p)
1129 return False; /* reject wraparounds */
1130 if (size == 0)
1131 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001132
sewardjb5f6f512005-03-10 23:59:00 +00001133 p = PGROUNDDN(p);
1134 size = PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001135 vg_assert(VG_IS_PAGE_ALIGNED(p));
1136 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001137
sewardjb5f6f512005-03-10 23:59:00 +00001138 for (; size > 0; size -= VKI_PAGE_SIZE) {
1139 seg = VG_(find_segment)(p);
1140 if (!seg)
1141 return False;
1142 if ((seg->prot & prot) != prot)
1143 return False;
1144 p += VKI_PAGE_SIZE;
1145 }
jsgf855d93d2003-10-13 22:26:55 +00001146
sewardjb5f6f512005-03-10 23:59:00 +00001147 return True;
jsgf855d93d2003-10-13 22:26:55 +00001148}
1149
sewardjb5f6f512005-03-10 23:59:00 +00001150
sewardjde4a1d02002-03-22 01:27:54 +00001151/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001152/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001153/*--------------------------------------------------------------------*/
1154
nethercote57e36b32004-07-10 14:56:28 +00001155// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001156Addr VG_(get_memory_from_mmap_for_client)
1157 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001158{
1159 len = PGROUNDUP(len);
1160
njnca82cc02004-11-22 17:18:48 +00001161 tl_assert(!(sf_flags & SF_FIXED));
1162 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001163
nethercote8e9eab02004-07-11 18:01:06 +00001164 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1165 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1166 sf_flags | SF_CORE, -1, 0);
1167 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001168 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001169 else
1170 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001171}
1172
fitzhardinge98abfc72003-12-16 02:05:15 +00001173
njn86f12dc2005-03-14 01:16:05 +00001174/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001175 range, which isn't SF_CORE, a root.
1176*/
njn86f12dc2005-03-14 01:16:05 +00001177void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1178{
sewardj882af5f2005-03-16 12:27:53 +00001179 Int i;
1180 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001181 Segment *s;
1182
sewardj882af5f2005-03-16 12:27:53 +00001183 for (i = 0; i < segments_used; i++) {
1184 s = &segments[i];
1185 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1186 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001187 if (flags != SF_MMAP && flags != SF_STACK)
1188 continue;
sewardj882af5f2005-03-16 12:27:53 +00001189 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1190 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001191 continue;
1192 if (!VG_(is_client_addr)(s->addr) ||
1193 !VG_(is_client_addr)(s->addr+s->len))
1194 continue;
1195
1196 (*add_rootrange)(s->addr, s->len);
1197 }
njn86f12dc2005-03-14 01:16:05 +00001198}
1199
1200
nethercote88a90162004-07-10 16:59:25 +00001201/*--------------------------------------------------------------------*/
1202/*--- Querying memory layout ---*/
1203/*--------------------------------------------------------------------*/
1204
fitzhardinge98abfc72003-12-16 02:05:15 +00001205Bool VG_(is_client_addr)(Addr a)
1206{
1207 return a >= VG_(client_base) && a < VG_(client_end);
1208}
1209
1210Bool VG_(is_shadow_addr)(Addr a)
1211{
1212 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1213}
1214
fitzhardinge98abfc72003-12-16 02:05:15 +00001215Addr VG_(get_shadow_size)(void)
1216{
1217 return VG_(shadow_end)-VG_(shadow_base);
1218}
1219
sewardjfa8202f2005-04-24 11:05:55 +00001220
nethercote88a90162004-07-10 16:59:25 +00001221/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001222/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001223/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001224
1225void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1226{
sewardj548be6d2005-02-16 01:31:37 +00001227vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001228 if (0)
1229 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1230
1231 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001232 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001233
1234 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1235 p = PGROUNDDN(p);
1236
1237 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1238
1239 if (call_init)
1240 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001241 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001242 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1243
nethercote73b526f2004-10-31 18:48:21 +00001244 p += VKI_PAGE_SIZE;
1245 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001246 }
1247}
1248
1249void *VG_(shadow_alloc)(UInt size)
1250{
1251 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001252 Addr try_here;
1253 Int r;
1254
1255 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001256
1257 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001258 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001259
1260 size = PGROUNDUP(size);
1261
1262 if (shadow_alloc == 0)
1263 shadow_alloc = VG_(shadow_base);
1264
1265 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001266 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001267
sewardj79048ce2005-02-18 08:28:32 +00001268 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001269 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1270 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001271 vg_assert(size > 0);
1272
1273 if (0)
1274 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1275
1276 /* this is big-bang allocated, so we don't expect to find a listed
1277 segment for it. */
1278 /* This is really an absolute disgrace. Sometimes the big-bang
1279 mapping is in the list (due to re-reads of /proc/self/maps,
1280 presumably) and sometimes it isn't. */
1281#if 0
1282 r = find_segment(try_here);
1283 vg_assert(r == -1);
1284 r = find_segment(try_here+size-1);
1285 vg_assert(r == -1);
1286#endif
1287
1288 r = VG_(mprotect_native)( (void*)try_here,
1289 size, VKI_PROT_READ|VKI_PROT_WRITE );
1290
1291 if (r != 0)
1292 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001293
1294 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001295 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001296
sewardj79048ce2005-02-18 08:28:32 +00001297 failed:
1298 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001299 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001300 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001301 size
sewardj79048ce2005-02-18 08:28:32 +00001302 );
1303 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001304}
1305
1306/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001307/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001308/*--------------------------------------------------------------------*/