Further cleanups to low-level memory management. It's still a
conceptual mess and needs a redesign, but this is a start. Most stuff
now works again.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3247 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_memory.c b/coregrind/vg_memory.c
index 34b165e..77fb28c 100644
--- a/coregrind/vg_memory.c
+++ b/coregrind/vg_memory.c
@@ -37,24 +37,118 @@
static const Bool mem_debug = False;
+#define IS_PAGE_ALIGNED(_aa) (((_aa) & (VKI_PAGE_SIZE-1)) == 0)
+
+
/*--------------------------------------------------------------*/
-/*--- ---*/
+/*--- A simple, self-contained ordered array of segments. ---*/
/*--------------------------------------------------------------*/
-#define VG_N_SEGMENTS 400
+/* Max number of segments we can track. */
+#define VG_N_SEGMENTS 1000
+
+/* Max number of segment file names we can track. */
+#define VG_N_SEGNAMES 200
+
+/* Max length of a segment file name. */
+#define VG_MAX_SEGNAMELEN 1000
+
+
+/* ------ STATE for the address-space manager ------ */
/* Array [0 .. segments_used-1] of all mappings. */
/* Sorted by .addr field. */
/* I: len may not be zero. */
/* I: overlapping segments are not allowed. */
+/* Each segment can optionally hold an index into the filename table. */
static Segment segments[VG_N_SEGMENTS];
static Int segments_used = 0;
+typedef
+ struct {
+ Bool inUse;
+ Bool mark;
+ HChar fname[VG_MAX_SEGNAMELEN];
+ }
+ SegName;
+
+/* Filename table. _used is the high water mark; an entry is only
+ valid if its index >= 0, < _used, and its .inUse field == True.
+ The .mark field is used to garbage-collect dead entries.
+*/
+static SegName segnames[VG_N_SEGNAMES];
+static Int segnames_used = 0;
+
+
+/* ------ end of STATE for the address-space manager ------ */
+
+
+/* Searches the filename table to find an index for the given name.
+ If none is found, an index is allocated and the name stored. If no
+ space is available we just give up. If the string is too long to
+ store, return -1.
+*/
+static Int allocate_segname ( const HChar* name )
+{
+ Int i, j, len;
+
+ vg_assert(name);
+
+ if (0) VG_(printf)("alloc_segname %s\n", name);
+
+ len = VG_(strlen)(name);
+ if (len >= VG_MAX_SEGNAMELEN-1) {
+ return -1;
+ }
+
+ /* first see if we already have the name. */
+ for (i = 0; i < segnames_used; i++) {
+ if (!segnames[i].inUse)
+ continue;
+ if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) {
+ return i;
+ }
+ }
+
+ /* no we don't. So look for a free slot. */
+ for (i = 0; i < segnames_used; i++)
+ if (!segnames[i].inUse)
+ break;
+
+ if (i == segnames_used) {
+ /* no free slots .. advance the high-water mark. */
+ if (segnames_used+1 < VG_N_SEGNAMES) {
+ i = segnames_used;
+ segnames_used++;
+ } else {
+ VG_(printf)(
+ "coregrind/vg_memory.c:\n"
+ " VG_N_SEGNAMES is too small: "
+ "increase it and rebuild Valgrind.\n"
+ );
+ VG_(printf)(
+ "coregrind/vg_memory.c:\n"
+ " giving up now.\n\n"
+ );
+ VG_(exit)(0);
+ }
+ }
+
+ /* copy it in */
+ segnames[i].inUse = True;
+ for (j = 0; j < len; j++)
+ segnames[i].fname[j] = name[j];
+ vg_assert(len < VG_MAX_SEGNAMELEN);
+ segnames[i].fname[len] = 0;
+ return i;
+}
+
/* Returns -1 if 'a' denotes an address prior to seg, 1 if it denotes
an address after it, and 0 if it denotes an address covered by
- seg. */
+ seg.
+*/
static Int compare_addr_with_seg ( Addr a, Segment* seg )
{
if (a < seg->addr)
@@ -64,8 +158,10 @@
return 0;
}
+
/* Find the (index of the) segment that contains 'a', or -1 if
- none. */
+ none.
+*/
static Int find_segment ( Addr a )
{
Int i;
@@ -88,7 +184,7 @@
r = compare_addr_with_seg(a, &segments[i]);
vg_assert(r != 0); /* 'a' should not be in any segment. */
if (r == 1)
- continue;
+ continue;
vg_assert(r == -1);
break;
}
@@ -133,14 +229,28 @@
Int j;
vg_assert(i >= 0 && i <= segments_used);
vg_assert(segments_used >= 0);
+ if (segments_used+1 == VG_N_SEGMENTS) {
+ VG_(printf)(
+ "coregrind/vg_memory.c:\n"
+ " VG_N_SEGMENTS is too small: "
+ "increase it and rebuild Valgrind.\n"
+ );
+ VG_(printf)(
+ "coregrind/vg_memory.c:\n"
+ " giving up now.\n\n"
+ );
+ VG_(exit)(0);
+ }
vg_assert(segments_used+1 < VG_N_SEGMENTS);
for (j = segments_used; j > i; j--)
segments[j] = segments[j-1];
segments_used++;
}
+
/* Shift segments [i+1 .. segments_used-1] down by one, and decrement
- segments_used. */
+ segments_used.
+*/
static void delete_segment_at ( Int i )
{
Int j;
@@ -156,17 +266,19 @@
static void zeroise_segment ( Int i )
{
vg_assert(i >= 0 && i < segments_used);
- segments[i].prot = 0;
- segments[i].flags = 0;
- segments[i].addr = 0;
- segments[i].len = 0;
- segments[i].offset = 0;
+ segments[i].prot = 0;
+ segments[i].flags = 0;
+ segments[i].addr = 0;
+ segments[i].len = 0;
+ segments[i].offset = 0;
segments[i].filename = NULL;
- segments[i].dev = 0;
- segments[i].ino = 0;
- segments[i].symtab = NULL;
+ segments[i].fnIdx = -1;
+ segments[i].dev = 0;
+ segments[i].ino = 0;
+ segments[i].symtab = NULL;
}
+
/* Create a segment to contain 'a', and return its index. Or -1 if
this failed because some other segment already contains 'a'. If
successful, fill in the segment's .addr field with 'a' but leave
@@ -192,19 +304,34 @@
return i;
}
-//static
-void show_segments ( HChar* who )
+
+/* Print out the segment array (debugging only!). Note, this calls
+ VG_(printf), and I'm not 100% clear that that wouldn't require
+ dynamic memory allocation and hence more segments to be allocated.
+*/
+static void show_segments ( HChar* who )
{
- Int i;
- VG_(printf)("<<< SHOW_SEGMENTS: %s %d\n", who, segments_used);
- for (i = 0; i < segments_used; i++) {
+ Int i;
+ VG_(printf)("<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",
+ who, segments_used, segnames_used);
+ for (i = 0; i < segnames_used; i++) {
+ if (!segnames[i].inUse)
+ continue;
+ VG_(printf)("(%2d) %s\n", i, segnames[i].fname);
+ }
+ for (i = 0; i < segments_used; i++) {
VG_(printf)(
- "%2d: %p %llu 0x%x 0x%x 0x%x %d %lld %s\n",
+ "%3d: %08p-%08p %7llu pr=0x%x fl=0x%04x d=0x%03x i=%-7d o=%-7lld (%d)\n",
i,
- segments[i].addr, (ULong)segments[i].len, segments[i].prot, segments[i].flags, segments[i].dev, segments[i].ino, (Long)segments[i].offset, "qqq" /*segments[i].filename*/);
+ segments[i].addr, segments[i].addr + segments[i].len,
+ (ULong)segments[i].len, segments[i].prot,
+ segments[i].flags, segments[i].dev, segments[i].ino,
+ (Long)segments[i].offset,
+ segments[i].fnIdx);
+ }
+ VG_(printf)(">>>\n");
}
- VG_(printf)(">>>\n");
-}
+
/* Find the segment containing 'a' and split it into two pieces at
'a'. Does nothing if no segment contains 'a', or if the split
@@ -220,7 +347,7 @@
{
Int r;
HWord delta;
- vg_assert((a & (VKI_PAGE_SIZE-1)) == 0);
+ vg_assert(IS_PAGE_ALIGNED(a));
r = find_segment(a);
if (r == -1)
/* not found */
@@ -242,12 +369,116 @@
return r+1;
}
+
+/* Return true if two segments are adjacent and mergable (s1 is
+ assumed to have a lower ->addr than s2) */
+static inline Bool segments_are_mergeable(Segment *s1, Segment *s2)
+{
+ if (s1->addr+s1->len != s2->addr)
+ return False;
+
+ if (s1->flags != s2->flags)
+ return False;
+
+ if (s1->prot != s2->prot)
+ return False;
+
+ if (s1->symtab != s2->symtab)
+ return False;
+
+ if (s1->flags & SF_FILE){
+ if ((s1->offset + s1->len) != s2->offset)
+ return False;
+ if (s1->dev != s2->dev)
+ return False;
+ if (s1->ino != s2->ino)
+ return False;
+ if (s1->fnIdx != s2->fnIdx)
+ return False;
+ }
+
+ return True;
+}
+
+
+/* Clean up and sanity check the segment array:
+ - check segments are in ascending order
+ - check segments do not overlap
+ - check no segment has zero size
+ - merge adjacent where possible
+ - perform checks on the filename table, and reclaim dead entries
+*/
+static void preen_segments ( void )
+{
+ Int i, j, rd, wr;
+ Segment *s, *s1;
+ vg_assert(segments_used >= 0 && segments_used < VG_N_SEGMENTS);
+ vg_assert(segnames_used >= 0 && segnames_used < VG_N_SEGNAMES);
+
+ if (0) show_segments("before preen");
+
+ /* clear string table mark bits */
+ for (i = 0; i < segnames_used; i++)
+ segnames[i].mark = False;
+
+ /* check for non-zero size, and set mark bits for any used strings */
+ for (i = 0; i < segments_used; i++) {
+ vg_assert(segments[i].len > 0);
+ j = segments[i].fnIdx;
+ vg_assert(j >= -1 && j < segnames_used);
+ if (j >= 0) {
+ vg_assert(segnames[j].inUse);
+ segnames[j].mark = True;
+ }
+ }
+
+ /* check ascendingness and non-overlap */
+ for (i = 0; i < segments_used-1; i++) {
+ s = &segments[i];
+ s1 = &segments[i+1];
+ vg_assert(s->addr < s1->addr);
+ vg_assert(s->addr + s->len <= s1->addr);
+ }
+
+ /* merge */
+ if (segments_used < 1)
+ return;
+
+ wr = 1;
+ for (rd = 1; rd < segments_used; rd++) {
+ s = &segments[wr-1];
+ s1 = &segments[rd];
+ if (segments_are_mergeable(s,s1)) {
+ if (0)
+ VG_(printf)("merge %p-%p with %p-%p\n",
+ s->addr, s->addr+s->len,
+ s1->addr, s1->addr+s1->len);
+ s->len += s1->len;
+ continue;
+ }
+ if (wr < rd)
+ segments[wr] = segments[rd];
+ wr++;
+ }
+ vg_assert(wr >= 0 && wr <= segments_used);
+ segments_used = wr;
+
+ /* Free up any strings which are no longer referenced. */
+ for (i = 0; i < segnames_used; i++) {
+ if (segnames[i].mark == False) {
+ segnames[i].inUse = False;
+ segnames[i].fname[0] = 0;
+ }
+ }
+
+ if (0) show_segments("after preen");
+}
+
+
/*--------------------------------------------------------------*/
/*--- ---*/
/*--------------------------------------------------------------*/
-#define IS_PAGE_ALIGNED(_aa) (((_aa) & (VKI_PAGE_SIZE-1)) == 0)
-
static Int addrcmp(const void *ap, const void *bp)
{
@@ -366,11 +597,10 @@
partial mappings at the ends are truncated. */
void VG_(unmap_range)(Addr addr, SizeT len)
{
- Segment *s;
- Segment *next;
static const Bool debug = False || mem_debug;
- Addr end, s_end;
- Int i;
+ Segment* s;
+ Addr end, s_end;
+ Int i;
if (len == 0)
return;
@@ -379,7 +609,7 @@
if (debug)
VG_(printf)("unmap_range(%p, %d)\n", addr, len);
- if (0) show_segments("unmap_range");
+ if (0) show_segments("unmap_range(BEFORE)");
end = addr+len;
/* Everything must be page-aligned */
@@ -418,7 +648,8 @@
Word delta = end - s->addr;
if (debug)
- VG_(printf)(" case 2: s->addr=%p s->len=%d delta=%d\n", s->addr, s->len, delta);
+ VG_(printf)(" case 2: s->addr=%p s->len=%d delta=%d\n",
+ s->addr, s->len, delta);
s->addr += delta;
s->offset += delta;
@@ -449,35 +680,8 @@
addr, addr+len);
}
}
- if (0) show_segments("unmap_range(AFTER)");
-}
-
-/* Return true if two segments are adjacent and mergable (s1 is
- assumed to have a lower ->addr than s2) */
-static inline Bool neighbours(Segment *s1, Segment *s2)
-{
- if (s1->addr+s1->len != s2->addr)
- return False;
-
- if (s1->flags != s2->flags)
- return False;
-
- if (s1->prot != s2->prot)
- return False;
-
- if (s1->symtab != s2->symtab)
- return False;
-
- if (s1->flags & SF_FILE){
- if ((s1->offset + s1->len) != s2->offset)
- return False;
- if (s1->dev != s2->dev)
- return False;
- if (s1->ino != s2->ino)
- return False;
- }
-
- return True;
+ preen_segments();
+ if (0) show_segments("unmap_range(AFTER)");
}
/* If possible, merge segment with its neighbours - some segments,
@@ -497,7 +701,7 @@
s != NULL && s->addr < (a+len);) {
next = VG_(SkipNode_Next)(&sk_segments, s);
- if (next && neighbours(s, next)) {
+ if (next && segments_are_mergeable(s, next)) {
Segment *rs;
if (0)
@@ -526,10 +730,9 @@
UInt dev, UInt ino, ULong off,
const Char *filename)
{
- Segment *s;
static const Bool debug = False || mem_debug;
- Bool recycled;
- Int idx;
+ Segment* s;
+ Int idx;
if (debug)
VG_(printf)(
@@ -551,91 +754,40 @@
vg_assert(segments_used >= 0 && segments_used <= VG_N_SEGMENTS);
vg_assert(idx != -1);
vg_assert(idx >= 0 && idx < segments_used);
- vg_assert(segments[idx].addr == addr);
- segments[idx].prot = prot;
- segments[idx].flags = flags;
- segments[idx].len = len;
- segments[idx].offset = off;
- segments[idx].filename = filename;
- segments[idx].dev = dev;
- segments[idx].ino = ino;
- segments[idx].symtab = NULL;
- return;
-#if 0
- /* First look to see what already exists around here */
- s = VG_(SkipList_Find)(&sk_segments, &addr);
+ s = &segments[idx];
+ vg_assert(s->addr == addr);
+ s->prot = prot;
+ s->flags = flags;
+ s->len = len;
+ s->offset = off;
+ s->fnIdx = filename==NULL ? -1 : allocate_segname(filename);
+ s->filename = s->fnIdx==-1 ? NULL : &segnames[s->fnIdx].fname[0];
+ s->dev = dev;
+ s->ino = ino;
+ s->symtab = NULL;
- if (s != NULL && s->addr == addr && s->len == len) {
- recycled = True;
- recycleseg(s);
-
- /* If we had a symtab, but the new mapping is incompatible, then
- free up the old symtab in preparation for a new one. */
- if (s->symtab != NULL &&
- (!(s->flags & SF_FILE) ||
- !(flags & SF_FILE) ||
- s->dev != dev ||
- s->ino != ino ||
- s->offset != off)) {
- VG_(symtab_decref)(s->symtab, s->addr);
- s->symtab = NULL;
- }
- } else {
- recycled = False;
- VG_(unmap_range)(addr, len);
-
- s = VG_(SkipNode_Alloc)(&sk_segments);
-
- s->addr = addr;
- s->len = len;
- s->symtab = NULL;
- }
-
- s->flags = flags;
- s->prot = prot;
- s->dev = dev;
- s->ino = ino;
- s->offset = off;
-
- if (filename != NULL)
- s->filename = VG_(arena_strdup)(VG_AR_CORE, filename);
- else
- s->filename = NULL;
-
- if (debug) {
- Segment *ts;
- for(ts = VG_(SkipNode_First)(&sk_segments);
- ts != NULL;
- ts = VG_(SkipNode_Next)(&sk_segments, ts))
- VG_(printf)("list: %8p->%8p ->%d (0x%x) prot=%x flags=%x\n",
- ts, ts->addr, ts->len, ts->len, ts->prot, ts->flags);
-
- VG_(printf)("inserting s=%p addr=%p len=%d\n",
- s, s->addr, s->len);
- }
-
- if (!recycled)
- VG_(SkipList_Insert)(&sk_segments, s);
+ /* Clean up right now */
+ preen_segments();
+ if (0) show_segments("after map_file_segment");
/* If this mapping is of the beginning of a file, isn't part of
Valgrind, is at least readable and seems to contain an object
- file, then try reading symbols from it. */
- if ((flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP &&
- s->symtab == NULL) {
- if (off == 0 &&
- filename != NULL &&
- (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC) &&
- len >= VKI_PAGE_SIZE &&
- s->symtab == NULL &&
- VG_(is_object_file)((void *)addr))
- {
+ file, then try reading symbols from it.
+ */
+ if (s->symtab == NULL
+ && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) {
+ if (off == 0
+ && s->fnIdx != -1
+ && (prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == (VKI_PROT_READ|VKI_PROT_EXEC)
+ && len >= VKI_PAGE_SIZE
+ && VG_(is_object_file)((void *)addr)) {
s->symtab = VG_(read_seg_symbols)(s);
-
if (s->symtab != NULL) {
s->flags |= SF_DYNLIB;
}
} else if (flags & SF_MMAP) {
+#if 0
const SegInfo *info;
/* Otherwise see if an existing symtab applies to this Segment */
@@ -648,12 +800,12 @@
VG_(symtab_incref)((SegInfo *)info);
}
}
+#endif
}
}
/* clean up */
- merge_segments(addr, len);
-#endif
+ preen_segments();
}
void VG_(map_fd_segment)(Addr addr, SizeT len, UInt prot, UInt flags,
@@ -661,7 +813,6 @@
{
struct vki_stat st;
Char *name = NULL;
- //vg_assert(0);
st.st_dev = 0;
st.st_ino = 0;
@@ -673,16 +824,14 @@
flags &= ~SF_FILE;
}
- // if ((flags & SF_FILE) && filename == NULL && fd != -1)
- // name = VG_(resolve_filename)(fd);
+ if ((flags & SF_FILE) && filename == NULL && fd != -1)
+ name = VG_(resolve_filename_nodup)(fd);
if (filename == NULL)
filename = name;
- VG_(map_file_segment)(addr, len, prot, flags, st.st_dev, st.st_ino, off, filename);
-
- if (name)
- VG_(arena_free)(VG_AR_CORE, name);
+ VG_(map_file_segment)(addr, len, prot, flags,
+ st.st_dev, st.st_ino, off, filename);
}
void VG_(map_segment)(Addr addr, SizeT len, UInt prot, UInt flags)
@@ -695,8 +844,7 @@
/* set new protection flags on an address range */
void VG_(mprotect_range)(Addr a, SizeT len, UInt prot)
{
- Int r;
- Segment *s, *next;
+ Int r;
static const Bool debug = False || mem_debug;
if (debug)
@@ -705,34 +853,22 @@
if (0) show_segments( "mprotect_range(before)" );
/* Everything must be page-aligned */
- vg_assert((a & (VKI_PAGE_SIZE-1)) == 0);
+ vg_assert(IS_PAGE_ALIGNED(a));
len = PGROUNDUP(len);
- /*VG_*/ (split_segment)(a);
- /*VG_*/ (split_segment)(a+len);
+ split_segment(a);
+ split_segment(a+len);
r = find_segment(a);
vg_assert(r != -1);
segments[r].prot = prot;
+
+ preen_segments();
+
if (0) show_segments( "mprotect_range(after)");
-
- return;
-
-vg_assert(0);
- for(s = VG_(SkipList_Find)(&sk_segments, &a);
- s != NULL && s->addr < a+len;
- s = next)
- {
- next = VG_(SkipNode_Next)(&sk_segments, s);
- if (s->addr < a)
- continue;
-
- s->prot = prot;
- }
-
- merge_segments(a, len);
}
+
/* Try to find a map space for [addr,addr+len). If addr==0, it means
the caller is prepared to accept a space at any location; if not,
we will try for addr, but fail if we can't get it. This mimics
@@ -741,7 +877,6 @@
Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client)
{
static const Bool debug = False || mem_debug;
- Segment *s;
Addr ret;
Addr limit = (for_client ? VG_(client_end)-1 : VG_(valgrind_last));
Addr base = (for_client ? VG_(client_mapbase) : VG_(valgrind_base));
@@ -857,49 +992,9 @@
addr, len, for_client, ret);
return ret;
-
- vg_assert(0);
-vg_assert(0);
-///////////
- if (debug)
- VG_(printf)("find_map_space: ret starts as %p-%p client=%d\n",
- ret, ret+len, for_client);
-
- s = VG_(SkipList_Find)(&sk_segments, &ret);
- if (s == NULL)
- s = VG_(SkipNode_First)(&sk_segments);
-
- for( ;
- s != NULL && s->addr < (ret+len);
- s = VG_(SkipNode_Next)(&sk_segments, s))
- {
- if (debug)
- VG_(printf)("s->addr=%p len=%d (%p) ret=%p\n",
- s->addr, s->len, s->addr+s->len, ret);
-
- if (s->addr < (ret + len) && (s->addr + s->len) > ret)
- ret = s->addr+s->len;
- }
-
- if (debug) {
- if (s)
- VG_(printf)(" s->addr=%p ->len=%d\n", s->addr, s->len);
- else
- VG_(printf)(" s == NULL\n");
- }
-
- if (((limit - len)+1) < ret)
- ret = 0; /* no space */
- else
- ret += VKI_PAGE_SIZE; /* skip leading redzone */
-
- if (debug)
- VG_(printf)("find_map_space(%p, %d, %d) -> %p\n\n",
- addr, len, for_client, ret);
-
- return ret;
}
+
/* Pad the entire process address space, from VG_(client_base)
to VG_(valgrind_last) by creating an anonymous and inaccessible
mapping over any part of the address space which is not covered
@@ -970,8 +1065,6 @@
if (0) show_segments("find_segment");
if (r == -1) return NULL;
return &segments[r];
-vg_assert(0);
- return VG_(SkipList_Find)(&sk_segments, &a);
}
/* Assumes that 'a' is not in any segment. Finds the lowest-addressed
@@ -1128,7 +1221,6 @@
Addr VG_(client_alloc)(Addr addr, SizeT len, UInt prot, UInt sf_flags)
{
len = PGROUNDUP(len);
-vg_assert(0);
tl_assert(!(sf_flags & SF_FIXED));
tl_assert(0 == addr);
@@ -1242,8 +1334,10 @@
void *VG_(shadow_alloc)(UInt size)
{
static Addr shadow_alloc = 0;
- void *ret;
-vg_assert(0);
+ Addr try_here;
+ Int r;
+
+ if (0) show_segments("shadow_alloc(before)");
vg_assert(VG_(needs).shadow_memory);
vg_assert(!VG_(defined_init_shadow_page)());
@@ -1254,17 +1348,46 @@
shadow_alloc = VG_(shadow_base);
if (shadow_alloc >= VG_(shadow_end))
- return 0;
+ goto failed;
- ret = (void *)shadow_alloc;
- VG_(mprotect)(ret, size, VKI_PROT_READ|VKI_PROT_WRITE);
+ try_here = shadow_alloc;
+ vg_assert(IS_PAGE_ALIGNED(try_here));
+ vg_assert(IS_PAGE_ALIGNED(size));
+ vg_assert(size > 0);
+
+ if (0)
+ VG_(printf)("shadow_alloc: size %d, trying at %p\n", size, (void*)try_here);
+
+ /* this is big-bang allocated, so we don't expect to find a listed
+ segment for it. */
+ /* This is really an absolute disgrace. Sometimes the big-bang
+ mapping is in the list (due to re-reads of /proc/self/maps,
+ presumably) and sometimes it isn't. */
+#if 0
+ r = find_segment(try_here);
+ vg_assert(r == -1);
+ r = find_segment(try_here+size-1);
+ vg_assert(r == -1);
+#endif
+
+ r = VG_(mprotect_native)( (void*)try_here,
+ size, VKI_PROT_READ|VKI_PROT_WRITE );
+
+ if (r != 0)
+ goto failed;
shadow_alloc += size;
+ return (void*)try_here;
- return ret;
+ failed:
+ VG_(printf)(
+ "valgrind: Could not allocate address space (%p bytes)\n"
+ "valgrind: for shadow memory chunk.\n",
+ (void*)size
+ );
+ VG_(exit)(1);
}
/*--------------------------------------------------------------------*/
/*--- end vg_memory.c ---*/
/*--------------------------------------------------------------------*/
-