blob: def6a4180d751fb340bc2f716d5165a043613c01 [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"
njn2521d322005-05-08 14:45:13 +000043#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000044#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000045#include "pub_core_transtab.h"
njn3c660b62005-05-13 22:18:47 +000046#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000047
sewardjde4a1d02002-03-22 01:27:54 +000048
sewardja4495682002-10-21 07:29:59 +000049/* Define to debug the memory-leak-detector. */
50/* #define VG_DEBUG_LEAKCHECK */
51
sewardje517b802005-02-16 01:58:51 +000052static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000053
54/*--------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +000055/*--- Basic globals about the address space. ---*/
56/*--------------------------------------------------------------*/
57
58/* Client address space, lowest to highest (see top of ume.c) */
59Addr VG_(client_base); /* client address space limits */
60Addr VG_(client_end);
61Addr VG_(client_mapbase);
62Addr VG_(client_trampoline_code);
63Addr VG_(clstk_base);
64Addr VG_(clstk_end);
rjwalsh0140af52005-06-04 20:42:33 +000065UWord VG_(clstk_id);
njn04e16982005-05-31 00:23:43 +000066
67Addr VG_(brk_base); /* start of brk */
68Addr VG_(brk_limit); /* current brk */
69
70Addr VG_(shadow_base); /* tool's shadow memory */
71Addr VG_(shadow_end);
72
73Addr VG_(valgrind_base); /* valgrind's address range */
74
75// Note that VG_(valgrind_last) names the last byte of the section, whereas
76// the VG_(*_end) vars name the byte one past the end of the section.
77Addr VG_(valgrind_last);
78
79/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000080/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000081/*--------------------------------------------------------------*/
82
sewardj79048ce2005-02-18 08:28:32 +000083/* Max number of segments we can track. */
84#define VG_N_SEGMENTS 1000
85
86/* Max number of segment file names we can track. */
87#define VG_N_SEGNAMES 200
88
89/* Max length of a segment file name. */
90#define VG_MAX_SEGNAMELEN 1000
91
92
93/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000094
95/* Array [0 .. segments_used-1] of all mappings. */
96/* Sorted by .addr field. */
97/* I: len may not be zero. */
98/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000099/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +0000100
101static Segment segments[VG_N_SEGMENTS];
102static Int segments_used = 0;
103
sewardj79048ce2005-02-18 08:28:32 +0000104typedef
105 struct {
106 Bool inUse;
107 Bool mark;
108 HChar fname[VG_MAX_SEGNAMELEN];
109 }
110 SegName;
111
112/* Filename table. _used is the high water mark; an entry is only
113 valid if its index >= 0, < _used, and its .inUse field == True.
114 The .mark field is used to garbage-collect dead entries.
115*/
116static SegName segnames[VG_N_SEGNAMES];
117static Int segnames_used = 0;
118
119
120/* ------ end of STATE for the address-space manager ------ */
121
122
123/* Searches the filename table to find an index for the given name.
124 If none is found, an index is allocated and the name stored. If no
125 space is available we just give up. If the string is too long to
126 store, return -1.
127*/
128static Int allocate_segname ( const HChar* name )
129{
130 Int i, j, len;
131
132 vg_assert(name);
133
134 if (0) VG_(printf)("alloc_segname %s\n", name);
135
136 len = VG_(strlen)(name);
137 if (len >= VG_MAX_SEGNAMELEN-1) {
138 return -1;
139 }
140
141 /* first see if we already have the name. */
142 for (i = 0; i < segnames_used; i++) {
143 if (!segnames[i].inUse)
144 continue;
145 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
146 return i;
147 }
148 }
149
150 /* no we don't. So look for a free slot. */
151 for (i = 0; i < segnames_used; i++)
152 if (!segnames[i].inUse)
153 break;
154
155 if (i == segnames_used) {
156 /* no free slots .. advance the high-water mark. */
157 if (segnames_used+1 < VG_N_SEGNAMES) {
158 i = segnames_used;
159 segnames_used++;
160 } else {
161 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000162 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000163 " VG_N_SEGNAMES is too small: "
164 "increase it and rebuild Valgrind.\n"
165 );
166 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000167 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000168 " giving up now.\n\n"
169 );
170 VG_(exit)(0);
171 }
172 }
173
174 /* copy it in */
175 segnames[i].inUse = True;
176 for (j = 0; j < len; j++)
177 segnames[i].fname[j] = name[j];
178 vg_assert(len < VG_MAX_SEGNAMELEN);
179 segnames[i].fname[len] = 0;
180 return i;
181}
182
sewardj548be6d2005-02-16 01:31:37 +0000183
184/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
185 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000186 seg.
187*/
sewardj548be6d2005-02-16 01:31:37 +0000188static Int compare_addr_with_seg ( Addr a, Segment* seg )
189{
190 if (a < seg->addr)
191 return -1;
192 if (a >= seg->addr + seg->len)
193 return 1;
194 return 0;
195}
196
sewardj79048ce2005-02-18 08:28:32 +0000197
sewardj548be6d2005-02-16 01:31:37 +0000198/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000199 none.
200*/
sewardj548be6d2005-02-16 01:31:37 +0000201static Int find_segment ( Addr a )
202{
203 Int i;
204 for (i = 0; i < segments_used; i++) {
205 if (compare_addr_with_seg(a, &segments[i]) == 0)
206 return i;
207 }
208 return -1;
209}
210
211
212/* Assumes that 'a' is not in any segment. Finds the index of the
213 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
214 which is in fact in a segment is a checked error.
215*/
216static Int find_segment_above_unmapped ( Addr a )
217{
218 Int i, r;
219 for (i = 0; i < segments_used; i++) {
220 r = compare_addr_with_seg(a, &segments[i]);
221 vg_assert(r != 0); /* 'a' should not be in any segment. */
222 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000223 continue;
sewardj548be6d2005-02-16 01:31:37 +0000224 vg_assert(r == -1);
225 break;
226 }
227
228 if (i == segments_used)
229 return -1; /* not found */
230 else
231 return i;
232}
233
234
235/* Assumes that 'a' is in some segment. Finds the next segment along,
236 or NULL if none. Passing 'a' which is in fact not in a segment is
237 a checked error.
238*/
239static Int find_segment_above_mapped ( Addr a )
240{
241 Int i, r;
242 for (i = 0; i < segments_used; i++) {
243 r = compare_addr_with_seg(a, &segments[i]);
244 if (r == 1)
245 continue; /* not yet there */
246 if (r == 0)
247 break; /* found it */
248 vg_assert(0);
249 /* we shouldn't get here -- r == -1 and so it means we went past
250 'a' without seeing it -- it is therefore unmapped. */
251 /*NOTREACHED*/
252 }
253
254 vg_assert(i < segments_used);
255 if (i == segments_used-1)
256 return -1; /* not found */
257 else
258 return i+1;
259}
260
261
262/* Shift segments[i .. segments_used-1] up by one. */
263static void make_space_at ( Int i )
264{
265 Int j;
266 vg_assert(i >= 0 && i <= segments_used);
267 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000268 if (segments_used+1 == VG_N_SEGMENTS) {
269 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000270 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000271 " VG_N_SEGMENTS is too small: "
272 "increase it and rebuild Valgrind.\n"
273 );
274 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000275 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000276 " giving up now.\n\n"
277 );
278 VG_(exit)(0);
279 }
sewardj548be6d2005-02-16 01:31:37 +0000280 vg_assert(segments_used+1 < VG_N_SEGMENTS);
281 for (j = segments_used; j > i; j--)
282 segments[j] = segments[j-1];
283 segments_used++;
284}
285
sewardj79048ce2005-02-18 08:28:32 +0000286
sewardj548be6d2005-02-16 01:31:37 +0000287/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000288 segments_used.
289*/
sewardj548be6d2005-02-16 01:31:37 +0000290static void delete_segment_at ( Int i )
291{
292 Int j;
293 vg_assert(i >= 0 && i < segments_used);
294 for (j = i+1; j < segments_used; j++)
295 segments[j-1] = segments[j];
296 segments_used--;
297 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
298}
299
300
301/* Fill the i'th record all with zeroes. */
302static void zeroise_segment ( Int i )
303{
304 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000305 segments[i].prot = 0;
306 segments[i].flags = 0;
307 segments[i].addr = 0;
308 segments[i].len = 0;
309 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000310 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000311 segments[i].fnIdx = -1;
312 segments[i].dev = 0;
313 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000314 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000315}
316
sewardj79048ce2005-02-18 08:28:32 +0000317
sewardj548be6d2005-02-16 01:31:37 +0000318/* Create a segment to contain 'a', and return its index. Or -1 if
319 this failed because some other segment already contains 'a'. If
320 successful, fill in the segment's .addr field with 'a' but leave
321 all other fields alone.
322*/
323static Int create_segment ( Addr a )
324{
325 Int i, r;
326 for (i = 0; i < segments_used; i++) {
327 r = compare_addr_with_seg( a, &segments[i] );
328 if (r == 1)
329 continue; /* seg[i] precedes a */
330 if (r == 0)
331 return -1; /* seg[i] contains a. Give up */
332 vg_assert(r == -1);
333 break;
334 }
335 /* a precedes seg[i]. Shift segs at i and above up one, and use
336 this slot. */
337 make_space_at(i);
338 zeroise_segment(i);
339 segments[i].addr = a;
340 return i;
341}
342
sewardj79048ce2005-02-18 08:28:32 +0000343
344/* Print out the segment array (debugging only!). Note, this calls
345 VG_(printf), and I'm not 100% clear that that wouldn't require
346 dynamic memory allocation and hence more segments to be allocated.
347*/
348static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000349{
sewardj79048ce2005-02-18 08:28:32 +0000350 Int i;
351 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
352 who, segments_used, segnames_used);
353 for (i = 0; i < segnames_used; i++) {
354 if (!segnames[i].inUse)
355 continue;
356 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
357 }
358 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000359 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000360 "%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 +0000361 i,
sewardj79048ce2005-02-18 08:28:32 +0000362 segments[i].addr, segments[i].addr + segments[i].len,
363 (ULong)segments[i].len, segments[i].prot,
364 segments[i].flags, segments[i].dev, segments[i].ino,
365 (Long)segments[i].offset,
366 segments[i].fnIdx);
367 }
368 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000369}
sewardj79048ce2005-02-18 08:28:32 +0000370
sewardj548be6d2005-02-16 01:31:37 +0000371
372/* Find the segment containing 'a' and split it into two pieces at
373 'a'. Does nothing if no segment contains 'a', or if the split
374 would cause either of the pieces to have zero size.
375
376 If 'a' is not found, or if no splitting happens, -1 is returned.
377
378 If a value 'r' other than -1 is returned, this is the index of the
379 higher-addressed segment resulting from the split, and the index of
380 the lower-addressed segment is r-1.
381*/
382static Int split_segment ( Addr a )
383{
384 Int r;
385 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000386 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000387 r = find_segment(a);
388 if (r == -1)
389 /* not found */
390 return -1;
391 if (segments[r].addr == a)
392 /* segment starts at 'a', so splitting it would create a
393 zero-sized segment */
394 return -1;
395
396 /* copy original; make adjustments. */
397 vg_assert(a > segments[r].addr);
398 delta = a - segments[r].addr;
399 make_space_at(r);
400 segments[r] = segments[r+1];
401 segments[r].len = delta;
402 segments[r+1].len -= delta;
403 segments[r+1].addr += delta;
404 segments[r+1].offset += delta;
405 return r+1;
406}
407
sewardj79048ce2005-02-18 08:28:32 +0000408
409/* Return true if two segments are adjacent and mergable (s1 is
410 assumed to have a lower ->addr than s2) */
411static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
412{
413 if (s1->addr+s1->len != s2->addr)
414 return False;
415
416 if (s1->flags != s2->flags)
417 return False;
418
419 if (s1->prot != s2->prot)
420 return False;
421
njn36ef6ba2005-05-14 18:42:26 +0000422 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000423 return False;
424
425 if (s1->flags & SF_FILE){
426 if ((s1->offset + s1->len) != s2->offset)
427 return False;
428 if (s1->dev != s2->dev)
429 return False;
430 if (s1->ino != s2->ino)
431 return False;
432 if (s1->fnIdx != s2->fnIdx)
433 return False;
434 }
435
436 return True;
437}
438
439
440/* Clean up and sanity check the segment array:
441 - check segments are in ascending order
442 - check segments do not overlap
443 - check no segment has zero size
444 - merge adjacent where possible
445 - perform checks on the filename table, and reclaim dead entries
446*/
447static void preen_segments ( void )
448{
449 Int i, j, rd, wr;
450 Segment *s, *s1;
451 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
452 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
453
454 if (0) show_segments("before preen");
455
456 /* clear string table mark bits */
457 for (i = 0; i < segnames_used; i++)
458 segnames[i].mark = False;
459
460 /* check for non-zero size, and set mark bits for any used strings */
461 for (i = 0; i < segments_used; i++) {
462 vg_assert(segments[i].len > 0);
463 j = segments[i].fnIdx;
464 vg_assert(j >= -1 && j < segnames_used);
465 if (j >= 0) {
466 vg_assert(segnames[j].inUse);
467 segnames[j].mark = True;
468 }
469 }
470
471 /* check ascendingness and non-overlap */
472 for (i = 0; i < segments_used-1; i++) {
473 s = &segments[i];
474 s1 = &segments[i+1];
475 vg_assert(s->addr < s1->addr);
476 vg_assert(s->addr + s->len <= s1->addr);
477 }
478
479 /* merge */
480 if (segments_used < 1)
481 return;
482
483 wr = 1;
484 for (rd = 1; rd < segments_used; rd++) {
485 s = &segments[wr-1];
486 s1 = &segments[rd];
487 if (segments_are_mergeable(s,s1)) {
488 if (0)
489 VG_(printf)("merge %p-%p with %p-%p\n",
490 s->addr, s->addr+s->len,
491 s1->addr, s1->addr+s1->len);
492 s->len += s1->len;
493 continue;
494 }
495 if (wr < rd)
496 segments[wr] = segments[rd];
497 wr++;
498 }
499 vg_assert(wr >= 0 && wr <= segments_used);
500 segments_used = wr;
501
502 /* Free up any strings which are no longer referenced. */
503 for (i = 0; i < segnames_used; i++) {
504 if (segnames[i].mark == False) {
505 segnames[i].inUse = False;
506 segnames[i].fname[0] = 0;
507 }
508 }
509
510 if (0) show_segments("after preen");
511}
512
513
sewardj548be6d2005-02-16 01:31:37 +0000514/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000515/*--- Maintain an ordered list of all the client's mappings ---*/
516/*--------------------------------------------------------------*/
517
nethercote8991d5a2004-11-03 17:07:46 +0000518Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000519{
520 Addr se = s->addr+s->len;
521 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000522 vg_assert(pe >= p);
523
524 return (p >= s->addr && pe <= se);
525}
526
nethercote8991d5a2004-11-03 17:07:46 +0000527Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000528{
529 Addr se = s->addr+s->len;
530 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000531 vg_assert(pe >= p);
532
533 return (p < se && pe > s->addr);
534}
535
sewardj1024cf72005-02-28 14:39:21 +0000536#if 0
537/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000538/* Prepare a Segment structure for recycling by freeing everything
539 hanging off it. */
540static void recycleseg(Segment *s)
541{
542 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000543 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000544
545 if (s->filename != NULL)
546 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
547
548 /* keep the SegInfo, if any - it probably still applies */
549}
550
551/* When freeing a Segment, also clean up every one else's ideas of
552 what was going on in that range of memory */
553static void freeseg(Segment *s)
554{
555 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000556 if (s->seginfo != NULL) {
557 VG_(seginfo_decref)(s->seginfo, s->addr);
558 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000559 }
560
561 VG_(SkipNode_Free)(&sk_segments, s);
562}
sewardj1024cf72005-02-28 14:39:21 +0000563#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000564
sewardj1024cf72005-02-28 14:39:21 +0000565
566/* Get rid of any translations arising from s. */
567/* Note, this is not really the job of the low level memory manager.
568 When it comes time to rewrite this subsystem, clean this up. */
569static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000570{
sewardj1024cf72005-02-28 14:39:21 +0000571 if (s->flags & SF_CODE) {
572 VG_(discard_translations)(s->addr, s->len);
573 if (0)
574 VG_(printf)("dumping translations in %p .. %p\n",
575 s->addr, s->addr+s->len);
576 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000577}
578
sewardj1024cf72005-02-28 14:39:21 +0000579
fitzhardinge98abfc72003-12-16 02:05:15 +0000580/* This unmaps all the segments in the range [addr, addr+len); any
581 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000582void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000583{
fitzhardingee3632c62003-12-22 10:58:06 +0000584 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000585 Segment* s;
586 Addr end, s_end;
587 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000588 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000589
590 if (len == 0)
591 return;
592
njn13bfd852005-06-02 03:52:53 +0000593 len = VG_PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000594
fitzhardinge98abfc72003-12-16 02:05:15 +0000595 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000596 VG_(printf)("unmap_range(%p, %llu)\n", addr, (ULong)len);
sewardj79048ce2005-02-18 08:28:32 +0000597 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000598 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000599
600 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000601 vg_assert(VG_IS_PAGE_ALIGNED(addr));
602 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000603
sewardj548be6d2005-02-16 01:31:37 +0000604 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000605
606 /* do not delete .. even though it looks stupid */
607 vg_assert(i >= 0);
608
609 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000610 s = &segments[i];
611 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000612
sewardj548be6d2005-02-16 01:31:37 +0000613 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000614 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000615 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000616
fitzhardinge1a303042003-12-22 08:48:50 +0000617 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000618 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000619 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000620 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000621 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000622
623 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000624 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000625 addr < s_end &&
626 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000627 /* this segment's tail is truncated by [addr, addr+len)
628 -> truncate tail
629 */
sewardj1024cf72005-02-28 14:39:21 +0000630 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000631 s->len = addr - s->addr;
632
633 if (debug)
tom9be7c982005-04-25 16:55:44 +0000634 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000635 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000636 /* this segment's head is truncated by [addr, addr+len)
637 -> truncate head
638 */
sewardj548be6d2005-02-16 01:31:37 +0000639 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000640
641 if (debug)
tom9be7c982005-04-25 16:55:44 +0000642 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000643 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000644
sewardj1024cf72005-02-28 14:39:21 +0000645 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000646 s->addr += delta;
647 s->offset += delta;
648 s->len -= delta;
649
650 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000651 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000652 /* this segment is completely contained within [addr, addr+len)
653 -> delete segment
654 */
sewardj1024cf72005-02-28 14:39:21 +0000655 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000656 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000657 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000658
659 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000660 VG_(printf)(" case 3: seg %d deleted\n", i);
661 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000662 /* [addr, addr+len) is contained within a single segment
663 -> split segment into 3, delete middle portion
664 */
sewardj1024cf72005-02-28 14:39:21 +0000665 Int i_middle;
666 dump_translations_from(s);
667 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000668 vg_assert(i_middle != -1);
669 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000670 vg_assert(segments[i_middle].addr == addr);
671 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000672 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000673
674 if (debug)
675 VG_(printf)(" case 4: subrange %p-%p deleted\n",
676 addr, addr+len);
677 }
sewardj47c98a72005-03-12 20:36:15 +0000678
679 /* If we deleted this segment (or any above), those above will
680 have been moved down to fill in the hole in the segment
681 array. In order that we don't miss them, we have to
682 re-consider this slot number; hence the i--. */
683 if (deleted)
684 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000685 }
sewardj79048ce2005-02-18 08:28:32 +0000686 preen_segments();
687 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000688}
689
sewardj548be6d2005-02-16 01:31:37 +0000690
691/* Add a binding of [addr,addr+len) to
692 (prot,flags,dev,ino,off,filename) in the segment array.
693 Delete/truncate any previous mapping(s) covering that range.
694*/
695void
696VG_(map_file_segment)( Addr addr, SizeT len,
697 UInt prot, UInt flags,
698 UInt dev, UInt ino, ULong off,
699 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000700{
fitzhardinge98abfc72003-12-16 02:05:15 +0000701 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000702 Segment* s;
703 Int idx;
sewardja8d8e232005-06-07 20:04:56 +0000704 HChar* stage2_suffix = "lib/valgrind/stage2";
705 Bool is_stage2 = VG_(strstr)(filename, stage2_suffix) != NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000706
707 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000708 VG_(printf)(
709 "\n"
tom9be7c982005-04-25 16:55:44 +0000710 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000711 " dev=0x%4x ino=%d off=%ld\n"
712 " filename='%s')\n",
713 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000714
sewardja8d8e232005-06-07 20:04:56 +0000715 if (0) show_segments("before map_file_segment");
716
fitzhardinge98abfc72003-12-16 02:05:15 +0000717 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000718 vg_assert(VG_IS_PAGE_ALIGNED(addr));
njn13bfd852005-06-02 03:52:53 +0000719 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000720
sewardj548be6d2005-02-16 01:31:37 +0000721 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
722 VG_(unmap_range)(addr, len);
723
724 /* and now install this one */
725 idx = create_segment(addr);
726 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
727 vg_assert(idx != -1);
728 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000729
sewardj79048ce2005-02-18 08:28:32 +0000730 s = &segments[idx];
731 vg_assert(s->addr == addr);
732 s->prot = prot;
733 s->flags = flags;
734 s->len = len;
735 s->offset = off;
736 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
737 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
738 s->dev = dev;
739 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000740 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000741
sewardj79048ce2005-02-18 08:28:32 +0000742 /* Clean up right now */
743 preen_segments();
744 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000745
746 /* If this mapping is of the beginning of a file, isn't part of
747 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000748 file, then try reading symbols from it.
749 */
njn36ef6ba2005-05-14 18:42:26 +0000750 if (s->seginfo == NULL
sewardja8d8e232005-06-07 20:04:56 +0000751 && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
752 || is_stage2
753 )
sewardj79048ce2005-02-18 08:28:32 +0000754 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
755 if (off == 0
756 && s->fnIdx != -1
757 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
758 && len >= VKI_PAGE_SIZE
759 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000760 s->seginfo = VG_(read_seg_symbols)(s);
761 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000762 s->flags |= SF_DYNLIB;
763 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000764 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000765#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000766 const SegInfo *info;
767
njn36ef6ba2005-05-14 18:42:26 +0000768 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000769 for(info = VG_(next_seginfo)(NULL);
770 info != NULL;
771 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000772 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
773 {
njn36ef6ba2005-05-14 18:42:26 +0000774 s->seginfo = (SegInfo *)info;
775 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000776 }
777 }
sewardj79048ce2005-02-18 08:28:32 +0000778#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000779 }
780 }
781
782 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000783 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000784}
785
nethercote8b5f40c2004-11-02 13:29:50 +0000786void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000787 Int fd, ULong off, const Char *filename)
788{
789 struct vki_stat st;
790 Char *name = NULL;
791
792 st.st_dev = 0;
793 st.st_ino = 0;
794
795 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000796 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000797
798 if (VG_(fstat)(fd, &st) < 0)
799 flags &= ~SF_FILE;
800 }
801
sewardj79048ce2005-02-18 08:28:32 +0000802 if ((flags & SF_FILE) && filename == NULL && fd != -1)
803 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000804
805 if (filename == NULL)
806 filename = name;
807
sewardj79048ce2005-02-18 08:28:32 +0000808 VG_(map_file_segment)(addr, len, prot, flags,
809 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000810}
811
nethercote8b5f40c2004-11-02 13:29:50 +0000812void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000813{
814 flags &= ~SF_FILE;
815
816 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
817}
818
819/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000820void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000821{
sewardj79048ce2005-02-18 08:28:32 +0000822 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000823 static const Bool debug = False || mem_debug;
824
825 if (debug)
tom9be7c982005-04-25 16:55:44 +0000826 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000827
828 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000829
830 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000831 vg_assert(VG_IS_PAGE_ALIGNED(a));
njn13bfd852005-06-02 03:52:53 +0000832 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000833
sewardj79048ce2005-02-18 08:28:32 +0000834 split_segment(a);
835 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000836
sewardj548be6d2005-02-16 01:31:37 +0000837 r = find_segment(a);
838 vg_assert(r != -1);
839 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000840
841 preen_segments();
842
sewardje517b802005-02-16 01:58:51 +0000843 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000844}
845
sewardj79048ce2005-02-18 08:28:32 +0000846
sewardj548be6d2005-02-16 01:31:37 +0000847/* Try to find a map space for [addr,addr+len). If addr==0, it means
848 the caller is prepared to accept a space at any location; if not,
849 we will try for addr, but fail if we can't get it. This mimics
850 mmap fixed vs mmap not-fixed.
851*/
nethercote8b5f40c2004-11-02 13:29:50 +0000852Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000853{
fitzhardingee3632c62003-12-22 10:58:06 +0000854 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000855 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000856 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000857 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
858 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000859 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
860 Int i, i_any, i_fixed, i_final;
861 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000862
sewardj548be6d2005-02-16 01:31:37 +0000863 Bool fixed;
864
sewardje517b802005-02-16 01:58:51 +0000865 if (debug) {
866 VG_(printf)("\n\n");
sewardja8d8e232005-06-07 20:04:56 +0000867 VG_(printf)("find_map_space(%p, %llu, %d) ...\n",
868 addr, (ULong)len, for_client);
sewardje517b802005-02-16 01:58:51 +0000869 }
870
871 if (0) show_segments("find_map_space: start");
872
sewardj548be6d2005-02-16 01:31:37 +0000873 if (addr == 0) {
874 fixed = False;
875 } else {
876 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000877 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000878 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000879 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000880 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000881
882 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000883 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
njn13bfd852005-06-02 03:52:53 +0000884 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000885
nethercote73b526f2004-10-31 18:48:21 +0000886 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000887
sewardj548be6d2005-02-16 01:31:37 +0000888 /* Scan the segment list, looking for a hole which satisfies the
889 requirements. At each point i we ask the question "can we use
890 the hole in between segments[i-1] and segments[i] ?" */
891 i_any = i_fixed = -1;
892 hstart_any = hstart_fixed = 0;
893
894 hole_start = hole_end = 0;
895
896 /* Iterate over all possible holes, generating them into
897 hole_start/hole_end. Filter out invalid ones. Then see if any
898 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
899 */
900 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
901 if (i == 0) {
902 hole_start = 0;
903 hole_end = segments[0].addr-1;
904 }
905 else {
906 vg_assert(segments_used > 0);
907 if (i == segments_used) {
908 hole_start = segments[i-1].addr + segments[i-1].len;
909 hole_end = ~(Addr)0;
910 } else {
911 hole_start = segments[i-1].addr + segments[i-1].len;
912 hole_end = segments[i].addr - 1;
913 }
914 }
915
916 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
917
918 /* ignore zero-sized holes */
919 if (hole_start == hole_end+1)
920 continue;
921
njnbe91aae2005-03-27 01:42:41 +0000922 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
923 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000924
925 /* ignore holes which fall outside the allowable area */
926 if (!(hole_start >= base && hole_end <= limit))
927 continue;
928
929 vg_assert(hole_end > hole_start);
930 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000931 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000932
933 if (hole_len >= len && i_any == -1) {
934 /* It will at least fit in this hole. */
935 i_any = i;
936 hstart_any = hole_start;
937 }
938
sewardjb5f6f512005-03-10 23:59:00 +0000939 if (fixed && hole_start <= addr
940 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000941 /* We were asked for a fixed mapping, and this hole works.
942 Bag it -- and stop searching as further searching is
943 pointless. */
944 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000945 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000946 break;
947 }
948 }
949
950 /* Summarise the final decision into i_final/hstart_final. */
951 i_final = -1;
952 hstart_final = 0;
953
954 if (fixed) {
955 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000956 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000957 } else {
958 i_final = i_any;
959 hstart_final = hstart_any;
960 }
961
962
963 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000964 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000965 else
966 ret = 0; /* not found */
967
968 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000969 VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n",
970 addr, (ULong)len, for_client, ret);
sewardj548be6d2005-02-16 01:31:37 +0000971
sewardjb5f6f512005-03-10 23:59:00 +0000972 if (fixed) {
973 vg_assert(ret == 0 || ret == addrOrig);
974 }
975
sewardj548be6d2005-02-16 01:31:37 +0000976 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000977}
978
sewardj79048ce2005-02-18 08:28:32 +0000979
sewardjb5f6f512005-03-10 23:59:00 +0000980/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000981 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000982 mapping over any part of the address space which is not covered
983 by an entry in the segment list.
984
985 This is designed for use around system calls which allocate
986 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000987 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000988 address with VG_(find_map_space) and then adding a segment for
989 it and padding the address space valgrind can ensure that the
990 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000991void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000992{
sewardj394790d2005-03-17 02:14:44 +0000993 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +0000994 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +0000995
996 Int i = 0;
997 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000998
nethercote820bd8c2004-09-07 23:04:49 +0000999 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001000 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +00001001 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +00001002 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1003 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001004 }
thughes9aaebc32004-07-15 23:13:37 +00001005 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001006 i++;
1007 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001008 }
1009
nethercote820bd8c2004-09-07 23:04:49 +00001010 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001011 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001012 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1013 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001014 }
thughes9aaebc32004-07-15 23:13:37 +00001015}
1016
thughesc70b8c62004-07-16 23:07:58 +00001017/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001018 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001019void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001020{
sewardj394790d2005-03-17 02:14:44 +00001021 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001022 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001023
1024 Int i = 0;
1025 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001026
nethercote820bd8c2004-09-07 23:04:49 +00001027 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001028 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +00001029 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001030 }
thughes9aaebc32004-07-15 23:13:37 +00001031 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001032 i++;
1033 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001034 }
1035
nethercote820bd8c2004-09-07 23:04:49 +00001036 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001037 ret = VG_(do_syscall2)(__NR_munmap, addr,
1038 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001039 }
thughes9aaebc32004-07-15 23:13:37 +00001040}
1041
sewardj548be6d2005-02-16 01:31:37 +00001042/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001043Segment *VG_(find_segment)(Addr a)
1044{
sewardj548be6d2005-02-16 01:31:37 +00001045 Int r = find_segment(a);
1046 if (0) show_segments("find_segment");
1047 if (r == -1) return NULL;
1048 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001049}
1050
sewardj548be6d2005-02-16 01:31:37 +00001051/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1052 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1053 a segment is a checked error.
1054*/
1055Segment *VG_(find_segment_above_unmapped)(Addr a)
1056{
1057 Int r = find_segment_above_unmapped(a);
1058 if (0) show_segments("find_segment_above_unmapped");
1059 if (r == -1) return NULL;
1060 return &segments[r];
1061}
1062
1063/* Assumes that 'a' is in some segment. Finds the next segment along,
1064 or NULL if none. Passing 'a' which is in fact not in a segment is
1065 a checked error.
1066*/
1067Segment *VG_(find_segment_above_mapped)(Addr a)
1068{
1069 Int r = find_segment_above_mapped(a);
1070 if (0) show_segments("find_segment_above_mapped");
1071 if (r == -1) return NULL;
1072 return &segments[r];
1073}
1074
1075
sewardjde4a1d02002-03-22 01:27:54 +00001076/*------------------------------------------------------------*/
1077/*--- Tracking permissions around %esp changes. ---*/
1078/*------------------------------------------------------------*/
1079
1080/*
1081 The stack
1082 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001083 The stack's segment seems to be dynamically extended downwards by
1084 the kernel as the stack pointer moves down. Initially, a 1-page
1085 (4k) stack is allocated. When SP moves below that for the first
1086 time, presumably a page fault occurs. The kernel detects that the
njna60a7c12005-05-08 17:49:37 +00001087 faulting address is in the range from SP - VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001088 upwards to the current valid stack. It then extends the stack
1089 segment downwards for enough to cover the faulting address, and
1090 resumes the process (invisibly). The process is unaware of any of
1091 this.
sewardjde4a1d02002-03-22 01:27:54 +00001092
sewardjfa8202f2005-04-24 11:05:55 +00001093 That means that Valgrind can't spot when the stack segment is being
1094 extended. Fortunately, we want to precisely and continuously
1095 update stack permissions around SP, so we need to spot all writes
1096 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001097
sewardjfa8202f2005-04-24 11:05:55 +00001098 The deal is: when SP is assigned a lower value, the stack is being
1099 extended. Create suitably-permissioned pages to fill in any holes
1100 between the old stack ptr and this one, if necessary. Then mark
1101 all bytes in the area just "uncovered" by this SP change as
1102 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001103
sewardjfa8202f2005-04-24 11:05:55 +00001104 When SP goes back up, mark the area receded over as unreadable and
1105 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001106
njna60a7c12005-05-08 17:49:37 +00001107 Just to record the SP boundary conditions somewhere convenient:
1108 SP - VGA_STACK_REDZONE_SZB always points to the lowest live byte in
1109 the stack. All addresses below SP - VGA_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001110 live; those at and above it are.
1111
njna60a7c12005-05-08 17:49:37 +00001112 We do not concern ourselves here with the VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001113 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001114*/
1115
rjwalsh0140af52005-06-04 20:42:33 +00001116/*
1117 * This structure holds information about the start and end addresses of
1118 * registered stacks. There's always at least one stack registered:
1119 * the main process stack. It will be the first stack registered and
1120 * so will have a stack id of 0. The user does not need to register
1121 * this stack: Valgrind does it automatically right before it starts
1122 * running the client. No other stacks are automatically registered by
1123 * Valgrind, however.
1124 */
1125
1126typedef struct _Stack {
1127 UWord id;
1128 Addr start;
1129 Addr end;
1130 struct _Stack *next;
1131} Stack;
1132
1133static Stack *stacks;
1134static UWord next_id; /* Next id we hand out to a newly registered stack */
1135
1136/*
1137 * These are the id, start and end values of the current stack. If the
1138 * stack pointer falls outside the range of the current stack, we search
1139 * the stacks list above for a matching stack.
1140 */
1141
1142static Addr current_stack_start;
1143static Addr current_stack_end;
1144static UWord current_stack_id;
1145
1146/* Search for a particular stack by id number. */
1147static Bool find_stack_by_id(UWord id, Addr *start, Addr *end)
1148{
1149 Stack *i = stacks;
1150 while(i) {
1151 if(i->id == id) {
1152 *start = i->start;
1153 *end = i->end;
1154 return True;
1155 }
1156 i = i->next;
1157 }
1158 return False;
1159}
1160
1161/* Find what stack an address falls into. */
1162static Bool find_stack_by_addr(Addr sp, Addr *start, Addr *end, UWord *id)
1163{
1164 Stack *i = stacks;
1165 while(i) {
1166 if(sp >= i->start && sp <= i->end) {
1167 *start = i->start;
1168 *end = i->end;
1169 *id = i->id;
1170 return True;
1171 }
1172 i = i->next;
1173 }
1174 return False;
1175}
1176
1177/* Change over to a new stack. */
1178static Bool set_current_stack(UWord id)
1179{
1180 Addr start, end;
1181 if (find_stack_by_id(id, &start, &end)) {
1182 current_stack_id = id;
1183 current_stack_start = start;
1184 current_stack_end = end;
1185 return True;
1186 }
1187 return False;
1188}
1189
1190/*
1191 * Register a new stack from start - end. This is invoked from the
1192 * VALGRIND_STACK_REGISTER client request, and is also called just before
1193 * we start the client running, to register the main process stack.
1194 *
1195 * Note: this requires allocating a piece of memory to store the Stack
1196 * structure, which places a dependency between this module and the
1197 * mallocfree module. However, there is no real chance of a circular
1198 * dependency here, since the mallocfree module would never call back to
1199 * this function.
1200 */
1201
1202UWord VG_(handle_stack_register)(Addr start, Addr end)
1203{
1204 Stack *i;
1205 if (start > end) {
1206 Addr t = end;
1207 end = start;
1208 start = t;
1209 }
1210
1211 i = (Stack *)VG_(arena_malloc)(VG_AR_CORE, sizeof(Stack));
1212 i->start = start;
1213 i->end = end;
1214 i->id = next_id++;
1215 i->next = stacks;
1216 stacks = i;
1217
1218 if(i->id == 0) {
1219 set_current_stack(i->id);
1220 }
1221
1222 return i->id;
1223}
1224
1225/*
1226 * Deregister a stack. This is invoked from the VALGRIND_STACK_DEREGISTER
1227 * client request.
1228 *
1229 * Note: this requires freeing the piece of memory that was used to store
1230 * the Stack structure, which places a dependency between this module
1231 * and the mallocfree module. However, there is no real chance of
1232 * a circular dependency here, since the mallocfree module would never
1233 * call back to this function.
1234 */
1235
1236void VG_(handle_stack_deregister)(UWord id)
1237{
1238 Stack *i = stacks;
1239 Stack *prev = NULL;
1240
1241 if(current_stack_id == id) {
1242 return;
1243 }
1244
1245 while(i) {
1246 if (i->id == id) {
1247 if(prev == NULL) {
1248 stacks = i->next;
1249 } else {
1250 prev->next = i->next;
1251 }
1252 VG_(arena_free)(VG_AR_CORE, i);
1253 return;
1254 }
1255 prev = i;
1256 i = i->next;
1257 }
1258}
1259
1260/*
1261 * Change a stack. This is invoked from the VALGRIND_STACK_CHANGE client
1262 * request and from the stack growth stuff the signals module when
1263 * extending the main process stack.
1264 */
1265
1266void VG_(handle_stack_change)(UWord id, Addr start, Addr end)
1267{
1268 Stack *i = stacks;
1269
1270 if (id == current_stack_id) {
1271 current_stack_start = start;
1272 current_stack_end = end;
1273 }
1274
1275 while(i) {
1276 if (i->id == id) {
1277 i->start = start;
1278 i->end = end;
1279 return;
1280 }
1281 i = i->next;
1282 }
1283}
1284
njn9b007f62003-04-07 14:40:25 +00001285/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001286 tracked by the tool, and one of the specialised cases
1287 (eg. new_mem_stack_4) isn't used in preference.
1288*/
njn9fb73db2005-03-27 01:55:21 +00001289VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001290void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001291{
sewardj97724e52005-04-02 23:40:59 +00001292 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001293 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001294
rjwalsh0140af52005-06-04 20:42:33 +00001295 /* Check if the stack pointer is still in the same stack as before. */
1296 if (new_SP < current_stack_start || new_SP > current_stack_end) {
1297 Addr start, end;
1298 UWord new_id;
1299 Bool found = find_stack_by_addr(new_SP, &start, &end, &new_id);
1300 if (found && new_id != current_stack_id) {
1301 /* The stack pointer is now in another stack. Update the current
1302 stack information and return without doing anything else. */
1303 set_current_stack(new_id);
1304 return;
1305 }
1306 }
1307
sewardj97724e52005-04-02 23:40:59 +00001308 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1309 /* SP has changed by more than some threshold amount (by
1310 default, 2MB). We take this to mean that the application is
1311 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001312
1313 JRS 20021001: following discussions with John Regehr, if a stack
1314 switch happens, it seems best not to mess at all with memory
1315 permissions. Seems to work well with Netscape 4.X. Really the
1316 only remaining difficulty is knowing exactly when a stack switch is
1317 happening. */
sewardj97724e52005-04-02 23:40:59 +00001318 if (VG_(clo_verbosity) > 0 && moans > 0) {
1319 moans--;
1320 VG_(message)(Vg_UserMsg,
1321 "Warning: client switching stacks? "
1322 "SP change: %p --> %p", old_SP, new_SP);
1323 VG_(message)(Vg_UserMsg,
1324 " to suppress, use: --max-stackframe=%d or greater",
1325 (delta < 0 ? -delta : delta));
1326 if (moans == 0)
1327 VG_(message)(Vg_UserMsg,
1328 " further instances of this message "
1329 "will not be shown.");
1330 }
njn9b007f62003-04-07 14:40:25 +00001331 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001332 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001333
njn9b007f62003-04-07 14:40:25 +00001334 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001335 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001336 }
1337}
1338
jsgf855d93d2003-10-13 22:26:55 +00001339/*
sewardjb5f6f512005-03-10 23:59:00 +00001340 Test if a piece of memory is addressable with at least the "prot"
1341 protection permissions by examining the underlying segments.
1342
1343 Really this is a very stupid algorithm and we could do much
1344 better by iterating through the segment array instead of through
1345 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001346 */
sewardjb5f6f512005-03-10 23:59:00 +00001347Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001348{
sewardjb5f6f512005-03-10 23:59:00 +00001349 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001350
sewardjb5f6f512005-03-10 23:59:00 +00001351 if ((p + size) < p)
1352 return False; /* reject wraparounds */
1353 if (size == 0)
1354 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001355
njn13bfd852005-06-02 03:52:53 +00001356 p = VG_PGROUNDDN(p);
1357 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001358 vg_assert(VG_IS_PAGE_ALIGNED(p));
1359 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001360
sewardjb5f6f512005-03-10 23:59:00 +00001361 for (; size > 0; size -= VKI_PAGE_SIZE) {
1362 seg = VG_(find_segment)(p);
1363 if (!seg)
1364 return False;
1365 if ((seg->prot & prot) != prot)
1366 return False;
1367 p += VKI_PAGE_SIZE;
1368 }
jsgf855d93d2003-10-13 22:26:55 +00001369
sewardjb5f6f512005-03-10 23:59:00 +00001370 return True;
jsgf855d93d2003-10-13 22:26:55 +00001371}
1372
sewardjb5f6f512005-03-10 23:59:00 +00001373
sewardjde4a1d02002-03-22 01:27:54 +00001374/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +00001375/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001376/*--------------------------------------------------------------------*/
1377
nethercote57e36b32004-07-10 14:56:28 +00001378// Returns 0 on failure.
sewardj215776c2005-03-16 12:11:12 +00001379Addr VG_(get_memory_from_mmap_for_client)
1380 (Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +00001381{
njn13bfd852005-06-02 03:52:53 +00001382 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +00001383
njnca82cc02004-11-22 17:18:48 +00001384 tl_assert(!(sf_flags & SF_FIXED));
1385 tl_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001386
nethercote8e9eab02004-07-11 18:01:06 +00001387 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
1388 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
1389 sf_flags | SF_CORE, -1, 0);
1390 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00001391 return addr;
nethercote8e9eab02004-07-11 18:01:06 +00001392 else
1393 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001394}
1395
fitzhardinge98abfc72003-12-16 02:05:15 +00001396
njn86f12dc2005-03-14 01:16:05 +00001397/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001398 range, which isn't SF_CORE, a root.
1399*/
njn86f12dc2005-03-14 01:16:05 +00001400void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1401{
sewardj882af5f2005-03-16 12:27:53 +00001402 Int i;
1403 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001404 Segment *s;
1405
sewardj882af5f2005-03-16 12:27:53 +00001406 for (i = 0; i < segments_used; i++) {
1407 s = &segments[i];
1408 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1409 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001410 if (flags != SF_MMAP && flags != SF_STACK)
1411 continue;
sewardj882af5f2005-03-16 12:27:53 +00001412 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1413 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001414 continue;
1415 if (!VG_(is_client_addr)(s->addr) ||
1416 !VG_(is_client_addr)(s->addr+s->len))
1417 continue;
1418
1419 (*add_rootrange)(s->addr, s->len);
1420 }
njn86f12dc2005-03-14 01:16:05 +00001421}
1422
1423
nethercote88a90162004-07-10 16:59:25 +00001424/*--------------------------------------------------------------------*/
1425/*--- Querying memory layout ---*/
1426/*--------------------------------------------------------------------*/
1427
fitzhardinge98abfc72003-12-16 02:05:15 +00001428Bool VG_(is_client_addr)(Addr a)
1429{
1430 return a >= VG_(client_base) && a < VG_(client_end);
1431}
1432
1433Bool VG_(is_shadow_addr)(Addr a)
1434{
1435 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1436}
1437
fitzhardinge98abfc72003-12-16 02:05:15 +00001438Addr VG_(get_shadow_size)(void)
1439{
1440 return VG_(shadow_end)-VG_(shadow_base);
1441}
1442
sewardjfa8202f2005-04-24 11:05:55 +00001443
nethercote88a90162004-07-10 16:59:25 +00001444/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001445/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001446/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001447
1448void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1449{
sewardj548be6d2005-02-16 01:31:37 +00001450vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001451 if (0)
1452 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1453
1454 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001455 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001456
njn13bfd852005-06-02 03:52:53 +00001457 sz = VG_PGROUNDUP(p+sz) - VG_PGROUNDDN(p);
1458 p = VG_PGROUNDDN(p);
fitzhardinge98abfc72003-12-16 02:05:15 +00001459
1460 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1461
1462 if (call_init)
1463 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001464 /* ask the tool to initialize each page */
njn13bfd852005-06-02 03:52:53 +00001465 VG_TRACK( init_shadow_page, VG_PGROUNDDN(p) );
fitzhardinge98abfc72003-12-16 02:05:15 +00001466
nethercote73b526f2004-10-31 18:48:21 +00001467 p += VKI_PAGE_SIZE;
1468 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001469 }
1470}
1471
1472void *VG_(shadow_alloc)(UInt size)
1473{
1474 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001475 Addr try_here;
njne9befc62005-06-11 15:51:30 +00001476 SysRes r;
sewardj79048ce2005-02-18 08:28:32 +00001477
1478 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001479
1480 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001481 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001482
njn13bfd852005-06-02 03:52:53 +00001483 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001484
1485 if (shadow_alloc == 0)
1486 shadow_alloc = VG_(shadow_base);
1487
1488 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001489 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001490
sewardj79048ce2005-02-18 08:28:32 +00001491 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001492 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1493 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001494 vg_assert(size > 0);
1495
1496 if (0)
1497 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1498
1499 /* this is big-bang allocated, so we don't expect to find a listed
1500 segment for it. */
1501 /* This is really an absolute disgrace. Sometimes the big-bang
1502 mapping is in the list (due to re-reads of /proc/self/maps,
1503 presumably) and sometimes it isn't. */
1504#if 0
1505 r = find_segment(try_here);
1506 vg_assert(r == -1);
1507 r = find_segment(try_here+size-1);
1508 vg_assert(r == -1);
1509#endif
1510
1511 r = VG_(mprotect_native)( (void*)try_here,
1512 size, VKI_PROT_READ|VKI_PROT_WRITE );
1513
njne9befc62005-06-11 15:51:30 +00001514 if (r.isError)
sewardj79048ce2005-02-18 08:28:32 +00001515 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001516
1517 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001518 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001519
sewardj79048ce2005-02-18 08:28:32 +00001520 failed:
1521 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001522 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001523 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001524 size
sewardj79048ce2005-02-18 08:28:32 +00001525 );
1526 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001527}
1528
njne3f06352005-06-01 03:48:33 +00001529/*------------------------------------------------------------*/
1530/*--- pointercheck ---*/
1531/*------------------------------------------------------------*/
1532
1533Bool VGA_(setup_pointercheck)(Addr client_base, Addr client_end)
1534{
1535 vg_assert(0 != client_end);
1536#if defined(VGP_x86_linux)
1537 /* Client address space segment limit descriptor entry */
1538 #define POINTERCHECK_SEGIDX 1
1539
1540 vki_modify_ldt_t ldt = {
1541 POINTERCHECK_SEGIDX, // entry_number
1542 client_base, // base_addr
1543 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1544 1, // seg_32bit
1545 0, // contents: data, RW, non-expanding
1546 0, // ! read_exec_only
1547 1, // limit_in_pages
1548 0, // ! seg not present
1549 1, // useable
1550 };
sewardja8d8e232005-06-07 20:04:56 +00001551 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1552 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001553 VG_(message)(Vg_UserMsg,
1554 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001555 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001556 return False;
1557 } else {
1558 return True;
1559 }
1560#elif defined(VGP_amd64_linux)
1561 if (0)
1562 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1563 return True;
1564#else
1565# error Unknown architecture
1566#endif
1567}
1568
fitzhardinge98abfc72003-12-16 02:05:15 +00001569/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001570/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001571/*--------------------------------------------------------------------*/