From 84ffa34efda511974bce59e594cdfc3781d7f4f9 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 28 Nov 2008 14:07:11 +0000 Subject: [PATCH] safer x86_64 backtrace svn: r12630 --- src/mzscheme/src/jit.c | 8 +++++- src/mzscheme/src/unwind/libunwind.c | 35 ++++++++++++++++++++++++--- src/mzscheme/src/unwind/libunwind.h | 3 +++ src/mzscheme/src/unwind/libunwind_i.h | 10 +++++--- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/mzscheme/src/jit.c b/src/mzscheme/src/jit.c index 959ec4e5ae..127dd82e39 100644 --- a/src/mzscheme/src/jit.c +++ b/src/mzscheme/src/jit.c @@ -8178,6 +8178,11 @@ Scheme_Object *scheme_native_stack_trace(void) tail = scheme_null; } +#ifdef MZ_USE_DWARF_LIBUNWIND + unw_set_safe_pointer_range(stack_start, stack_end); + unw_reset_bad_ptr_flag(); +#endif + halfway = STK_DIFF(stack_end, (unsigned long)p) / 2; if (halfway < CACHE_STACK_MIN_TRIGGER) halfway = stack_end; @@ -8306,7 +8311,8 @@ Scheme_Object *scheme_native_stack_trace(void) void *prev_q = q; unw_step(&c); q = (void *)unw_get_ip(&c); - if (q == prev_q) + if ((q == prev_q) + || unw_reset_bad_ptr_flag()) break; } } diff --git a/src/mzscheme/src/unwind/libunwind.c b/src/mzscheme/src/unwind/libunwind.c index 15dcf15a6e..55a687bfcc 100644 --- a/src/mzscheme/src/unwind/libunwind.c +++ b/src/mzscheme/src/unwind/libunwind.c @@ -2462,6 +2462,35 @@ int unw_step (unw_cursor_t *c) return dwarf_step(&((struct cursor *)c)->dwarf); } +static int saw_bad_ptr = 0; +static char safe_space[8]; +static unw_word_t safe_start_address, safe_end_address; + +void unw_set_safe_pointer_range(unw_word_t s, unw_word_t e) +{ + safe_start_address = s; + safe_end_address = e; +} + +int unw_reset_bad_ptr_flag() +{ + int v = saw_bad_ptr; + saw_bad_ptr = 0; + return v; +} + +static void *safe_pointer(unw_word_t p) +{ + if (safe_start_address != safe_end_address) + if ((p < safe_start_address) + || (p >= safe_end_address)) { + saw_bad_ptr = 1; + return safe_space; + } + + return (void *)p; +} + #if UNW_DEBUG int unwi_debug_level = 100; #endif @@ -2473,7 +2502,7 @@ unw_word_t unw_get_ip(unw_cursor_t *c) unw_word_t unw_get_frame_pointer(unw_cursor_t *c) { - return *(unw_word_t *)((struct cursor *)c)->dwarf.loc[6 /* = BP */].val; + return *(unw_word_t *)safe_pointer(((struct cursor *)c)->dwarf.loc[6 /* = BP */].val); } void unw_manual_step(unw_cursor_t *_c, @@ -2493,8 +2522,8 @@ void unw_manual_step(unw_cursor_t *_c, 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.ip = *(unw_word_t *)safe_pointer(ip_addr); + c->dwarf.cfa = *(unw_word_t *)safe_pointer(sp_addr); c->dwarf.ret_addr_column = RIP; c->dwarf.pi_valid = 0; c->dwarf.hint = 0; diff --git a/src/mzscheme/src/unwind/libunwind.h b/src/mzscheme/src/unwind/libunwind.h index fbb8f52f2d..504b9b4b5b 100644 --- a/src/mzscheme/src/unwind/libunwind.h +++ b/src/mzscheme/src/unwind/libunwind.h @@ -476,6 +476,9 @@ void unw_manual_step(unw_cursor_t *_c, extern unw_addr_space_t unw_local_addr_space; +extern int unw_reset_bad_ptr_flag(); +extern void unw_set_safe_pointer_range(unw_word_t s, unw_word_t e); + #define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) extern int unw_tdep_is_fpreg (int); diff --git a/src/mzscheme/src/unwind/libunwind_i.h b/src/mzscheme/src/unwind/libunwind_i.h index e0357716e3..5457d6acc7 100644 --- a/src/mzscheme/src/unwind/libunwind_i.h +++ b/src/mzscheme/src/unwind/libunwind_i.h @@ -695,12 +695,14 @@ struct cursor # define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ tdep_uc_addr((c)->as_arg, (r)), 0)) +static void *safe_pointer(unw_word_t); + static inline int dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) { if (!DWARF_GET_LOC (loc)) return -1; - *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc); + *val = *(unw_fpreg_t *) safe_pointer(DWARF_GET_LOC (loc)); return 0; } @@ -709,7 +711,7 @@ dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) { if (!DWARF_GET_LOC (loc)) return -1; - *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val; + *(unw_fpreg_t *) safe_pointer(DWARF_GET_LOC (loc)) = val; return 0; } @@ -718,7 +720,7 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) { if (!DWARF_GET_LOC (loc)) return -1; - *val = *(unw_word_t *) DWARF_GET_LOC (loc); + *val = *(unw_word_t *) safe_pointer(DWARF_GET_LOC (loc)); return 0; } @@ -727,7 +729,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) { if (!DWARF_GET_LOC (loc)) return -1; - *(unw_word_t *) DWARF_GET_LOC (loc) = val; + *(unw_word_t *) safe_pointer(DWARF_GET_LOC (loc)) = val; return 0; }