blob: 3a88b953ebf6405c6eb04860b41094319ac6fb68 [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
njnc7561b92005-06-19 01:24:32 +000033#include "pub_core_basics.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"
njn67741c62005-06-20 02:23:07 +000037#include "pub_core_libcfile.h" // For VG_(fstat), VG_(resolve_filename_nodup)
njne9befc62005-06-11 15:51:30 +000038#include "pub_core_libcmman.h"
njn36a20fa2005-06-03 03:08:39 +000039#include "pub_core_libcprint.h"
njnaf1d7df2005-06-11 01:31:52 +000040#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000041#include "pub_core_options.h"
njn9abd6082005-06-17 21:31:45 +000042#include "pub_core_syscall.h"
njn43b9a8a2005-05-10 04:37:01 +000043#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000044#include "pub_core_transtab.h"
njn3c660b62005-05-13 22:18:47 +000045#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000046
sewardjde4a1d02002-03-22 01:27:54 +000047
sewardja4495682002-10-21 07:29:59 +000048/* Define to debug the memory-leak-detector. */
49/* #define VG_DEBUG_LEAKCHECK */
50
sewardje517b802005-02-16 01:58:51 +000051static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000052
53/*--------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +000054/*--- Basic globals about the address space. ---*/
55/*--------------------------------------------------------------*/
56
57/* Client address space, lowest to highest (see top of ume.c) */
58Addr VG_(client_base); /* client address space limits */
59Addr VG_(client_end);
60Addr VG_(client_mapbase);
njn04e16982005-05-31 00:23:43 +000061Addr VG_(clstk_base);
62Addr VG_(clstk_end);
rjwalsh0140af52005-06-04 20:42:33 +000063UWord VG_(clstk_id);
njn04e16982005-05-31 00:23:43 +000064
65Addr VG_(brk_base); /* start of brk */
66Addr VG_(brk_limit); /* current brk */
67
68Addr VG_(shadow_base); /* tool's shadow memory */
69Addr VG_(shadow_end);
70
71Addr VG_(valgrind_base); /* valgrind's address range */
72
73// Note that VG_(valgrind_last) names the last byte of the section, whereas
74// the VG_(*_end) vars name the byte one past the end of the section.
75Addr VG_(valgrind_last);
76
77/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000078/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000079/*--------------------------------------------------------------*/
80
sewardj79048ce2005-02-18 08:28:32 +000081/* Max number of segments we can track. */
82#define VG_N_SEGMENTS 1000
83
84/* Max number of segment file names we can track. */
85#define VG_N_SEGNAMES 200
86
87/* Max length of a segment file name. */
88#define VG_MAX_SEGNAMELEN 1000
89
90
91/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000092
93/* Array [0 .. segments_used-1] of all mappings. */
94/* Sorted by .addr field. */
95/* I: len may not be zero. */
96/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000097/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000098
99static Segment segments[VG_N_SEGMENTS];
100static Int segments_used = 0;
101
sewardj79048ce2005-02-18 08:28:32 +0000102typedef
103 struct {
104 Bool inUse;
105 Bool mark;
106 HChar fname[VG_MAX_SEGNAMELEN];
107 }
108 SegName;
109
110/* Filename table. _used is the high water mark; an entry is only
111 valid if its index >= 0, < _used, and its .inUse field == True.
112 The .mark field is used to garbage-collect dead entries.
113*/
114static SegName segnames[VG_N_SEGNAMES];
115static Int segnames_used = 0;
116
117
118/* ------ end of STATE for the address-space manager ------ */
119
120
121/* Searches the filename table to find an index for the given name.
122 If none is found, an index is allocated and the name stored. If no
123 space is available we just give up. If the string is too long to
124 store, return -1.
125*/
126static Int allocate_segname ( const HChar* name )
127{
128 Int i, j, len;
129
130 vg_assert(name);
131
132 if (0) VG_(printf)("alloc_segname %s\n", name);
133
134 len = VG_(strlen)(name);
135 if (len >= VG_MAX_SEGNAMELEN-1) {
136 return -1;
137 }
138
139 /* first see if we already have the name. */
140 for (i = 0; i < segnames_used; i++) {
141 if (!segnames[i].inUse)
142 continue;
143 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
144 return i;
145 }
146 }
147
148 /* no we don't. So look for a free slot. */
149 for (i = 0; i < segnames_used; i++)
150 if (!segnames[i].inUse)
151 break;
152
153 if (i == segnames_used) {
154 /* no free slots .. advance the high-water mark. */
155 if (segnames_used+1 < VG_N_SEGNAMES) {
156 i = segnames_used;
157 segnames_used++;
158 } else {
159 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000160 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000161 " VG_N_SEGNAMES is too small: "
162 "increase it and rebuild Valgrind.\n"
163 );
164 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000165 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000166 " giving up now.\n\n"
167 );
168 VG_(exit)(0);
169 }
170 }
171
172 /* copy it in */
173 segnames[i].inUse = True;
174 for (j = 0; j < len; j++)
175 segnames[i].fname[j] = name[j];
176 vg_assert(len < VG_MAX_SEGNAMELEN);
177 segnames[i].fname[len] = 0;
178 return i;
179}
180
sewardj548be6d2005-02-16 01:31:37 +0000181
182/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
183 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000184 seg.
185*/
sewardj548be6d2005-02-16 01:31:37 +0000186static Int compare_addr_with_seg ( Addr a, Segment* seg )
187{
188 if (a < seg->addr)
189 return -1;
190 if (a >= seg->addr + seg->len)
191 return 1;
192 return 0;
193}
194
sewardj79048ce2005-02-18 08:28:32 +0000195
sewardj548be6d2005-02-16 01:31:37 +0000196/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000197 none.
198*/
sewardj548be6d2005-02-16 01:31:37 +0000199static Int find_segment ( Addr a )
200{
201 Int i;
202 for (i = 0; i < segments_used; i++) {
203 if (compare_addr_with_seg(a, &segments[i]) == 0)
204 return i;
205 }
206 return -1;
207}
208
209
210/* Assumes that 'a' is not in any segment. Finds the index of the
211 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
212 which is in fact in a segment is a checked error.
213*/
214static Int find_segment_above_unmapped ( Addr a )
215{
216 Int i, r;
217 for (i = 0; i < segments_used; i++) {
218 r = compare_addr_with_seg(a, &segments[i]);
219 vg_assert(r != 0); /* 'a' should not be in any segment. */
220 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000221 continue;
sewardj548be6d2005-02-16 01:31:37 +0000222 vg_assert(r == -1);
223 break;
224 }
225
226 if (i == segments_used)
227 return -1; /* not found */
228 else
229 return i;
230}
231
232
233/* Assumes that 'a' is in some segment. Finds the next segment along,
234 or NULL if none. Passing 'a' which is in fact not in a segment is
235 a checked error.
236*/
237static Int find_segment_above_mapped ( Addr a )
238{
239 Int i, r;
240 for (i = 0; i < segments_used; i++) {
241 r = compare_addr_with_seg(a, &segments[i]);
242 if (r == 1)
243 continue; /* not yet there */
244 if (r == 0)
245 break; /* found it */
246 vg_assert(0);
247 /* we shouldn't get here -- r == -1 and so it means we went past
248 'a' without seeing it -- it is therefore unmapped. */
249 /*NOTREACHED*/
250 }
251
252 vg_assert(i < segments_used);
253 if (i == segments_used-1)
254 return -1; /* not found */
255 else
256 return i+1;
257}
258
259
260/* Shift segments[i .. segments_used-1] up by one. */
261static void make_space_at ( Int i )
262{
263 Int j;
264 vg_assert(i >= 0 && i <= segments_used);
265 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000266 if (segments_used+1 == VG_N_SEGMENTS) {
267 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000268 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000269 " VG_N_SEGMENTS is too small: "
270 "increase it and rebuild Valgrind.\n"
271 );
272 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000273 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000274 " giving up now.\n\n"
275 );
276 VG_(exit)(0);
277 }
sewardj548be6d2005-02-16 01:31:37 +0000278 vg_assert(segments_used+1 < VG_N_SEGMENTS);
279 for (j = segments_used; j > i; j--)
280 segments[j] = segments[j-1];
281 segments_used++;
282}
283
sewardj79048ce2005-02-18 08:28:32 +0000284
sewardj548be6d2005-02-16 01:31:37 +0000285/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000286 segments_used.
287*/
sewardj548be6d2005-02-16 01:31:37 +0000288static void delete_segment_at ( Int i )
289{
290 Int j;
291 vg_assert(i >= 0 && i < segments_used);
292 for (j = i+1; j < segments_used; j++)
293 segments[j-1] = segments[j];
294 segments_used--;
295 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
296}
297
298
299/* Fill the i'th record all with zeroes. */
300static void zeroise_segment ( Int i )
301{
302 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000303 segments[i].prot = 0;
304 segments[i].flags = 0;
305 segments[i].addr = 0;
306 segments[i].len = 0;
307 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000308 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000309 segments[i].fnIdx = -1;
310 segments[i].dev = 0;
311 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000312 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000313}
314
sewardj79048ce2005-02-18 08:28:32 +0000315
sewardj548be6d2005-02-16 01:31:37 +0000316/* Create a segment to contain 'a', and return its index. Or -1 if
317 this failed because some other segment already contains 'a'. If
318 successful, fill in the segment's .addr field with 'a' but leave
319 all other fields alone.
320*/
321static Int create_segment ( Addr a )
322{
323 Int i, r;
324 for (i = 0; i < segments_used; i++) {
325 r = compare_addr_with_seg( a, &segments[i] );
326 if (r == 1)
327 continue; /* seg[i] precedes a */
328 if (r == 0)
329 return -1; /* seg[i] contains a. Give up */
330 vg_assert(r == -1);
331 break;
332 }
333 /* a precedes seg[i]. Shift segs at i and above up one, and use
334 this slot. */
335 make_space_at(i);
336 zeroise_segment(i);
337 segments[i].addr = a;
338 return i;
339}
340
sewardj79048ce2005-02-18 08:28:32 +0000341
342/* Print out the segment array (debugging only!). Note, this calls
343 VG_(printf), and I'm not 100% clear that that wouldn't require
344 dynamic memory allocation and hence more segments to be allocated.
345*/
346static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000347{
sewardj79048ce2005-02-18 08:28:32 +0000348 Int i;
349 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
350 who, segments_used, segnames_used);
351 for (i = 0; i < segnames_used; i++) {
352 if (!segnames[i].inUse)
353 continue;
354 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
355 }
356 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000357 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000358 "%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 +0000359 i,
sewardj79048ce2005-02-18 08:28:32 +0000360 segments[i].addr, segments[i].addr + segments[i].len,
361 (ULong)segments[i].len, segments[i].prot,
362 segments[i].flags, segments[i].dev, segments[i].ino,
363 (Long)segments[i].offset,
364 segments[i].fnIdx);
365 }
366 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000367}
sewardj79048ce2005-02-18 08:28:32 +0000368
sewardj548be6d2005-02-16 01:31:37 +0000369
370/* Find the segment containing 'a' and split it into two pieces at
371 'a'. Does nothing if no segment contains 'a', or if the split
372 would cause either of the pieces to have zero size.
373
374 If 'a' is not found, or if no splitting happens, -1 is returned.
375
376 If a value 'r' other than -1 is returned, this is the index of the
377 higher-addressed segment resulting from the split, and the index of
378 the lower-addressed segment is r-1.
379*/
380static Int split_segment ( Addr a )
381{
382 Int r;
383 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000384 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000385 r = find_segment(a);
386 if (r == -1)
387 /* not found */
388 return -1;
389 if (segments[r].addr == a)
390 /* segment starts at 'a', so splitting it would create a
391 zero-sized segment */
392 return -1;
393
394 /* copy original; make adjustments. */
395 vg_assert(a > segments[r].addr);
396 delta = a - segments[r].addr;
397 make_space_at(r);
398 segments[r] = segments[r+1];
399 segments[r].len = delta;
400 segments[r+1].len -= delta;
401 segments[r+1].addr += delta;
402 segments[r+1].offset += delta;
403 return r+1;
404}
405
sewardj79048ce2005-02-18 08:28:32 +0000406
407/* Return true if two segments are adjacent and mergable (s1 is
408 assumed to have a lower ->addr than s2) */
409static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
410{
411 if (s1->addr+s1->len != s2->addr)
412 return False;
413
414 if (s1->flags != s2->flags)
415 return False;
416
417 if (s1->prot != s2->prot)
418 return False;
419
njn36ef6ba2005-05-14 18:42:26 +0000420 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000421 return False;
422
423 if (s1->flags & SF_FILE){
424 if ((s1->offset + s1->len) != s2->offset)
425 return False;
426 if (s1->dev != s2->dev)
427 return False;
428 if (s1->ino != s2->ino)
429 return False;
430 if (s1->fnIdx != s2->fnIdx)
431 return False;
432 }
433
434 return True;
435}
436
437
438/* Clean up and sanity check the segment array:
439 - check segments are in ascending order
440 - check segments do not overlap
441 - check no segment has zero size
442 - merge adjacent where possible
443 - perform checks on the filename table, and reclaim dead entries
444*/
445static void preen_segments ( void )
446{
447 Int i, j, rd, wr;
448 Segment *s, *s1;
449 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
450 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
451
452 if (0) show_segments("before preen");
453
454 /* clear string table mark bits */
455 for (i = 0; i < segnames_used; i++)
456 segnames[i].mark = False;
457
458 /* check for non-zero size, and set mark bits for any used strings */
459 for (i = 0; i < segments_used; i++) {
460 vg_assert(segments[i].len > 0);
461 j = segments[i].fnIdx;
462 vg_assert(j >= -1 && j < segnames_used);
463 if (j >= 0) {
464 vg_assert(segnames[j].inUse);
465 segnames[j].mark = True;
466 }
467 }
468
469 /* check ascendingness and non-overlap */
470 for (i = 0; i < segments_used-1; i++) {
471 s = &segments[i];
472 s1 = &segments[i+1];
473 vg_assert(s->addr < s1->addr);
474 vg_assert(s->addr + s->len <= s1->addr);
475 }
476
477 /* merge */
478 if (segments_used < 1)
479 return;
480
481 wr = 1;
482 for (rd = 1; rd < segments_used; rd++) {
483 s = &segments[wr-1];
484 s1 = &segments[rd];
485 if (segments_are_mergeable(s,s1)) {
486 if (0)
487 VG_(printf)("merge %p-%p with %p-%p\n",
488 s->addr, s->addr+s->len,
489 s1->addr, s1->addr+s1->len);
490 s->len += s1->len;
491 continue;
492 }
493 if (wr < rd)
494 segments[wr] = segments[rd];
495 wr++;
496 }
497 vg_assert(wr >= 0 && wr <= segments_used);
498 segments_used = wr;
499
500 /* Free up any strings which are no longer referenced. */
501 for (i = 0; i < segnames_used; i++) {
502 if (segnames[i].mark == False) {
503 segnames[i].inUse = False;
504 segnames[i].fname[0] = 0;
505 }
506 }
507
508 if (0) show_segments("after preen");
509}
510
511
sewardj548be6d2005-02-16 01:31:37 +0000512/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000513/*--- Maintain an ordered list of all the client's mappings ---*/
514/*--------------------------------------------------------------*/
515
nethercote8991d5a2004-11-03 17:07:46 +0000516Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000517{
518 Addr se = s->addr+s->len;
519 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000520 vg_assert(pe >= p);
521
522 return (p >= s->addr && pe <= se);
523}
524
nethercote8991d5a2004-11-03 17:07:46 +0000525Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000526{
527 Addr se = s->addr+s->len;
528 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000529 vg_assert(pe >= p);
530
531 return (p < se && pe > s->addr);
532}
533
sewardj1024cf72005-02-28 14:39:21 +0000534#if 0
535/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000536/* Prepare a Segment structure for recycling by freeing everything
537 hanging off it. */
538static void recycleseg(Segment *s)
539{
540 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000541 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000542
543 if (s->filename != NULL)
544 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
545
546 /* keep the SegInfo, if any - it probably still applies */
547}
548
549/* When freeing a Segment, also clean up every one else's ideas of
550 what was going on in that range of memory */
551static void freeseg(Segment *s)
552{
553 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000554 if (s->seginfo != NULL) {
555 VG_(seginfo_decref)(s->seginfo, s->addr);
556 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000557 }
558
559 VG_(SkipNode_Free)(&sk_segments, s);
560}
sewardj1024cf72005-02-28 14:39:21 +0000561#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000562
sewardj1024cf72005-02-28 14:39:21 +0000563
564/* Get rid of any translations arising from s. */
565/* Note, this is not really the job of the low level memory manager.
566 When it comes time to rewrite this subsystem, clean this up. */
567static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000568{
sewardj1024cf72005-02-28 14:39:21 +0000569 if (s->flags & SF_CODE) {
570 VG_(discard_translations)(s->addr, s->len);
571 if (0)
572 VG_(printf)("dumping translations in %p .. %p\n",
573 s->addr, s->addr+s->len);
574 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000575}
576
sewardj1024cf72005-02-28 14:39:21 +0000577
fitzhardinge98abfc72003-12-16 02:05:15 +0000578/* This unmaps all the segments in the range [addr, addr+len); any
579 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000580void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000581{
fitzhardingee3632c62003-12-22 10:58:06 +0000582 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000583 Segment* s;
584 Addr end, s_end;
585 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000586 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000587
588 if (len == 0)
589 return;
590
njn13bfd852005-06-02 03:52:53 +0000591 len = VG_PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000592
fitzhardinge98abfc72003-12-16 02:05:15 +0000593 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000594 VG_(printf)("unmap_range(%p, %llu)\n", addr, (ULong)len);
sewardj79048ce2005-02-18 08:28:32 +0000595 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000596 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000597
598 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000599 vg_assert(VG_IS_PAGE_ALIGNED(addr));
600 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000601
sewardj548be6d2005-02-16 01:31:37 +0000602 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000603
604 /* do not delete .. even though it looks stupid */
605 vg_assert(i >= 0);
606
607 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000608 s = &segments[i];
609 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000610
sewardj548be6d2005-02-16 01:31:37 +0000611 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000612 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000613 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000614
fitzhardinge1a303042003-12-22 08:48:50 +0000615 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000616 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000617 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000618 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000619 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000620
621 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000622 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000623 addr < s_end &&
624 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000625 /* this segment's tail is truncated by [addr, addr+len)
626 -> truncate tail
627 */
sewardj1024cf72005-02-28 14:39:21 +0000628 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000629 s->len = addr - s->addr;
630
631 if (debug)
tom9be7c982005-04-25 16:55:44 +0000632 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000633 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000634 /* this segment's head is truncated by [addr, addr+len)
635 -> truncate head
636 */
sewardj548be6d2005-02-16 01:31:37 +0000637 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000638
639 if (debug)
tom9be7c982005-04-25 16:55:44 +0000640 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000641 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000642
sewardj1024cf72005-02-28 14:39:21 +0000643 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000644 s->addr += delta;
645 s->offset += delta;
646 s->len -= delta;
647
648 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000649 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000650 /* this segment is completely contained within [addr, addr+len)
651 -> delete segment
652 */
sewardj1024cf72005-02-28 14:39:21 +0000653 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000654 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000655 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000656
657 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000658 VG_(printf)(" case 3: seg %d deleted\n", i);
659 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000660 /* [addr, addr+len) is contained within a single segment
661 -> split segment into 3, delete middle portion
662 */
sewardj1024cf72005-02-28 14:39:21 +0000663 Int i_middle;
664 dump_translations_from(s);
665 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000666 vg_assert(i_middle != -1);
667 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000668 vg_assert(segments[i_middle].addr == addr);
669 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000670 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000671
672 if (debug)
673 VG_(printf)(" case 4: subrange %p-%p deleted\n",
674 addr, addr+len);
675 }
sewardj47c98a72005-03-12 20:36:15 +0000676
677 /* If we deleted this segment (or any above), those above will
678 have been moved down to fill in the hole in the segment
679 array. In order that we don't miss them, we have to
680 re-consider this slot number; hence the i--. */
681 if (deleted)
682 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000683 }
sewardj79048ce2005-02-18 08:28:32 +0000684 preen_segments();
685 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000686}
687
sewardj548be6d2005-02-16 01:31:37 +0000688
689/* Add a binding of [addr,addr+len) to
690 (prot,flags,dev,ino,off,filename) in the segment array.
691 Delete/truncate any previous mapping(s) covering that range.
692*/
693void
694VG_(map_file_segment)( Addr addr, SizeT len,
695 UInt prot, UInt flags,
696 UInt dev, UInt ino, ULong off,
697 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000698{
fitzhardinge98abfc72003-12-16 02:05:15 +0000699 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000700 Segment* s;
701 Int idx;
sewardja8d8e232005-06-07 20:04:56 +0000702 HChar* stage2_suffix = "lib/valgrind/stage2";
703 Bool is_stage2 = VG_(strstr)(filename, stage2_suffix) != NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000704
705 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000706 VG_(printf)(
707 "\n"
tom9be7c982005-04-25 16:55:44 +0000708 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000709 " dev=0x%4x ino=%d off=%ld\n"
710 " filename='%s')\n",
711 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000712
sewardja8d8e232005-06-07 20:04:56 +0000713 if (0) show_segments("before map_file_segment");
714
fitzhardinge98abfc72003-12-16 02:05:15 +0000715 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000716 vg_assert(VG_IS_PAGE_ALIGNED(addr));
njn13bfd852005-06-02 03:52:53 +0000717 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000718
sewardj548be6d2005-02-16 01:31:37 +0000719 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
720 VG_(unmap_range)(addr, len);
721
722 /* and now install this one */
723 idx = create_segment(addr);
724 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
725 vg_assert(idx != -1);
726 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000727
sewardj79048ce2005-02-18 08:28:32 +0000728 s = &segments[idx];
729 vg_assert(s->addr == addr);
730 s->prot = prot;
731 s->flags = flags;
732 s->len = len;
733 s->offset = off;
734 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
735 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
736 s->dev = dev;
737 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000738 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000739
sewardj79048ce2005-02-18 08:28:32 +0000740 /* Clean up right now */
741 preen_segments();
742 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000743
744 /* If this mapping is of the beginning of a file, isn't part of
745 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000746 file, then try reading symbols from it.
747 */
njn36ef6ba2005-05-14 18:42:26 +0000748 if (s->seginfo == NULL
sewardja8d8e232005-06-07 20:04:56 +0000749 && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
750 || is_stage2
751 )
sewardj79048ce2005-02-18 08:28:32 +0000752 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
753 if (off == 0
754 && s->fnIdx != -1
755 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
756 && len >= VKI_PAGE_SIZE
757 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000758 s->seginfo = VG_(read_seg_symbols)(s);
759 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000760 s->flags |= SF_DYNLIB;
761 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000762 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000763#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000764 const SegInfo *info;
765
njn36ef6ba2005-05-14 18:42:26 +0000766 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000767 for(info = VG_(next_seginfo)(NULL);
768 info != NULL;
769 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000770 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
771 {
njn36ef6ba2005-05-14 18:42:26 +0000772 s->seginfo = (SegInfo *)info;
773 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000774 }
775 }
sewardj79048ce2005-02-18 08:28:32 +0000776#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000777 }
778 }
779
780 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000781 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000782}
783
nethercote8b5f40c2004-11-02 13:29:50 +0000784void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000785 Int fd, ULong off, const Char *filename)
786{
787 struct vki_stat st;
788 Char *name = NULL;
789
790 st.st_dev = 0;
791 st.st_ino = 0;
792
793 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000794 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000795
796 if (VG_(fstat)(fd, &st) < 0)
797 flags &= ~SF_FILE;
798 }
799
sewardj79048ce2005-02-18 08:28:32 +0000800 if ((flags & SF_FILE) && filename == NULL && fd != -1)
801 name = VG_(resolve_filename_nodup)(fd);
fitzhardinge98abfc72003-12-16 02:05:15 +0000802
803 if (filename == NULL)
804 filename = name;
805
sewardj79048ce2005-02-18 08:28:32 +0000806 VG_(map_file_segment)(addr, len, prot, flags,
807 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000808}
809
nethercote8b5f40c2004-11-02 13:29:50 +0000810void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000811{
812 flags &= ~SF_FILE;
813
814 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
815}
816
817/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000818void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000819{
sewardj79048ce2005-02-18 08:28:32 +0000820 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000821 static const Bool debug = False || mem_debug;
822
823 if (debug)
tom9be7c982005-04-25 16:55:44 +0000824 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000825
826 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000827
828 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000829 vg_assert(VG_IS_PAGE_ALIGNED(a));
njn13bfd852005-06-02 03:52:53 +0000830 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000831
sewardj79048ce2005-02-18 08:28:32 +0000832 split_segment(a);
833 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000834
sewardj548be6d2005-02-16 01:31:37 +0000835 r = find_segment(a);
836 vg_assert(r != -1);
837 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000838
839 preen_segments();
840
sewardje517b802005-02-16 01:58:51 +0000841 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000842}
843
sewardj79048ce2005-02-18 08:28:32 +0000844
sewardj548be6d2005-02-16 01:31:37 +0000845/* Try to find a map space for [addr,addr+len). If addr==0, it means
846 the caller is prepared to accept a space at any location; if not,
847 we will try for addr, but fail if we can't get it. This mimics
848 mmap fixed vs mmap not-fixed.
849*/
nethercote8b5f40c2004-11-02 13:29:50 +0000850Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000851{
fitzhardingee3632c62003-12-22 10:58:06 +0000852 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000853 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000854 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000855 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
856 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000857 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
858 Int i, i_any, i_fixed, i_final;
859 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000860
sewardj548be6d2005-02-16 01:31:37 +0000861 Bool fixed;
862
sewardje517b802005-02-16 01:58:51 +0000863 if (debug) {
864 VG_(printf)("\n\n");
sewardja8d8e232005-06-07 20:04:56 +0000865 VG_(printf)("find_map_space(%p, %llu, %d) ...\n",
866 addr, (ULong)len, for_client);
sewardje517b802005-02-16 01:58:51 +0000867 }
868
869 if (0) show_segments("find_map_space: start");
870
sewardj548be6d2005-02-16 01:31:37 +0000871 if (addr == 0) {
872 fixed = False;
873 } else {
874 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000875 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000876 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000877 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000878 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000879
880 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000881 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
njn13bfd852005-06-02 03:52:53 +0000882 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000883
nethercote73b526f2004-10-31 18:48:21 +0000884 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000885
sewardj548be6d2005-02-16 01:31:37 +0000886 /* Scan the segment list, looking for a hole which satisfies the
887 requirements. At each point i we ask the question "can we use
888 the hole in between segments[i-1] and segments[i] ?" */
889 i_any = i_fixed = -1;
890 hstart_any = hstart_fixed = 0;
891
892 hole_start = hole_end = 0;
893
894 /* Iterate over all possible holes, generating them into
895 hole_start/hole_end. Filter out invalid ones. Then see if any
896 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
897 */
898 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
899 if (i == 0) {
900 hole_start = 0;
901 hole_end = segments[0].addr-1;
902 }
903 else {
904 vg_assert(segments_used > 0);
905 if (i == segments_used) {
906 hole_start = segments[i-1].addr + segments[i-1].len;
907 hole_end = ~(Addr)0;
908 } else {
909 hole_start = segments[i-1].addr + segments[i-1].len;
910 hole_end = segments[i].addr - 1;
911 }
912 }
913
914 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
915
916 /* ignore zero-sized holes */
917 if (hole_start == hole_end+1)
918 continue;
919
njnbe91aae2005-03-27 01:42:41 +0000920 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
921 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000922
923 /* ignore holes which fall outside the allowable area */
924 if (!(hole_start >= base && hole_end <= limit))
925 continue;
926
927 vg_assert(hole_end > hole_start);
928 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000929 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000930
931 if (hole_len >= len && i_any == -1) {
932 /* It will at least fit in this hole. */
933 i_any = i;
934 hstart_any = hole_start;
935 }
936
sewardjb5f6f512005-03-10 23:59:00 +0000937 if (fixed && hole_start <= addr
938 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000939 /* We were asked for a fixed mapping, and this hole works.
940 Bag it -- and stop searching as further searching is
941 pointless. */
942 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000943 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000944 break;
945 }
946 }
947
948 /* Summarise the final decision into i_final/hstart_final. */
949 i_final = -1;
950 hstart_final = 0;
951
952 if (fixed) {
953 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000954 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000955 } else {
956 i_final = i_any;
957 hstart_final = hstart_any;
958 }
959
960
961 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000962 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000963 else
964 ret = 0; /* not found */
965
966 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000967 VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n",
968 addr, (ULong)len, for_client, ret);
sewardj548be6d2005-02-16 01:31:37 +0000969
sewardjb5f6f512005-03-10 23:59:00 +0000970 if (fixed) {
971 vg_assert(ret == 0 || ret == addrOrig);
972 }
973
sewardj548be6d2005-02-16 01:31:37 +0000974 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000975}
976
sewardj79048ce2005-02-18 08:28:32 +0000977
sewardjb5f6f512005-03-10 23:59:00 +0000978/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000979 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000980 mapping over any part of the address space which is not covered
981 by an entry in the segment list.
982
983 This is designed for use around system calls which allocate
984 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000985 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000986 address with VG_(find_map_space) and then adding a segment for
987 it and padding the address space valgrind can ensure that the
988 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000989void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000990{
sewardj394790d2005-03-17 02:14:44 +0000991 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +0000992 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +0000993
994 Int i = 0;
995 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000996
nethercote820bd8c2004-09-07 23:04:49 +0000997 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000998 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +0000999 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +00001000 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1001 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001002 }
thughes9aaebc32004-07-15 23:13:37 +00001003 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001004 i++;
1005 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001006 }
1007
nethercote820bd8c2004-09-07 23:04:49 +00001008 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001009 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001010 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1011 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001012 }
thughes9aaebc32004-07-15 23:13:37 +00001013}
1014
thughesc70b8c62004-07-16 23:07:58 +00001015/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001016 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001017void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001018{
sewardj394790d2005-03-17 02:14:44 +00001019 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001020 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001021
1022 Int i = 0;
1023 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001024
nethercote820bd8c2004-09-07 23:04:49 +00001025 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001026 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +00001027 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001028 }
thughes9aaebc32004-07-15 23:13:37 +00001029 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001030 i++;
1031 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001032 }
1033
nethercote820bd8c2004-09-07 23:04:49 +00001034 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001035 ret = VG_(do_syscall2)(__NR_munmap, addr,
1036 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001037 }
thughes9aaebc32004-07-15 23:13:37 +00001038}
1039
sewardj548be6d2005-02-16 01:31:37 +00001040/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001041Segment *VG_(find_segment)(Addr a)
1042{
sewardj548be6d2005-02-16 01:31:37 +00001043 Int r = find_segment(a);
1044 if (0) show_segments("find_segment");
1045 if (r == -1) return NULL;
1046 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001047}
1048
sewardj548be6d2005-02-16 01:31:37 +00001049/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1050 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1051 a segment is a checked error.
1052*/
1053Segment *VG_(find_segment_above_unmapped)(Addr a)
1054{
1055 Int r = find_segment_above_unmapped(a);
1056 if (0) show_segments("find_segment_above_unmapped");
1057 if (r == -1) return NULL;
1058 return &segments[r];
1059}
1060
1061/* Assumes that 'a' is in some segment. Finds the next segment along,
1062 or NULL if none. Passing 'a' which is in fact not in a segment is
1063 a checked error.
1064*/
1065Segment *VG_(find_segment_above_mapped)(Addr a)
1066{
1067 Int r = find_segment_above_mapped(a);
1068 if (0) show_segments("find_segment_above_mapped");
1069 if (r == -1) return NULL;
1070 return &segments[r];
1071}
1072
1073
sewardjde4a1d02002-03-22 01:27:54 +00001074/*------------------------------------------------------------*/
1075/*--- Tracking permissions around %esp changes. ---*/
1076/*------------------------------------------------------------*/
1077
1078/*
1079 The stack
1080 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001081 The stack's segment seems to be dynamically extended downwards by
1082 the kernel as the stack pointer moves down. Initially, a 1-page
1083 (4k) stack is allocated. When SP moves below that for the first
1084 time, presumably a page fault occurs. The kernel detects that the
njna60a7c12005-05-08 17:49:37 +00001085 faulting address is in the range from SP - VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001086 upwards to the current valid stack. It then extends the stack
1087 segment downwards for enough to cover the faulting address, and
1088 resumes the process (invisibly). The process is unaware of any of
1089 this.
sewardjde4a1d02002-03-22 01:27:54 +00001090
sewardjfa8202f2005-04-24 11:05:55 +00001091 That means that Valgrind can't spot when the stack segment is being
1092 extended. Fortunately, we want to precisely and continuously
1093 update stack permissions around SP, so we need to spot all writes
1094 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001095
sewardjfa8202f2005-04-24 11:05:55 +00001096 The deal is: when SP is assigned a lower value, the stack is being
1097 extended. Create suitably-permissioned pages to fill in any holes
1098 between the old stack ptr and this one, if necessary. Then mark
1099 all bytes in the area just "uncovered" by this SP change as
1100 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001101
sewardjfa8202f2005-04-24 11:05:55 +00001102 When SP goes back up, mark the area receded over as unreadable and
1103 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001104
njna60a7c12005-05-08 17:49:37 +00001105 Just to record the SP boundary conditions somewhere convenient:
1106 SP - VGA_STACK_REDZONE_SZB always points to the lowest live byte in
1107 the stack. All addresses below SP - VGA_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001108 live; those at and above it are.
1109
njna60a7c12005-05-08 17:49:37 +00001110 We do not concern ourselves here with the VGA_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001111 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001112*/
1113
rjwalsh0140af52005-06-04 20:42:33 +00001114/*
1115 * This structure holds information about the start and end addresses of
1116 * registered stacks. There's always at least one stack registered:
1117 * the main process stack. It will be the first stack registered and
1118 * so will have a stack id of 0. The user does not need to register
1119 * this stack: Valgrind does it automatically right before it starts
1120 * running the client. No other stacks are automatically registered by
1121 * Valgrind, however.
1122 */
1123
1124typedef struct _Stack {
1125 UWord id;
1126 Addr start;
1127 Addr end;
1128 struct _Stack *next;
1129} Stack;
1130
1131static Stack *stacks;
1132static UWord next_id; /* Next id we hand out to a newly registered stack */
1133
1134/*
1135 * These are the id, start and end values of the current stack. If the
1136 * stack pointer falls outside the range of the current stack, we search
1137 * the stacks list above for a matching stack.
1138 */
1139
1140static Addr current_stack_start;
1141static Addr current_stack_end;
1142static UWord current_stack_id;
1143
1144/* Search for a particular stack by id number. */
1145static Bool find_stack_by_id(UWord id, Addr *start, Addr *end)
1146{
1147 Stack *i = stacks;
1148 while(i) {
1149 if(i->id == id) {
1150 *start = i->start;
1151 *end = i->end;
1152 return True;
1153 }
1154 i = i->next;
1155 }
1156 return False;
1157}
1158
1159/* Find what stack an address falls into. */
1160static Bool find_stack_by_addr(Addr sp, Addr *start, Addr *end, UWord *id)
1161{
1162 Stack *i = stacks;
1163 while(i) {
1164 if(sp >= i->start && sp <= i->end) {
1165 *start = i->start;
1166 *end = i->end;
1167 *id = i->id;
1168 return True;
1169 }
1170 i = i->next;
1171 }
1172 return False;
1173}
1174
1175/* Change over to a new stack. */
1176static Bool set_current_stack(UWord id)
1177{
1178 Addr start, end;
1179 if (find_stack_by_id(id, &start, &end)) {
1180 current_stack_id = id;
1181 current_stack_start = start;
1182 current_stack_end = end;
1183 return True;
1184 }
1185 return False;
1186}
1187
1188/*
1189 * Register a new stack from start - end. This is invoked from the
1190 * VALGRIND_STACK_REGISTER client request, and is also called just before
1191 * we start the client running, to register the main process stack.
1192 *
1193 * Note: this requires allocating a piece of memory to store the Stack
1194 * structure, which places a dependency between this module and the
1195 * mallocfree module. However, there is no real chance of a circular
1196 * dependency here, since the mallocfree module would never call back to
1197 * this function.
1198 */
1199
1200UWord VG_(handle_stack_register)(Addr start, Addr end)
1201{
1202 Stack *i;
1203 if (start > end) {
1204 Addr t = end;
1205 end = start;
1206 start = t;
1207 }
1208
1209 i = (Stack *)VG_(arena_malloc)(VG_AR_CORE, sizeof(Stack));
1210 i->start = start;
1211 i->end = end;
1212 i->id = next_id++;
1213 i->next = stacks;
1214 stacks = i;
1215
1216 if(i->id == 0) {
1217 set_current_stack(i->id);
1218 }
1219
1220 return i->id;
1221}
1222
1223/*
1224 * Deregister a stack. This is invoked from the VALGRIND_STACK_DEREGISTER
1225 * client request.
1226 *
1227 * Note: this requires freeing the piece of memory that was used to store
1228 * the Stack structure, which places a dependency between this module
1229 * and the mallocfree module. However, there is no real chance of
1230 * a circular dependency here, since the mallocfree module would never
1231 * call back to this function.
1232 */
1233
1234void VG_(handle_stack_deregister)(UWord id)
1235{
1236 Stack *i = stacks;
1237 Stack *prev = NULL;
1238
1239 if(current_stack_id == id) {
1240 return;
1241 }
1242
1243 while(i) {
1244 if (i->id == id) {
1245 if(prev == NULL) {
1246 stacks = i->next;
1247 } else {
1248 prev->next = i->next;
1249 }
1250 VG_(arena_free)(VG_AR_CORE, i);
1251 return;
1252 }
1253 prev = i;
1254 i = i->next;
1255 }
1256}
1257
1258/*
1259 * Change a stack. This is invoked from the VALGRIND_STACK_CHANGE client
1260 * request and from the stack growth stuff the signals module when
1261 * extending the main process stack.
1262 */
1263
1264void VG_(handle_stack_change)(UWord id, Addr start, Addr end)
1265{
1266 Stack *i = stacks;
1267
1268 if (id == current_stack_id) {
1269 current_stack_start = start;
1270 current_stack_end = end;
1271 }
1272
1273 while(i) {
1274 if (i->id == id) {
1275 i->start = start;
1276 i->end = end;
1277 return;
1278 }
1279 i = i->next;
1280 }
1281}
1282
njn9b007f62003-04-07 14:40:25 +00001283/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001284 tracked by the tool, and one of the specialised cases
1285 (eg. new_mem_stack_4) isn't used in preference.
1286*/
njn9fb73db2005-03-27 01:55:21 +00001287VGA_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001288void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001289{
sewardj97724e52005-04-02 23:40:59 +00001290 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001291 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001292
rjwalsh0140af52005-06-04 20:42:33 +00001293 /* Check if the stack pointer is still in the same stack as before. */
1294 if (new_SP < current_stack_start || new_SP > current_stack_end) {
1295 Addr start, end;
1296 UWord new_id;
1297 Bool found = find_stack_by_addr(new_SP, &start, &end, &new_id);
1298 if (found && new_id != current_stack_id) {
1299 /* The stack pointer is now in another stack. Update the current
1300 stack information and return without doing anything else. */
1301 set_current_stack(new_id);
1302 return;
1303 }
1304 }
1305
sewardj97724e52005-04-02 23:40:59 +00001306 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1307 /* SP has changed by more than some threshold amount (by
1308 default, 2MB). We take this to mean that the application is
1309 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001310
1311 JRS 20021001: following discussions with John Regehr, if a stack
1312 switch happens, it seems best not to mess at all with memory
1313 permissions. Seems to work well with Netscape 4.X. Really the
1314 only remaining difficulty is knowing exactly when a stack switch is
1315 happening. */
sewardj97724e52005-04-02 23:40:59 +00001316 if (VG_(clo_verbosity) > 0 && moans > 0) {
1317 moans--;
1318 VG_(message)(Vg_UserMsg,
1319 "Warning: client switching stacks? "
1320 "SP change: %p --> %p", old_SP, new_SP);
1321 VG_(message)(Vg_UserMsg,
1322 " to suppress, use: --max-stackframe=%d or greater",
1323 (delta < 0 ? -delta : delta));
1324 if (moans == 0)
1325 VG_(message)(Vg_UserMsg,
1326 " further instances of this message "
1327 "will not be shown.");
1328 }
njn9b007f62003-04-07 14:40:25 +00001329 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001330 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001331
njn9b007f62003-04-07 14:40:25 +00001332 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001333 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001334 }
1335}
1336
jsgf855d93d2003-10-13 22:26:55 +00001337/*
sewardjb5f6f512005-03-10 23:59:00 +00001338 Test if a piece of memory is addressable with at least the "prot"
1339 protection permissions by examining the underlying segments.
1340
1341 Really this is a very stupid algorithm and we could do much
1342 better by iterating through the segment array instead of through
1343 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001344 */
sewardjb5f6f512005-03-10 23:59:00 +00001345Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001346{
sewardjb5f6f512005-03-10 23:59:00 +00001347 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001348
sewardjb5f6f512005-03-10 23:59:00 +00001349 if ((p + size) < p)
1350 return False; /* reject wraparounds */
1351 if (size == 0)
1352 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001353
njn13bfd852005-06-02 03:52:53 +00001354 p = VG_PGROUNDDN(p);
1355 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001356 vg_assert(VG_IS_PAGE_ALIGNED(p));
1357 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001358
sewardjb5f6f512005-03-10 23:59:00 +00001359 for (; size > 0; size -= VKI_PAGE_SIZE) {
1360 seg = VG_(find_segment)(p);
1361 if (!seg)
1362 return False;
1363 if ((seg->prot & prot) != prot)
1364 return False;
1365 p += VKI_PAGE_SIZE;
1366 }
jsgf855d93d2003-10-13 22:26:55 +00001367
sewardjb5f6f512005-03-10 23:59:00 +00001368 return True;
jsgf855d93d2003-10-13 22:26:55 +00001369}
1370
sewardjb5f6f512005-03-10 23:59:00 +00001371
sewardjde4a1d02002-03-22 01:27:54 +00001372/*--------------------------------------------------------------------*/
njn9260c782005-06-19 21:57:54 +00001373/*--- Random function that doesn't really belong here ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001374/*--------------------------------------------------------------------*/
1375
njn86f12dc2005-03-14 01:16:05 +00001376/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001377 range, which isn't SF_CORE, a root.
1378*/
njn86f12dc2005-03-14 01:16:05 +00001379void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1380{
sewardj882af5f2005-03-16 12:27:53 +00001381 Int i;
1382 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001383 Segment *s;
1384
sewardj882af5f2005-03-16 12:27:53 +00001385 for (i = 0; i < segments_used; i++) {
1386 s = &segments[i];
1387 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1388 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001389 if (flags != SF_MMAP && flags != SF_STACK)
1390 continue;
sewardj882af5f2005-03-16 12:27:53 +00001391 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1392 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001393 continue;
1394 if (!VG_(is_client_addr)(s->addr) ||
1395 !VG_(is_client_addr)(s->addr+s->len))
1396 continue;
1397
1398 (*add_rootrange)(s->addr, s->len);
1399 }
njn86f12dc2005-03-14 01:16:05 +00001400}
1401
1402
nethercote88a90162004-07-10 16:59:25 +00001403/*--------------------------------------------------------------------*/
1404/*--- Querying memory layout ---*/
1405/*--------------------------------------------------------------------*/
1406
fitzhardinge98abfc72003-12-16 02:05:15 +00001407Bool VG_(is_client_addr)(Addr a)
1408{
1409 return a >= VG_(client_base) && a < VG_(client_end);
1410}
1411
1412Bool VG_(is_shadow_addr)(Addr a)
1413{
1414 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1415}
1416
fitzhardinge98abfc72003-12-16 02:05:15 +00001417Addr VG_(get_shadow_size)(void)
1418{
1419 return VG_(shadow_end)-VG_(shadow_base);
1420}
1421
sewardjfa8202f2005-04-24 11:05:55 +00001422
nethercote88a90162004-07-10 16:59:25 +00001423/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001424/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001425/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001426
1427void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1428{
sewardj548be6d2005-02-16 01:31:37 +00001429vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001430 if (0)
1431 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1432
1433 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001434 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001435
njn13bfd852005-06-02 03:52:53 +00001436 sz = VG_PGROUNDUP(p+sz) - VG_PGROUNDDN(p);
1437 p = VG_PGROUNDDN(p);
fitzhardinge98abfc72003-12-16 02:05:15 +00001438
1439 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1440
1441 if (call_init)
1442 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001443 /* ask the tool to initialize each page */
njn13bfd852005-06-02 03:52:53 +00001444 VG_TRACK( init_shadow_page, VG_PGROUNDDN(p) );
fitzhardinge98abfc72003-12-16 02:05:15 +00001445
nethercote73b526f2004-10-31 18:48:21 +00001446 p += VKI_PAGE_SIZE;
1447 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001448 }
1449}
1450
1451void *VG_(shadow_alloc)(UInt size)
1452{
1453 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001454 Addr try_here;
njne9befc62005-06-11 15:51:30 +00001455 SysRes r;
sewardj79048ce2005-02-18 08:28:32 +00001456
1457 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001458
1459 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001460 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001461
njn13bfd852005-06-02 03:52:53 +00001462 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001463
1464 if (shadow_alloc == 0)
1465 shadow_alloc = VG_(shadow_base);
1466
1467 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001468 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001469
sewardj79048ce2005-02-18 08:28:32 +00001470 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001471 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1472 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001473 vg_assert(size > 0);
1474
1475 if (0)
1476 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1477
1478 /* this is big-bang allocated, so we don't expect to find a listed
1479 segment for it. */
1480 /* This is really an absolute disgrace. Sometimes the big-bang
1481 mapping is in the list (due to re-reads of /proc/self/maps,
1482 presumably) and sometimes it isn't. */
1483#if 0
1484 r = find_segment(try_here);
1485 vg_assert(r == -1);
1486 r = find_segment(try_here+size-1);
1487 vg_assert(r == -1);
1488#endif
1489
1490 r = VG_(mprotect_native)( (void*)try_here,
1491 size, VKI_PROT_READ|VKI_PROT_WRITE );
1492
njne9befc62005-06-11 15:51:30 +00001493 if (r.isError)
sewardj79048ce2005-02-18 08:28:32 +00001494 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001495
1496 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001497 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001498
sewardj79048ce2005-02-18 08:28:32 +00001499 failed:
1500 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001501 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001502 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001503 size
sewardj79048ce2005-02-18 08:28:32 +00001504 );
1505 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001506}
1507
njne3f06352005-06-01 03:48:33 +00001508/*------------------------------------------------------------*/
1509/*--- pointercheck ---*/
1510/*------------------------------------------------------------*/
1511
1512Bool VGA_(setup_pointercheck)(Addr client_base, Addr client_end)
1513{
1514 vg_assert(0 != client_end);
1515#if defined(VGP_x86_linux)
1516 /* Client address space segment limit descriptor entry */
1517 #define POINTERCHECK_SEGIDX 1
1518
1519 vki_modify_ldt_t ldt = {
1520 POINTERCHECK_SEGIDX, // entry_number
1521 client_base, // base_addr
1522 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1523 1, // seg_32bit
1524 0, // contents: data, RW, non-expanding
1525 0, // ! read_exec_only
1526 1, // limit_in_pages
1527 0, // ! seg not present
1528 1, // useable
1529 };
sewardja8d8e232005-06-07 20:04:56 +00001530 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1531 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001532 VG_(message)(Vg_UserMsg,
1533 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001534 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001535 return False;
1536 } else {
1537 return True;
1538 }
1539#elif defined(VGP_amd64_linux)
1540 if (0)
1541 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1542 return True;
1543#else
1544# error Unknown architecture
1545#endif
1546}
1547
fitzhardinge98abfc72003-12-16 02:05:15 +00001548/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001549/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001550/*--------------------------------------------------------------------*/