diff --git a/coregrind/stage1.c b/coregrind/stage1.c index 7a87d8ffd..6e8d56dc9 100644 --- a/coregrind/stage1.c +++ b/coregrind/stage1.c @@ -30,13 +30,16 @@ #define _FILE_OFFSET_BITS 64 +#include #include #include #include #include #include #include +#include #include +#include #include "core.h" @@ -51,6 +54,10 @@ static const char *valgrind_lib = VG_LIBDIR; /* stage2's name */ static const char stage2[] = "stage2"; +/*------------------------------------------------------------*/ +/*--- Auxv modification ---*/ +/*------------------------------------------------------------*/ + /* Modify the auxv the kernel gave us to make it look like we were execed as the shared object. @@ -153,6 +160,89 @@ static void *fix_auxv(void *v_init_esp, const struct exeinfo *info, return v_init_esp; } + +/*------------------------------------------------------------*/ +/*--- Address space padding ---*/ +/*------------------------------------------------------------*/ + +static void check_mmap(void* res, void* base, int len) +{ + if ((void*)-1 == res) { + fprintf(stderr, "valgrind: padding mmap(%p, %d) failed during startup.\n" + "valgrind: is there a hard virtual memory limit set?\n", + base, len); + exit(1); + } +} + +typedef struct { + char* fillgap_start; + char* fillgap_end; + int fillgap_padfile; +} fillgap_extra; + +static int fillgap(char *segstart, char *segend, const char *perm, off_t off, + int maj, int min, int ino, void* e) +{ + fillgap_extra* extra = e; + + if (segstart >= extra->fillgap_end) + return 0; + + if (segstart > extra->fillgap_start) { + void* res = mmap(extra->fillgap_start, segstart - extra->fillgap_start, + PROT_NONE, MAP_FIXED|MAP_PRIVATE, + extra->fillgap_padfile, 0); + check_mmap(res, extra->fillgap_start, segstart - extra->fillgap_start); + } + extra->fillgap_start = segend; + + return 1; +} + +// Choose a name for the padfile, open it. +int as_openpadfile(void) +{ + char buf[256]; + int padfile; + int seq = 1; + do { + snprintf(buf, 256, "/tmp/.pad.%d.%d", getpid(), seq++); + padfile = open(buf, O_RDWR|O_CREAT|O_EXCL, 0); + unlink(buf); + if (padfile == -1 && errno != EEXIST) { + fprintf(stderr, "valgrind: couldn't open padfile\n"); + exit(44); + } + } while(padfile == -1); + + return padfile; +} + +// Pad all the empty spaces in a range of address space to stop interlopers. +void as_pad(void *start, void *end, int padfile) +{ + fillgap_extra extra; + extra.fillgap_start = start; + extra.fillgap_end = end; + extra.fillgap_padfile = padfile; + + foreach_map(fillgap, &extra); + + if (extra.fillgap_start < extra.fillgap_end) { + void* res = mmap(extra.fillgap_start, + extra.fillgap_end - extra.fillgap_start, + PROT_NONE, MAP_FIXED|MAP_PRIVATE, padfile, 0); + check_mmap(res, extra.fillgap_start, + extra.fillgap_end - extra.fillgap_start); + } +} + + +/*------------------------------------------------------------*/ +/*--- main() and related pieces ---*/ +/*------------------------------------------------------------*/ + static int prmap(char *start, char *end, const char *perm, off_t off, int maj, int min, int ino, void* dummy) { printf("mapping %10p-%10p %s %02x:%02x %d\n", diff --git a/coregrind/ume.c b/coregrind/ume.c index be5185d4a..a2cbc3e49 100644 --- a/coregrind/ume.c +++ b/coregrind/ume.c @@ -55,9 +55,7 @@ struct elfinfo static void check_mmap(void* res, void* base, int len) { if ((void*)-1 == res) { - fprintf(stderr, "valgrind: mmap(%p, %d) failed during startup.\n" - "valgrind: is there a hard virtual memory limit set?\n", - base, len); + fprintf(stderr, "valgrind: mmap(%p, %d) failed in UME.\n", base, len); exit(1); } } @@ -112,130 +110,6 @@ void foreach_map(int (*fn)(char *start, char *end, } } -typedef struct { - char* fillgap_start; - char* fillgap_end; - int fillgap_padfile; -} fillgap_extra; - -static int fillgap(char *segstart, char *segend, const char *perm, off_t off, - int maj, int min, int ino, void* e) -{ - fillgap_extra* extra = e; - - if (segstart >= extra->fillgap_end) - return 0; - - if (segstart > extra->fillgap_start) { - void* res = mmap(extra->fillgap_start, segstart - extra->fillgap_start, - PROT_NONE, MAP_FIXED|MAP_PRIVATE|MAP_NORESERVE, - extra->fillgap_padfile, 0); - check_mmap(res, extra->fillgap_start, segstart - extra->fillgap_start); - } - extra->fillgap_start = segend; - - return 1; -} - -// Choose a name for the padfile, open it. -int as_openpadfile(void) -{ - char buf[256]; - int padfile; - int seq = 1; - do { - snprintf(buf, 256, "/tmp/.pad.%d.%d", getpid(), seq++); - padfile = open(buf, O_RDWR|O_CREAT|O_EXCL, 0); - unlink(buf); - if (padfile == -1 && errno != EEXIST) { - fprintf(stderr, "valgrind: couldn't open padfile\n"); - exit(44); - } - } while(padfile == -1); - - return padfile; -} - -// Pad all the empty spaces in a range of address space to stop interlopers. -void as_pad(void *start, void *end, int padfile) -{ - fillgap_extra extra; - extra.fillgap_start = start; - extra.fillgap_end = end; - extra.fillgap_padfile = padfile; - - foreach_map(fillgap, &extra); - - if (extra.fillgap_start < extra.fillgap_end) { - void* res = mmap(extra.fillgap_start, - extra.fillgap_end - extra.fillgap_start, - PROT_NONE, MAP_FIXED|MAP_PRIVATE|MAP_NORESERVE, padfile, 0); - check_mmap(res, extra.fillgap_start, - extra.fillgap_end - extra.fillgap_start); - } -} - -typedef struct { - char* killpad_start; - char* killpad_end; - struct stat* killpad_padstat; -} killpad_extra; - -static int killpad(char *segstart, char *segend, const char *perm, off_t off, - int maj, int min, int ino, void* ex) -{ - killpad_extra* extra = ex; - void *b, *e; - int res; - - assert(NULL != extra->killpad_padstat); - - if (extra->killpad_padstat->st_dev != makedev(maj, min) || - extra->killpad_padstat->st_ino != ino) - return 1; - - if (segend <= extra->killpad_start || segstart >= extra->killpad_end) - return 1; - - if (segstart <= extra->killpad_start) - b = extra->killpad_start; - else - b = segstart; - - if (segend >= extra->killpad_end) - e = extra->killpad_end; - else - e = segend; - - res = munmap(b, (char *)e-(char *)b); - assert(0 == res); - - return 1; -} - -// Remove padding of 'padfile' from a range of address space. -void as_unpad(void *start, void *end, int padfile) -{ - static struct stat padstat; - killpad_extra extra; - int res; - - assert(padfile > 0); - - res = fstat(padfile, &padstat); - assert(0 == res); - extra.killpad_padstat = &padstat; - extra.killpad_start = start; - extra.killpad_end = end; - foreach_map(killpad, &extra); -} - -void as_closepadfile(int padfile) -{ - int res = close(padfile); - assert(0 == res); -} - /*------------------------------------------------------------*/ /*--- Finding auxv on the stack ---*/ /*------------------------------------------------------------*/ diff --git a/coregrind/ume.h b/coregrind/ume.h index d59b9e9a0..1d7cef93b 100644 --- a/coregrind/ume.h +++ b/coregrind/ume.h @@ -39,6 +39,15 @@ /*--- General stuff ---*/ /*------------------------------------------------------------*/ +void foreach_map(int (*fn)(char *start, char *end, + const char *perm, off_t offset, + int maj, int min, int ino, void* extra), + void* extra); + +/*------------------------------------------------------------*/ +/*--- Loading ELF files ---*/ +/*------------------------------------------------------------*/ + #if ELFSZ == 64 #define ESZ(x) Elf64_##x #elif ELFSZ == 32 @@ -50,15 +59,6 @@ /* Integer type the same size as a pointer */ typedef ESZ(Addr) addr_t; -void foreach_map(int (*fn)(char *start, char *end, - const char *perm, off_t offset, - int maj, int min, int ino, void* extra), - void* extra); - -/*------------------------------------------------------------*/ -/*--- Loading ELF files ---*/ -/*------------------------------------------------------------*/ - // Info needed to load and run a program. IN/INOUT/OUT refers to the // inputs/outputs of do_exec(). struct exeinfo @@ -87,16 +87,6 @@ struct exeinfo // the program. int do_exec(const char *exe, struct exeinfo *info); -/*------------------------------------------------------------*/ -/*--- Address space padding ---*/ -/*------------------------------------------------------------*/ - -// Padding functions used at startup to force things where we want them. -int as_openpadfile (void); -void as_pad (void *start, void *end, int padfile); -void as_unpad (void *start, void *end, int padfile); -void as_closepadfile(int padfile); - /*------------------------------------------------------------*/ /*--- Finding and dealing with auxv ---*/ /*------------------------------------------------------------*/ diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index 5c701e8c1..bf7063db0 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -1400,6 +1400,71 @@ static void load_client(char* cl_argv[], const char* exec, Int need_help, VG_(brk_base) = VG_(brk_limit) = info->brkbase; } +/*====================================================================*/ +/*=== Address space unpadding ===*/ +/*====================================================================*/ + +typedef struct { + char* killpad_start; + char* killpad_end; + struct stat* killpad_padstat; +} killpad_extra; + +static int killpad(char *segstart, char *segend, const char *perm, off_t off, + int maj, int min, int ino, void* ex) +{ + killpad_extra* extra = ex; + void *b, *e; + int res; + + vg_assert(NULL != extra->killpad_padstat); + + if (extra->killpad_padstat->st_dev != makedev(maj, min) || + extra->killpad_padstat->st_ino != ino) + return 1; + + if (segend <= extra->killpad_start || segstart >= extra->killpad_end) + return 1; + + if (segstart <= extra->killpad_start) + b = extra->killpad_start; + else + b = segstart; + + if (segend >= extra->killpad_end) + e = extra->killpad_end; + else + e = segend; + + res = munmap(b, (char *)e-(char *)b); + vg_assert(0 == res); + + return 1; +} + +// Remove padding of 'padfile' from a range of address space. +void as_unpad(void *start, void *end, int padfile) +{ + static struct stat padstat; + killpad_extra extra; + int res; + + vg_assert(padfile > 0); + + res = fstat(padfile, &padstat); + vg_assert(0 == res); + extra.killpad_padstat = &padstat; + extra.killpad_start = start; + extra.killpad_end = end; + foreach_map(killpad, &extra); +} + +void as_closepadfile(int padfile) +{ + int res = close(padfile); + vg_assert(0 == res); +} + /*====================================================================*/ /*=== Command-line: variables, processing, etc ===*/ @@ -2570,7 +2635,7 @@ int main(int argc, char **argv) load_client(cl_argv, exec, need_help, &info, &client_eip); //-------------------------------------------------------------- - // Everything in place, unpad us + // Everything in place, remove padding done by stage1 // p: layout_remaining_space() [everything must be mapped in before now] // p: load_client() [ditto] //--------------------------------------------------------------