]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
FreeBSD: clean up guest stack creation code
authorPaul Floyd <pjfloyd@wanadoo.fr>
Sun, 25 Feb 2024 13:50:57 +0000 (14:50 +0100)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Sun, 25 Feb 2024 13:50:57 +0000 (14:50 +0100)
At one time I thought of using sysctls to get the same stack
max size and growth size as the OS uses. But that won't work
for x86 on amd64. So I've just cleaned the code a bit and
added more comments explaining what is going on.

coregrind/m_aspacemgr/aspacemgr-linux.c
coregrind/m_initimg/initimg-freebsd.c

index da3db87fcdc088a056879821c9a2f18464c66409..aab9eb8d18a9cf769bfb2a23f352b7a8a4cf85e5 100644 (file)
@@ -1686,9 +1686,6 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
    // and fills the space up to the end of the segment
    // see man mmap
 
-   // Version number from
-   // https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions-10.html
-
    // On x86 this is 0x3FE0000
    // And on amd64 it is 0x1FFE0000 (536739840)
    // There is less of an issue on amd64 as we just choose some arbitrary address rather then trying
@@ -1701,13 +1698,15 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
    // This seems to be in the sysctl kern.sgrowsiz
    // Then there is kern.maxssiz which is the total stack size (grow size + guard area)
    // In other words guard area = maxssiz - sgrowsiz
-
-#if (__FreeBSD_version >= 1003516)
+   //
+   // Unfortunately there isn't a maxssiz32 for x86 on amd64
+   // That means x86 on amd64 gets the amd64 stack size of 512M
+   // which is really quite big for the x86 address space
+   // so we can't use these syscalls. Maybe one day when all supported platforms
+   // have them.
 
 #if 0
    // this block implements what is described above
-   // this makes no changes to the regression tests
-   // I'm keeping it for a rainy day.
    // note this needs
    // #include "pub_core_libcproc.h"
    SizeT kern_maxssiz;
@@ -1715,17 +1714,20 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
    SizeT sysctl_size = sizeof(SizeT);
    VG_(sysctlbyname)("kern.maxssiz", &kern_maxssiz, &sysctl_size, NULL, 0);
    VG_(sysctlbyname)("kern.sgrowsiz", &kern_sgrowsiz, &sysctl_size, NULL, 0);
-
-   suggested_clstack_end = aspacem_maxAddr - (kern_maxssiz - kern_sgrowsiz) + VKI_PAGE_SIZE;
+   VG_(printf)("maxssiz %lx\n", kern_maxssiz);
+   //suggested_clstack_end = aspacem_maxAddr - (kern_maxssiz - kern_sgrowsiz) + VKI_PAGE_SIZE;
 #endif
 
+   // on amd64 we have oodles of space and just shove the new stack somewhere out of the way
+   // x86 is far more constrained, and we put the new stack just below the stack passed in to V
+   // except that it has stack space and the growth stack guard below it as decribed above
+   // so we need to skip over the existing stack/growth area on x86
+
+# if VG_WORDSIZE == 4
    suggested_clstack_end = aspacem_maxAddr - 64*1024*1024UL
                                            + VKI_PAGE_SIZE;
-
 #else
-   suggested_clstack_end = aspacem_maxAddr - 16*1024*1024UL
-                                           + VKI_PAGE_SIZE;
-
+   suggested_clstack_end = aspacem_maxAddr;
 #endif
 
    // --- Solaris ------------------------------------------
index 7de1702ca796cca6c6c2421d996f9ed24ce5c2ec..db0d6ec67dd6f1a787e70ac3e74b82f59f4bb73c 100644 (file)
@@ -325,6 +325,23 @@ static HChar *copy_bytes(HChar **tab, const HChar *src, SizeT size)
    return orig;
 }
 
+static const struct auxv *find_auxv(const UWord* sp)
+{
+   sp++;                // skip argc (Nb: is word-sized, not int-sized!)
+
+   while (*sp != 0) {   // skip argv
+      sp++;
+   }
+   sp++;
+
+   while (*sp != 0) {   // skip env
+      sp++;
+   }
+   sp++;
+
+   return (const struct auxv *)sp;
+}
+
 /* ----------------------------------------------------------------
 
    This sets up the client's initial stack, containing the args,
@@ -350,7 +367,7 @@ static HChar *copy_bytes(HChar **tab, const HChar *src, SizeT size)
                   | argv            |
                   +-----------------+
                   | argc            |
-   lower address  +-----------------+ <- sp
+   lower address  +-----------------+ <- client_SP (return value)
                   | undefined       |
                   :                 :
 
@@ -360,27 +377,26 @@ static HChar *copy_bytes(HChar **tab, const HChar *src, SizeT size)
 
    The client's auxv is created by copying and modifying our own one.
 
-   ---------------------------------------------------------------- */
+   init_sp: used to find the auxv passed by the OS to V
+   some of it will be used to generate the client auxv
 
-static struct auxv *find_auxv(UWord* sp)
-{
-   sp++;                // skip argc (Nb: is word-sized, not int-sized!)
+   new_client_envp: this is a copy of the original client envp
+   with LD_PRELOADs added and VALGRIND_LAUNCHER removed
 
-   while (*sp != 0) {   // skip argv
-      sp++;
-   }
-   sp++;
+   info: structure containing about the memory mappings of the
+   exe (text and stack)
 
-   while (*sp != 0) {   // skip env
-      sp++;
-   }
-   sp++;
+   client_auxv: (output) the auxv created here
 
-   return (struct auxv *)sp;
-}
+   clstack_end: the value returned by VG_(am_startup), which is
+   128G
 
