blob: a1eaf4447fb7ed6e84fcd4954a8ae75a415112f4 [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)()
njne9befc62005-06-11 15:51:30 +000038#include "pub_core_libcmman.h"
njn36a20fa2005-06-03 03:08:39 +000039#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000040#include "pub_core_libcproc.h"
njnaf1d7df2005-06-11 01:31:52 +000041#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000042#include "pub_core_options.h"
njn9abd6082005-06-17 21:31:45 +000043#include "pub_core_syscall.h"
njn2521d322005-05-08 14:45:13 +000044#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000045#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000046#include "pub_core_transtab.h"
njn3c660b62005-05-13 22:18:47 +000047#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000048
sewardjde4a1d02002-03-22 01:27:54 +000049
sewardja4495682002-10-21 07:29:59 +000050/* Define to debug the memory-leak-detector. */
51/* #define VG_DEBUG_LEAKCHECK */
52
sewardje517b802005-02-16 01:58:51 +000053static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000054
55/*--------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +000056/*--- Basic globals about the address space. ---*/
57/*--------------------------------------------------------------*/
58
59/* Client address space, lowest to highest (see top of ume.c) */
60Addr VG_(client_base); /* client address space limits */
61Addr VG_(client_end);
62Addr VG_(client_mapbase);
63Addr VG_(client_trampoline_code);
64Addr VG_(clstk_base);
65Addr VG_(clstk_end);
rjwalsh0140af52005-06-04 20:42:33 +000066UWord VG_(clstk_id);
njn04e16982005-05-31 00:23:43 +000067
68Addr VG_(brk_base); /* start of brk */
69Addr VG_(brk_limit); /* current brk */
70
71Addr VG_(shadow_base); /* tool's shadow memory */
72Addr VG_(shadow_end);
73
74Addr VG_(valgrind_base); /* valgrind's address range */
75
76// Note that VG_(valgrind_last) names the last byte of the section, whereas
77// the VG_(*_end) vars name the byte one past the end of the section.
78Addr VG_(valgrind_last);
79
80/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000081/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000082/*--------------------------------------------------------------*/
83
sewardj79048ce2005-02-18 08:28:32 +000084/* Max number of segments we can track. */
85#define VG_N_SEGMENTS 1000
86
87/* Max number of segment file names we can track. */
88#define VG_N_SEGNAMES 200
89
90/* Max length of a segment file name. */
91#define VG_MAX_SEGNAMELEN 1000
92
93
94/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000095
96/* Array [0 .. segments_used-1] of all mappings. */
97/* Sorted by .addr field. */
98/* I: len may not be zero. */
99/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +0000100/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +0000101
102static Segment segments[VG_N_SEGMENTS];
103static Int segments_used = 0;
104
sewardj79048ce2005-02-18 08:28:32 +0000105typedef
106 struct {
107 Bool inUse;
108 Bool mark;
109 HChar fname[VG_MAX_SEGNAMELEN];
110 }
111 SegName;
112
113/* Filename table. _used is the high water mark; an entry is only
114 valid if its index >= 0, < _used, and its .inUse field == True.
115 The .mark field is used to garbage-collect dead entries.
116*/
117static SegName segnames[VG_N_SEGNAMES];
118static Int segnames_used = 0;
119
120
121/* ------ end of STATE for the address-space manager ------ */
122
123
124/* Searches the filename table to find an index for the given name.
125 If none is found, an index is allocated and the name stored. If no
126 space is available we just give up. If the string is too long to
127 store, return -1.
128*/
129static Int allocate_segname ( const HChar* name )
130{
131 Int i, j, len;
132
133 vg_assert(name);
134
135 if (0) VG_(printf)("alloc_segname %s\n", name);
136
137 len = VG_(strlen)(name);
138 if (len >= VG_MAX_SEGNAMELEN-1) {
139 return -1;
140 }
141
142 /* first see if we already have the name. */
143 for (i = 0; i < segnames_used; i++) {
144 if (!segnames[i].inUse)
145 continue;
146 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
147 return i;
148 }
149 }
150
151 /* no we don't. So look for a free slot. */
152 for (i = 0; i < segnames_used; i++)
153 if (!segnames[i].inUse)
154 break;
155
156 if (i == segnames_used) {
157 /* no free slots .. advance the high-water mark. */
158 if (segnames_used+1 < VG_N_SEGNAMES) {
159 i = segnames_used;
160 segnames_used++;
161 } else {
162 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000163 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000164 " VG_N_SEGNAMES is too small: "
165 "increase it and rebuild Valgrind.\n"
166 );
167 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000168 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000169 " giving up now.\n\n"
170 );
171 VG_(exit)(0);
172 }
173 }
174
175 /* copy it in */
176 segnames[i].inUse = True;
177 for (j = 0; j < len; j++)
178 segnames[i].fname[j] = name[j];
179 vg_assert(len < VG_MAX_SEGNAMELEN);
180 segnames[i].fname[len] = 0;
181 return i;
182}
183
sewardj548be6d2005-02-16 01:31:37 +0000184
185/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
186 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000187 seg.
188*/
sewardj548be6d2005-02-16 01:31:37 +0000189static Int compare_addr_with_seg ( Addr a, Segment* seg )
190{
191 if (a < seg->addr)
192 return -1;
193 if (a >= seg->addr + seg->len)
194 return 1;
195 return 0;
196}
197
sewardj79048ce2005-02-18 08:28:32 +0000198
sewardj548be6d2005-02-16 01:31:37 +0000199/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000200 none.
201*/
sewardj548be6d2005-02-16 01:31:37 +0000202static Int find_segment ( Addr a )
203{
204 Int i;
205 for (i = 0; i < segments_used; i++) {
206 if (compare_addr_with_seg(a, &segments[i]) == 0)
207 return i;
208 }
209 return -1;
210}
211
212
213/* Assumes that 'a' is not in any segment. Finds the index of the
214 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
215 which is in fact in a segment is a checked error.
216*/
217static Int find_segment_above_unmapped ( Addr a )
218{
219 Int i, r;
220 for (i = 0; i < segments_used; i++) {
221 r = compare_addr_with_seg(a, &segments[i]);
222 vg_assert(r != 0); /* 'a' should not be in any segment. */
223 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000224 continue;
sewardj548be6d2005-02-16 01:31:37 +0000225 vg_assert(r == -1);
226 break;
227 }
228
229 if (i == segments_used)
230 return -1; /* not found */
231 else
232 return i;
233}
234
235
236/* Assumes that 'a' is in some segment. Finds the next segment along,
237 or NULL if none. Passing 'a' which is in fact not in a segment is
238 a checked error.
239*/
240static Int find_segment_above_mapped ( Addr a )
241{
242 Int i, r;
243 for (i = 0; i < segments_used; i++) {
244 r = compare_addr_with_seg(a, &segments[i]);
245 if (r == 1)
246 continue; /* not yet there */
247 if (r == 0)
248 break; /* found it */
249 vg_assert(0);
250 /* we shouldn't get here -- r == -1 and so it means we went past
251 'a' without seeing it -- it is therefore unmapped. */
252 /*NOTREACHED*/
253 }
254
255 vg_assert(i < segments_used);
256 if (i == segments_used-1)
257 return -1; /* not found */
258 else
259 return i+1;
260}
261
262
263/* Shift segments[i .. segments_used-1] up by one. */
264static void make_space_at ( Int i )
265{
266 Int j;
267 vg_assert(i >= 0 && i <= segments_used);
268 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000269 if (segments_used+1 == VG_N_SEGMENTS) {
270 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000271 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000272 " VG_N_SEGMENTS is too small: "
273 "increase it and rebuild Valgrind.\n"
274 );
275 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000276 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000277 " giving up now.\n\n"
278 );
279 VG_(exit)(0);
280 }
sewardj548be6d2005-02-16 01:31:37 +0000281 vg_assert(segments_used+1 < VG_N_SEGMENTS);
282 for (j = segments_used; j > i; j--)
283 segments[j] = segments[j-1];
284 segments_used++;
285}
286
sewardj79048ce2005-02-18 08:28:32 +0000287
sewardj548be6d2005-02-16 01:31:37 +0000288/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000289 segments_used.
290*/
sewardj548be6d2005-02-16 01:31:37 +0000291static void delete_segment_at ( Int i )
292{
293 Int j;
294 vg_assert(i >= 0 && i < segments_used);
295 for (j = i+1; j < segments_used; j++)
296 segments[j-1] = segments[j];
297 segments_used--;
298 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
299}
300
301
302/* Fill the i'th record all with zeroes. */
303static void zeroise_segment ( Int i )
304{
305 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000306 segments[i].prot = 0;
307 segments[i].flags = 0;
308 segments[i].addr = 0;
309 segments[i].len = 0;
310 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000311 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000312 segments[i].fnIdx = -1;
313 segments[i].dev = 0;
314 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000315 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000316}
317
sewardj79048ce2005-02-18 08:28:32 +0000318
sewardj548be6d2005-02-16 01:31:37 +0000319/* Create a segment to contain 'a', and return its index. Or -1 if
320 this failed because some other segment already contains 'a'. If
321 successful, fill in the segment's .addr field with 'a' but leave
322 all other fields alone.
323*/
324static Int create_segment ( Addr a )
325{
326 Int i, r;
327 for (i = 0; i < segments_used; i++) {
328 r = compare_addr_with_seg( a, &segments[i] );
329 if (r == 1)
330 continue; /* seg[i] precedes a */
331 if (r == 0)
332 return -1; /* seg[i] contains a. Give up */
333 vg_assert(r == -1);
334 break;
335 }
336 /* a precedes seg[i]. Shift segs at i and above up one, and use
337 this slot. */
338 make_space_at(i);
339 zeroise_segment(i);
340 segments[i].addr = a;
341 return i;
342}
343
sewardj79048ce2005-02-18 08:28:32 +0000344
345/* Print out the segment array (debugging only!). Note, this calls
346 VG_(printf), and I'm not 100% clear that that wouldn't require
347 dynamic memory allocation and hence more segments to be allocated.
348*/
349static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000350{
sewardj79048ce2005-02-18 08:28:32 +0000351 Int i;
352 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
353 who, segments_used, segnames_used);
354 for (i = 0; i < segnames_used; i++) {
355 if (!segnames[i].inUse)
356 continue;
357 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
358 }
359 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000360 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000361 "%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 +0000362 i,
sewardj79048ce2005-02-18 08:28:32 +0000363 segments[i].addr, segments[i].addr + segments[i].len,
364 (ULong)segments[i].len, segments[i].prot,
365 segments[i].flags, segments[i].dev, segments[i].ino,
366 (Long)segments[i].offset,
367 segments[i].fnIdx);
368 }
369 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000370}
sewardj79048ce2005-02-18 08:28:32 +0000371
sewardj548be6d2005-02-16 01:31:37 +0000372
373/* Find the segment containing 'a' and split it into two pieces at
374 'a'. Does nothing if no segment contains 'a', or if the split
375 would cause either of the pieces to have zero size.
376
377 If 'a' is not found, or if no splitting happens, -1 is returned.
378
379 If a value 'r' other than -1 is returned, this is the index of the
380 higher-addressed segment resulting from the split, and the index of
381 the lower-addressed segment is r-1.
382*/
383static Int split_segment ( Addr a )
384{
385 Int r;
386 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000387 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000388 r = find_segment(a);
389 if (r == -1)
390 /* not found */
391 return -1;
392 if (segments[r].addr == a)
393 /* segment starts at 'a', so splitting it would create a
394 zero-sized segment */
395 return -1;
396
397 /* copy original; make adjustments. */
398 vg_assert(a > segments[r].addr);
399 delta = a - segments[r].addr;
400 make_space_at(r);
401 segments[r] = segments[r+1];
402 segments[r].len = delta;
403 segments[r+1].len -= delta;
404 segments[r+1].addr += delta;
405 segments[r+1].offset += delta;
406 return r+1;
407}
408
sewardj79048ce2005-02-18 08:28:32 +0000409
410/* Return true if two segments are adjacent and mergable (s1 is
411 assumed to have a lower ->addr than s2) */
412static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
413{
414 if (s1->addr+s1->len != s2->addr)
415 return False;
416
417 if (s1->flags != s2->flags)
418 return False;
419
420 if (s1->prot != s2->prot)
421 return False;
422
njn36ef6ba2005-05-14 18:42:26 +0000423 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000424 return False;
425
426 if (s1->flags & SF_FILE){
427 if ((s1->offset + s1->len) != s2->offset)
428 return False;
429 if (s1->dev != s2->dev)
430 return False;
431 if (s1->ino != s2->ino)
432 return False;
433 if (s1->fnIdx != s2->fnIdx)
434 return False;
435 }
436
437 return True;
438}
439
440
441/* Clean up and sanity check the segment array:
442 - check segments are in ascending order
443 - check segments do not overlap
444 - check no segment has zero size
445 - merge adjacent where possible
446 - perform checks on the filename table, and reclaim dead entries
447*/
448static void preen_segments ( void )
449{
450 Int i, j, rd, wr;
451 Segment *s, *s1;
452 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
453 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
454
455 if (0) show_segments("before preen");
456
457 /* clear string table mark bits */
458 for (i = 0; i < segnames_used; i++)
459 segnames[i].mark = False;
460
461 /* check for non-zero size, and set mark bits for any used strings */
462 for (i = 0; i < segments_used; i++) {
463 vg_assert(segments[i].len > 0);
464 j = segments[i].fnIdx;
465 vg_assert(j >= -1 && j < segnames_used);
466 if (j >= 0) {
467 vg_assert(segnames[j].inUse);
468 segnames[j].mark = True;
469 }
470 }
471
472 /* check ascendingness and non-overlap */
473 for (i = 0; i < segments_used-1; i++) {
474 s = &segments[i];
475 s1 = &segments[i+1];
476 vg_assert(s->addr < s1->addr);
477 vg_assert(s->addr + s->len <= s1->addr);
478 }
479
480 /* merge */
481 if (segments_used < 1)
482 return;
483
484 wr = 1;
485 for (rd = 1; rd < segments_used; rd++) {
486 s = &segments[wr-1];
487 s1 = &segments[rd];
488 if (segments_are_mergeable(s,s1)) {
489 if (0)
490 VG_(printf)("merge %p-%p with %p-%p\n",
491 s->addr, s->addr+s->len,
492 s1->addr, s1->addr+s1->len);
493 s->len += s1->len;
494 continue;
495 }
496 if (wr < rd)
497 segments[wr] = segments[rd];
498 wr++;
499 }
500 vg_assert(wr >= 0 && wr <= segments_used);
501 segments_used = wr;
502
503 /* Free up any strings which are no longer referenced. */
504 for (i = 0; i < segnames_used; i++) {
505 if (segnames[i].mark == False) {
506 segnames[i].inUse = False;
507 segnames[i].fname[0] = 0;
508 }
509 }
510
511 if (0) show_segments("after preen");
512}
513
514
sewardj548be6d2005-02-16 01:31:37 +0000515/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000516/*--- Maintain an ordered list of all the client's mappings ---*/
517/*--------------------------------------------------------------*/
518
nethercote8991d5a2004-11-03 17:07:46 +0000519Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000520{
521 Addr se = s->addr+s->len;
522 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000523 vg_assert(pe >= p);
524
525 return (p >= s->addr && pe <= se);
526}
527
nethercote8991d5a2004-11-03 17:07:46 +0000528Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000529{
530 Addr se = s->addr+s->len;
531 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000532 vg_assert(pe >= p);
533
534 return (p < se && pe > s->addr);
535}
536
sewardj1024cf72005-02-28 14:39:21 +0000537#if 0
538/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000539/* Prepare a Segment structure for recycling by freeing everything
540 hanging off it. */
541static void recycleseg(Segment *s)
542{
543 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000544 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000545
546 if (s->filename != NULL)
547 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
548
549 /* keep the SegInfo, if any - it probably still applies */
550}
551
552/* When freeing a Segment, also clean up every one else's ideas of
553 what was going on in that range of memory */
554static void freeseg(Segment *s)
555{
556 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000557 if (s->seginfo != NULL) {
558 VG_(seginfo_decref)(s->seginfo, s->addr);
559 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000560 }
561
562 VG_(SkipNode_Free)(&sk_segments, s);
563}
sewardj1024cf72005-02-28 14:39:21 +0000564#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000565
sewardj1024cf72005-02-28 14:39:21 +0000566
567/* Get rid of any translations arising from s. */
568/* Note, this is not really the job of the low level memory manager.
569 When it comes time to rewrite this subsystem, clean this up. */
570static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000571{
sewardj1024cf72005-02-28 14:39:21 +0000572 if (s->flags & SF_CODE) {
573 VG_(discard_translations)(s->addr, s->len);
574 if (0)
575 VG_(printf)("dumping translations in %p .. %p\n",
576 s->addr, s->addr+s->len);
577 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000578}
579
sewardj1024cf72005-02-28 14:39:21 +0000580
fitzhardinge98abfc72003-12-16 02:05:15 +0000581/* This unmaps all the segments in the range [addr, addr+len); any
582 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000583void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000584{
fitzhardingee3632c62003-12-22 10:58:06 +0000585 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000586 Segment* s;
587 Addr end, s_end;
588 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000589 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000590
591 if (len == 0)
592 return;
593
njn13bfd852005-06-02 03:52:53 +0000594 len = VG_PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000595
fitzhardinge98abfc72003-12-16 02:05:15 +0000596 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000597 VG_(printf)("unmap_range(%p, %llu)\n", addr, (ULong)len);
sewardj79048ce2005-02-18 08:28:32 +0000598 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000599 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000600
601 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000602 vg_assert(VG_IS_PAGE_ALIGNED(addr));
603 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000604
sewardj548be6d2005-02-16 01:31:37 +0000605 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000606
607 /* do not delete .. even though it looks stupid */
608 vg_assert(i >= 0);
609
610 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000611 s = &segments[i];
612 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000613
sewardj548be6d2005-02-16 01:31:37 +0000614 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000615 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000616 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000617
fitzhardinge1a303042003-12-22 08:48:50 +0000618 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000619 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000620 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000621 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000622 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000623
624 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000625 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000626 addr < s_end &&
627 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000628 /* this segment's tail is truncated by [addr, addr+len)
629 -> truncate tail
630 */
sewardj1024cf72005-02-28 14:39:21 +0000631 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000632 s->len = addr - s->addr;
633
634 if (debug)
tom9be7c982005-04-25 16:55:44 +0000635 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000636 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000637 /* this segment's head is truncated by [addr, addr+len)
638 -> truncate head
639 */
sewardj548be6d2005-02-16 01:31:37 +0000640 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000641
642 if (debug)
tom9be7c982005-04-25 16:55:44 +0000643 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000644 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000645
sewardj1024cf72005-02-28 14:39:21 +0000646 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000647 s->addr += delta;
648 s->offset += delta;
649 s->len -= delta;
650
651 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000652 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000653 /* this segment is completely contained within [addr, addr+len)
654 -> delete segment
655 */
sewardj1024cf72005-02-28 14:39:21 +0000656 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000657 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000658 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000659
660 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000661 VG_(printf)(" case 3: seg %d deleted\n", i);
662 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000663 /* [addr, addr+len) is contained within a single segment
664 -> split segment into 3, delete middle portion
665 */
sewardj1024cf72005-02-28 14:39:21 +0000666 Int i_middle;
667 dump_translations_from(s);
668 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000669 vg_assert(i_middle != -1);
670 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000671 vg_assert(segments[i_middle].addr == addr);
672 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000673 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000674
675 if (debug)
676 VG_(printf)(" case 4: subrange %p-%p deleted\n",
677 addr, addr+len);
678 }
sewardj47c98a72005-03-12 20:36:15 +0000679
680 /* If we deleted this segment (or any above), those above will
681 have been moved down to fill in the hole in the segment
682 array. In order that we don't miss them, we have to
683 re-consider this slot number; hence the i--. */
684 if (deleted)
685 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000686 }
sewardj79048ce2005-02-18 08:28:32 +0000687 preen_segments();
688 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000689}
690
sewardj548be6d2005-02-16 01:31:37 +0000691
692/* Add a binding of [addr,addr+len) to
693 (prot,flags,dev,ino,off,filename) in the segment array.
694 Delete/truncate any previous mapping(s) covering that range.
695*/
696void
697VG_(map_file_segment)( Addr addr, SizeT len,
698 UInt prot, UInt flags,
699 UInt dev, UInt ino, ULong off,
700 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000701{
fitzhardinge98abfc72003-12-16 02:05:15 +0000702 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000703 Segment* s;
704 Int idx;
sewardja8d8e232005-06-07 20:04:56 +0000705 HChar* stage2_suffix = "lib/valgrind/stage2";
706 Bool is_stage2 = VG_(strstr)(filename, stage2_suffix) != NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000707
708 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000709 VG_(printf)(
710 "\n"
tom9be7c982005-04-25 16:55:44 +0000711 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000712 " dev=0x%4x ino=%d off=%ld\n"
713 " filename='%s')\n",
714 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000715
sewardja8d8e232005-06-07 20:04:56 +0000716 if (0) show_segments("before map_file_segment");
717
fitzhardinge98abfc72003-12-16 02:05:15 +0000718 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000719 vg_assert(VG_IS_PAGE_ALIGNED(addr));
njn13bfd852005-06-02 03:52:53 +0000720 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000721
sewardj548be6d2005-02-16 01:31:37 +0000722 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
723 VG_(unmap_range)(addr, len);
724
725 /* and now install this one */
726 idx = create_segment(addr);
727 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
728 vg_assert(idx != -1);
729 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000730
sewardj79048ce2005-02-18 08:28:32 +0000731 s = &segments[idx];
732 vg_assert(s->addr == addr);
733 s->prot = prot;
734 s->flags = flags;
735 s->len = len;
736 s->offset = off;
737 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
738 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
739 s->dev = dev;
740 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000741 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000742
sewardj79048ce2005-02-18 08:28:32 +0000743 /* Clean up right now */
744 preen_segments();
745 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000746
747 /* If this mapping is of the beginning of a file, isn't part of
748 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000749 file, then try reading symbols from it.
750 */
njn36ef6ba2005-05-14 18:42:26 +0000751 if (s->seginfo == NULL
sewardja8d8e232005-06-07 20:04:56 +0000752 && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
753 || is_stage2
754 )
sewardj79048ce2005-02-18 08:28:32 +0000755 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
756 if (off == 0
757 && s->fnIdx != -1
758 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
759 && len >= VKI_PAGE_SIZE
760 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000761 s->seginfo = VG_(read_seg_symbols)(s);
762 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000763 s->flags |= SF_DYNLIB;
764 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000765 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000766#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000767 const SegInfo *info;
768
njn36ef6ba2005-05-14 18:42:26 +0000769 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000770 for(info = VG_(next_seginfo)(NULL);
771 info != NULL;
772 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000773 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
774 {
njn36ef6ba2005-05-14 18:42:26 +0000775 s->seginfo = (SegInfo *)info;
776 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000777 }
778 }
sewardj79048ce2005-02-18 08:28:32 +0000779#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000780 }
781 }
782
783 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000784 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000785}
786
nethercote8b5f40c2004-11-02 13:29:50 +0000787void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000788 Int fd, ULong off, const Char *filename)
789{
790 struct vki_stat st;
791 Char *name = NULL;
792
793 st.st_dev = 0;
794 st.st_ino = 0;
795
796 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000797 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000798
799 if (VG_(fstat)(fd, &st) < 0)
800 flags &= ~SF_FILE;
801 }
802
sewardj79048ce2005-02-18 08:28:32 +0000803 if ((flags & SF_FILE) && filename == NULL && fd != -1)
804 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000805
806 if (filename == NULL)
807 filename = name;
808
sewardj79048ce2005-02-18 08:28:32 +0000809 VG_(map_file_segment)(addr, len, prot, flags,
810 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000811}
812
nethercote8b5f40c2004-11-02 13:29:50 +0000813void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000814{
815 flags &= ~SF_FILE;
816
817 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
818}
819
820/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000821void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000822{
sewardj79048ce2005-02-18 08:28:32 +0000823 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000824 static const Bool debug = False || mem_debug;
825
826 if (debug)
tom9be7c982005-04-25 16:55:44 +0000827 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000828
829 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000830
831 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000832 vg_assert(VG_IS_PAGE_ALIGNED(a));
njn13bfd852005-06-02 03:52:53 +0000833 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000834
sewardj79048ce2005-02-18 08:28:32 +0000835 split_segment(a);
836 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000837
sewardj548be6d2005-02-16 01:31:37 +0000838 r = find_segment(a);
839 vg_assert(r != -1);
840 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000841
842 preen_segments();
843
sewardje517b802005-02-16 01:58:51 +0000844 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000845}
846
sewardj79048ce2005-02-18 08:28:32 +0000847
sewardj548be6d2005-02-16 01:31:37 +0000848/* Try to find a map space for [addr,addr+len). If addr==0, it means
849 the caller is prepared to accept a space at any location; if not,
850 we will try for addr, but fail if we can't get it. This mimics
851 mmap fixed vs mmap not-fixed.
852*/
nethercote8b5f40c2004-11-02 13:29:50 +0000853Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000854{
fitzhardingee3632c62003-12-22 10:58:06 +0000855 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000856 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000857 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000858 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
859 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000860 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
861 Int i, i_any, i_fixed, i_final;
862 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000863
sewardj548be6d2005-02-16 01:31:37 +0000864 Bool fixed;
865
sewardje517b802005-02-16 01:58:51 +0000866 if (debug) {
867 VG_(printf)("\n\n");
sewardja8d8e232005-06-07 20:04:56 +0000868 VG_(printf)("find_map_space(%p, %llu, %d) ...\n",
869 addr, (ULong)len, for_client);
sewardje517b802005-02-16 01:58:51 +0000870 }
871
872 if (0) show_segments("find_map_space: start");
873
sewardj548be6d2005-02-16 01:31:37 +0000874 if (addr == 0) {
875 fixed = False;
876 } else {
877 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000878 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000879 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000880 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000881 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000882
883 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000884 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
njn13bfd852005-06-02 03:52:53 +0000885 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000886
nethercote73b526f2004-10-31 18:48:21 +0000887 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000888
sewardj548be6d2005-02-16 01:31:37 +0000889 /* Scan the segment list, looking for a hole which satisfies the
890 requirements. At each point i we ask the question "can we use
891 the hole in between segments[i-1] and segments[i] ?" */
892 i_any = i_fixed = -1;
893 hstart_any = hstart_fixed = 0;
894
895 hole_start = hole_end = 0;
896
897 /* Iterate over all possible holes, generating them into
898 hole_start/hole_end. Filter out invalid ones. Then see if any
899 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
900 */
901 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
902 if (i == 0) {
903 hole_start = 0;
904 hole_end = segments[0].addr-1;
905 }
906 else {
907 vg_assert(segments_used > 0);
908 if (i == segments_used) {
909 hole_start = segments[i-1].addr + segments[i-1].len;
910 hole_end = ~(Addr)0;
911 } else {
912 hole_start = segments[i-1].addr + segments[i-1].len;
913 hole_end = segments[i].addr - 1;
914 }
915 }
916
917 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
918
919 /* ignore zero-sized holes */
920 if (hole_start == hole_end+1)
921 continue;
922
njnbe91aae2005-03-27 01:42:41 +0000923 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
924 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000925
926 /* ignore holes which fall outside the allowable area */
927 if (!(hole_start >= base && hole_end <= limit))
928 continue;
929
930 vg_assert(hole_end > hole_start);
931 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000932 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000933
934 if (hole_len >= len && i_any == -1) {
935 /* It will at least fit in this hole. */
936 i_any = i;
937 hstart_any = hole_start;
938 }
939
sewardjb5f6f512005-03-10 23:59:00 +0000940 if (fixed && hole_start <= addr
941 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000942 /* We were asked for a fixed mapping, and this hole works.
943 Bag it -- and stop searching as further searching is
944 pointless. */
945 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000946 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000947 break;
948 }
949 }
950
951 /* Summarise the final decision into i_final/hstart_final. */
952 i_final = -1;
953 hstart_final = 0;
954
955 if (fixed) {
956 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000957 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000958 } else {
959 i_final = i_any;
960 hstart_final = hstart_any;
961 }
962
963
964 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000965 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000966 else
967 ret = 0; /* not found */
968
969 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000970 VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n",
971 addr, (ULong)len, for_client, ret);
sewardj548be6d2005-02-16 01:31:37 +0000972
sewardjb5f6f512005-03-10 23:59:00 +0000973 if (fixed) {
974 vg_assert(ret == 0 || ret == addrOrig);
975 }
976
sewardj548be6d2005-02-16 01:31:37 +0000977 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000978}
979
sewardj79048ce2005-02-18 08:28:32 +0000980
sewardjb5f6f512005-03-10 23:59:00 +0000981/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000982 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000983 mapping over any part of the address space which is not covered
984 by an entry in the segment list.
985
986 This is designed for use around system calls which allocate
987 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000988 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000989 address with VG_(find_map_space) and then adding a segment for
990 it and padding the address space valgrind can ensure that the
991 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000992void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000993{
sewardj394790d2005-03-17 02:14:44 +0000994 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +0000995 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +0000996
997 Int i = 0;
998 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000999
nethercote820bd8c2004-09-07 23:04:49 +00001000 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001001 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +00001002 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +00001003 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1004 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001005 }
thughes9aaebc32004-07-15 23:13:37 +00001006 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001007 i++;
1008 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001009 }
1010
nethercote820bd8c2004-09-07 23:04:49 +00001011 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001012 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001013 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1014 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001015 }
thughes9aaebc32004-07-15 23:13:37 +00001016}
1017
thughesc70b8c62004-07-16 23:07:58 +00001018/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001019 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001020void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001021{
sewardj394790d2005-03-17 02:14:44 +00001022 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001023 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001024
1025 Int i = 0;
1026 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001027
nethercote820bd8c2004-09-07 23:04:49 +00001028 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001029 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +00001030 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001031 }
thughes9aaebc32004-07-15 23:13:37 +00001032 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001033 i++;
1034 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001035 }
1036
nethercote820bd8c2004-09-07 23:04:49 +00001037 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001038 ret = VG_(do_syscall2)(__NR_munmap, addr,
1039 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001040 }
thughes9aaebc32004-07-15 23:13:37 +00001041}
1042
sewardj548be6d2005-02-16 01:31:37 +00001043/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001044Segment *VG_(find_segment)(Addr a)
1045{
sewardj548be6d2005-02-16 01:31:37 +00001046 Int r = find_segment(a);
1047 if (0) show_segments("find_segment");
1048 if (r == -1) return NULL;
1049 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001050}
1051
sewardj548be6d2005-02-16 01:31:37 +00001052/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1053 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1054 a segment is a checked error.
1055*/
1056Segment *VG_(find_segment_above_unmapped)(Addr a)
1057{
1058 Int r = find_segment_above_unmapped(a);
1059 if (0) show_segments("find_segment_above_unmapped");
1060 if (r == -1) return NULL;
1061 return &segments[r];
1062}
1063
1064/* Assumes that 'a' is in some segment. Finds the next segment along,
1065 or NULL if none. Passing 'a' which is in fact not in a segment is
1066 a checked error.
1067*/
1068Segment *VG_(find_segment_above_mapped)(Addr a)
1069{
1070 Int r = find_segment_above_mapped(a);
1071 if (0) show_segments("find_segment_above_mapped");
1072 if (r == -1) return NULL;
1073 return &segments[r];
1074}
1075
1076
sewardjde4a1d02002-03-22 01:27:54 +00001077/*------------------------------------------------------------*/
1078/*--- Tracking permissions around %esp changes. ---*/
1079/*------------------------------------------------------------*/
1080
1081/*
1082 The stack
1083 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001084 The stack's segment seems to be dynamically extended downwards by
1085 the kernel as the stack pointer moves down. Initially, a 1-page
1086 (4k) stack is allocated. When SP moves below that for the first
1087 time, presumably a page fault occurs. The kernel detects that the
njna60a7c12005-05-08 17:49:37 +00001088 faulting address is in the range from SP - VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001089 upwards to the current valid stack. It then extends the stack
1090 segment downwards for enough to cover the faulting address, and
1091 resumes the process (invisibly). The process is unaware of any of
1092 this.
sewardjde4a1d02002-03-22 01:27:54 +00001093
sewardjfa8202f2005-04-24 11:05:55 +00001094 That means that Valgrind can't spot when the stack segment is being
1095 extended. Fortunately, we want to precisely and continuously
1096 update stack permissions around SP, so we need to spot all writes
1097 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001098
sewardjfa8202f2005-04-24 11:05:55 +00001099 The deal is: when SP is assigned a lower value, the stack is being
1100 extended. Create suitably-permissioned pages to fill in any holes
1101 between the old stack ptr and this one, if necessary. Then mark
1102 all bytes in the area just "uncovered" by this SP change as
1103 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001104
sewardjfa8202f2005-04-24 11:05:55 +00001105 When SP goes back up, mark the area receded over as unreadable and
1106 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001107
njna60a7c12005-05-08 17:49:37 +00001108 Just to record the SP boundary conditions somewhere convenient:
1109 SP - VGA_STACK_REDZONE_SZB always points to the lowest live byte in
1110 the stack. All addresses below SP - VGA_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001111 live; those at and above it are.
1112
njna60a7c12005-05-08 17:49:37 +00001113 We do not concern ourselves here with the VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001114 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001115*/
1116
rjwalsh0140af52005-06-04 20:42:33 +00001117/*
1118 * This structure holds information about the start and end addresses of
1119 * registered stacks. There's always at least one stack registered:
1120 * the main process stack. It will be the first stack registered and
1121 * so will have a stack id of 0. The user does not need to register
1122 * this stack: Valgrind does it automatically right before it starts
1123 * running the client. No other stacks are automatically registered by
1124 * Valgrind, however.
1125 */
1126
1127typedef struct _Stack {
1128 UWord id;
1129 Addr start;
1130 Addr end;
1131 struct _Stack *next;
1132} Stack;
1133
1134static Stack *stacks;
1135static UWord next_id; /* Next id we hand out to a newly registered stack */
1136
1137/*
1138 * These are the id, start and end values of the current stack. If the
1139 * stack pointer falls outside the range of the current stack, we search
1140 * the stacks list above for a matching stack.
1141 */
1142
1143static Addr current_stack_start;
1144static Addr current_stack_end;
1145static UWord current_stack_id;
1146
1147/* Search for a particular stack by id number. */
1148static Bool find_stack_by_id(UWord id, Addr *start, Addr *end)
1149{
1150 Stack *i = stacks;
1151 while(i) {
1152 if(i->id == id) {
1153 *start = i->start;
1154 *end = i->end;
1155 return True;
1156 }
1157 i = i->next;
1158 }
1159 return False;
1160}
1161
1162/* Find what stack an address falls into. */
1163static Bool find_stack_by_addr(Addr sp, Addr *start, Addr *end, UWord *id)
1164{
1165 Stack *i = stacks;
1166 while(i) {
1167 if(sp >= i->start && sp <= i->end) {
1168 *start = i->start;
1169 *end = i->end;
1170 *id = i->id;
1171 return True;
1172 }
1173 i = i->next;
1174 }
1175 return False;
1176}
1177
1178/* Change over to a new stack. */
1179static Bool set_current_stack(UWord id)
1180{
1181 Addr start, end;
1182 if (find_stack_by_id(id, &start, &end)) {
1183 current_stack_id = id;
1184 current_stack_start = start;
1185 current_stack_end = end;
1186 return True;
1187 }
1188 return False;
1189}
1190
1191/*
1192 * Register a new stack from start - end. This is invoked from the
1193 * VALGRIND_STACK_REGISTER client request, and is also called just before
1194 * we start the client running, to register the main process stack.
1195 *
1196 * Note: this requires allocating a piece of memory to store the Stack
1197 * structure, which places a dependency between this module and the
1198 * mallocfree module. However, there is no real chance of a circular
1199 * dependency here, since the mallocfree module would never call back to
1200 * this function.
1201 */
1202
1203UWord VG_(handle_stack_register)(Addr start, Addr end)
1204{
1205 Stack *i;
1206 if (start > end) {
1207 Addr t = end;
1208 end = start;
1209 start = t;
1210 }
1211
1212 i = (Stack *)VG_(arena_malloc)(VG_AR_CORE, sizeof(Stack));
1213 i->start = start;
1214 i->end = end;
1215 i->id = next_id++;
1216 i->next = stacks;
1217 stacks = i;
1218
1219 if(i->id == 0) {
1220 set_current_stack(i->id);
1221 }
1222
1223 return i->id;
1224}
1225
1226/*
1227 * Deregister a stack. This is invoked from the VALGRIND_STACK_DEREGISTER
1228 * client request.
1229 *
1230 * Note: this requires freeing the piece of memory that was used to store
1231 * the Stack structure, which places a dependency between this module
1232 * and the mallocfree module. However, there is no real chance of
1233 * a circular dependency here, since the mallocfree module would never
1234 * call back to this function.
1235 */
1236
1237void VG_(handle_stack_deregister)(UWord id)
1238{
1239 Stack *i = stacks;
1240 Stack *prev = NULL;
1241
1242 if(current_stack_id == id) {
1243 return;
1244 }
1245
1246 while(i) {
1247 if (i->id == id) {
1248 if(prev == NULL) {
1249 stacks = i->next;
1250 } else {
1251 prev->next = i->next;
1252 }
1253 VG_(arena_free)(VG_AR_CORE, i);
1254 return;
1255 }
1256 prev = i;
1257 i = i->next;
1258 }
1259}
1260
1261/*
1262 * Change a stack. This is invoked from the VALGRIND_STACK_CHANGE client
1263 * request and from the stack growth stuff the signals module when
1264 * extending the main process stack.
1265 */
1266
1267void VG_(handle_stack_change)(UWord id, Addr start, Addr end)
1268{
1269 Stack *i = stacks;
1270
1271 if (id == current_stack_id) {
1272 current_stack_start = start;
1273 current_stack_end = end;
1274 }
1275
1276 while(i) {
1277 if (i->id == id) {
1278 i->start = start;
1279 i->end = end;
1280 return;
1281 }
1282 i = i->next;
1283 }
1284}
1285
njn9b007f62003-04-07 14:40:25 +00001286/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001287 tracked by the tool, and one of the specialised cases
1288 (eg. new_mem_stack_4) isn't used in preference.
1289*/
njn9fb73db2005-03-27 01:55:21 +00001290VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001291void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001292{
sewardj97724e52005-04-02 23:40:59 +00001293 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001294 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001295
rjwalsh0140af52005-06-04 20:42:33 +00001296 /* Check if the stack pointer is still in the same stack as before. */
1297 if (new_SP < current_stack_start || new_SP > current_stack_end) {
1298 Addr start, end;
1299 UWord new_id;
1300 Bool found = find_stack_by_addr(new_SP, &start, &end, &new_id);
1301 if (found && new_id != current_stack_id) {
1302 /* The stack pointer is now in another stack. Update the current
1303 stack information and return without doing anything else. */
1304 set_current_stack(new_id);
1305 return;
1306 }
1307 }
1308
sewardj97724e52005-04-02 23:40:59 +00001309 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1310 /* SP has changed by more than some threshold amount (by
1311 default, 2MB). We take this to mean that the application is
1312 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001313
1314 JRS 20021001: following discussions with John Regehr, if a stack
1315 switch happens, it seems best not to mess at all with memory
1316 permissions. Seems to work well with Netscape 4.X. Really the
1317 only remaining difficulty is knowing exactly when a stack switch is
1318 happening. */
sewardj97724e52005-04-02 23:40:59 +00001319 if (VG_(clo_verbosity) > 0 && moans > 0) {
1320 moans--;
1321 VG_(message)(Vg_UserMsg,
1322 "Warning: client switching stacks? "
1323 "SP change: %p --> %p", old_SP, new_SP);
1324 VG_(message)(Vg_UserMsg,
1325 " to suppress, use: --max-stackframe=%d or greater",
1326 (delta < 0 ? -delta : delta));
1327 if (moans == 0)
1328 VG_(message)(Vg_UserMsg,
1329 " further instances of this message "
1330 "will not be shown.");
1331 }
njn9b007f62003-04-07 14:40:25 +00001332 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001333 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001334
njn9b007f62003-04-07 14:40:25 +00001335 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001336 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001337 }
1338}
1339
jsgf855d93d2003-10-13 22:26:55 +00001340/*
sewardjb5f6f512005-03-10 23:59:00 +00001341 Test if a piece of memory is addressable with at least the "prot"
1342 protection permissions by examining the underlying segments.
1343
1344 Really this is a very stupid algorithm and we could do much
1345 better by iterating through the segment array instead of through
1346 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001347 */
sewardjb5f6f512005-03-10 23:59:00 +00001348Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001349{
sewardjb5f6f512005-03-10 23:59:00 +00001350 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001351
sewardjb5f6f512005-03-10 23:59:00 +00001352 if ((p + size) < p)
1353 return False; /* reject wraparounds */
1354 if (size == 0)
1355 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001356
njn13bfd852005-06-02 03:52:53 +00001357 p = VG_PGROUNDDN(p);
1358 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001359 vg_assert(VG_IS_PAGE_ALIGNED(p));
1360 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001361
sewardjb5f6f512005-03-10 23:59:00 +00001362 for (; size > 0; size -= VKI_PAGE_SIZE) {
1363 seg = VG_(find_segment)(p);
1364 if (!seg)
1365 return False;
1366 if ((seg->prot & prot) != prot)
1367 return False;
1368 p += VKI_PAGE_SIZE;
1369 }
jsgf855d93d2003-10-13 22:26:55 +00001370
sewardjb5f6f512005-03-10 23:59:00 +00001371 return True;
jsgf855d93d2003-10-13 22:26:55 +00001372}
1373
sewardjb5f6f512005-03-10 23:59:00 +00001374
sewardjde4a1d02002-03-22 01:27:54 +00001375/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001376/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001377/*--------------------------------------------------------------------*/
1378
nethercote57e36b32004-07-10 14:56:28 +00001379// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001380Addr VG_(get_memory_from_mmap_for_client)
1381 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001382{
njn13bfd852005-06-02 03:52:53 +00001383 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +00001384
njnca82cc02004-11-22 17:18:48 +00001385 tl_assert(!(sf_flags & SF_FIXED));
1386 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001387
nethercote8e9eab02004-07-11 18:01:06 +00001388 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1389 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1390 sf_flags | SF_CORE, -1, 0);
1391 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001392 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001393 else
1394 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001395}
1396
fitzhardinge98abfc72003-12-16 02:05:15 +00001397
njn86f12dc2005-03-14 01:16:05 +00001398/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001399 range, which isn't SF_CORE, a root.
1400*/
njn86f12dc2005-03-14 01:16:05 +00001401void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1402{
sewardj882af5f2005-03-16 12:27:53 +00001403 Int i;
1404 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001405 Segment *s;
1406
sewardj882af5f2005-03-16 12:27:53 +00001407 for (i = 0; i < segments_used; i++) {
1408 s = &segments[i];
1409 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1410 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001411 if (flags != SF_MMAP && flags != SF_STACK)
1412 continue;
sewardj882af5f2005-03-16 12:27:53 +00001413 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1414 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001415 continue;
1416 if (!VG_(is_client_addr)(s->addr) ||
1417 !VG_(is_client_addr)(s->addr+s->len))
1418 continue;
1419
1420 (*add_rootrange)(s->addr, s->len);
1421 }
njn86f12dc2005-03-14 01:16:05 +00001422}
1423
1424
nethercote88a90162004-07-10 16:59:25 +00001425/*--------------------------------------------------------------------*/
1426/*--- Querying memory layout ---*/
1427/*--------------------------------------------------------------------*/
1428
fitzhardinge98abfc72003-12-16 02:05:15 +00001429Bool VG_(is_client_addr)(Addr a)
1430{
1431 return a >= VG_(client_base) && a < VG_(client_end);
1432}
1433
1434Bool VG_(is_shadow_addr)(Addr a)
1435{
1436 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1437}
1438
fitzhardinge98abfc72003-12-16 02:05:15 +00001439Addr VG_(get_shadow_size)(void)
1440{
1441 return VG_(shadow_end)-VG_(shadow_base);
1442}
1443
sewardjfa8202f2005-04-24 11:05:55 +00001444
nethercote88a90162004-07-10 16:59:25 +00001445/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001446/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001447/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001448
1449void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1450{
sewardj548be6d2005-02-16 01:31:37 +00001451vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001452 if (0)
1453 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1454
1455 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001456 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001457
njn13bfd852005-06-02 03:52:53 +00001458 sz = VG_PGROUNDUP(p+sz) - VG_PGROUNDDN(p);
1459 p = VG_PGROUNDDN(p);
fitzhardinge98abfc72003-12-16 02:05:15 +00001460
1461 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1462
1463 if (call_init)
1464 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001465 /* ask the tool to initialize each page */
njn13bfd852005-06-02 03:52:53 +00001466 VG_TRACK( init_shadow_page, VG_PGROUNDDN(p) );
fitzhardinge98abfc72003-12-16 02:05:15 +00001467
nethercote73b526f2004-10-31 18:48:21 +00001468 p += VKI_PAGE_SIZE;
1469 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001470 }
1471}
1472
1473void *VG_(shadow_alloc)(UInt size)
1474{
1475 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001476 Addr try_here;
njne9befc62005-06-11 15:51:30 +00001477 SysRes r;
sewardj79048ce2005-02-18 08:28:32 +00001478
1479 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001480
1481 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001482 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001483
njn13bfd852005-06-02 03:52:53 +00001484 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001485
1486 if (shadow_alloc == 0)
1487 shadow_alloc = VG_(shadow_base);
1488
1489 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001490 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001491
sewardj79048ce2005-02-18 08:28:32 +00001492 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001493 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1494 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001495 vg_assert(size > 0);
1496
1497 if (0)
1498 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1499
1500 /* this is big-bang allocated, so we don't expect to find a listed
1501 segment for it. */
1502 /* This is really an absolute disgrace. Sometimes the big-bang
1503 mapping is in the list (due to re-reads of /proc/self/maps,
1504 presumably) and sometimes it isn't. */
1505#if 0
1506 r = find_segment(try_here);
1507 vg_assert(r == -1);
1508 r = find_segment(try_here+size-1);
1509 vg_assert(r == -1);
1510#endif
1511
1512 r = VG_(mprotect_native)( (void*)try_here,
1513 size, VKI_PROT_READ|VKI_PROT_WRITE );
1514
njne9befc62005-06-11 15:51:30 +00001515 if (r.isError)
sewardj79048ce2005-02-18 08:28:32 +00001516 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001517
1518 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001519 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001520
sewardj79048ce2005-02-18 08:28:32 +00001521 failed:
1522 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001523 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001524 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001525 size
sewardj79048ce2005-02-18 08:28:32 +00001526 );
1527 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001528}
1529
njne3f06352005-06-01 03:48:33 +00001530/*------------------------------------------------------------*/
1531/*--- pointercheck ---*/
1532/*------------------------------------------------------------*/
1533
1534Bool VGA_(setup_pointercheck)(Addr client_base, Addr client_end)
1535{
1536 vg_assert(0 != client_end);
1537#if defined(VGP_x86_linux)
1538 /* Client address space segment limit descriptor entry */
1539 #define POINTERCHECK_SEGIDX 1
1540
1541 vki_modify_ldt_t ldt = {
1542 POINTERCHECK_SEGIDX, // entry_number
1543 client_base, // base_addr
1544 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1545 1, // seg_32bit
1546 0, // contents: data, RW, non-expanding
1547 0, // ! read_exec_only
1548 1, // limit_in_pages
1549 0, // ! seg not present
1550 1, // useable
1551 };
sewardja8d8e232005-06-07 20:04:56 +00001552 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1553 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001554 VG_(message)(Vg_UserMsg,
1555 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001556 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001557 return False;
1558 } else {
1559 return True;
1560 }
1561#elif defined(VGP_amd64_linux)
1562 if (0)
1563 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1564 return True;
1565#else
1566# error Unknown architecture
1567#endif
1568}
1569
fitzhardinge98abfc72003-12-16 02:05:15 +00001570/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001571/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001572/*--------------------------------------------------------------------*/