diff --git a/.gitignore b/.gitignore index 36c3b61d..120b5553 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,4 @@ tests/test-proc-info tests/test-ptrace-misc tests/test-varargs tests/test-static-link +tests/[GL]test-trace diff --git a/include/libunwind-arm.h b/include/libunwind-arm.h index be9e59ab..a764b155 100644 --- a/include/libunwind-arm.h +++ b/include/libunwind-arm.h @@ -297,7 +297,7 @@ unw_tdep_frame_t; #define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) extern int unw_tdep_is_fpreg (int); -#define unw_tdep_trace(cur,addr,n,c) (-UNW_ENOINFO) +#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO) #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/libunwind-common.h.in b/include/libunwind-common.h.in index 26048c62..2fb78e8e 100644 --- a/include/libunwind-common.h.in +++ b/include/libunwind-common.h.in @@ -228,7 +228,6 @@ unw_save_loc_t; #define unw_regname UNW_ARCH_OBJ(regname) #define unw_flush_cache UNW_ARCH_OBJ(flush_cache) #define unw_strerror UNW_ARCH_OBJ(strerror) -#define unw_backtrace UNW_OBJ(backtrace) extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int); extern void unw_destroy_addr_space (unw_addr_space_t); @@ -254,6 +253,4 @@ extern int unw_handle_signal_frame (unw_cursor_t *); extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); extern const char *unw_strerror (int); -extern int unw_backtrace (void **buffer, int size); - extern unw_addr_space_t unw_local_addr_space; diff --git a/include/libunwind-hppa.h b/include/libunwind-hppa.h index 8c8a0590..04eacee5 100644 --- a/include/libunwind-hppa.h +++ b/include/libunwind-hppa.h @@ -124,7 +124,7 @@ unw_tdep_proc_info_t; #define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext) extern int unw_tdep_getcontext (unw_tdep_context_t *); -#define unw_tdep_trace(cur,addr,n,c) (-UNW_ENOINFO) +#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO) #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/libunwind-ia64.h b/include/libunwind-ia64.h index 86808d5c..72480d24 100644 --- a/include/libunwind-ia64.h +++ b/include/libunwind-ia64.h @@ -193,7 +193,7 @@ extern unw_word_t _Uia64_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *, signal-safe. */ extern int _Uia64_get_kernel_table (unw_dyn_info_t *); -#define unw_tdep_trace(cur,addr,n,c) (-UNW_ENOINFO) +#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO) #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/libunwind-mips.h b/include/libunwind-mips.h index 1bb07275..b05e7406 100644 --- a/include/libunwind-mips.h +++ b/include/libunwind-mips.h @@ -154,7 +154,7 @@ extern int unw_tdep_getcontext (ucontext_t *uc); #define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) extern int unw_tdep_is_fpreg (int); -#define unw_tdep_trace(cur,addr,n,c) (-UNW_ENOINFO) +#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO) #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/libunwind-ppc32.h b/include/libunwind-ppc32.h index b0fd6502..dca2a74e 100644 --- a/include/libunwind-ppc32.h +++ b/include/libunwind-ppc32.h @@ -206,7 +206,7 @@ unw_tdep_frame_t; #define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) extern int unw_tdep_is_fpreg (int); -#define unw_tdep_trace(cur,addr,n,c) (-UNW_ENOINFO) +#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO) #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/libunwind-ppc64.h b/include/libunwind-ppc64.h index 33c3e711..7370f603 100644 --- a/include/libunwind-ppc64.h +++ b/include/libunwind-ppc64.h @@ -263,7 +263,7 @@ unw_tdep_frame_t; #define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) extern int unw_tdep_is_fpreg (int); -#define unw_tdep_trace(cur,addr,n,c) (-UNW_ENOINFO) +#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO) #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/libunwind-x86.h b/include/libunwind-x86.h index 70b529dd..60c97bf6 100644 --- a/include/libunwind-x86.h +++ b/include/libunwind-x86.h @@ -186,7 +186,7 @@ extern int unw_tdep_getcontext (unw_tdep_context_t *); #define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) extern int unw_tdep_is_fpreg (int); -#define unw_tdep_trace(cur,addr,n,c) (-UNW_ENOINFO) +#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO) #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/src/mi/backtrace.c b/src/mi/backtrace.c index fb2e05d2..a126b1a9 100644 --- a/src/mi/backtrace.c +++ b/src/mi/backtrace.c @@ -31,32 +31,51 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* See glibc manual for a description of this function. */ -int -unw_backtrace (void **buffer, int size) +static inline int +slow_backtrace (void **buffer, int size) { unw_cursor_t cursor; - unw_context_t uc, ucsave; - int n = size; + unw_context_t uc; + unw_word_t ip; + int n = 0; + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + return 0; + + while (unw_step (&cursor) > 0) + { + if (n >= size) + return n; + + if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0) + return n; + buffer[n++] = (void *) (uintptr_t) ip; + } + return n; +} + +int +backtrace (void **buffer, int size) +{ + unw_cursor_t cursor; + unw_context_t uc; + int n = size; + int ret; unw_getcontext (&uc); - memcpy (&ucsave, &uc, sizeof(uc)); if (unw_init_local (&cursor, &uc) < 0) return 0; + /* We don't need backtrace() to show up in buffer */ + ret = unw_step (&cursor); + if (ret < 0) + return ret; + if (unw_tdep_trace (&cursor, buffer, &n) < 0) { - n = 0; - unw_init_local (&cursor, &ucsave); - while (n < size) - { - unw_word_t ip; - if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0) - return n; - buffer[n++] = (void *) (uintptr_t) ip; - if (unw_step (&cursor) <= 0) - break; - } + return slow_backtrace(buffer, size); } return n; diff --git a/tests/Gtest-trace.c b/tests/Gtest-trace.c index 90452be6..8565436c 100644 --- a/tests/Gtest-trace.c +++ b/tests/Gtest-trace.c @@ -53,9 +53,6 @@ char buf[512], name[256]; void *addresses[2][128]; unw_cursor_t cursor; ucontext_t uc; -#if UNW_TARGET_X86_64 -unw_tdep_frame_t *cache; -#endif static void do_backtrace (void) @@ -73,7 +70,7 @@ do_backtrace (void) panic ("unw_init_local failed!\n"); #if UNW_TARGET_X86_64 - if ((ret = unw_tdep_trace (&cursor, addresses[0], &depth, cache)) < 0) + if ((ret = unw_tdep_trace (&cursor, addresses[0], &depth)) < 0) { unw_get_reg (&cursor, UNW_REG_IP, &ip); printf ("FAILURE: unw_tdep_trace() returned %d for ip=%lx\n", ret, (long) ip); @@ -211,10 +208,6 @@ main (int argc, char **argv) struct sigaction act; stack_t stk; -#if UNW_TARGET_X86_64 - cache = unw_tdep_make_frame_cache (0); -#endif - verbose = (argc > 1); if (verbose) @@ -255,10 +248,6 @@ main (int argc, char **argv) exit (-1); } -#if UNW_TARGET_X86_64 - unw_tdep_free_frame_cache (cache); -#endif - if (verbose) printf ("SUCCESS.\n"); return 0; diff --git a/tests/Makefile.am b/tests/Makefile.am index a981d635..aebe1296 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -136,6 +136,7 @@ Gtest_exc_LDADD = $(LIBUNWIND) Gtest_init_LDADD = $(LIBUNWIND) Gtest_resume_sig_LDADD = $(LIBUNWIND) Gperf_simple_LDADD = $(LIBUNWIND) +Gtest_trace_LDADD=$(LIBUNWIND) Ltest_bt_LDADD = $(LIBUNWIND_local) Ltest_concurrent_LDADD = $(LIBUNWIND_local) -lpthread @@ -145,6 +146,8 @@ Ltest_init_LDADD = $(LIBUNWIND_local) Ltest_nomalloc_LDADD = $(LIBUNWIND_local) @DLLIB@ Ltest_resume_sig_LDADD = $(LIBUNWIND) Lperf_simple_LDADD = $(LIBUNWIND_local) +Ltest_trace_LDADD = $(LIBUNWIND_local) test_setjmp_LDADD = $(LIBUNWIND_setjmp) ia64_test_setjmp_LDADD = $(LIBUNWIND_setjmp) + diff --git a/tests/check-namespace.sh.in b/tests/check-namespace.sh.in index 9d9fb974..757d475c 100644 --- a/tests/check-namespace.sh.in +++ b/tests/check-namespace.sh.in @@ -123,8 +123,6 @@ check_local_unw_abi () { match _U${plat}_is_fpreg match _UL${plat}_dwarf_search_unwind_table match _U${plat}_setcontext - match _UL${plat}_free_frame_cache - match _UL${plat}_make_frame_cache match _UL${plat}_trace ;; *) @@ -189,8 +187,6 @@ check_generic_unw_abi () { match _U${plat}_get_elf_image match _U${plat}_is_fpreg match _U${plat}_dwarf_search_unwind_table - match _U${plat}_free_frame_cache - match _U${plat}_make_frame_cache match _U${plat}_trace ;; *)