blob: 56d43075305de0e9c6d2ba66eea6fe7ee04f1085 [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"
njn899ce732005-06-21 00:28:11 +000034#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
sewardj55f9d1a2005-04-25 11:11:44 +000035#include "pub_core_aspacemgr.h"
njn97405b22005-06-02 03:39:33 +000036#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000037#include "pub_core_libcassert.h"
njn67741c62005-06-20 02:23:07 +000038#include "pub_core_libcfile.h" // For VG_(fstat), VG_(resolve_filename_nodup)
njne9befc62005-06-11 15:51:30 +000039#include "pub_core_libcmman.h"
njn36a20fa2005-06-03 03:08:39 +000040#include "pub_core_libcprint.h"
njnaf1d7df2005-06-11 01:31:52 +000041#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000042#include "pub_core_options.h"
njn9abd6082005-06-17 21:31:45 +000043#include "pub_core_syscall.h"
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);
njn04e16982005-05-31 00:23:43 +000062Addr VG_(clstk_base);
63Addr VG_(clstk_end);
rjwalsh0140af52005-06-04 20:42:33 +000064UWord VG_(clstk_id);
njn04e16982005-05-31 00:23:43 +000065
66Addr VG_(brk_base); /* start of brk */
67Addr VG_(brk_limit); /* current brk */
68
69Addr VG_(shadow_base); /* tool's shadow memory */
70Addr VG_(shadow_end);
71
72Addr VG_(valgrind_base); /* valgrind's address range */
73
74// Note that VG_(valgrind_last) names the last byte of the section, whereas
75// the VG_(*_end) vars name the byte one past the end of the section.
76Addr VG_(valgrind_last);
77
78/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +000079/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +000080/*--------------------------------------------------------------*/
81
sewardj79048ce2005-02-18 08:28:32 +000082/* Max number of segments we can track. */
83#define VG_N_SEGMENTS 1000
84
85/* Max number of segment file names we can track. */
86#define VG_N_SEGNAMES 200
87
88/* Max length of a segment file name. */
89#define VG_MAX_SEGNAMELEN 1000
90
91
92/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +000093
94/* Array [0 .. segments_used-1] of all mappings. */
95/* Sorted by .addr field. */
96/* I: len may not be zero. */
97/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +000098/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +000099
100static Segment segments[VG_N_SEGMENTS];
101static Int segments_used = 0;
102
sewardj79048ce2005-02-18 08:28:32 +0000103typedef
104 struct {
105 Bool inUse;
106 Bool mark;
107 HChar fname[VG_MAX_SEGNAMELEN];
108 }
109 SegName;
110
111/* Filename table. _used is the high water mark; an entry is only
112 valid if its index >= 0, < _used, and its .inUse field == True.
113 The .mark field is used to garbage-collect dead entries.
114*/
115static SegName segnames[VG_N_SEGNAMES];
116static Int segnames_used = 0;
117
118
119/* ------ end of STATE for the address-space manager ------ */
120
121
122/* Searches the filename table to find an index for the given name.
123 If none is found, an index is allocated and the name stored. If no
124 space is available we just give up. If the string is too long to
125 store, return -1.
126*/
127static Int allocate_segname ( const HChar* name )
128{
129 Int i, j, len;
130
131 vg_assert(name);
132
133 if (0) VG_(printf)("alloc_segname %s\n", name);
134
135 len = VG_(strlen)(name);
136 if (len >= VG_MAX_SEGNAMELEN-1) {
137 return -1;
138 }
139
140 /* first see if we already have the name. */
141 for (i = 0; i < segnames_used; i++) {
142 if (!segnames[i].inUse)
143 continue;
144 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
145 return i;
146 }
147 }
148
149 /* no we don't. So look for a free slot. */
150 for (i = 0; i < segnames_used; i++)
151 if (!segnames[i].inUse)
152 break;
153
154 if (i == segnames_used) {
155 /* no free slots .. advance the high-water mark. */
156 if (segnames_used+1 < VG_N_SEGNAMES) {
157 i = segnames_used;
158 segnames_used++;
159 } else {
160 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000161 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000162 " VG_N_SEGNAMES is too small: "
163 "increase it and rebuild Valgrind.\n"
164 );
165 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000166 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000167 " giving up now.\n\n"
168 );
169 VG_(exit)(0);
170 }
171 }
172
173 /* copy it in */
174 segnames[i].inUse = True;
175 for (j = 0; j < len; j++)
176 segnames[i].fname[j] = name[j];
177 vg_assert(len < VG_MAX_SEGNAMELEN);
178 segnames[i].fname[len] = 0;
179 return i;
180}
181
sewardj548be6d2005-02-16 01:31:37 +0000182
183/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
184 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000185 seg.
186*/
sewardj548be6d2005-02-16 01:31:37 +0000187static Int compare_addr_with_seg ( Addr a, Segment* seg )
188{
189 if (a < seg->addr)
190 return -1;
191 if (a >= seg->addr + seg->len)
192 return 1;
193 return 0;
194}
195
sewardj79048ce2005-02-18 08:28:32 +0000196
sewardj548be6d2005-02-16 01:31:37 +0000197/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000198 none.
199*/
sewardj548be6d2005-02-16 01:31:37 +0000200static Int find_segment ( Addr a )
201{
202 Int i;
203 for (i = 0; i < segments_used; i++) {
204 if (compare_addr_with_seg(a, &segments[i]) == 0)
205 return i;
206 }
207 return -1;
208}
209
210
211/* Assumes that 'a' is not in any segment. Finds the index of the
212 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
213 which is in fact in a segment is a checked error.
214*/
215static Int find_segment_above_unmapped ( Addr a )
216{
217 Int i, r;
218 for (i = 0; i < segments_used; i++) {
219 r = compare_addr_with_seg(a, &segments[i]);
220 vg_assert(r != 0); /* 'a' should not be in any segment. */
221 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000222 continue;
sewardj548be6d2005-02-16 01:31:37 +0000223 vg_assert(r == -1);
224 break;
225 }
226
227 if (i == segments_used)
228 return -1; /* not found */
229 else
230 return i;
231}
232
233
234/* Assumes that 'a' is in some segment. Finds the next segment along,
235 or NULL if none. Passing 'a' which is in fact not in a segment is
236 a checked error.
237*/
238static Int find_segment_above_mapped ( Addr a )
239{
240 Int i, r;
241 for (i = 0; i < segments_used; i++) {
242 r = compare_addr_with_seg(a, &segments[i]);
243 if (r == 1)
244 continue; /* not yet there */
245 if (r == 0)
246 break; /* found it */
247 vg_assert(0);
248 /* we shouldn't get here -- r == -1 and so it means we went past
249 'a' without seeing it -- it is therefore unmapped. */
250 /*NOTREACHED*/
251 }
252
253 vg_assert(i < segments_used);
254 if (i == segments_used-1)
255 return -1; /* not found */
256 else
257 return i+1;
258}
259
260
261/* Shift segments[i .. segments_used-1] up by one. */
262static void make_space_at ( Int i )
263{
264 Int j;
265 vg_assert(i >= 0 && i <= segments_used);
266 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000267 if (segments_used+1 == VG_N_SEGMENTS) {
268 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000269 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000270 " VG_N_SEGMENTS is too small: "
271 "increase it and rebuild Valgrind.\n"
272 );
273 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000274 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000275 " giving up now.\n\n"
276 );
277 VG_(exit)(0);
278 }
sewardj548be6d2005-02-16 01:31:37 +0000279 vg_assert(segments_used+1 < VG_N_SEGMENTS);
280 for (j = segments_used; j > i; j--)
281 segments[j] = segments[j-1];
282 segments_used++;
283}
284
sewardj79048ce2005-02-18 08:28:32 +0000285
sewardj548be6d2005-02-16 01:31:37 +0000286/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000287 segments_used.
288*/
sewardj548be6d2005-02-16 01:31:37 +0000289static void delete_segment_at ( Int i )
290{
291 Int j;
292 vg_assert(i >= 0 && i < segments_used);
293 for (j = i+1; j < segments_used; j++)
294 segments[j-1] = segments[j];
295 segments_used--;
296 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
297}
298
299
300/* Fill the i'th record all with zeroes. */
301static void zeroise_segment ( Int i )
302{
303 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000304 segments[i].prot = 0;
305 segments[i].flags = 0;
306 segments[i].addr = 0;
307 segments[i].len = 0;
308 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000309 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000310 segments[i].fnIdx = -1;
311 segments[i].dev = 0;
312 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000313 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000314}
315
sewardj79048ce2005-02-18 08:28:32 +0000316
sewardj548be6d2005-02-16 01:31:37 +0000317/* Create a segment to contain 'a', and return its index. Or -1 if
318 this failed because some other segment already contains 'a'. If
319 successful, fill in the segment's .addr field with 'a' but leave
320 all other fields alone.
321*/
322static Int create_segment ( Addr a )
323{
324 Int i, r;
325 for (i = 0; i < segments_used; i++) {
326 r = compare_addr_with_seg( a, &segments[i] );
327 if (r == 1)
328 continue; /* seg[i] precedes a */
329 if (r == 0)
330 return -1; /* seg[i] contains a. Give up */
331 vg_assert(r == -1);
332 break;
333 }
334 /* a precedes seg[i]. Shift segs at i and above up one, and use
335 this slot. */
336 make_space_at(i);
337 zeroise_segment(i);
338 segments[i].addr = a;
339 return i;
340}
341
sewardj79048ce2005-02-18 08:28:32 +0000342
343/* Print out the segment array (debugging only!). Note, this calls
344 VG_(printf), and I'm not 100% clear that that wouldn't require
345 dynamic memory allocation and hence more segments to be allocated.
346*/
347static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000348{
sewardj79048ce2005-02-18 08:28:32 +0000349 Int i;
350 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
351 who, segments_used, segnames_used);
352 for (i = 0; i < segnames_used; i++) {
353 if (!segnames[i].inUse)
354 continue;
355 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
356 }
357 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000358 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000359 "%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 +0000360 i,
sewardj79048ce2005-02-18 08:28:32 +0000361 segments[i].addr, segments[i].addr + segments[i].len,
362 (ULong)segments[i].len, segments[i].prot,
363 segments[i].flags, segments[i].dev, segments[i].ino,
364 (Long)segments[i].offset,
365 segments[i].fnIdx);
366 }
367 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000368}
sewardj79048ce2005-02-18 08:28:32 +0000369
sewardj548be6d2005-02-16 01:31:37 +0000370
371/* Find the segment containing 'a' and split it into two pieces at
372 'a'. Does nothing if no segment contains 'a', or if the split
373 would cause either of the pieces to have zero size.
374
375 If 'a' is not found, or if no splitting happens, -1 is returned.
376
377 If a value 'r' other than -1 is returned, this is the index of the
378 higher-addressed segment resulting from the split, and the index of
379 the lower-addressed segment is r-1.
380*/
381static Int split_segment ( Addr a )
382{
383 Int r;
384 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000385 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000386 r = find_segment(a);
387 if (r == -1)
388 /* not found */
389 return -1;
390 if (segments[r].addr == a)
391 /* segment starts at 'a', so splitting it would create a
392 zero-sized segment */
393 return -1;
394
395 /* copy original; make adjustments. */
396 vg_assert(a > segments[r].addr);
397 delta = a - segments[r].addr;
398 make_space_at(r);
399 segments[r] = segments[r+1];
400 segments[r].len = delta;
401 segments[r+1].len -= delta;
402 segments[r+1].addr += delta;
403 segments[r+1].offset += delta;
404 return r+1;
405}
406
sewardj79048ce2005-02-18 08:28:32 +0000407
408/* Return true if two segments are adjacent and mergable (s1 is
409 assumed to have a lower ->addr than s2) */
410static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
411{
412 if (s1->addr+s1->len != s2->addr)
413 return False;
414
415 if (s1->flags != s2->flags)
416 return False;
417
418 if (s1->prot != s2->prot)
419 return False;
420
njn36ef6ba2005-05-14 18:42:26 +0000421 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000422 return False;
423
424 if (s1->flags & SF_FILE){
425 if ((s1->offset + s1->len) != s2->offset)
426 return False;
427 if (s1->dev != s2->dev)
428 return False;
429 if (s1->ino != s2->ino)
430 return False;
431 if (s1->fnIdx != s2->fnIdx)
432 return False;
433 }
434
435 return True;
436}
437
438
439/* Clean up and sanity check the segment array:
440 - check segments are in ascending order
441 - check segments do not overlap
442 - check no segment has zero size
443 - merge adjacent where possible
444 - perform checks on the filename table, and reclaim dead entries
445*/
446static void preen_segments ( void )
447{
448 Int i, j, rd, wr;
449 Segment *s, *s1;
450 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
451 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
452
453 if (0) show_segments("before preen");
454
455 /* clear string table mark bits */
456 for (i = 0; i < segnames_used; i++)
457 segnames[i].mark = False;
458
459 /* check for non-zero size, and set mark bits for any used strings */
460 for (i = 0; i < segments_used; i++) {
461 vg_assert(segments[i].len > 0);
462 j = segments[i].fnIdx;
463 vg_assert(j >= -1 && j < segnames_used);
464 if (j >= 0) {
465 vg_assert(segnames[j].inUse);
466 segnames[j].mark = True;
467 }
468 }
469
470 /* check ascendingness and non-overlap */
471 for (i = 0; i < segments_used-1; i++) {
472 s = &segments[i];
473 s1 = &segments[i+1];
474 vg_assert(s->addr < s1->addr);
475 vg_assert(s->addr + s->len <= s1->addr);
476 }
477
478 /* merge */
479 if (segments_used < 1)
480 return;
481
482 wr = 1;
483 for (rd = 1; rd < segments_used; rd++) {
484 s = &segments[wr-1];
485 s1 = &segments[rd];
486 if (segments_are_mergeable(s,s1)) {
487 if (0)
488 VG_(printf)("merge %p-%p with %p-%p\n",
489 s->addr, s->addr+s->len,
490 s1->addr, s1->addr+s1->len);
491 s->len += s1->len;
492 continue;
493 }
494 if (wr < rd)
495 segments[wr] = segments[rd];
496 wr++;
497 }
498 vg_assert(wr >= 0 && wr <= segments_used);
499 segments_used = wr;
500
501 /* Free up any strings which are no longer referenced. */
502 for (i = 0; i < segnames_used; i++) {
503 if (segnames[i].mark == False) {
504 segnames[i].inUse = False;
505 segnames[i].fname[0] = 0;
506 }
507 }
508
509 if (0) show_segments("after preen");
510}
511
512
sewardj548be6d2005-02-16 01:31:37 +0000513/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000514/*--- Maintain an ordered list of all the client's mappings ---*/
515/*--------------------------------------------------------------*/
516
nethercote8991d5a2004-11-03 17:07:46 +0000517Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000518{
519 Addr se = s->addr+s->len;
520 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000521 vg_assert(pe >= p);
522
523 return (p >= s->addr && pe <= se);
524}
525
nethercote8991d5a2004-11-03 17:07:46 +0000526Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000527{
528 Addr se = s->addr+s->len;
529 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000530 vg_assert(pe >= p);
531
532 return (p < se && pe > s->addr);
533}
534
sewardj1024cf72005-02-28 14:39:21 +0000535#if 0
536/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000537/* Prepare a Segment structure for recycling by freeing everything
538 hanging off it. */
539static void recycleseg(Segment *s)
540{
541 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000542 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000543
544 if (s->filename != NULL)
545 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
546
547 /* keep the SegInfo, if any - it probably still applies */
548}
549
550/* When freeing a Segment, also clean up every one else's ideas of
551 what was going on in that range of memory */
552static void freeseg(Segment *s)
553{
554 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000555 if (s->seginfo != NULL) {
556 VG_(seginfo_decref)(s->seginfo, s->addr);
557 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000558 }
559
560 VG_(SkipNode_Free)(&sk_segments, s);
561}
sewardj1024cf72005-02-28 14:39:21 +0000562#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000563
sewardj1024cf72005-02-28 14:39:21 +0000564
565/* Get rid of any translations arising from s. */
566/* Note, this is not really the job of the low level memory manager.
567 When it comes time to rewrite this subsystem, clean this up. */
568static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000569{
sewardj1024cf72005-02-28 14:39:21 +0000570 if (s->flags & SF_CODE) {
571 VG_(discard_translations)(s->addr, s->len);
572 if (0)
573 VG_(printf)("dumping translations in %p .. %p\n",
574 s->addr, s->addr+s->len);
575 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000576}
577
sewardj1024cf72005-02-28 14:39:21 +0000578
fitzhardinge98abfc72003-12-16 02:05:15 +0000579/* This unmaps all the segments in the range [addr, addr+len); any
580 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000581void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000582{
fitzhardingee3632c62003-12-22 10:58:06 +0000583 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000584 Segment* s;
585 Addr end, s_end;
586 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000587 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000588
589 if (len == 0)
590 return;
591
njn13bfd852005-06-02 03:52:53 +0000592 len = VG_PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000593
fitzhardinge98abfc72003-12-16 02:05:15 +0000594 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000595 VG_(printf)("unmap_range(%p, %llu)\n", addr, (ULong)len);
sewardj79048ce2005-02-18 08:28:32 +0000596 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000597 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000598
599 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000600 vg_assert(VG_IS_PAGE_ALIGNED(addr));
601 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000602
sewardj548be6d2005-02-16 01:31:37 +0000603 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000604
605 /* do not delete .. even though it looks stupid */
606 vg_assert(i >= 0);
607
608 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000609 s = &segments[i];
610 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000611
sewardj548be6d2005-02-16 01:31:37 +0000612 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000613 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000614 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000615
fitzhardinge1a303042003-12-22 08:48:50 +0000616 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000617 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000618 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000619 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000620 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000621
622 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000623 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000624 addr < s_end &&
625 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000626 /* this segment's tail is truncated by [addr, addr+len)
627 -> truncate tail
628 */
sewardj1024cf72005-02-28 14:39:21 +0000629 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000630 s->len = addr - s->addr;
631
632 if (debug)
tom9be7c982005-04-25 16:55:44 +0000633 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000634 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000635 /* this segment's head is truncated by [addr, addr+len)
636 -> truncate head
637 */
sewardj548be6d2005-02-16 01:31:37 +0000638 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000639
640 if (debug)
tom9be7c982005-04-25 16:55:44 +0000641 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000642 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000643
sewardj1024cf72005-02-28 14:39:21 +0000644 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000645 s->addr += delta;
646 s->offset += delta;
647 s->len -= delta;
648
649 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000650 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000651 /* this segment is completely contained within [addr, addr+len)
652 -> delete segment
653 */
sewardj1024cf72005-02-28 14:39:21 +0000654 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000655 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000656 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000657
658 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000659 VG_(printf)(" case 3: seg %d deleted\n", i);
660 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000661 /* [addr, addr+len) is contained within a single segment
662 -> split segment into 3, delete middle portion
663 */
sewardj1024cf72005-02-28 14:39:21 +0000664 Int i_middle;
665 dump_translations_from(s);
666 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000667 vg_assert(i_middle != -1);
668 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000669 vg_assert(segments[i_middle].addr == addr);
670 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000671 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000672
673 if (debug)
674 VG_(printf)(" case 4: subrange %p-%p deleted\n",
675 addr, addr+len);
676 }
sewardj47c98a72005-03-12 20:36:15 +0000677
678 /* If we deleted this segment (or any above), those above will
679 have been moved down to fill in the hole in the segment
680 array. In order that we don't miss them, we have to
681 re-consider this slot number; hence the i--. */
682 if (deleted)
683 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000684 }
sewardj79048ce2005-02-18 08:28:32 +0000685 preen_segments();
686 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000687}
688
sewardj548be6d2005-02-16 01:31:37 +0000689
690/* Add a binding of [addr,addr+len) to
691 (prot,flags,dev,ino,off,filename) in the segment array.
692 Delete/truncate any previous mapping(s) covering that range.
693*/
694void
695VG_(map_file_segment)( Addr addr, SizeT len,
696 UInt prot, UInt flags,
697 UInt dev, UInt ino, ULong off,
698 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000699{
fitzhardinge98abfc72003-12-16 02:05:15 +0000700 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000701 Segment* s;
702 Int idx;
sewardja8d8e232005-06-07 20:04:56 +0000703 HChar* stage2_suffix = "lib/valgrind/stage2";
704 Bool is_stage2 = VG_(strstr)(filename, stage2_suffix) != NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000705
706 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000707 VG_(printf)(
708 "\n"
tom9be7c982005-04-25 16:55:44 +0000709 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000710 " dev=0x%4x ino=%d off=%ld\n"
711 " filename='%s')\n",
712 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000713
sewardja8d8e232005-06-07 20:04:56 +0000714 if (0) show_segments("before map_file_segment");
715
fitzhardinge98abfc72003-12-16 02:05:15 +0000716 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000717 vg_assert(VG_IS_PAGE_ALIGNED(addr));
njn13bfd852005-06-02 03:52:53 +0000718 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000719
sewardj548be6d2005-02-16 01:31:37 +0000720 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
721 VG_(unmap_range)(addr, len);
722
723 /* and now install this one */
724 idx = create_segment(addr);
725 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
726 vg_assert(idx != -1);
727 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000728
sewardj79048ce2005-02-18 08:28:32 +0000729 s = &segments[idx];
730 vg_assert(s->addr == addr);
731 s->prot = prot;
732 s->flags = flags;
733 s->len = len;
734 s->offset = off;
735 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
736 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
737 s->dev = dev;
738 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000739 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000740
sewardj79048ce2005-02-18 08:28:32 +0000741 /* Clean up right now */
742 preen_segments();
743 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000744
745 /* If this mapping is of the beginning of a file, isn't part of
746 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000747 file, then try reading symbols from it.
748 */
njn36ef6ba2005-05-14 18:42:26 +0000749 if (s->seginfo == NULL
sewardja8d8e232005-06-07 20:04:56 +0000750 && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
751 || is_stage2
752 )
sewardj79048ce2005-02-18 08:28:32 +0000753 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
754 if (off == 0
755 && s->fnIdx != -1
756 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
757 && len >= VKI_PAGE_SIZE
758 && VG_(is_object_file)((void *)addr)) {
njn36ef6ba2005-05-14 18:42:26 +0000759 s->seginfo = VG_(read_seg_symbols)(s);
760 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000761 s->flags |= SF_DYNLIB;
762 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000763 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000764#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000765 const SegInfo *info;
766
njn36ef6ba2005-05-14 18:42:26 +0000767 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000768 for(info = VG_(next_seginfo)(NULL);
769 info != NULL;
770 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000771 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
772 {
njn36ef6ba2005-05-14 18:42:26 +0000773 s->seginfo = (SegInfo *)info;
774 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000775 }
776 }
sewardj79048ce2005-02-18 08:28:32 +0000777#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000778 }
779 }
780
781 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000782 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000783}
784
nethercote8b5f40c2004-11-02 13:29:50 +0000785void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000786 Int fd, ULong off, const Char *filename)
787{
njnf845f8f2005-06-23 02:26:47 +0000788 Char buf[VKI_PATH_MAX];
fitzhardinge98abfc72003-12-16 02:05:15 +0000789 struct vki_stat st;
fitzhardinge98abfc72003-12-16 02:05:15 +0000790
791 st.st_dev = 0;
792 st.st_ino = 0;
793
794 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000795 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000796
797 if (VG_(fstat)(fd, &st) < 0)
798 flags &= ~SF_FILE;
799 }
800
sewardj79048ce2005-02-18 08:28:32 +0000801 if ((flags & SF_FILE) && filename == NULL && fd != -1)
njnf845f8f2005-06-23 02:26:47 +0000802 if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX))
803 filename = buf;
fitzhardinge98abfc72003-12-16 02:05:15 +0000804
sewardj79048ce2005-02-18 08:28:32 +0000805 VG_(map_file_segment)(addr, len, prot, flags,
806 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000807}
808
nethercote8b5f40c2004-11-02 13:29:50 +0000809void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000810{
811 flags &= ~SF_FILE;
812
813 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
814}
815
816/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000817void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000818{
sewardj79048ce2005-02-18 08:28:32 +0000819 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000820 static const Bool debug = False || mem_debug;
821
822 if (debug)
tom9be7c982005-04-25 16:55:44 +0000823 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000824
825 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000826
827 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000828 vg_assert(VG_IS_PAGE_ALIGNED(a));
njn13bfd852005-06-02 03:52:53 +0000829 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000830
sewardj79048ce2005-02-18 08:28:32 +0000831 split_segment(a);
832 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000833
sewardj548be6d2005-02-16 01:31:37 +0000834 r = find_segment(a);
835 vg_assert(r != -1);
836 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000837
838 preen_segments();
839
sewardje517b802005-02-16 01:58:51 +0000840 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000841}
842
sewardj79048ce2005-02-18 08:28:32 +0000843
sewardj548be6d2005-02-16 01:31:37 +0000844/* Try to find a map space for [addr,addr+len). If addr==0, it means
845 the caller is prepared to accept a space at any location; if not,
846 we will try for addr, but fail if we can't get it. This mimics
847 mmap fixed vs mmap not-fixed.
848*/
nethercote8b5f40c2004-11-02 13:29:50 +0000849Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000850{
fitzhardingee3632c62003-12-22 10:58:06 +0000851 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000852 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000853 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000854 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
855 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000856 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
857 Int i, i_any, i_fixed, i_final;
858 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000859
sewardj548be6d2005-02-16 01:31:37 +0000860 Bool fixed;
861
sewardje517b802005-02-16 01:58:51 +0000862 if (debug) {
863 VG_(printf)("\n\n");
sewardja8d8e232005-06-07 20:04:56 +0000864 VG_(printf)("find_map_space(%p, %llu, %d) ...\n",
865 addr, (ULong)len, for_client);
sewardje517b802005-02-16 01:58:51 +0000866 }
867
868 if (0) show_segments("find_map_space: start");
869
sewardj548be6d2005-02-16 01:31:37 +0000870 if (addr == 0) {
871 fixed = False;
872 } else {
873 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000874 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000875 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000876 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000877 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000878
879 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000880 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
njn13bfd852005-06-02 03:52:53 +0000881 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000882
nethercote73b526f2004-10-31 18:48:21 +0000883 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000884
sewardj548be6d2005-02-16 01:31:37 +0000885 /* Scan the segment list, looking for a hole which satisfies the
886 requirements. At each point i we ask the question "can we use
887 the hole in between segments[i-1] and segments[i] ?" */
888 i_any = i_fixed = -1;
889 hstart_any = hstart_fixed = 0;
890
891 hole_start = hole_end = 0;
892
893 /* Iterate over all possible holes, generating them into
894 hole_start/hole_end. Filter out invalid ones. Then see if any
895 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
896 */
897 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
898 if (i == 0) {
899 hole_start = 0;
900 hole_end = segments[0].addr-1;
901 }
902 else {
903 vg_assert(segments_used > 0);
904 if (i == segments_used) {
905 hole_start = segments[i-1].addr + segments[i-1].len;
906 hole_end = ~(Addr)0;
907 } else {
908 hole_start = segments[i-1].addr + segments[i-1].len;
909 hole_end = segments[i].addr - 1;
910 }
911 }
912
913 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
914
915 /* ignore zero-sized holes */
916 if (hole_start == hole_end+1)
917 continue;
918
njnbe91aae2005-03-27 01:42:41 +0000919 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
920 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000921
922 /* ignore holes which fall outside the allowable area */
923 if (!(hole_start >= base && hole_end <= limit))
924 continue;
925
926 vg_assert(hole_end > hole_start);
927 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000928 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000929
930 if (hole_len >= len && i_any == -1) {
931 /* It will at least fit in this hole. */
932 i_any = i;
933 hstart_any = hole_start;
934 }
935
sewardjb5f6f512005-03-10 23:59:00 +0000936 if (fixed && hole_start <= addr
937 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000938 /* We were asked for a fixed mapping, and this hole works.
939 Bag it -- and stop searching as further searching is
940 pointless. */
941 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000942 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000943 break;
944 }
945 }
946
947 /* Summarise the final decision into i_final/hstart_final. */
948 i_final = -1;
949 hstart_final = 0;
950
951 if (fixed) {
952 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000953 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000954 } else {
955 i_final = i_any;
956 hstart_final = hstart_any;
957 }
958
959
960 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +0000961 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +0000962 else
963 ret = 0; /* not found */
964
965 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000966 VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n",
967 addr, (ULong)len, for_client, ret);
sewardj548be6d2005-02-16 01:31:37 +0000968
sewardjb5f6f512005-03-10 23:59:00 +0000969 if (fixed) {
970 vg_assert(ret == 0 || ret == addrOrig);
971 }
972
sewardj548be6d2005-02-16 01:31:37 +0000973 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000974}
975
sewardj79048ce2005-02-18 08:28:32 +0000976
sewardjb5f6f512005-03-10 23:59:00 +0000977/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +0000978 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000979 mapping over any part of the address space which is not covered
980 by an entry in the segment list.
981
982 This is designed for use around system calls which allocate
983 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000984 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000985 address with VG_(find_map_space) and then adding a segment for
986 it and padding the address space valgrind can ensure that the
987 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +0000988void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +0000989{
sewardj394790d2005-03-17 02:14:44 +0000990 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +0000991 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +0000992
993 Int i = 0;
994 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +0000995
nethercote820bd8c2004-09-07 23:04:49 +0000996 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000997 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +0000998 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +0000999 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1000 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001001 }
thughes9aaebc32004-07-15 23:13:37 +00001002 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001003 i++;
1004 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001005 }
1006
nethercote820bd8c2004-09-07 23:04:49 +00001007 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001008 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001009 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1010 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001011 }
thughes9aaebc32004-07-15 23:13:37 +00001012}
1013
thughesc70b8c62004-07-16 23:07:58 +00001014/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001015 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001016void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001017{
sewardj394790d2005-03-17 02:14:44 +00001018 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001019 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001020
1021 Int i = 0;
1022 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001023
nethercote820bd8c2004-09-07 23:04:49 +00001024 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001025 if (addr < s->addr) {
njnca6fef02004-11-29 16:49:18 +00001026 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001027 }
thughes9aaebc32004-07-15 23:13:37 +00001028 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001029 i++;
1030 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001031 }
1032
nethercote820bd8c2004-09-07 23:04:49 +00001033 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001034 ret = VG_(do_syscall2)(__NR_munmap, addr,
1035 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001036 }
thughes9aaebc32004-07-15 23:13:37 +00001037}
1038
sewardj548be6d2005-02-16 01:31:37 +00001039/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001040Segment *VG_(find_segment)(Addr a)
1041{
sewardj548be6d2005-02-16 01:31:37 +00001042 Int r = find_segment(a);
1043 if (0) show_segments("find_segment");
1044 if (r == -1) return NULL;
1045 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001046}
1047
sewardj548be6d2005-02-16 01:31:37 +00001048/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1049 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1050 a segment is a checked error.
1051*/
1052Segment *VG_(find_segment_above_unmapped)(Addr a)
1053{
1054 Int r = find_segment_above_unmapped(a);
1055 if (0) show_segments("find_segment_above_unmapped");
1056 if (r == -1) return NULL;
1057 return &segments[r];
1058}
1059
1060/* Assumes that 'a' is in some segment. Finds the next segment along,
1061 or NULL if none. Passing 'a' which is in fact not in a segment is
1062 a checked error.
1063*/
1064Segment *VG_(find_segment_above_mapped)(Addr a)
1065{
1066 Int r = find_segment_above_mapped(a);
1067 if (0) show_segments("find_segment_above_mapped");
1068 if (r == -1) return NULL;
1069 return &segments[r];
1070}
1071
1072
sewardjde4a1d02002-03-22 01:27:54 +00001073/*------------------------------------------------------------*/
1074/*--- Tracking permissions around %esp changes. ---*/
1075/*------------------------------------------------------------*/
1076
1077/*
1078 The stack
1079 ~~~~~~~~~
sewardjfa8202f2005-04-24 11:05:55 +00001080 The stack's segment seems to be dynamically extended downwards by
1081 the kernel as the stack pointer moves down. Initially, a 1-page
1082 (4k) stack is allocated. When SP moves below that for the first
1083 time, presumably a page fault occurs. The kernel detects that the
njnaf839f52005-06-23 03:27:57 +00001084 faulting address is in the range from SP - VG_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001085 upwards to the current valid stack. It then extends the stack
1086 segment downwards for enough to cover the faulting address, and
1087 resumes the process (invisibly). The process is unaware of any of
1088 this.
sewardjde4a1d02002-03-22 01:27:54 +00001089
sewardjfa8202f2005-04-24 11:05:55 +00001090 That means that Valgrind can't spot when the stack segment is being
1091 extended. Fortunately, we want to precisely and continuously
1092 update stack permissions around SP, so we need to spot all writes
1093 to SP anyway.
sewardjde4a1d02002-03-22 01:27:54 +00001094
sewardjfa8202f2005-04-24 11:05:55 +00001095 The deal is: when SP is assigned a lower value, the stack is being
1096 extended. Create suitably-permissioned pages to fill in any holes
1097 between the old stack ptr and this one, if necessary. Then mark
1098 all bytes in the area just "uncovered" by this SP change as
1099 write-only.
sewardjde4a1d02002-03-22 01:27:54 +00001100
sewardjfa8202f2005-04-24 11:05:55 +00001101 When SP goes back up, mark the area receded over as unreadable and
1102 unwritable.
sewardjde4a1d02002-03-22 01:27:54 +00001103
njna60a7c12005-05-08 17:49:37 +00001104 Just to record the SP boundary conditions somewhere convenient:
njnaf839f52005-06-23 03:27:57 +00001105 SP - VG_STACK_REDZONE_SZB always points to the lowest live byte in
1106 the stack. All addresses below SP - VG_STACK_REDZONE_SZB are not
sewardjfa8202f2005-04-24 11:05:55 +00001107 live; those at and above it are.
1108
njnaf839f52005-06-23 03:27:57 +00001109 We do not concern ourselves here with the VG_STACK_REDZONE_SZB
sewardjfa8202f2005-04-24 11:05:55 +00001110 bias; that is handled by new_mem_stack/die_mem_stack.
sewardjde4a1d02002-03-22 01:27:54 +00001111*/
1112
rjwalsh0140af52005-06-04 20:42:33 +00001113/*
1114 * This structure holds information about the start and end addresses of
1115 * registered stacks. There's always at least one stack registered:
1116 * the main process stack. It will be the first stack registered and
1117 * so will have a stack id of 0. The user does not need to register
1118 * this stack: Valgrind does it automatically right before it starts
1119 * running the client. No other stacks are automatically registered by
1120 * Valgrind, however.
1121 */
1122
1123typedef struct _Stack {
1124 UWord id;
1125 Addr start;
1126 Addr end;
1127 struct _Stack *next;
1128} Stack;
1129
1130static Stack *stacks;
1131static UWord next_id; /* Next id we hand out to a newly registered stack */
1132
1133/*
1134 * These are the id, start and end values of the current stack. If the
1135 * stack pointer falls outside the range of the current stack, we search
1136 * the stacks list above for a matching stack.
1137 */
1138
1139static Addr current_stack_start;
1140static Addr current_stack_end;
1141static UWord current_stack_id;
1142
1143/* Search for a particular stack by id number. */
1144static Bool find_stack_by_id(UWord id, Addr *start, Addr *end)
1145{
1146 Stack *i = stacks;
1147 while(i) {
1148 if(i->id == id) {
1149 *start = i->start;
1150 *end = i->end;
1151 return True;
1152 }
1153 i = i->next;
1154 }
1155 return False;
1156}
1157
1158/* Find what stack an address falls into. */
1159static Bool find_stack_by_addr(Addr sp, Addr *start, Addr *end, UWord *id)
1160{
1161 Stack *i = stacks;
1162 while(i) {
1163 if(sp >= i->start && sp <= i->end) {
1164 *start = i->start;
1165 *end = i->end;
1166 *id = i->id;
1167 return True;
1168 }
1169 i = i->next;
1170 }
1171 return False;
1172}
1173
1174/* Change over to a new stack. */
1175static Bool set_current_stack(UWord id)
1176{
1177 Addr start, end;
1178 if (find_stack_by_id(id, &start, &end)) {
1179 current_stack_id = id;
1180 current_stack_start = start;
1181 current_stack_end = end;
1182 return True;
1183 }
1184 return False;
1185}
1186
1187/*
1188 * Register a new stack from start - end. This is invoked from the
1189 * VALGRIND_STACK_REGISTER client request, and is also called just before
1190 * we start the client running, to register the main process stack.
1191 *
1192 * Note: this requires allocating a piece of memory to store the Stack
1193 * structure, which places a dependency between this module and the
1194 * mallocfree module. However, there is no real chance of a circular
1195 * dependency here, since the mallocfree module would never call back to
1196 * this function.
1197 */
1198
1199UWord VG_(handle_stack_register)(Addr start, Addr end)
1200{
1201 Stack *i;
1202 if (start > end) {
1203 Addr t = end;
1204 end = start;
1205 start = t;
1206 }
1207
1208 i = (Stack *)VG_(arena_malloc)(VG_AR_CORE, sizeof(Stack));
1209 i->start = start;
1210 i->end = end;
1211 i->id = next_id++;
1212 i->next = stacks;
1213 stacks = i;
1214
1215 if(i->id == 0) {
1216 set_current_stack(i->id);
1217 }
1218
1219 return i->id;
1220}
1221
1222/*
1223 * Deregister a stack. This is invoked from the VALGRIND_STACK_DEREGISTER
1224 * client request.
1225 *
1226 * Note: this requires freeing the piece of memory that was used to store
1227 * the Stack structure, which places a dependency between this module
1228 * and the mallocfree module. However, there is no real chance of
1229 * a circular dependency here, since the mallocfree module would never
1230 * call back to this function.
1231 */
1232
1233void VG_(handle_stack_deregister)(UWord id)
1234{
1235 Stack *i = stacks;
1236 Stack *prev = NULL;
1237
1238 if(current_stack_id == id) {
1239 return;
1240 }
1241
1242 while(i) {
1243 if (i->id == id) {
1244 if(prev == NULL) {
1245 stacks = i->next;
1246 } else {
1247 prev->next = i->next;
1248 }
1249 VG_(arena_free)(VG_AR_CORE, i);
1250 return;
1251 }
1252 prev = i;
1253 i = i->next;
1254 }
1255}
1256
1257/*
1258 * Change a stack. This is invoked from the VALGRIND_STACK_CHANGE client
1259 * request and from the stack growth stuff the signals module when
1260 * extending the main process stack.
1261 */
1262
1263void VG_(handle_stack_change)(UWord id, Addr start, Addr end)
1264{
1265 Stack *i = stacks;
1266
1267 if (id == current_stack_id) {
1268 current_stack_start = start;
1269 current_stack_end = end;
1270 }
1271
1272 while(i) {
1273 if (i->id == id) {
1274 i->start = start;
1275 i->end = end;
1276 return;
1277 }
1278 i = i->next;
1279 }
1280}
1281
njn9b007f62003-04-07 14:40:25 +00001282/* This function gets called if new_mem_stack and/or die_mem_stack are
sewardjfa8202f2005-04-24 11:05:55 +00001283 tracked by the tool, and one of the specialised cases
1284 (eg. new_mem_stack_4) isn't used in preference.
1285*/
njnaf839f52005-06-23 03:27:57 +00001286VG_REGPARM(2)
sewardj2a99cf62004-11-24 10:44:19 +00001287void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP )
sewardjde4a1d02002-03-22 01:27:54 +00001288{
sewardj97724e52005-04-02 23:40:59 +00001289 static Int moans = 3;
nethercotefc646ee2004-11-04 19:29:06 +00001290 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +00001291
rjwalsh0140af52005-06-04 20:42:33 +00001292 /* Check if the stack pointer is still in the same stack as before. */
1293 if (new_SP < current_stack_start || new_SP > current_stack_end) {
1294 Addr start, end;
1295 UWord new_id;
1296 Bool found = find_stack_by_addr(new_SP, &start, &end, &new_id);
1297 if (found && new_id != current_stack_id) {
1298 /* The stack pointer is now in another stack. Update the current
1299 stack information and return without doing anything else. */
1300 set_current_stack(new_id);
1301 return;
1302 }
1303 }
1304
sewardj97724e52005-04-02 23:40:59 +00001305 if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
1306 /* SP has changed by more than some threshold amount (by
1307 default, 2MB). We take this to mean that the application is
1308 switching to a new stack, for whatever reason.
njn9b007f62003-04-07 14:40:25 +00001309
1310 JRS 20021001: following discussions with John Regehr, if a stack
1311 switch happens, it seems best not to mess at all with memory
1312 permissions. Seems to work well with Netscape 4.X. Really the
1313 only remaining difficulty is knowing exactly when a stack switch is
1314 happening. */
sewardj97724e52005-04-02 23:40:59 +00001315 if (VG_(clo_verbosity) > 0 && moans > 0) {
1316 moans--;
1317 VG_(message)(Vg_UserMsg,
1318 "Warning: client switching stacks? "
1319 "SP change: %p --> %p", old_SP, new_SP);
1320 VG_(message)(Vg_UserMsg,
1321 " to suppress, use: --max-stackframe=%d or greater",
1322 (delta < 0 ? -delta : delta));
1323 if (moans == 0)
1324 VG_(message)(Vg_UserMsg,
1325 " further instances of this message "
1326 "will not be shown.");
1327 }
njn9b007f62003-04-07 14:40:25 +00001328 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +00001329 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +00001330
njn9b007f62003-04-07 14:40:25 +00001331 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +00001332 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +00001333 }
1334}
1335
jsgf855d93d2003-10-13 22:26:55 +00001336/*
sewardjb5f6f512005-03-10 23:59:00 +00001337 Test if a piece of memory is addressable with at least the "prot"
1338 protection permissions by examining the underlying segments.
1339
1340 Really this is a very stupid algorithm and we could do much
1341 better by iterating through the segment array instead of through
1342 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001343 */
sewardjb5f6f512005-03-10 23:59:00 +00001344Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001345{
sewardjb5f6f512005-03-10 23:59:00 +00001346 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001347
sewardjb5f6f512005-03-10 23:59:00 +00001348 if ((p + size) < p)
1349 return False; /* reject wraparounds */
1350 if (size == 0)
1351 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001352
njn13bfd852005-06-02 03:52:53 +00001353 p = VG_PGROUNDDN(p);
1354 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001355 vg_assert(VG_IS_PAGE_ALIGNED(p));
1356 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001357
sewardjb5f6f512005-03-10 23:59:00 +00001358 for (; size > 0; size -= VKI_PAGE_SIZE) {
1359 seg = VG_(find_segment)(p);
1360 if (!seg)
1361 return False;
1362 if ((seg->prot & prot) != prot)
1363 return False;
1364 p += VKI_PAGE_SIZE;
1365 }
jsgf855d93d2003-10-13 22:26:55 +00001366
sewardjb5f6f512005-03-10 23:59:00 +00001367 return True;
jsgf855d93d2003-10-13 22:26:55 +00001368}
1369
sewardjb5f6f512005-03-10 23:59:00 +00001370
sewardjde4a1d02002-03-22 01:27:54 +00001371/*--------------------------------------------------------------------*/
njn9260c782005-06-19 21:57:54 +00001372/*--- Random function that doesn't really belong here ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001373/*--------------------------------------------------------------------*/
1374
njn86f12dc2005-03-14 01:16:05 +00001375/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001376 range, which isn't SF_CORE, a root.
1377*/
njn86f12dc2005-03-14 01:16:05 +00001378void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1379{
sewardj882af5f2005-03-16 12:27:53 +00001380 Int i;
1381 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001382 Segment *s;
1383
sewardj882af5f2005-03-16 12:27:53 +00001384 for (i = 0; i < segments_used; i++) {
1385 s = &segments[i];
1386 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1387 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001388 if (flags != SF_MMAP && flags != SF_STACK)
1389 continue;
sewardj882af5f2005-03-16 12:27:53 +00001390 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1391 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001392 continue;
1393 if (!VG_(is_client_addr)(s->addr) ||
1394 !VG_(is_client_addr)(s->addr+s->len))
1395 continue;
1396
1397 (*add_rootrange)(s->addr, s->len);
1398 }
njn86f12dc2005-03-14 01:16:05 +00001399}
1400
1401
nethercote88a90162004-07-10 16:59:25 +00001402/*--------------------------------------------------------------------*/
1403/*--- Querying memory layout ---*/
1404/*--------------------------------------------------------------------*/
1405
fitzhardinge98abfc72003-12-16 02:05:15 +00001406Bool VG_(is_client_addr)(Addr a)
1407{
1408 return a >= VG_(client_base) && a < VG_(client_end);
1409}
1410
1411Bool VG_(is_shadow_addr)(Addr a)
1412{
1413 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1414}
1415
sewardjfa8202f2005-04-24 11:05:55 +00001416
nethercote88a90162004-07-10 16:59:25 +00001417/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001418/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001419/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001420
1421void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
1422{
sewardj548be6d2005-02-16 01:31:37 +00001423vg_assert(0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001424 if (0)
1425 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
1426
1427 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001428 vg_assert(VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001429
njn13bfd852005-06-02 03:52:53 +00001430 sz = VG_PGROUNDUP(p+sz) - VG_PGROUNDDN(p);
1431 p = VG_PGROUNDDN(p);
fitzhardinge98abfc72003-12-16 02:05:15 +00001432
1433 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
1434
1435 if (call_init)
1436 while(sz) {
nethercote996901a2004-08-03 13:29:09 +00001437 /* ask the tool to initialize each page */
njn13bfd852005-06-02 03:52:53 +00001438 VG_TRACK( init_shadow_page, VG_PGROUNDDN(p) );
fitzhardinge98abfc72003-12-16 02:05:15 +00001439
nethercote73b526f2004-10-31 18:48:21 +00001440 p += VKI_PAGE_SIZE;
1441 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +00001442 }
1443}
1444
1445void *VG_(shadow_alloc)(UInt size)
1446{
1447 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001448 Addr try_here;
njne9befc62005-06-11 15:51:30 +00001449 SysRes r;
sewardj79048ce2005-02-18 08:28:32 +00001450
1451 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001452
1453 vg_assert(VG_(needs).shadow_memory);
njn51d827b2005-05-09 01:02:08 +00001454 vg_assert(!VG_(tdict).track_init_shadow_page);
fitzhardinge98abfc72003-12-16 02:05:15 +00001455
njn13bfd852005-06-02 03:52:53 +00001456 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001457
1458 if (shadow_alloc == 0)
1459 shadow_alloc = VG_(shadow_base);
1460
1461 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001462 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001463
sewardj79048ce2005-02-18 08:28:32 +00001464 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001465 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1466 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001467 vg_assert(size > 0);
1468
1469 if (0)
1470 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1471
1472 /* this is big-bang allocated, so we don't expect to find a listed
1473 segment for it. */
1474 /* This is really an absolute disgrace. Sometimes the big-bang
1475 mapping is in the list (due to re-reads of /proc/self/maps,
1476 presumably) and sometimes it isn't. */
1477#if 0
1478 r = find_segment(try_here);
1479 vg_assert(r == -1);
1480 r = find_segment(try_here+size-1);
1481 vg_assert(r == -1);
1482#endif
1483
1484 r = VG_(mprotect_native)( (void*)try_here,
1485 size, VKI_PROT_READ|VKI_PROT_WRITE );
1486
njne9befc62005-06-11 15:51:30 +00001487 if (r.isError)
sewardj79048ce2005-02-18 08:28:32 +00001488 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001489
1490 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001491 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001492
sewardj79048ce2005-02-18 08:28:32 +00001493 failed:
1494 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001495 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001496 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001497 size
sewardj79048ce2005-02-18 08:28:32 +00001498 );
1499 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001500}
1501
njne3f06352005-06-01 03:48:33 +00001502/*------------------------------------------------------------*/
1503/*--- pointercheck ---*/
1504/*------------------------------------------------------------*/
1505
njnaf839f52005-06-23 03:27:57 +00001506Bool VG_(setup_pointercheck)(Addr client_base, Addr client_end)
njne3f06352005-06-01 03:48:33 +00001507{
1508 vg_assert(0 != client_end);
1509#if defined(VGP_x86_linux)
1510 /* Client address space segment limit descriptor entry */
1511 #define POINTERCHECK_SEGIDX 1
1512
1513 vki_modify_ldt_t ldt = {
1514 POINTERCHECK_SEGIDX, // entry_number
1515 client_base, // base_addr
1516 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1517 1, // seg_32bit
1518 0, // contents: data, RW, non-expanding
1519 0, // ! read_exec_only
1520 1, // limit_in_pages
1521 0, // ! seg not present
1522 1, // useable
1523 };
sewardja8d8e232005-06-07 20:04:56 +00001524 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1525 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001526 VG_(message)(Vg_UserMsg,
1527 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001528 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001529 return False;
1530 } else {
1531 return True;
1532 }
1533#elif defined(VGP_amd64_linux)
1534 if (0)
1535 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1536 return True;
cerion85665ca2005-06-20 15:51:07 +00001537#elif defined(VGP_ppc32_linux)
1538 if (0)
1539 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1540 return True;
njne3f06352005-06-01 03:48:33 +00001541#else
1542# error Unknown architecture
1543#endif
1544}
1545
fitzhardinge98abfc72003-12-16 02:05:15 +00001546/*--------------------------------------------------------------------*/
sewardj55f9d1a2005-04-25 11:11:44 +00001547/*--- end aspacemgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001548/*--------------------------------------------------------------------*/