summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Hunt <hunt@monkey.(none)>2008-04-15 21:10:34 -0400
committerMartin Hunt <hunt@monkey.(none)>2008-04-15 21:10:34 -0400
commit4f7a75f2cb3394290d1093a031546aa848ace929 (patch)
tree081546c0cd685ed58bc90c4903a7d954415300bf
parent8558d3925ee2931b654a19f243bfa8b3be0bfc12 (diff)
downloadsystemtap-steved-4f7a75f2cb3394290d1093a031546aa848ace929.tar.gz
systemtap-steved-4f7a75f2cb3394290d1093a031546aa848ace929.tar.xz
systemtap-steved-4f7a75f2cb3394290d1093a031546aa848ace929.zip
2.6.25 fixes and stack level limits.
-rw-r--r--runtime/ChangeLog16
-rw-r--r--runtime/regs.h4
-rw-r--r--runtime/runtime.h4
-rw-r--r--runtime/stack-i386.c50
-rw-r--r--runtime/stack.c8
-rw-r--r--runtime/sym.c5
-rw-r--r--runtime/unwind/i386.h18
-rw-r--r--tapset/ChangeLog4
-rw-r--r--tapset/context.stp4
9 files changed, 59 insertions, 54 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index b33fa22a..5066279e 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,19 @@
+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 6405
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 *)&REG_SP(regs);
- unsigned long context = (unsigned long)stack & ~(THREAD_SIZE - 1);
+ unsigned long context = (unsigned long)&REG_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.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/unwind/i386.h b/runtime/unwind/i386.h
index 6511f76a..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/tapset/ChangeLog b/tapset/ChangeLog
index dae8b452..c4c526f4 100644
--- a/tapset/ChangeLog
+++ b/tapset/ChangeLog
@@ -1,3 +1,7 @@
+2008-04-15 Martin Hunt <hunt@monkey>
+
+ * context.stp (print_backtrace, backtrace): Use MAXTRACE.
+
2008-03-21 Eugene Teo <eugeneteo@kernel.sg>
PR 5528
diff --git a/tapset/context.stp b/tapset/context.stp
index 4aa75158..dc560316 100644
--- a/tapset/context.stp
+++ b/tapset/context.stp
@@ -15,7 +15,7 @@ function print_regs () %{
function print_backtrace () %{
if (CONTEXT->regs) {
- _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi);
+ _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE);
} else {
_stp_printf("Systemtap probe: %s\n", CONTEXT->probe_point);
}
@@ -23,7 +23,7 @@ function print_backtrace () %{
function backtrace:string () %{ /* pure */
if (CONTEXT->regs)
- _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN, CONTEXT->regs, 0, CONTEXT->pi);
+ _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN, CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE);
else
strlcpy (THIS->__retvalue, "", MAXSTRINGLEN);
%}