blob: 343a4cb91ef5c7cba78d23805d2f3738f58c1626 [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"
njn132bfcc2005-06-04 19:16:06 +000036#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000037#include "pub_core_libcfile.h" // For VG_(fstat)()
njn36a20fa2005-06-03 03:08:39 +000038#include "pub_core_libcprint.h"
njn20242342005-05-16 23:31:24 +000039#include "pub_core_options.h"
njn2521d322005-05-08 14:45:13 +000040#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000041#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000042#include "pub_core_transtab.h"
njn3c660b62005-05-13 22:18:47 +000043#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000044
sewardjde4a1d02002-03-22 01:27:54 +000045
sewardja4495682002-10-21 07:29:59 +000046/* Define to debug the memory-leak-detector. */
47/* #define VG_DEBUG_LEAKCHECK */
48
sewardje517b802005-02-16 01:58:51 +000049static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000050
51/*--------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +000052/*--- Basic globals about the address space. ---*/
53/*--------------------------------------------------------------*/
54
55/* Client address space, lowest to highest (see top of ume.c) */
56Addr VG_(client_base); /* client address space limits */
57Addr VG_(client_end);
58Addr VG_(client_mapbase);
59Addr VG_(client_trampoline_code);
60Addr VG_(clstk_base);
61Addr VG_(clstk_end);
rjwalsh0140af52005-06-04 20:42:33 +000062UWord VG_(clstk_id);
njn04e16982005-05-31 00:23:43 +000063
64Addr VG_(brk_base); /* start of brk */
65Addr VG_(brk_limit); /* current brk */
66
67Addr VG_(shadow_base); /* tool's shadow memory */
68Addr VG_(shadow_end);
69
70Addr VG_(valgrind_base); /* valgrind's address range */
71
72// Note that VG_(valgrind_last) names the last byte of the section, whereas
73// the VG_(*_end) vars name the byte one past the end of the section.
74Addr VG_(valgrind_last);
75
76/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000077/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000078/*--------------------------------------------------------------*/
79
sewardj79048ce2005-02-18 08:28:32 +000080/* Max number of segments we can track. */
81#define VG_N_SEGMENTS 1000
82
83/* Max number of segment file names we can track. */
84#define VG_N_SEGNAMES 200
85
86/* Max length of a segment file name. */
87#define VG_MAX_SEGNAMELEN 1000
88
89
90/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000091
92/* Array [0 .. segments_used-1] of all mappings. */
93/* Sorted by .addr field. */
94/* I: len may not be zero. */
95/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000096/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000097
98static Segment segments[VG_N_SEGMENTS];
99static Int segments_used = 0;
100
sewardj79048ce2005-02-18 08:28:32 +0000101typedef
102 struct {
103 Bool inUse;
104 Bool mark;
105 HChar fname[VG_MAX_SEGNAMELEN];
106 }
107 SegName;
108
109/* Filename table. _used is the high water mark; an entry is only
110 valid if its index >= 0, < _used, and its .inUse field == True.
111 The .mark field is used to garbage-collect dead entries.
112*/
113static SegName segnames[VG_N_SEGNAMES];
114static Int segnames_used = 0;
115
116
117/* ------ end of STATE for the address-space manager ------ */
118
119
120/* Searches the filename table to find an index for the given name.
121 If none is found, an index is allocated and the name stored. If no
122 space is available we just give up. If the string is too long to
123 store, return -1.
124*/
125static Int allocate_segname ( const HChar* name )
126{
127 Int i, j, len;
128
129 vg_assert(name);
130
131 if (0) VG_(printf)("alloc_segname %s\n", name);
132
133 len = VG_(strlen)(name);
134 if (len >= VG_MAX_SEGNAMELEN-1) {
135 return -1;
136 }
137
138 /* first see if we already have the name. */
139 for (i = 0; i < segnames_used; i++) {
140 if (!segnames[i].inUse)
141 continue;
142 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
143 return i;
144 }
145 }
146
147 /* no we don't. So look for a free slot. */
148 for (i = 0; i < segnames_used; i++)
149 if (!segnames[i].inUse)
150 break;
151
152 if (i == segnames_used) {
153 /* no free slots .. advance the high-water mark. */
154 if (segnames_used+1 < VG_N_SEGNAMES) {
155 i = segnames_used;
156 segnames_used++;
157 } else {
158 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000159 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000160 " VG_N_SEGNAMES is too small: "
161 "increase it and rebuild Valgrind.\n"
162 );
163 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000164 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000165 " giving up now.\n\n"
166 );
167 VG_(exit)(0);
168 }
169 }
170
171 /* copy it in */
172 segnames[i].inUse = True;
173 for (j = 0; j < len; j++)
174 segnames[i].fname[j] = name[j];
175 vg_assert(len < VG_MAX_SEGNAMELEN);
176 segnames[i].fname[len] = 0;
177 return i;
178}
179
sewardj548be6d2005-02-16 01:31:37 +0000180
181/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
182 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000183 seg.
184*/
sewardj548be6d2005-02-16 01:31:37 +0000185static Int compare_addr_with_seg ( Addr a, Segment* seg )
186{
187 if (a < seg->addr)
188 return -1;
189 if (a >= seg->addr + seg->len)
190 return 1;
191 return 0;
192}
193
sewardj79048ce2005-02-18 08:28:32 +0000194
sewardj548be6d2005-02-16 01:31:37 +0000195/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000196 none.
197*/
sewardj548be6d2005-02-16 01:31:37 +0000198static Int find_segment ( Addr a )
199{
200 Int i;
201 for (i = 0; i < segments_used; i++) {
202 if (compare_addr_with_seg(a, &segments[i]) == 0)
203 return i;
204 }
205 return -1;
206}
207
208
209/* Assumes that 'a' is not in any segment. Finds the index of the
210 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
211 which is in fact in a segment is a checked error.
212*/
213static Int find_segment_above_unmapped ( Addr a )
214{
215 Int i, r;
216 for (i = 0; i < segments_used; i++) {
217 r = compare_addr_with_seg(a, &segments[i]);
218 vg_assert(r != 0); /* 'a' should not be in any segment. */
219 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000220 continue;
sewardj548be6d2005-02-16 01:31:37 +0000221 vg_assert(r == -1);
222 break;
223 }
224
225 if (i == segments_used)
226 return -1; /* not found */
227 else
228 return i;
229}
230
231
232/* Assumes that 'a' is in some segment. Finds the next segment along,
233 or NULL if none. Passing 'a' which is in fact not in a segment is
234 a checked error.
235*/
236static Int find_segment_above_mapped ( Addr a )
237{
238 Int i, r;
239 for (i = 0; i < segments_used; i++) {
240 r = compare_addr_with_seg(a, &segments[i]);
241 if (r == 1)
242 continue; /* not yet there */
243 if (r == 0)
244 break; /* found it */
245 vg_assert(0);
246 /* we shouldn't get here -- r == -1 and so it means we went past
247 'a' without seeing it -- it is therefore unmapped. */
248 /*NOTREACHED*/
249 }
250
251 vg_assert(i < segments_used);
252 if (i == segments_used-1)
253 return -1; /* not found */
254 else
255 return i+1;
256}
257
258
259/* Shift segments[i .. segments_used-1] up by one. */
260static void make_space_at ( Int i )
261{
262 Int j;
263 vg_assert(i >= 0 && i <= segments_used);
264 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000265 if (segments_used+1 == VG_N_SEGMENTS) {
266 VG_(printf)(
267 "coregrind/vg_memory.c:\n"
268 " VG_N_SEGMENTS is too small: "
269 "increase it and rebuild Valgrind.\n"
270 );
271 VG_(printf)(
272 "coregrind/vg_memory.c:\n"
273 " giving up now.\n\n"
274 );
275 VG_(exit)(0);
276 }
sewardj548be6d2005-02-16 01:31:37 +0000277 vg_assert(segments_used+1 < VG_N_SEGMENTS);
278 for (j = segments_used; j > i; j--)
279 segments[j] = segments[j-1];
280 segments_used++;
281}
282
sewardj79048ce2005-02-18 08:28:32 +0000283
sewardj548be6d2005-02-16 01:31:37 +0000284/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000285 segments_used.
286*/
sewardj548be6d2005-02-16 01:31:37 +0000287static void delete_segment_at ( Int i )
288{
289 Int j;
290 vg_assert(i >= 0 && i < segments_used);
291 for (j = i+1; j < segments_used; j++)
292 segments[j-1] = segments[j];
293 segments_used--;
294 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
295}
296
297
298/* Fill the i'th record all with zeroes. */
299static void zeroise_segment ( Int i )
300{
301 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000302 segments[i].prot = 0;
303 segments[i].flags = 0;
304 segments[i].addr = 0;
305 segments[i].len = 0;
306 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000307 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000308 segments[i].fnIdx = -1;
309 segments[i].dev = 0;
310 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000311 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000312}
313
sewardj79048ce2005-02-18 08:28:32 +0000314
sewardj548be6d2005-02-16 01:31:37 +0000315/* Create a segment to contain 'a', and return its index. Or -1 if
316 this failed because some other segment already contains 'a'. If
317 successful, fill in the segment's .addr field with 'a' but leave
318 all other fields alone.
319*/
320static Int create_segment ( Addr a )
321{
322 Int i, r;
323 for (i = 0; i < segments_used; i++) {
324 r = compare_addr_with_seg( a, &segments[i] );
325 if (r == 1)
326 continue; /* seg[i] precedes a */
327 if (r == 0)
328 return -1; /* seg[i] contains a. Give up */
329 vg_assert(r == -1);
330 break;
331 }
332 /* a precedes seg[i]. Shift segs at i and above up one, and use
333 this slot. */
334 make_space_at(i);
335 zeroise_segment(i);
336 segments[i].addr = a;
337 return i;
338}
339
sewardj79048ce2005-02-18 08:28:32 +0000340
341/* Print out the segment array (debugging only!). Note, this calls
342 VG_(printf), and I'm not 100% clear that that wouldn't require
343 dynamic memory allocation and hence more segments to be allocated.
344*/
345static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000346{
sewardj79048ce2005-02-18 08:28:32 +0000347 Int i;
348 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
349 who, segments_used, segnames_used);
350 for (i = 0; i < segnames_used; i++) {
351 if (!segnames[i].inUse)
352 continue;
353 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
354 }
355 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000356 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000357 "%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 +0000358 i,
sewardj79048ce2005-02-18 08:28:32 +0000359 segments[i].addr, segments[i].addr + segments[i].len,
360 (ULong)segments[i].len, segments[i].prot,
361 segments[i].flags, segments[i].dev, segments[i].ino,
362 (Long)segments[i].offset,
363 segments[i].fnIdx);
364 }
365 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000366}
sewardj79048ce2005-02-18 08:28:32 +0000367
sewardj548be6d2005-02-16 01:31:37 +0000368
369/* Find the segment containing 'a' and split it into two pieces at
370 'a'. Does nothing if no segment contains 'a', or if the split
371 would cause either of the pieces to have zero size.
372
373 If 'a' is not found, or if no splitting happens, -1 is returned.
374
375 If a value 'r' other than -1 is returned, this is the index of the
376 higher-addressed segment resulting from the split, and the index of
377 the lower-addressed segment is r-1.
378*/
379static Int split_segment ( Addr a )
380{
381 Int r;
382 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000383 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000384 r = find_segment(a);
385 if (r == -1)
386 /* not found */
387 return -1;
388 if (segments[r].addr == a)
389 /* segment starts at 'a', so splitting it would create a
390 zero-sized segment */
391 return -1;
392
393 /* copy original; make adjustments. */
394 vg_assert(a > segments[r].addr);
395 delta = a - segments[r].addr;
396 make_space_at(r);
397 segments[r] = segments[r+1];
398 segments[r].len = delta;
399 segments[r+1].len -= delta;
400 segments[r+1].addr += delta;
401 segments[r+1].offset += delta;
402 return r+1;
403}
404
sewardj79048ce2005-02-18 08:28:32 +0000405
406/* Return true if two segments are adjacent and mergable (s1 is
407 assumed to have a lower ->addr than s2) */
408static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
409{
410 if (s1->addr+s1->len != s2->addr)
411 return False;
412
413 if (s1->flags != s2->flags)
414 return False;
415
416 if (s1->prot != s2->prot)
417 return False;
418
njn36ef6ba2005-05-14 18:42:26 +0000419 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000420 return False;
421
422 if (s1->flags & SF_FILE){
423 if ((s1->offset + s1->len) != s2->offset)
424 return False;
425 if (s1->dev != s2->dev)
426 return False;
427 if (s1->ino != s2->ino)
428 return False;
429 if (s1->fnIdx != s2->fnIdx)
430 return False;
431 }
432
433 return True;
434}
435
436
437/* Clean up and sanity check the segment array:
438 - check segments are in ascending order
439 - check segments do not overlap
440 - check no segment has zero size
441 - merge adjacent where possible
442 - perform checks on the filename table, and reclaim dead entries
443*/
444static void preen_segments ( void )
445{
446 Int i, j, rd, wr;
447 Segment *s, *s1;
448 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
449 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
450
451 if (0) show_segments("before preen");
452
453 /* clear string table mark bits */
454 for (i = 0; i < segnames_used; i++)
455 segnames[i].mark = False;
456
457 /* check for non-zero size, and set mark bits for any used strings */
458 for (i = 0; i < segments_used; i++) {
459 vg_assert(segments[i].len > 0);
460 j = segments[i].fnIdx;
461 vg_assert(j >= -1 && j < segnames_used);
462 if (j >= 0) {
463 vg_assert(segnames[j].inUse);
464 segnames[j].mark = True;
465 }
466 }
467
468 /* check ascendingness and non-overlap */
469 for (i = 0; i < segments_used-1; i++) {
470 s = &segments[i];
471 s1 = &segments[i+1];
472 vg_assert(s->addr < s1->addr);
473 vg_assert(s->addr + s->len <= s1->addr);
474 }
475
476 /* merge */
477 if (segments_used < 1)
478 return;
479
480 wr = 1;
481 for (rd = 1; rd < segments_used; rd++) {
482 s = &segments[wr-1];
483 s1 = &segments[rd];
484 if (segments_are_mergeable(s,s1)) {
485 if (0)
486 VG_(printf)("merge %p-%p with %p-%p\n",
487 s->addr, s->addr+s->len,
488 s1->addr, s1->addr+s1->len);
489 s->len += s1->len;
490 continue;
491 }
492 if (wr < rd)
493 segments[wr] = segments[rd];
494 wr++;
495 }
496 vg_assert(wr >= 0 && wr <= segments_used);
497 segments_used = wr;
498
499 /* Free up any strings which are no longer referenced. */
500 for (i = 0; i < segnames_used; i++) {
501 if (segnames[i].mark == False) {
502 segnames[i].inUse = False;
503 segnames[i].fname[0] = 0;
504 }
505 }
506
507 if (0) show_segments("after preen");
508}
509
510
sewardj548be6d2005-02-16 01:31:37 +0000511/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000512/*--- Maintain an ordered list of all the client's mappings ---*/
513/*--------------------------------------------------------------*/
514
nethercote8991d5a2004-11-03 17:07:46 +0000515Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000516{
517 Addr se = s->addr+s->len;
518 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000519 vg_assert(pe >= p);
520
521 return (p >= s->addr && pe <= se);
522}
523
nethercote8991d5a2004-11-03 17:07:46 +0000524Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000525{
526 Addr se = s->addr+s->len;
527 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000528 vg_assert(pe >= p);
529
530 return (p < se && pe > s->addr);
531}
532
sewardj1024cf72005-02-28 14:39:21 +0000533#if 0
534/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000535/* Prepare a Segment structure for recycling by freeing everything
536 hanging off it. */
537static void recycleseg(Segment *s)
538{
539 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000540 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000541
542 if (s->filename != NULL)
543 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
544
545 /* keep the SegInfo, if any - it probably still applies */
546}
547
548/* When freeing a Segment, also clean up every one else's ideas of
549 what was going on in that range of memory */
550static void freeseg(Segment *s)
551{
552 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000553 if (s->seginfo != NULL) {
554 VG_(seginfo_decref)(s->seginfo, s->addr);
555 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000556 }
557
558 VG_(SkipNode_Free)(&sk_segments, s);
559}
sewardj1024cf72005-02-28 14:39:21 +0000560#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000561
sewardj1024cf72005-02-28 14:39:21 +0000562
563/* Get rid of any translations arising from s. */
564/* Note, this is not really the job of the low level memory manager.
565 When it comes time to rewrite this subsystem, clean this up. */
566static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000567{
sewardj1024cf72005-02-28 14:39:21 +0000568 if (s->flags & SF_CODE) {
569 VG_(discard_translations)(s->addr, s->len);
570 if (0)
571 VG_(printf)("dumping translations in %p .. %p\n",
572 s->addr, s->addr+s->len);
573 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000574}
575
sewardj1024cf72005-02-28 14:39:21 +0000576
fitzhardinge98abfc72003-12-16 02:05:15 +0000577/* This unmaps all the segments in the range [addr, addr+len); any
578 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000579void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000580{
fitzhardingee3632c62003-12-22 10:58:06 +0000581 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000582 Segment* s;
583 Addr end, s_end;
584 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000585 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000586
587 if (len == 0)
588 return;
589
njn13bfd852005-06-02 03:52:53 +0000590 len = VG_PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000591
fitzhardinge98abfc72003-12-16 02:05:15 +0000592 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000593 VG_(printf)("unmap_range(%p, %llu)\n", addr, (ULong)len);
sewardj79048ce2005-02-18 08:28:32 +0000594 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000595 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000596
597 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000598 vg_assert(VG_IS_PAGE_ALIGNED(addr));
599 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000600
sewardj548be6d2005-02-16 01:31:37 +0000601 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000602
603 /* do not delete .. even though it looks stupid */
604 vg_assert(i >= 0);
605
606 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000607 s = &segments[i];
608 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000609
sewardj548be6d2005-02-16 01:31:37 +0000610 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000611 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000612 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000613
fitzhardinge1a303042003-12-22 08:48:50 +0000614 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000615 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000616 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000617 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000618 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000619
620 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000621 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000622 addr < s_end &&
623 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000624 /* this segment's tail is truncated by [addr, addr+len)
625 -> truncate tail
626 */
sewardj1024cf72005-02-28 14:39:21 +0000627 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000628 s->len = addr - s->addr;
629
630 if (debug)
tom9be7c982005-04-25 16:55:44 +0000631 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000632 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000633 /* this segment's head is truncated by [addr, addr+len)
634 -> truncate head
635 */
sewardj548be6d2005-02-16 01:31:37 +0000636 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000637
638 if (debug)
tom9be7c982005-04-25 16:55:44 +0000639 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000640 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000641
sewardj1024cf72005-02-28 14:39:21 +0000642 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000643 s->addr += delta;
644 s->offset += delta;
645 s->len -= delta;
646
647 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000648 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000649 /* this segment is completely contained within [addr, addr+len)
650 -> delete segment
651 */
sewardj1024cf72005-02-28 14:39:21 +0000652 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000653 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000654 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000655
656 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000657 VG_(printf)(" case 3: seg %d deleted\n", i);
658 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000659 /* [addr, addr+len) is contained within a single segment
660 -> split segment into 3, delete middle portion
661 */
sewardj1024cf72005-02-28 14:39:21 +0000662 Int i_middle;
663 dump_translations_from(s);
664 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000665 vg_assert(i_middle != -1);
666 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000667 vg_assert(segments[i_middle].addr == addr);
668 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000669 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000670
671 if (debug)
672 VG_(printf)(" case 4: subrange %p-%p deleted\n",
673 addr, addr+len);
674 }
sewardj47c98a72005-03-12 20:36:15 +0000675
676 /* If we deleted this segment (or any above), those above will
677 have been moved down to fill in the hole in the segment
678 array. In order that we don't miss them, we have to
679 re-consider this slot number; hence the i--. */
680 if (deleted)
681 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000682 }
sewardj79048ce2005-02-18 08:28:32 +0000683 preen_segments();
684 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000685}
686
sewardj548be6d2005-02-16 01:31:37 +0000687
688/* Add a binding of [addr,addr+len) to
689 (prot,flags,dev,ino,off,filename) in the segment array.
690 Delete/truncate any previous mapping(s) covering that range.
691*/
692void
693VG_(map_file_segment)( Addr addr, SizeT len,
694 UInt prot, UInt flags,
695 UInt dev, UInt ino, ULong off,
696 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000697{
fitzhardinge98abfc72003-12-16 02:05:15 +0000698 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000699 Segment* s;
700 Int idx;
sewardja8d8e232005-06-07 20:04:56 +0000701 HChar* stage2_suffix = "lib/valgrind/stage2";
702 Bool is_stage2 = VG_(strstr)(filename, stage2_suffix) != NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000703
704 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000705 VG_(printf)(
706 "\n"
tom9be7c982005-04-25 16:55:44 +0000707 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000708 " dev=0x%4x ino=%d off=%ld\n"
709 " filename='%s')\n",
710 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000711
sewardja8d8e232005-06-07 20:04:56 +0000712 if (0) show_segments("before map_file_segment");
713
fitzhardinge98abfc72003-12-16 02:05:15 +0000714 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000715 vg_assert(VG_IS_PAGE_ALIGNED(addr));
njn13bfd852005-06-02 03:52:53 +0000716 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000717
sewardj548be6d2005-02-16 01:31:37 +0000718 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
719 VG_(unmap_range)(addr, len);
720
721 /* and now install this one */
722 idx = create_segment(addr);
723 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
724 vg_assert(idx != -1);
725 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000726
sewardj79048ce2005-02-18 08:28:32 +0000727 s = &segments[idx];
728 vg_assert(s->addr == addr);
729 s->prot = prot;
730 s->flags = flags;
731 s->len = len;
732 s->offset = off;
733 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
734 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
735 s->dev = dev;
736 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000737 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000738
sewardj79048ce2005-02-18 08:28:32 +0000739 /* Clean up right now */
740 preen_segments();
741 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000742
743 /* If this mapping is of the beginning of a file, isn't part of
744 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000745 file, then try reading symbols from it.
746 */
njn36ef6ba2005-05-14 18:42:26 +0000747 if (s->seginfo == NULL
sewardja8d8e232005-06-07 20:04:56 +0000748 && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
749 || is_stage2
750 )
sewardj79048ce2005-02-18 08:28:32 +0000751 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
752 if (off == 0
753 && s->fnIdx != -1
754 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
755 && len >= VKI_PAGE_SIZE
756 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000757 s->seginfo = VG_(read_seg_symbols)(s);
758 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000759 s->flags |= SF_DYNLIB;
760 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000761 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000762#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000763 const SegInfo *info;
764
njn36ef6ba2005-05-14 18:42:26 +0000765 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000766 for(info = VG_(next_seginfo)(NULL);
767 info != NULL;
768 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000769 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
770 {
njn36ef6ba2005-05-14 18:42:26 +0000771 s->seginfo = (SegInfo *)info;
772 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000773 }
774 }
sewardj79048ce2005-02-18 08:28:32 +0000775#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000776 }
777 }
778
779 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000780 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000781}
782
nethercote8b5f40c2004-11-02 13:29:50 +0000783void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000784 Int fd, ULong off, const Char *filename)
785{
786 struct vki_stat st;
787 Char *name = NULL;
788
789 st.st_dev = 0;
790 st.st_ino = 0;
791
792 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000793 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000794
795 if (VG_(fstat)(fd, &st) < 0)
796 flags &= ~SF_FILE;
797 }
798
sewardj79048ce2005-02-18 08:28:32 +0000799 if ((flags & SF_FILE) && filename == NULL && fd != -1)
800 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000801
802 if (filename == NULL)
803 filename = name;
804
sewardj79048ce2005-02-18 08:28:32 +0000805 VG_(map_file_segment)(addr, len, prot, flags,
806 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000807}
808
nethercote8b5f40c2004-11-02 13:29:50 +0000809void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000810{
811 flags &= ~SF_FILE;
812
813 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
814}
815
816/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000817void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000818{
sewardj79048ce2005-02-18 08:28:32 +0000819 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000820 static const Bool debug = False || mem_debug;
821
822 if (debug)
tom9be7c982005-04-25 16:55:44 +0000823 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000824
825 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000826
827 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000828 vg_assert(VG_IS_PAGE_ALIGNED(a));
njn13bfd852005-06-02 03:52:53 +0000829 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000830
sewardj79048ce2005-02-18 08:28:32 +0000831 split_segment(a);
832 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000833
sewardj548be6d2005-02-16 01:31:37 +0000834 r = find_segment(a);
835 vg_assert(r != -1);
836 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000837
838 preen_segments();
839
sewardje517b802005-02-16 01:58:51 +0000840 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000841}
842
sewardj79048ce2005-02-18 08:28:32 +0000843
sewardj548be6d2005-02-16 01:31:37 +0000844/* Try to find a map space for [addr,addr+len). If addr==0, it means
845 the caller is prepared to accept a space at any location; if not,
846 we will try for addr, but fail if we can't get it. This mimics
847 mmap fixed vs mmap not-fixed.
848*/
nethercote8b5f40c2004-11-02 13:29:50 +0000849Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000850{
fitzhardingee3632c62003-12-22 10:58:06 +0000851 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000852 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000853 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000854 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
855 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000856 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
857 Int i, i_any, i_fixed, i_final;
858 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000859
sewardj548be6d2005-02-16 01:31:37 +0000860 Bool fixed;
861
sewardje517b802005-02-16 01:58:51 +0000862 if (debug) {
863 VG_(printf)("\n\n");
sewardja8d8e232005-06-07 20:04:56 +0000864 VG_(printf)("find_map_space(%p, %llu, %d) ...\n",
865 addr, (ULong)len, for_client);
sewardje517b802005-02-16 01:58:51 +0000866 }
867
868 if (0) show_segments("find_map_space: start");
869
sewardj548be6d2005-02-16 01:31:37 +0000870 if (addr == 0) {
871 fixed = False;
872 } else {
873 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000874 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000875 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000876 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000877 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000878
879 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000880 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
njn13bfd852005-06-02 03:52:53 +0000881 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000882
nethercote73b526f2004-10-31 18:48:21 +0000883 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000884
sewardj548be6d2005-02-16 01:31:37 +0000885 /* Scan the segment list, looking for a hole which satisfies the
886 requirements. At each point i we ask the question "can we use
887 the hole in between segments[i-1] and segments[i] ?" */
888 i_any = i_fixed = -1;
889 hstart_any = hstart_fixed = 0;
890
891 hole_start = hole_end = 0;
892
893 /* Iterate over all possible holes, generating them into
894 hole_start/hole_end. Filter out invalid ones. Then see if any
895 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
896 */
897 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
898 if (i == 0) {
899 hole_start = 0;
900 hole_end = segments[0].addr-1;
901 }
902 else {
903 vg_assert(segments_used > 0);
904 if (i == segments_used) {
905 hole_start = segments[i-1].addr + segments[i-1].len;
906 hole_end = ~(Addr)0;
907 } else {
908 hole_start = segments[i-1].addr + segments[i-1].len;
909 hole_end = segments[i].addr - 1;
910 }
911 }
912
913 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
914
915 /* ignore zero-sized holes */
916 if (hole_start == hole_end+1)
917 continue;
918
njnbe91aae2005-03-27 01:42:41 +0000919 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
920 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000921
922 /* ignore holes which fall outside the allowable area */
923 if (!(hole_start >= base && hole_end <= limit))
924 continue;
925
926 vg_assert(hole_end > hole_start);
927 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000928 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000929
930 if (hole_len >= len && i_any == -1) {
931 /* It will at least fit in this hole. */
932 i_any = i;
933 hstart_any = hole_start;
934 }
935
sewardjb5f6f512005-03-10 23:59:00 +0000936 if (fixed && hole_start <= addr
937 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000938 /* We were asked for a fixed mapping, and this hole works.
939 Bag it -- and stop searching as further searching is
940 pointless. */
941 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000942 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000943 break;
944 }
945 }
946
947 /* Summarise the final decision into i_final/hstart_final. */
948 i_final = -1;
949 hstart_final = 0;
950
951 if (fixed) {
952 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000953 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000954 } else {
955 i_final = i_any;
956 hstart_final = hstart_any;
957 }
958
959
960 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000961 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000962 else
963 ret = 0; /* not found */
964
965 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000966 VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n",
967 addr, (ULong)len, for_client, ret);
sewardj548be6d2005-02-16 01:31:37 +0000968
sewardjb5f6f512005-03-10 23:59:00 +0000969 if (fixed) {
970 vg_assert(ret == 0 || ret == addrOrig);
971 }
972
sewardj548be6d2005-02-16 01:31:37 +0000973 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000974}
975
sewardj79048ce2005-02-18 08:28:32 +0000976
sewardjb5f6f512005-03-10 23:59:00 +0000977/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000978 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000979 mapping over any part of the address space which is not covered
980 by an entry in the segment list.
981
982 This is designed for use around system calls which allocate
983 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000984 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000985 address with VG_(find_map_space) and then adding a segment for
986 it and padding the address space valgrind can ensure that the
987 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000988void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000989{
sewardj394790d2005-03-17 02:14:44 +0000990 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +0000991 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +0000992
993 Int i = 0;
994 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000995
nethercote820bd8c2004-09-07 23:04:49 +0000996 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000997 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +0000998 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 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 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001003 i++;
1004 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001005 }
1006
nethercote820bd8c2004-09-07 23:04:49 +00001007 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001008 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001009 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1010 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001011 }
thughes9aaebc32004-07-15 23:13:37 +00001012}
1013
thughesc70b8c62004-07-16 23:07:58 +00001014/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001015 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001016void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001017{
sewardj394790d2005-03-17 02:14:44 +00001018 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001019 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001020
1021 Int i = 0;
1022 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001023
nethercote820bd8c2004-09-07 23:04:49 +00001024 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001025 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +00001026 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001027 }
thughes9aaebc32004-07-15 23:13:37 +00001028 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001029 i++;
1030 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001031 }
1032
nethercote820bd8c2004-09-07 23:04:49 +00001033 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001034 ret = VG_(do_syscall2)(__NR_munmap, addr,
1035 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001036 }
thughes9aaebc32004-07-15 23:13:37 +00001037}
1038
sewardj548be6d2005-02-16 01:31:37 +00001039/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001040Segment *VG_(find_segment)(Addr a)
1041{
sewardj548be6d2005-02-16 01:31:37 +00001042 Int r = find_segment(a);
1043 if (0) show_segments("find_segment");
1044 if (r == -1) return NULL;
1045 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001046}
1047
sewardj548be6d2005-02-16 01:31:37 +00001048/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1049 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1050 a segment is a checked error.
1051*/
1052Segment *VG_(find_segment_above_unmapped)(Addr a)
1053{
1054 Int r = find_segment_above_unmapped(a);
1055 if (0) show_segments("find_segment_above_unmapped");
1056 if (r == -1) return NULL;
1057 return &segments[r];
1058}
1059
1060/* Assumes that 'a' is in some segment. Finds the next segment along,
1061 or NULL if none. Passing 'a' which is in fact not in a segment is
1062 a checked error.
1063*/
1064Segment *VG_(find_segment_above_mapped)(Addr a)
1065{
1066 Int r = find_segment_above_mapped(a);
1067 if (0) show_segments("find_segment_above_mapped");
1068 if (r == -1) return NULL;
1069 return &segments[r];
1070}
1071
1072
sewardjde4a1d02002-03-22 01:27:54 +00001073/*------------------------------------------------------------*/
1074/*--- Tracking permissions around %esp changes. ---*/
1075/*------------------------------------------------------------*/
1076
1077/*
1078 The stack
1079 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001080 The stack's segment seems to be dynamically extended downwards by
1081 the kernel as the stack pointer moves down. Initially, a 1-page
1082 (4k) stack is allocated. When SP moves below that for the first
1083 time, presumably a page fault occurs. The kernel detects that the
njna60a7c12005-05-08 17:49:37 +00001084 faulting address is in the range from SP - VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001085 upwards to the current valid stack. It then extends the stack
1086 segment downwards for enough to cover the faulting address, and
1087 resumes the process (invisibly). The process is unaware of any of
1088 this.
sewardjde4a1d02002-03-22 01:27:54 +00001089
sewardjfa8202f2005-04-24 11:05:55 +00001090 That means that Valgrind can't spot when the stack segment is being
1091 extended. Fortunately, we want to precisely and continuously
1092 update stack permissions around SP, so we need to spot all writes
1093 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001094
sewardjfa8202f2005-04-24 11:05:55 +00001095 The deal is: when SP is assigned a lower value, the stack is being
1096 extended. Create suitably-permissioned pages to fill in any holes
1097 between the old stack ptr and this one, if necessary. Then mark
1098 all bytes in the area just "uncovered" by this SP change as
1099 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001100
sewardjfa8202f2005-04-24 11:05:55 +00001101 When SP goes back up, mark the area receded over as unreadable and
1102 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001103
njna60a7c12005-05-08 17:49:37 +00001104 Just to record the SP boundary conditions somewhere convenient:
1105 SP - VGA_STACK_REDZONE_SZB always points to the lowest live byte in
1106 the stack. All addresses below SP - VGA_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001107 live; those at and above it are.
1108
njna60a7c12005-05-08 17:49:37 +00001109 We do not concern ourselves here with the VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001110 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001111*/
1112
rjwalsh0140af52005-06-04 20:42:33 +00001113/*
1114 * This structure holds information about the start and end addresses of
1115 * registered stacks. There's always at least one stack registered:
1116 * the main process stack. It will be the first stack registered and
1117 * so will have a stack id of 0. The user does not need to register
1118 * this stack: Valgrind does it automatically right before it starts
1119 * running the client. No other stacks are automatically registered by
1120 * Valgrind, however.
1121 */
1122
1123typedef struct _Stack {
1124 UWord id;
1125 Addr start;
1126 Addr end;
1127 struct _Stack *next;
1128} Stack;
1129
1130static Stack *stacks;
1131static UWord next_id; /* Next id we hand out to a newly registered stack */
1132
1133/*
1134 * These are the id, start and end values of the current stack. If the
1135 * stack pointer falls outside the range of the current stack, we search
1136 * the stacks list above for a matching stack.
1137 */
1138
1139static Addr current_stack_start;
1140static Addr current_stack_end;
1141static UWord current_stack_id;
1142
1143/* Search for a particular stack by id number. */
1144static Bool find_stack_by_id(UWord id, Addr *start, Addr *end)
1145{
1146 Stack *i = stacks;
1147 while(i) {
1148 if(i->id == id) {
1149 *start = i->start;
1150 *end = i->end;
1151 return True;
1152 }
1153 i = i->next;
1154 }
1155 return False;
1156}
1157
1158/* Find what stack an address falls into. */
1159static Bool find_stack_by_addr(Addr sp, Addr *start, Addr *end, UWord *id)
1160{
1161 Stack *i = stacks;
1162 while(i) {
1163 if(sp >= i->start && sp <= i->end) {
1164 *start = i->start;
1165 *end = i->end;
1166 *id = i->id;
1167 return True;
1168 }
1169 i = i->next;
1170 }
1171 return False;
1172}
1173
1174/* Change over to a new stack. */
1175static Bool set_current_stack(UWord id)
1176{
1177 Addr start, end;
1178 if (find_stack_by_id(id, &start, &end)) {
1179 current_stack_id = id;
1180 current_stack_start = start;
1181 current_stack_end = end;
1182 return True;
1183 }
1184 return False;
1185}
1186
1187/*
1188 * Register a new stack from start - end. This is invoked from the
1189 * VALGRIND_STACK_REGISTER client request, and is also called just before
1190 * we start the client running, to register the main process stack.
1191 *
1192 * Note: this requires allocating a piece of memory to store the Stack
1193 * structure, which places a dependency between this module and the
1194 * mallocfree module. However, there is no real chance of a circular
1195 * dependency here, since the mallocfree module would never call back to
1196 * this function.
1197 */
1198
1199UWord VG_(handle_stack_register)(Addr start, Addr end)
1200{
1201 Stack *i;
1202 if (start > end) {
1203 Addr t = end;
1204 end = start;
1205 start = t;
1206 }
1207
1208 i = (Stack *)VG_(arena_malloc)(VG_AR_CORE, sizeof(Stack));
1209 i->start = start;
1210 i->end = end;
1211 i->id = next_id++;
1212 i->next = stacks;
1213 stacks = i;
1214
1215 if(i->id == 0) {
1216 set_current_stack(i->id);
1217 }
1218
1219 return i->id;
1220}
1221
1222/*
1223 * Deregister a stack. This is invoked from the VALGRIND_STACK_DEREGISTER
1224 * client request.
1225 *
1226 * Note: this requires freeing the piece of memory that was used to store
1227 * the Stack structure, which places a dependency between this module
1228 * and the mallocfree module. However, there is no real chance of
1229 * a circular dependency here, since the mallocfree module would never
1230 * call back to this function.
1231 */
1232
1233void VG_(handle_stack_deregister)(UWord id)
1234{
1235 Stack *i = stacks;
1236 Stack *prev = NULL;
1237
1238 if(current_stack_id == id) {
1239 return;
1240 }
1241
1242 while(i) {
1243 if (i->id == id) {
1244 if(prev == NULL) {
1245 stacks = i->next;
1246 } else {
1247 prev->next = i->next;
1248 }
1249 VG_(arena_free)(VG_AR_CORE, i);
1250 return;
1251 }
1252 prev = i;
1253 i = i->next;
1254 }
1255}
1256
1257/*
1258 * Change a stack. This is invoked from the VALGRIND_STACK_CHANGE client
1259 * request and from the stack growth stuff the signals module when
1260 * extending the main process stack.
1261 */
1262
1263void VG_(handle_stack_change)(UWord id, Addr start, Addr end)
1264{
1265 Stack *i = stacks;
1266
1267 if (id == current_stack_id) {
1268 current_stack_start = start;
1269 current_stack_end = end;
1270 }
1271
1272 while(i) {
1273 if (i->id == id) {
1274 i->start = start;
1275 i->end = end;
1276 return;
1277 }
1278 i = i->next;
1279 }
1280}
1281
njn9b007f62003-04-07 14:40:25 +00001282/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001283 tracked by the tool, and one of the specialised cases
1284 (eg. new_mem_stack_4) isn't used in preference.
1285*/
njn9fb73db2005-03-27 01:55:21 +00001286VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001287void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001288{
sewardj97724e52005-04-02 23:40:59 +00001289 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001290 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001291
rjwalsh0140af52005-06-04 20:42:33 +00001292 /* Check if the stack pointer is still in the same stack as before. */
1293 if (new_SP < current_stack_start || new_SP > current_stack_end) {
1294 Addr start, end;
1295 UWord new_id;
1296 Bool found = find_stack_by_addr(new_SP, &start, &end, &new_id);
1297 if (found && new_id != current_stack_id) {
1298 /* The stack pointer is now in another stack. Update the current
1299 stack information and return without doing anything else. */
1300 set_current_stack(new_id);
1301 return;
1302 }
1303 }
1304
sewardj97724e52005-04-02 23:40:59 +00001305 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1306 /* SP has changed by more than some threshold amount (by
1307 default, 2MB). We take this to mean that the application is
1308 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001309
1310 JRS 20021001: following discussions with John Regehr, if a stack
1311 switch happens, it seems best not to mess at all with memory
1312 permissions. Seems to work well with Netscape 4.X. Really the
1313 only remaining difficulty is knowing exactly when a stack switch is
1314 happening. */
sewardj97724e52005-04-02 23:40:59 +00001315 if (VG_(clo_verbosity) > 0 && moans > 0) {
1316 moans--;
1317 VG_(message)(Vg_UserMsg,
1318 "Warning: client switching stacks? "
1319 "SP change: %p --> %p", old_SP, new_SP);
1320 VG_(message)(Vg_UserMsg,
1321 " to suppress, use: --max-stackframe=%d or greater",
1322 (delta < 0 ? -delta : delta));
1323 if (moans == 0)
1324 VG_(message)(Vg_UserMsg,
1325 " further instances of this message "
1326 "will not be shown.");
1327 }
njn9b007f62003-04-07 14:40:25 +00001328 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001329 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001330
njn9b007f62003-04-07 14:40:25 +00001331 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001332 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001333 }
1334}
1335
jsgf855d93d2003-10-13 22:26:55 +00001336/*
sewardjb5f6f512005-03-10 23:59:00 +00001337 Test if a piece of memory is addressable with at least the "prot"
1338 protection permissions by examining the underlying segments.
1339
1340 Really this is a very stupid algorithm and we could do much
1341 better by iterating through the segment array instead of through
1342 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001343 */
sewardjb5f6f512005-03-10 23:59:00 +00001344Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001345{
sewardjb5f6f512005-03-10 23:59:00 +00001346 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001347
sewardjb5f6f512005-03-10 23:59:00 +00001348 if ((p + size) < p)
1349 return False; /* reject wraparounds */
1350 if (size == 0)
1351 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001352
njn13bfd852005-06-02 03:52:53 +00001353 p = VG_PGROUNDDN(p);
1354 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001355 vg_assert(VG_IS_PAGE_ALIGNED(p));
1356 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001357
sewardjb5f6f512005-03-10 23:59:00 +00001358 for (; size > 0; size -= VKI_PAGE_SIZE) {
1359 seg = VG_(find_segment)(p);
1360 if (!seg)
1361 return False;
1362 if ((seg->prot & prot) != prot)
1363 return False;
1364 p += VKI_PAGE_SIZE;
1365 }
jsgf855d93d2003-10-13 22:26:55 +00001366
sewardjb5f6f512005-03-10 23:59:00 +00001367 return True;
jsgf855d93d2003-10-13 22:26:55 +00001368}
1369
sewardjb5f6f512005-03-10 23:59:00 +00001370
sewardjde4a1d02002-03-22 01:27:54 +00001371/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001372/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001373/*--------------------------------------------------------------------*/
1374
nethercote57e36b32004-07-10 14:56:28 +00001375// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001376Addr VG_(get_memory_from_mmap_for_client)
1377 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001378{
njn13bfd852005-06-02 03:52:53 +00001379 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +00001380
njnca82cc02004-11-22 17:18:48 +00001381 tl_assert(!(sf_flags & SF_FIXED));
1382 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001383
nethercote8e9eab02004-07-11 18:01:06 +00001384 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1385 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1386 sf_flags | SF_CORE, -1, 0);
1387 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001388 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001389 else
1390 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001391}
1392
fitzhardinge98abfc72003-12-16 02:05:15 +00001393
njn86f12dc2005-03-14 01:16:05 +00001394/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001395 range, which isn't SF_CORE, a root.
1396*/
njn86f12dc2005-03-14 01:16:05 +00001397void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1398{
sewardj882af5f2005-03-16 12:27:53 +00001399 Int i;
1400 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001401 Segment *s;
1402
sewardj882af5f2005-03-16 12:27:53 +00001403 for (i = 0; i < segments_used; i++) {
1404 s = &segments[i];
1405 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1406 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001407 if (flags != SF_MMAP && flags != SF_STACK)
1408 continue;
sewardj882af5f2005-03-16 12:27:53 +00001409 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1410 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001411 continue;
1412 if (!VG_(is_client_addr)(s->addr) ||
1413 !VG_(is_client_addr)(s->addr+s->len))
1414 continue;
1415
1416 (*add_rootrange)(s->addr, s->len);
1417 }
njn86f12dc2005-03-14 01:16:05 +00001418}
1419
1420
nethercote88a90162004-07-10 16:59:25 +00001421/*--------------------------------------------------------------------*/
1422/*--- Querying memory layout ---*/
1423/*--------------------------------------------------------------------*/
1424
fitzhardinge98abfc72003-12-16 02:05:15 +00001425Bool VG_(is_client_addr)(Addr a)
1426{
1427 return a >= VG_(client_base) && a < VG_(client_end);
1428}
1429
1430Bool VG_(is_shadow_addr)(Addr a)
1431{
1432 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1433}
1434
fitzhardinge98abfc72003-12-16 02:05:15 +00001435Addr VG_(get_shadow_size)(void)
1436{
1437 return VG_(shadow_end)-VG_(shadow_base);
1438}
1439
sewardjfa8202f2005-04-24 11:05:55 +00001440
nethercote88a90162004-07-10 16:59:25 +00001441/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001442/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001443/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001444
1445void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1446{
sewardj548be6d2005-02-16 01:31:37 +00001447vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001448 if (0)
1449 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1450
1451 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001452 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001453
njn13bfd852005-06-02 03:52:53 +00001454 sz = VG_PGROUNDUP(p+sz) - VG_PGROUNDDN(p);
1455 p = VG_PGROUNDDN(p);
fitzhardinge98abfc72003-12-16 02:05:15 +00001456
1457 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1458
1459 if (call_init)
1460 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001461 /* ask the tool to initialize each page */
njn13bfd852005-06-02 03:52:53 +00001462 VG_TRACK( init_shadow_page, VG_PGROUNDDN(p) );
fitzhardinge98abfc72003-12-16 02:05:15 +00001463
nethercote73b526f2004-10-31 18:48:21 +00001464 p += VKI_PAGE_SIZE;
1465 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001466 }
1467}
1468
1469void *VG_(shadow_alloc)(UInt size)
1470{
1471 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001472 Addr try_here;
1473 Int r;
1474
1475 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001476
1477 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001478 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001479
njn13bfd852005-06-02 03:52:53 +00001480 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001481
1482 if (shadow_alloc == 0)
1483 shadow_alloc = VG_(shadow_base);
1484
1485 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001486 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001487
sewardj79048ce2005-02-18 08:28:32 +00001488 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001489 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1490 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001491 vg_assert(size > 0);
1492
1493 if (0)
1494 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1495
1496 /* this is big-bang allocated, so we don't expect to find a listed
1497 segment for it. */
1498 /* This is really an absolute disgrace. Sometimes the big-bang
1499 mapping is in the list (due to re-reads of /proc/self/maps,
1500 presumably) and sometimes it isn't. */
1501#if 0
1502 r = find_segment(try_here);
1503 vg_assert(r == -1);
1504 r = find_segment(try_here+size-1);
1505 vg_assert(r == -1);
1506#endif
1507
1508 r = VG_(mprotect_native)( (void*)try_here,
1509 size, VKI_PROT_READ|VKI_PROT_WRITE );
1510
1511 if (r != 0)
1512 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001513
1514 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001515 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001516
sewardj79048ce2005-02-18 08:28:32 +00001517 failed:
1518 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001519 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001520 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001521 size
sewardj79048ce2005-02-18 08:28:32 +00001522 );
1523 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001524}
1525
njne3f06352005-06-01 03:48:33 +00001526/*------------------------------------------------------------*/
1527/*--- pointercheck ---*/
1528/*------------------------------------------------------------*/
1529
1530Bool VGA_(setup_pointercheck)(Addr client_base, Addr client_end)
1531{
1532 vg_assert(0 != client_end);
1533#if defined(VGP_x86_linux)
1534 /* Client address space segment limit descriptor entry */
1535 #define POINTERCHECK_SEGIDX 1
1536
1537 vki_modify_ldt_t ldt = {
1538 POINTERCHECK_SEGIDX, // entry_number
1539 client_base, // base_addr
1540 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1541 1, // seg_32bit
1542 0, // contents: data, RW, non-expanding
1543 0, // ! read_exec_only
1544 1, // limit_in_pages
1545 0, // ! seg not present
1546 1, // useable
1547 };
sewardja8d8e232005-06-07 20:04:56 +00001548 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1549 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001550 VG_(message)(Vg_UserMsg,
1551 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001552 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001553 return False;
1554 } else {
1555 return True;
1556 }
1557#elif defined(VGP_amd64_linux)
1558 if (0)
1559 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1560 return True;
1561#else
1562# error Unknown architecture
1563#endif
1564}
1565
fitzhardinge98abfc72003-12-16 02:05:15 +00001566/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001567/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001568/*--------------------------------------------------------------------*/