|
@@ -70,17 +70,30 @@ int notrace unwind_frame(struct stackframe *frame)
|
|
|
* Check whether we are going to walk through from interrupt stack
|
|
|
* to task stack.
|
|
|
* If we reach the end of the stack - and its an interrupt stack,
|
|
|
- * read the original task stack pointer from the dummy frame.
|
|
|
+ * unpack the dummy frame to find the original elr.
|
|
|
*
|
|
|
* Check the frame->fp we read from the bottom of the irq_stack,
|
|
|
* and the original task stack pointer are both in current->stack.
|
|
|
*/
|
|
|
if (frame->sp == irq_stack_ptr) {
|
|
|
+ struct pt_regs *irq_args;
|
|
|
unsigned long orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr);
|
|
|
|
|
|
- if(object_is_on_stack((void *)orig_sp) &&
|
|
|
- object_is_on_stack((void *)frame->fp))
|
|
|
+ if (object_is_on_stack((void *)orig_sp) &&
|
|
|
+ object_is_on_stack((void *)frame->fp)) {
|
|
|
frame->sp = orig_sp;
|
|
|
+
|
|
|
+ /* orig_sp is the saved pt_regs, find the elr */
|
|
|
+ irq_args = (struct pt_regs *)orig_sp;
|
|
|
+ frame->pc = irq_args->pc;
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * This frame has a non-standard format, and we
|
|
|
+ * didn't fix it, because the data looked wrong.
|
|
|
+ * Refuse to output this frame.
|
|
|
+ */
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return 0;
|