-static Addr setup_client_stack(void*  init_sp,
-                               HChar** orig_envp,
+   clstack_max_size: the max of sysctlkern.maxssiz and VG_(clo_main_stacksize)
+   aspacem_maxAddr
+
+   ---------------------------------------------------------------- */
+static Addr setup_client_stack(const void*  init_sp,
+                               HChar** new_client_envp,
                                const ExeInfo* info,
                                UInt** client_auxv,
                                Addr   clstack_end,
@@ -388,19 +404,19 @@ static Addr setup_client_stack(void*  init_sp,
 {
    SysRes res;
    HChar **cpp;
-   HChar *strtab;    /* string table */
+   HChar *strtab;            /* string table */
    HChar *stringbase;
    Addr *ptr;
    struct auxv *auxv;
    const struct auxv *orig_auxv;
    const struct auxv *cauxv;
-   unsigned stringsize;    /* total size of strings in bytes */
-   unsigned auxsize;    /* total size of auxv in bytes */
-   Int argc;         /* total argc */
-   Int envc;         /* total number of env vars */
-   unsigned stacksize;     /* total client stack size */
+   unsigned stringsize;      /* total size of strings in bytes */
+   unsigned auxsize;         /* total size of auxv in bytes */
+   Int argc;                 /* total argc */
+   Int envc;                 /* total number of env vars */
+   unsigned used_stacksize;  /* total used client stack size */
    Addr client_SP;           /* client stack base (initial SP) */
-   Addr clstack_start;
+   Addr clstack_start;       /* client_SP rounded down to nearest page */
    Int i;
    Bool have_exename;
    Word client_argv;
@@ -447,7 +463,7 @@ static Addr setup_client_stack(void*  init_sp,
 
    /* ...and the environment */
    envc = 0;
-   for (cpp = orig_envp; cpp && *cpp; cpp++) {
+   for (cpp = new_client_envp; cpp && *cpp; cpp++) {
       envc++;
       stringsize += VG_(strlen)(*cpp) + 1;
    }
@@ -494,7 +510,7 @@ static Addr setup_client_stack(void*  init_sp,
    }
 
    /* OK, now we know how big the client stack is */
-   stacksize =
+   used_stacksize =
       sizeof(Word) +                          /* argc */
       (have_exename ? sizeof(HChar **) : 0) +  /* argc[0] == exename */
       sizeof(HChar **)*argc +                 /* argv */
@@ -505,11 +521,11 @@ static Addr setup_client_stack(void*  init_sp,
       VG_ROUNDUP(stringsize, sizeof(Word));   /* strings (aligned) */
 
    if (0) {
-      VG_(printf)("stacksize = %u\n", stacksize);
+      VG_(printf)("stacksize = %u\n", used_stacksize);
    }
 
    /* client_SP is the client's stack pointer */
-   client_SP = clstack_end - stacksize;
+   client_SP = clstack_end - used_stacksize;
    client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */
 
    /* base of the string table (aligned) */
@@ -525,13 +541,31 @@ static Addr setup_client_stack(void*  init_sp,
       VG_(printf)("stringsize=%u auxsize=%u stacksize=%u maxsize=0x%lx\n"
                   "clstack_start %p\n"
                   "clstack_end   %p\n",
-                  stringsize, auxsize, stacksize, clstack_max_size,
+                  stringsize, auxsize, used_stacksize, clstack_max_size,
                   (void*)clstack_start, (void*)clstack_end);
    }
 
    /* ==================== allocate space ==================== */
 
+   /*
+   higher address +-----------------+ <- clstack_end    ^                ^
+                  | args env auxv   |                   |                |
+                  |   see above     |                   |                |
+    ower address  +-----------------+ <- client_SP   anon_size           |
+                  |  round to page  |                   |                |
+                  +-----------------+ <- clstack_start  |                |
+                  |    one page     |                   |           clstack_max_size
+                  +-----------------+ <- anon_start     v                |
+                  :                 :                   ^                |
+                  :      RSVN       :                resvn_size          |
+                  :                 :                   |                |
+                  +-----------------+ <- resvn_start    v                v
+
+   */
+
    {
+      // see comment in VG_(am_startup) about getting the maxssiz from
+      // the OS, not currently feasible with x86 on amd64
       SizeT anon_size   = clstack_end - clstack_start + 1;
       SizeT resvn_size  = clstack_max_size - anon_size;
       Addr  anon_start  = clstack_start;
@@ -568,7 +602,7 @@ static Addr setup_client_stack(void*  init_sp,
 #    endif
 
       if (0) {
-         VG_(printf)("%#lx 0x%lx  %#lx 0x%lx\n",
+         VG_(printf)("resvn_start %#lx resvn_size 0x%lx  anon_start %#lx anon_size 0x%lx\n",
                      resvn_start, resvn_size, anon_start, anon_size);
       }
 
@@ -638,7 +672,7 @@ static Addr setup_client_stack(void*  init_sp,
 
    /* --- envp --- */
    VG_(client_envp) = (HChar **)ptr;
-   for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++) {
+   for (cpp = new_client_envp; cpp && *cpp; ptr++, cpp++) {
       *ptr = (Addr)copy_str(&strtab, *cpp);
    }
    *ptr++ = 0;