summaryrefslogtreecommitdiff
path: root/arch/sh/kernel/dwarf.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-02-25 20:41:34 (GMT)
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-02-25 20:41:34 (GMT)
commit2a2d10f386c1bacabe1a530c06dc8488eac419e5 (patch)
tree4606a4a3bafa42a8aa70e001d35883956a0f0589 /arch/sh/kernel/dwarf.c
parent2f68ffd11aa76b251921976c982b814df9ebe890 (diff)
parentc499546f43f2c31b681271ef7db922839fcde5fe (diff)
downloadlinux-2a2d10f386c1bacabe1a530c06dc8488eac419e5.tar.xz
Merge branch 'for-rmk' of git://git.marvell.com/orion into devel-stable
Diffstat (limited to 'arch/sh/kernel/dwarf.c')
-rw-r--r--arch/sh/kernel/dwarf.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index 88d28ec..e511680 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -540,6 +540,8 @@ void dwarf_free_frame(struct dwarf_frame *frame)
mempool_free(frame, dwarf_frame_pool);
}
+extern void ret_from_irq(void);
+
/**
* dwarf_unwind_stack - unwind the stack
*
@@ -678,6 +680,24 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc,
addr = frame->cfa + reg->addr;
frame->return_addr = __raw_readl(addr);
+ /*
+ * Ah, the joys of unwinding through interrupts.
+ *
+ * Interrupts are tricky - the DWARF info needs to be _really_
+ * accurate and unfortunately I'm seeing a lot of bogus DWARF
+ * info. For example, I've seen interrupts occur in epilogues
+ * just after the frame pointer (r14) had been restored. The
+ * problem was that the DWARF info claimed that the CFA could be
+ * reached by using the value of the frame pointer before it was
+ * restored.
+ *
+ * So until the compiler can be trusted to produce reliable
+ * DWARF info when it really matters, let's stop unwinding once
+ * we've calculated the function that was interrupted.
+ */
+ if (prev && prev->pc == (unsigned long)ret_from_irq)
+ frame->return_addr = 0;
+
return frame;
bail: