From: Arjan van de Ven <arjan@infradead.org>
To: linux-kernel@vger.kernel.org
Cc: mingo@elte.hu, tglx@tglx.de, hpa@zytor.com
Subject: [patch 2/2] Use the stack frames to get exact stack-traces for CONFIG_FRAMEPOINTER on x86-64
Date: Mon, 7 Jan 2008 21:14:37 -0800 [thread overview]
Message-ID: <20080107211437.5ba42f18@laptopd505.fenrus.org> (raw)
Subject: Use the stack frames to get exact stack-traces for CONFIG_FRAMEPOINTER on x86-64
From: Arjan van de Ven <arjan@linux.intel.com>
x86 32 bit already has this feature: This patch uses the stack frames with
frame pointer into an exact stack trace, by following the frame pointer.
This only affects kernels built with the CONFIG_FRAME_POINTER config option
enabled, and greatly reduces the amount of noise in oopses.
The code tries to use the frame pointers to do a backtrace, but if it smells
iffy or invalid, falls back to the traditional way of printing backtraces,
to make sure that at least some useful backtrace is created.
Due to the fragility and importance of the backtrace code, this needs to
be well reviewed and well tested before merging into mainlne.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
arch/x86/kernel/traps_64.c | 72 ++++++++++++++++++++++++++++++++++++++-------
1 file changed, 62 insertions(+), 10 deletions(-)
Index: linux-2.6.24-rc7/arch/x86/kernel/traps_64.c
===================================================================
--- linux-2.6.24-rc7.orig/arch/x86/kernel/traps_64.c
+++ linux-2.6.24-rc7/arch/x86/kernel/traps_64.c
@@ -221,17 +221,55 @@ static inline int valid_stack_ptr(struct
return p > t && p < t + THREAD_SIZE - size;
}
-static inline unsigned long print_context_stack(struct thread_info *tinfo,
+/* The form of the top of the frame on the stack */
+struct stack_frame {
+ struct stack_frame *next_frame;
+ unsigned long return_address;
+};
+
+
+static inline unsigned long print_context_stack(void *tinfo,
unsigned long *stack, unsigned long ebp,
const struct stacktrace_ops *ops, void *data,
unsigned long *end)
{
+
+#ifdef CONFIG_FRAME_POINTER
+ struct stack_frame *frame = (struct stack_frame *)ebp;
+
/*
- * Print function call entries within a stack. 'cond' is the
- * "end of stackframe" condition, that the 'stack++'
- * iteration will eventually trigger.
+ * if EBP is in the current stack frame, use stack frame tracking;
+ * otherwise fall back to the traditional method.
*/
- while (valid_stack_ptr(tinfo, stack, 3, end))) {
+
+ if (valid_stack_ptr(tinfo, frame, sizeof(*frame), end)) {
+ while (valid_stack_ptr(tinfo, frame, sizeof(*frame), end)) {
+ struct stack_frame *next;
+ unsigned long addr;
+
+ addr = frame->return_address;
+ if (__kernel_text_address(addr))
+ ops->address(data, addr);
+ /*
+ * break out of recursive entries (such as
+ * end_of_stack_stop_unwind_function). Also,
+ * we can never allow a frame pointer to
+ * move downwards!
+ */
+ next = frame->next_frame;
+ ebp = (unsigned long)next;
+ if (next <= frame)
+ break;
+ frame = next;
+ }
+ } else
+#endif
+ /*
+ * Print function call entries within a stack.
+ * The end condition is either a bound on the stack, or
+ * an invalid stack ptr, depending on the caller.
+ */
+ while (valid_stack_ptr(tinfo, stack, 3, end)) {
unsigned long addr = *stack++;
/* Use unlocked access here because except for NMIs
we should be already protected against module unloads */
@@ -258,6 +296,7 @@ void dump_trace(struct task_struct *tsk,
unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr;
unsigned used = 0;
struct thread_info *tinfo;
+ unsigned long ebp = 0;
if (!tsk)
tsk = current;
@@ -270,6 +309,19 @@ void dump_trace(struct task_struct *tsk,
stack = (unsigned long *)tsk->thread.rsp;
}
+#ifdef CONFIG_FRAME_POINTER
+ if (!ebp) {
+ if (tsk == current) {
+ /* Grab ebp right from our regs */
+ asm("movq %%rbp, %0" : "=r" (ebp):);
+ } else {
+ /* ebp is the last reg pushed by switch_to */
+ ebp = *(unsigned long *) tsk->thread.rsp;
+ }
+ }
+#endif
+
+
/*
* Print function call entries in all stacks, starting at the
@@ -286,8 +338,8 @@ void dump_trace(struct task_struct *tsk,
if (ops->stack(data, id) < 0)
break;
- print_context_stack(tinfo, stack, 0, ops,
- data, estack_end);
+ ebp = print_context_stack(tinfo, stack, ebp, ops,
+ data, estack_end);
ops->stack(data, "<EOE>");
/*
* We link to the next stack via the
@@ -305,8 +357,8 @@ void dump_trace(struct task_struct *tsk,
if (stack >= irqstack && stack < irqstack_end) {
if (ops->stack(data, "IRQ") < 0)
break;
- print_context_stack(tinfo, stack, 0, ops,
- data, irqstack_end);
+ ebp = print_context_stack(tinfo, stack, ebp,
+ ops, data, irqstack_end);
/*
* We link to the next stack (which would be
* the process stack normally) the last
@@ -324,7 +376,7 @@ void dump_trace(struct task_struct *tsk,
/*
* This handles the process stack:
*/
- print_context_stack(tinfo, stack, 0, ops, data, NULL);
+ ebp = print_context_stack(tinfo, stack, ebp, ops, data, NULL);
put_cpu();
}
EXPORT_SYMBOL(dump_trace);
--
If you want to reach me at my work email, use arjan@linux.intel.com
For development, discussion and tips for power savings,
visit http://www.lesswatts.org
next reply other threads:[~2008-01-08 5:14 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-08 5:14 Arjan van de Ven [this message]
2008-01-08 7:11 ` Ingo Molnar
2008-01-08 17:01 ` Andi Kleen
2008-01-08 17:28 ` Arjan van de Ven
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080107211437.5ba42f18@laptopd505.fenrus.org \
--to=arjan@infradead.org \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=tglx@tglx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®