blob: 92d67b4b70ba3b661ee910bb09ccd9e6d6784174 [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*/
sewardj447f2a12005-07-07 13:52:53 +0000225static inline Int compare_addr_with_seg ( Addr a, Segment* seg )
sewardj548be6d2005-02-16 01:31:37 +0000226{
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.
sewardj78164b92005-07-09 10:36:25 +0000790
791 Getting this heuristic right is critical. On x86-linux,
792 objects are typically mapped twice:
793
794 1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
795 1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
796
797 whereas ppc32-linux mysteriously does this:
798
799 118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
800 118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
801 118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
802
803 The third mapping should not be considered to have executable code in.
804 Therefore a test which works for both is: r and x and NOT w. Reading
805 symbols from the rwx segment -- which overlaps the r-x segment in the
806 file -- causes the redirection mechanism to redirect to addresses in
807 that third segment, which is wrong and causes crashes.
sewardj79048ce2005-02-18 08:28:32 +0000808 */
njn36ef6ba2005-05-14 18:42:26 +0000809 if (s->seginfo == NULL
sewardja8d8e232005-06-07 20:04:56 +0000810 && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last))
811 || is_stage2
812 )
njn88c51482005-06-25 20:49:33 +0000813 && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP
njn88c51482005-06-25 20:49:33 +0000814 ) {
sewardj78164b92005-07-09 10:36:25 +0000815 if (off == 0
816 && s->fnIdx != -1
817 /* r, x are set */
818 && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
819 /* w is clear */
820 && (prot & VKI_PROT_WRITE) == 0
821 /* other checks .. */
822 && len >= VKI_PAGE_SIZE
823 && VG_(is_object_file)((void *)addr) ) {
njn88c51482005-06-25 20:49:33 +0000824 s->seginfo = VG_(read_seg_symbols)(s->addr, s->len, s->offset,
825 s->filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000826 }
sewardj78164b92005-07-09 10:36:25 +0000827 //else
828 //if (flags & SF_MMAP) {
829 // const SegInfo *info;
830 //
831 // /* Otherwise see if an existing SegInfo applies to this Segment */
832 // for(info = VG_(next_seginfo)(NULL);
833 // info != NULL;
834 // info = VG_(next_seginfo)(info)) {
835 // if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
836 // {
837 // s->seginfo = (SegInfo *)info;
838 // VG_(seginfo_incref)((SegInfo *)info);
839 // }
840 // }
841 //}
fitzhardinge98abfc72003-12-16 02:05:15 +0000842 }
843
844 /* clean up */
sewardj79048ce2005-02-18 08:28:32 +0000845 preen_segments();
fitzhardinge98abfc72003-12-16 02:05:15 +0000846}
847
nethercote8b5f40c2004-11-02 13:29:50 +0000848void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000849 Int fd, ULong off, const Char *filename)
850{
njnf845f8f2005-06-23 02:26:47 +0000851 Char buf[VKI_PATH_MAX];
fitzhardinge98abfc72003-12-16 02:05:15 +0000852 struct vki_stat st;
fitzhardinge98abfc72003-12-16 02:05:15 +0000853
854 st.st_dev = 0;
855 st.st_ino = 0;
856
857 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000858 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000859
860 if (VG_(fstat)(fd, &st) < 0)
861 flags &= ~SF_FILE;
862 }
863
sewardj79048ce2005-02-18 08:28:32 +0000864 if ((flags & SF_FILE) && filename == NULL && fd != -1)
njnf845f8f2005-06-23 02:26:47 +0000865 if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX))
866 filename = buf;
fitzhardinge98abfc72003-12-16 02:05:15 +0000867
sewardj79048ce2005-02-18 08:28:32 +0000868 VG_(map_file_segment)(addr, len, prot, flags,
869 st.st_dev, st.st_ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000870}
871
nethercote8b5f40c2004-11-02 13:29:50 +0000872void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000873{
874 flags &= ~SF_FILE;
875
876 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
877}
878
879/* set new protection flags on an address range */
nethercote8b5f40c2004-11-02 13:29:50 +0000880void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000881{
sewardj79048ce2005-02-18 08:28:32 +0000882 Int r;
fitzhardinge98abfc72003-12-16 02:05:15 +0000883 static const Bool debug = False || mem_debug;
884
885 if (debug)
tom9be7c982005-04-25 16:55:44 +0000886 VG_(printf)("\nmprotect_range(%p, %lu, %x)\n", a, len, prot);
sewardje517b802005-02-16 01:58:51 +0000887
888 if (0) show_segments( "mprotect_range(before)" );
fitzhardinge98abfc72003-12-16 02:05:15 +0000889
890 /* Everything must be page-aligned */
njnbe91aae2005-03-27 01:42:41 +0000891 vg_assert(VG_IS_PAGE_ALIGNED(a));
njn13bfd852005-06-02 03:52:53 +0000892 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000893
sewardj79048ce2005-02-18 08:28:32 +0000894 split_segment(a);
895 split_segment(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000896
sewardj548be6d2005-02-16 01:31:37 +0000897 r = find_segment(a);
898 vg_assert(r != -1);
899 segments[r].prot = prot;
sewardj79048ce2005-02-18 08:28:32 +0000900
901 preen_segments();
902
sewardje517b802005-02-16 01:58:51 +0000903 if (0) show_segments( "mprotect_range(after)");
fitzhardinge98abfc72003-12-16 02:05:15 +0000904}
905
sewardj79048ce2005-02-18 08:28:32 +0000906
sewardj548be6d2005-02-16 01:31:37 +0000907/* Try to find a map space for [addr,addr+len). If addr==0, it means
908 the caller is prepared to accept a space at any location; if not,
909 we will try for addr, but fail if we can't get it. This mimics
910 mmap fixed vs mmap not-fixed.
911*/
nethercote8b5f40c2004-11-02 13:29:50 +0000912Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000913{
fitzhardingee3632c62003-12-22 10:58:06 +0000914 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000915 Addr ret;
sewardjb5f6f512005-03-10 23:59:00 +0000916 Addr addrOrig = addr;
nethercotea8bc3802004-10-19 17:54:02 +0000917 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
918 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
sewardj548be6d2005-02-16 01:31:37 +0000919 Addr hole_start, hole_end, hstart_any, hstart_fixed, hstart_final;
920 Int i, i_any, i_fixed, i_final;
921 SizeT hole_len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000922
sewardj548be6d2005-02-16 01:31:37 +0000923 Bool fixed;
924
sewardje517b802005-02-16 01:58:51 +0000925 if (debug) {
926 VG_(printf)("\n\n");
sewardja8d8e232005-06-07 20:04:56 +0000927 VG_(printf)("find_map_space(%p, %llu, %d) ...\n",
928 addr, (ULong)len, for_client);
sewardje517b802005-02-16 01:58:51 +0000929 }
930
931 if (0) show_segments("find_map_space: start");
932
sewardj548be6d2005-02-16 01:31:37 +0000933 if (addr == 0) {
934 fixed = False;
935 } else {
936 fixed = True;
fitzhardinge98abfc72003-12-16 02:05:15 +0000937 /* leave space for redzone and still try to get the exact
sewardj548be6d2005-02-16 01:31:37 +0000938 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000939 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000940 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000941
942 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000943 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
njn13bfd852005-06-02 03:52:53 +0000944 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000945
nethercote73b526f2004-10-31 18:48:21 +0000946 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000947
sewardj548be6d2005-02-16 01:31:37 +0000948 /* Scan the segment list, looking for a hole which satisfies the
949 requirements. At each point i we ask the question "can we use
950 the hole in between segments[i-1] and segments[i] ?" */
951 i_any = i_fixed = -1;
952 hstart_any = hstart_fixed = 0;
953
954 hole_start = hole_end = 0;
955
956 /* Iterate over all possible holes, generating them into
957 hole_start/hole_end. Filter out invalid ones. Then see if any
958 are usable; if so set i_fixed/i_any and hstart_fixed/hstart_any.
959 */
960 for (i = 0; i <=/*yes,really*/ segments_used; i++) {
961 if (i == 0) {
962 hole_start = 0;
963 hole_end = segments[0].addr-1;
964 }
965 else {
966 vg_assert(segments_used > 0);
967 if (i == segments_used) {
968 hole_start = segments[i-1].addr + segments[i-1].len;
969 hole_end = ~(Addr)0;
970 } else {
971 hole_start = segments[i-1].addr + segments[i-1].len;
972 hole_end = segments[i].addr - 1;
973 }
974 }
975
976 vg_assert(hole_start <= hole_end || hole_start == hole_end+1);
977
978 /* ignore zero-sized holes */
979 if (hole_start == hole_end+1)
980 continue;
981
njnbe91aae2005-03-27 01:42:41 +0000982 vg_assert(VG_IS_PAGE_ALIGNED(hole_start));
983 vg_assert(VG_IS_PAGE_ALIGNED(hole_end+1));
sewardj548be6d2005-02-16 01:31:37 +0000984
985 /* ignore holes which fall outside the allowable area */
986 if (!(hole_start >= base && hole_end <= limit))
987 continue;
988
989 vg_assert(hole_end > hole_start);
990 hole_len = hole_end - hole_start + 1;
njnbe91aae2005-03-27 01:42:41 +0000991 vg_assert(VG_IS_PAGE_ALIGNED(hole_len));
sewardj548be6d2005-02-16 01:31:37 +0000992
993 if (hole_len >= len && i_any == -1) {
994 /* It will at least fit in this hole. */
995 i_any = i;
996 hstart_any = hole_start;
997 }
998
sewardjb5f6f512005-03-10 23:59:00 +0000999 if (fixed && hole_start <= addr
1000 && hole_start+hole_len >= addr+len) {
sewardj548be6d2005-02-16 01:31:37 +00001001 /* We were asked for a fixed mapping, and this hole works.
1002 Bag it -- and stop searching as further searching is
1003 pointless. */
1004 i_fixed = i;
sewardjb5f6f512005-03-10 23:59:00 +00001005 hstart_fixed = addr;
sewardj548be6d2005-02-16 01:31:37 +00001006 break;
1007 }
1008 }
1009
1010 /* Summarise the final decision into i_final/hstart_final. */
1011 i_final = -1;
1012 hstart_final = 0;
1013
1014 if (fixed) {
1015 i_final = i_fixed;
sewardjb5f6f512005-03-10 23:59:00 +00001016 hstart_final = hstart_fixed + VKI_PAGE_SIZE; /* skip leading redzone */
sewardj548be6d2005-02-16 01:31:37 +00001017 } else {
1018 i_final = i_any;
1019 hstart_final = hstart_any;
1020 }
1021
1022
1023 if (i_final != -1)
sewardjb5f6f512005-03-10 23:59:00 +00001024 ret = hstart_final;
sewardj548be6d2005-02-16 01:31:37 +00001025 else
1026 ret = 0; /* not found */
1027
1028 if (debug)
sewardja8d8e232005-06-07 20:04:56 +00001029 VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n",
1030 addr, (ULong)len, for_client, ret);
sewardj548be6d2005-02-16 01:31:37 +00001031
sewardjb5f6f512005-03-10 23:59:00 +00001032 if (fixed) {
1033 vg_assert(ret == 0 || ret == addrOrig);
1034 }
1035
sewardj548be6d2005-02-16 01:31:37 +00001036 return ret;
fitzhardinge98abfc72003-12-16 02:05:15 +00001037}
1038
sewardj79048ce2005-02-18 08:28:32 +00001039
sewardjb5f6f512005-03-10 23:59:00 +00001040/* Pad the entire process address space, from "start"
nethercote820bd8c2004-09-07 23:04:49 +00001041 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +00001042 mapping over any part of the address space which is not covered
1043 by an entry in the segment list.
1044
1045 This is designed for use around system calls which allocate
1046 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +00001047 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +00001048 address with VG_(find_map_space) and then adding a segment for
1049 it and padding the address space valgrind can ensure that the
1050 kernel has no choice but to put the memory where we want it. */
sewardjb5f6f512005-03-10 23:59:00 +00001051void VG_(pad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001052{
sewardj394790d2005-03-17 02:14:44 +00001053 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001054 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001055
1056 Int i = 0;
1057 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001058
nethercote820bd8c2004-09-07 23:04:49 +00001059 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001060 if (addr < s->addr) {
njn7df470b2005-05-29 18:46:38 +00001061 ret = VG_(mmap_native)((void*)addr, s->addr - addr, 0,
njnf6d228b2005-03-26 02:42:31 +00001062 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1063 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001064 }
thughes9aaebc32004-07-15 23:13:37 +00001065 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001066 i++;
1067 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001068 }
1069
nethercote820bd8c2004-09-07 23:04:49 +00001070 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001071 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001072 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1073 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +00001074 }
thughes9aaebc32004-07-15 23:13:37 +00001075}
1076
thughesc70b8c62004-07-16 23:07:58 +00001077/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001078 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001079void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001080{
sewardj394790d2005-03-17 02:14:44 +00001081 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001082 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001083
1084 Int i = 0;
1085 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001086
nethercote820bd8c2004-09-07 23:04:49 +00001087 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001088 if (addr < s->addr) {
njnb69f7c12005-06-24 22:17:38 +00001089 //ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
njnca6fef02004-11-29 16:49:18 +00001090 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001091 }
thughes9aaebc32004-07-15 23:13:37 +00001092 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001093 i++;
1094 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001095 }
1096
nethercote820bd8c2004-09-07 23:04:49 +00001097 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001098 ret = VG_(do_syscall2)(__NR_munmap, addr,
1099 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001100 }
thughes9aaebc32004-07-15 23:13:37 +00001101}
1102
sewardj548be6d2005-02-16 01:31:37 +00001103/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001104Segment *VG_(find_segment)(Addr a)
1105{
sewardj548be6d2005-02-16 01:31:37 +00001106 Int r = find_segment(a);
1107 if (0) show_segments("find_segment");
1108 if (r == -1) return NULL;
1109 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001110}
1111
sewardj548be6d2005-02-16 01:31:37 +00001112/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1113 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1114 a segment is a checked error.
1115*/
1116Segment *VG_(find_segment_above_unmapped)(Addr a)
1117{
1118 Int r = find_segment_above_unmapped(a);
1119 if (0) show_segments("find_segment_above_unmapped");
1120 if (r == -1) return NULL;
1121 return &segments[r];
1122}
1123
1124/* Assumes that 'a' is in some segment. Finds the next segment along,
1125 or NULL if none. Passing 'a' which is in fact not in a segment is
1126 a checked error.
1127*/
1128Segment *VG_(find_segment_above_mapped)(Addr a)
1129{
1130 Int r = find_segment_above_mapped(a);
1131 if (0) show_segments("find_segment_above_mapped");
1132 if (r == -1) return NULL;
1133 return &segments[r];
1134}
1135
1136
jsgf855d93d2003-10-13 22:26:55 +00001137/*
sewardjb5f6f512005-03-10 23:59:00 +00001138 Test if a piece of memory is addressable with at least the "prot"
1139 protection permissions by examining the underlying segments.
1140
1141 Really this is a very stupid algorithm and we could do much
1142 better by iterating through the segment array instead of through
1143 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001144 */
sewardjb5f6f512005-03-10 23:59:00 +00001145Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001146{
sewardjb5f6f512005-03-10 23:59:00 +00001147 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001148
sewardjb5f6f512005-03-10 23:59:00 +00001149 if ((p + size) < p)
1150 return False; /* reject wraparounds */
1151 if (size == 0)
1152 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001153
njn13bfd852005-06-02 03:52:53 +00001154 p = VG_PGROUNDDN(p);
1155 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001156 vg_assert(VG_IS_PAGE_ALIGNED(p));
1157 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001158
sewardjb5f6f512005-03-10 23:59:00 +00001159 for (; size > 0; size -= VKI_PAGE_SIZE) {
1160 seg = VG_(find_segment)(p);
1161 if (!seg)
1162 return False;
1163 if ((seg->prot & prot) != prot)
1164 return False;
1165 p += VKI_PAGE_SIZE;
1166 }
jsgf855d93d2003-10-13 22:26:55 +00001167
sewardjb5f6f512005-03-10 23:59:00 +00001168 return True;
jsgf855d93d2003-10-13 22:26:55 +00001169}
1170
sewardjb5f6f512005-03-10 23:59:00 +00001171
sewardjde4a1d02002-03-22 01:27:54 +00001172/*--------------------------------------------------------------------*/
njn9260c782005-06-19 21:57:54 +00001173/*--- Random function that doesn't really belong here ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001174/*--------------------------------------------------------------------*/
1175
njn86f12dc2005-03-14 01:16:05 +00001176/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001177 range, which isn't SF_CORE, a root.
1178*/
njn86f12dc2005-03-14 01:16:05 +00001179void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1180{
sewardj882af5f2005-03-16 12:27:53 +00001181 Int i;
1182 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001183 Segment *s;
1184
sewardj882af5f2005-03-16 12:27:53 +00001185 for (i = 0; i < segments_used; i++) {
1186 s = &segments[i];
njnf253dac2005-06-28 22:38:24 +00001187 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND|SF_CORE|SF_STACK);
tom5912dd72005-07-18 09:40:29 +00001188 if (flags != SF_MMAP && flags != SF_STACK && flags != (SF_MMAP|SF_STACK))
njn86f12dc2005-03-14 01:16:05 +00001189 continue;
sewardj882af5f2005-03-16 12:27:53 +00001190 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1191 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001192 continue;
1193 if (!VG_(is_client_addr)(s->addr) ||
njnf253dac2005-06-28 22:38:24 +00001194 !VG_(is_client_addr)(s->addr+s->len-1))
njn86f12dc2005-03-14 01:16:05 +00001195 continue;
1196
1197 (*add_rootrange)(s->addr, s->len);
1198 }
njn86f12dc2005-03-14 01:16:05 +00001199}
1200
1201
nethercote88a90162004-07-10 16:59:25 +00001202/*--------------------------------------------------------------------*/
1203/*--- Querying memory layout ---*/
1204/*--------------------------------------------------------------------*/
1205
fitzhardinge98abfc72003-12-16 02:05:15 +00001206Bool VG_(is_client_addr)(Addr a)
1207{
1208 return a >= VG_(client_base) && a < VG_(client_end);
1209}
1210
1211Bool VG_(is_shadow_addr)(Addr a)
1212{
1213 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1214}
1215
sewardjfa8202f2005-04-24 11:05:55 +00001216
nethercote88a90162004-07-10 16:59:25 +00001217/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001218/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001219/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001220
fitzhardinge98abfc72003-12-16 02:05:15 +00001221void *VG_(shadow_alloc)(UInt size)
1222{
1223 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001224 Addr try_here;
njne9befc62005-06-11 15:51:30 +00001225 SysRes r;
sewardj79048ce2005-02-18 08:28:32 +00001226
1227 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001228
1229 vg_assert(VG_(needs).shadow_memory);
fitzhardinge98abfc72003-12-16 02:05:15 +00001230
njn13bfd852005-06-02 03:52:53 +00001231 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001232
1233 if (shadow_alloc == 0)
1234 shadow_alloc = VG_(shadow_base);
1235
1236 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001237 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001238
sewardj79048ce2005-02-18 08:28:32 +00001239 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001240 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1241 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001242 vg_assert(size > 0);
1243
1244 if (0)
1245 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1246
1247 /* this is big-bang allocated, so we don't expect to find a listed
1248 segment for it. */
1249 /* This is really an absolute disgrace. Sometimes the big-bang
1250 mapping is in the list (due to re-reads of /proc/self/maps,
1251 presumably) and sometimes it isn't. */
1252#if 0
1253 r = find_segment(try_here);
1254 vg_assert(r == -1);
1255 r = find_segment(try_here+size-1);
1256 vg_assert(r == -1);
1257#endif
1258
1259 r = VG_(mprotect_native)( (void*)try_here,
1260 size, VKI_PROT_READ|VKI_PROT_WRITE );
1261
njne9befc62005-06-11 15:51:30 +00001262 if (r.isError)
sewardj79048ce2005-02-18 08:28:32 +00001263 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001264
1265 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001266 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001267
sewardj79048ce2005-02-18 08:28:32 +00001268 failed:
1269 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001270 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001271 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001272 size
sewardj79048ce2005-02-18 08:28:32 +00001273 );
1274 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001275}
1276
njne3f06352005-06-01 03:48:33 +00001277/*------------------------------------------------------------*/
1278/*--- pointercheck ---*/
1279/*------------------------------------------------------------*/
1280
njnaf839f52005-06-23 03:27:57 +00001281Bool VG_(setup_pointercheck)(Addr client_base, Addr client_end)
njne3f06352005-06-01 03:48:33 +00001282{
1283 vg_assert(0 != client_end);
1284#if defined(VGP_x86_linux)
1285 /* Client address space segment limit descriptor entry */
1286 #define POINTERCHECK_SEGIDX 1
1287
1288 vki_modify_ldt_t ldt = {
1289 POINTERCHECK_SEGIDX, // entry_number
1290 client_base, // base_addr
1291 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1292 1, // seg_32bit
1293 0, // contents: data, RW, non-expanding
1294 0, // ! read_exec_only
1295 1, // limit_in_pages
1296 0, // ! seg not present
1297 1, // useable
1298 };
sewardja8d8e232005-06-07 20:04:56 +00001299 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1300 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001301 VG_(message)(Vg_UserMsg,
1302 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001303 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001304 return False;
1305 } else {
1306 return True;
1307 }
1308#elif defined(VGP_amd64_linux)
1309 if (0)
1310 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1311 return True;
cerion85665ca2005-06-20 15:51:07 +00001312#elif defined(VGP_ppc32_linux)
1313 if (0)
1314 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1315 return True;
njne3f06352005-06-01 03:48:33 +00001316#else
1317# error Unknown architecture
1318#endif
1319}
1320
fitzhardinge98abfc72003-12-16 02:05:15 +00001321/*--------------------------------------------------------------------*/
njn945ed2e2005-06-24 03:28:30 +00001322/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001323/*--------------------------------------------------------------------*/