From: Nicholas Nethercote Date: Thu, 15 Jul 2004 12:59:41 +0000 (+0000) Subject: Merged Valgrind's heap and stack. This has two main advantages: X-Git-Tag: svn/VALGRIND_2_1_2~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=472d50b40af91ef7a85c9b4c29be13beba989b62;p=thirdparty%2Fvalgrind.git Merged Valgrind's heap and stack. This has two main advantages: 1. It simplifies various things a bit. 2. Valgrind/tools will run out of memory later than currently in many circumstances. This is good news esp. for Calltree. Some things were going in V's 128MB heap, and some were going in V's 128MB map segment. Now all these things are going into a single 256MB map segment. stage2 has been moved down to 0xb0000000, the start of the 256MB map segment. The .so files needed by it are placed at 0xb1000000 (that's the map_base). This required some bootstrapping at startup for memory -- we need to allocate memory to create the segments skip-list which lets us allocate memory... solution was to make the first superblock allocated a special static one. That's pretty simple and enough to get things going. Removed vg_glibc.c which wasn't doing anything anyway. Removed VG_(brk) and associated stuff, made all the things that were calling it call VG_(mmap)() instead. Removed VG_(valgrind_mmap_end) which was no longer needed. Rejigged the startup order a bit as necessary. Moved an important comment from ume.c to vg_main.c where it should be. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2482 --- diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index f4855d06fe..ec0eaefd5d 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -52,7 +52,6 @@ stage2_SOURCES = \ vg_errcontext.c \ vg_execontext.c \ vg_from_ucode.c \ - vg_glibc.c \ vg_hashtable.c \ vg_helpers.S \ vg_instrument.c \ @@ -81,7 +80,7 @@ stage2_SOURCES = \ vg_cpuid.S stage2_DEPENDENCIES = $(srcdir)/valgrind.vs x86/stage2.lds stage2_LDFLAGS=-Wl,--export-dynamic -Wl,-e,_ume_entry -g \ - -Wl,-defsym,kickstart_base=0xb8000000 \ + -Wl,-defsym,kickstart_base=0xb0000000 \ -Wl,-T,x86/stage2.lds \ -Wl,-version-script $(srcdir)/valgrind.vs stage2_LDADD= \ diff --git a/coregrind/stage1.c b/coregrind/stage1.c index 3dffe731ce..abc722e126 100644 --- a/coregrind/stage1.c +++ b/coregrind/stage1.c @@ -179,7 +179,7 @@ static void hoops(void) - it could have a special PHDR (v. ELF specific) - something else? */ - info.map_base = 0xb0000000; + info.map_base = 0xb1000000; info.argv = NULL; snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2); diff --git a/coregrind/ume.c b/coregrind/ume.c index 8ae974d36f..8c37751a5c 100644 --- a/coregrind/ume.c +++ b/coregrind/ume.c @@ -28,48 +28,6 @@ The GNU General Public License is contained in the file COPYING. */ -/* - User-mode exec - - This bootstraps Valgrind. This code decides on the layout of the - client and Valgrind address spaces, loads valgrind.so and the - skin.so into the valgrind part, loads the client executable (and the - dynamic linker, if necessary) into the client part, and calls into - Valgrind proper. - - The code is careful not to allow spurious mappings to appear in the - wrong parts of the address space. In particular, to make sure - dlopen puts things in the right place, it will pad out the forbidden - chunks of address space so that dlopen is forced to put things where - we want them. - - The memory map it creates is: - - CLIENT_BASE +-------------------------+ - | client address space | - : : - : : - | client stack | - client_end +-------------------------+ - | redzone | - shadow_base +-------------------------+ - | | - : shadow memory for skins : - | (may be 0 sized) | - shadow_end +-------------------------+ - : gap (may be 0 sized) : - valgrind_base +-------------------------+ - | valgrind .so files | - | and mappings | - valgrind_mmap_end - - | kickstart executable | - - - - | valgrind heap vvvvvvvvv| - valgrind_end - - - | valgrind stack ^^^^^^^^^| - +-------------------------+ - : kernel : - */ #define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 diff --git a/coregrind/vg_glibc.c b/coregrind/vg_glibc.c deleted file mode 100644 index d4af2c9c6e..0000000000 --- a/coregrind/vg_glibc.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include "vg_include.h" - -extern void *__curbrk; /* in glibc */ - -/* libc overrides, so that things can use normal allocators if they - wish. - XXX override malloc with VG_(arena_malloc)? -*/ -int brk(void *end) -{ - void *res = VG_(brk)(end); - - if (res != end) { - errno = -ENOMEM; - return -1; - } - return 0; -} -int __brk(void *) __attribute__((alias ("brk"))); - -void *sbrk(ptrdiff_t inc) -{ - void *oldbrk = __curbrk; - - if (inc == 0) - return __curbrk; - if (__brk(__curbrk + inc) < 0) - return (void *)-1; - - return oldbrk; -} -int __sbrk(void *) __attribute__((alias ("sbrk"))); - -#if 0 -void *mmap(void *addr, size_t len, int prot, int flags, int fd, __off_t offset) -{ - return VG_(mmap)(addr, len, prot, flags, fd, offset); -} -#endif diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index a5e154bc5d..80fd3bce48 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -1133,9 +1133,6 @@ extern void VG_(core_assert_fail) ( const Char* expr, const Char* file, __attribute__ ((__noreturn__)) extern void VG_(core_panic) ( Char* str ); -/* VG_(brk) not public so skins cannot screw with curr_dataseg_end */ -extern void* VG_(brk) ( void* end_data_segment ); - /* Skins use VG_(strdup)() which doesn't expose ArenaId */ extern Char* VG_(arena_strdup) ( ArenaId aid, const Char* s); @@ -1438,7 +1435,6 @@ extern Addr VG_(brk_limit); /* current brk */ extern Addr VG_(shadow_base); /* skin's shadow memory */ extern Addr VG_(shadow_end); extern Addr VG_(valgrind_base); /* valgrind's address range */ -extern Addr VG_(valgrind_mmap_end); extern Addr VG_(valgrind_end); extern vki_rlimit VG_(client_rlimit_data); /* client's original rlimit data */ diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index 7ea690635e..caa3e9243c 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -74,9 +74,6 @@ #define AT_SECURE 23 /* secure mode boolean */ #endif /* AT_SECURE */ -/* Amount to reserve for Valgrind's internal mappings */ -#define VALGRIND_MAPSIZE (128*1024*1024) - /* redzone gap between client address space and shadow */ #define REDZONE_SIZE (1 * 1024*1024) @@ -111,7 +108,6 @@ Addr VG_(shadow_base); /* skin's shadow memory */ Addr VG_(shadow_end); Addr VG_(valgrind_base); /* valgrind's address range */ -Addr VG_(valgrind_mmap_end); /* valgrind's mmaps are between valgrind_base and here */ Addr VG_(valgrind_end); vki_rlimit VG_(client_rlimit_data); @@ -492,8 +488,7 @@ static void scan_auxv(void) static void layout_client_space(Addr argc_addr) { VG_(client_base) = CLIENT_BASE; - VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */ - VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE; + VG_(valgrind_base) = (addr_t)&kickstart_base; VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */ as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base)); @@ -530,15 +525,13 @@ static void layout_remaining_space(float ratio) "shadow_base %8x (%dMB)\n" "shadow_end %8x (%dMB)\n" "valgrind_base %8x (%dMB)\n" - "valgrind_mmap_end %8x (%dMB)\n" "valgrind_end %8x\n", VG_(client_base), SEGSIZE(client_base, client_mapbase), VG_(client_mapbase), SEGSIZE(client_mapbase, client_end), VG_(client_end), SEGSIZE(client_end, shadow_base), VG_(shadow_base), SEGSIZE(shadow_base, shadow_end), VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base), - VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_mmap_end), - VG_(valgrind_mmap_end), SEGSIZE(valgrind_mmap_end, valgrind_end), + VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end), VG_(valgrind_end) ); @@ -2639,6 +2632,53 @@ void VG_(do_sanity_checks) ( Bool force_expensive ) /*=== main() ===*/ /*====================================================================*/ +/* + This code decides on the layout of the client and Valgrind address + spaces, loads valgrind.so and the skin.so into the valgrind part, + loads the client executable (and the dynamic linker, if necessary) + into the client part, and calls into Valgrind proper. + + The code is careful not to allow spurious mappings to appear in the + wrong parts of the address space. In particular, to make sure + dlopen puts things in the right place, it will pad out the forbidden + chunks of address space so that dlopen is forced to put things where + we want them. + + The memory map it creates is: + + CLIENT_BASE +-------------------------+ + | client address space | + : : + : : + | client stack | + client_end +-------------------------+ + | redzone | + shadow_base +-------------------------+ + | | + : shadow memory for skins : + | (may be 0 sized) | + shadow_end +-------------------------+ + : gap (may be 0 sized) : + valgrind_base +-------------------------+ + | kickstart executable | + | valgrind heap vvvvvvvvv| (barely used) + - - + | valgrind .so files | + | and mappings | + - - + | valgrind stack ^^^^^^^^^| + valgrind_end +-------------------------+ + : kernel : + + Nb: Before we can do general allocations with VG_(arena_malloc)() and + VG_(mmap)(), we need to build the segment skip-list, so we know where + we can put things. However, building that structure requires + allocating memory. So we need to a bootstrapping process. It's done + by making VG_(arena_malloc)() have a special static superblock that's + used for the first 1MB's worth of allocations. This is enough to + build the segment skip-list. +*/ + static int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) { printf("mapping %10p-%10p %s %02x:%02x %d\n", @@ -2689,7 +2729,7 @@ int main(int argc, char **argv) //-------------------------------------------------------------- // Check we were launched by stage1 - // p: n/a [must be first step] + // p: n/a //-------------------------------------------------------------- scan_auxv(); @@ -2736,12 +2776,12 @@ int main(int argc, char **argv) //============================================================== // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool() - // -- redzone size is now set. + // -- redzone size is now set. This is checked by vg_malloc2.c. //============================================================== //-------------------------------------------------------------- // Finalise address space layout - // p: layout_client_space(), load_tool() [for 'toolinfo'] + // p: layout_client_space(), load_tool() [for 'toolinfo'] //-------------------------------------------------------------- layout_remaining_space( toolinfo->shadow_ratio ); @@ -2784,12 +2824,6 @@ int main(int argc, char **argv) // Valgrind. (This is where the old VG_(main)() started.) //============================================================== - //-------------------------------------------------------------- - // Read /proc/self/maps into a buffer - // p: all memory layout, environment setup [so memory maps are right] - //-------------------------------------------------------------- - VG_(read_procselfmaps)(); - //-------------------------------------------------------------- // atfork // p: n/a @@ -2804,35 +2838,64 @@ int main(int argc, char **argv) setup_file_descriptors(); //-------------------------------------------------------------- - // Setup tool - // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls - // VG_(malloc), any mmap'd superblocks aren't erroneously - // identified later as being owned by the client] - // XXX: is that necessary, now that we look for V's segments separately? - // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it - // wrong to ignore any segments that might add in parse_procselfmaps? - // p: setup_client_stack() [for 'VG_(client_arg[cv]'] + // Read /proc/self/maps into a buffer + // p: all memory layout, environment setup [so memory maps are right] + //-------------------------------------------------------------- + VG_(read_procselfmaps)(); + + //-------------------------------------------------------------- + // Build segment map (Valgrind segments only) + // p: read proc/self/maps + // p: sk_pre_clo_init() [to setup new_mem_startup tracker] + //-------------------------------------------------------------- + VG_(parse_procselfmaps) ( build_valgrind_map_callback ); + + //============================================================== + // Can use VG_(arena_malloc)() with non-CORE arena after segments set up + //============================================================== + + //-------------------------------------------------------------- + // Init tool: pre_clo_init, process cmd line, post_clo_init + // p: setup_client_stack() [for 'VG_(client_arg[cv]'] + // p: load_tool() [for 'tool'] + // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)'] + // p: parse_procselfmaps [so VG segments are setup so tool can + // call VG_(malloc)] //-------------------------------------------------------------- (*toolinfo->sk_pre_clo_init)(); VG_(tool_init_dlsym)(tool_dlhandle); VG_(sanity_check_needs)(); - //-------------------------------------------------------------- // If --tool and --help/--help-debug was given, now give the core+tool // help message - // p: pre_clo_init() - //-------------------------------------------------------------- if (need_help) { usage(/*--help-debug?*/2 == need_help); } + process_cmd_line_options(client_auxv, tool); + + SK_(post_clo_init)(); //-------------------------------------------------------------- - // Process Valgrind's + tool's command-line options - // p: load_tool() [for 'tool'] - // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)'] - // p: sk_pre_clo_init [to set 'command_line_options' need] + // Build segment map (all segments) + // p: setup_client_stack() [for 'esp_at_startup'] + // p: init tool [for 'new_mem_startup'] //-------------------------------------------------------------- - process_cmd_line_options(client_auxv, tool); + esp_at_startup___global_arg = esp_at_startup; + VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */ + esp_at_startup___global_arg = 0; + + //-------------------------------------------------------------- + // Initialize our trampoline page (which is also sysinfo stuff) + // p: setup_client_stack() [for 'esp_at_startup'] + //-------------------------------------------------------------- + VG_(memcpy)( (void *)VG_(client_trampoline_code), + &VG_(trampoline_code_start), VG_(trampoline_code_length) ); + VG_(mprotect)( (void *)VG_(client_trampoline_code), + VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC ); + + //============================================================== + // Can use VG_(map)() after segments set up + //============================================================== //-------------------------------------------------------------- // Allow GDB attach @@ -2846,12 +2909,6 @@ int main(int argc, char **argv) VG_(do_syscall)(__NR_pause); } - //-------------------------------------------------------------- - // Setup tool, post command-line processing - // p: process_cmd_line_options [tool assumes it] - //-------------------------------------------------------------- - SK_(post_clo_init)(); - //-------------------------------------------------------------- // Set up baseBlock // p: {pre,post}_clo_init() [for tool helper registration] @@ -2906,52 +2963,6 @@ int main(int argc, char **argv) VGP_PUSHCC(VgpStartup); - //-------------------------------------------------------------- - // Reserve Valgrind's kickstart, heap and stack - // p: XXX ??? - //-------------------------------------------------------------- - VG_(map_segment)(VG_(valgrind_mmap_end), - VG_(valgrind_end)-VG_(valgrind_mmap_end), - VKI_PROT_NONE, SF_VALGRIND|SF_FIXED); - - //-------------------------------------------------------------- - // Identify Valgrind's segments - // p: read proc/self/maps - // p: VG_(map_segment) [XXX ???] - // p: sk_pre_clo_init() [to setup new_mem_startup tracker] - //-------------------------------------------------------------- - VG_(parse_procselfmaps) ( build_valgrind_map_callback ); - - // XXX: I can't see why these two need to be separate; could they be - // folded together? If not, need a comment explaining why. - // - // XXX: can we merge reading and parsing of /proc/self/maps? - // - // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap - // it?) Or does that disturb its contents... - - //-------------------------------------------------------------- - // Build segment map (all segments) - // p: setup_client_stack() [for 'esp_at_startup'] - //-------------------------------------------------------------- - esp_at_startup___global_arg = esp_at_startup; - VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */ - esp_at_startup___global_arg = 0; - - //============================================================== - // Can only use VG_(map)() after VG_(map_segment)() [XXX ???] - //============================================================== - - //-------------------------------------------------------------- - // Build segment map (all segments) - // p: setup_client_stack() [for 'esp_at_startup'] - //-------------------------------------------------------------- - /* Initialize our trampoline page (which is also sysinfo stuff) */ - VG_(memcpy)( (void *)VG_(client_trampoline_code), - &VG_(trampoline_code_start), VG_(trampoline_code_length) ); - VG_(mprotect)( (void *)VG_(client_trampoline_code), - VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC ); - //-------------------------------------------------------------- // Read suppression file // p: process_cmd_line_options() [for VG_(clo_suppressions)] @@ -2989,8 +3000,6 @@ int main(int argc, char **argv) //-------------------------------------------------------------- setup_pointercheck(); - - //-------------------------------------------------------------- // Run! //-------------------------------------------------------------- diff --git a/coregrind/vg_malloc2.c b/coregrind/vg_malloc2.c index c21f3eb525..a3ddbd3a58 100644 --- a/coregrind/vg_malloc2.c +++ b/coregrind/vg_malloc2.c @@ -187,6 +187,8 @@ void* align_upwards ( void* p, Int align ) /*--- Arena management stuff ---*/ /*------------------------------------------------------------*/ +#define CORE_ARENA_MIN_SZW 262144 + /* The arena structures themselves. */ static Arena vg_arena[VG_N_ARENAS]; @@ -246,10 +248,16 @@ void VG_(show_all_arena_stats) ( void ) static void ensure_mm_init ( void ) { - Int client_rz_szW; + static Int client_rz_szW; static Bool init_done = False; - if (init_done) return; + if (init_done) { + // Make sure the client arena's redzone size never changes. Could + // happen if VG_(arena_malloc) was called too early, ie. before the + // tool was loaded. + vg_assert(client_rz_szW == VG_(vg_malloc_redzone_szB)/4); + return; + } /* Use checked red zones (of various sizes) for our internal stuff, and an unchecked zone of arbitrary size for the client. Of @@ -258,7 +266,7 @@ void ensure_mm_init ( void ) here, which merely checks at the time of freeing that the red zone words are unchanged. */ - arena_init ( &vg_arena[VG_AR_CORE], "core", 2, True, 262144, False ); + arena_init ( &vg_arena[VG_AR_CORE], "core", 2, True, CORE_ARENA_MIN_SZW, False ); arena_init ( &vg_arena[VG_AR_TOOL], "tool", 2, True, 262144, False ); @@ -316,29 +324,44 @@ Bool VG_(is_inside_segment_mmapd_by_low_level_MM)( Addr aa ) /*--- Superblock management stuff ---*/ /*------------------------------------------------------------*/ +// If not enough memory available, either aborts (for non-client memory) +// or returns 0 (for client memory). static Superblock* newSuperblock ( Arena* a, Int cszW ) { + static Bool called_before = False; + static Word bootstrap_superblock[CORE_ARENA_MIN_SZW]; + Int cszB; Superblock* sb; + cszW += 2; /* Take into account sb->next and sb->n_words fields */ if (cszW < a->min_sblockW) cszW = a->min_sblockW; while ((cszW % VKI_WORDS_PER_PAGE) > 0) cszW++; - if (a->clientmem) { + cszB = cszW * sizeof(Word); + + if (!called_before) { + // First time we're called -- use the special static bootstrap + // superblock (see comment at top of main() for details). + called_before = True; + vg_assert(a == &vg_arena[VG_AR_CORE]); + vg_assert(CORE_ARENA_MIN_SZW*sizeof(Word) >= cszB); + sb = (Superblock*)bootstrap_superblock; + + } else if (a->clientmem) { // client allocation -- return 0 to client if it fails sb = (Superblock *) - VG_(client_alloc)(0, cszW * sizeof(Word), + VG_(client_alloc)(0, cszB, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, 0); if (NULL == sb) { return 0; } } else { // non-client allocation -- abort if it fails - sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word), - "newSuperblock" ); + sb = VG_(get_memory_from_mmap) ( cszB, "newSuperblock" ); } sb->n_payload_words = cszW - 2; - a->bytes_mmaped += cszW * sizeof(Word); + a->bytes_mmaped += cszB; if (0) VG_(message)(Vg_DebugMsg, "newSuperblock, %d payload words", sb->n_payload_words); diff --git a/coregrind/vg_memory.c b/coregrind/vg_memory.c index f179c96400..4a476f7584 100644 --- a/coregrind/vg_memory.c +++ b/coregrind/vg_memory.c @@ -493,7 +493,7 @@ Addr VG_(find_map_space)(Addr addr, UInt len, Bool for_client) static const Bool debug = False || mem_debug; Segment *s; Addr ret; - Addr limit = (for_client ? VG_(client_end) : VG_(valgrind_mmap_end)); + Addr limit = (for_client ? VG_(client_end) : VG_(valgrind_end)); if (addr == 0) addr = for_client ? VG_(client_mapbase) : VG_(valgrind_base); diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c index b80b9e6497..f8f7322acc 100644 --- a/coregrind/vg_mylibc.c +++ b/coregrind/vg_mylibc.c @@ -372,54 +372,6 @@ Int VG_(nanosleep)( const struct vki_timespec *req, return 0; } -extern Char _end; -Char *VG_(curbrk) = NULL; -extern void *__curbrk; /* in glibc */ - -void* VG_(brk) ( void* end_data_segment ) -{ - Addr end; - Addr brkpage; - Addr endpage; - - if (VG_(curbrk) == NULL) { - VG_(curbrk) = &_end; - __curbrk = (void *)VG_(curbrk); - } - - end = (Addr)end_data_segment; - brkpage = PGROUNDUP(VG_(curbrk)); - endpage = PGROUNDUP(end); - - if (0 && VG_(curbrk) != __curbrk) - VG_(printf)("__curbrk changed unexpectedly: VG_(curbrk)=%p, __curbrk=%p\n", - VG_(curbrk), __curbrk); - - if (0) - VG_(printf)("brk(end_data_segment=%p); brkpage=%p endpage=%p end=%p curbrk=%p &_end=%p\n", - end_data_segment, brkpage, endpage, end, VG_(curbrk), &_end); - - if (endpage < (Addr)&_end) { - __curbrk = (void *)VG_(curbrk); - return (void *)VG_(curbrk); - } - - if (brkpage != endpage) { - if (brkpage > endpage) { - Int res = munmap_inner((void *)brkpage, brkpage-endpage); - vg_assert(0 == res); - } else { - Addr res = mmap_inner((void *)brkpage, endpage-brkpage, - VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, - VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, -1, 0); - vg_assert((Addr)-1 != res); - } - } - VG_(curbrk) = (Char *)__curbrk = end_data_segment; - - return end_data_segment; -} - /* --------------------------------------------------------------------- printf implementation. The key function, vg_vprintf(), emits chars @@ -1675,16 +1627,12 @@ void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who ) { static UInt tot_alloc = 0; void* p; - Char *b = VG_(brk)(0); - - p = (void *)PGROUNDUP(b); - b = VG_(brk)(p + PGROUNDUP(nBytes)); - - if (b != (p + PGROUNDUP(nBytes))) - p = (void *)-1; + p = VG_(mmap)(0, nBytes, + VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, + VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, -1, 0); if (p != ((void*)(-1))) { - vg_assert(p >= (void *)VG_(valgrind_mmap_end) && p < (void *)VG_(valgrind_end)); + vg_assert(p >= (void*)VG_(valgrind_base) && p < (void*)VG_(valgrind_end)); tot_alloc += (UInt)nBytes; if (0) VG_(printf)(