From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 4Z4JLGa24GpbaS8AWB0awg (envelope-from ) for ; Tue, 27 Oct 2026 10:34:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=simark.ca; s=mail; t=1793111654; bh=H0gWe0lRB8TswGGvw7hNyp1rrXfdKnC4g5SZ5KiEyXc=; h=Date:Subject:To:Cc:References:From:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=JBOvkQsnN0sldamhgquF7MRvf9YZusTsvyu2ozf8E1WbG4NXwOr/8p5rx/mVCp2vU aIvcQKXcLQkysBVuETBVu9jaKpUfQ0caQdCjk0L/43Xw0cBx/GwE0VQWbOqnOISaB9 oZCcqVsIb+q929t/axyitxZfw5Q1uYEPFLf9oQHc= Received: by simark.ca (Postfix, from userid 112) id B0678378002; Tue, 27 Oct 2026 10:34:14 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=simark.ca header.i=@simark.ca header.a=rsa-sha256 header.s=mail header.b=Szcohu4F; dkim-atps=neutral Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id CE2A3378002 for ; Tue, 27 Oct 2026 10:34:13 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 38AFF4BA7980 for ; Tue, 27 Oct 2026 14:34:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 38AFF4BA7980 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=simark.ca header.i=@simark.ca header.a=rsa-sha256 header.s=mail header.b=Szcohu4F Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id E1E584BA23D0 for ; Tue, 27 Oct 2026 14:33:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E1E584BA23D0 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=simark.ca Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=simark.ca ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E1E584BA23D0 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1793111627; cv=none; b=M7PX+sQ168Fy3oIDzCSkHkN0HvI8nXrmkEJc8Dq93bO0/ZplJiuy2ZHxg3miCzEG+RiSuPah/2W3yXo1UdZxF1VGfzY2PjEMX2vMdWkBZSe368w1fdMa8tILCbg0wtVVl3UZM0J15XzIWiw/T/FElZwBaIOFeOw3EgSNw6AANAQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1793111627; c=relaxed/simple; bh=H0gWe0lRB8TswGGvw7hNyp1rrXfdKnC4g5SZ5KiEyXc=; h=DKIM-Signature:Message-ID:Date:MIME-Version:Subject:To:From; b=MjcKJTdCTuMpMuV+G0hDRzOd9INHV1Ju3jBDNTEqJ5zGgo2AFTgfiqlmSh50XTcINuF0q6H1qcmtMpL+GvL3bktg4Cu3wddKx8MXkMk4xz5hWJmJNq8WsIH6950CA2eu42IbzSqynMI1yjCYO9ZcUXF6HOSNwtUhiEY+ilab4V0= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=simark.ca header.i=@simark.ca header.a=rsa-sha256 header.s=mail header.b=Szcohu4F DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E1E584BA23D0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=simark.ca; s=mail; t=1793111625; bh=H0gWe0lRB8TswGGvw7hNyp1rrXfdKnC4g5SZ5KiEyXc=; h=Date:Subject:To:Cc:References:From:In-Reply-To:From; b=Szcohu4Ff+w8h95yaOpO2pHpxYCF8V1HWOYwKIMOtZnK5cwOBZZlptclLkjapO434 Ypu+Gc7VJn05SGLrbU524j9TH8AZtu9aTor2DVOCQxsGamA05gROKYd3Vus1G+OjOC GvWpKxuOApzQCVGVam/srIUPpJ9+MN1dBv5wv43s= Received: by simark.ca (Postfix) id 0303D378002; Tue, 27 Oct 2026 10:33:45 -0400 (EDT) Message-ID: <3ea54b53-eaa0-4532-a068-e7dc48a64ec7@simark.ca> Date: Tue, 27 Oct 2026 10:33:44 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCHv9 3/4] gdb: allow 'until' to work in outermost frame To: Andrew Burgess , gdb-patches@sourceware.org Cc: Simon Marchi References: <41fc9ac7b20577ba647a4be79b50b8f19811de9a.1787588386.git.aburgess@redhat.com> Content-Language: fr From: Simon Marchi In-Reply-To: <41fc9ac7b20577ba647a4be79b50b8f19811de9a.1787588386.git.aburgess@redhat.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org On 8/24/26 12:22 PM, Andrew Burgess wrote: > The 'until' command with an argument, e.g. 'until *ADDRESS', is > implemented by 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, > if the until breakpoint was not hit. > > 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, where we call > inside_entry_func. This checks if a frame is one of the two possible > entry frames, the inferior entry frame or the executable entry frame. > See the previous commit for more details. The important thing is that > the inferior entry frame is the absolute outer frame, the very first > frame that the inferior executed when starting, while the executable > entry frame is just the first frame within the main executable. > > There are a number of user configurable filters in get_prev_frame, the > backtrace past-main filter, the backtrace frame limit filter, and the > backtrace past-entry filter that we are discussing here. > > When creating the caller frame breakpoint, the 'until' command doesn't > use get_prev_frame, it uses frame_unwind_caller_frame, which calls > get_prev_frame_always. This is so that the user configurable filters > don't prevent the caller frame breakpoint from being created. But > this means that when creating the breakpoint, we skip the entry frame > check. 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 add an entry frame check into > frame_unwind_caller_frame path, similar to the one found in > get_prev_frame. > > To achieve this I create get_prev_frame_with_entry_frame_check, a new > function that checks if a frame is an entry frame, and returns NULL if > it is. Otherwise, get_prev_frame_with_entry_frame_check just calls > get_prev_frame_always. > > Then in get_prev_frame and frame_unwind_caller_frame, instead of > calling get_prev_frame_always directly, we can call the new > get_prev_frame_with_entry_frame_check. > > Finally, the existing entry frame check can be removed from > get_prev_frame. > > Notice that in moving the entry frame check from get_prev_frame I have > removed the 'frame_pc.has_value ()' check. Previously > inside_entry_func called get_frame_func which would throw if the > frame's $pc was not available. I have updated inside_entry_func to > call get_frame_func_if_available, which doesn't throw. As a result > the `frame_pc.has_value ()` check is no longer needed. > > An earlier version of this patch tried moving the inside_entry_frame > check into get_prev_frame_always, however, if get_prev_frame_always is > unable to unwind a frame then it must set the stop reason on the last > frame, this can be seen in `get_frame_unwind_stop_reason` where the > assert `gdb_assert (frame->prev_p);` will trigger if the previous > frame is not setup correctly. > > Setting the stop reason means the decision about whether there's a > previous frame or not is permanent (at least until the next frame > cache flush), but we need commands like 'bt -past-entry' to work, > which means the choice for whether there's a previous frame or not > needs to remain dynamic. > > The test for this fix ran into an issue where the frame-id for the > outermost frame would change between the first instruction and later > instructions in the frame. This was true for both the executable > entry frame and the inferior entry frame. I created bug PR gdb/34245 > for this issue. > > Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34245 You could also add: Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34211 Simon