blob: 43915e18c535055c3a15f2ac69bfabd201577b55 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00003/*--- Memory-related stuff: segment initialisation and tracking, ---*/
4/*--- stack operations ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005/*--- vg_memory.c ---*/
6/*--------------------------------------------------------------------*/
7
8/*
njnc9539842002-10-02 13:26:35 +00009 This file is part of Valgrind, an extensible x86 protected-mode
10 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000011
nethercotebb1c9912004-01-04 16:43:23 +000012 Copyright (C) 2000-2004 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
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
sewardjde4a1d02002-03-22 01:27:54 +000034
sewardja4495682002-10-21 07:29:59 +000035/* Define to debug the memory-leak-detector. */
36/* #define VG_DEBUG_LEAKCHECK */
37
fitzhardinge98abfc72003-12-16 02:05:15 +000038static const Bool mem_debug = False;
39
40static Int addrcmp(const void *ap, const void *bp)
41{
42 Addr a = *(Addr *)ap;
43 Addr b = *(Addr *)bp;
44 Int ret;
45
46 if (a == b)
47 ret = 0;
48 else
49 ret = (a < b) ? -1 : 1;
50
51 return ret;
52}
53
54static Char *straddr(void *p)
55{
56 static Char buf[16];
57
58 VG_(sprintf)(buf, "%p", *(Addr *)p);
59
60 return buf;
61}
62
63static SkipList sk_segments = SKIPLIST_INIT(Segment, addr, addrcmp, straddr, VG_AR_CORE);
64
65/*--------------------------------------------------------------*/
66/*--- Maintain an ordered list of all the client's mappings ---*/
67/*--------------------------------------------------------------*/
68
69Bool VG_(seg_contains)(const Segment *s, Addr p, UInt len)
70{
71 Addr se = s->addr+s->len;
72 Addr pe = p+len;
73
74 vg_assert(pe >= p);
75
76 return (p >= s->addr && pe <= se);
77}
78
79Bool VG_(seg_overlaps)(const Segment *s, Addr p, UInt len)
80{
81 Addr se = s->addr+s->len;
82 Addr pe = p+len;
83
84 vg_assert(pe >= p);
85
86 return (p < se && pe > s->addr);
87}
88
89/* Prepare a Segment structure for recycling by freeing everything
90 hanging off it. */
91static void recycleseg(Segment *s)
92{
93 if (s->flags & SF_CODE)
94 VG_(invalidate_translations)(s->addr, s->len, False);
95
96 if (s->filename != NULL)
97 VG_(arena_free)(VG_AR_CORE, (Char *)s->filename);
98
99 /* keep the SegInfo, if any - it probably still applies */
100}
101
102/* When freeing a Segment, also clean up every one else's ideas of
103 what was going on in that range of memory */
104static void freeseg(Segment *s)
105{
106 recycleseg(s);
107 if (s->symtab != NULL) {
108 VG_(symtab_decref)(s->symtab, s->addr, s->len);
109 s->symtab = NULL;
110 }
111
112 VG_(SkipNode_Free)(&sk_segments, s);
113}
114
fitzhardinge1a303042003-12-22 08:48:50 +0000115/* Split a segment at address a, returning the new segment */
116Segment *VG_(split_segment)(Addr a)
fitzhardinge98abfc72003-12-16 02:05:15 +0000117{
118 Segment *s = VG_(SkipList_Find)(&sk_segments, &a);
119 Segment *ns;
120 Int delta;
121
nethercote73b526f2004-10-31 18:48:21 +0000122 vg_assert((a & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000123
124 /* missed */
125 if (s == NULL)
126 return NULL;
127
128 /* a at or beyond endpoint */
129 if (s->addr == a || a >= (s->addr+s->len))
130 return NULL;
131
132 vg_assert(a > s->addr && a < (s->addr+s->len));
133
134 ns = VG_(SkipNode_Alloc)(&sk_segments);
135
136 *ns = *s;
137
138 delta = a - s->addr;
139 ns->addr += delta;
140 ns->offset += delta;
141 ns->len -= delta;
fitzhardingee3632c62003-12-22 10:58:06 +0000142 s->len = delta;
fitzhardinge98abfc72003-12-16 02:05:15 +0000143
fitzhardinge1a4adf02003-12-22 10:42:59 +0000144 if (s->filename != NULL)
145 ns->filename = VG_(arena_strdup)(VG_AR_CORE, s->filename);
146
fitzhardinge98abfc72003-12-16 02:05:15 +0000147 if (ns->symtab != NULL)
148 VG_(symtab_incref)(ns->symtab);
149
150 VG_(SkipList_Insert)(&sk_segments, ns);
151
152 return ns;
153}
154
155/* This unmaps all the segments in the range [addr, addr+len); any
156 partial mappings at the ends are truncated. */
157void VG_(unmap_range)(Addr addr, UInt len)
158{
159 Segment *s;
160 Segment *next;
fitzhardingee3632c62003-12-22 10:58:06 +0000161 static const Bool debug = False || mem_debug;
fitzhardinge1a4adf02003-12-22 10:42:59 +0000162 Addr end;
fitzhardinge98abfc72003-12-16 02:05:15 +0000163
164 if (len == 0)
165 return;
166
fitzhardinge1a4adf02003-12-22 10:42:59 +0000167 len = PGROUNDUP(len);
168 vg_assert(addr == PGROUNDDN(addr));
169
fitzhardinge98abfc72003-12-16 02:05:15 +0000170 if (debug)
171 VG_(printf)("unmap_range(%p, %d)\n", addr, len);
172
fitzhardinge1a4adf02003-12-22 10:42:59 +0000173 end = addr+len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000174
175 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000176 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
177 vg_assert((len & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000178
179 for(s = VG_(SkipList_Find)(&sk_segments, &addr);
180 s != NULL && s->addr < (addr+len);
181 s = next) {
fitzhardinge1a303042003-12-22 08:48:50 +0000182 Addr seg_end = s->addr + s->len;
fitzhardinge98abfc72003-12-16 02:05:15 +0000183
184 /* fetch next now in case we end up deleting this segment */
185 next = VG_(SkipNode_Next)(&sk_segments, s);
186
187 if (debug)
fitzhardinge1a303042003-12-22 08:48:50 +0000188 VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
fitzhardinge1a4adf02003-12-22 10:42:59 +0000189 addr, end, s, s->addr, seg_end, s->len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000190
fitzhardinge1a303042003-12-22 08:48:50 +0000191 if (!VG_(seg_overlaps)(s, addr, len)) {
192 if (debug)
193 VG_(printf)(" (no overlap)\n");
fitzhardinge98abfc72003-12-16 02:05:15 +0000194 continue;
fitzhardinge1a303042003-12-22 08:48:50 +0000195 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000196
197 /* 4 cases: */
fitzhardinge1a303042003-12-22 08:48:50 +0000198 if (addr > s->addr &&
199 addr < seg_end &&
200 end >= seg_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000201 /* this segment's tail is truncated by [addr, addr+len)
202 -> truncate tail
203 */
204 s->len = addr - s->addr;
205
206 if (debug)
207 VG_(printf)(" case 1: s->len=%d\n", s->len);
fitzhardingee3632c62003-12-22 10:58:06 +0000208 } else if (addr <= s->addr && end > s->addr && end < seg_end) {
209 /* this segment's head is truncated by [addr, addr+len)
210 -> truncate head
211 */
212 Int delta = end - s->addr;
213
214 if (debug)
215 VG_(printf)(" case 2: s->addr=%p s->len=%d delta=%d\n", s->addr, s->len, delta);
216
217 s->addr += delta;
218 s->offset += delta;
219 s->len -= delta;
220
221 vg_assert(s->len != 0);
fitzhardinge1a303042003-12-22 08:48:50 +0000222 } else if (addr <= s->addr && end >= seg_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000223 /* this segment is completely contained within [addr, addr+len)
224 -> delete segment
225 */
226 Segment *rs = VG_(SkipList_Remove)(&sk_segments, &s->addr);
227 vg_assert(rs == s);
228 freeseg(s);
229
230 if (debug)
fitzhardingee3632c62003-12-22 10:58:06 +0000231 VG_(printf)(" case 3: s==%p deleted\n", s);
fitzhardinge1a303042003-12-22 08:48:50 +0000232 } else if (addr > s->addr && end < seg_end) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000233 /* [addr, addr+len) is contained within a single segment
234 -> split segment into 3, delete middle portion
235 */
236 Segment *middle, *rs;
237
fitzhardinge1a303042003-12-22 08:48:50 +0000238 middle = VG_(split_segment)(addr);
239 VG_(split_segment)(addr+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000240
241 vg_assert(middle->addr == addr);
242 rs = VG_(SkipList_Remove)(&sk_segments, &addr);
243 vg_assert(rs == middle);
244
245 freeseg(rs);
246
247 if (debug)
248 VG_(printf)(" case 4: subrange %p-%p deleted\n",
249 addr, addr+len);
250 }
251 }
252}
253
fitzhardinge1a4adf02003-12-22 10:42:59 +0000254/* Return true if two segments are adjacent and mergable (s1 is
255 assumed to have a lower ->addr than s2) */
fitzhardinge98abfc72003-12-16 02:05:15 +0000256static inline Bool neighbours(Segment *s1, Segment *s2)
257{
258 if (s1->addr+s1->len != s2->addr)
259 return False;
260
261 if (s1->flags != s2->flags)
262 return False;
263
264 if (s1->prot != s2->prot)
265 return False;
266
267 if (s1->symtab != s2->symtab)
268 return False;
269
270 if (s1->flags & SF_FILE){
271 if ((s1->offset + s1->len) != s2->offset)
272 return False;
273 if (s1->dev != s2->dev)
274 return False;
275 if (s1->ino != s2->ino)
276 return False;
277 }
278
279 return True;
280}
281
fitzhardinge1a4adf02003-12-22 10:42:59 +0000282/* If possible, merge segment with its neighbours - some segments,
283 including s, may be destroyed in the process */
fitzhardinge98abfc72003-12-16 02:05:15 +0000284static void merge_segments(Addr a, UInt len)
285{
286 Segment *s;
287 Segment *next;
288
nethercote73b526f2004-10-31 18:48:21 +0000289 vg_assert((a & (VKI_PAGE_SIZE-1)) == 0);
290 vg_assert((len & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000291
nethercote73b526f2004-10-31 18:48:21 +0000292 a -= VKI_PAGE_SIZE;
293 len += VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000294
295 for(s = VG_(SkipList_Find)(&sk_segments, &a);
296 s != NULL && s->addr < (a+len);) {
297 next = VG_(SkipNode_Next)(&sk_segments, s);
298
299 if (next && neighbours(s, next)) {
300 Segment *rs;
301
302 if (0)
303 VG_(printf)("merge %p-%p with %p-%p\n",
304 s->addr, s->addr+s->len,
305 next->addr, next->addr+next->len);
306 s->len += next->len;
307 s = VG_(SkipNode_Next)(&sk_segments, next);
308
309 rs = VG_(SkipList_Remove)(&sk_segments, &next->addr);
310 vg_assert(next == rs);
311 freeseg(next);
312 } else
313 s = next;
314 }
315}
316
317void VG_(map_file_segment)(Addr addr, UInt len, UInt prot, UInt flags,
318 UInt dev, UInt ino, ULong off, const Char *filename)
319{
320 Segment *s;
321 static const Bool debug = False || mem_debug;
322 Bool recycled;
323
324 if (debug)
325 VG_(printf)("map_file_segment(%p, %d, %x, %x, %4x, %d, %ld, %s)\n",
326 addr, len, prot, flags, dev, ino, off, filename);
327
328 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000329 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000330 len = PGROUNDUP(len);
331
332 /* First look to see what already exists around here */
333 s = VG_(SkipList_Find)(&sk_segments, &addr);
334
335 if (s != NULL && s->addr == addr && s->len == len) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000336 recycled = True;
337 recycleseg(s);
338
339 /* If we had a symtab, but the new mapping is incompatible, then
340 free up the old symtab in preparation for a new one. */
341 if (s->symtab != NULL &&
342 (!(s->flags & SF_FILE) ||
343 !(flags & SF_FILE) ||
344 s->dev != dev ||
345 s->ino != ino ||
346 s->offset != off)) {
347 VG_(symtab_decref)(s->symtab, s->addr, s->len);
348 s->symtab = NULL;
349 }
350 } else {
351 recycled = False;
352 VG_(unmap_range)(addr, len);
353
354 s = VG_(SkipNode_Alloc)(&sk_segments);
355
356 s->addr = addr;
357 s->len = len;
358 s->symtab = NULL;
359 }
360
361 s->flags = flags;
362 s->prot = prot;
363 s->dev = dev;
364 s->ino = ino;
365 s->offset = off;
366
367 if (filename != NULL)
368 s->filename = VG_(arena_strdup)(VG_AR_CORE, filename);
369 else
370 s->filename = NULL;
371
372 if (debug) {
373 Segment *ts;
374 for(ts = VG_(SkipNode_First)(&sk_segments);
375 ts != NULL;
376 ts = VG_(SkipNode_Next)(&sk_segments, ts))
377 VG_(printf)("list: %8p->%8p ->%d (0x%x) prot=%x flags=%x\n",
378 ts, ts->addr, ts->len, ts->len, ts->prot, ts->flags);
379
380 VG_(printf)("inserting s=%p addr=%p len=%d\n",
381 s, s->addr, s->len);
382 }
383
384 if (!recycled)
385 VG_(SkipList_Insert)(&sk_segments, s);
386
387 /* If this mapping is of the beginning of a file, isn't part of
388 Valgrind, is at least readable and seems to contain an object
389 file, then try reading symbols from it. */
390 if ((flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP &&
391 s->symtab == NULL) {
392 if (off == 0 &&
393 filename != NULL &&
394 (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC) &&
nethercote73b526f2004-10-31 18:48:21 +0000395 len >= VKI_PAGE_SIZE &&
fitzhardinge98abfc72003-12-16 02:05:15 +0000396 s->symtab == NULL &&
nethercote71980f02004-01-24 18:18:54 +0000397 VG_(is_object_file)((void *)addr))
398 {
399 s->symtab = VG_(read_seg_symbols)(s);
fitzhardinge98abfc72003-12-16 02:05:15 +0000400
nethercote71980f02004-01-24 18:18:54 +0000401 if (s->symtab != NULL) {
402 s->flags |= SF_DYNLIB;
403 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000404 } else if (flags & SF_MMAP) {
405 const SegInfo *info;
406
407 /* Otherwise see if an existing symtab applies to this Segment */
408 for(info = VG_(next_seginfo)(NULL);
409 info != NULL;
410 info = VG_(next_seginfo)(info)) {
nethercote71980f02004-01-24 18:18:54 +0000411 if (VG_(seg_overlaps)(s, VG_(seg_start)(info), VG_(seg_size)(info)))
412 {
fitzhardinge98abfc72003-12-16 02:05:15 +0000413 s->symtab = (SegInfo *)info;
414 VG_(symtab_incref)((SegInfo *)info);
415 }
416 }
417 }
418 }
419
420 /* clean up */
421 merge_segments(addr, len);
422}
423
424void VG_(map_fd_segment)(Addr addr, UInt len, UInt prot, UInt flags,
425 Int fd, ULong off, const Char *filename)
426{
427 struct vki_stat st;
428 Char *name = NULL;
429
430 st.st_dev = 0;
431 st.st_ino = 0;
432
433 if (fd != -1 && (flags & SF_FILE)) {
nethercote73b526f2004-10-31 18:48:21 +0000434 vg_assert((off & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000435
436 if (VG_(fstat)(fd, &st) < 0)
437 flags &= ~SF_FILE;
438 }
439
440 if ((flags & SF_FILE) && filename == NULL && fd != -1)
441 name = VG_(resolve_filename)(fd);
442
443 if (filename == NULL)
444 filename = name;
445
446 VG_(map_file_segment)(addr, len, prot, flags, st.st_dev, st.st_ino, off, filename);
447
448 if (name)
449 VG_(arena_free)(VG_AR_CORE, name);
450}
451
452void VG_(map_segment)(Addr addr, UInt len, UInt prot, UInt flags)
453{
454 flags &= ~SF_FILE;
455
456 VG_(map_file_segment)(addr, len, prot, flags, 0, 0, 0, 0);
457}
458
459/* set new protection flags on an address range */
460void VG_(mprotect_range)(Addr a, UInt len, UInt prot)
461{
462 Segment *s, *next;
463 static const Bool debug = False || mem_debug;
464
465 if (debug)
466 VG_(printf)("mprotect_range(%p, %d, %x)\n", a, len, prot);
467
468 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000469 vg_assert((a & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge92360792003-12-24 10:11:11 +0000470 len = PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000471
fitzhardinge1a303042003-12-22 08:48:50 +0000472 VG_(split_segment)(a);
473 VG_(split_segment)(a+len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000474
475 for(s = VG_(SkipList_Find)(&sk_segments, &a);
476 s != NULL && s->addr < a+len;
477 s = next)
478 {
479 next = VG_(SkipNode_Next)(&sk_segments, s);
480 if (s->addr < a)
481 continue;
482
483 s->prot = prot;
484 }
485
486 merge_segments(a, len);
487}
488
489Addr VG_(find_map_space)(Addr addr, UInt len, Bool for_client)
490{
fitzhardingee3632c62003-12-22 10:58:06 +0000491 static const Bool debug = False || mem_debug;
fitzhardinge98abfc72003-12-16 02:05:15 +0000492 Segment *s;
493 Addr ret;
nethercotea8bc3802004-10-19 17:54:02 +0000494 Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
495 Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
fitzhardinge98abfc72003-12-16 02:05:15 +0000496
497 if (addr == 0)
nethercotea8bc3802004-10-19 17:54:02 +0000498 addr = base;
fitzhardinge98abfc72003-12-16 02:05:15 +0000499 else {
500 /* leave space for redzone and still try to get the exact
501 address asked for */
nethercote73b526f2004-10-31 18:48:21 +0000502 addr -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000503 }
504 ret = addr;
505
506 /* Everything must be page-aligned */
nethercote73b526f2004-10-31 18:48:21 +0000507 vg_assert((addr & (VKI_PAGE_SIZE-1)) == 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000508 len = PGROUNDUP(len);
509
nethercote73b526f2004-10-31 18:48:21 +0000510 len += VKI_PAGE_SIZE * 2; /* leave redzone gaps before and after mapping */
fitzhardinge98abfc72003-12-16 02:05:15 +0000511
512 if (debug)
513 VG_(printf)("find_map_space: ret starts as %p-%p client=%d\n",
514 ret, ret+len, for_client);
515
nethercote3f0eaad2004-08-23 09:28:37 +0000516 s = VG_(SkipList_Find)(&sk_segments, &ret);
517 if (s == NULL)
518 s = VG_(SkipNode_First)(&sk_segments);
519
520 for( ;
fitzhardinge98abfc72003-12-16 02:05:15 +0000521 s != NULL && s->addr < (ret+len);
522 s = VG_(SkipNode_Next)(&sk_segments, s))
523 {
524 if (debug)
525 VG_(printf)("s->addr=%p len=%d (%p) ret=%p\n",
526 s->addr, s->len, s->addr+s->len, ret);
527
528 if (s->addr < (ret + len) && (s->addr + s->len) > ret)
529 ret = s->addr+s->len;
530 }
531
532 if (debug) {
533 if (s)
534 VG_(printf)(" s->addr=%p ->len=%d\n", s->addr, s->len);
535 else
536 VG_(printf)(" s == NULL\n");
537 }
538
nethercote820bd8c2004-09-07 23:04:49 +0000539 if (((limit - len)+1) < ret)
fitzhardinge98abfc72003-12-16 02:05:15 +0000540 ret = 0; /* no space */
541 else
nethercote73b526f2004-10-31 18:48:21 +0000542 ret += VKI_PAGE_SIZE; /* skip leading redzone */
fitzhardinge98abfc72003-12-16 02:05:15 +0000543
544 if (debug)
545 VG_(printf)("find_map_space(%p, %d, %d) -> %p\n",
546 addr, len, for_client, ret);
547
548 return ret;
549}
550
thughes646c6aa2004-07-16 15:36:45 +0000551/* Pad the entire process address space, from VG_(client_base)
nethercote820bd8c2004-09-07 23:04:49 +0000552 to VG_(valgrind_last) by creating an anonymous and inaccessible
thughes646c6aa2004-07-16 15:36:45 +0000553 mapping over any part of the address space which is not covered
554 by an entry in the segment list.
555
556 This is designed for use around system calls which allocate
557 memory in the process address space without providing a way to
nethercoteccc9ecd2004-07-16 17:32:15 +0000558 control its location such as io_setup. By choosing a suitable
thughes646c6aa2004-07-16 15:36:45 +0000559 address with VG_(find_map_space) and then adding a segment for
560 it and padding the address space valgrind can ensure that the
561 kernel has no choice but to put the memory where we want it. */
thughes9aaebc32004-07-15 23:13:37 +0000562void VG_(pad_address_space)(void)
563{
564 Addr addr = VG_(client_base);
565 Segment *s = VG_(SkipNode_First)(&sk_segments);
566 UInt args[6];
567 Addr ret;
568
569 args[2] = 0;
570 args[3] = VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS;
571 args[4] = -1;
572 args[5] = 0;
573
nethercote820bd8c2004-09-07 23:04:49 +0000574 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000575 if (addr < s->addr) {
576 args[0] = (UInt)addr;
577 args[1] = s->addr - addr;
578
579 ret = VG_(do_syscall)(__NR_mmap, (UInt)args);
580 }
581
582 addr = s->addr + s->len;
583 s = VG_(SkipNode_Next)(&sk_segments, s);
584 }
585
nethercote820bd8c2004-09-07 23:04:49 +0000586 if (addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000587 args[0] = (UInt)addr;
nethercote820bd8c2004-09-07 23:04:49 +0000588 args[1] = VG_(valgrind_last) - addr + 1;
thughes9aaebc32004-07-15 23:13:37 +0000589
590 ret = VG_(do_syscall)(__NR_mmap, (UInt)args);
591 }
592
593 return;
594}
595
thughesc70b8c62004-07-16 23:07:58 +0000596/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000597 by removing any mappings that it created. */
thughes9aaebc32004-07-15 23:13:37 +0000598void VG_(unpad_address_space)(void)
599{
600 Addr addr = VG_(client_base);
601 Segment *s = VG_(SkipNode_First)(&sk_segments);
602 Int ret;
603
nethercote820bd8c2004-09-07 23:04:49 +0000604 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000605 if (addr < s->addr) {
606 ret = VG_(do_syscall)(__NR_munmap, (UInt)addr, s->addr - addr);
607 }
608
609 addr = s->addr + s->len;
610 s = VG_(SkipNode_Next)(&sk_segments, s);
611 }
612
nethercote820bd8c2004-09-07 23:04:49 +0000613 if (addr <= VG_(valgrind_last)) {
614 ret = VG_(do_syscall)(__NR_munmap, addr, (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +0000615 }
616
617 return;
618}
619
fitzhardinge98abfc72003-12-16 02:05:15 +0000620Segment *VG_(find_segment)(Addr a)
621{
622 return VG_(SkipList_Find)(&sk_segments, &a);
623}
624
fitzhardinged65dcad2004-03-13 02:06:58 +0000625Segment *VG_(first_segment)(void)
626{
627 return VG_(SkipNode_First)(&sk_segments);
628}
629
fitzhardinge98abfc72003-12-16 02:05:15 +0000630Segment *VG_(next_segment)(Segment *s)
631{
632 return VG_(SkipNode_Next)(&sk_segments, s);
633}
sewardjde4a1d02002-03-22 01:27:54 +0000634
sewardjde4a1d02002-03-22 01:27:54 +0000635/*------------------------------------------------------------*/
636/*--- Tracking permissions around %esp changes. ---*/
637/*------------------------------------------------------------*/
638
639/*
640 The stack
641 ~~~~~~~~~
642 The stack's segment seems to be dynamically extended downwards
643 by the kernel as the stack pointer moves down. Initially, a
644 1-page (4k) stack is allocated. When %esp moves below that for
645 the first time, presumably a page fault occurs. The kernel
646 detects that the faulting address is in the range from %esp upwards
647 to the current valid stack. It then extends the stack segment
648 downwards for enough to cover the faulting address, and resumes
649 the process (invisibly). The process is unaware of any of this.
650
651 That means that Valgrind can't spot when the stack segment is
652 being extended. Fortunately, we want to precisely and continuously
653 update stack permissions around %esp, so we need to spot all
654 writes to %esp anyway.
655
656 The deal is: when %esp is assigned a lower value, the stack is
657 being extended. Create a secondary maps to fill in any holes
658 between the old stack ptr and this one, if necessary. Then
659 mark all bytes in the area just "uncovered" by this %esp change
660 as write-only.
661
662 When %esp goes back up, mark the area receded over as unreadable
663 and unwritable.
664
665 Just to record the %esp boundary conditions somewhere convenient:
666 %esp always points to the lowest live byte in the stack. All
667 addresses below %esp are not live; those at and above it are.
668*/
669
sewardjde4a1d02002-03-22 01:27:54 +0000670/* Kludgey ... how much does %esp have to change before we reckon that
671 the application is switching stacks ? */
njn9b007f62003-04-07 14:40:25 +0000672#define VG_PLAUSIBLE_STACK_SIZE 8000000
673#define VG_HUGE_DELTA (VG_PLAUSIBLE_STACK_SIZE / 4)
sewardjde4a1d02002-03-22 01:27:54 +0000674
njn9b007f62003-04-07 14:40:25 +0000675/* This function gets called if new_mem_stack and/or die_mem_stack are
nethercote996901a2004-08-03 13:29:09 +0000676 tracked by the tool, and one of the specialised cases (eg. new_mem_stack_4)
njn9b007f62003-04-07 14:40:25 +0000677 isn't used in preference */
nethercoteeec46302004-08-23 15:06:23 +0000678REGPARM(1)
nethercote4ad74312004-10-26 09:59:49 +0000679void VG_(unknown_SP_update)(Addr new_SP)
sewardjde4a1d02002-03-22 01:27:54 +0000680{
nethercote15218bd2004-09-11 15:11:47 +0000681 Addr old_SP = VG_(get_archreg)(R_STACK_PTR);
682 Int delta = (Int)new_SP - (Int)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +0000683
njn9b007f62003-04-07 14:40:25 +0000684 if (delta < -(VG_HUGE_DELTA) || VG_HUGE_DELTA < delta) {
685 /* %esp has changed by more than HUGE_DELTA. We take this to mean
686 that the application is switching to a new stack, for whatever
687 reason.
688
689 JRS 20021001: following discussions with John Regehr, if a stack
690 switch happens, it seems best not to mess at all with memory
691 permissions. Seems to work well with Netscape 4.X. Really the
692 only remaining difficulty is knowing exactly when a stack switch is
693 happening. */
694 if (VG_(clo_verbosity) > 1)
695 VG_(message)(Vg_UserMsg, "Warning: client switching stacks? "
nethercote15218bd2004-09-11 15:11:47 +0000696 "%%esp: %p --> %p", old_SP, new_SP);
njn9b007f62003-04-07 14:40:25 +0000697 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +0000698 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +0000699
njn9b007f62003-04-07 14:40:25 +0000700 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +0000701 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +0000702 }
703}
704
jsgf855d93d2003-10-13 22:26:55 +0000705static jmp_buf segv_jmpbuf;
706
707static void segv_handler(Int seg)
708{
709 __builtin_longjmp(segv_jmpbuf, 1);
710 VG_(core_panic)("longjmp failed");
711}
712
713/*
714 Test if a piece of memory is addressable by setting up a temporary
715 SIGSEGV handler, then try to touch the memory. No signal = good,
716 signal = bad.
717 */
718Bool VG_(is_addressable)(Addr p, Int size)
719{
720 volatile Char * volatile cp = (volatile Char *)p;
721 volatile Bool ret;
nethercote73b526f2004-10-31 18:48:21 +0000722 struct vki_sigaction sa, origsa;
723 vki_sigset_t mask;
jsgf855d93d2003-10-13 22:26:55 +0000724
725 vg_assert(size > 0);
726
727 sa.ksa_handler = segv_handler;
nethercote73b526f2004-10-31 18:48:21 +0000728 sa.sa_flags = 0;
729 VG_(sigfillset)(&sa.sa_mask);
730 VG_(sigaction)(VKI_SIGSEGV, &sa, &origsa);
731 VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &mask);
jsgf855d93d2003-10-13 22:26:55 +0000732
733 if (__builtin_setjmp(&segv_jmpbuf) == 0) {
734 while(size--)
735 *cp++;
736 ret = True;
737 } else
738 ret = False;
739
nethercote73b526f2004-10-31 18:48:21 +0000740 VG_(sigaction)(VKI_SIGSEGV, &origsa, NULL);
741 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000742
743 return ret;
744}
745
sewardjde4a1d02002-03-22 01:27:54 +0000746/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +0000747/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000748/*--------------------------------------------------------------------*/
749
nethercote57e36b32004-07-10 14:56:28 +0000750// Returns 0 on failure.
nethercoteb4250ae2004-07-10 16:50:09 +0000751Addr VG_(client_alloc)(Addr addr, UInt len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000752{
753 len = PGROUNDUP(len);
754
nethercote8e9eab02004-07-11 18:01:06 +0000755 sk_assert(!(sf_flags & SF_FIXED));
756 sk_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000757
nethercote8e9eab02004-07-11 18:01:06 +0000758 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
759 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
760 sf_flags | SF_CORE, -1, 0);
761 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +0000762 return addr;
nethercote8e9eab02004-07-11 18:01:06 +0000763 else
764 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +0000765}
766
767void VG_(client_free)(Addr addr)
768{
769 Segment *s = VG_(find_segment)(addr);
770
771 if (s == NULL || s->addr != addr || !(s->flags & SF_CORE)) {
772 VG_(message)(Vg_DebugMsg, "VG_(client_free)(%p) - no CORE memory found there", addr);
773 return;
774 }
775
776 VG_(munmap)((void *)s->addr, s->len);
777}
778
nethercote88a90162004-07-10 16:59:25 +0000779/*--------------------------------------------------------------------*/
780/*--- Querying memory layout ---*/
781/*--------------------------------------------------------------------*/
782
fitzhardinge98abfc72003-12-16 02:05:15 +0000783Bool VG_(is_client_addr)(Addr a)
784{
785 return a >= VG_(client_base) && a < VG_(client_end);
786}
787
788Bool VG_(is_shadow_addr)(Addr a)
789{
790 return a >= VG_(shadow_base) && a < VG_(shadow_end);
791}
792
793Bool VG_(is_valgrind_addr)(Addr a)
794{
nethercote820bd8c2004-09-07 23:04:49 +0000795 return a >= VG_(valgrind_base) && a <= VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000796}
797
798Addr VG_(get_client_base)(void)
799{
800 return VG_(client_base);
801}
802
803Addr VG_(get_client_end)(void)
804{
805 return VG_(client_end);
806}
807
808Addr VG_(get_client_size)(void)
809{
810 return VG_(client_end)-VG_(client_base);
811}
812
813Addr VG_(get_shadow_base)(void)
814{
815 return VG_(shadow_base);
816}
817
818Addr VG_(get_shadow_end)(void)
819{
820 return VG_(shadow_end);
821}
822
823Addr VG_(get_shadow_size)(void)
824{
825 return VG_(shadow_end)-VG_(shadow_base);
826}
827
nethercote88a90162004-07-10 16:59:25 +0000828/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +0000829/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +0000830/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000831
832void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
833{
834 if (0)
835 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
836
837 vg_assert(VG_(needs).shadow_memory);
838 vg_assert(VG_(defined_init_shadow_page)());
839
840 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
841 p = PGROUNDDN(p);
842
843 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
844
845 if (call_init)
846 while(sz) {
nethercote996901a2004-08-03 13:29:09 +0000847 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +0000848 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
849
nethercote73b526f2004-10-31 18:48:21 +0000850 p += VKI_PAGE_SIZE;
851 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000852 }
853}
854
855void *VG_(shadow_alloc)(UInt size)
856{
857 static Addr shadow_alloc = 0;
858 void *ret;
859
860 vg_assert(VG_(needs).shadow_memory);
861 vg_assert(!VG_(defined_init_shadow_page)());
862
863 size = PGROUNDUP(size);
864
865 if (shadow_alloc == 0)
866 shadow_alloc = VG_(shadow_base);
867
868 if (shadow_alloc >= VG_(shadow_end))
869 return 0;
870
871 ret = (void *)shadow_alloc;
872 VG_(mprotect)(ret, size, VKI_PROT_READ|VKI_PROT_WRITE);
873
874 shadow_alloc += size;
875
876 return ret;
877}
878
879/*--------------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000880/*--- end vg_memory.c ---*/
881/*--------------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000882