From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id oea/Mb46vGnlhDAAWB0awg (envelope-from ) for ; Thu, 19 Mar 2026 14:04:46 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=00Do/Rcw; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=OFr5XsWm; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=00Do/Rcw; dkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=OFr5XsWm; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id C51241E0BC; Thu, 19 Mar 2026 14:04:46 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.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,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED 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 169711E08C for ; Thu, 19 Mar 2026 14:04:45 -0400 (EDT) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 99EF24B19694 for ; Thu, 19 Mar 2026 18:04:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 99EF24B19694 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=00Do/Rcw; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=OFr5XsWm; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=00Do/Rcw; dkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=OFr5XsWm Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2a07:de40:b251:101:10:150:64:1]) by sourceware.org (Postfix) with ESMTPS id E8E6B4BB590F for ; Thu, 19 Mar 2026 18:03:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E8E6B4BB590F Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E8E6B4BB590F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a07:de40:b251:101:10:150:64:1 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773943438; cv=none; b=ZBXhCgmSz6UuF3tCzgs6qa4aQzmHNZjNijUqeVggY65igRGPK8VwJiyy1sgfdYZaCCWCkSplr969MNMVY+3UvmyaNIDCZO2OWo/vI6LPq7/iuvu9hur/DwXrVWvjOuCNltzeDecnx5neipO5mOB87tYR8O0ITmAhkLcwE8x3GDQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773943438; c=relaxed/simple; bh=qkVbMXue4UxGyGjNS+Hc6bqFTqJQPGYOaai8lfnc/rE=; h=DKIM-Signature:DKIM-Signature:DKIM-Signature:DKIM-Signature: Message-ID:Date:MIME-Version:Subject:To:From; b=t0Kc95phCI/Qe2+3sSOgHOrtZMzJgfqazlFy2EGEBlrj1Vy5Gg9jo5XUJCqA1jnaOEV9dYfSBo6o43qCCPLgtBbnan90fmxKpooiLOvK/6+6UCALvXE/SMy/Xr6uitqWXuLosIjmzFxnqBsb9L8LcCOKG2bCmhWgAhlgTDRxXZ4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E8E6B4BB590F Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id BB1E94D218; Thu, 19 Mar 2026 18:03:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1773943435; h=from:from:reply-to: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=EyhWPBIrFM1Gu0JDlDeiePyrk8dXm3dDunx9X/EmHFc=; b=00Do/RcwaoQgnzXFHy0XWrcUtPxIQDM+O4fWVarzBY0VEFnana0BcWVQUPfkDDqDxZJKxe FXf07rK5SerYZmeR5l81fdqI3R0pvNzPoGKGjKpQhbejnkWyrYNcq5m8e9xEo6W7b8ywsD t6NN3wdqe9+ssh3Ol1hSPG/qTPDiptg= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1773943435; h=from:from:reply-to: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=EyhWPBIrFM1Gu0JDlDeiePyrk8dXm3dDunx9X/EmHFc=; b=OFr5XsWmzLfsj9PVO3eqJuPs0dOcbqK6pPAX/POLJZXXabdkomOVigWGloZti0xBm3Twm8 JswYuwIkdiakNXAw== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1773943435; h=from:from:reply-to: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=EyhWPBIrFM1Gu0JDlDeiePyrk8dXm3dDunx9X/EmHFc=; b=00Do/RcwaoQgnzXFHy0XWrcUtPxIQDM+O4fWVarzBY0VEFnana0BcWVQUPfkDDqDxZJKxe FXf07rK5SerYZmeR5l81fdqI3R0pvNzPoGKGjKpQhbejnkWyrYNcq5m8e9xEo6W7b8ywsD t6NN3wdqe9+ssh3Ol1hSPG/qTPDiptg= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1773943435; h=from:from:reply-to: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=EyhWPBIrFM1Gu0JDlDeiePyrk8dXm3dDunx9X/EmHFc=; b=OFr5XsWmzLfsj9PVO3eqJuPs0dOcbqK6pPAX/POLJZXXabdkomOVigWGloZti0xBm3Twm8 JswYuwIkdiakNXAw== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 9C9444273B; Thu, 19 Mar 2026 18:03:55 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id 4QzFJIs6vGm6WgAAD6G6ig (envelope-from ); Thu, 19 Mar 2026 18:03:55 +0000 Message-ID: <9e466544-aca0-4a0e-89fe-0221dfb5f7ed@suse.de> Date: Thu, 19 Mar 2026 19:03:55 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] [gdb] Fix missing print frame when stepping out of function To: Andrew Burgess , gdb-patches@sourceware.org References: <20260312120211.3806600-1-tdevries@suse.de> <871phh6wir.fsf@redhat.com> Content-Language: en-US From: Tom de Vries In-Reply-To: <871phh6wir.fsf@redhat.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spamd-Result: default: False [-4.29 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; NEURAL_HAM_SHORT(-0.19)[-0.953]; MIME_GOOD(-0.10)[text/plain]; RCVD_VIA_SMTP_AUTH(0.00)[]; FUZZY_RATELIMITED(0.00)[rspamd.com]; ARC_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; MID_RHS_MATCH_FROM(0.00)[]; RCPT_COUNT_TWO(0.00)[2]; RCVD_TLS_ALL(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; DBL_BLOCKED_OPENRESOLVER(0.00)[sourceware.org:url, suse.de:mid, suse.de:email, imap1.dmz-prg2.suse.org:helo] 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 3/18/26 3:29 PM, Andrew Burgess wrote: > Tom de Vries writes: > >> Consider test-case gdb.dwarf2/dw2-extend-inline-block.exp, specifically the >> "contiguous block" prefix part, which can be stepped through like this: >> ... >> $ gdb -q outputs/gdb.dwarf2/dw2-extend-inline-block/dw2-extend-inline-block-5 >> Reading symbols from dw2-extend-inline-block-5... >> (gdb) start >> ... >> Temporary breakpoint 1, main () at dw2-extend-inline-block.c:35 >> 35 /* main:2 */ >> (gdb) s >> 36 /* main:3 */ foo (); /* foo call line */ >> (gdb) >> foo () at dw2-extend-inline-block.c:26 >> 26 /* foo:1 */ >> (gdb) s >> 27 /* foo:2 */ >> (gdb) s >> 28 /* foo:3 */ >> (gdb) s >> main () at dw2-extend-inline-block.c:37 >> 37 /* main:4 */ >> (gdb) >> ... >> >> If we slightly modify the line program: >> ... >> DW_LNE_set_address main_4 >> + DW_LNS_advance_line 1 >> DW_LNS_copy >> >> DW_LNE_set_address main_5 >> - DW_LNS_advance_line 1 >> DW_LNS_negate_stmt >> DW_LNS_copy >> ... >> we change the 36/0x401165 entry into a 37/0x401165 entry: >> ... >> File name Line number Starting address View Stmt >> dw2-extend-inline-block.c 34 0x401116 x >> dw2-extend-inline-block.c 35 0x401129 x >> dw2-extend-inline-block.c 26 0x401138 x >> dw2-extend-inline-block.c 27 0x401147 x >> dw2-extend-inline-block.c 28 0x401156 x >> dw2-extend-inline-block.c 36 0x401156 >> -dw2-extend-inline-block.c 36 0x401165 >> +dw2-extend-inline-block.c 37 0x401165 >> dw2-extend-inline-block.c 37 0x401174 x >> dw2-extend-inline-block.c 38 0x401183 x >> dw2-extend-inline-block.c 39 0x401192 x >> dw2-extend-inline-block.c 40 0x4011a1 x >> dw2-extend-inline-block.c - 0x4011b7 >> ... >> >> As it happens, the fix to extend truncated inlined function blocks doesn't >> work in this case. This is PR33930. >> >> We can work around this by making sure that the inlined function block isn't >> truncated in the first place: >> ... >> - DW_AT_high_pc main_3 addr >> + DW_AT_high_pc main_4 addr >> ... >> >> But then we still run into PR33981: the problem that gdb doesn't notify us >> when stepping out of main: >> ... >> (gdb) step^M >> 28 /* foo:3 */^M >> (gdb) step^M >> 37 /* main:4 */^M >> (gdb) >> ... >> >> What happens is that the slightly different line program triggers a different >> stepping path, which includes a case of "stepped to a different frame, but >> it's not the start of a statement", which refreshes the stepping info and >> consequently updates tp->control.step_frame_id to the frame id of main. >> >> So by the time we're stopped at line 37, and are trying to figure out what to >> print in print_stop_location, this condition evaluates to true: >> ... >> if (tp->control.stop_step >> && (tp->control.step_frame_id >> == get_frame_id (get_current_frame ())) >> && (tp->control.step_start_function >> == find_symbol_for_pc (tp->stop_pc ()))) >> ... >> and we get: >> ... >> /* Finished step in same frame and same file, just print source >> line. */ >> source_flag = SRC_LINE; >> ... >> >> It's good to realize here that because foo is inlined into main, >> tp->control.step_start_function is not foo but main, so consequently the >> step_start_function check (which checks if we are still in the same function) >> also passes, even though we actually stepped from foo into main. >> >> No longer refreshing the stepping info in the "stepped to a different frame, >> but it's not the start of a statement" case does fix the problem. >> >> But the refreshing is needed to be able to handle stepping out of say function >> f1 into function f2 and immediately stepping back into f1 again. If we don't >> refresh in between, it looks like we stayed in f1. >> >> Fix this by: >> - adding a new field thread_control_state::step_frame_id_changed, >> - updating the new field in set_step_info when refreshing, and >> - using the new field in print_stop_location. >> >> Tested on x86_64-linux. >> >> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33981 >> --- >> gdb/gdbthread.h | 4 ++ >> gdb/infrun.c | 10 ++++- >> gdb/infrun.h | 5 ++- >> .../gdb.dwarf2/dw2-extend-inline-block.exp | 45 +++++++++++++++++-- >> 4 files changed, 57 insertions(+), 7 deletions(-) >> >> diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h >> index 68d7aebbbf7..02cf8f01fca 100644 >> --- a/gdb/gdbthread.h >> +++ b/gdb/gdbthread.h >> @@ -146,6 +146,10 @@ struct thread_control_state >> any inlined frames). */ >> struct frame_id step_stack_frame_id {}; >> >> + /* True if step_frame_id was changed after the stepping command was >> + issued. */ >> + bool step_frame_id_changed = false; >> + >> /* True if the thread is presently stepping over a breakpoint or >> a watchpoint, either with an inline step over or a displaced (out >> of line) step, and we're now expecting it to report a trap for >> diff --git a/gdb/infrun.c b/gdb/infrun.c >> index c05c2b0f42f..df55c9a3c66 100644 >> --- a/gdb/infrun.c >> +++ b/gdb/infrun.c >> @@ -3084,6 +3084,7 @@ clear_proceed_status_thread (struct thread_info *tp) >> tp->control.step_range_end = 0; >> tp->control.may_range_step = 0; >> tp->control.step_frame_id = null_frame_id; >> + tp->control.step_frame_id_changed = false; >> tp->control.step_stack_frame_id = null_frame_id; >> tp->control.step_over_calls = STEP_OVER_UNDEBUGGABLE; >> tp->control.step_start_function = nullptr; >> @@ -4818,12 +4819,16 @@ fetch_inferior_event () >> >> void >> set_step_info (thread_info *tp, const frame_info_ptr &frame, >> - struct symtab_and_line sal) >> + struct symtab_and_line sal, bool refresh_p) >> { >> /* This can be removed once this function no longer implicitly relies on the >> inferior_ptid value. */ >> gdb_assert (inferior_ptid == tp->ptid); >> >> + if (refresh_p >> + && tp->control.step_frame_id != null_frame_id > > Unfortunately, this doesn't work. Comparing frame_ids ends up in > frame_id::operator== in frame.c, which always returns false if either > frame-id is null_frame_id. As a result, the != above always returns > true. > > I think this is why you ended up having to add the refresh_p argument > maybe? As a *hack* to check this theory, I removed the check of > `refresh_p` here, and replaced the comparison to null_frame_id with: > > memcmp (&tp->control.step_frame_id, > &null_frame_id, > sizeof (decltype (null_frame_id))) != 0 > > NOTE: This is NOT actual proposed code, just a hack to test this theory. > > With these changes in place your modified dw2-extend-inline-block.exp > still passes. > > But I want to go back to something you said earlier: > >> It's good to realize here that because foo is inlined into main, >> tp->control.step_start_function is not foo but main, so consequently the >> step_start_function check (which checks if we are still in the same function) >> also passes, even though we actually stepped from foo into main. > > I haven't looked into the history of this, but I wonder if there is a > good reason why step_start_function doesn't record the actual function? > Again, without looking, my guess would be that this is just the way it > has always been, so maybe the answer here is to have step_start_function > track the actual function symbol. > > As a *hack* everywhere that step_start_function is set or referenced, > where we currently use `find_symbol_for_pc` I switched to use > `find_symbol_for_pc_sect_maybe_inline` passing nullptr for the section. > This would need dealing with properly for a real fix, but is good enough > for a quick test. With this change in place, and the GDB code parts of > your patch reverted, your modified test case still passes. > > I think that it is worth at least investigating altering > step_start_function to track the actual function, including inline > functions, this seems like it would be a better fix. But if not then at > least we'll understand why it's not the right solution. Hi, just a small update on this. I've given this a try ( https://github.com/vries/gdb/tree/gdb/fix-missing-print-frame-when-stepping-out-of-function-2 ) and ran into trouble with just one test-case, gdb.opt/inline-cmds.exp ). Basically, with current gdb we have: ... 63 x = 7; (gdb) s 64 y = 8; /* set mi break here */ (gdb) s 66 result = func1 (); (gdb) ... and with the patch series posted above: ... 63 x = 7; (gdb) s 64 y = 8; /* set mi break here */ (gdb) s main () at /data/vries/gdb/leap-16-0/build/../../src/gdb/testsuite/gdb.opt/inline-cmds.c:66 66 result = func1 (); (gdb) ... There is some code somewhere that allows entry into an inline function to happen in two steps, even if the pc stays the same inbetween, and that code seems to interact with the solution in the patch series. I'll take a further look tomorrow. Thanks, - Tom