From: Nicholas Nethercote Date: Fri, 30 Jul 2004 21:50:15 +0000 (+0000) Subject: Restructured the as_*() functions so they are simpler and there is no implicit X-Git-Tag: svn/VALGRIND_2_2_0~99 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1eb570df2c33ad28b10a6a5570b55c79967719b1;p=thirdparty%2Fvalgrind.git Restructured the as_*() functions so they are simpler and there is no implicit global state -- the state is threaded explicitly through via function arguments and return values. ume.c now has no global variables, which is nice. Also removed a redundant as_pad() call in stage2's main() which meant layout_client_space() could be merged with layout_remaining_space(). Also removed a couple of no-longer-used variables and #defines. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2537 --- diff --git a/coregrind/stage1.c b/coregrind/stage1.c index 4d50c49f0f..ce408d7986 100644 --- a/coregrind/stage1.c +++ b/coregrind/stage1.c @@ -61,7 +61,8 @@ static const char stage2[] = "stage2"; communicate some extra information to stage2 (namely, the fd of the padding file, so it can identiry and remove the padding later). */ -static void *fix_auxv(void *v_init_esp, const struct exeinfo *info) +static void *fix_auxv(void *v_init_esp, const struct exeinfo *info, + int padfile) { struct ume_auxv *auxv; int *newesp; @@ -90,7 +91,7 @@ static void *fix_auxv(void *v_init_esp, const struct exeinfo *info) /* stage2 needs this so it can clean up the padding we leave in place when we start it */ auxv[0].a_type = AT_UME_PADFD; - auxv[0].u.a_val = as_getpadfd(); + auxv[0].u.a_val = padfile; /* This will be needed by valgrind itself so that it can subsequently execve() children. This needs to be done here @@ -155,7 +156,8 @@ static void *fix_auxv(void *v_init_esp, const struct exeinfo *info) return v_init_esp; } -static int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) { +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", start, end, perm, maj, min, ino); return 1; @@ -163,7 +165,7 @@ static int prmap(void *start, void *end, const char *perm, off_t off, int maj, i static void hoops(void) { - int err; + int err, padfile; struct exeinfo info; extern char _end; int *esp; @@ -193,14 +195,15 @@ static void hoops(void) /* Make sure stage2's dynamic linker can't tromp on the lower part of the address space. */ - as_pad(0, (void *)info.map_base); + padfile = as_openpadfile(); + as_pad(0, (void *)info.map_base, padfile); - esp = fix_auxv(ume_exec_esp, &info); + esp = fix_auxv(ume_exec_esp, &info, padfile); if (0) { printf("---------- launch stage 2 ----------\n"); printf("eip=%p esp=%p\n", (void *)info.init_eip, esp); - foreach_map(prmap); + foreach_map(prmap, /*dummy*/NULL); } ume_go(info.init_eip, (addr_t)esp); diff --git a/coregrind/ume.c b/coregrind/ume.c index 89ffe8e05d..d7c1880392 100644 --- a/coregrind/ume.c +++ b/coregrind/ume.c @@ -57,11 +57,6 @@ struct elfinfo int fd; }; -static int padfile = -1; -static struct stat padstat; - -extern int kickstart_base; /* linker created */ - static void check_mmap(void* res, void* base, int len) { if ((void*)-1 == res) { @@ -72,9 +67,12 @@ static void check_mmap(void* res, void* base, int len) } } -void foreach_map(int (*fn)(void *start, void *end, +// 'extra' allows the caller to pass in extra args to 'fn', like free +// variables to a closure. +void foreach_map(int (*fn)(char *start, char *end, const char *perm, off_t offset, - int maj, int min, int ino)) + int maj, int min, int ino, void* extra), + void* extra) { static char buf[10240]; char *bufptr = buf; @@ -114,81 +112,103 @@ void foreach_map(int (*fn)(void *start, void *end, if (bufptr != NULL) bufptr++; /* skip \n */ - if (!(*fn)(segstart, segend, perm, offset, maj, min, ino)) + if (!(*fn)(segstart, segend, perm, offset, maj, min, ino, extra)) break; } } -static char *fillgap_addr; -static char *fillgap_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; -static int fillgap(void *segstart, void *segend, const char *perm, off_t off, - int maj, int min, int ino) { - if ((char *)segstart >= fillgap_end) + if (segstart >= extra->fillgap_end) return 0; - if ((char *)segstart > fillgap_addr) { - void* res = mmap(fillgap_addr, (char *)segstart-fillgap_addr, PROT_NONE, - MAP_FIXED|MAP_PRIVATE, padfile, 0); - check_mmap(res, fillgap_addr, (char*)segstart - fillgap_addr); + 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); } - fillgap_addr = segend; + extra->fillgap_start = segend; return 1; } -/* pad all the empty spaces in a range of address space to stop - interlopers */ -void as_pad(void *start, void *end) +// Choose a name for the padfile, open it. +int as_openpadfile(void) { - char buf[1024]; - - if (padfile == -1) { - int seq = 1; - do { - sprintf(buf, "/tmp/.pad.%d.%d", getpid(), seq++); - padfile = open(buf, O_RDWR|O_CREAT|O_EXCL, 0); - unlink(buf); - if (padfile == -1 && errno != EEXIST) - exit(44); - } while(padfile == -1); - fstat(padfile, &padstat); - } + 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; +} - fillgap_addr = start; - fillgap_end = end; +// 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); + foreach_map(fillgap, &extra); - if (fillgap_addr < fillgap_end) { - void* res = mmap(fillgap_addr, fillgap_end-fillgap_addr, PROT_NONE, - MAP_FIXED|MAP_PRIVATE, padfile, 0); - check_mmap(res, fillgap_addr, fillgap_end - fillgap_addr); + 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); } } -static void *killpad_start; -static void *killpad_end; +typedef struct { + char* killpad_start; + char* killpad_end; + struct stat* killpad_padstat; +} killpad_extra; -static int killpad(void *segstart, void *segend, const char *perm, off_t off, - int maj, int min, int ino) +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; - if (padstat.st_dev != makedev(maj, min) || padstat.st_ino != ino) + assert(NULL != extra->killpad_padstat); + + if (extra->killpad_padstat->st_dev != makedev(maj, min) || + extra->killpad_padstat->st_ino != ino) return 1; - if (segend <= killpad_start || segstart >= killpad_end) + if (segend <= extra->killpad_start || segstart >= extra->killpad_end) return 1; - if (segstart <= killpad_start) - b = killpad_start; + if (segstart <= extra->killpad_start) + b = extra->killpad_start; else b = segstart; - if (segend >= killpad_end) - e = killpad_end; + if (segend >= extra->killpad_end) + e = extra->killpad_end; else e = segend; @@ -198,37 +218,32 @@ static int killpad(void *segstart, void *segend, const char *perm, off_t off, return 1; } -/* remove padding from a range of address space - padding is always a - mapping of padfile*/ -void as_unpad(void *start, void *end) +// Remove padding of 'padfile' from a range of address space. +void as_unpad(void *start, void *end, int padfile) { - if (padfile == -1) /* no padfile, no padding */ - return; - - killpad_start = start; - killpad_end = end; - - foreach_map(killpad); -} + static struct stat padstat; + killpad_extra extra; + int res; -void as_closepadfile(void) -{ - /* don't unpad */ - close(padfile); - padfile = -1; + 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); } -int as_getpadfd(void) +void as_closepadfile(int padfile) { - return padfile; + int res = close(padfile); + assert(0 == res); } -void as_setpadfd(int fd) -{ - as_closepadfile(); - padfile = fd; - fstat(padfile, &padstat); -} +/*------------------------------------------------------------*/ +/*--- Finding auxv on the stack ---*/ +/*------------------------------------------------------------*/ struct ume_auxv *find_auxv(int *esp) { @@ -245,6 +260,9 @@ struct ume_auxv *find_auxv(int *esp) return (struct ume_auxv *)esp; } +/*------------------------------------------------------------*/ +/*--- Loading ELF files ---*/ +/*------------------------------------------------------------*/ struct elfinfo *readelf(int fd, const char *filename) { @@ -299,8 +317,6 @@ struct elfinfo *readelf(int fd, const char *filename) return e; } -#define REMAINS(x, a) ((x) & ((a)-1)) - /* Map an ELF file. Returns the brk address. */ ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base) { @@ -380,17 +396,17 @@ ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base) return elfbrk; } - +// Forward declaration. static int do_exec_inner(const char *exe, struct exeinfo *info); - static int match_ELF(const char *hdr, int len) { ESZ(Ehdr) *e = (ESZ(Ehdr) *)hdr; return (len > sizeof(*e)) && memcmp(&e->e_ident[0], ELFMAG, SELFMAG) == 0; } -static int load_ELF(char *hdr, int len, int fd, const char *name, struct exeinfo *info) +static int load_ELF(char *hdr, int len, int fd, const char *name, + struct exeinfo *info) { struct elfinfo *e; struct elfinfo *interp = NULL; @@ -530,7 +546,8 @@ static int match_script(const char *hdr, Int len) return (len > 2) && memcmp(hdr, "#!", 2) == 0; } -static int load_script(char *hdr, int len, int fd, const char *name, struct exeinfo *info) +static int load_script(char *hdr, int len, int fd, const char *name, + struct exeinfo *info) { char *interp; char *const end = hdr+len; @@ -582,17 +599,6 @@ static int load_script(char *hdr, int len, int fd, const char *name, struct exei return do_exec_inner(interp, info); } -struct binfmt { - int (*match)(const char *hdr, int len); - int (*load) ( char *hdr, int len, int fd, const char *name, struct exeinfo *); -}; - -static const struct binfmt formats[] = { - { match_ELF, load_ELF }, - { match_script, load_script }, -}; - - static int do_exec_inner(const char *exe, struct exeinfo *info) { int fd; @@ -601,6 +607,14 @@ static int do_exec_inner(const char *exe, struct exeinfo *info) int i; int ret; struct stat st; + static const struct { + int (*match)(const char *hdr, int len); + int (*load) ( char *hdr, int len, int fd2, const char *name, + struct exeinfo *); + } formats[] = { + { match_ELF, load_ELF }, + { match_script, load_script }, + }; fd = open(exe, O_RDONLY); if (fd == -1) { diff --git a/coregrind/ume.h b/coregrind/ume.h index 1155edecda..d59b9e9a09 100644 --- a/coregrind/ume.h +++ b/coregrind/ume.h @@ -50,6 +50,11 @@ /* 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 ---*/ /*------------------------------------------------------------*/ @@ -86,16 +91,11 @@ int do_exec(const char *exe, struct exeinfo *info); /*--- Address space padding ---*/ /*------------------------------------------------------------*/ -void foreach_map(int (*fn)(void *start, void *end, - const char *perm, off_t offset, - int maj, int min, int ino)); - // Padding functions used at startup to force things where we want them. -void as_pad(void *start, void *end); -void as_unpad(void *start, void *end); -void as_closepadfile(void); -int as_getpadfd(void); -void as_setpadfd(int); +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 c3f45232e3..86ca8e1dd2 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -455,15 +455,15 @@ static void newpid(ThreadId unused) /*====================================================================*/ /* Look for our AUXV table */ -static void scan_auxv(void) +int scan_auxv(void) { const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp); - int found = 0; + int padfile = -1, found = 0; for (; auxv->a_type != AT_NULL; auxv++) switch(auxv->a_type) { case AT_UME_PADFD: - as_setpadfd(auxv->u.a_val); + padfile = auxv->u.a_val; found |= 1; break; @@ -477,6 +477,8 @@ static void scan_auxv(void) fprintf(stderr, "valgrind: stage2 must be launched by stage1\n"); exit(127); } + vg_assert(padfile >= 0); + return padfile; } @@ -484,34 +486,28 @@ static void scan_auxv(void) /*=== Address space determination ===*/ /*====================================================================*/ -/* Pad client space so it doesn't get filled in before the right time */ -static void layout_client_space(Addr argc_addr) +static void layout_remaining_space(Addr argc_addr, float ratio) { - VG_(client_base) = CLIENT_BASE; - VG_(valgrind_base) = (addr_t)&kickstart_base; - VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */ + Int ires; + void* vres; + addr_t client_size, shadow_size; - as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base)); -} + VG_(valgrind_base) = (addr_t)&kickstart_base; + VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); // stack -static void layout_remaining_space(float ratio) -{ - Int ires; - void* vres; - - /* This tries to give the client as large as possible address space while - * taking into account the tool's shadow needs. */ - addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio), + // This gives the client the largest possible address space while + // taking into account the tool's shadow needs. + client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio), CLIENT_SIZE_MULTIPLE); - addr_t shadow_size = PGROUNDUP(client_size * ratio); - + VG_(client_base) = CLIENT_BASE; VG_(client_end) = VG_(client_base) + client_size; /* where !FIXED mmap goes */ VG_(client_mapbase) = VG_(client_base) + PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION)); - VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE; - VG_(shadow_end) = VG_(shadow_base) + shadow_size; + shadow_size = PGROUNDUP(client_size * ratio); + VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE; + VG_(shadow_end) = VG_(shadow_base) + shadow_size; #define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024)) @@ -2696,8 +2692,8 @@ void VG_(do_sanity_checks) ( Bool force_expensive ) build the segment skip-list. */ -static int prmap(void *start, void *end, const char *perm, off_t off, - int maj, int min, int ino) { +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", start, end, perm, maj, min, ino); return True; @@ -2720,6 +2716,7 @@ int main(int argc, char **argv) VgSchedReturnCode src; Int exitcode = 0; vki_rlimit zero = { 0, 0 }; + Int padfile; //============================================================ // Nb: startup is complex. Prerequisites are shown at every step. @@ -2748,11 +2745,11 @@ int main(int argc, char **argv) // Check we were launched by stage1 // p: n/a //-------------------------------------------------------------- - scan_auxv(); + padfile = scan_auxv(); if (0) { printf("========== main() ==========\n"); - foreach_map(prmap); + foreach_map(prmap, /*dummy*/NULL); } //-------------------------------------------------------------- @@ -2764,12 +2761,6 @@ int main(int argc, char **argv) VG_(libdir) = cp; } - //-------------------------------------------------------------- - // Begin working out address space layout - // p: n/a - //-------------------------------------------------------------- - layout_client_space( (Addr) & argc ); - //-------------------------------------------------------------- // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc). // Pre-process the command line. @@ -2785,7 +2776,6 @@ int main(int argc, char **argv) //-------------------------------------------------------------- // With client padded out, map in tool - // p: layout_client_space() [for padding] // p: set-libdir [for VG_(libdir)] // p: pre_process_cmd_line_options() [for 'tool'] //-------------------------------------------------------------- @@ -2798,13 +2788,12 @@ int main(int argc, char **argv) //-------------------------------------------------------------- // Finalise address space layout - // p: layout_client_space(), load_tool() [for 'toolinfo'] + // p: load_tool() [for 'toolinfo'] //-------------------------------------------------------------- - layout_remaining_space( toolinfo->shadow_ratio ); + layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio ); //-------------------------------------------------------------- // Load client executable, finding in $PATH if necessary - // p: layout_client_space() [so there's space] // p: pre_process_cmd_line_options() [for 'exec', 'need_help'] // p: layout_remaining_space [so there's space] //-------------------------------------------------------------- @@ -2815,8 +2804,8 @@ int main(int argc, char **argv) // p: layout_remaining_space() [everything must be mapped in before now] // p: load_client() [ditto] //-------------------------------------------------------------- - as_unpad((void *)VG_(shadow_end), (void *)~0); - as_closepadfile(); /* no more padding */ + as_unpad((void *)VG_(shadow_end), (void *)~0, padfile); + as_closepadfile(padfile); // no more padding //-------------------------------------------------------------- // Set up client's environment