diff options
Diffstat (limited to 'arch/arm/kernel/traps.c')
-rw-r--r-- | arch/arm/kernel/traps.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 79abc4ddc0cf..57eb0f6f6005 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/system.h> | 27 | #include <asm/system.h> |
28 | #include <asm/unistd.h> | 28 | #include <asm/unistd.h> |
29 | #include <asm/traps.h> | 29 | #include <asm/traps.h> |
30 | #include <asm/unwind.h> | ||
30 | 31 | ||
31 | #include "ptrace.h" | 32 | #include "ptrace.h" |
32 | #include "signal.h" | 33 | #include "signal.h" |
@@ -61,6 +62,7 @@ void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long | |||
61 | dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); | 62 | dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); |
62 | } | 63 | } |
63 | 64 | ||
65 | #ifndef CONFIG_ARM_UNWIND | ||
64 | /* | 66 | /* |
65 | * Stack pointers should always be within the kernels view of | 67 | * Stack pointers should always be within the kernels view of |
66 | * physical memory. If it is not there, then we can't dump | 68 | * physical memory. If it is not there, then we can't dump |
@@ -74,6 +76,7 @@ static int verify_stack(unsigned long sp) | |||
74 | 76 | ||
75 | return 0; | 77 | return 0; |
76 | } | 78 | } |
79 | #endif | ||
77 | 80 | ||
78 | /* | 81 | /* |
79 | * Dump out the contents of some memory nicely... | 82 | * Dump out the contents of some memory nicely... |
@@ -150,13 +153,33 @@ static void dump_instr(struct pt_regs *regs) | |||
150 | set_fs(fs); | 153 | set_fs(fs); |
151 | } | 154 | } |
152 | 155 | ||
156 | #ifdef CONFIG_ARM_UNWIND | ||
157 | static inline void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | ||
158 | { | ||
159 | unwind_backtrace(regs, tsk); | ||
160 | } | ||
161 | #else | ||
153 | static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | 162 | static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) |
154 | { | 163 | { |
155 | unsigned int fp; | 164 | unsigned int fp, mode; |
156 | int ok = 1; | 165 | int ok = 1; |
157 | 166 | ||
158 | printk("Backtrace: "); | 167 | printk("Backtrace: "); |
159 | fp = regs->ARM_fp; | 168 | |
169 | if (!tsk) | ||
170 | tsk = current; | ||
171 | |||
172 | if (regs) { | ||
173 | fp = regs->ARM_fp; | ||
174 | mode = processor_mode(regs); | ||
175 | } else if (tsk != current) { | ||
176 | fp = thread_saved_fp(tsk); | ||
177 | mode = 0x10; | ||
178 | } else { | ||
179 | asm("mov %0, fp" : "=r" (fp) : : "cc"); | ||
180 | mode = 0x10; | ||
181 | } | ||
182 | |||
160 | if (!fp) { | 183 | if (!fp) { |
161 | printk("no frame pointer"); | 184 | printk("no frame pointer"); |
162 | ok = 0; | 185 | ok = 0; |
@@ -168,29 +191,20 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
168 | printk("\n"); | 191 | printk("\n"); |
169 | 192 | ||
170 | if (ok) | 193 | if (ok) |
171 | c_backtrace(fp, processor_mode(regs)); | 194 | c_backtrace(fp, mode); |
172 | } | 195 | } |
196 | #endif | ||
173 | 197 | ||
174 | void dump_stack(void) | 198 | void dump_stack(void) |
175 | { | 199 | { |
176 | __backtrace(); | 200 | dump_backtrace(NULL, NULL); |
177 | } | 201 | } |
178 | 202 | ||
179 | EXPORT_SYMBOL(dump_stack); | 203 | EXPORT_SYMBOL(dump_stack); |
180 | 204 | ||
181 | void show_stack(struct task_struct *tsk, unsigned long *sp) | 205 | void show_stack(struct task_struct *tsk, unsigned long *sp) |
182 | { | 206 | { |
183 | unsigned long fp; | 207 | dump_backtrace(NULL, tsk); |
184 | |||
185 | if (!tsk) | ||
186 | tsk = current; | ||
187 | |||
188 | if (tsk != current) | ||
189 | fp = thread_saved_fp(tsk); | ||
190 | else | ||
191 | asm("mov %0, fp" : "=r" (fp) : : "cc"); | ||
192 | |||
193 | c_backtrace(fp, 0x10); | ||
194 | barrier(); | 208 | barrier(); |
195 | } | 209 | } |
196 | 210 | ||