blob: fa62f1a6241f5acb148e1b857397afa500168810 [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
nethercote8991d5a2004-11-03 17:07:46 +000069Bool VG_(seg_contains)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +000070{
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
nethercote8991d5a2004-11-03 17:07:46 +000079Bool VG_(seg_overlaps)(const Segment *s, Addr p, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +000080{
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) {
nethercote8991d5a2004-11-03 17:07:46 +0000108 VG_(symtab_decref)(s->symtab, s->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000109 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. */
nethercote8b5f40c2004-11-02 13:29:50 +0000157void VG_(unmap_range)(Addr addr, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000158{
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 */
nethercote8b5f40c2004-11-02 13:29:50 +0000284static void merge_segments(Addr a, SizeT len)
fitzhardinge98abfc72003-12-16 02:05:15 +0000285{
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
nethercote8b5f40c2004-11-02 13:29:50 +0000317void VG_(map_file_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000318 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)
nethercote8b5f40c2004-11-02 13:29:50 +0000325 VG_(printf)("map_file_segment(%p, %llu, %x, %x, %4x, %d, %ld, %s)\n",
326 addr, (ULong)len, prot, flags, dev, ino, off, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +0000327
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)) {
nethercote8991d5a2004-11-03 17:07:46 +0000347 VG_(symtab_decref)(s->symtab, s->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000348 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
nethercote8b5f40c2004-11-02 13:29:50 +0000424void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
fitzhardinge98abfc72003-12-16 02:05:15 +0000425 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
nethercote8b5f40c2004-11-02 13:29:50 +0000452void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000453{
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 */
nethercote8b5f40c2004-11-02 13:29:50 +0000460void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
fitzhardinge98abfc72003-12-16 02:05:15 +0000461{
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
nethercote8b5f40c2004-11-02 13:29:50 +0000489Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
fitzhardinge98abfc72003-12-16 02:05:15 +0000490{
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);
thughes9aaebc32004-07-15 23:13:37 +0000566 Addr ret;
567
nethercote820bd8c2004-09-07 23:04:49 +0000568 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000569 if (addr < s->addr) {
nethercotef18ca392004-11-04 18:45:22 +0000570 PLATFORM_DO_MMAP(ret, addr, s->addr - addr, 0,
571 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
572 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000573 }
574
575 addr = s->addr + s->len;
576 s = VG_(SkipNode_Next)(&sk_segments, s);
577 }
578
nethercote820bd8c2004-09-07 23:04:49 +0000579 if (addr <= VG_(valgrind_last)) {
nethercotef18ca392004-11-04 18:45:22 +0000580 PLATFORM_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
581 VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
582 -1, 0);
thughes9aaebc32004-07-15 23:13:37 +0000583 }
584
585 return;
586}
587
thughesc70b8c62004-07-16 23:07:58 +0000588/* Remove the address space padding added by VG_(pad_address_space)
thughes646c6aa2004-07-16 15:36:45 +0000589 by removing any mappings that it created. */
thughes9aaebc32004-07-15 23:13:37 +0000590void VG_(unpad_address_space)(void)
591{
592 Addr addr = VG_(client_base);
593 Segment *s = VG_(SkipNode_First)(&sk_segments);
594 Int ret;
595
nethercote820bd8c2004-09-07 23:04:49 +0000596 while (s && addr <= VG_(valgrind_last)) {
thughes9aaebc32004-07-15 23:13:37 +0000597 if (addr < s->addr) {
nethercote50397c22004-11-04 18:03:06 +0000598 ret = VG_(do_syscall)(__NR_munmap, addr, s->addr - addr);
thughes9aaebc32004-07-15 23:13:37 +0000599 }
600
601 addr = s->addr + s->len;
602 s = VG_(SkipNode_Next)(&sk_segments, s);
603 }
604
nethercote820bd8c2004-09-07 23:04:49 +0000605 if (addr <= VG_(valgrind_last)) {
606 ret = VG_(do_syscall)(__NR_munmap, addr, (VG_(valgrind_last) - addr) + 1);
thughes9aaebc32004-07-15 23:13:37 +0000607 }
608
609 return;
610}
611
fitzhardinge98abfc72003-12-16 02:05:15 +0000612Segment *VG_(find_segment)(Addr a)
613{
614 return VG_(SkipList_Find)(&sk_segments, &a);
615}
616
fitzhardinged65dcad2004-03-13 02:06:58 +0000617Segment *VG_(first_segment)(void)
618{
619 return VG_(SkipNode_First)(&sk_segments);
620}
621
fitzhardinge98abfc72003-12-16 02:05:15 +0000622Segment *VG_(next_segment)(Segment *s)
623{
624 return VG_(SkipNode_Next)(&sk_segments, s);
625}
sewardjde4a1d02002-03-22 01:27:54 +0000626
sewardjde4a1d02002-03-22 01:27:54 +0000627/*------------------------------------------------------------*/
628/*--- Tracking permissions around %esp changes. ---*/
629/*------------------------------------------------------------*/
630
631/*
632 The stack
633 ~~~~~~~~~
634 The stack's segment seems to be dynamically extended downwards
635 by the kernel as the stack pointer moves down. Initially, a
636 1-page (4k) stack is allocated. When %esp moves below that for
637 the first time, presumably a page fault occurs. The kernel
638 detects that the faulting address is in the range from %esp upwards
639 to the current valid stack. It then extends the stack segment
640 downwards for enough to cover the faulting address, and resumes
641 the process (invisibly). The process is unaware of any of this.
642
643 That means that Valgrind can't spot when the stack segment is
644 being extended. Fortunately, we want to precisely and continuously
645 update stack permissions around %esp, so we need to spot all
646 writes to %esp anyway.
647
648 The deal is: when %esp is assigned a lower value, the stack is
649 being extended. Create a secondary maps to fill in any holes
650 between the old stack ptr and this one, if necessary. Then
651 mark all bytes in the area just "uncovered" by this %esp change
652 as write-only.
653
654 When %esp goes back up, mark the area receded over as unreadable
655 and unwritable.
656
657 Just to record the %esp boundary conditions somewhere convenient:
658 %esp always points to the lowest live byte in the stack. All
659 addresses below %esp are not live; those at and above it are.
660*/
661
sewardjde4a1d02002-03-22 01:27:54 +0000662/* Kludgey ... how much does %esp have to change before we reckon that
663 the application is switching stacks ? */
njn9b007f62003-04-07 14:40:25 +0000664#define VG_PLAUSIBLE_STACK_SIZE 8000000
665#define VG_HUGE_DELTA (VG_PLAUSIBLE_STACK_SIZE / 4)
sewardjde4a1d02002-03-22 01:27:54 +0000666
njn9b007f62003-04-07 14:40:25 +0000667/* This function gets called if new_mem_stack and/or die_mem_stack are
nethercote996901a2004-08-03 13:29:09 +0000668 tracked by the tool, and one of the specialised cases (eg. new_mem_stack_4)
njn9b007f62003-04-07 14:40:25 +0000669 isn't used in preference */
nethercoteeec46302004-08-23 15:06:23 +0000670REGPARM(1)
nethercote4ad74312004-10-26 09:59:49 +0000671void VG_(unknown_SP_update)(Addr new_SP)
sewardjde4a1d02002-03-22 01:27:54 +0000672{
nethercote15218bd2004-09-11 15:11:47 +0000673 Addr old_SP = VG_(get_archreg)(R_STACK_PTR);
nethercotefc646ee2004-11-04 19:29:06 +0000674 Word delta = (Word)new_SP - (Word)old_SP;
sewardjde4a1d02002-03-22 01:27:54 +0000675
njn9b007f62003-04-07 14:40:25 +0000676 if (delta < -(VG_HUGE_DELTA) || VG_HUGE_DELTA < delta) {
677 /* %esp has changed by more than HUGE_DELTA. We take this to mean
678 that the application is switching to a new stack, for whatever
679 reason.
680
681 JRS 20021001: following discussions with John Regehr, if a stack
682 switch happens, it seems best not to mess at all with memory
683 permissions. Seems to work well with Netscape 4.X. Really the
684 only remaining difficulty is knowing exactly when a stack switch is
685 happening. */
686 if (VG_(clo_verbosity) > 1)
687 VG_(message)(Vg_UserMsg, "Warning: client switching stacks? "
nethercote15218bd2004-09-11 15:11:47 +0000688 "%%esp: %p --> %p", old_SP, new_SP);
njn9b007f62003-04-07 14:40:25 +0000689 } else if (delta < 0) {
nethercote15218bd2004-09-11 15:11:47 +0000690 VG_TRACK( new_mem_stack, new_SP, -delta );
sewardjde4a1d02002-03-22 01:27:54 +0000691
njn9b007f62003-04-07 14:40:25 +0000692 } else if (delta > 0) {
nethercote15218bd2004-09-11 15:11:47 +0000693 VG_TRACK( die_mem_stack, old_SP, delta );
sewardjde4a1d02002-03-22 01:27:54 +0000694 }
695}
696
jsgf855d93d2003-10-13 22:26:55 +0000697static jmp_buf segv_jmpbuf;
698
699static void segv_handler(Int seg)
700{
701 __builtin_longjmp(segv_jmpbuf, 1);
702 VG_(core_panic)("longjmp failed");
703}
704
705/*
706 Test if a piece of memory is addressable by setting up a temporary
707 SIGSEGV handler, then try to touch the memory. No signal = good,
708 signal = bad.
709 */
nethercote928a5f72004-11-03 18:10:37 +0000710Bool VG_(is_addressable)(Addr p, SizeT size)
jsgf855d93d2003-10-13 22:26:55 +0000711{
712 volatile Char * volatile cp = (volatile Char *)p;
713 volatile Bool ret;
nethercote73b526f2004-10-31 18:48:21 +0000714 struct vki_sigaction sa, origsa;
715 vki_sigset_t mask;
jsgf855d93d2003-10-13 22:26:55 +0000716
jsgf855d93d2003-10-13 22:26:55 +0000717 sa.ksa_handler = segv_handler;
nethercote73b526f2004-10-31 18:48:21 +0000718 sa.sa_flags = 0;
719 VG_(sigfillset)(&sa.sa_mask);
720 VG_(sigaction)(VKI_SIGSEGV, &sa, &origsa);
721 VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &mask);
jsgf855d93d2003-10-13 22:26:55 +0000722
723 if (__builtin_setjmp(&segv_jmpbuf) == 0) {
724 while(size--)
725 *cp++;
726 ret = True;
727 } else
728 ret = False;
729
nethercote73b526f2004-10-31 18:48:21 +0000730 VG_(sigaction)(VKI_SIGSEGV, &origsa, NULL);
731 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000732
733 return ret;
734}
735
sewardjde4a1d02002-03-22 01:27:54 +0000736/*--------------------------------------------------------------------*/
nethercote88a90162004-07-10 16:59:25 +0000737/*--- Manage allocation of memory on behalf of the client ---*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000738/*--------------------------------------------------------------------*/
739
nethercote57e36b32004-07-10 14:56:28 +0000740// Returns 0 on failure.
nethercote928a5f72004-11-03 18:10:37 +0000741Addr VG_(client_alloc)(Addr addr, SizeT len, UInt prot, UInt sf_flags)
fitzhardinge98abfc72003-12-16 02:05:15 +0000742{
743 len = PGROUNDUP(len);
744
nethercote8e9eab02004-07-11 18:01:06 +0000745 sk_assert(!(sf_flags & SF_FIXED));
746 sk_assert(0 == addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000747
nethercote8e9eab02004-07-11 18:01:06 +0000748 addr = (Addr)VG_(mmap)((void *)addr, len, prot,
749 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_CLIENT,
750 sf_flags | SF_CORE, -1, 0);
751 if ((Addr)-1 != addr)
fitzhardinge98abfc72003-12-16 02:05:15 +0000752 return addr;
nethercote8e9eab02004-07-11 18:01:06 +0000753 else
754 return 0;
fitzhardinge98abfc72003-12-16 02:05:15 +0000755}
756
757void VG_(client_free)(Addr addr)
758{
759 Segment *s = VG_(find_segment)(addr);
760
761 if (s == NULL || s->addr != addr || !(s->flags & SF_CORE)) {
762 VG_(message)(Vg_DebugMsg, "VG_(client_free)(%p) - no CORE memory found there", addr);
763 return;
764 }
765
766 VG_(munmap)((void *)s->addr, s->len);
767}
768
nethercote88a90162004-07-10 16:59:25 +0000769/*--------------------------------------------------------------------*/
770/*--- Querying memory layout ---*/
771/*--------------------------------------------------------------------*/
772
fitzhardinge98abfc72003-12-16 02:05:15 +0000773Bool VG_(is_client_addr)(Addr a)
774{
775 return a >= VG_(client_base) && a < VG_(client_end);
776}
777
778Bool VG_(is_shadow_addr)(Addr a)
779{
780 return a >= VG_(shadow_base) && a < VG_(shadow_end);
781}
782
783Bool VG_(is_valgrind_addr)(Addr a)
784{
nethercote820bd8c2004-09-07 23:04:49 +0000785 return a >= VG_(valgrind_base) && a <= VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000786}
787
788Addr VG_(get_client_base)(void)
789{
790 return VG_(client_base);
791}
792
793Addr VG_(get_client_end)(void)
794{
795 return VG_(client_end);
796}
797
798Addr VG_(get_client_size)(void)
799{
800 return VG_(client_end)-VG_(client_base);
801}
802
803Addr VG_(get_shadow_base)(void)
804{
805 return VG_(shadow_base);
806}
807
808Addr VG_(get_shadow_end)(void)
809{
810 return VG_(shadow_end);
811}
812
813Addr VG_(get_shadow_size)(void)
814{
815 return VG_(shadow_end)-VG_(shadow_base);
816}
817
nethercote88a90162004-07-10 16:59:25 +0000818/*--------------------------------------------------------------------*/
nethercote2f54e0d2004-07-10 17:27:20 +0000819/*--- Handling shadow memory ---*/
nethercote88a90162004-07-10 16:59:25 +0000820/*--------------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +0000821
822void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init)
823{
824 if (0)
825 VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
826
827 vg_assert(VG_(needs).shadow_memory);
828 vg_assert(VG_(defined_init_shadow_page)());
829
830 sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
831 p = PGROUNDDN(p);
832
833 VG_(mprotect)((void *)p, sz, VKI_PROT_READ|VKI_PROT_WRITE);
834
835 if (call_init)
836 while(sz) {
nethercote996901a2004-08-03 13:29:09 +0000837 /* ask the tool to initialize each page */
fitzhardinge98abfc72003-12-16 02:05:15 +0000838 VG_TRACK( init_shadow_page, PGROUNDDN(p) );
839
nethercote73b526f2004-10-31 18:48:21 +0000840 p += VKI_PAGE_SIZE;
841 sz -= VKI_PAGE_SIZE;
fitzhardinge98abfc72003-12-16 02:05:15 +0000842 }
843}
844
845void *VG_(shadow_alloc)(UInt size)
846{
847 static Addr shadow_alloc = 0;
848 void *ret;
849
850 vg_assert(VG_(needs).shadow_memory);
851 vg_assert(!VG_(defined_init_shadow_page)());
852
853 size = PGROUNDUP(size);
854
855 if (shadow_alloc == 0)
856 shadow_alloc = VG_(shadow_base);
857
858 if (shadow_alloc >= VG_(shadow_end))
859 return 0;
860
861 ret = (void *)shadow_alloc;
862 VG_(mprotect)(ret, size, VKI_PROT_READ|VKI_PROT_WRITE);
863
864 shadow_alloc += size;
865
866 return ret;
867}
868
869/*--------------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000870/*--- end vg_memory.c ---*/
871/*--------------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000872