Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Guinevere Larsen <guinevere@redhat.com>
To: Andrew Burgess <aburgess@redhat.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH] gdb: allow 'until' to work in outermost frame
Date: Fri, 12 Jun 2026 09:49:35 -0300	[thread overview]
Message-ID: <0e319062-cb2c-4873-aa7f-9e2236007581@redhat.com> (raw)
In-Reply-To: <87o6hgq08x.fsf@redhat.com>

On 6/11/26 5:40 PM, Andrew Burgess wrote:
> Guinevere Larsen <guinevere@redhat.com> writes:
>
>> On 6/8/26 3:14 PM, Andrew Burgess wrote:
>>> The 'until' command with an argument, e.g. 'until *ADDRESS', is
>>> implemented by the until_break_command in breakpoint.c.
>>>
>>> The most important thing this function does is convert the location
>>> argument '*ADDRESS' in my example, into a vector of symtab_and_line
>>> objects.  Each of these symtab_and_line objects is then used to create
>>> a temporary bp_until breakpoint.
>>>
>>> The other thing that until_break_command does is create a breakpoint
>>> in the caller frame.  This breakpoint is there to ensure the inferior
>>> stops upon exiting the frame in which the 'until' command was issued.
>>>
>>> When compiling an assembler file into a static test program, if I use
>>> 'starti' to stop the inferior within the outermost frame, and then try
>>> to use 'until *ADDRESS' I see the following error:
>>>
>>>     (gdb) starti
>>>     Starting program: /tmp/hello
>>>
>>>     Program stopped.
>>>     0x0000000000401000 in _start ()
>>>     (gdb) bt
>>>     #0  0x0000000000401000 in _start ()
>>>     (gdb) until *0x0000000000401015
>>>     Warning:
>>>     Cannot insert breakpoint 0.
>>>     Cannot access memory at address 0x1
>>>
>>>     Command aborted.
>>>     (gdb)
>>>
>>> The problem here is the breakpoint that 'until' tries to create in the
>>> caller frame.  Though the 'bt' in the above example indicates that
>>> there is only a single frame, the outermost frame, this is only
>>> because GDB has specific code in get_prev_frame to stop the backtrace
>>> at the outermost frame.  If we turn this off and try 'bt' again:
>>>
>>>     (gdb) set backtrace past-entry on
>>>     (gdb) bt
>>>     #0  0x0000000000401000 in _start ()
>>>     #1  0x0000000000000001 in ?? ()
>>>     #2  0x00007fffffffac73 in ?? ()
>>>     #3  0x0000000000000000 in ?? ()
>>>     (gdb)
>>>
>>> What we are seeing here is the garbage values that happen to be in the
>>> registers tricking GDB into thinking there are frames before _start.
>>>
>>> GDB's code to handle this is in get_prev_frame, however, when 'until'
>>> creates the caller frame breakpoint it calls frame_unwind_caller_pc
>>> which calls frame_unwind_caller_frame, which skips get_prev_frame and
>>> calls get_prev_frame_always.  As a result, the 'until' command will
>>> try to place a breakpoint in the bogus frame #1 shown above.  As the
>>> frame is at address 0x1, which is non-writable, we see an error when
>>> trying to insert the breakpoint.
>>>
>>> In this commit I propose that we share the outer frame detection logic
>>> between get_prev_frame and frame_unwind_caller_frame.  When 'backtrace
>>> past-entry' is off, which is the default, frame_unwind_caller_frame
>>> will return NULL for the outermost frame.  This means that a command
>>> like 'until *ADDRESS' will no longer try to create a breakpoint in the
>>> caller frame when used in the outermost frame.
>> Why not simply change frame_unwind_caller_frame to call get_prev_frame
>> instead of get_prev_frame_always? feels like it would be a better idea
>> to not assume that the caller is always available anyway, rather than
>> porting the bits of work-arounds back to it
> That's a great question.  get_prev_frame presents a "user" configured
> view of the backtrace, for example it will stop at 'main', or the user
> can adjust the number of visible frame with 'set backtrace limit N'.  In
> these cases it is possible that get_prev_frame will return NULL
> indicating that there is no previous frame, when in reality, there is a
> previous frame.
>
> In the context of the "until" command, where we want to place a
> breakpoint in the caller frame, we want that breakpoint created even if
> the user wouldn't normally see the caller frame in the 'bt' output.
>
> As a concrete example, if a user makes use of 'until' in the 'main'
> function, but the 'until' line is not hit, then GDB should stop upon
> return from 'main'.  If we used get_prev_frame that wouldn't happen as
> the previous frame is usually hidden from the user.

I see. The explanation makes perfect sense, but then I have further 
questions about either the naming convention or the functionality of 
get_prev_frame_always.

Based on the names, without exploring functionality, it seemed to me 
that "get_prev_frame" should be the version called in the rest of the 
code, and it would itself call "get_prev_frame_always", as it has 
guaranteed that there must be a previous frame and would avoid or handle 
the errors. In this understading, the _always version is essentially 
just a helper that separates the inferior reading from the error handling.

