diff --git a/src/racket/sconfig.h b/src/racket/sconfig.h index d4b0e3e916..bf24573860 100644 --- a/src/racket/sconfig.h +++ b/src/racket/sconfig.h @@ -203,6 +203,7 @@ # define SIGSET_IS_SIGNAL # define SIGSET_NEEDS_REINSTALL +# define LINUX_FIND_STACK_BASE # define USE_DYNAMIC_FDSET_SIZE # define USE_TIMEZONE_VAR_W_DLS @@ -1307,6 +1308,9 @@ WINDOWS_FIND_STACK_BOUNDS figures out the maximum stack position under Windows (uses GC_find_stack_base()) MACOS_FIND_STACK_BOUNDS figures out the stack limit on the Mac. + LINUX_FIND_STACK_BASE figures out the stack base under Linux + by reading from /proc/self/maps and looking for "[stack]" + line. ASSUME_FIXED_STACK_SIZE assumes that the main stack size is always FIXED_STACK_SIZE. Use only one of these if DO_STACK_CHECK is used, or none otherwise. */ diff --git a/src/racket/src/eval.c b/src/racket/src/eval.c index de3737ba7f..3847000fba 100644 --- a/src/racket/src/eval.c +++ b/src/racket/src/eval.c @@ -426,6 +426,54 @@ scheme_handle_stack_overflow(Scheme_Object *(*k)(void)) return NULL; /* never gets here */ } +#ifdef LINUX_FIND_STACK_BASE +uintptr_t adjust_stack_base(uintptr_t bnd) { + if (bnd == scheme_get_primordial_thread_stack_base()) { + /* The address `base' might be far from the actual stack base + if Exec Sheild is enabled. Use "/proc/self/maps" to get + exacty the stack base. */ + FILE *f; + char *buf; + f = fopen("/proc/self/maps", "r"); + if (f) { + buf = malloc(256); + while (fgets(buf, 256, f)) { + int len; + len = strlen(buf); + if ((len > 8) && !strcmp("[stack]\n", buf + len - 8)) { + uintptr_t p = 0; + int i; + /* find separator: */ + for (i = 0; buf[i]; i++) { + if (buf[i] == '-') { + i++; + break; + } + } + /* parse number after separator: */ + for (; buf[i]; i++) { + if ((buf[i] >= '0') && (buf[i] <= '9')) { + p = (p << 4) | (buf[i] - '0'); + } else if ((buf[i] >= 'a') && (buf[i] <= 'f')) { + p = (p << 4) | (buf[i] - 'a' + 10); + } else if ((buf[i] >= 'A') && (buf[i] <= 'F')) { + p = (p << 4) | (buf[i] - 'A' + 10); + } else + break; + } + /* printf("%p vs. %p: %d\n", (void*)bnd, (void*)p, p - bnd); */ + return p; + } + } + free(buf); + fclose(f); + } + } + + return bnd; +} +#endif + void scheme_init_stack_check() /* Finds the C stack limit --- platform-specific. */ { @@ -503,6 +551,10 @@ void scheme_init_stack_check() uintptr_t bnd, lim; bnd = (uintptr_t)scheme_get_current_os_thread_stack_base(); +# ifdef LINUX_FIND_STACK_BASE + bnd = adjust_stack_base(bnd); +# endif + lim = (uintptr_t)rl.rlim_cur; # ifdef UNIX_STACK_MAXIMUM if (lim > UNIX_STACK_MAXIMUM) diff --git a/src/racket/src/salloc.c b/src/racket/src/salloc.c index 9f420397ed..4bbb4fbd06 100644 --- a/src/racket/src/salloc.c +++ b/src/racket/src/salloc.c @@ -74,7 +74,7 @@ int scheme_thread_local_offset = 0; #endif extern int scheme_num_copied_stacks; -SHARED_OK static uintptr_t scheme_primordial_os_thread_stack_base; +SHARED_OK static uintptr_t primordial_os_thread_stack_base; THREAD_LOCAL_DECL(static uintptr_t scheme_os_thread_stack_base); #ifdef USE_THREAD_LOCAL SHARED_OK Thread_Local_Variables *scheme_vars; /* for debugging */ @@ -118,8 +118,8 @@ void scheme_set_stack_base(void *base, int no_auto_statics) XFORM_SKIP_PROC scheme_register_traversers(); #endif - scheme_primordial_os_thread_stack_base = (uintptr_t) base; - scheme_os_thread_stack_base = (uintptr_t) base; + primordial_os_thread_stack_base = (uintptr_t) base; + scheme_os_thread_stack_base = (uintptr_t) base; #if defined(MZ_PRECISE_GC) || defined(USE_SENORA_GC) GC_set_stack_base(base); @@ -152,6 +152,11 @@ uintptr_t scheme_get_current_os_thread_stack_base() return scheme_os_thread_stack_base; } +uintptr_t scheme_get_primordial_thread_stack_base() +{ + return primordial_os_thread_stack_base; +} + typedef struct { Scheme_Env_Main _main; int argc; diff --git a/src/racket/src/schpriv.h b/src/racket/src/schpriv.h index 6851da0061..cd86638035 100644 --- a/src/racket/src/schpriv.h +++ b/src/racket/src/schpriv.h @@ -130,7 +130,8 @@ int scheme_num_types(void); void scheme_reset_finalizations(void); -extern uintptr_t scheme_get_current_os_thread_stack_base(void); +uintptr_t scheme_get_primordial_thread_stack_base(void); +uintptr_t scheme_get_current_os_thread_stack_base(void); void scheme_set_current_os_thread_stack_base(void *base); int scheme_propagate_ephemeron_marks(void);