// 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
// 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;
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 ------------------------------------------
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,
| argv |
+-----------------+
| argc |
- lower address +-----------------+ <- sp
+ lower address +-----------------+ <- client_SP (return value)
| undefined |
: :
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,
{
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;
/* ...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;
}
}
/* 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 */
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) */
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;
# 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);
}
/* --- 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;