diff options
Diffstat (limited to 'arch/arm/kernel/unwind.c')
| -rw-r--r-- | arch/arm/kernel/unwind.c | 19 |
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) | |||
| 332 | void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) | 335 | void 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; |
