blob: 64745c64707414586e47bf904dd58ba4dacb9ccc [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 ---*/
njn945ed2e2005-06-24 03:28:30 +00005/*--- m_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)
njn36a20fa2005-06-03 03:08:39 +000039#include "pub_core_libcprint.h"
njn9abd6082005-06-17 21:31:45 +000040#include "pub_core_syscall.h"
njn43b9a8a2005-05-10 04:37:01 +000041#include "pub_core_tooliface.h"
njn945ed2e2005-06-24 03:28:30 +000042#include "pub_core_transtab.h" // For VG_(discard_translations)
njn3c660b62005-05-13 22:18:47 +000043#include "vki_unistd.h"
sewardj55f9d1a2005-04-25 11:11:44 +000044
sewardjde4a1d02002-03-22 01:27:54 +000045
sewardja4495682002-10-21 07:29:59 +000046/* Define to debug the memory-leak-detector. */
47/* #define VG_DEBUG_LEAKCHECK */
48
sewardje517b802005-02-16 01:58:51 +000049static const Bool mem_debug = False;
sewardj548be6d2005-02-16 01:31:37 +000050
51/*--------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +000052/*--- Basic globals about the address space. ---*/
53/*--------------------------------------------------------------*/
54
55/* Client address space, lowest to highest (see top of ume.c) */
56Addr VG_(client_base); /* client address space limits */
57Addr VG_(client_end);
58Addr VG_(client_mapbase);
njn04e16982005-05-31 00:23:43 +000059Addr VG_(clstk_base);
60Addr VG_(clstk_end);
rjwalsh0140af52005-06-04 20:42:33 +000061UWord VG_(clstk_id);
njn04e16982005-05-31 00:23:43 +000062
63Addr VG_(brk_base); /* start of brk */
64Addr VG_(brk_limit); /* current brk */
65
66Addr VG_(shadow_base); /* tool's shadow memory */
67Addr VG_(shadow_end);
68
69Addr VG_(valgrind_base); /* valgrind's address range */
70
71// Note that VG_(valgrind_last) names the last byte of the section, whereas
72// the VG_(*_end) vars name the byte one past the end of the section.
73Addr VG_(valgrind_last);
74
75/*--------------------------------------------------------------*/
njnb69f7c12005-06-24 22:17:38 +000076/*--- The raw mman syscalls ---*/
77/*--------------------------------------------------------------*/
78
79SysRes VG_(mmap_native)(void *start, SizeT length, UInt prot, UInt flags,
80 UInt fd, OffT offset)
81{
82 SysRes res;
83#if defined(VGP_x86_linux)
84 {
85 UWord args[6];
86 args[0] = (UWord)start;
87 args[1] = length;
88 args[2] = prot;
89 args[3] = flags;
90 args[4] = fd;
91 args[5] = offset;
92 res = VG_(do_syscall1)(__NR_mmap, (UWord)args );
93 }
94#elif defined(VGP_amd64_linux)
95 res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
96 prot, flags, fd, offset);
97#elif defined(VGP_ppc32_linux)
98 res = VG_(do_syscall6)(__NR_mmap, (UWord)(start), (length),
99 prot, flags, fd, offset);
100#else
101# error Unknown platform
102#endif
103 return res;
104}
105
106SysRes VG_(munmap_native)(void *start, SizeT length)
107{
108 return VG_(do_syscall2)(__NR_munmap, (UWord)start, length );
109}
110
111SysRes VG_(mprotect_native)( void *start, SizeT length, UInt prot )
112{
113 return VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot );
114}
115
116/*--------------------------------------------------------------*/
sewardj79048ce2005-02-18 08:28:32 +0000117/*--- A simple, self-contained ordered array of segments. ---*/
sewardj548be6d2005-02-16 01:31:37 +0000118/*--------------------------------------------------------------*/
119
sewardj79048ce2005-02-18 08:28:32 +0000120/* Max number of segments we can track. */
121#define VG_N_SEGMENTS 1000
122
123/* Max number of segment file names we can track. */
124#define VG_N_SEGNAMES 200
125
126/* Max length of a segment file name. */
127#define VG_MAX_SEGNAMELEN 1000
128
129
130/* ------ STATE for the address-space manager ------ */
sewardj548be6d2005-02-16 01:31:37 +0000131
132/* Array [0 .. segments_used-1] of all mappings. */
133/* Sorted by .addr field. */
134/* I: len may not be zero. */
135/* I: overlapping segments are not allowed. */
sewardj79048ce2005-02-18 08:28:32 +0000136/* Each segment can optionally hold an index into the filename table. */
sewardj548be6d2005-02-16 01:31:37 +0000137
138static Segment segments[VG_N_SEGMENTS];
139static Int segments_used = 0;
140
sewardj79048ce2005-02-18 08:28:32 +0000141typedef
142 struct {
143 Bool inUse;
144 Bool mark;
145 HChar fname[VG_MAX_SEGNAMELEN];
146 }
147 SegName;
148
149/* Filename table. _used is the high water mark; an entry is only
150 valid if its index >= 0, < _used, and its .inUse field == True.
151 The .mark field is used to garbage-collect dead entries.
152*/
153static SegName segnames[VG_N_SEGNAMES];
154static Int segnames_used = 0;
155
156
157/* ------ end of STATE for the address-space manager ------ */
158
159
160/* Searches the filename table to find an index for the given name.
161 If none is found, an index is allocated and the name stored. If no
162 space is available we just give up. If the string is too long to
163 store, return -1.
164*/
165static Int allocate_segname ( const HChar* name )
166{
167 Int i, j, len;
168
169 vg_assert(name);
170
171 if (0) VG_(printf)("alloc_segname %s\n", name);
172
173 len = VG_(strlen)(name);
174 if (len >= VG_MAX_SEGNAMELEN-1) {
175 return -1;
176 }
177
178 /* first see if we already have the name. */
179 for (i = 0; i < segnames_used; i++) {
180 if (!segnames[i].inUse)
181 continue;
182 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
183 return i;
184 }
185 }
186
187 /* no we don't. So look for a free slot. */
188 for (i = 0; i < segnames_used; i++)
189 if (!segnames[i].inUse)
190 break;
191
192 if (i == segnames_used) {
193 /* no free slots .. advance the high-water mark. */
194 if (segnames_used+1 < VG_N_SEGNAMES) {
195 i = segnames_used;
196 segnames_used++;
197 } else {
198 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000199 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000200 " VG_N_SEGNAMES is too small: "
201 "increase it and rebuild Valgrind.\n"
202 );
203 VG_(printf)(
tom3a07e9b2005-05-17 11:03:52 +0000204 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000205 " giving up now.\n\n"
206 );
207 VG_(exit)(0);
208 }
209 }
210
211 /* copy it in */
212 segnames[i].inUse = True;
213 for (j = 0; j < len; j++)
214 segnames[i].fname[j] = name[j];
215 vg_assert(len < VG_MAX_SEGNAMELEN);
216 segnames[i].fname[len] = 0;
217 return i;
218}
219
sewardj548be6d2005-02-16 01:31:37 +0000220
221/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
222 an address after it, and 0 if it denotes an address covered by
sewardj79048ce2005-02-18 08:28:32 +0000223 seg.
224*/
sewardj548be6d2005-02-16 01:31:37 +0000225static Int compare_addr_with_seg ( Addr a, Segment* seg )
226{
227 if (a < seg->addr)
228 return -1;
229 if (a >= seg->addr + seg->len)
230 return 1;
231 return 0;
232}
233
sewardj79048ce2005-02-18 08:28:32 +0000234
sewardj548be6d2005-02-16 01:31:37 +0000235/* Find the (index of the) segment that contains 'a', or -1 if
sewardj79048ce2005-02-18 08:28:32 +0000236 none.
237*/
sewardj548be6d2005-02-16 01:31:37 +0000238static Int find_segment ( Addr a )
239{
240 Int i;
241 for (i = 0; i < segments_used; i++) {
242 if (compare_addr_with_seg(a, &segments[i]) == 0)
243 return i;
244 }
245 return -1;
246}
247
248
249/* Assumes that 'a' is not in any segment. Finds the index of the
250 lowest-addressed segment above 'a', or -1 if none. Passing 'a'
251 which is in fact in a segment is a checked error.
252*/
253static Int find_segment_above_unmapped ( Addr a )
254{
255 Int i, r;
256 for (i = 0; i < segments_used; i++) {
257 r = compare_addr_with_seg(a, &segments[i]);
258 vg_assert(r != 0); /* 'a' should not be in any segment. */
259 if (r == 1)
sewardj79048ce2005-02-18 08:28:32 +0000260 continue;
sewardj548be6d2005-02-16 01:31:37 +0000261 vg_assert(r == -1);
262 break;
263 }
264
265 if (i == segments_used)
266 return -1; /* not found */
267 else
268 return i;
269}
270
271
272/* Assumes that 'a' is in some segment. Finds the next segment along,
273 or NULL if none. Passing 'a' which is in fact not in a segment is
274 a checked error.
275*/
276static Int find_segment_above_mapped ( Addr a )
277{
278 Int i, r;
279 for (i = 0; i < segments_used; i++) {
280 r = compare_addr_with_seg(a, &segments[i]);
281 if (r == 1)
282 continue; /* not yet there */
283 if (r == 0)
284 break; /* found it */
285 vg_assert(0);
286 /* we shouldn't get here -- r == -1 and so it means we went past
287 'a' without seeing it -- it is therefore unmapped. */
288 /*NOTREACHED*/
289 }
290
291 vg_assert(i < segments_used);
292 if (i == segments_used-1)
293 return -1; /* not found */
294 else
295 return i+1;
296}
297
298
299/* Shift segments[i .. segments_used-1] up by one. */
300static void make_space_at ( Int i )
301{
302 Int j;
303 vg_assert(i >= 0 && i <= segments_used);
304 vg_assert(segments_used >= 0);
sewardj79048ce2005-02-18 08:28:32 +0000305 if (segments_used+1 == VG_N_SEGMENTS) {
306 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000307 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000308 " VG_N_SEGMENTS is too small: "
309 "increase it and rebuild Valgrind.\n"
310 );
311 VG_(printf)(
tom8a51bb82005-06-15 10:24:26 +0000312 "coregrind/m_aspacemgr/aspacemgr.c:\n"
sewardj79048ce2005-02-18 08:28:32 +0000313 " giving up now.\n\n"
314 );
315 VG_(exit)(0);
316 }
sewardj548be6d2005-02-16 01:31:37 +0000317 vg_assert(segments_used+1 < VG_N_SEGMENTS);
318 for (j = segments_used; j > i; j--)
319 segments[j] = segments[j-1];
320 segments_used++;
321}
322
sewardj79048ce2005-02-18 08:28:32 +0000323
sewardj548be6d2005-02-16 01:31:37 +0000324/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
sewardj79048ce2005-02-18 08:28:32 +0000325 segments_used.
326*/
sewardj548be6d2005-02-16 01:31:37 +0000327static void delete_segment_at ( Int i )
328{
329 Int j;
330 vg_assert(i >= 0 && i < segments_used);
331 for (j = i+1; j < segments_used; j++)
332 segments[j-1] = segments[j];
333 segments_used--;
334 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
335}
336
337
338/* Fill the i'th record all with zeroes. */
339static void zeroise_segment ( Int i )
340{
341 vg_assert(i >= 0 && i < segments_used);
sewardj79048ce2005-02-18 08:28:32 +0000342 segments[i].prot = 0;
343 segments[i].flags = 0;
344 segments[i].addr = 0;
345 segments[i].len = 0;
346 segments[i].offset = 0;
sewardj548be6d2005-02-16 01:31:37 +0000347 segments[i].filename = NULL;
sewardj79048ce2005-02-18 08:28:32 +0000348 segments[i].fnIdx = -1;
349 segments[i].dev = 0;
350 segments[i].ino = 0;
njn36ef6ba2005-05-14 18:42:26 +0000351 segments[i].seginfo = NULL;
sewardj548be6d2005-02-16 01:31:37 +0000352}
353
sewardj79048ce2005-02-18 08:28:32 +0000354
sewardj548be6d2005-02-16 01:31:37 +0000355/* Create a segment to contain 'a', and return its index. Or -1 if
356 this failed because some other segment already contains 'a'. If
357 successful, fill in the segment's .addr field with 'a' but leave
358 all other fields alone.
359*/
360static Int create_segment ( Addr a )
361{
362 Int i, r;
363 for (i = 0; i < segments_used; i++) {
364 r = compare_addr_with_seg( a, &segments[i] );
365 if (r == 1)
366 continue; /* seg[i] precedes a */
367 if (r == 0)
368 return -1; /* seg[i] contains a. Give up */
369 vg_assert(r == -1);
370 break;
371 }
372 /* a precedes seg[i]. Shift segs at i and above up one, and use
373 this slot. */
374 make_space_at(i);
375 zeroise_segment(i);
376 segments[i].addr = a;
377 return i;
378}
379
sewardj79048ce2005-02-18 08:28:32 +0000380
381/* Print out the segment array (debugging only!). Note, this calls
382 VG_(printf), and I'm not 100% clear that that wouldn't require
383 dynamic memory allocation and hence more segments to be allocated.
384*/
385static void show_segments ( HChar* who )
sewardj548be6d2005-02-16 01:31:37 +0000386{
sewardj79048ce2005-02-18 08:28:32 +0000387 Int i;
388 VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
389 who, segments_used, segnames_used);
390 for (i = 0; i < segnames_used; i++) {
391 if (!segnames[i].inUse)
392 continue;
393 VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
394 }
395 for (i = 0; i < segments_used; i++) {
sewardj548be6d2005-02-16 01:31:37 +0000396 VG_(printf)(
sewardj79048ce2005-02-18 08:28:32 +0000397 "%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 +0000398 i,
sewardj79048ce2005-02-18 08:28:32 +0000399 segments[i].addr, segments[i].addr + segments[i].len,
400 (ULong)segments[i].len, segments[i].prot,
401 segments[i].flags, segments[i].dev, segments[i].ino,
402 (Long)segments[i].offset,
403 segments[i].fnIdx);
404 }
405 VG_(printf)(">>>\n");
sewardj548be6d2005-02-16 01:31:37 +0000406}
sewardj79048ce2005-02-18 08:28:32 +0000407
sewardj548be6d2005-02-16 01:31:37 +0000408
409/* Find the segment containing 'a' and split it into two pieces at
410 'a'. Does nothing if no segment contains 'a', or if the split
411 would cause either of the pieces to have zero size.
412
413 If 'a' is not found, or if no splitting happens, -1 is returned.
414
415 If a value 'r' other than -1 is returned, this is the index of the
416 higher-addressed segment resulting from the split, and the index of
417 the lower-addressed segment is r-1.
418*/
419static Int split_segment ( Addr a )
420{
421 Int r;
422 HWord delta;
njnbe91aae2005-03-27 01:42:41 +0000423 vg_assert(VG_IS_PAGE_ALIGNED(a));
sewardj548be6d2005-02-16 01:31:37 +0000424 r = find_segment(a);
425 if (r == -1)
426 /* not found */
427 return -1;
428 if (segments[r].addr == a)
429 /* segment starts at 'a', so splitting it would create a
430 zero-sized segment */
431 return -1;
432
433 /* copy original; make adjustments. */
434 vg_assert(a > segments[r].addr);
435 delta = a - segments[r].addr;
436 make_space_at(r);
437 segments[r] = segments[r+1];
438 segments[r].len = delta;
439 segments[r+1].len -= delta;
440 segments[r+1].addr += delta;
441 segments[r+1].offset += delta;
442 return r+1;
443}
444
sewardj79048ce2005-02-18 08:28:32 +0000445
446/* Return true if two segments are adjacent and mergable (s1 is
447 assumed to have a lower ->addr than s2) */
448static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
449{
450 if (s1->addr+s1->len != s2->addr)
451 return False;
452
453 if (s1->flags != s2->flags)
454 return False;
455
456 if (s1->prot != s2->prot)
457 return False;
458
njn36ef6ba2005-05-14 18:42:26 +0000459 if (s1->seginfo != s2->seginfo)
sewardj79048ce2005-02-18 08:28:32 +0000460 return False;
461
462 if (s1->flags & SF_FILE){
463 if ((s1->offset + s1->len) != s2->offset)
464 return False;
465 if (s1->dev != s2->dev)
466 return False;
467 if (s1->ino != s2->ino)
468 return False;
469 if (s1->fnIdx != s2->fnIdx)
470 return False;
471 }
472
473 return True;
474}
475
476
477/* Clean up and sanity check the segment array:
478 - check segments are in ascending order
479 - check segments do not overlap
480 - check no segment has zero size
481 - merge adjacent where possible
482 - perform checks on the filename table, and reclaim dead entries
483*/
484static void preen_segments ( void )
485{
486 Int i, j, rd, wr;
487 Segment *s, *s1;
488 vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
489 vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
490
491 if (0) show_segments("before preen");
492
493 /* clear string table mark bits */
494 for (i = 0; i < segnames_used; i++)
495 segnames[i].mark = False;
496
497 /* check for non-zero size, and set mark bits for any used strings */
498 for (i = 0; i < segments_used; i++) {
499 vg_assert(segments[i].len > 0);
500 j = segments[i].fnIdx;
501 vg_assert(j >= -1 && j < segnames_used);
502 if (j >= 0) {
503 vg_assert(segnames[j].inUse);
504 segnames[j].mark = True;
505 }
506 }
507
508 /* check ascendingness and non-overlap */
509 for (i = 0; i < segments_used-1; i++) {
510 s = &segments[i];
511 s1 = &segments[i+1];
512 vg_assert(s->addr < s1->addr);
513 vg_assert(s->addr + s->len <= s1->addr);
514 }
515
516 /* merge */
517 if (segments_used < 1)
518 return;
519
520 wr = 1;
521 for (rd = 1; rd < segments_used; rd++) {
522 s = &segments[wr-1];
523 s1 = &segments[rd];
524 if (segments_are_mergeable(s,s1)) {
525 if (0)
526 VG_(printf)("merge %p-%p with %p-%p\n",
527 s->addr, s->addr+s->len,
528 s1->addr, s1->addr+s1->len);
529 s->len += s1->len;
530 continue;
531 }
532 if (wr < rd)
533 segments[wr] = segments[rd];
534 wr++;
535 }
536 vg_assert(wr >= 0 && wr <= segments_used);
537 segments_used = wr;
538
539 /* Free up any strings which are no longer referenced. */
540 for (i = 0; i < segnames_used; i++) {
541 if (segnames[i].mark == False) {
542 segnames[i].inUse = False;
543 segnames[i].fname[0] = 0;
544 }
545 }
546
547 if (0) show_segments("after preen");
548}
549
550
sewardj548be6d2005-02-16 01:31:37 +0000551/*--------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000552/*--- Maintain an ordered list of all the client's mappings ---*/
553/*--------------------------------------------------------------*/
554
nethercote8991d5a2004-11-03 17:07:46 +0000555Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000556{
557 Addr se = s->addr+s->len;
558 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000559 vg_assert(pe >= p);
560
561 return (p >= s->addr && pe <= se);
562}
563
nethercote8991d5a2004-11-03 17:07:46 +0000564Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000565{
566 Addr se = s->addr+s->len;
567 Addr pe = p+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000568 vg_assert(pe >= p);
569
570 return (p < se && pe > s->addr);
571}
572
sewardj1024cf72005-02-28 14:39:21 +0000573#if 0
574/* 20050228: apparently unused */
fitzhardinge98abfc72003-12-16 02:05:15 +0000575/* Prepare a Segment structure for recycling by freeing everything
576 hanging off it. */
577static void recycleseg(Segment *s)
578{
579 if (s->flags & SF_CODE)
sewardjfa8ec112005-01-19 11:55:34 +0000580 VG_(discard_translations)(s->addr, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000581
582 if (s->filename != NULL)
583 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
584
585 /* keep the SegInfo, if any - it probably still applies */
586}
587
588/* When freeing a Segment, also clean up every one else's ideas of
589 what was going on in that range of memory */
590static void freeseg(Segment *s)
591{
592 recycleseg(s);
njn36ef6ba2005-05-14 18:42:26 +0000593 if (s->seginfo != NULL) {
594 VG_(seginfo_decref)(s->seginfo, s->addr);
595 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000596 }
597
598 VG_(SkipNode_Free)(&sk_segments, s);
599}
sewardj1024cf72005-02-28 14:39:21 +0000600#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000601
sewardj1024cf72005-02-28 14:39:21 +0000602
603/* Get rid of any translations arising from s. */
604/* Note, this is not really the job of the low level memory manager.
605 When it comes time to rewrite this subsystem, clean this up. */
606static void dump_translations_from ( Segment* s )
fitzhardinge98abfc72003-12-16 02:05:15 +0000607{
sewardj1024cf72005-02-28 14:39:21 +0000608 if (s->flags & SF_CODE) {
609 VG_(discard_translations)(s->addr, s->len);
610 if (0)
611 VG_(printf)("dumping translations in %p .. %p\n",
612 s->addr, s->addr+s->len);
613 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000614}
615
sewardj1024cf72005-02-28 14:39:21 +0000616
fitzhardinge98abfc72003-12-16 02:05:15 +0000617/* This unmaps all the segments in the range [addr, addr+len); any
618 partial mappings at the ends are truncated. */
nethercote8b5f40c2004-11-02 13:29:50 +0000619void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000620{
fitzhardingee3632c62003-12-22 10:58:06 +0000621 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000622 Segment* s;
623 Addr end, s_end;
624 Int i;
sewardj47c98a72005-03-12 20:36:15 +0000625 Bool deleted;
fitzhardinge98abfc72003-12-16 02:05:15 +0000626
627 if (len == 0)
628 return;
629
njn13bfd852005-06-02 03:52:53 +0000630 len = VG_PGROUNDUP(len);
fitzhardinge1a4adf02003-12-22 10:42:59 +0000631
fitzhardinge98abfc72003-12-16 02:05:15 +0000632 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000633 VG_(printf)("unmap_range(%p, %llu)\n", addr, (ULong)len);
sewardj79048ce2005-02-18 08:28:32 +0000634 if (0) show_segments("unmap_range(BEFORE)");
fitzhardinge1a4adf02003-12-22 10:42:59 +0000635 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000636
637 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000638 vg_assert(VG_IS_PAGE_ALIGNED(addr));
639 vg_assert(VG_IS_PAGE_ALIGNED(len));
fitzhardinge98abfc72003-12-16 02:05:15 +0000640
sewardj548be6d2005-02-16 01:31:37 +0000641 for (i = 0; i < segments_used; i++) {
sewardj47c98a72005-03-12 20:36:15 +0000642
643 /* do not delete .. even though it looks stupid */
644 vg_assert(i >= 0);
645
646 deleted = False;
sewardj548be6d2005-02-16 01:31:37 +0000647 s = &segments[i];
648 s_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000649
sewardj548be6d2005-02-16 01:31:37 +0000650 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000651 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
sewardj548be6d2005-02-16 01:31:37 +0000652 addr, end, s, s->addr, s_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000653
fitzhardinge1a303042003-12-22 08:48:50 +0000654 if (!VG_(seg_overlaps)(s, addr, len)) {
sewardj548be6d2005-02-16 01:31:37 +0000655 if (0 && debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000656 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000657 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000658 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000659
660 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000661 if (addr > s->addr &&
sewardj548be6d2005-02-16 01:31:37 +0000662 addr < s_end &&
663 end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000664 /* this segment's tail is truncated by [addr, addr+len)
665 -> truncate tail
666 */
sewardj1024cf72005-02-28 14:39:21 +0000667 dump_translations_from(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000668 s->len = addr - s->addr;
669
670 if (debug)
tom9be7c982005-04-25 16:55:44 +0000671 VG_(printf)(" case 1: s->len=%lu\n", s->len);
sewardj548be6d2005-02-16 01:31:37 +0000672 } else if (addr <= s->addr && end > s->addr && end < s_end) {
fitzhardingee3632c62003-12-22 10:58:06 +0000673 /* this segment's head is truncated by [addr, addr+len)
674 -> truncate head
675 */
sewardj548be6d2005-02-16 01:31:37 +0000676 Word delta = end - s->addr;
fitzhardingee3632c62003-12-22 10:58:06 +0000677
678 if (debug)
tom9be7c982005-04-25 16:55:44 +0000679 VG_(printf)(" case 2: s->addr=%p s->len=%lu delta=%d\n",
sewardj79048ce2005-02-18 08:28:32 +0000680 s->addr, s->len, delta);
fitzhardingee3632c62003-12-22 10:58:06 +0000681
sewardj1024cf72005-02-28 14:39:21 +0000682 dump_translations_from(s);
fitzhardingee3632c62003-12-22 10:58:06 +0000683 s->addr += delta;
684 s->offset += delta;
685 s->len -= delta;
686
687 vg_assert(s->len != 0);
sewardj548be6d2005-02-16 01:31:37 +0000688 } else if (addr <= s->addr && end >= s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000689 /* this segment is completely contained within [addr, addr+len)
690 -> delete segment
691 */
sewardj1024cf72005-02-28 14:39:21 +0000692 dump_translations_from(s);
sewardj548be6d2005-02-16 01:31:37 +0000693 delete_segment_at(i);
sewardj47c98a72005-03-12 20:36:15 +0000694 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000695
696 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000697 VG_(printf)(" case 3: seg %d deleted\n", i);
698 } else if (addr > s->addr && end < s_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000699 /* [addr, addr+len) is contained within a single segment
700 -> split segment into 3, delete middle portion
701 */
sewardj1024cf72005-02-28 14:39:21 +0000702 Int i_middle;
703 dump_translations_from(s);
704 i_middle = split_segment(addr);
sewardj548be6d2005-02-16 01:31:37 +0000705 vg_assert(i_middle != -1);
706 (void)split_segment(addr+len);
sewardj548be6d2005-02-16 01:31:37 +0000707 vg_assert(segments[i_middle].addr == addr);
708 delete_segment_at(i_middle);
sewardj47c98a72005-03-12 20:36:15 +0000709 deleted = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000710
711 if (debug)
712 VG_(printf)(" case 4: subrange %p-%p deleted\n",
713 addr, addr+len);
714 }
sewardj47c98a72005-03-12 20:36:15 +0000715
716 /* If we deleted this segment (or any above), those above will
717 have been moved down to fill in the hole in the segment
718 array. In order that we don't miss them, we have to
719 re-consider this slot number; hence the i--. */
720 if (deleted)
721 i--;
fitzhardinge98abfc72003-12-16 02:05:15 +0000722 }
sewardj79048ce2005-02-18 08:28:32 +0000723 preen_segments();
724 if (0) show_segments("unmap_range(AFTER)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000725}
726
sewardj548be6d2005-02-16 01:31:37 +0000727
728/* Add a binding of [addr,addr+len) to
729 (prot,flags,dev,ino,off,filename) in the segment array.
730 Delete/truncate any previous mapping(s) covering that range.
731*/
732void
733VG_(map_file_segment)( Addr addr, SizeT len,
734 UInt prot, UInt flags,
735 UInt dev, UInt ino, ULong off,
736 const Char *filename)
fitzhardinge98abfc72003-12-16 02:05:15 +0000737{
fitzhardinge98abfc72003-12-16 02:05:15 +0000738 static const Bool debug = False || mem_debug;
sewardj79048ce2005-02-18 08:28:32 +0000739 Segment* s;
740 Int idx;
njn6081fce2005-06-25 19:45:34 +0000741 HChar* stage2_suffix1 = "lib/valgrind/stage2";
742 HChar* stage2_suffix2 = "coregrind/stage2";
743 Bool is_stage2 = False;
744
745 is_stage2 = is_stage2 || ( VG_(strstr)(filename, stage2_suffix1) != NULL );
746 is_stage2 = is_stage2 || ( VG_(strstr)(filename, stage2_suffix2) != NULL );
fitzhardinge98abfc72003-12-16 02:05:15 +0000747
748 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000749 VG_(printf)(
750 "\n"
tom9be7c982005-04-25 16:55:44 +0000751 "map_file_segment(addr=%p len=%lu prot=0x%x flags=0x%x\n"
sewardj548be6d2005-02-16 01:31:37 +0000752 " dev=0x%4x ino=%d off=%ld\n"
753 " filename='%s')\n",
754 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000755
sewardja8d8e232005-06-07 20:04:56 +0000756 if (0) show_segments("before map_file_segment");
757
fitzhardinge98abfc72003-12-16 02:05:15 +0000758 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000759 vg_assert(VG_IS_PAGE_ALIGNED(addr));
njn13bfd852005-06-02 03:52:53 +0000760 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000761
sewardj548be6d2005-02-16 01:31:37 +0000762 /* Nuke/truncate any existing segment(s) covering [addr,addr+len) */
763 VG_(unmap_range)(addr, len);
764
765 /* and now install this one */
766 idx = create_segment(addr);
767 vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
768 vg_assert(idx != -1);
769 vg_assert(idx >= 0 && idx < segments_used);
sewardj548be6d2005-02-16 01:31:37 +0000770
sewardj79048ce2005-02-18 08:28:32 +0000771 s = &segments[idx];
772 vg_assert(s->addr == addr);
773 s->prot = prot;
774 s->flags = flags;
775 s->len = len;
776 s->offset = off;
777 s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
778 s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
779 s->dev = dev;
780 s->ino = ino;
njn36ef6ba2005-05-14 18:42:26 +0000781 s->seginfo = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +0000782
sewardj79048ce2005-02-18 08:28:32 +0000783 /* Clean up right now */
784 preen_segments();
785 if (0) show_segments("after map_file_segment");
fitzhardinge98abfc72003-12-16 02:05:15 +0000786
787 /* If this mapping is of the beginning of a file, isn't part of
788 Valgrind, is at least readable and seems to contain an object
sewardj79048ce2005-02-18 08:28:32 +0000789 file, then try reading symbols from it.
790 */
njn36ef6ba2005-05-14 18:42:26 +0000791 if (s->seginfo == NULL
sewardja8d8e232005-06-07 20:04:56 +0000792 && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
793 || is_stage2
794 )
njn88c51482005-06-25 20:49:33 +0000795 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP
796 ) {
sewardj79048ce2005-02-18 08:28:32 +0000797 if (off == 0
798 && s->fnIdx != -1
799 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
800 && len >= VKI_PAGE_SIZE
njn88c51482005-06-25 20:49:33 +0000801 && VG_(is_object_file)((void *)addr)
802 ) {
803 s->seginfo = VG_(read_seg_symbols)(s->addr, s->len, s->offset,
804 s->filename);
njn36ef6ba2005-05-14 18:42:26 +0000805 if (s->seginfo != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000806 s->flags |= SF_DYNLIB;
807 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000808 } else if (flags & SF_MMAP) {
sewardj79048ce2005-02-18 08:28:32 +0000809#if 0
fitzhardinge98abfc72003-12-16 02:05:15 +0000810 const SegInfo *info;
811
njn36ef6ba2005-05-14 18:42:26 +0000812 /* Otherwise see if an existing SegInfo applies to this Segment */
fitzhardinge98abfc72003-12-16 02:05:15 +0000813 for(info = VG_(next_seginfo)(NULL);
814 info != NULL;
815 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000816 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
817 {
njn36ef6ba2005-05-14 18:42:26 +0000818 s->seginfo = (SegInfo *)info;
819 VG_(seginfo_incref)((SegInfo *)info);
fitzhardinge98abfc72003-12-16 02:05:15 +0000820 }
821 }
sewardj79048ce2005-02-18 08:28:32 +0000822#endif
fitzhardinge98abfc72003-12-16 02:05:15 +0000823 }
824 }
825
826 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000827 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000828}
829
nethercote8b5f40c2004-11-02 13:29:50 +0000830void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000831 Int fd, ULong off, const Char *filename)
832{
njnf845f8f2005-06-23 02:26:47 +0000833 Char buf[VKI_PATH_MAX];
fitzhardinge98abfc72003-12-16 02:05:15 +0000834 struct vki_stat st;
fitzhardinge98abfc72003-12-16 02:05:15 +0000835
836 st.st_dev = 0;
837 st.st_ino = 0;
838
839 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000840 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000841
842 if (VG_(fstat)(fd, &st) < 0)
843 flags &= ~SF_FILE;
844 }
845
sewardj79048ce2005-02-18 08:28:32 +0000846 if ((flags & SF_FILE) && filename == NULL && fd != -1)
njnf845f8f2005-06-23 02:26:47 +0000847 if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX))
848 filename = buf;
fitzhardinge98abfc72003-12-16 02:05:15 +0000849
sewardj79048ce2005-02-18 08:28:32 +0000850 VG_(map_file_segment)(addr, len, prot, flags,
851 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000852}
853
nethercote8b5f40c2004-11-02 13:29:50 +0000854void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000855{
856 flags &= ~SF_FILE;
857
858 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
859}
860
861/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000862void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000863{
sewardj79048ce2005-02-18 08:28:32 +0000864 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000865 static const Bool debug = False || mem_debug;
866
867 if (debug)
tom9be7c982005-04-25 16:55:44 +0000868 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000869
870 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000871
872 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000873 vg_assert(VG_IS_PAGE_ALIGNED(a));
njn13bfd852005-06-02 03:52:53 +0000874 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000875
sewardj79048ce2005-02-18 08:28:32 +0000876 split_segment(a);
877 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000878
sewardj548be6d2005-02-16 01:31:37 +0000879 r = find_segment(a);
880 vg_assert(r != -1);
881 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000882
883 preen_segments();
884
sewardje517b802005-02-16 01:58:51 +0000885 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000886}
887
sewardj79048ce2005-02-18 08:28:32 +0000888
sewardj548be6d2005-02-16 01:31:37 +0000889/* Try to find a map space for [addr,addr+len). If addr==0, it means
890 the caller is prepared to accept a space at any location; if not,
891 we will try for addr, but fail if we can't get it. This mimics
892 mmap fixed vs mmap not-fixed.
893*/
nethercote8b5f40c2004-11-02 13:29:50 +0000894Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000895{
fitzhardingee3632c62003-12-22 10:58:06 +0000896 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000897 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000898 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000899 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
900 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000901 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
902 Int i, i_any, i_fixed, i_final;
903 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000904
sewardj548be6d2005-02-16 01:31:37 +0000905 Bool fixed;
906
sewardje517b802005-02-16 01:58:51 +0000907 if (debug) {
908 VG_(printf)("\n\n");
sewardja8d8e232005-06-07 20:04:56 +0000909 VG_(printf)("find_map_space(%p, %llu, %d) ...\n",
910 addr, (ULong)len, for_client);
sewardje517b802005-02-16 01:58:51 +0000911 }
912
913 if (0) show_segments("find_map_space: start");
914
sewardj548be6d2005-02-16 01:31:37 +0000915 if (addr == 0) {
916 fixed = False;
917 } else {
918 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000919 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000920 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000921 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000922 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000923
924 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000925 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
njn13bfd852005-06-02 03:52:53 +0000926 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000927
nethercote73b526f2004-10-31 18:48:21 +0000928 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000929
sewardj548be6d2005-02-16 01:31:37 +0000930 /* Scan the segment list, looking for a hole which satisfies the
931 requirements. At each point i we ask the question "can we use
932 the hole in between segments[i-1] and segments[i] ?" */
933 i_any = i_fixed = -1;
934 hstart_any = hstart_fixed = 0;
935
936 hole_start = hole_end = 0;
937
938 /* Iterate over all possible holes, generating them into
939 hole_start/hole_end. Filter out invalid ones. Then see if any
940 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
941 */
942 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
943 if (i == 0) {
944 hole_start = 0;
945 hole_end = segments[0].addr-1;
946 }
947 else {
948 vg_assert(segments_used > 0);
949 if (i == segments_used) {
950 hole_start = segments[i-1].addr + segments[i-1].len;
951 hole_end = ~(Addr)0;
952 } else {
953 hole_start = segments[i-1].addr + segments[i-1].len;
954 hole_end = segments[i].addr - 1;
955 }
956 }
957
958 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
959
960 /* ignore zero-sized holes */
961 if (hole_start == hole_end+1)
962 continue;
963
njnbe91aae2005-03-27 01:42:41 +0000964 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
965 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000966
967 /* ignore holes which fall outside the allowable area */
968 if (!(hole_start >= base && hole_end <= limit))
969 continue;
970
971 vg_assert(hole_end > hole_start);
972 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000973 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000974
975 if (hole_len >= len && i_any == -1) {
976 /* It will at least fit in this hole. */
977 i_any = i;
978 hstart_any = hole_start;
979 }
980
sewardjb5f6f512005-03-10 23:59:00 +0000981 if (fixed && hole_start <= addr
982 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +0000983 /* We were asked for a fixed mapping, and this hole works.
984 Bag it -- and stop searching as further searching is
985 pointless. */
986 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +0000987 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +0000988 break;
989 }
990 }
991
992 /* Summarise the final decision into i_final/hstart_final. */
993 i_final = -1;
994 hstart_final = 0;
995
996 if (fixed) {
997 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +0000998 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +0000999 } else {
1000 i_final = i_any;
1001 hstart_final = hstart_any;
1002 }
1003
1004
1005 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +00001006 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +00001007 else
1008 ret = 0; /* not found */
1009
1010 if (debug)
sewardja8d8e232005-06-07 20:04:56 +00001011 VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n",
1012 addr, (ULong)len, for_client, ret);
sewardj548be6d2005-02-16 01:31:37 +00001013
sewardjb5f6f512005-03-10 23:59:00 +00001014 if (fixed) {
1015 vg_assert(ret == 0 || ret == addrOrig);
1016 }
1017
sewardj548be6d2005-02-16 01:31:37 +00001018 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +00001019}
1020
sewardj79048ce2005-02-18 08:28:32 +00001021
sewardjb5f6f512005-03-10 23:59:00 +00001022/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +00001023 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +00001024 mapping over any part of the address space which is not covered
1025 by an entry in the segment list.
1026
1027 This is designed for use around system calls which allocate
1028 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +00001029 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +00001030 address with VG_(find_map_space) and then adding a segment for
1031 it and padding the address space valgrind can ensure that the
1032 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +00001033void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001034{
sewardj394790d2005-03-17 02:14:44 +00001035 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001036 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001037
1038 Int i = 0;
1039 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001040
nethercote820bd8c2004-09-07 23:04:49 +00001041 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001042 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +00001043 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +00001044 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1045 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001046 }
thughes9aaebc32004-07-15 23:13:37 +00001047 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001048 i++;
1049 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001050 }
1051
nethercote820bd8c2004-09-07 23:04:49 +00001052 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001053 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001054 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1055 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001056 }
thughes9aaebc32004-07-15 23:13:37 +00001057}
1058
thughesc70b8c62004-07-16 23:07:58 +00001059/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001060 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001061void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001062{
sewardj394790d2005-03-17 02:14:44 +00001063 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001064 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001065
1066 Int i = 0;
1067 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001068
nethercote820bd8c2004-09-07 23:04:49 +00001069 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001070 if (addr < s->addr) {
njnb69f7c12005-06-24 22:17:38 +00001071 //ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
njnca6fef02004-11-29 16:49:18 +00001072 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001073 }
thughes9aaebc32004-07-15 23:13:37 +00001074 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001075 i++;
1076 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001077 }
1078
nethercote820bd8c2004-09-07 23:04:49 +00001079 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001080 ret = VG_(do_syscall2)(__NR_munmap, addr,
1081 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001082 }
thughes9aaebc32004-07-15 23:13:37 +00001083}
1084
sewardj548be6d2005-02-16 01:31:37 +00001085/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001086Segment *VG_(find_segment)(Addr a)
1087{
sewardj548be6d2005-02-16 01:31:37 +00001088 Int r = find_segment(a);
1089 if (0) show_segments("find_segment");
1090 if (r == -1) return NULL;
1091 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001092}
1093
sewardj548be6d2005-02-16 01:31:37 +00001094/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1095 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1096 a segment is a checked error.
1097*/
1098Segment *VG_(find_segment_above_unmapped)(Addr a)
1099{
1100 Int r = find_segment_above_unmapped(a);
1101 if (0) show_segments("find_segment_above_unmapped");
1102 if (r == -1) return NULL;
1103 return &segments[r];
1104}
1105
1106/* Assumes that 'a' is in some segment. Finds the next segment along,
1107 or NULL if none. Passing 'a' which is in fact not in a segment is
1108 a checked error.
1109*/
1110Segment *VG_(find_segment_above_mapped)(Addr a)
1111{
1112 Int r = find_segment_above_mapped(a);
1113 if (0) show_segments("find_segment_above_mapped");
1114 if (r == -1) return NULL;
1115 return &segments[r];
1116}
1117
1118
jsgf855d93d2003-10-13 22:26:55 +00001119/*
sewardjb5f6f512005-03-10 23:59:00 +00001120 Test if a piece of memory is addressable with at least the "prot"
1121 protection permissions by examining the underlying segments.
1122
1123 Really this is a very stupid algorithm and we could do much
1124 better by iterating through the segment array instead of through
1125 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001126 */
sewardjb5f6f512005-03-10 23:59:00 +00001127Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001128{
sewardjb5f6f512005-03-10 23:59:00 +00001129 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001130
sewardjb5f6f512005-03-10 23:59:00 +00001131 if ((p + size) < p)
1132 return False; /* reject wraparounds */
1133 if (size == 0)
1134 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001135
njn13bfd852005-06-02 03:52:53 +00001136 p = VG_PGROUNDDN(p);
1137 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001138 vg_assert(VG_IS_PAGE_ALIGNED(p));
1139 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001140
sewardjb5f6f512005-03-10 23:59:00 +00001141 for (; size > 0; size -= VKI_PAGE_SIZE) {
1142 seg = VG_(find_segment)(p);
1143 if (!seg)
1144 return False;
1145 if ((seg->prot & prot) != prot)
1146 return False;
1147 p += VKI_PAGE_SIZE;
1148 }
jsgf855d93d2003-10-13 22:26:55 +00001149
sewardjb5f6f512005-03-10 23:59:00 +00001150 return True;
jsgf855d93d2003-10-13 22:26:55 +00001151}
1152
sewardjb5f6f512005-03-10 23:59:00 +00001153
sewardjde4a1d02002-03-22 01:27:54 +00001154/*--------------------------------------------------------------------*/
njn9260c782005-06-19 21:57:54 +00001155/*--- Random function that doesn't really belong here ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001156/*--------------------------------------------------------------------*/
1157
njn86f12dc2005-03-14 01:16:05 +00001158/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001159 range, which isn't SF_CORE, a root.
1160*/
njn86f12dc2005-03-14 01:16:05 +00001161void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1162{
sewardj882af5f2005-03-16 12:27:53 +00001163 Int i;
1164 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001165 Segment *s;
1166
sewardj882af5f2005-03-16 12:27:53 +00001167 for (i = 0; i < segments_used; i++) {
1168 s = &segments[i];
1169 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND
1170 |SF_CORE|SF_STACK|SF_DEVICE);
njn86f12dc2005-03-14 01:16:05 +00001171 if (flags != SF_MMAP && flags != SF_STACK)
1172 continue;
sewardj882af5f2005-03-16 12:27:53 +00001173 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1174 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001175 continue;
1176 if (!VG_(is_client_addr)(s->addr) ||
1177 !VG_(is_client_addr)(s->addr+s->len))
1178 continue;
1179
1180 (*add_rootrange)(s->addr, s->len);
1181 }
njn86f12dc2005-03-14 01:16:05 +00001182}
1183
1184
nethercote88a90162004-07-10 16:59:25 +00001185/*--------------------------------------------------------------------*/
1186/*--- Querying memory layout ---*/
1187/*--------------------------------------------------------------------*/
1188
fitzhardinge98abfc72003-12-16 02:05:15 +00001189Bool VG_(is_client_addr)(Addr a)
1190{
1191 return a >= VG_(client_base) && a < VG_(client_end);
1192}
1193
1194Bool VG_(is_shadow_addr)(Addr a)
1195{
1196 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1197}
1198
sewardjfa8202f2005-04-24 11:05:55 +00001199
nethercote88a90162004-07-10 16:59:25 +00001200/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001201/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001202/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001203
fitzhardinge98abfc72003-12-16 02:05:15 +00001204void *VG_(shadow_alloc)(UInt size)
1205{
1206 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001207 Addr try_here;
njne9befc62005-06-11 15:51:30 +00001208 SysRes r;
sewardj79048ce2005-02-18 08:28:32 +00001209
1210 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001211
1212 vg_assert(VG_(needs).shadow_memory);
fitzhardinge98abfc72003-12-16 02:05:15 +00001213
njn13bfd852005-06-02 03:52:53 +00001214 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001215
1216 if (shadow_alloc == 0)
1217 shadow_alloc = VG_(shadow_base);
1218
1219 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001220 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001221
sewardj79048ce2005-02-18 08:28:32 +00001222 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001223 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1224 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001225 vg_assert(size > 0);
1226
1227 if (0)
1228 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1229
1230 /* this is big-bang allocated, so we don't expect to find a listed
1231 segment for it. */
1232 /* This is really an absolute disgrace. Sometimes the big-bang
1233 mapping is in the list (due to re-reads of /proc/self/maps,
1234 presumably) and sometimes it isn't. */
1235#if 0
1236 r = find_segment(try_here);
1237 vg_assert(r == -1);
1238 r = find_segment(try_here+size-1);
1239 vg_assert(r == -1);
1240#endif
1241
1242 r = VG_(mprotect_native)( (void*)try_here,
1243 size, VKI_PROT_READ|VKI_PROT_WRITE );
1244
njne9befc62005-06-11 15:51:30 +00001245 if (r.isError)
sewardj79048ce2005-02-18 08:28:32 +00001246 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001247
1248 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001249 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001250
sewardj79048ce2005-02-18 08:28:32 +00001251 failed:
1252 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001253 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001254 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001255 size
sewardj79048ce2005-02-18 08:28:32 +00001256 );
1257 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001258}
1259
njne3f06352005-06-01 03:48:33 +00001260/*------------------------------------------------------------*/
1261/*--- pointercheck ---*/
1262/*------------------------------------------------------------*/
1263
njnaf839f52005-06-23 03:27:57 +00001264Bool VG_(setup_pointercheck)(Addr client_base, Addr client_end)
njne3f06352005-06-01 03:48:33 +00001265{
1266 vg_assert(0 != client_end);
1267#if defined(VGP_x86_linux)
1268 /* Client address space segment limit descriptor entry */
1269 #define POINTERCHECK_SEGIDX 1
1270
1271 vki_modify_ldt_t ldt = {
1272 POINTERCHECK_SEGIDX, // entry_number
1273 client_base, // base_addr
1274 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1275 1, // seg_32bit
1276 0, // contents: data, RW, non-expanding
1277 0, // ! read_exec_only
1278 1, // limit_in_pages
1279 0, // ! seg not present
1280 1, // useable
1281 };
sewardja8d8e232005-06-07 20:04:56 +00001282 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1283 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001284 VG_(message)(Vg_UserMsg,
1285 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001286 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001287 return False;
1288 } else {
1289 return True;
1290 }
1291#elif defined(VGP_amd64_linux)
1292 if (0)
1293 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1294 return True;
cerion85665ca2005-06-20 15:51:07 +00001295#elif defined(VGP_ppc32_linux)
1296 if (0)
1297 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1298 return True;
njne3f06352005-06-01 03:48:33 +00001299#else
1300# error Unknown architecture
1301#endif
1302}
1303
fitzhardinge98abfc72003-12-16 02:05:15 +00001304/*--------------------------------------------------------------------*/
njn945ed2e2005-06-24 03:28:30 +00001305/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001306/*--------------------------------------------------------------------*/