Re: Fix a crash when stepping and unwinding fails

Daniel Jacobowitz
2006-02-21T20:28:39Z

On Tue, Feb 21, 2006 at 09:15:16PM +0100, Mark Kettenis wrote:
> > It's still not great, but at least it's an improvement over crashing.
> > It is reasonably likely that we've just stepped over a standard
> > function call, and that consequentially the function return
> > address is in the standard place for the architecture; in fact,
> > GDB used to have a hook for this, before the frame overhaul:
> > SAVED_PC_AFTER_CALL. But it's gone now and there's no easy analogue,
> > and it was never 100% reliable anyway. So unfortunately, if we
> > single-step out to an address that we can't find a way to unwind from,
> > we'll stop instead of stepping out.
>
> How can this happen? Both affected calls to
> insert_step_resume_breakpoint_at_frame() are in the same
>
> if (frame_id_eq (frame_unwind_id (get_current_frame ()), step_frame_id))
> {
>
> block. Assuming that step_frame_id isn't equal to null_frame_id, this
> means that we *can* unwind.

There's your problem: you're assuming that step_frame_id isn't equal to
null_frame_id. But in fact it is. If we can't unwind past the current
frame, then that means the last frame sniffer (generally the prologue
analyzer), which is required to accept any frame given to it, could not
make heads or tails of it. Which in turn means it doesn't know what
the frame's ID is, so it gets left as invalid. Which means the current
frame will have an ID of null_frame_id.

That's what's happening to me, although I seem to recall something
similar could be produced by stepping across main without debug info.

> Seems like the problem is that the code
> uses get_prev_frame(), which can return NULL, even if we could unwind,
> for example when we try to unwind past main. Looks to me the real bug
> here is that we're using get_prev_frame(). The right solution is
> probably to use frame_pc_unwind(), and insert a the step resume
> breakpoint there. That should never fail.
>
> This would probably demand us to introduce
> insert_step_resume_breakpoint_at_pc(), and we could probably eliminate
> insert_step_resume_breakpoint_at_frame() altogether. An alternative
> would be to export get_prev_name_1() from frame.c (giving it a more
> useful name).

That seems like a good change indeed, but probably wouldn't fix this
problem.

Hmm, what does frame_pc_unwind do when we've hit the last frame? I'm
not sure it's meaningful.