]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Restructured the as_*() functions so they are simpler and there is no implicit
authorNicholas Nethercote <n.nethercote@gmail.com>
Fri, 30 Jul 2004 21:50:15 +0000 (21:50 +0000)
committerNicholas Nethercote <n.nethercote@gmail.com>
Fri, 30 Jul 2004 21:50:15 +0000 (21:50 +0000)
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

coregrind/stage1.c
coregrind/ume.c
coregrind/ume.h
coregrind/vg_main.c

index 4d50c49f0fc20b8b89172b24b09a975d94cbf31b..ce408d7986e0dc3ab2200de0313ce7a8f82ad991 100644 (file)
@@ -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);   
index 89ffe8e05d92e128643ed4cc5a8d87d5f996dc12..d7c18803928766620d8da391bc8f6d70dab1e0b0 100644 (file)
@@ -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) {
index 1155edecda10f43f9a893f446eea56b7d84f876e..d59b9e9a091cce40acaf552768df6ddfb6064faa 100644 (file)
 /* 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                        ---*/
index c3f45232e385d9b369c67a81b2143399abb2d3b4..86ca8e1dd26a1de4bca568769c613d09f3a00125 100644 (file)
@@ -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