unwind x86: Add dump_trace dwarf implementation
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
index 70bbe39..ed31d6d 100644
--- a/arch/x86/include/asm/stacktrace.h
+++ b/arch/x86/include/asm/stacktrace.h
@@ -47,6 +47,12 @@
unsigned long *stack, unsigned long bp,
const struct stacktrace_ops *ops, void *data);
+#ifdef CONFIG_DWARF_UNWIND
+void dump_trace_dwarf(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *stack, unsigned long bp,
+ const struct stacktrace_ops *ops, void *data);
+#endif
+
#ifdef CONFIG_X86_32
#define STACKSLOTS_PER_LINE 8
#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :)
diff --git a/arch/x86/kernel/dwarf_unwind/Makefile b/arch/x86/kernel/dwarf_unwind/Makefile
index 9a06b04..c8b91d5 100644
--- a/arch/x86/kernel/dwarf_unwind/Makefile
+++ b/arch/x86/kernel/dwarf_unwind/Makefile
@@ -1 +1 @@
-obj-y := regs.o
+obj-y := regs.o dumptrace.o
diff --git a/arch/x86/kernel/dwarf_unwind/dumptrace.c b/arch/x86/kernel/dwarf_unwind/dumptrace.c
new file mode 100644
index 0000000..950e3e0f
--- /dev/null
+++ b/arch/x86/kernel/dwarf_unwind/dumptrace.c
@@ -0,0 +1,50 @@
+
+#include <linux/dwarf_unwind.h>
+#include <asm/stacktrace.h>
+
+struct trace_data {
+ const struct stacktrace_ops *ops;
+ void *data;
+};
+
+static int unwind_trace(struct pt_regs *regs, void *data)
+{
+ struct trace_data *td = data;
+ const struct stacktrace_ops *ops = td->ops;
+
+ ops->address(td->data, regs->ip, 1);
+
+ return 0;
+}
+
+void dump_trace_dwarf(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *stack, unsigned long bp __maybe_unused,
+ const struct stacktrace_ops *ops, void *data)
+{
+ struct trace_data td = {
+ .ops = ops,
+ .data = data,
+ };
+ struct pt_regs regs_tmp;
+ unsigned long dummy;
+
+ if (!task)
+ task = current;
+
+ if (!stack) {
+ if (regs)
+ stack = (unsigned long *) regs->sp;
+ else if (task != current)
+ stack = (unsigned long *) task->thread.sp;
+ else
+ stack = &dummy;
+ }
+
+ if (!regs) {
+ regs_load(®s_tmp);
+ regs = ®s_tmp;
+ regs->sp = (unsigned long) stack;
+ }
+
+ dwarf_unwind(regs, unwind_trace, &td);
+}