[prev in list] [next in list] [prev in thread] [next in thread] 

List:       user-mode-linux-devel
Subject:    [uml-devel] [PATCH 3/5] UML: Enable CONFIG_STACKTRACE_SUPPORT
From:       Paul Menage <menage () google ! com>
Date:       2009-06-16 0:17:39
Message-ID: 20090616001739.30398.50579.stgit () menage ! mtv ! corp ! google ! com
[Download RAW message or body]

UML: Enable CONFIG_STACKTRACE_SUPPORT

Adds a simple stacktrace function, only tested/enabled on X86

Signed-off-by: Paul Menage <menage@google.com>

---

 arch/um/Kconfig.common      |    2 +
 arch/um/kernel/Makefile     |    1 +
 arch/um/kernel/stacktrace.c |   68 +++++++++++++++++++++++++++++++++++++++++++
 arch/um/kernel/sysrq.c      |   20 +++++++++++++
 4 files changed, 90 insertions(+), 1 deletions(-)
 create mode 100644 arch/um/kernel/stacktrace.c

diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
index 8a54ae4..b757c36 100644
--- a/arch/um/Kconfig.common
+++ b/arch/um/Kconfig.common
@@ -44,7 +44,7 @@ config LOCKDEP_SUPPORT
 
 config STACKTRACE_SUPPORT
 	bool
-	default n
+	default UML_X86
 
 config GENERIC_CALIBRATE_DELAY
 	bool
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 388ec0a..b1867a0 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -14,6 +14,7 @@ obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
 obj-$(CONFIG_GCOV)	+= gmon_syms.o
+obj-$(CONFIG_STACKTRACE_SUPPORT) += stacktrace.o
 
 USER_OBJS := config.o
 
diff --git a/arch/um/kernel/stacktrace.c b/arch/um/kernel/stacktrace.c
new file mode 100644
index 0000000..a0d6a60
--- /dev/null
+++ b/arch/um/kernel/stacktrace.c
@@ -0,0 +1,68 @@
+/*
+ * Simple stacktrace function. Only tested on x86, but can probably
+ * be adapted to other architectures with minimal work. (E.g. checking
+ * stack direction)
+ */
+#include "linux/stddef.h"
+#include <linux/stacktrace.h>
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+
+static void save_stack_address(unsigned long addr, struct stack_trace *trace)
+{
+	if (!__kernel_text_address(addr))
+		return;
+
+	if (trace->skip) {
+		trace->skip--;
+		return;
+	}
+
+	trace->entries[trace->nr_entries++] = addr;
+}
+
+#define THREAD_MASK (THREAD_SIZE-1)
+
+#ifdef CONFIG_FRAME_POINTER
+
+struct stack_frame {
+	struct stack_frame *next_frame;
+	unsigned long return_address;
+};
+
+void save_stack_trace(struct stack_trace *trace)
+{
+	unsigned long addr;
+	struct stack_frame *frame, *end;
+	frame = __builtin_frame_address(0);
+	end = (struct stack_frame *)
+		((((unsigned long)frame) + THREAD_MASK) & ~THREAD_MASK);
+	while (trace->nr_entries < trace->max_entries) {
+		addr = frame->return_address;
+		save_stack_address(addr, trace);
+		if (frame->next_frame <= frame || frame->next_frame > end)
+			break;
+		frame = frame->next_frame;
+	}
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+#else
+
+void save_stack_trace(struct stack_trace *trace)
+{
+	unsigned long addr;
+	unsigned long *stack = (unsigned long *)&stack;
+	while (trace->nr_entries < trace->max_entries) {
+		addr = *stack;
+		save_stack_address(addr, trace);
+		stack++;
+		if (!(stack & THREAD_MASK))
+			break;
+	}
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+#endif
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 56d43d0..42b832c 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -11,6 +11,25 @@
 
 /* Catch non-i386 SUBARCH's. */
 #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
+#ifdef CONFIG_STACKTRACE
+void show_trace(struct task_struct *task, unsigned long * stack)
+{
+	struct stack_trace trace;
+	unsigned long entries[64];
+
+	if (!stack) {
+		stack = (unsigned long *) &stack;
+		WARN_ON(1);
+	}
+
+	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
 void show_trace(struct task_struct *task, unsigned long * stack)
 {
 	unsigned long addr;
@@ -33,6 +52,7 @@ void show_trace(struct task_struct *task, unsigned long * stack)
 	}
 	printk(KERN_INFO "\n");
 }
+#endif  /& CONFIG_STACKTRACE */
 #endif
 
 /*


------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing 
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
User-mode-linux-devel mailing list
User-mode-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic