fix native stack traversal for stack dumps

When caching the result of a stack traversal, adjust
the actual stack only after the traversal is complete
to avoid interfering with libunwind's decoding of the
stack.
This commit is contained in:
Matthew Flatt 2016-12-09 06:21:41 -07:00
parent 2b3128cdb4
commit 7812c604f4
2 changed files with 19 additions and 10 deletions

View File

@ -1461,7 +1461,8 @@ typedef struct {
static void jit_register_sub_func(mz_jit_state *jitter, void *code, Scheme_Object *protocol, int gcable)
/* protocol: #f => normal lightweight call protocol
void => next return address is in LOCAL2
eof => name to use is in LOCAL2 */
eof => name to use is in LOCAL2
null => no name, but usual frame */
{
void *code_end;
@ -1482,7 +1483,7 @@ void scheme_jit_register_helper_func(mz_jit_state *jitter, void *code, int gcabl
{
#if defined(MZ_USE_DWARF_LIBUNWIND) || defined(_WIN64)
/* Null indicates that there's no function name to report, but the
stack should be unwound manually using the JJIT-generated convention. */
stack should be unwound manually using the JIT-generated convention. */
jit_register_sub_func(jitter, code, scheme_null, gcable);
#endif
}

View File

@ -161,9 +161,9 @@ static void set_cache(void *p, Scheme_Object *last)
Scheme_Object *scheme_native_stack_trace(void)
{
void *p, *q, *cache_frame_p;
void *p, *q, *cache_frame_p, *set_cache_sp = NULL;
uintptr_t stack_end, real_stack_end, stack_start, halfway;
Scheme_Object *name, *last = NULL, *first = NULL, *tail;
Scheme_Object *name, *last = NULL, *first = NULL, *tail, *set_cache_last = NULL;
int cache_had_name = 0;
#ifdef MZ_USE_DWARF_LIBUNWIND
unw_context_t cx;
@ -200,7 +200,7 @@ Scheme_Object *scheme_native_stack_trace(void)
#ifdef MZ_USE_DWARF_LIBUNWIND
unw_getcontext(&cx);
unw_init_local(&c, &cx);
unw_set_safe_pointer_range(&c, stack_start, stack_end);
unw_set_safe_pointer_range(&c, stack_start, real_stack_end);
use_unw = 1;
p = NULL;
#else
@ -296,7 +296,8 @@ Scheme_Object *scheme_native_stack_trace(void)
if (cache_sp) {
if (STK_COMP((uintptr_t)halfway, (uintptr_t)cache_sp)) {
set_cache(cache_sp, last);
set_cache_sp = cache_sp;
set_cache_last = last;
if (!name)
shift_cache_to_next = 1;
halfway = stack_end;
@ -313,7 +314,10 @@ Scheme_Object *scheme_native_stack_trace(void)
}
if (shift_cache_to_next)
stack_cache_stack[stack_cache_stack_pos].cache = tail;
set_cache_last = tail;
if (set_cache_sp)
set_cache(set_cache_sp, set_cache_last);
if (last)
SCHEME_CDR(last) = tail;
@ -438,7 +442,7 @@ Scheme_Object *scheme_native_stack_trace(void)
first = name;
last = name;
if (shift_cache_to_next) {
stack_cache_stack[stack_cache_stack_pos].cache = last;
set_cache_last = last;
shift_cache_to_next = 0;
}
added_list_elem = 1;
@ -458,7 +462,8 @@ Scheme_Object *scheme_native_stack_trace(void)
it will use the return address from the stack. */
if (STK_COMP((uintptr_t)halfway, (uintptr_t)cache_frame_p)
&& cache_had_name) {
set_cache(cache_frame_p, last);
set_cache_sp = cache_frame_p;
set_cache_last = last;
if (!added_list_elem)
shift_cache_to_next = 1;
halfway = stack_end;
@ -509,7 +514,10 @@ Scheme_Object *scheme_native_stack_trace(void)
}
if (shift_cache_to_next)
stack_cache_stack[stack_cache_stack_pos].cache = tail;
set_cache_last = tail;
if (set_cache_sp)
set_cache(set_cache_sp, set_cache_last);
#ifdef MZ_USE_DWARF_LIBUNWIND
unw_destroy_local(&c);