blob: 36d42cd3f156fdf1aa5ccf7a4aa47f8eb8b6b99c [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"
njn97405b22005-06-02 03:39:33 +000035#include "pub_core_libcbase.h"
njn20242342005-05-16 23:31:24 +000036#include "pub_core_options.h"
njn2521d322005-05-08 14:45:13 +000037#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000038#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000039#include "pub_core_transtab.h"
njn3c660b62005-05-13 22:18:47 +000040#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000041
sewardjde4a1d02002-03-22 01:27:54 +000042
sewardja4495682002-10-21 07:29:59 +000043/* Define to debug the memory-leak-detector. */
44/* #define VG_DEBUG_LEAKCHECK */
45
sewardje517b802005-02-16 01:58:51 +000046static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000047
48/*--------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +000049/*--- Basic globals about the address space. ---*/
50/*--------------------------------------------------------------*/
51
52/* Client address space, lowest to highest (see top of ume.c) */
53Addr VG_(client_base); /* client address space limits */
54Addr VG_(client_end);
55Addr VG_(client_mapbase);
56Addr VG_(client_trampoline_code);
57Addr VG_(clstk_base);
58Addr VG_(clstk_end);
59
60Addr VG_(brk_base); /* start of brk */
61Addr VG_(brk_limit); /* current brk */
62
63Addr VG_(shadow_base); /* tool's shadow memory */
64Addr VG_(shadow_end);
65
66Addr VG_(valgrind_base); /* valgrind's address range */
67
68// Note that VG_(valgrind_last) names the last byte of the section, whereas
69// the VG_(*_end) vars name the byte one past the end of the section.
70Addr VG_(valgrind_last);
71
72/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000073/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000074/*--------------------------------------------------------------*/
75
sewardj79048ce2005-02-18 08:28:32 +000076/* Max number of segments we can track. */
77#define VG_N_SEGMENTS 1000
78
79/* Max number of segment file names we can track. */
80#define VG_N_SEGNAMES 200
81
82/* Max length of a segment file name. */
83#define VG_MAX_SEGNAMELEN 1000
84
85
86/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000087
88/* Array [0 .. segments_used-1] of all mappings. */
89/* Sorted by .addr field. */
90/* I: len may not be zero. */
91/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000092/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000093
94static Segment segments[VG_N_SEGMENTS];
95static Int segments_used = 0;
96
sewardj79048ce2005-02-18 08:28:32 +000097typedef
98 struct {
99 Bool inUse;
100 Bool mark;
101 HChar fname[VG_MAX_SEGNAMELEN];
102 }
103 SegName;
104
105/* Filename table. _used is the high water mark; an entry is only
106 valid if its index >= 0, < _used, and its .inUse field == True.
107 The .mark field is used to garbage-collect dead entries.
108*/
109static SegName segnames[VG_N_SEGNAMES];
110static Int segnames_used = 0;
111
112
113/* ------ end of STATE for the address-space manager ------ */
114
115
116/* Searches the filename table to find an index for the given name.
117 If none is found, an index is allocated and the name stored. If no
118 space is available we just give up. If the string is too long to
119 store, return -1.
120*/
121static Int allocate_segname ( const HChar* name )
122{
123 Int i, j, len;
124
125 vg_assert(name);
126
127 if (0) VG_(printf)("alloc_segname %s\n", name);
128
129 len = VG_(strlen)(name);
130 if (len >= VG_MAX_SEGNAMELEN-1) {
131 return -1;
132 }
133
134 /* first see if we already have the name. */
135 for (i = 0; i < segnames_used; i++) {
136 if (!segnames[i].inUse)
137 continue;
138 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
139 return i;
140 }
141 }
142
143 /* no we don't. So look for a free slot. */
144 for (i = 0; i < segnames_used; i++)
145 if (!segnames[i].inUse)
146 break;
147
148 if (i == segnames_used) {
149 /* no free slots .. advance the high-water mark. */
150 if (segnames_used+1 < VG_N_SEGNAMES) {
151 i = segnames_used;
152 segnames_used++;
153 } else {
154 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000155 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000156 " VG_N_SEGNAMES is too small: "
157 "increase it and rebuild Valgrind.\n"
158 );
159 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000160 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000161 " giving up now.\n\n"
162 );
163 VG_(exit)(0);
164 }
165 }
166
167 /* copy it in */
168 segnames[i].inUse = True;
169 for (j = 0; j < len; j++)
170 segnames[i].fname[j] = name[j];
171 vg_assert(len < VG_MAX_SEGNAMELEN);
172 segnames[i].fname[len] = 0;
173 return i;
174}
175
sewardj548be6d2005-02-16 01:31:37 +0000176
177/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
178 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000179 seg.
180*/
sewardj548be6d2005-02-16 01:31:37 +0000181static Int compare_addr_with_seg ( Addr a, Segment* seg )
182{
183 if (a < seg->addr)
184 return -1;
185 if (a >= seg->addr + seg->len)
186 return 1;
187 return 0;
188}
189
sewardj79048ce2005-02-18 08:28:32 +0000190
sewardj548be6d2005-02-16 01:31:37 +0000191/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000192 none.
193*/
sewardj548be6d2005-02-16 01:31:37 +0000194static Int find_segment ( Addr a )
195{
196 Int i;
197 for (i = 0; i < segments_used; i++) {
198 if (compare_addr_with_seg(a, &segments[i]) == 0)
199 return i;
200 }
201 return -1;
202}
203
204
205/* Assumes that 'a' is not in any segment. Finds the index of the
206 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
207 which is in fact in a segment is a checked error.
208*/
209static Int find_segment_above_unmapped ( Addr a )
210{
211 Int i, r;
212 for (i = 0; i < segments_used; i++) {
213 r = compare_addr_with_seg(a, &segments[i]);
214 vg_assert(r != 0); /* 'a' should not be in any segment. */
215 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000216 continue;
sewardj548be6d2005-02-16 01:31:37 +0000217 vg_assert(r == -1);
218 break;
219 }
220
221 if (i == segments_used)
222 return -1; /* not found */
223 else
224 return i;
225}
226
227
228/* Assumes that 'a' is in some segment. Finds the next segment along,
229 or NULL if none. Passing 'a' which is in fact not in a segment is
230 a checked error.
231*/
232static Int find_segment_above_mapped ( Addr a )
233{
234 Int i, r;
235 for (i = 0; i < segments_used; i++) {
236 r = compare_addr_with_seg(a, &segments[i]);
237 if (r == 1)
238 continue; /* not yet there */
239 if (r == 0)
240 break; /* found it */
241 vg_assert(0);
242 /* we shouldn't get here -- r == -1 and so it means we went past
243 'a' without seeing it -- it is therefore unmapped. */
244 /*NOTREACHED*/
245 }
246
247 vg_assert(i < segments_used);
248 if (i == segments_used-1)
249 return -1; /* not found */
250 else
251 return i+1;
252}
253
254
255/* Shift segments[i .. segments_used-1] up by one. */
256static void make_space_at ( Int i )
257{
258 Int j;
259 vg_assert(i >= 0 && i <= segments_used);
260 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000261 if (segments_used+1 == VG_N_SEGMENTS) {
262 VG_(printf)(
263 "coregrind/vg_memory.c:\n"
264 " VG_N_SEGMENTS is too small: "
265 "increase it and rebuild Valgrind.\n"
266 );
267 VG_(printf)(
268 "coregrind/vg_memory.c:\n"
269 " giving up now.\n\n"
270 );
271 VG_(exit)(0);
272 }
sewardj548be6d2005-02-16 01:31:37 +0000273 vg_assert(segments_used+1 < VG_N_SEGMENTS);
274 for (j = segments_used; j > i; j--)
275 segments[j] = segments[j-1];
276 segments_used++;
277}
278
sewardj79048ce2005-02-18 08:28:32 +0000279
sewardj548be6d2005-02-16 01:31:37 +0000280/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000281 segments_used.
282*/
sewardj548be6d2005-02-16 01:31:37 +0000283static void delete_segment_at ( Int i )
284{
285 Int j;
286 vg_assert(i >= 0 && i < segments_used);
287 for (j = i+1; j < segments_used; j++)
288 segments[j-1] = segments[j];
289 segments_used--;
290 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
291}
292
293
294/* Fill the i'th record all with zeroes. */
295static void zeroise_segment ( Int i )
296{
297 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000298 segments[i].prot = 0;
299 segments[i].flags = 0;
300 segments[i].addr = 0;
301 segments[i].len = 0;
302 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000303 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000304 segments[i].fnIdx = -1;
305 segments[i].dev = 0;
306 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000307 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000308}
309
sewardj79048ce2005-02-18 08:28:32 +0000310
sewardj548be6d2005-02-16 01:31:37 +0000311/* Create a segment to contain 'a', and return its index. Or -1 if
312 this failed because some other segment already contains 'a'. If
313 successful, fill in the segment's .addr field with 'a' but leave
314 all other fields alone.
315*/
316static Int create_segment ( Addr a )
317{
318 Int i, r;
319 for (i = 0; i < segments_used; i++) {
320 r = compare_addr_with_seg( a, &segments[i] );
321 if (r == 1)
322 continue; /* seg[i] precedes a */
323 if (r == 0)
324 return -1; /* seg[i] contains a. Give up */
325 vg_assert(r == -1);
326 break;
327 }
328 /* a precedes seg[i]. Shift segs at i and above up one, and use
329 this slot. */
330 make_space_at(i);
331 zeroise_segment(i);
332 segments[i].addr = a;
333 return i;
334}
335
sewardj79048ce2005-02-18 08:28:32 +0000336
337/* Print out the segment array (debugging only!). Note, this calls
338 VG_(printf), and I'm not 100% clear that that wouldn't require
339 dynamic memory allocation and hence more segments to be allocated.
340*/
341static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000342{
sewardj79048ce2005-02-18 08:28:32 +0000343 Int i;
344 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
345 who, segments_used, segnames_used);
346 for (i = 0; i < segnames_used; i++) {
347 if (!segnames[i].inUse)
348 continue;
349 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
350 }
351 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000352 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000353 "%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 +0000354 i,
sewardj79048ce2005-02-18 08:28:32 +0000355 segments[i].addr, segments[i].addr + segments[i].len,
356 (ULong)segments[i].len, segments[i].prot,
357 segments[i].flags, segments[i].dev, segments[i].ino,
358 (Long)segments[i].offset,
359 segments[i].fnIdx);
360 }
361 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000362}
sewardj79048ce2005-02-18 08:28:32 +0000363
sewardj548be6d2005-02-16 01:31:37 +0000364
365/* Find the segment containing 'a' and split it into two pieces at
366 'a'. Does nothing if no segment contains 'a', or if the split
367 would cause either of the pieces to have zero size.
368
369 If 'a' is not found, or if no splitting happens, -1 is returned.
370
371 If a value 'r' other than -1 is returned, this is the index of the
372 higher-addressed segment resulting from the split, and the index of
373 the lower-addressed segment is r-1.
374*/
375static Int split_segment ( Addr a )
376{
377 Int r;
378 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000379 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000380 r = find_segment(a);
381 if (r == -1)
382 /* not found */
383 return -1;
384 if (segments[r].addr == a)
385 /* segment starts at 'a', so splitting it would create a
386 zero-sized segment */
387 return -1;
388
389 /* copy original; make adjustments. */
390 vg_assert(a > segments[r].addr);
391 delta = a - segments[r].addr;
392 make_space_at(r);
393 segments[r] = segments[r+1];
394 segments[r].len = delta;
395 segments[r+1].len -= delta;
396 segments[r+1].addr += delta;
397 segments[r+1].offset += delta;
398 return r+1;
399}
400
sewardj79048ce2005-02-18 08:28:32 +0000401
402/* Return true if two segments are adjacent and mergable (s1 is
403 assumed to have a lower ->addr than s2) */
404static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
405{
406 if (s1->addr+s1->len != s2->addr)
407 return False;
408
409 if (s1->flags != s2->flags)
410 return False;
411
412 if (s1->prot != s2->prot)
413 return False;
414
njn36ef6ba2005-05-14 18:42:26 +0000415 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000416 return False;
417
418 if (s1->flags & SF_FILE){
419 if ((s1->offset + s1->len) != s2->offset)
420 return False;
421 if (s1->dev != s2->dev)
422 return False;
423 if (s1->ino != s2->ino)
424 return False;
425 if (s1->fnIdx != s2->fnIdx)
426 return False;
427 }
428
429 return True;
430}
431
432
433/* Clean up and sanity check the segment array:
434 - check segments are in ascending order
435 - check segments do not overlap
436 - check no segment has zero size
437 - merge adjacent where possible
438 - perform checks on the filename table, and reclaim dead entries
439*/
440static void preen_segments ( void )
441{
442 Int i, j, rd, wr;
443 Segment *s, *s1;
444 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
445 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
446
447 if (0) show_segments("before preen");
448
449 /* clear string table mark bits */
450 for (i = 0; i < segnames_used; i++)
451 segnames[i].mark = False;
452
453 /* check for non-zero size, and set mark bits for any used strings */
454 for (i = 0; i < segments_used; i++) {
455 vg_assert(segments[i].len > 0);
456 j = segments[i].fnIdx;
457 vg_assert(j >= -1 && j < segnames_used);
458 if (j >= 0) {
459 vg_assert(segnames[j].inUse);
460 segnames[j].mark = True;
461 }
462 }
463
464 /* check ascendingness and non-overlap */
465 for (i = 0; i < segments_used-1; i++) {
466 s = &segments[i];
467 s1 = &segments[i+1];
468 vg_assert(s->addr < s1->addr);
469 vg_assert(s->addr + s->len <= s1->addr);
470 }
471
472 /* merge */
473 if (segments_used < 1)
474 return;
475
476 wr = 1;
477 for (rd = 1; rd < segments_used; rd++) {
478 s = &segments[wr-1];
479 s1 = &segments[rd];
480 if (segments_are_mergeable(s,s1)) {
481 if (0)
482 VG_(printf)("merge %p-%p with %p-%p\n",
483 s->addr, s->addr+s->len,
484 s1->addr, s1->addr+s1->len);
485 s->len += s1->len;
486 continue;
487 }
488 if (wr < rd)
489 segments[wr] = segments[rd];
490 wr++;
491 }
492 vg_assert(wr >= 0 && wr <= segments_used);
493 segments_used = wr;
494
495 /* Free up any strings which are no longer referenced. */
496 for (i = 0; i < segnames_used; i++) {
497 if (segnames[i].mark == False) {
498 segnames[i].inUse = False;
499 segnames[i].fname[0] = 0;
500 }
501 }
502
503 if (0) show_segments("after preen");
504}
505
506
sewardj548be6d2005-02-16 01:31:37 +0000507/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000508/*--- Maintain an ordered list of all the client's mappings ---*/
509/*--------------------------------------------------------------*/
510
nethercote8991d5a2004-11-03 17:07:46 +0000511Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000512{
513 Addr se = s->addr+s->len;
514 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000515 vg_assert(pe >= p);
516
517 return (p >= s->addr && pe <= se);
518}
519
nethercote8991d5a2004-11-03 17:07:46 +0000520Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000521{
522 Addr se = s->addr+s->len;
523 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000524 vg_assert(pe >= p);
525
526 return (p < se && pe > s->addr);
527}
528
sewardj1024cf72005-02-28 14:39:21 +0000529#if 0
530/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000531/* Prepare a Segment structure for recycling by freeing everything
532 hanging off it. */
533static void recycleseg(Segment *s)
534{
535 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000536 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000537
538 if (s->filename != NULL)
539 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
540
541 /* keep the SegInfo, if any - it probably still applies */
542}
543
544/* When freeing a Segment, also clean up every one else's ideas of
545 what was going on in that range of memory */
546static void freeseg(Segment *s)
547{
548 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000549 if (s->seginfo != NULL) {
550 VG_(seginfo_decref)(s->seginfo, s->addr);
551 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000552 }
553
554 VG_(SkipNode_Free)(&sk_segments, s);
555}
sewardj1024cf72005-02-28 14:39:21 +0000556#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000557
sewardj1024cf72005-02-28 14:39:21 +0000558
559/* Get rid of any translations arising from s. */
560/* Note, this is not really the job of the low level memory manager.
561 When it comes time to rewrite this subsystem, clean this up. */
562static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000563{
sewardj1024cf72005-02-28 14:39:21 +0000564 if (s->flags & SF_CODE) {
565 VG_(discard_translations)(s->addr, s->len);
566 if (0)
567 VG_(printf)("dumping translations in %p .. %p\n",
568 s->addr, s->addr+s->len);
569 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000570}
571
sewardj1024cf72005-02-28 14:39:21 +0000572
fitzhardinge98abfc72003-12-16 02:05:15 +0000573/* This unmaps all the segments in the range [addr, addr+len); any
574 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000575void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000576{
fitzhardingee3632c62003-12-22 10:58:06 +0000577 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000578 Segment* s;
579 Addr end, s_end;
580 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000581 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000582
583 if (len == 0)
584 return;
585
fitzhardinge1a4adf02003-12-22 10:42:59 +0000586 len = PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000587
fitzhardinge98abfc72003-12-16 02:05:15 +0000588 if (debug)
tom9be7c982005-04-25 16:55:44 +0000589 VG_(printf)("unmap_range(%p, %lu)\n", addr, len);
sewardj79048ce2005-02-18 08:28:32 +0000590 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000591 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000592
593 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000594 vg_assert(VG_IS_PAGE_ALIGNED(addr));
595 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000596
sewardj548be6d2005-02-16 01:31:37 +0000597 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000598
599 /* do not delete .. even though it looks stupid */
600 vg_assert(i >= 0);
601
602 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000603 s = &segments[i];
604 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000605
sewardj548be6d2005-02-16 01:31:37 +0000606 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000607 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000608 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000609
fitzhardinge1a303042003-12-22 08:48:50 +0000610 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000611 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000612 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000613 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000614 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000615
616 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000617 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000618 addr < s_end &&
619 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000620 /* this segment's tail is truncated by [addr, addr+len)
621 -> truncate tail
622 */
sewardj1024cf72005-02-28 14:39:21 +0000623 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000624 s->len = addr - s->addr;
625
626 if (debug)
tom9be7c982005-04-25 16:55:44 +0000627 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000628 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000629 /* this segment's head is truncated by [addr, addr+len)
630 -> truncate head
631 */
sewardj548be6d2005-02-16 01:31:37 +0000632 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000633
634 if (debug)
tom9be7c982005-04-25 16:55:44 +0000635 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000636 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000637
sewardj1024cf72005-02-28 14:39:21 +0000638 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000639 s->addr += delta;
640 s->offset += delta;
641 s->len -= delta;
642
643 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000644 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000645 /* this segment is completely contained within [addr, addr+len)
646 -> delete segment
647 */
sewardj1024cf72005-02-28 14:39:21 +0000648 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000649 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000650 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000651
652 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000653 VG_(printf)(" case 3: seg %d deleted\n", i);
654 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000655 /* [addr, addr+len) is contained within a single segment
656 -> split segment into 3, delete middle portion
657 */
sewardj1024cf72005-02-28 14:39:21 +0000658 Int i_middle;
659 dump_translations_from(s);
660 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000661 vg_assert(i_middle != -1);
662 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000663 vg_assert(segments[i_middle].addr == addr);
664 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000665 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000666
667 if (debug)
668 VG_(printf)(" case 4: subrange %p-%p deleted\n",
669 addr, addr+len);
670 }
sewardj47c98a72005-03-12 20:36:15 +0000671
672 /* If we deleted this segment (or any above), those above will
673 have been moved down to fill in the hole in the segment
674 array. In order that we don't miss them, we have to
675 re-consider this slot number; hence the i--. */
676 if (deleted)
677 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000678 }
sewardj79048ce2005-02-18 08:28:32 +0000679 preen_segments();
680 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000681}
682
sewardj548be6d2005-02-16 01:31:37 +0000683
684/* Add a binding of [addr,addr+len) to
685 (prot,flags,dev,ino,off,filename) in the segment array.
686 Delete/truncate any previous mapping(s) covering that range.
687*/
688void
689VG_(map_file_segment)( Addr addr, SizeT len,
690 UInt prot, UInt flags,
691 UInt dev, UInt ino, ULong off,
692 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000693{
fitzhardinge98abfc72003-12-16 02:05:15 +0000694 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000695 Segment* s;
696 Int idx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000697
698 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000699 VG_(printf)(
700 "\n"
tom9be7c982005-04-25 16:55:44 +0000701 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000702 " dev=0x%4x ino=%d off=%ld\n"
703 " filename='%s')\n",
704 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000705
706 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000707 vg_assert(VG_IS_PAGE_ALIGNED(addr));
fitzhardinge98abfc72003-12-16 02:05:15 +0000708 len = PGROUNDUP(len);
709
sewardj548be6d2005-02-16 01:31:37 +0000710 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
711 VG_(unmap_range)(addr, len);
712
713 /* and now install this one */
714 idx = create_segment(addr);
715 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
716 vg_assert(idx != -1);
717 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000718
sewardj79048ce2005-02-18 08:28:32 +0000719 s = &segments[idx];
720 vg_assert(s->addr == addr);
721 s->prot = prot;
722 s->flags = flags;
723 s->len = len;
724 s->offset = off;
725 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
726 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
727 s->dev = dev;
728 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000729 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000730
sewardj79048ce2005-02-18 08:28:32 +0000731 /* Clean up right now */
732 preen_segments();
733 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000734
735 /* If this mapping is of the beginning of a file, isn't part of
736 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000737 file, then try reading symbols from it.
738 */
njn36ef6ba2005-05-14 18:42:26 +0000739 if (s->seginfo == NULL
sewardjb71816c2005-03-14 19:11:10 +0000740 && (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
sewardj79048ce2005-02-18 08:28:32 +0000741 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
742 if (off == 0
743 && s->fnIdx != -1
744 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
745 && len >= VKI_PAGE_SIZE
746 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000747 s->seginfo = VG_(read_seg_symbols)(s);
748 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000749 s->flags |= SF_DYNLIB;
750 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000751 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000752#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000753 const SegInfo *info;
754
njn36ef6ba2005-05-14 18:42:26 +0000755 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000756 for(info = VG_(next_seginfo)(NULL);
757 info != NULL;
758 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000759 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
760 {
njn36ef6ba2005-05-14 18:42:26 +0000761 s->seginfo = (SegInfo *)info;
762 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000763 }
764 }
sewardj79048ce2005-02-18 08:28:32 +0000765#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000766 }
767 }
768
769 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000770 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000771}
772
nethercote8b5f40c2004-11-02 13:29:50 +0000773void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000774 Int fd, ULong off, const Char *filename)
775{
776 struct vki_stat st;
777 Char *name = NULL;
778
779 st.st_dev = 0;
780 st.st_ino = 0;
781
782 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000783 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000784
785 if (VG_(fstat)(fd, &st) < 0)
786 flags &= ~SF_FILE;
787 }
788
sewardj79048ce2005-02-18 08:28:32 +0000789 if ((flags & SF_FILE) && filename == NULL && fd != -1)
790 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000791
792 if (filename == NULL)
793 filename = name;
794
sewardj79048ce2005-02-18 08:28:32 +0000795 VG_(map_file_segment)(addr, len, prot, flags,
796 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000797}
798
nethercote8b5f40c2004-11-02 13:29:50 +0000799void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000800{
801 flags &= ~SF_FILE;
802
803 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
804}
805
806/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000807void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000808{
sewardj79048ce2005-02-18 08:28:32 +0000809 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000810 static const Bool debug = False || mem_debug;
811
812 if (debug)
tom9be7c982005-04-25 16:55:44 +0000813 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000814
815 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000816
817 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000818 vg_assert(VG_IS_PAGE_ALIGNED(a));
fitzhardinge92360792003-12-24 10:11:11 +0000819 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000820
sewardj79048ce2005-02-18 08:28:32 +0000821 split_segment(a);
822 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000823
sewardj548be6d2005-02-16 01:31:37 +0000824 r = find_segment(a);
825 vg_assert(r != -1);
826 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000827
828 preen_segments();
829
sewardje517b802005-02-16 01:58:51 +0000830 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000831}
832
sewardj79048ce2005-02-18 08:28:32 +0000833
sewardj548be6d2005-02-16 01:31:37 +0000834/* Try to find a map space for [addr,addr+len). If addr==0, it means
835 the caller is prepared to accept a space at any location; if not,
836 we will try for addr, but fail if we can't get it. This mimics
837 mmap fixed vs mmap not-fixed.
838*/
nethercote8b5f40c2004-11-02 13:29:50 +0000839Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000840{
fitzhardingee3632c62003-12-22 10:58:06 +0000841 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000842 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000843 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000844 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
845 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000846 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
847 Int i, i_any, i_fixed, i_final;
848 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000849
sewardj548be6d2005-02-16 01:31:37 +0000850 Bool fixed;
851
sewardje517b802005-02-16 01:58:51 +0000852 if (debug) {
853 VG_(printf)("\n\n");
tom9be7c982005-04-25 16:55:44 +0000854 VG_(printf)("find_map_space(%p, %lu, %d) ...\n",
sewardje517b802005-02-16 01:58:51 +0000855 addr, len, for_client);
856 }
857
858 if (0) show_segments("find_map_space: start");
859
sewardj548be6d2005-02-16 01:31:37 +0000860 if (addr == 0) {
861 fixed = False;
862 } else {
863 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000864 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000865 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000866 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000867 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000868
869 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000870 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000871 len = PGROUNDUP(len);
872
nethercote73b526f2004-10-31 18:48:21 +0000873 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000874
sewardj548be6d2005-02-16 01:31:37 +0000875 /* Scan the segment list, looking for a hole which satisfies the
876 requirements. At each point i we ask the question "can we use
877 the hole in between segments[i-1] and segments[i] ?" */
878 i_any = i_fixed = -1;
879 hstart_any = hstart_fixed = 0;
880
881 hole_start = hole_end = 0;
882
883 /* Iterate over all possible holes, generating them into
884 hole_start/hole_end. Filter out invalid ones. Then see if any
885 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
886 */
887 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
888 if (i == 0) {
889 hole_start = 0;
890 hole_end = segments[0].addr-1;
891 }
892 else {
893 vg_assert(segments_used > 0);
894 if (i == segments_used) {
895 hole_start = segments[i-1].addr + segments[i-1].len;
896 hole_end = ~(Addr)0;
897 } else {
898 hole_start = segments[i-1].addr + segments[i-1].len;
899 hole_end = segments[i].addr - 1;
900 }
901 }
902
903 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
904
905 /* ignore zero-sized holes */
906 if (hole_start == hole_end+1)
907 continue;
908
njnbe91aae2005-03-27 01:42:41 +0000909 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
910 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000911
912 /* ignore holes which fall outside the allowable area */
913 if (!(hole_start >= base && hole_end <= limit))
914 continue;
915
916 vg_assert(hole_end > hole_start);
917 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000918 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000919
920 if (hole_len >= len && i_any == -1) {
921 /* It will at least fit in this hole. */
922 i_any = i;
923 hstart_any = hole_start;
924 }
925
sewardjb5f6f512005-03-10 23:59:00 +0000926 if (fixed && hole_start <= addr
927 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000928 /* We were asked for a fixed mapping, and this hole works.
929 Bag it -- and stop searching as further searching is
930 pointless. */
931 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000932 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000933 break;
934 }
935 }
936
937 /* Summarise the final decision into i_final/hstart_final. */
938 i_final = -1;
939 hstart_final = 0;
940
941 if (fixed) {
942 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000943 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000944 } else {
945 i_final = i_any;
946 hstart_final = hstart_any;
947 }
948
949
950 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000951 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000952 else
953 ret = 0; /* not found */
954
955 if (debug)
tom9be7c982005-04-25 16:55:44 +0000956 VG_(printf)("find_map_space(%p, %lu, %d) -> %p\n\n",
sewardj548be6d2005-02-16 01:31:37 +0000957 addr, len, for_client, ret);
958
sewardjb5f6f512005-03-10 23:59:00 +0000959 if (fixed) {
960 vg_assert(ret == 0 || ret == addrOrig);
961 }
962
sewardj548be6d2005-02-16 01:31:37 +0000963 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000964}
965
sewardj79048ce2005-02-18 08:28:32 +0000966
sewardjb5f6f512005-03-10 23:59:00 +0000967/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000968 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000969 mapping over any part of the address space which is not covered
970 by an entry in the segment list.
971
972 This is designed for use around system calls which allocate
973 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000974 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000975 address with VG_(find_map_space) and then adding a segment for
976 it and padding the address space valgrind can ensure that the
977 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000978void VG_(pad_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;
njn7df470b2005-05-29 18:46:38 +0000981 void* ret;
sewardj394790d2005-03-17 02:14:44 +0000982
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) {
njn7df470b2005-05-29 18:46:38 +0000988 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +0000989 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
990 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000991 }
thughes9aaebc32004-07-15 23:13:37 +0000992 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +0000993 i++;
994 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000995 }
996
nethercote820bd8c2004-09-07 23:04:49 +0000997 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +0000998 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +0000999 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1000 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001001 }
thughes9aaebc32004-07-15 23:13:37 +00001002}
1003
thughesc70b8c62004-07-16 23:07:58 +00001004/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001005 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001006void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001007{
sewardj394790d2005-03-17 02:14:44 +00001008 Addr addr = (start == 0) ? VG_(client_base) : start;
1009 Int ret;
1010
1011 Int i = 0;
1012 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001013
nethercote820bd8c2004-09-07 23:04:49 +00001014 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001015 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +00001016 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001017 }
thughes9aaebc32004-07-15 23:13:37 +00001018 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001019 i++;
1020 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001021 }
1022
nethercote820bd8c2004-09-07 23:04:49 +00001023 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001024 ret = VG_(do_syscall2)(__NR_munmap, addr,
1025 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001026 }
thughes9aaebc32004-07-15 23:13:37 +00001027}
1028
sewardj548be6d2005-02-16 01:31:37 +00001029/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001030Segment *VG_(find_segment)(Addr a)
1031{
sewardj548be6d2005-02-16 01:31:37 +00001032 Int r = find_segment(a);
1033 if (0) show_segments("find_segment");
1034 if (r == -1) return NULL;
1035 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001036}
1037
sewardj548be6d2005-02-16 01:31:37 +00001038/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1039 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1040 a segment is a checked error.
1041*/
1042Segment *VG_(find_segment_above_unmapped)(Addr a)
1043{
1044 Int r = find_segment_above_unmapped(a);
1045 if (0) show_segments("find_segment_above_unmapped");
1046 if (r == -1) return NULL;
1047 return &segments[r];
1048}
1049
1050/* Assumes that 'a' is in some segment. Finds the next segment along,
1051 or NULL if none. Passing 'a' which is in fact not in a segment is
1052 a checked error.
1053*/
1054Segment *VG_(find_segment_above_mapped)(Addr a)
1055{
1056 Int r = find_segment_above_mapped(a);
1057 if (0) show_segments("find_segment_above_mapped");
1058 if (r == -1) return NULL;
1059 return &segments[r];
1060}
1061
1062
sewardjde4a1d02002-03-22 01:27:54 +00001063/*------------------------------------------------------------*/
1064/*--- Tracking permissions around %esp changes. ---*/
1065/*------------------------------------------------------------*/
1066
1067/*
1068 The stack
1069 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001070 The stack's segment seems to be dynamically extended downwards by
1071 the kernel as the stack pointer moves down. Initially, a 1-page
1072 (4k) stack is allocated. When SP moves below that for the first
1073 time, presumably a page fault occurs. The kernel detects that the
njna60a7c12005-05-08 17:49:37 +00001074 faulting address is in the range from SP - VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001075 upwards to the current valid stack. It then extends the stack
1076 segment downwards for enough to cover the faulting address, and
1077 resumes the process (invisibly). The process is unaware of any of
1078 this.
sewardjde4a1d02002-03-22 01:27:54 +00001079
sewardjfa8202f2005-04-24 11:05:55 +00001080 That means that Valgrind can't spot when the stack segment is being
1081 extended. Fortunately, we want to precisely and continuously
1082 update stack permissions around SP, so we need to spot all writes
1083 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001084
sewardjfa8202f2005-04-24 11:05:55 +00001085 The deal is: when SP is assigned a lower value, the stack is being
1086 extended. Create suitably-permissioned pages to fill in any holes
1087 between the old stack ptr and this one, if necessary. Then mark
1088 all bytes in the area just "uncovered" by this SP change as
1089 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001090
sewardjfa8202f2005-04-24 11:05:55 +00001091 When SP goes back up, mark the area receded over as unreadable and
1092 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001093
njna60a7c12005-05-08 17:49:37 +00001094 Just to record the SP boundary conditions somewhere convenient:
1095 SP - VGA_STACK_REDZONE_SZB always points to the lowest live byte in
1096 the stack. All addresses below SP - VGA_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001097 live; those at and above it are.
1098
njna60a7c12005-05-08 17:49:37 +00001099 We do not concern ourselves here with the VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001100 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001101*/
1102
njn9b007f62003-04-07 14:40:25 +00001103/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001104 tracked by the tool, and one of the specialised cases
1105 (eg. new_mem_stack_4) isn't used in preference.
1106*/
njn9fb73db2005-03-27 01:55:21 +00001107VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001108void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001109{
sewardj97724e52005-04-02 23:40:59 +00001110 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001111 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001112
sewardj97724e52005-04-02 23:40:59 +00001113 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1114 /* SP has changed by more than some threshold amount (by
1115 default, 2MB). We take this to mean that the application is
1116 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001117
1118 JRS 20021001: following discussions with John Regehr, if a stack
1119 switch happens, it seems best not to mess at all with memory
1120 permissions. Seems to work well with Netscape 4.X. Really the
1121 only remaining difficulty is knowing exactly when a stack switch is
1122 happening. */
sewardj97724e52005-04-02 23:40:59 +00001123 if (VG_(clo_verbosity) > 0 && moans > 0) {
1124 moans--;
1125 VG_(message)(Vg_UserMsg,
1126 "Warning: client switching stacks? "
1127 "SP change: %p --> %p", old_SP, new_SP);
1128 VG_(message)(Vg_UserMsg,
1129 " to suppress, use: --max-stackframe=%d or greater",
1130 (delta < 0 ? -delta : delta));
1131 if (moans == 0)
1132 VG_(message)(Vg_UserMsg,
1133 " further instances of this message "
1134 "will not be shown.");
1135 }
njn9b007f62003-04-07 14:40:25 +00001136 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001137 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001138
njn9b007f62003-04-07 14:40:25 +00001139 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001140 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001141 }
1142}
1143
jsgf855d93d2003-10-13 22:26:55 +00001144/*
sewardjb5f6f512005-03-10 23:59:00 +00001145 Test if a piece of memory is addressable with at least the "prot"
1146 protection permissions by examining the underlying segments.
1147
1148 Really this is a very stupid algorithm and we could do much
1149 better by iterating through the segment array instead of through
1150 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001151 */
sewardjb5f6f512005-03-10 23:59:00 +00001152Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001153{
sewardjb5f6f512005-03-10 23:59:00 +00001154 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001155
sewardjb5f6f512005-03-10 23:59:00 +00001156 if ((p + size) < p)
1157 return False; /* reject wraparounds */
1158 if (size == 0)
1159 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001160
sewardjb5f6f512005-03-10 23:59:00 +00001161 p = PGROUNDDN(p);
1162 size = PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001163 vg_assert(VG_IS_PAGE_ALIGNED(p));
1164 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001165
sewardjb5f6f512005-03-10 23:59:00 +00001166 for (; size > 0; size -= VKI_PAGE_SIZE) {
1167 seg = VG_(find_segment)(p);
1168 if (!seg)
1169 return False;
1170 if ((seg->prot & prot) != prot)
1171 return False;
1172 p += VKI_PAGE_SIZE;
1173 }
jsgf855d93d2003-10-13 22:26:55 +00001174
sewardjb5f6f512005-03-10 23:59:00 +00001175 return True;
jsgf855d93d2003-10-13 22:26:55 +00001176}
1177
sewardjb5f6f512005-03-10 23:59:00 +00001178
sewardjde4a1d02002-03-22 01:27:54 +00001179/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001180/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001181/*--------------------------------------------------------------------*/
1182
nethercote57e36b32004-07-10 14:56:28 +00001183// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001184Addr VG_(get_memory_from_mmap_for_client)
1185 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001186{
1187 len = PGROUNDUP(len);
1188
njnca82cc02004-11-22 17:18:48 +00001189 tl_assert(!(sf_flags & SF_FIXED));
1190 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001191
nethercote8e9eab02004-07-11 18:01:06 +00001192 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1193 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1194 sf_flags | SF_CORE, -1, 0);
1195 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001196 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001197 else
1198 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001199}
1200
fitzhardinge98abfc72003-12-16 02:05:15 +00001201
njn86f12dc2005-03-14 01:16:05 +00001202/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001203 range, which isn't SF_CORE, a root.
1204*/
njn86f12dc2005-03-14 01:16:05 +00001205void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1206{
sewardj882af5f2005-03-16 12:27:53 +00001207 Int i;
1208 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001209 Segment *s;
1210
sewardj882af5f2005-03-16 12:27:53 +00001211 for (i = 0; i < segments_used; i++) {
1212 s = &segments[i];
1213 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1214 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001215 if (flags != SF_MMAP && flags != SF_STACK)
1216 continue;
sewardj882af5f2005-03-16 12:27:53 +00001217 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1218 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001219 continue;
1220 if (!VG_(is_client_addr)(s->addr) ||
1221 !VG_(is_client_addr)(s->addr+s->len))
1222 continue;
1223
1224 (*add_rootrange)(s->addr, s->len);
1225 }
njn86f12dc2005-03-14 01:16:05 +00001226}
1227
1228
nethercote88a90162004-07-10 16:59:25 +00001229/*--------------------------------------------------------------------*/
1230/*--- Querying memory layout ---*/
1231/*--------------------------------------------------------------------*/
1232
fitzhardinge98abfc72003-12-16 02:05:15 +00001233Bool VG_(is_client_addr)(Addr a)
1234{
1235 return a >= VG_(client_base) && a < VG_(client_end);
1236}
1237
1238Bool VG_(is_shadow_addr)(Addr a)
1239{
1240 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1241}
1242
fitzhardinge98abfc72003-12-16 02:05:15 +00001243Addr VG_(get_shadow_size)(void)
1244{
1245 return VG_(shadow_end)-VG_(shadow_base);
1246}
1247
sewardjfa8202f2005-04-24 11:05:55 +00001248
nethercote88a90162004-07-10 16:59:25 +00001249/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001250/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001251/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001252
1253void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1254{
sewardj548be6d2005-02-16 01:31:37 +00001255vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001256 if (0)
1257 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1258
1259 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001260 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001261
1262 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
1263 p = PGROUNDDN(p);
1264
1265 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1266
1267 if (call_init)
1268 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001269 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +00001270 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
1271
nethercote73b526f2004-10-31 18:48:21 +00001272 p += VKI_PAGE_SIZE;
1273 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001274 }
1275}
1276
1277void *VG_(shadow_alloc)(UInt size)
1278{
1279 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001280 Addr try_here;
1281 Int r;
1282
1283 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001284
1285 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001286 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001287
1288 size = PGROUNDUP(size);
1289
1290 if (shadow_alloc == 0)
1291 shadow_alloc = VG_(shadow_base);
1292
1293 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001294 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001295
sewardj79048ce2005-02-18 08:28:32 +00001296 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001297 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1298 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001299 vg_assert(size > 0);
1300
1301 if (0)
1302 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1303
1304 /* this is big-bang allocated, so we don't expect to find a listed
1305 segment for it. */
1306 /* This is really an absolute disgrace. Sometimes the big-bang
1307 mapping is in the list (due to re-reads of /proc/self/maps,
1308 presumably) and sometimes it isn't. */
1309#if 0
1310 r = find_segment(try_here);
1311 vg_assert(r == -1);
1312 r = find_segment(try_here+size-1);
1313 vg_assert(r == -1);
1314#endif
1315
1316 r = VG_(mprotect_native)( (void*)try_here,
1317 size, VKI_PROT_READ|VKI_PROT_WRITE );
1318
1319 if (r != 0)
1320 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001321
1322 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001323 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001324
sewardj79048ce2005-02-18 08:28:32 +00001325 failed:
1326 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001327 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001328 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001329 size
sewardj79048ce2005-02-18 08:28:32 +00001330 );
1331 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001332}
1333
njne3f06352005-06-01 03:48:33 +00001334/*------------------------------------------------------------*/
1335/*--- pointercheck ---*/
1336/*------------------------------------------------------------*/
1337
1338Bool VGA_(setup_pointercheck)(Addr client_base, Addr client_end)
1339{
1340 vg_assert(0 != client_end);
1341#if defined(VGP_x86_linux)
1342 /* Client address space segment limit descriptor entry */
1343 #define POINTERCHECK_SEGIDX 1
1344
1345 vki_modify_ldt_t ldt = {
1346 POINTERCHECK_SEGIDX, // entry_number
1347 client_base, // base_addr
1348 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1349 1, // seg_32bit
1350 0, // contents: data, RW, non-expanding
1351 0, // ! read_exec_only
1352 1, // limit_in_pages
1353 0, // ! seg not present
1354 1, // useable
1355 };
1356 int ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1357 if (ret < 0) {
1358 VG_(message)(Vg_UserMsg,
1359 "Warning: ignoring --pointercheck=yes, "
1360 "because modify_ldt failed (errno=%d)", -ret);
1361 return False;
1362 } else {
1363 return True;
1364 }
1365#elif defined(VGP_amd64_linux)
1366 if (0)
1367 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1368 return True;
1369#else
1370# error Unknown architecture
1371#endif
1372}
1373
fitzhardinge98abfc72003-12-16 02:05:15 +00001374/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001375/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001376/*--------------------------------------------------------------------*/