If some other functions can call "get_prev_frame_always" directly, I 
think that function should identify when no previous frame exists and 
not return anything (therefore using "always" as the opposition for the 
user option). Another option would be to rename "get_prev_frame" to make 
it apparent that it is the user-configured view (maybe 
get_user_prev_frame), and have an actual get_prev_frame that works in 
the (in my opinion, more intuitive) way, so that get_prev_frame_always 
can continue to work as it does now.

Bottom line is that I think there should be a function that handles 
points 3 and 4 that is called by those that call 
"get_prev_frame_always", so that we don't need to export this logic to 
all callers.

-- 
Cheers,
Guinevere Larsen
it/its
she/her (deprecated)

>
> The entry frame is different.  The entry frame is the very first frame,
> and there are no earlier frames.  But, that doesn't mean that GDB
> doesn't see earlier frames!  If the inferior starts with garbage in its
> registers then GDB might think there are frames before the entry frame,
> but the chances are these frames are completely bogus, and trying to
> place a breakpoint in them will only cause problems (e.g. cannot write
> to memory errors).
>
> If we look at all the checks in get_prev_frame there are:
>
>    1. Should the unwind stop at main?  This check should be ignored for
>       things like 'until'.
>
>    2. Has the user backtrace limit been reached?  This check should be
>       ignored for things like 'until'.
>
>    3. Has the entry frame been reached?  I think this check should apply
>       in the 'until' case.
>
>    4. Have we reached a frame with a zero $pc?  I'm unsure about this
>       one, so chose to ignore it for now.  It's possible that this should
>       also apply in the 'until' case, but I've chosen to ignore this case
>       for now without a motivating example.
>
> A final note, I'm about to post a V2 for this patch, as what I posted
> here still has some problems.
>
> Thanks,
> Andrew
>


  reply	other threads:[~2026-06-12 12:50 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-08 18:14 Andrew Burgess
2026-06-11 19:24 ` Guinevere Larsen
2026-06-11 20:40   ` Andrew Burgess
2026-06-12 12:49     ` Guinevere Larsen [this message]
2026-06-11 21:59 ` [PATCHv2 0/3] " Andrew Burgess
2026-06-11 21:59   ` [PATCHv2 1/3] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-06-12 15:41     ` Pedro Alves
2026-06-11 21:59   ` [PATCHv2 2/3] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-06-12  6:07     ` Eli Zaretskii
2026-06-15 10:14       ` Andrew Burgess
2026-06-15 12:01         ` Eli Zaretskii
2026-06-12 15:41     ` Pedro Alves
2026-06-15 10:29       ` Andrew Burgess
2026-06-16 18:36         ` Pedro Alves
2026-06-23  9:46           ` Andrew Burgess
2026-06-23 10:20             ` Pedro Alves
2026-06-11 21:59   ` [PATCHv2 3/3] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-12 15:57     ` Pedro Alves
2026-06-16 19:47   ` [PATCHv3 0/4] " Andrew Burgess
2026-06-16 19:47     ` [PATCHv3 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-06-16 19:47     ` [PATCHv3 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-06-17 11:52       ` Eli Zaretskii
2026-06-16 19:47     ` [PATCHv3 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-16 19:47     ` [PATCHv3 4/4] gdb: cache program space entry point information Andrew Burgess
2026-06-23 10:47     ` [PATCHv4 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-23 10:47       ` [PATCHv4 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-06-23 10:47       ` [PATCHv4 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-06-23 10:47       ` [PATCHv4 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-23 10:47       ` [PATCHv4 4/4] gdb: cache program space entry point information Andrew Burgess
2026-06-25 15:26       ` [PATCHv5 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-25 15:26         ` [PATCHv5 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-06-25 15:26         ` [PATCHv5 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-06-25 15:26         ` [PATCHv5 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-25 15:26         ` [PATCHv5 4/4] gdb: cache program space entry point information Andrew Burgess
2026-07-10 14:24         ` [PATCHv6 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-10 14:24           ` [PATCHv6 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-07-10 14:24           ` [PATCHv6 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-07-10 15:39             ` Simon Marchi
2026-07-10 14:24           ` [PATCHv6 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-10 17:00             ` Simon Marchi
2026-07-10 17:01               ` Simon Marchi
2026-07-16 15:06               ` Andrew Burgess
2026-07-10 14:24           ` [PATCHv6 4/4] gdb: cache program space entry point information Andrew Burgess
2026-07-10 17:07             ` Simon Marchi
2026-07-18 13:11           ` [PATCHv7 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-18 13:11             ` [PATCHv7 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-07-18 13:11             ` [PATCHv7 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-07-18 13:11             ` [PATCHv7 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-18 13:11             ` [PATCHv7 4/4] gdb: cache program space entry point information Andrew Burgess
2026-07-20  9:52             ` [PATCHv8 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-20  9:52               ` [PATCHv8 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-07-20  9:52               ` [PATCHv8 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-07-20  9:52               ` [PATCHv8 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-20  9:52               ` [PATCHv8 4/4] gdb: cache program space entry point information Andrew Burgess

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0e319062-cb2c-4873-aa7f-9e2236007581@redhat.com \
    --to=guinevere@redhat.com \
    --cc=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox