From e0e672e9cab4d879608a24913426fd6824b9b6b1 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Thu, 27 Nov 2008 19:32:55 +0000 Subject: [PATCH] finish x86_64+JIT backtrace support svn: r12624 --- src/mzscheme/src/jit.c | 95 ++++++++++++++++++++--------- src/mzscheme/src/unwind/libunwind.c | 27 +++++++- src/mzscheme/src/unwind/libunwind.h | 8 +++ 3 files changed, 99 insertions(+), 31 deletions(-) diff --git a/src/mzscheme/src/jit.c b/src/mzscheme/src/jit.c index 1317fdc418..959ec4e5ae 100644 --- a/src/mzscheme/src/jit.c +++ b/src/mzscheme/src/jit.c @@ -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); diff --git a/src/mzscheme/src/unwind/libunwind.c b/src/mzscheme/src/unwind/libunwind.c index 0e44dc1d26..15dcf15a6e 100644 --- a/src/mzscheme/src/unwind/libunwind.c +++ b/src/mzscheme/src/unwind/libunwind.c @@ -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 diff --git a/src/mzscheme/src/unwind/libunwind.h b/src/mzscheme/src/unwind/libunwind.h index 163814e5c1..fbb8f52f2d 100644 --- a/src/mzscheme/src/unwind/libunwind.h +++ b/src/mzscheme/src/unwind/libunwind.h @@ -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)