Re: gdb command "next" wrongly working as command "step"

Andrew Burgess <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>
* William Tambe <[email protected]> [2019-09-01 14:05:56 -0500]:

> On Mon, Aug 26, 2019 at 8:18 AM Pedro Alves <[email protected]> wrote:
> >
> > On 8/25/19 8:04 PM, William Tambe wrote:
> > > Please see below, less noisy GDB output showing a working backtrace
> > > where I can see the caller in frame #1; but yet GDB command "next" is
> > > working as though it was "step"; any suggestion where else I could
> > > look ?
> >
> > - You'll just have to debug gdb.  Try to figure out why this code, inside
> >   the "infrun: stepped into subroutine" block,seemingly isn't being reached:
> >
> >         /* Set a breakpoint at callee's return address (the address
> >            at which the caller will resume).  */
> >         insert_step_resume_breakpoint_at_caller (frame);
> >
> > - I'd use "nexti" instead of "next" to try stepping over the
> >   instruction that calls the subroutine, just to make it easier
> >   to debug what goes wrong.
> 
> I have debugged the issue that I am having to be originating from
> frame_id_eq(); see below patch that I apply to work-around the issue I
> am having; I am sure it is not the fix.
> 
> frame_id_eq() is used to check whether two frames are identical, and
> in comparing the two frames it will compare whether the two frames
> have the same program-counter value.
> 
> I caught GDB comparing two identical frames differing only by their
> program-counter values; where in one frame, the program-counter value
> would be at the first instruction of the line making the
> function-call, while in the other frame the program-counter value
> would be at the return-address from the function-call.

From this description, my guess is that your bug is in your
implementation of the frame_this_id method.

The frame_id of a function is (basically) made of a $sp and $pc value.
The $sp should be the $sp on entry to the frame (or the frame base
address, which is similar), and the $pc should be for the start of the
function.

It sounds to me (just a guess based on the above) that your
frame_this_id method is just using the current $pc in the frame to
build the frame id.  This would explain the issues you are seeing.

Thanks,
Andrew



> 
> I will guess that, when "next" is used, GDB does not always use the
> frame program-counter value after the jump-and-link instruction within
> the line making the function-call, but instead use the frame
> program-counter value of the first instruction of the line making
> function-call.
> To get the program-counter value of a frame, I see GDB calling the
> callback function (struct frame_unwind *)->prev_register(); and in my
> GDB port, that function returns the program-counter value after the
> jump-and-link instruction; I will guess that GDB does not always use
> that callback function to get the program-counter value of a frame; in
> that case, what would be the other function that GDB uses to get the
> program-counter value of a frame ?
> 
> As mentioned above, here-after is patch that I apply to work-around
> the issue I am having.
> Any idea what I am missing in my GDB port such that I wouldn't need
> the patch below ?
> 
> diff --git a/gdb/frame.c b/gdb/frame.c
> index d8b5f819f1..c75f8ead38 100644
> --- a/gdb/frame.c
> +++ b/gdb/frame.c
> @@ -707,10 +707,14 @@ frame_id_eq (struct frame_id l, struct frame_id r)
>    else if (l.stack_status != r.stack_status || l.stack_addr != r.stack_addr)
>      /* If .stack addresses are different, the frames are different.  */
>      eq = 0;
> +#if 0
> +  // ### Disabled for now; as .code addresses could be
> +  // ### different while still being for the same frame.
>    else if (l.code_addr_p && r.code_addr_p && l.code_addr != r.code_addr)
>      /* An invalid code addr is a wild card.  If .code addresses are
>         different, the frames are different.  */
>      eq = 0;
> +#endif
>    else if (l.special_addr_p && r.special_addr_p
>            && l.special_addr != r.special_addr)
>      /* An invalid special addr is a wild card (or unused).  Otherwise
> 
> 
> >
> > Thanks,
> > Pedro Alves
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.