diff options
-rw-r--r-- | runtime/ChangeLog | 8 | ||||
-rw-r--r-- | runtime/stack-i386.c | 63 | ||||
-rw-r--r-- | runtime/stack-x86_64.c | 54 | ||||
-rw-r--r-- | runtime/sym.c | 35 |
4 files changed, 45 insertions, 115 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 2e9cf933..a9696791 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,11 @@ +2007-07-02 Martin Hunt <hunt@redhat.com> + + * sym.c (_stp_kallsyms_lookup): Improve heuristic + for determining when a pointer is in a function. + (_stp_func_print): New function. + * stack-i386.c, stack-x86_64.c: Remove obsolete + unwind code. Use _stp_func_print(). + 2007-06-22 Frank Ch. Eigler <fche@elastic.org> * string.c (_stp_text_str): Fix handling of embedded diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c index 161e22ee..a80de048 100644 --- a/runtime/stack-i386.c +++ b/runtime/stack-i386.c @@ -7,37 +7,6 @@ * Public License (GPL); either version 2, or (at your option) any * later version. */ -#ifdef CONFIG_STACK_UNWIND -#include <linux/unwind.h> - -static inline int _stp_valid_stack_ptr_info(struct unwind_frame_info *info) -{ - unsigned long context = (unsigned long)UNW_SP(info) & ~(THREAD_SIZE - 1); - unsigned long p = UNW_PC(info); - return p > context && p < context + THREAD_SIZE - 3; -} - -static int -_stp_show_trace_unwind(struct unwind_frame_info *info, int verbose) -{ - int n = 0; - - while (unwind(info) == 0 && UNW_PC(info)) { - if (_stp_valid_stack_ptr_info(info)) - break; - n++; - if (verbose) { - _stp_print_char (' '); - _stp_symbol_print (UNW_PC(info)); - _stp_print_char ('\n'); - } else - _stp_printf ("0x%08lx ", UNW_PC(info)); - if (arch_unw_user_mode(info)) - break; - } - return n; -} -#endif /* CONFIG_STACK_UNWIND */ static inline int _stp_valid_stack_ptr(unsigned long context, unsigned long p) { @@ -49,31 +18,14 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) unsigned long *stack = (unsigned long *)®_SP(regs); unsigned long context = (unsigned long)stack & ~(THREAD_SIZE - 1); unsigned long addr; - int uw_ret = 0; - -#ifdef CONFIG_STACK_UNWIND - struct unwind_frame_info info; - if (unwind_init_frame_info(&info, current, regs) == 0) - uw_ret = _stp_show_trace_unwind(&info, verbose); - stack = (void *)UNW_SP(&info); -#endif - - if (uw_ret == 0) - _stp_print("Inexact backtrace:\n"); #ifdef CONFIG_FRAME_POINTER { - unsigned long ebp; - /* Grab ebp right from our regs.*/ - asm ("movl %%ebp, %0" : "=r" (ebp) : ); + unsigned long ebp = regs->ebp; while (_stp_valid_stack_ptr(context, (unsigned long)ebp)) { addr = *(unsigned long *)(ebp + 4); if (verbose) { - if (uw_ret) { - uw_ret = 0; - _stp_print("Leftover inexact backtrace:\n"); - } _stp_print_char(' '); _stp_symbol_print (addr); _stp_print_char('\n'); @@ -85,18 +37,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) #else while (_stp_valid_stack_ptr(context, (unsigned long)stack)) { addr = *stack++; - if (_stp_kta(addr)) { - if (verbose) { - if (uw_ret) { - uw_ret = 0; - _stp_print("Leftover inexact backtrace:\n"); - } - _stp_print_char(' '); - _stp_symbol_print(addr); - _stp_print_char('\n'); - } else - _stp_printf ("0x%08lx ", addr); - } + _stp_func_print(addr, verbose); } #endif } diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c index 15bac801..6f02e7ba 100644 --- a/runtime/stack-x86_64.c +++ b/runtime/stack-x86_64.c @@ -7,66 +7,14 @@ * Public License (GPL); either version 2, or (at your option) any * later version. */ -#ifdef CONFIG_STACK_UNWIND -#include <linux/unwind.h> - -static inline int _stp_valid_stack_ptr(struct unwind_frame_info *info) -{ - unsigned long context = (unsigned long)UNW_SP(info) & ~(THREAD_SIZE - 1); - unsigned long p = UNW_PC(info); - return p > context && p < context + THREAD_SIZE - 3; -} - -static int _stp_show_trace_unwind(struct unwind_frame_info *info, int verbose) -{ - int n = 0; - - while (unwind(info) == 0 && UNW_PC(info)) { - if (_stp_valid_stack_ptr(info)) - break; - n++; - if (verbose) { - _stp_print_char(' '); - _stp_symbol_print (UNW_PC(info)); - _stp_print_char('\n'); - } else - _stp_printf ("0x%016lx ", UNW_PC(info)); - if (arch_unw_user_mode(info)) - break; - } - return n; -} -#endif /* CONFIG_STACK_UNWIND */ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) { unsigned long *stack = (unsigned long *)®_SP(regs); unsigned long addr; - int uw_ret = 0; - -#ifdef CONFIG_STACK_UNWIND - struct unwind_frame_info info; - if (unwind_init_frame_info(&info, current, regs) == 0) - uw_ret = _stp_show_trace_unwind(&info, verbose); - stack = (void *)UNW_SP(&info); -#endif - - if (uw_ret == 0) - _stp_print("Inexact backtrace:\n"); while ((long)stack & (THREAD_SIZE-1)) { addr = *stack++; - if (_stp_kta(addr)) { - if (verbose) { - if (uw_ret) { - uw_ret = 0; - _stp_print("Leftover inexact backtrace:\n"); - } - _stp_print_char(' '); - _stp_symbol_print(addr); - _stp_print_char('\n'); - } else - _stp_printf("0x%016lx ", addr); - } + _stp_func_print(addr, verbose); } } diff --git a/runtime/sym.c b/runtime/sym.c index d8ad3f2c..c40f48db 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -32,7 +32,7 @@ unsigned long _stp_module_relocate (const char *module, const char *section, uns return 0; } - dbug("_stp_relocate_module: %s, %s, %lx\n", module, section, offset); + dbug("%s, %s, %lx\n", module, section, offset); STP_LOCK_MODULES; if (! module @@ -47,6 +47,7 @@ unsigned long _stp_module_relocate (const char *module, const char *section, uns if (!strcmp (module, last->name) && !strcmp (section, last_sec->symbol)) { offset += last_sec->addr; STP_UNLOCK_MODULES; + dbug("offset = %lx\n", offset); return offset; } } @@ -71,6 +72,7 @@ unsigned long _stp_module_relocate (const char *module, const char *section, uns if (!strcmp (section, last_sec->symbol)) { offset += last_sec->addr; STP_UNLOCK_MODULES; + dbug("offset = %lx\n", offset); return offset; } } @@ -127,6 +129,14 @@ static const char * _stp_kallsyms_lookup ( begin = 0; end = m->num_symbols; + /* m->data is the lowest address of a data section. It should be */ + /* after the text section. */ + /* If our address is in the data section, then return now. */ + if (m->data > m->text && addr >= m->data) { + STP_UNLOCK_MODULES; + return NULL; + } + /* binary search for symbols within the module */ do { unsigned mid = (begin + end) / 2; @@ -190,6 +200,29 @@ void _stp_symbol_print (unsigned long address) } } +/* Like _stp_symbol_print, except only print if the address is a valid function address */ + +void _stp_func_print (unsigned long address, int verbose) +{ + char *modname; + const char *name; + unsigned long offset, size; + + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL); + + if (name) { + if (verbose) { + if (modname) + _stp_printf (" %p : %s+%#lx/%#lx [%s]\n", + (int64_t)address, name, offset, size, modname); + else + _stp_printf (" %p : %s+%#lx/%#lx\n", + (int64_t)address, name, offset, size); + } else + _stp_printf ("%p ", (int64_t)address); + } +} + void _stp_symbol_snprint (char *str, size_t len, unsigned long address) { char *modname; |