blob: 250a535d7f74d77d94edbd2f654083975e9fa903 [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);
tom32327ec2005-07-19 07:37:51 +00001064 vg_assert(!ret.isError);
thughes9aaebc32004-07-15 23:13:37 +00001065 }
thughes9aaebc32004-07-15 23:13:37 +00001066 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001067 i++;
1068 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001069 }
1070
nethercote820bd8c2004-09-07 23:04:49 +00001071 if (addr <= VG_(valgrind_last)) {
njn7df470b2005-05-29 18:46:38 +00001072 ret = VG_(mmap_native)((void*)addr, VG_(valgrind_last) - addr + 1, 0,
njnf6d228b2005-03-26 02:42:31 +00001073 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
1074 -1, 0);
tom32327ec2005-07-19 07:37:51 +00001075 vg_assert(!ret.isError);
thughes9aaebc32004-07-15 23:13:37 +00001076 }
thughes9aaebc32004-07-15 23:13:37 +00001077}
1078
thughesc70b8c62004-07-16 23:07:58 +00001079/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +00001080 by removing any mappings that it created. */
sewardjb5f6f512005-03-10 23:59:00 +00001081void VG_(unpad_address_space)(Addr start)
thughes9aaebc32004-07-15 23:13:37 +00001082{
sewardj394790d2005-03-17 02:14:44 +00001083 Addr addr = (start == 0) ? VG_(client_base) : start;
sewardja8d8e232005-06-07 20:04:56 +00001084 SysRes ret;
sewardj394790d2005-03-17 02:14:44 +00001085
1086 Int i = 0;
1087 Segment* s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001088
nethercote820bd8c2004-09-07 23:04:49 +00001089 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +00001090 if (addr < s->addr) {
njnb69f7c12005-06-24 22:17:38 +00001091 //ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
njnca6fef02004-11-29 16:49:18 +00001092 ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +00001093 }
thughes9aaebc32004-07-15 23:13:37 +00001094 addr = s->addr + s->len;
sewardj394790d2005-03-17 02:14:44 +00001095 i++;
1096 s = i >= segments_used ? NULL : &segments[i];
thughes9aaebc32004-07-15 23:13:37 +00001097 }
1098
nethercote820bd8c2004-09-07 23:04:49 +00001099 if (addr <= VG_(valgrind_last)) {
sewardj394790d2005-03-17 02:14:44 +00001100 ret = VG_(do_syscall2)(__NR_munmap, addr,
1101 (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +00001102 }
thughes9aaebc32004-07-15 23:13:37 +00001103}
1104
sewardj548be6d2005-02-16 01:31:37 +00001105/* Find the segment holding 'a', or NULL if none. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001106Segment *VG_(find_segment)(Addr a)
1107{
sewardj548be6d2005-02-16 01:31:37 +00001108 Int r = find_segment(a);
1109 if (0) show_segments("find_segment");
1110 if (r == -1) return NULL;
1111 return &segments[r];
fitzhardinge98abfc72003-12-16 02:05:15 +00001112}
1113
sewardj548be6d2005-02-16 01:31:37 +00001114/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
1115 segment above 'a', or NULL if none. Passing 'a' which is in fact in
1116 a segment is a checked error.
1117*/
1118Segment *VG_(find_segment_above_unmapped)(Addr a)
1119{
1120 Int r = find_segment_above_unmapped(a);
1121 if (0) show_segments("find_segment_above_unmapped");
1122 if (r == -1) return NULL;
1123 return &segments[r];
1124}
1125
1126/* Assumes that 'a' is in some segment. Finds the next segment along,
1127 or NULL if none. Passing 'a' which is in fact not in a segment is
1128 a checked error.
1129*/
1130Segment *VG_(find_segment_above_mapped)(Addr a)
1131{
1132 Int r = find_segment_above_mapped(a);
1133 if (0) show_segments("find_segment_above_mapped");
1134 if (r == -1) return NULL;
1135 return &segments[r];
1136}
1137
1138
jsgf855d93d2003-10-13 22:26:55 +00001139/*
sewardjb5f6f512005-03-10 23:59:00 +00001140 Test if a piece of memory is addressable with at least the "prot"
1141 protection permissions by examining the underlying segments.
1142
1143 Really this is a very stupid algorithm and we could do much
1144 better by iterating through the segment array instead of through
1145 the address space.
jsgf855d93d2003-10-13 22:26:55 +00001146 */
sewardjb5f6f512005-03-10 23:59:00 +00001147Bool VG_(is_addressable)(Addr p, SizeT size, UInt prot)
jsgf855d93d2003-10-13 22:26:55 +00001148{
sewardjb5f6f512005-03-10 23:59:00 +00001149 Segment *seg;
jsgf855d93d2003-10-13 22:26:55 +00001150
sewardjb5f6f512005-03-10 23:59:00 +00001151 if ((p + size) < p)
1152 return False; /* reject wraparounds */
1153 if (size == 0)
1154 return True; /* isn't this a bit of a strange case? */
jsgf855d93d2003-10-13 22:26:55 +00001155
njn13bfd852005-06-02 03:52:53 +00001156 p = VG_PGROUNDDN(p);
1157 size = VG_PGROUNDUP(size);
njnbe91aae2005-03-27 01:42:41 +00001158 vg_assert(VG_IS_PAGE_ALIGNED(p));
1159 vg_assert(VG_IS_PAGE_ALIGNED(size));
jsgf855d93d2003-10-13 22:26:55 +00001160
sewardjb5f6f512005-03-10 23:59:00 +00001161 for (; size > 0; size -= VKI_PAGE_SIZE) {
1162 seg = VG_(find_segment)(p);
1163 if (!seg)
1164 return False;
1165 if ((seg->prot & prot) != prot)
1166 return False;
1167 p += VKI_PAGE_SIZE;
1168 }
jsgf855d93d2003-10-13 22:26:55 +00001169
sewardjb5f6f512005-03-10 23:59:00 +00001170 return True;
jsgf855d93d2003-10-13 22:26:55 +00001171}
1172
sewardjb5f6f512005-03-10 23:59:00 +00001173
sewardjde4a1d02002-03-22 01:27:54 +00001174/*--------------------------------------------------------------------*/
njn9260c782005-06-19 21:57:54 +00001175/*--- Random function that doesn't really belong here ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001176/*--------------------------------------------------------------------*/
1177
njn86f12dc2005-03-14 01:16:05 +00001178/* We'll call any RW mmaped memory segment, within the client address
sewardj882af5f2005-03-16 12:27:53 +00001179 range, which isn't SF_CORE, a root.
1180*/
njn86f12dc2005-03-14 01:16:05 +00001181void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
1182{
sewardj882af5f2005-03-16 12:27:53 +00001183 Int i;
1184 UInt flags;
njn86f12dc2005-03-14 01:16:05 +00001185 Segment *s;
1186
sewardj882af5f2005-03-16 12:27:53 +00001187 for (i = 0; i < segments_used; i++) {
1188 s = &segments[i];
njnf253dac2005-06-28 22:38:24 +00001189 flags = s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND|SF_CORE|SF_STACK);
tom5912dd72005-07-18 09:40:29 +00001190 if (flags != SF_MMAP && flags != SF_STACK && flags != (SF_MMAP|SF_STACK))
njn86f12dc2005-03-14 01:16:05 +00001191 continue;
sewardj882af5f2005-03-16 12:27:53 +00001192 if ((s->prot & (VKI_PROT_READ|VKI_PROT_WRITE))
1193 != (VKI_PROT_READ|VKI_PROT_WRITE))
njn86f12dc2005-03-14 01:16:05 +00001194 continue;
1195 if (!VG_(is_client_addr)(s->addr) ||
njnf253dac2005-06-28 22:38:24 +00001196 !VG_(is_client_addr)(s->addr+s->len-1))
njn86f12dc2005-03-14 01:16:05 +00001197 continue;
1198
1199 (*add_rootrange)(s->addr, s->len);
1200 }
njn86f12dc2005-03-14 01:16:05 +00001201}
1202
1203
nethercote88a90162004-07-10 16:59:25 +00001204/*--------------------------------------------------------------------*/
1205/*--- Querying memory layout ---*/
1206/*--------------------------------------------------------------------*/
1207
fitzhardinge98abfc72003-12-16 02:05:15 +00001208Bool VG_(is_client_addr)(Addr a)
1209{
1210 return a >= VG_(client_base) && a < VG_(client_end);
1211}
1212
1213Bool VG_(is_shadow_addr)(Addr a)
1214{
1215 return a >= VG_(shadow_base) && a < VG_(shadow_end);
1216}
1217
sewardjfa8202f2005-04-24 11:05:55 +00001218
nethercote88a90162004-07-10 16:59:25 +00001219/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +00001220/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +00001221/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001222
fitzhardinge98abfc72003-12-16 02:05:15 +00001223void *VG_(shadow_alloc)(UInt size)
1224{
1225 static Addr shadow_alloc = 0;
sewardj79048ce2005-02-18 08:28:32 +00001226 Addr try_here;
njne9befc62005-06-11 15:51:30 +00001227 SysRes r;
sewardj79048ce2005-02-18 08:28:32 +00001228
1229 if (0) show_segments("shadow_alloc(before)");
fitzhardinge98abfc72003-12-16 02:05:15 +00001230
1231 vg_assert(VG_(needs).shadow_memory);
fitzhardinge98abfc72003-12-16 02:05:15 +00001232
njn13bfd852005-06-02 03:52:53 +00001233 size = VG_PGROUNDUP(size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001234
1235 if (shadow_alloc == 0)
1236 shadow_alloc = VG_(shadow_base);
1237
1238 if (shadow_alloc >= VG_(shadow_end))
sewardj79048ce2005-02-18 08:28:32 +00001239 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001240
sewardj79048ce2005-02-18 08:28:32 +00001241 try_here = shadow_alloc;
njnbe91aae2005-03-27 01:42:41 +00001242 vg_assert(VG_IS_PAGE_ALIGNED(try_here));
1243 vg_assert(VG_IS_PAGE_ALIGNED(size));
sewardj79048ce2005-02-18 08:28:32 +00001244 vg_assert(size > 0);
1245
1246 if (0)
1247 VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
1248
1249 /* this is big-bang allocated, so we don't expect to find a listed
1250 segment for it. */
1251 /* This is really an absolute disgrace. Sometimes the big-bang
1252 mapping is in the list (due to re-reads of /proc/self/maps,
1253 presumably) and sometimes it isn't. */
1254#if 0
1255 r = find_segment(try_here);
1256 vg_assert(r == -1);
1257 r = find_segment(try_here+size-1);
1258 vg_assert(r == -1);
1259#endif
1260
1261 r = VG_(mprotect_native)( (void*)try_here,
1262 size, VKI_PROT_READ|VKI_PROT_WRITE );
1263
njne9befc62005-06-11 15:51:30 +00001264 if (r.isError)
sewardj79048ce2005-02-18 08:28:32 +00001265 goto failed;
fitzhardinge98abfc72003-12-16 02:05:15 +00001266
1267 shadow_alloc += size;
sewardj79048ce2005-02-18 08:28:32 +00001268 return (void*)try_here;
fitzhardinge98abfc72003-12-16 02:05:15 +00001269
sewardj79048ce2005-02-18 08:28:32 +00001270 failed:
1271 VG_(printf)(
sewardj96db5e12005-03-21 17:43:34 +00001272 "valgrind: Could not allocate address space (0x%x bytes)\n"
sewardj79048ce2005-02-18 08:28:32 +00001273 "valgrind: for shadow memory chunk.\n",
sewardj96db5e12005-03-21 17:43:34 +00001274 size
sewardj79048ce2005-02-18 08:28:32 +00001275 );
1276 VG_(exit)(1);
fitzhardinge98abfc72003-12-16 02:05:15 +00001277}
1278
njne3f06352005-06-01 03:48:33 +00001279/*------------------------------------------------------------*/
1280/*--- pointercheck ---*/
1281/*------------------------------------------------------------*/
1282
njnaf839f52005-06-23 03:27:57 +00001283Bool VG_(setup_pointercheck)(Addr client_base, Addr client_end)
njne3f06352005-06-01 03:48:33 +00001284{
1285 vg_assert(0 != client_end);
1286#if defined(VGP_x86_linux)
1287 /* Client address space segment limit descriptor entry */
1288 #define POINTERCHECK_SEGIDX 1
1289
1290 vki_modify_ldt_t ldt = {
1291 POINTERCHECK_SEGIDX, // entry_number
1292 client_base, // base_addr
1293 (client_end - client_base) / VKI_PAGE_SIZE, // limit
1294 1, // seg_32bit
1295 0, // contents: data, RW, non-expanding
1296 0, // ! read_exec_only
1297 1, // limit_in_pages
1298 0, // ! seg not present
1299 1, // useable
1300 };
sewardja8d8e232005-06-07 20:04:56 +00001301 SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt));
1302 if (ret.isError) {
njne3f06352005-06-01 03:48:33 +00001303 VG_(message)(Vg_UserMsg,
1304 "Warning: ignoring --pointercheck=yes, "
sewardja8d8e232005-06-07 20:04:56 +00001305 "because modify_ldt failed (errno=%d)", ret.val);
njne3f06352005-06-01 03:48:33 +00001306 return False;
1307 } else {
1308 return True;
1309 }
1310#elif defined(VGP_amd64_linux)
1311 if (0)
1312 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1313 return True;
cerion85665ca2005-06-20 15:51:07 +00001314#elif defined(VGP_ppc32_linux)
1315 if (0)
1316 VG_(message)(Vg_DebugMsg, "ignoring --pointercheck (unimplemented)");
1317 return True;
njne3f06352005-06-01 03:48:33 +00001318#else
1319# error Unknown architecture
1320#endif
1321}
1322
fitzhardinge98abfc72003-12-16 02:05:15 +00001323/*--------------------------------------------------------------------*/
njn945ed2e2005-06-24 03:28:30 +00001324/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001325/*--------------------------------------------------------------------*/