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 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/ume.c b/coregrind/ume.c
index 89ffe8e..d7c1880 100644
--- a/coregrind/ume.c
+++ b/coregrind/ume.c
@@ -57,11 +57,6 @@
    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 @@
    }
 }
 
-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 @@
       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(void *segstart, void *segend, const char *perm, off_t off, 
-                   int maj, int min, int ino) {
-   if ((char *)segstart >= fillgap_end)
+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 ((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];
+   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);
 
-   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);
-   }
+   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 @@
    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;
+   static struct stat padstat;
+   killpad_extra extra;
+   int res;
+
+   assert(padfile > 0);
    
-   killpad_start = start;
-   killpad_end = end;
-   
-   foreach_map(killpad);
+   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(void)
+void as_closepadfile(int padfile)
 {
-   /* don't unpad */
-   close(padfile);
-   padfile = -1;
+   int res = close(padfile);
+   assert(0 == res);
 }
 
-int as_getpadfd(void)
-{
-   return padfile;
-}
-
-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 @@
    return (struct ume_auxv *)esp;
 }
 
+/*------------------------------------------------------------*/
+/*--- Loading ELF files                                    ---*/
+/*------------------------------------------------------------*/
 
 struct elfinfo *readelf(int fd, const char *filename)
 {
@@ -299,8 +317,6 @@
    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 @@
    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 @@
    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 @@
    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 @@
    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) {