JIT ARM: improve stack trace
Fix a problem at the boundary of DWARF-driven backtrace and frame-driver backtrace, as well as handling of the JIT's different internal calling conventions. Also, allow crossing back from frame-driven to DWARF-driven.
This commit is contained in:
parent
d9f7353d63
commit
55a66dc4cb
|
@ -330,76 +330,77 @@ Scheme_Object *scheme_native_stack_trace(void)
|
|||
&& STK_COMP(stack_start, (uintptr_t)p)))
|
||||
break;
|
||||
q = ((void **)p)[RETURN_ADDRESS_OFFSET];
|
||||
/* p is the frame pointer for the function called by q,
|
||||
not for q. */
|
||||
/* Except on PPC, p is the frame pointer for the function called
|
||||
by q, not for q. */
|
||||
}
|
||||
|
||||
name = find_symbol((uintptr_t)q);
|
||||
#ifdef MZ_USE_DWARF_LIBUNWIND
|
||||
if (name && !manual_unw) {
|
||||
if (name && !manual_unw)
|
||||
manual_unw = 1;
|
||||
# ifdef MZ_USE_JIT_ARM
|
||||
use_unw = 0;
|
||||
p = (void *)unw_get_frame_pointer(&c);
|
||||
if (!(STK_COMP((uintptr_t)p, stack_end)
|
||||
&& STK_COMP(stack_start, (uintptr_t)p)))
|
||||
break;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SCHEME_FALSEP(name) || SCHEME_VOIDP(name)) {
|
||||
/* Code uses special calling convention */
|
||||
#if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_ARM)
|
||||
/* JIT_LOCAL2 has the next return address */
|
||||
q = ((void **)p)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
|
||||
#endif
|
||||
#ifdef MZ_USE_JIT_I386
|
||||
# ifdef MZ_USE_DWARF_LIBUNWIND
|
||||
if (use_unw) {
|
||||
q = (void *)unw_get_frame_pointer(&c);
|
||||
} else
|
||||
# endif
|
||||
q = ((void **)p)[NEXT_FRAME_OFFSET];
|
||||
|
||||
/* q is now the frame pointer for the former q,
|
||||
so we can find the actual q */
|
||||
if (STK_COMP((uintptr_t)q, real_stack_end)
|
||||
&& STK_COMP(stack_start, (uintptr_t)q)) {
|
||||
if (SCHEME_VOIDP(name)) {
|
||||
/* JIT_LOCAL2 has the next return address */
|
||||
q = ((void **)q)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
|
||||
} else {
|
||||
/* Push after local stack of return-address proc
|
||||
has the next return address */
|
||||
q = ((void **)q)[-(3 + LOCAL_FRAME_SIZE + 1)];
|
||||
}
|
||||
} else {
|
||||
q = NULL;
|
||||
}
|
||||
#endif
|
||||
name = find_symbol((uintptr_t)q);
|
||||
} else if (SCHEME_EOFP(name)) {
|
||||
/* Stub (to mark start of running a module body, for example) */
|
||||
/* JIT_LOCAL2 has the name to use */
|
||||
#if defined(MZ_USE_JIT_PPC) || defined(MZ_USE_JIT_ARM)
|
||||
name = *(Scheme_Object **)((void **)p)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
|
||||
#endif
|
||||
#ifdef MZ_USE_JIT_I386
|
||||
/* The function `q' was reached through a lighter-weight
|
||||
internal ABI; we want the name of the function that
|
||||
called `q' */
|
||||
void *np;
|
||||
#ifdef MZ_USE_JIT_PPC
|
||||
np = p;
|
||||
#else
|
||||
/* Since `p' is the frame pointer for the function called
|
||||
by `q', so we need to step one more frame to look
|
||||
at the frame for `q': */
|
||||
# ifdef MZ_USE_DWARF_LIBUNWIND
|
||||
if (use_unw) {
|
||||
np = (void *)unw_get_frame_pointer(&c);
|
||||
} else
|
||||
# endif
|
||||
np = *(void **)p;
|
||||
np = ((void **)p)[NEXT_FRAME_OFFSET];
|
||||
/* `np' is now the frame pointer for `q',
|
||||
so we can find the actual `q' */
|
||||
#endif
|
||||
|
||||
if (STK_COMP((uintptr_t)np, real_stack_end)
|
||||
&& STK_COMP(stack_start, (uintptr_t)np)) {
|
||||
if (SCHEME_VOIDP(name)) {
|
||||
/* JIT_LOCAL2 has the next return address (always) */
|
||||
q = ((void **)np)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
|
||||
} else {
|
||||
#ifdef MZ_USE_JIT_I386
|
||||
/* Push after local stack of return-address proc
|
||||
has the next return address */
|
||||
q = ((void **)np)[-(3 + LOCAL_FRAME_SIZE + 1)];
|
||||
#else
|
||||
/* JIT_LOCAL2 has the next return address */
|
||||
q = ((void **)np)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
q = NULL;
|
||||
}
|
||||
name = find_symbol((uintptr_t)q);
|
||||
} else if (SCHEME_EOFP(name)) {
|
||||
/* Stub (to mark start of running a module body, for example);
|
||||
JIT_LOCAL2 has the name to use. */
|
||||
void *np;
|
||||
#ifdef MZ_USE_JIT_PPC
|
||||
np = p;
|
||||
#else
|
||||
/* Need to step a frame, as above. */
|
||||
# ifdef MZ_USE_DWARF_LIBUNWIND
|
||||
if (use_unw) {
|
||||
np = (void *)unw_get_frame_pointer(&c);
|
||||
} else
|
||||
# endif
|
||||
np = ((void **)p)[NEXT_FRAME_OFFSET];
|
||||
#endif
|
||||
|
||||
if (STK_COMP((uintptr_t)np, real_stack_end)
|
||||
&& STK_COMP(stack_start, (uintptr_t)np)) {
|
||||
name = *(Scheme_Object **)((void **)np)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
|
||||
} else
|
||||
name = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (name && !SCHEME_NULLP(name)) { /* null is used to help unwind without a true name */
|
||||
|
@ -438,7 +439,7 @@ Scheme_Object *scheme_native_stack_trace(void)
|
|||
}
|
||||
|
||||
prev_had_name = !!name;
|
||||
|
||||
|
||||
#ifdef MZ_USE_DWARF_LIBUNWIND
|
||||
if (use_unw) {
|
||||
if (manual_unw) {
|
||||
|
@ -448,9 +449,18 @@ Scheme_Object *scheme_native_stack_trace(void)
|
|||
if (!(STK_COMP((uintptr_t)pp, stack_end)
|
||||
&& STK_COMP(stack_start, (uintptr_t)pp)))
|
||||
break;
|
||||
# ifdef MZ_USE_JIT_ARM
|
||||
stack_addr = (unw_word_t)&(pp[JIT_NEXT_FP_OFFSET+2]);
|
||||
unw_manual_step(&c,
|
||||
&pp[RETURN_ADDRESS_OFFSET], &stack_addr,
|
||||
&pp[0], &pp[1], &pp[2], &pp[3],
|
||||
&pp[4], &pp[5], &pp[6], &pp[7],
|
||||
&pp[NEXT_FRAME_OFFSET]);
|
||||
# else
|
||||
stack_addr = (unw_word_t)&(pp[RETURN_ADDRESS_OFFSET+1]);
|
||||
unw_manual_step(&c, &pp[RETURN_ADDRESS_OFFSET], &pp[0],
|
||||
&stack_addr, &pp[-1], &pp[-2], &pp[-3]);
|
||||
# endif
|
||||
manual_unw = 0;
|
||||
} else {
|
||||
void *prev_q = q;
|
||||
|
|
|
@ -3231,6 +3231,7 @@ unw_word_t unw_get_frame_pointer(unw_cursor_t *c)
|
|||
return *(unw_word_t *)safe_pointer(((struct cursor *)c)->dwarf.loc[JIT_FRAME_POINTER_ID].val);
|
||||
}
|
||||
|
||||
#ifdef UNW_X86_64
|
||||
void unw_manual_step(unw_cursor_t *_c,
|
||||
void *ip_addr,
|
||||
void *bp_addr,
|
||||
|
@ -3255,5 +3256,37 @@ void unw_manual_step(unw_cursor_t *_c,
|
|||
c->dwarf.hint = 0;
|
||||
c->dwarf.prev_rs = 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef UNW_ARM
|
||||
void unw_manual_step(unw_cursor_t *_c,
|
||||
void *ip_addr,
|
||||
void *sp_addr,
|
||||
void *r0_addr, void *r1_addr, void *r2_addr, void *r3_addr,
|
||||
void *r4_addr, void *r5_addr, void *r6_addr, void *r7_addr,
|
||||
void *fp_addr)
|
||||
{
|
||||
struct cursor *c = (struct cursor *)_c;
|
||||
|
||||
c->dwarf.loc[0].val = (unw_word_t)r0_addr;
|
||||
c->dwarf.loc[1].val = (unw_word_t)r1_addr;
|
||||
c->dwarf.loc[2].val = (unw_word_t)r2_addr;
|
||||
c->dwarf.loc[3].val = (unw_word_t)r3_addr;
|
||||
c->dwarf.loc[4].val = (unw_word_t)r4_addr;
|
||||
c->dwarf.loc[5].val = (unw_word_t)r5_addr;
|
||||
c->dwarf.loc[6].val = (unw_word_t)r6_addr;
|
||||
c->dwarf.loc[7].val = (unw_word_t)r7_addr;
|
||||
|
||||
c->dwarf.loc[UNW_ARM_RIP].val = (unw_word_t)ip_addr;
|
||||
c->dwarf.loc[UNW_ARM_RSP].val = (unw_word_t)sp_addr;
|
||||
c->dwarf.loc[UNW_ARM_R11].val = (unw_word_t)fp_addr;
|
||||
|
||||
c->dwarf.ip = *(unw_word_t *)safe_pointer((unw_word_t)ip_addr);
|
||||
c->dwarf.cfa = *(unw_word_t *)safe_pointer((unw_word_t)sp_addr);
|
||||
c->dwarf.ret_addr_column = UNW_TDEP_IP;
|
||||
c->dwarf.pi_valid = 0;
|
||||
c->dwarf.hint = 0;
|
||||
c->dwarf.prev_rs = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -565,6 +565,7 @@ extern unw_word_t unw_get_ip(unw_cursor_t *);
|
|||
extern unw_word_t unw_get_frame_pointer(unw_cursor_t *);
|
||||
extern const char *unw_strerror (int);
|
||||
|
||||
#ifdef UNW_X86_64
|
||||
void unw_manual_step(unw_cursor_t *_c,
|
||||
void *ip_addr,
|
||||
void *bp_addr,
|
||||
|
@ -572,7 +573,16 @@ void unw_manual_step(unw_cursor_t *_c,
|
|||
void *bx_addr,
|
||||
void *r12_addr,
|
||||
void *r13_addr);
|
||||
|
||||
#endif
|
||||
#ifdef UNW_ARM
|
||||
void unw_manual_step(unw_cursor_t *_c,
|
||||
void *ip_addr,
|
||||
void *sp_addr,
|
||||
void *r0_addr, void *r1_addr, void *r2_addr, void *r3_addr,
|
||||
void *r4_addr, void *r5_addr, void *r6_addr, void *r7_addr,
|
||||
void *fp_addr);
|
||||
#endif
|
||||
|
||||
extern unw_addr_space_t unw_local_addr_space;
|
||||
|
||||
extern int unw_reset_bad_ptr_flag();
|
||||
|
|
Loading…
Reference in New Issue
Block a user