[RFC REPOST] lib/bug: Show backtrace for generic WARN

From: Dave Martin
Date: Mon Jul 13 2015 - 11:23:45 EST


Some arches that don't rely on bug.c for WARN output rather more
information for WARNs than report_bug() does.

report_bug() does print the regs, but nothing else. Since WARNs
are indicators of possible bugs or violated assumptions in the
kernel, understanding the context that lead up to a WARN is
valuable for debugging. A symbolic backtrace is not too verbose,
and is more human-readable than register or stack dumps, so it
seems a good halfway house between printing nothing and printing
a stack dump.

This patch adds support for a backtrace between the oops markers
for WARN, for arches that don't generate the dump themselves.

show_stack() nearly does the right thing for this, but it doesn't
pass enough context to allow all arches to determine the initial
frame for the backtrace, so some arches just ignore the sp parameter
and generate a full backtrace with extraneous, irrelevant frames at
the top of the stack included.

This patch defines a new show_backtrace() interface which passes a
pt_regs instead of a bare stack pointer. A corresponding arch
helper arch_dump_backtrace() provides the actual arch-dependent
implementation, if HAVE_ARCH_DUMP_BACKTRACE is selected, otherwise
show_stack() is used as a fallback.

Signed-off-by: Dave Martin <Dave.Martin@xxxxxxx>
---

For arches that don't need anything except the stack pointer to
start the backtrace, we might be able to define a generic
arch_dump_backtrace() that invokes show_stack with sp instead of
just assuming the sp is unavailable, but as a minimum each arch
would have to provide a helper to extract the relevant value
from struct pt_regs.

The current patch does not assume the existence of such a per-arch
helper, but I'm open to suggestions about the cleanest solution.


include/linux/sched.h | 15 +++++++++++++++
lib/bug.c | 1 +
2 files changed, 16 insertions(+)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index 26a2e61..14fac57 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -364,6 +364,21 @@ extern void show_regs(struct pt_regs *);
*/
extern void show_stack(struct task_struct *task, unsigned long *sp);

+/*
+ * Similar to show_stack(), but with all regs instead of just the stack
+ * pointer. This permits clean dumping from the interrupted frame after
+ * an exception.
+ * Passing NULL for task prints a backtrace for the current thread.
+ * Passing NULL for regs prints the entire backtrace, like show_stack(NULL).
+ */
+#ifdef CONFIG_HAVE_ARCH_DUMP_BACKTRACE
+extern void arch_dump_backtrace(struct task_struct *task,
+ struct pt_regs *regs);
+#define show_backtrace(task, regs) arch_dump_backtrace(task, regs)
+#else
+#define show_backtrace(task, regs) show_stack(NULL, task)
+#endif /* ! CONFIG_HAVE_ARCH_DUMP_BACKTRACE */
+
extern void cpu_init (void);
extern void trap_init(void);
extern void update_process_times(int user);
diff --git a/lib/bug.c b/lib/bug.c
index 0c3bd95..feabf15 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -174,6 +174,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)

print_modules();
show_regs(regs);
+ show_backtrace(NULL, regs);
print_oops_end_marker();
/* Just a warning, don't kill lockdep. */
add_taint(BUG_GET_TAINT(bug), LOCKDEP_STILL_OK);
--
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/