From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id Q0GJNIYALGpOMAMAWB0awg (envelope-from ) for ; Fri, 12 Jun 2026 08:50:14 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=I0/S/YWI; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id C3F671E070; Fri, 12 Jun 2026 08:50: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=-6.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H2 autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.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 DA4991E070 for ; Fri, 12 Jun 2026 08:50:13 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 59F394B99F46 for ; Fri, 12 Jun 2026 12:50:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 59F394B99F46 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=I0/S/YWI Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 495B04BA2E1A for ; Fri, 12 Jun 2026 12:49:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 495B04BA2E1A Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 495B04BA2E1A Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1781268584; cv=none; b=rf2fPxqLL2+v1IOQhn4i/4q0o2PacRK501ZQN5iaZD+NjBG5jGln0gd2s/QDlAdH68sI0FL5gy8LfZf1a098M7HhjiVzB7hTKJfeeO6ZJyG0wtz5URVQmK8Px+BbfnY5kk1K65B5TD5V10GOuKDksHBGyW8L8NN2MN1+AT7T7C4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1781268584; c=relaxed/simple; bh=hIx7U1q7lxRD5Ur/NUI40kZQKs337a3EMsyrigQQL4g=; h=DKIM-Signature:Message-ID:Date:MIME-Version:Subject:To:From; b=Z89EhE5jk5KU1wE9gZbcgJl/Hb6ENVXf3dWt/8gMGGXU2lbwtX572C6H9RkSZr7sDO/PRmhop2o+Zg3Cx1VUu3KN8UFVq8zwr6UrqSidcUNvudufD/Rwv7RezcPpPOQsNY439tBxfjy5gEvR+AIVnQ9c9Jp0/VVsysQWYdKwyQE= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=I0/S/YWI DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 495B04BA2E1A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1781268583; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nMhPR8HoK5vAMKS4ljmKbArZQflQGh+BhphfqT+QtLo=; b=I0/S/YWIguIC3rYpRtjpDXcogvJPGx6KnnZZ4PpgkFnyJXIu0vCrxBQ3dOfuTItPRqWUpW Bkqqm6dBzIKjiMh7m65WGZRbTDQaRu9F6rf7NL9n/VUtDoMRfxcDrXdpsxSHAPNXHXaccD 5DILukn+wz96+wdn/2c5LgVfZ84aC+U= Received: from mail-vs1-f71.google.com (mail-vs1-f71.google.com [209.85.217.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-662-Me0C6JhaMlODYwAKH08rEw-1; Fri, 12 Jun 2026 08:49:42 -0400 X-MC-Unique: Me0C6JhaMlODYwAKH08rEw-1 X-Mimecast-MFC-AGG-ID: Me0C6JhaMlODYwAKH08rEw_1781268582 Received: by mail-vs1-f71.google.com with SMTP id ada2fe7eead31-6c4335eef08so987950137.0 for ; Fri, 12 Jun 2026 05:49:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781268582; x=1781873382; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=nMhPR8HoK5vAMKS4ljmKbArZQflQGh+BhphfqT+QtLo=; b=YQvxADYLIQDyBZOQy0NS0h3Oa5ZseuJeyceUV2VuTlh6cz7jTfFVa2ZIDGJa0qX5P3 Mlx4xkpgp/9A3OCVia142LQ/SNC9vjEWZKVk2bAgFQby5Ow7a2T4cNJuWZv8eEG9GqGv gjiTHzJZtVTNZDIrcAv/oKW63491MIiMHn7Dor3zYOvv5Paa1JH69607iqJ9KtOEWnrt YLbIHiFbLwHe1La+l2lZxIVqDRFsDe+t9IoVORIsi7lSCxPQd0x7+blIHnsXcqzkkkOe 94WH6GuV2N2SDTMeaNQMnpQmxd4s30vENlDoiYV0T63vJ/rPRYL40jI2Uh2N1g5j8L25 4cIQ== X-Forwarded-Encrypted: i=1; AFNElJ/qYPuM5CFt8rGgCntV/RmCVqRKV0YTXPqFAhNhHNuM4gVzzf9PNHkI44MQtXdZqum826lfD/uTHtnhxQ==@sourceware.org X-Gm-Message-State: AOJu0YypPk9rkSut9qywYRK/VK3cnA1YbcWtihrRHXqBaNm+j5MSeGJy 1ntYqOsPU80CbAp3wV/pJnBQvvj24RwW4TbID6lmMEZSU7rhW+QNanjFMPT88tAy/c2aLNNBLR9 W/pVP5kW1EgpQ0hPWazICEs7zfO9IhDkCZn8AxJERZAhhxaW8bW8MAgSpHWWuvUiKUMyYndk= X-Gm-Gg: Acq92OEyR7cY6WRaTMnFpHUPU9xNBz8dBbkUN7uTmRD1mJe14Tz/7p11dr5aXsnW5Nl 0XmfZzqFpiJSIN9Jjqz9TDh3n9qiJ2opoZP3QHrLon+MUHZEeKekbuXgBMy7DSr2+WcNjidmUhr UOs1l7A6RVYoLN9/7dmq1rCDu9ULDL0PrKqNgM0hOYmuun54fktkt8YhWAXnmdlL8TX6t55Xhw0 44LL1UAfs9QsiDEd80fnZ81y/sA+1fwtUas/Otr8wToBXHOTDR+vn5Hf/uOA87qvf/ZXVxAHvoi 88E2UyiuxLDoI46JMb+P7aHAYfJoB4+x97r1FjaG6qcqvTchlwNqF8ao8+OAP88mLNLawEuqGRq 4u5S2Kh9qFe5RW3Kw6QVuT4Y0YRarMaBX/MaUUtPZp+8vnkXxULrwGoSsxRBlN4RDw3fF X-Received: by 2002:a05:6102:f81:b0:62f:3e1d:a55a with SMTP id ada2fe7eead31-71e88aeb954mr1371031137.2.1781268581832; Fri, 12 Jun 2026 05:49:41 -0700 (PDT) X-Received: by 2002:a05:6102:f81:b0:62f:3e1d:a55a with SMTP id ada2fe7eead31-71e88aeb954mr1371018137.2.1781268581311; Fri, 12 Jun 2026 05:49:41 -0700 (PDT) Received: from ?IPV6:2804:14d:8084:993e:2d5d:7adb:2b6:a50e? ([2804:14d:8084:993e:2d5d:7adb:2b6:a50e]) by smtp.gmail.com with ESMTPSA id ada2fe7eead31-71e88a100f0sm1183482137.7.2026.06.12.05.49.39 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 12 Jun 2026 05:49:40 -0700 (PDT) Message-ID: <0e319062-cb2c-4873-aa7f-9e2236007581@redhat.com> Date: Fri, 12 Jun 2026 09:49:35 -0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] gdb: allow 'until' to work in outermost frame To: Andrew Burgess , gdb-patches@sourceware.org References: <41fe591d58ba010fa771e80ca674b61e30feef2f.1780942441.git.aburgess@redhat.com> <02e967d8-a06a-4774-8618-e8fddd665c26@redhat.com> <87o6hgq08x.fsf@redhat.com> From: Guinevere Larsen In-Reply-To: <87o6hgq08x.fsf@redhat.com> X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 8wElD36plEwzc1oZPCnrt53PqJmDmHFh0wx1IAbm83Q_1781268582 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed 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 6/11/26 5:40 PM, Andrew Burgess wrote: > Guinevere Larsen 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 >