aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/unwind.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-22 17:56:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-22 17:56:13 -0400
commit9e268beb92ee3a853b3946e84b10358207e2085f (patch)
treedec36344c8b16d53e56763aa174dd7ea806b653f /arch/arm/kernel/unwind.c
parent2e8b5a09ebf1f98f02c1988a48415e89d4c25168 (diff)
parent9ccdac3662dbf3c75e8f8851a214bdf7d365a4bd (diff)
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (49 commits) [ARM] idle: clean up pm_idle calling, obey hlt_counter [ARM] S3C: Fix gpio-config off-by-one bug [ARM] S3C64XX: add to_irq() support for EINT() GPIO [ARM] S3C64XX: clock.c: fix typo in usb-host clock ctrlbit [ARM] S3C64XX: fix HCLK gate defines [ARM] Update mach-types [ARM] wire up rt_tgsigqueueinfo and perf_counter_open OMAP2 clock/powerdomain: off by 1 error in loop timeout comparisons OMAP3 SDRC: set FIXEDDELAY when disabling SDRC DLL OMAP3: Add support for DPLL3 divisor values higher than 2 OMAP3 SRAM: convert SRAM code to use macros rather than magic numbers OMAP3 SRAM: add more comments on the SRAM code OMAP3 clock/SDRC: program SDRC_MR register during SDRC clock change OMAP3 clock: add a short delay when lowering CORE clk rate OMAP3 clock: initialize SDRC timings at kernel start OMAP3 clock: remove wait for DPLL3 M2 clock to stabilize [ARM] Add old Feroceon support to compressed/head.S [ARM] 5559/1: Limit the stack unwinding caused by a kthread exit [ARM] 5558/1: Add extra checks to ARM unwinder to avoid tracing corrupt stacks [ARM] 5557/1: Discard some ARM.ex*.*exit.text sections when !HOTPLUG or !HOTPLUG_CPU ...
Diffstat (limited to 'arch/arm/kernel/unwind.c')
-rw-r--r--arch/arm/kernel/unwind.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index 1dedc2c7ff49..dd56e11f339a 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -212,7 +212,8 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
212 ctrl->vrs[14] = *vsp++; 212 ctrl->vrs[14] = *vsp++;
213 ctrl->vrs[SP] = (unsigned long)vsp; 213 ctrl->vrs[SP] = (unsigned long)vsp;
214 } else if (insn == 0xb0) { 214 } else if (insn == 0xb0) {
215 ctrl->vrs[PC] = ctrl->vrs[LR]; 215 if (ctrl->vrs[PC] == 0)
216 ctrl->vrs[PC] = ctrl->vrs[LR];
216 /* no further processing */ 217 /* no further processing */
217 ctrl->entries = 0; 218 ctrl->entries = 0;
218 } else if (insn == 0xb1) { 219 } else if (insn == 0xb1) {
@@ -309,18 +310,20 @@ int unwind_frame(struct stackframe *frame)
309 } 310 }
310 311
311 while (ctrl.entries > 0) { 312 while (ctrl.entries > 0) {
312 int urc; 313 int urc = unwind_exec_insn(&ctrl);
313
314 if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high)
315 return -URC_FAILURE;
316 urc = unwind_exec_insn(&ctrl);
317 if (urc < 0) 314 if (urc < 0)
318 return urc; 315 return urc;
316 if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high)
317 return -URC_FAILURE;
319 } 318 }
320 319
321 if (ctrl.vrs[PC] == 0) 320 if (ctrl.vrs[PC] == 0)
322 ctrl.vrs[PC] = ctrl.vrs[LR]; 321 ctrl.vrs[PC] = ctrl.vrs[LR];
323 322
323 /* check for infinite loop */
324 if (frame->pc == ctrl.vrs[PC])
325 return -URC_FAILURE;
326
324 frame->fp = ctrl.vrs[FP]; 327 frame->fp = ctrl.vrs[FP];
325 frame->sp = ctrl.vrs[SP]; 328 frame->sp = ctrl.vrs[SP];
326 frame->lr = ctrl.vrs[LR]; 329 frame->lr = ctrl.vrs[LR];
@@ -332,7 +335,6 @@ int unwind_frame(struct stackframe *frame)
332void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) 335void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
333{ 336{
334 struct stackframe frame; 337 struct stackframe frame;
335 unsigned long high, low;
336 register unsigned long current_sp asm ("sp"); 338 register unsigned long current_sp asm ("sp");
337 339
338 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); 340 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
@@ -362,9 +364,6 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
362 frame.pc = thread_saved_pc(tsk); 364 frame.pc = thread_saved_pc(tsk);
363 } 365 }
364 366
365 low = frame.sp & ~(THREAD_SIZE - 1);
366 high = low + THREAD_SIZE;
367
368 while (1) { 367 while (1) {
369 int urc; 368 int urc;
370 unsigned long where = frame.pc; 369 unsigned long where = frame.pc;