finish x86_64+JIT backtrace support

svn: r12624
This commit is contained in:
Matthew Flatt 2008-11-27 19:32:55 +00:00
parent ca45e93763
commit e0e672e9ca
3 changed files with 99 additions and 31 deletions

View File

@ -2327,6 +2327,15 @@ static void register_sub_func(mz_jit_state *jitter, void *code, Scheme_Object *p
add_symbol((unsigned long)code, (unsigned long)code_end - 1, protocol, 0);
}
static void register_helper_func(mz_jit_state *jitter, void *code)
{
#ifdef MZ_USE_DWARF_LIBUNWIND
/* Null indicates that there's no function name to report, but the
stack should be unwound manually using the JJIT-generated convention. */
register_sub_func(jitter, code, scheme_null);
#endif
}
int do_generate_shared_call(mz_jit_state *jitter, void *_data)
{
Generate_Call_Data *data = (Generate_Call_Data *)_data;
@ -2336,10 +2345,19 @@ int do_generate_shared_call(mz_jit_state *jitter, void *_data)
#endif
if (data->is_tail) {
int ok;
void *code;
code = jit_get_ip().ptr;
if (data->direct_prim)
return generate_direct_prim_tail_call(jitter, data->num_rands);
ok = generate_direct_prim_tail_call(jitter, data->num_rands);
else
return generate_tail_call(jitter, data->num_rands, data->direct_native, 1);
ok = generate_tail_call(jitter, data->num_rands, data->direct_native, 1);
register_helper_func(jitter, code);
return ok;
} else {
int ok;
void *code;
@ -6721,6 +6739,7 @@ static int do_generate_common(mz_jit_state *jitter, void *_data)
mz_pop_locals();
jit_ret();
CHECK_LIMIT();
register_helper_func(jitter, on_demand_jit_code);
/* *** app_values_tail_slow_code *** */
/* RELIES ON jit_prolog(3) FROM ABOVE */
@ -6742,9 +6761,11 @@ static int do_generate_common(mz_jit_state *jitter, void *_data)
finish_tail_call_code = jit_get_ip().ptr;
generate_finish_tail_call(jitter, 0);
CHECK_LIMIT();
register_helper_func(jitter, finish_tail_call_code);
finish_tail_call_fixup_code = jit_get_ip().ptr;
generate_finish_tail_call(jitter, 2);
CHECK_LIMIT();
register_helper_func(jitter, finish_tail_call_fixup_code);
/* *** get_stack_pointer_code *** */
get_stack_pointer_code = jit_get_ip().ptr;
@ -7614,6 +7635,10 @@ static void on_demand_generate_lambda(Scheme_Native_Closure *nc)
if (data->name) {
add_symbol((unsigned long)code, (unsigned long)gdata.code_end - 1, data->name, 1);
} else {
#ifdef MZ_USE_DWARF_LIBUNWIND
add_symbol((unsigned long)code, (unsigned long)gdata.code_end - 1, scheme_null, 1);
#endif
}
has_rest = ((SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_REST) ? 1 : 0);
@ -8118,6 +8143,8 @@ Scheme_Object *scheme_native_stack_trace(void)
#ifdef MZ_USE_DWARF_LIBUNWIND
unw_context_t cx;
unw_cursor_t c;
int manual_unw;
unw_word_t stack_addr;
#else
Get_Stack_Proc gs;
#endif
@ -8176,18 +8203,15 @@ Scheme_Object *scheme_native_stack_trace(void)
&& STK_COMP(stack_start, (unsigned long)p)))
break;
q = ((void **)p)[RETURN_ADDRESS_OFFSET];
/* p is the frame pointer for the function called by q,
not for q. */
}
name = find_symbol((unsigned long)q);
#ifdef MZ_USE_DWARF_LIBUNWIND
if (name && use_unw) {
use_unw = 0;
p = (void *)unw_get_frame_pointer(&c);
if (!(STK_COMP((unsigned long)p, stack_end)
&& STK_COMP(stack_start, (unsigned long)p)))
break;
}
if (name) manual_unw = 1;
#endif
if (SCHEME_FALSEP(name) || SCHEME_VOIDP(name)) {
/* Code uses special calling convention */
#ifdef MZ_USE_JIT_PPC
@ -8195,30 +8219,34 @@ Scheme_Object *scheme_native_stack_trace(void)
q = ((void **)p)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
#endif
#ifdef MZ_USE_JIT_I386
if (SCHEME_VOIDP(name)) {
/* JIT_LOCAL2 has the next return address */
q = *(void **)p;
if (STK_COMP((unsigned long)q, stack_end)
&& STK_COMP(stack_start, (unsigned long)q)) {
q = ((void **)q)[JIT_LOCAL2 >> JIT_LOG_WORD_SIZE];
} else
q = NULL;
# ifdef MZ_USE_DWARF_LIBUNWIND
if (use_unw) {
q = (void *)unw_get_frame_pointer(&c);
} else
# endif
q = *(void **)p;
/* q is now the frame pointer for the former q,
so we can find the actual q */
if (STK_COMP((unsigned long)q, stack_end)
&& STK_COMP(stack_start, (unsigned long)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 {
/* Push after local stack of return-address proc
has the next return address */
q = *(void **)p;
if (STK_COMP((unsigned long)q, stack_end)
&& STK_COMP(stack_start, (unsigned long)q)) {
q = ((void **)q)[-(3 + LOCAL_FRAME_SIZE + 1)];
} else {
q = NULL;
}
q = NULL;
}
#endif
name = find_symbol((unsigned long)q);
}
if (name) {
if (name && !SCHEME_NULLP(name)) { /* null is used to help unwind without a true name */
name = scheme_make_pair(name, scheme_null);
if (last)
SCHEME_CDR(last) = name;
@ -8263,10 +8291,17 @@ Scheme_Object *scheme_native_stack_trace(void)
#ifdef MZ_USE_DWARF_LIBUNWIND
if (use_unw) {
if (name) {
if (manual_unw) {
/* A JIT-generated function, so we unwind ourselves... */
/* For now, once we cross into JIT world, stay there. */
use_unw = 0;
void **pp;
pp = (void **)unw_get_frame_pointer(&c);
if (!(STK_COMP((unsigned long)pp, stack_end)
&& STK_COMP(stack_start, (unsigned long)pp)))
break;
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]);
manual_unw = 0;
} else {
void *prev_q = q;
unw_step(&c);

View File

@ -2473,7 +2473,32 @@ unw_word_t unw_get_ip(unw_cursor_t *c)
unw_word_t unw_get_frame_pointer(unw_cursor_t *c)
{
return ((struct cursor *)c)->dwarf.loc[6].val;
return *(unw_word_t *)((struct cursor *)c)->dwarf.loc[6 /* = BP */].val;
}
void unw_manual_step(unw_cursor_t *_c,
void *ip_addr,
void *bp_addr,
void *sp_addr,
void *bx_addr,
void *r12_addr,
void *r13_addr)
{
struct cursor *c = (struct cursor *)_c;
c->dwarf.loc[3].val = (unw_word_t)bx_addr;
c->dwarf.loc[6].val = (unw_word_t)bp_addr;
c->dwarf.loc[7].val = (unw_word_t)sp_addr;
c->dwarf.loc[12].val = (unw_word_t)r12_addr;
c->dwarf.loc[13].val = (unw_word_t)r13_addr;
c->dwarf.loc[16].val = (unw_word_t)ip_addr;
c->dwarf.ip = *(unw_word_t *)ip_addr;
c->dwarf.cfa = *(unw_word_t *)sp_addr;
c->dwarf.ret_addr_column = RIP;
c->dwarf.pi_valid = 0;
c->dwarf.hint = 0;
c->dwarf.prev_rs = 0;
}
#endif

View File

@ -466,6 +466,14 @@ 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);
void unw_manual_step(unw_cursor_t *_c,
void *ip_addr,
void *bp_addr,
void *sp_addr,
void *bx_addr,
void *r12_addr,
void *r13_addr);
extern unw_addr_space_t unw_local_addr_space;
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)