Skip to content

Commit

Permalink
Merge branch 'core/stacktrace' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/tip/linux-2.6-tip

* 'core/stacktrace' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  generic-ipi: powerpc/generic-ipi tree build failure
  stacktrace: fix build failure on sparc64
  stacktrace: export save_stack_trace[_tsk]
  stacktrace: fix modular build, export print_stack_trace and save_stack_trace
  backtrace: replace timer with tasklet + completions
  stacktrace: add saved stack traces to backtrace self-test
  stacktrace: print_stack_trace() cleanup
  debugging: make stacktrace independent from DEBUG_KERNEL
  stacktrace: don't crash on invalid stack trace structs
  • Loading branch information
Linus Torvalds committed Jul 15, 2008
2 parents 1dc60c5 + 7798ed0 commit af5329c
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 18 deletions.
1 change: 1 addition & 0 deletions arch/arm/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,5 @@ void save_stack_trace(struct stack_trace *trace)
{
save_stack_trace_tsk(current, trace);
}
EXPORT_SYMBOL_GPL(save_stack_trace);
#endif
1 change: 1 addition & 0 deletions arch/avr32/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ void save_stack_trace(struct stack_trace *trace)
fp = frame->fp;
}
}
EXPORT_SYMBOL_GPL(save_stack_trace);
1 change: 1 addition & 0 deletions arch/mips/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,4 @@ void save_stack_trace(struct stack_trace *trace)
prepare_frametrace(regs);
save_context_stack(trace, regs);
}
EXPORT_SYMBOL_GPL(save_stack_trace);
2 changes: 2 additions & 0 deletions arch/powerpc/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/module.h>
#include <asm/ptrace.h>

/*
Expand Down Expand Up @@ -44,3 +45,4 @@ void save_stack_trace(struct stack_trace *trace)
sp = newsp;
}
}
EXPORT_SYMBOL_GPL(save_stack_trace);
2 changes: 2 additions & 0 deletions arch/s390/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ void save_stack_trace(struct stack_trace *trace)
S390_lowcore.thread_info,
S390_lowcore.thread_info + THREAD_SIZE, 1);
}
EXPORT_SYMBOL_GPL(save_stack_trace);

void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
Expand All @@ -93,3 +94,4 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
if (trace->nr_entries < trace->max_entries)
trace->entries[trace->nr_entries++] = ULONG_MAX;
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
1 change: 1 addition & 0 deletions arch/sh/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ void save_stack_trace(struct stack_trace *trace)
}
}
}
EXPORT_SYMBOL_GPL(save_stack_trace);
2 changes: 2 additions & 0 deletions arch/sparc64/kernel/stacktrace.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/thread_info.h>
#include <linux/module.h>
#include <asm/ptrace.h>
#include <asm/stacktrace.h>

Expand Down Expand Up @@ -47,3 +48,4 @@ void save_stack_trace(struct stack_trace *trace)
trace->entries[trace->nr_entries++] = pc;
} while (trace->nr_entries < trace->max_entries);
}
EXPORT_SYMBOL_GPL(save_stack_trace);
2 changes: 2 additions & 0 deletions arch/x86/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@ void save_stack_trace(struct stack_trace *trace)
if (trace->nr_entries < trace->max_entries)
trace->entries[trace->nr_entries++] = ULONG_MAX;
}
EXPORT_SYMBOL_GPL(save_stack_trace);

void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace);
if (trace->nr_entries < trace->max_entries)
trace->entries[trace->nr_entries++] = ULONG_MAX;
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
65 changes: 54 additions & 11 deletions kernel/backtracetest.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,73 @@
* of the License.
*/

#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/stacktrace.h>

static void backtrace_test_normal(void)
{
printk("Testing a backtrace from process context.\n");
printk("The following trace is a kernel self test and not a bug!\n");

static struct timer_list backtrace_timer;
dump_stack();
}

static void backtrace_test_timer(unsigned long data)
static DECLARE_COMPLETION(backtrace_work);

static void backtrace_test_irq_callback(unsigned long data)
{
dump_stack();
complete(&backtrace_work);
}

static DECLARE_TASKLET(backtrace_tasklet, &backtrace_test_irq_callback, 0);

static void backtrace_test_irq(void)
{
printk("Testing a backtrace from irq context.\n");
printk("The following trace is a kernel self test and not a bug!\n");
dump_stack();

init_completion(&backtrace_work);
tasklet_schedule(&backtrace_tasklet);
wait_for_completion(&backtrace_work);
}

#ifdef CONFIG_STACKTRACE
static void backtrace_test_saved(void)
{
struct stack_trace trace;
unsigned long entries[8];

printk("Testing a saved backtrace.\n");
printk("The following trace is a kernel self test and not a bug!\n");

trace.nr_entries = 0;
trace.max_entries = ARRAY_SIZE(entries);
trace.entries = entries;
trace.skip = 0;

save_stack_trace(&trace);
print_stack_trace(&trace, 0);
}
#else
static void backtrace_test_saved(void)
{
printk("Saved backtrace test skipped.\n");
}
#endif

static int backtrace_regression_test(void)
{
printk("====[ backtrace testing ]===========\n");
printk("Testing a backtrace from process context.\n");
printk("The following trace is a kernel self test and not a bug!\n");
dump_stack();

init_timer(&backtrace_timer);
backtrace_timer.function = backtrace_test_timer;
mod_timer(&backtrace_timer, jiffies + 10);
backtrace_test_normal();
backtrace_test_irq();
backtrace_test_saved();

msleep(10);
printk("====[ end of backtrace testing ]====\n");
return 0;
}
Expand Down
14 changes: 8 additions & 6 deletions kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@
* Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
*/
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/stacktrace.h>

void print_stack_trace(struct stack_trace *trace, int spaces)
{
int i, j;
int i;

for (i = 0; i < trace->nr_entries; i++) {
unsigned long ip = trace->entries[i];
if (WARN_ON(!trace->entries))
return;

for (j = 0; j < spaces + 1; j++)
printk(" ");
print_ip_sym(ip);
for (i = 0; i < trace->nr_entries; i++) {
printk("%*c", 1 + spaces, ' ');
print_ip_sym(trace->entries[i]);
}
}
EXPORT_SYMBOL_GPL(print_stack_trace);

4 changes: 3 additions & 1 deletion lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,6 @@ config DEBUG_LOCKING_API_SELFTESTS

config STACKTRACE
bool
depends on DEBUG_KERNEL
depends on STACKTRACE_SUPPORT

config DEBUG_KOBJECT
Expand Down Expand Up @@ -563,6 +562,9 @@ config BACKTRACE_SELF_TEST
for distributions or general kernels, but only for kernel
developers working on architecture code.

Note that if you want to also test saved backtraces, you will
have to enable STACKTRACE as well.

Say N if you are unsure.

config LKDTM
Expand Down

0 comments on commit af5329c

Please sign in to comment.