diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/ChangeLog | 38 | ||||
-rw-r--r-- | runtime/autoconf-module-nsections.c | 8 | ||||
-rw-r--r-- | runtime/regs.h | 4 | ||||
-rw-r--r-- | runtime/runtime.h | 4 | ||||
-rw-r--r-- | runtime/stack-i386.c | 50 | ||||
-rw-r--r-- | runtime/stack-x86_64.c | 17 | ||||
-rw-r--r-- | runtime/stack.c | 8 | ||||
-rw-r--r-- | runtime/sym.c | 5 | ||||
-rw-r--r-- | runtime/transport/ChangeLog | 11 | ||||
-rw-r--r-- | runtime/transport/symbols.c | 21 | ||||
-rw-r--r-- | runtime/unwind.c | 5 | ||||
-rw-r--r-- | runtime/unwind/i386.h | 18 | ||||
-rw-r--r-- | runtime/unwind/unwind.h | 4 |
13 files changed, 131 insertions, 62 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 09a3e35d..7184a980 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,41 @@ +2008-04-15 hunt <hunt@redhat.com> + + * stack-x86_64.c (_stp_stack_print_fallback): Add levels. + (__stp_stack_print): Count levels properly. + +2008-04-15 Martin Hunt <hunt@redhat.com> + + Finish support for limits on backtrace depth. + * runtime.h (MAXTRACE): Default to 20. + * stack.c (_stp_stack_print): Call __stp_stack_print + with levels set properly. + * sym.c (_stp_func_print): Return a value indicating + if something was printed. + + Support for i386 and x86_64 on 2.6.25 kernel + * unwind/i386.h: Support unified registers on 2.6.25. + Remove unused frame stuff, including STACK_*. + * stack-i386.c (__stp_stack_print): Support unified + registers on 2.6.25. + * regs.h (REG_FP): Define for i386. + +2008-04-15 Frank Ch. Eigler <fche@elastic.org> + + PR 6410. + * unwind.c, unwind.h: Make body conditional in STP_USE_DWARF_UNWINDER. + * stack-x86_64.c (__stp_stack_print): Tolerate !unwinder. + +2008-04-15 Frank Ch. Eigler <fche@elastic.org> + + PR 6405 + * autoconf-module-nsections.c: New file. + +2008-04-15 Frank Ch. Eigler <fche@elastic.org> + + * unwind/i386.h (STACK_BOTTOM, STACK_TOP): Comment out these + unused definitions, for they collide with some kernels + (2.6.25-0.121.rc5.git4 rawhide). + 2008-04-13 Frank Ch. Eigler <fche@elastic.org> * print.c (_stp_pbuf_full): New function to note full print buffer. diff --git a/runtime/autoconf-module-nsections.c b/runtime/autoconf-module-nsections.c new file mode 100644 index 00000000..c1ce58b7 --- /dev/null +++ b/runtime/autoconf-module-nsections.c @@ -0,0 +1,8 @@ +#include <linux/module.h> + +struct module_sect_attrs x; + +void foo (void) +{ + (void) x.nsections; +} diff --git a/runtime/regs.h b/runtime/regs.h index c1e2344b..4954020f 100644 --- a/runtime/regs.h +++ b/runtime/regs.h @@ -1,5 +1,5 @@ /* common register includes used in multiple modules - * Copyright (C) 2005 Red Hat Inc. + * Copyright (C) 2005-2008 Red Hat Inc. * Copyright (C) 2005 Intel Corporation. * * This file is part of systemtap, and is free software. You can @@ -14,6 +14,7 @@ #if defined (STAPCONF_X86_UNIREGS) && (defined (__x86_64__) || defined (__i386__)) #define REG_IP(regs) regs->ip #define REG_SP(regs) regs->sp +#define REG_FP(regs) regs->bp; #elif defined (__x86_64__) @@ -24,6 +25,7 @@ #define REG_IP(regs) regs->eip #define REG_SP(regs) regs->esp +#define REG_FP(regs) regs->ebp; #elif defined (__ia64__) #define REG_IP(regs) ((regs)->cr_iip +ia64_psr(regs)->ri) diff --git a/runtime/runtime.h b/runtime/runtime.h index 8d267173..50eb9d31 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -70,6 +70,10 @@ static struct #define MAXSTRINGLEN 128 #endif +#ifndef MAXTRACE +#define MAXTRACE 20 +#endif + #ifdef CONFIG_FRAME_POINTER /* Just because frame pointers are available does not mean we can trust them. */ #if defined (__i386__) || defined (__arm__) diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c index 78f89b0d..ad101889 100644 --- a/runtime/stack-i386.c +++ b/runtime/stack-i386.c @@ -14,65 +14,61 @@ static int _stp_valid_stack_ptr(unsigned long context, unsigned long p) } /* DWARF unwinder failed. Just dump intereting addresses on kernel stack. */ -static void _stp_stack_print_fallback(unsigned long context, unsigned long stack, int verbose) +static void _stp_stack_print_fallback(unsigned long context, unsigned long stack, int verbose, int levels) { unsigned long addr; - while (_stp_valid_stack_ptr(context, stack) && - !_stp_pbuf_full()) { + while (levels && _stp_valid_stack_ptr(context, stack)) { if (unlikely(_stp_read_address(addr, (unsigned long *)stack, KERNEL_DS))) { /* cannot access stack. give up. */ return; } - _stp_func_print(addr, verbose, 0); + if (_stp_func_print(addr, verbose, 0)) + levels--; stack++; } } 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 context = (unsigned long)®_SP(regs) & ~(THREAD_SIZE - 1); #ifdef STP_USE_FRAME_POINTER - /* FIXME: need to use _stp_func_print() and safe copy */ unsigned long addr; - -#ifdef STAPCONF_X86_UNIREGS - unsigned long ebp = regs->bp; -#else - unsigned long ebp = regs->ebp; -#endif /* STAPCONF_X86_UNIREGS */ - - while (_stp_valid_stack_ptr(context, (unsigned long)ebp) && - !_stp_pbuf_full()) { - if (unlikely(_stp_read_address(addr, (unsigned long *)(ebp + 4), KERNEL_DS))) { + unsigned long next_fp, fp = REG_FP(regs); + + while (levels && _stp_valid_stack_ptr(context, (unsigned long)fp)) { + if (unlikely(_stp_read_address(addr, (unsigned long *)(fp + 4), KERNEL_DS))) { /* cannot access stack. give up. */ return; } - if (verbose) { - _stp_print_char(' '); - _stp_symbol_print (addr); - _stp_print_char('\n'); - } else - _stp_printf ("0x%08lx ", addr); - ebp = *(unsigned long *)ebp; + _stp_func_print(addr, verbose, 1); + if (unlikely(_stp_read_address(next_fp, (unsigned long *)fp, KERNEL_DS))) { + /* cannot access stack. give up. */ + return; + } + levels--; + + /* frame pointers move upwards */ + if (next_fp <= fp) + break; + fp = next_fp; } #else struct unwind_frame_info info; arch_unw_init_frame_info(&info, regs); - while (!arch_unw_user_mode(&info) && - !_stp_pbuf_full ()) { + while (levels && !arch_unw_user_mode(&info)) { int ret = unwind(&info); dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info)); if (ret == 0) { _stp_func_print(UNW_PC(&info), verbose, 1); + levels--; continue; } /* If an error happened or we hit a kretprobe trampoline, use fallback backtrace */ /* FIXME: is there a way to unwind across kretprobe trampolines? */ if (ret < 0 || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline)) - _stp_stack_print_fallback(context, UNW_SP(&info), verbose); + _stp_stack_print_fallback(context, UNW_SP(&info), verbose, levels); break; } #endif /* STP_USE_FRAME_POINTER */ diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c index 9915c594..729b8a2a 100644 --- a/runtime/stack-x86_64.c +++ b/runtime/stack-x86_64.c @@ -9,37 +9,42 @@ */ /* DWARF unwinder failed. Just dump intereting addresses on kernel stack. */ -static void _stp_stack_print_fallback(unsigned long stack, int verbose) +static void _stp_stack_print_fallback(unsigned long stack, int verbose, int levels) { unsigned long addr; - while (stack & (THREAD_SIZE - 1) && - !_stp_pbuf_full()) { + while (levels && stack & (THREAD_SIZE - 1)) { if (unlikely(_stp_read_address(addr, (unsigned long *)stack, KERNEL_DS))) { /* cannot access stack. give up. */ return; } - _stp_func_print(addr, verbose, 0); + if (_stp_func_print(addr, verbose, 0)) + levels--; stack++; } } static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels) { +#ifdef STP_USE_DWARF_UNWINDER // FIXME: large stack allocation struct unwind_frame_info info; arch_unw_init_frame_info(&info, regs); - while (!arch_unw_user_mode(&info)) { + while (levels && !arch_unw_user_mode(&info)) { int ret = unwind(&info); dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info)); if (ret == 0) { _stp_func_print(UNW_PC(&info), verbose, 1); + levels--; continue; } /* If an error happened or we hit a kretprobe trampoline, use fallback backtrace */ /* FIXME: is there a way to unwind across kretprobe trampolines? */ if (ret < 0 || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline)) - _stp_stack_print_fallback(UNW_SP(&info), verbose); + _stp_stack_print_fallback(UNW_SP(&info), verbose, levels); break; } +#else /* ! STP_USE_DWARF_UNWINDER */ + _stp_stack_print_fallback(REG_SP(regs), verbose); +#endif } diff --git a/runtime/stack.c b/runtime/stack.c index 772c5baf..23ac2edc 100644 --- a/runtime/stack.c +++ b/runtime/stack.c @@ -47,7 +47,7 @@ * @param regs A pointer to the struct pt_regs. */ -void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instance *pi) +void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels) { if (verbose) { /* print the current address */ @@ -66,7 +66,7 @@ void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instan else _stp_printf("%p ", (int64_t) REG_IP(regs)); - __stp_stack_print(regs, verbose, 0); + __stp_stack_print(regs, verbose, levels); } /** Writes stack backtrace to a string @@ -75,14 +75,14 @@ void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instan * @param regs A pointer to the struct pt_regs. * @returns void */ -void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int verbose, struct kretprobe_instance *pi) +void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels) { /* To get a string, we use a simple trick. First flush the print buffer, */ /* then call _stp_stack_print, then copy the result into the output string */ /* and clear the print buffer. */ _stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id()); _stp_print_flush(); - _stp_stack_print(regs, verbose, pi); + _stp_stack_print(regs, verbose, pi, levels); strlcpy(str, pb->buf, size < (int)pb->len ? size : (int)pb->len); pb->len = 0; } diff --git a/runtime/sym.c b/runtime/sym.c index 3d5ff01d..7163bf92 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -223,8 +223,7 @@ 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, int exact) +int _stp_func_print(unsigned long address, int verbose, int exact) { char *modname; const char *name; @@ -247,7 +246,9 @@ void _stp_func_print(unsigned long address, int verbose, int exact) _stp_printf(" %p : %s+%#lx/%#lx%s\n", (int64_t) address, name, offset, size, exstr); } else _stp_printf("%p ", (int64_t) address); + return 1; } + return 0; } void _stp_symbol_snprint(char *str, size_t len, unsigned long address) diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog index b3a159e3..807f6eda 100644 --- a/runtime/transport/ChangeLog +++ b/runtime/transport/ChangeLog @@ -1,3 +1,14 @@ +2008-04-15 Frank Ch. Eigler <fche@elastic.org> + + PR 6410 + * symbols.c (_stp_do_unwind_data): Tolerate !STP_USE_DWARF_UNWINDER. + +2008-04-15 Frank Ch. Eigler <fche@elastic.org> + + PR 6405 + * symbols.c (_stp_load_module_symbols): Support older kernels + without module->sect_attrs->nsections. + 2008-04-09 Martin Hunt <hunt@dragon> * symbols.c (_stp_init_kernel_symbols): Print error diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c index b0e7c319..087bf893 100644 --- a/runtime/transport/symbols.c +++ b/runtime/transport/symbols.c @@ -290,7 +290,9 @@ static void _stp_do_unwind_data(const char __user *buf, size_t count) goto done; } m->unwind_data_len = count; +#ifdef STP_USE_DWARF_UNWINDER _stp_create_unwind_hdr(m); +#endif done: write_unlock(&m->lock); } @@ -401,14 +403,25 @@ static int _stp_section_is_interesting(const char *name) static struct _stp_module *_stp_load_module_symbols(struct module *mod) { int i, num, overflow = 0; - struct module_sect_attrs *sa; + struct module_sect_attrs *sa = mod->sect_attrs; + struct attribute_group *sag = & sa->grp; unsigned sect_size = 0, sect_num = 0, sym_size, sym_num; struct _stp_module *sm; char *dataptr, *endptr; + unsigned nsections = 0; + +#ifdef STAPCONF_MODULE_NSECTIONS + nsections = sa->nsections; +#else + /* count section attributes on older kernel */ + struct attribute** gattr; + for (gattr = sag->attrs; *gattr; gattr++) + nsections++; + dbug_sym(2, "\tcount %d\n", nsections); +#endif - sa = mod->sect_attrs; /* calculate how much space to allocate for section strings */ - for (i = 0; i < sa->nsections; i++) { + for (i = 0; i < nsections; i++) { if (_stp_section_is_interesting(sa->attrs[i].name)) { sect_num++; sect_size += strlen(sa->attrs[i].name) + 1; @@ -438,7 +451,7 @@ static struct _stp_module *_stp_load_module_symbols(struct module *mod) dataptr = (char *)((long)sm->sections + sect_num * sizeof(struct _stp_symbol)); endptr = (char *)((long)sm->sections + sect_size); num = 0; - for (i = 0; i < sa->nsections; i++) { + for (i = 0; i < nsections; i++) { size_t len, maxlen; if (_stp_section_is_interesting(sa->attrs[i].name)) { sm->sections[num].addr = sa->attrs[i].address; diff --git a/runtime/unwind.c b/runtime/unwind.c index f0010372..aa270cad 100644 --- a/runtime/unwind.c +++ b/runtime/unwind.c @@ -15,6 +15,8 @@ #include "unwind/unwind.h" +#ifdef STP_USE_DWARF_UNWINDER + struct eh_frame_hdr_table_entry { unsigned long start, fde; }; @@ -957,3 +959,6 @@ done: #undef CASES #undef FRAME_REG } + + +#endif /* STP_USE_DWARF_UNWINDER */ diff --git a/runtime/unwind/i386.h b/runtime/unwind/i386.h index 1f69b4a9..79e6ba73 100644 --- a/runtime/unwind/i386.h +++ b/runtime/unwind/i386.h @@ -34,15 +34,6 @@ struct unwind_frame_info #define UNW_PC(frame) (frame)->regs.ip #define UNW_SP(frame) (frame)->regs.sp -#ifdef STP_USE_FRAME_POINTER -#define UNW_FP(frame) (frame)->regs.bp -#define FRAME_RETADDR_OFFSET 4 -#define FRAME_LINK_OFFSET 0 -#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.sp0) -#define STACK_TOP(tsk) ((tsk)->thread.sp0) -#else -#define UNW_FP(frame) ((void)(frame), 0) -#endif #define UNW_REGISTER_INFO \ PTREGS_INFO(ax), \ @@ -59,15 +50,6 @@ struct unwind_frame_info #define UNW_PC(frame) (frame)->regs.eip #define UNW_SP(frame) (frame)->regs.esp -#ifdef STP_USE_FRAME_POINTER -#define UNW_FP(frame) (frame)->regs.ebp -#define FRAME_RETADDR_OFFSET 4 -#define FRAME_LINK_OFFSET 0 -#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0) -#define STACK_TOP(tsk) ((tsk)->thread.esp0) -#else -#define UNW_FP(frame) ((void)(frame), 0) -#endif #define UNW_REGISTER_INFO \ PTREGS_INFO(eax), \ diff --git a/runtime/unwind/unwind.h b/runtime/unwind/unwind.h index 8651cb9e..ae5e75d3 100644 --- a/runtime/unwind/unwind.h +++ b/runtime/unwind/unwind.h @@ -13,6 +13,8 @@ #ifndef _STP_UNWIND_H_ #define _STP_UNWIND_H_ +#ifdef STP_USE_DWARF_UNWINDER + #if defined (__x86_64__) #include "x86_64.h" #elif defined (__i386__) @@ -139,4 +141,6 @@ static const u32 bad_cie, not_fde; static const u32 *cie_for_fde(const u32 *fde, const struct _stp_module *); static signed fde_pointer_type(const u32 *cie); + +#endif /* STP_USE_DWARF_UNWINDER */ #endif /*_STP_UNWIND_H_*/ |