|
|
@@ -320,10 +320,14 @@ bool unwind_next_frame(struct unwind_state *state)
|
|
|
}
|
|
|
|
|
|
/* Get the next frame pointer: */
|
|
|
- if (state->regs)
|
|
|
+ if (state->next_bp) {
|
|
|
+ next_bp = state->next_bp;
|
|
|
+ state->next_bp = NULL;
|
|
|
+ } else if (state->regs) {
|
|
|
next_bp = (unsigned long *)state->regs->bp;
|
|
|
- else
|
|
|
+ } else {
|
|
|
next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task, *state->bp);
|
|
|
+ }
|
|
|
|
|
|
/* Move to the next frame if it's safe: */
|
|
|
if (!update_stack_state(state, next_bp))
|
|
|
@@ -398,6 +402,21 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
|
|
|
|
|
bp = get_frame_pointer(task, regs);
|
|
|
|
|
|
+ /*
|
|
|
+ * If we crash with IP==0, the last successfully executed instruction
|
|
|
+ * was probably an indirect function call with a NULL function pointer.
|
|
|
+ * That means that SP points into the middle of an incomplete frame:
|
|
|
+ * *SP is a return pointer, and *(SP-sizeof(unsigned long)) is where we
|
|
|
+ * would have written a frame pointer if we hadn't crashed.
|
|
|
+ * Pretend that the frame is complete and that BP points to it, but save
|
|
|
+ * the real BP so that we can use it when looking for the next frame.
|
|
|
+ */
|
|
|
+ if (regs && regs->ip == 0 &&
|
|
|
+ (unsigned long *)kernel_stack_pointer(regs) >= first_frame) {
|
|
|
+ state->next_bp = bp;
|
|
|
+ bp = ((unsigned long *)kernel_stack_pointer(regs)) - 1;
|
|
|
+ }
|
|
|
+
|
|
|
/* Initialize stack info and make sure the frame data is accessible: */
|
|
|
get_stack_info(bp, state->task, &state->stack_info,
|
|
|
&state->stack_mask);
|
|
|
@@ -410,7 +429,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
|
|
*/
|
|
|
while (!unwind_done(state) &&
|
|
|
(!on_stack(&state->stack_info, first_frame, sizeof(long)) ||
|
|
|
- state->bp < first_frame))
|
|
|
+ (state->next_bp == NULL && state->bp < first_frame)))
|
|
|
unwind_next_frame(state);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(__unwind_start);
|