mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-03-10 07:00:20 -07:00
stacks: move C shadow stack to a separate structure
This commit is contained in:
parent
593d9d2190
commit
45f3be3aa1
4 changed files with 49 additions and 51 deletions
|
|
@ -34,7 +34,7 @@ cs_set_size(cl_env_ptr env, cl_index new_size)
|
|||
struct rlimit rl;
|
||||
|
||||
if (!getrlimit(RLIMIT_STACK, &rl)) {
|
||||
env->cs_max_size = rl.rlim_max;
|
||||
env->c_stack.max_size = rl.rlim_max;
|
||||
if (new_size > rl.rlim_cur) {
|
||||
rl.rlim_cur = (new_size > rl.rlim_max) ? rl.rlim_max : new_size;
|
||||
if (setrlimit(RLIMIT_STACK, &rl))
|
||||
|
|
@ -52,29 +52,29 @@ cs_set_size(cl_env_ptr env, cl_index new_size)
|
|||
new_size = rl.rlim_cur;
|
||||
}
|
||||
#ifdef ECL_DOWN_STACK
|
||||
env->cs_barrier = env->cs_org - new_size;
|
||||
env->c_stack.max = env->c_stack.org - new_size;
|
||||
#else
|
||||
env->cs_barrier = env->cs_org + new_size;
|
||||
env->c_stack.max = env->c_stack.org + new_size;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
env->cs_limit_size = new_size - (2*margin);
|
||||
env->c_stack.limit_size = new_size - (2*margin);
|
||||
#ifdef ECL_DOWN_STACK
|
||||
if (&foo > (env->cs_org - new_size) + 16) {
|
||||
env->cs_limit = (env->cs_org - new_size) + (2*margin);
|
||||
if (env->cs_limit < env->cs_barrier)
|
||||
env->cs_barrier = env->cs_limit;
|
||||
if (&foo > (env->c_stack.org - new_size) + 16) {
|
||||
env->c_stack.limit = (env->c_stack.org - new_size) + (2*margin);
|
||||
if (env->c_stack.limit < env->c_stack.max)
|
||||
env->c_stack.max = env->c_stack.limit;
|
||||
}
|
||||
#else
|
||||
if (&foo < (env->cs_org + new_size) - 16) {
|
||||
env->cs_limit = (env->cs_org + new_size) - (2*margin);
|
||||
if (env->cs_limit > env->cs_barrier)
|
||||
env->cs_barrier = env->cs_limit;
|
||||
if (&foo < (env->c_stack.org + new_size) - 16) {
|
||||
env->c_stack.limit = (env->c_stack.org + new_size) - (2*margin);
|
||||
if (env->c_stack.limit > env->c_stack.max)
|
||||
env->c_stack.max = env->c_stack.limit;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ecl_internal_error("Can't set the size of the C stack: sanity check failed");
|
||||
env->cs_size = new_size;
|
||||
env->c_stack.size = new_size;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -86,18 +86,18 @@ ecl_cs_overflow(void)
|
|||
";;;\n\n";
|
||||
cl_env_ptr env = ecl_process_env();
|
||||
cl_index margin = ecl_option_values[ECL_OPT_C_STACK_SAFETY_AREA];
|
||||
cl_index size = env->cs_size;
|
||||
cl_index size = env->c_stack.size;
|
||||
#ifdef ECL_DOWN_STACK
|
||||
if (env->cs_limit > env->cs_org - size)
|
||||
env->cs_limit -= margin;
|
||||
if (env->c_stack.limit > env->c_stack.org - size)
|
||||
env->c_stack.limit -= margin;
|
||||
#else
|
||||
if (env->cs_limit < env->cs_org + size)
|
||||
env->cs_limit += margin;
|
||||
if (env->c_stack.limit < env->c_stack.org + size)
|
||||
env->c_stack.limit += margin;
|
||||
#endif
|
||||
else
|
||||
ecl_unrecoverable_error(env, stack_overflow_msg);
|
||||
|
||||
if (env->cs_max_size == (cl_index)0 || env->cs_size < env->cs_max_size)
|
||||
if (env->c_stack.max_size == (cl_index)0 || env->c_stack.size < env->c_stack.max_size)
|
||||
si_serror(6, @"Extend stack size",
|
||||
@'ext::stack-overflow',
|
||||
@':size', ecl_make_fixnum(size),
|
||||
|
|
@ -108,8 +108,8 @@ ecl_cs_overflow(void)
|
|||
@':size', ECL_NIL,
|
||||
@':type', @'ext::c-stack');
|
||||
size += size/2;
|
||||
if (size > env->cs_max_size)
|
||||
size = env->cs_max_size;
|
||||
if (size > env->c_stack.max_size)
|
||||
size = env->c_stack.max_size;
|
||||
cs_set_size(env, size);
|
||||
}
|
||||
|
||||
|
|
@ -119,17 +119,17 @@ ecl_cs_set_org(cl_env_ptr env)
|
|||
#ifdef GBC_BOEHM
|
||||
struct GC_stack_base base;
|
||||
if (GC_get_stack_base(&base) == GC_SUCCESS)
|
||||
env->cs_org = (char*)base.mem_base;
|
||||
env->c_stack.org = (char*)base.mem_base;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Rough estimate. Not very safe. We assume that cl_boot()
|
||||
* is invoked from the main() routine of the program.
|
||||
*/
|
||||
env->cs_org = (char*)(&env);
|
||||
env->c_stack.org = (char*)(&env);
|
||||
}
|
||||
env->cs_barrier = env->cs_org;
|
||||
env->cs_max_size = 0;
|
||||
env->c_stack.max = env->c_stack.org;
|
||||
env->c_stack.max_size = 0;
|
||||
cs_set_size(env, ecl_option_values[ECL_OPT_C_STACK_SIZE]);
|
||||
}
|
||||
|
||||
|
|
@ -833,7 +833,7 @@ si_get_limit(cl_object type)
|
|||
else if (type == @'ext::binding-stack')
|
||||
output = env->bds_stack.limit_size;
|
||||
else if (type == @'ext::c-stack')
|
||||
output = env->cs_limit_size;
|
||||
output = env->c_stack.limit_size;
|
||||
else if (type == @'ext::lisp-stack')
|
||||
output = env->stack_limit_size;
|
||||
else if (type == @'ext::heap-size') {
|
||||
|
|
@ -853,7 +853,7 @@ si_reset_margin(cl_object type)
|
|||
else if (type == @'ext::binding-stack')
|
||||
ecl_bds_set_size(env, env->bds_stack.size);
|
||||
else if (type == @'ext::c-stack')
|
||||
cs_set_size(env, env->cs_size);
|
||||
cs_set_size(env, env->c_stack.size);
|
||||
else
|
||||
ecl_return1(env, ECL_NIL);
|
||||
|
||||
|
|
|
|||
|
|
@ -829,16 +829,16 @@ handler_fn_prototype(sigsegv_handler, int sig, siginfo_t *info, void *aux)
|
|||
# endif /* ECL_USE_MPROTECT */
|
||||
# ifdef ECL_DOWN_STACK
|
||||
if (sig == SIGSEGV &&
|
||||
(char*)info->si_addr > the_env->cs_barrier &&
|
||||
(char*)info->si_addr <= the_env->cs_org) {
|
||||
(char*)info->si_addr > the_env->c_stack.max &&
|
||||
(char*)info->si_addr <= the_env->c_stack.org) {
|
||||
unblock_signal(the_env, sig);
|
||||
ecl_unrecoverable_error(the_env, stack_overflow_msg);
|
||||
return;
|
||||
}
|
||||
# else
|
||||
if (sig == SIGSEGV &&
|
||||
(char*)info->si_addr < the_env->cs_barrier &&
|
||||
(char*)info->si_addr >= the_env->cs_org) {
|
||||
(char*)info->si_addr < the_env->c_stack.max &&
|
||||
(char*)info->si_addr >= the_env->c_stack.org) {
|
||||
unblock_signal(the_env, sig);
|
||||
ecl_unrecoverable_error(the_env, stack_overflow_msg);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,21 @@ struct ecl_history_stack {
|
|||
struct ecl_ihs_frame *top;
|
||||
};
|
||||
|
||||
/* The following pointers to the C Stack are used to ensure that a recursive
|
||||
* function does not enter an infinite loop and exhausts all memory. They will
|
||||
* eventually disappear, because most operating systems already take care of
|
||||
* this. */
|
||||
struct ecl_c_stack {
|
||||
cl_index max_size; /* maximum possible size */
|
||||
|
||||
cl_index size; /* current size */
|
||||
cl_index limit_size; /* maximum size minus safety area */
|
||||
char *org; /* origin address */
|
||||
char *max; /* overflow address (real maximum address) */
|
||||
char *limit; /* overflow address (spares recovery area) */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Per-thread data.
|
||||
*/
|
||||
|
|
@ -78,24 +93,7 @@ struct cl_env_struct {
|
|||
struct ecl_binding_stack bds_stack;
|
||||
struct ecl_frames_stack frs_stack;
|
||||
struct ecl_history_stack ihs_stack;
|
||||
|
||||
/*
|
||||
* The following pointers to the C Stack are used to ensure that a
|
||||
* recursive function does not enter an infinite loop and exhausts all
|
||||
* memory. They will eventually disappear, because most operating
|
||||
* systems already take care of this.
|
||||
*/
|
||||
cl_index cs_size; /* current size */
|
||||
cl_index cs_limit_size; /* current size minus safety area */
|
||||
cl_index cs_max_size; /* maximum possible size */
|
||||
char *cs_org; /* origin address */
|
||||
char *cs_limit; /* limit address; if the stack pointer
|
||||
goes beyond this value, a stack
|
||||
overflow will be signaled ... */
|
||||
char *cs_barrier; /* ... but the area up to cs_barrier
|
||||
is still available to allow
|
||||
programs to recover from the
|
||||
stack overflow */
|
||||
struct ecl_c_stack c_stack;
|
||||
|
||||
/* Private variables used by different parts of ECL: */
|
||||
/* ... the reader and printer ... */
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ extern "C" {
|
|||
|
||||
#ifdef ECL_DOWN_STACK
|
||||
#define ecl_cs_check(env,var) \
|
||||
if (ecl_unlikely((char*)(&var) <= (env)->cs_limit)) ecl_cs_overflow()
|
||||
if (ecl_unlikely((char*)(&var) <= (env)->c_stack.limit)) ecl_cs_overflow()
|
||||
#else
|
||||
#define ecl_cs_check(env,var) \
|
||||
if (ecl_unlikely((char*)(&var) >= (env)->cs_limit)) ecl_cs_overflow()
|
||||
if (ecl_unlikely((char*)(&var) >= (env)->c_stack.limit)) ecl_cs_overflow()
|
||||
#endif
|
||||
|
||||
/*********************************************************
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue