From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id yRGWHGqrsmnU7SUAWB0awg (envelope-from ) for ; Thu, 12 Mar 2026 08:02:50 -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=CBTcVBVt; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=/BlyJvUm; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=a04LfeY6; dkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=RtFquCZh; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 6140E1E0DD; Thu, 12 Mar 2026 08:02:50 -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_MSPIKE_H2,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 715721E08D for ; Thu, 12 Mar 2026 08:02:48 -0400 (EDT) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id E044C4BBC0DA for ; Thu, 12 Mar 2026 12:02:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E044C4BBC0DA 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=CBTcVBVt; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=/BlyJvUm; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=a04LfeY6; dkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=RtFquCZh Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) by sourceware.org (Postfix) with ESMTPS id 6CB4E4BBC08B for ; Thu, 12 Mar 2026 12:02:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6CB4E4BBC08B 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 6CB4E4BBC08B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773316938; cv=none; b=PLmYnv5K2VOb3PE8ecFAWKNAjpUX3XEt79k+jWLc2OYk2nVZ1asr5VVWvtGg1uciV0xRGbyo1djzINNcz3kaaW2Op4bOopCTL8X1/x1eB6ETm9Hdlv8w4xEdcFgnwajQA2eil5SFioVFpZVnB2yEZlzmQZzltrgaCSjZhvgLEb4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773316938; c=relaxed/simple; bh=+2Ty6wkKdwHDoCSKkFx1NyyGk0t6/knCdAmhTApMmoY=; h=DKIM-Signature:DKIM-Signature:DKIM-Signature:DKIM-Signature:From: To:Subject:Date:Message-ID:MIME-Version; b=dKNNBJJTP6bwsfjZJTcGAnUID1xJWQWBd2loTQvpldjDKBlxhoDcAUdyqaIcuVFH0v6GdqiO/uNTwcSma3DHQkry2rhMiH7Jlszl2kv3ZadTe//i2SoxEFx8wSIcRvCKONcbN5UYktedDEN97S2lVQ0YI5FA8HKSN3muFj1rrFo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6CB4E4BBC08B Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104: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 684104D21B for ; Thu, 12 Mar 2026 12:02:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1773316937; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=7Y43xcWc9WDZWn86JD7W/4M3jrkHAPyGG+qyrqptRKo=; b=CBTcVBVtNJkFnnR2kdLiAOy/mjODn63oYZOqtr7PZk68phUZqVbmTzmPz9D0FOwjvktCU8 eHDVcs44PGrL/mz3ZYk5r6llygAiAmzB9dnvrR6aOha6IHAmrEfIl8w9bTWtAem/lQ2GlR zVhq8Sn+GeXC81OipCMr97k+kyZ013o= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1773316937; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=7Y43xcWc9WDZWn86JD7W/4M3jrkHAPyGG+qyrqptRKo=; b=/BlyJvUmF2jIdD7SgsM2h/3W3gdWwVhiSFSbuGHiXAkCjFkkqwmy46W7OMfEkOokOzXJuI fGLPwAf60MdGNtBw== Authentication-Results: smtp-out1.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b=a04LfeY6; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=RtFquCZh DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1773316932; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=7Y43xcWc9WDZWn86JD7W/4M3jrkHAPyGG+qyrqptRKo=; b=a04LfeY6wEnV1UHziJAOp6fTuZVeXYX2WZxN47kKnUtNd6tXf8k2wqj53xgN/ZiNvn1ELf saah47isSgQsc1T8tioxkubLrwFmurCfT9HV9Dw7kvZO7IoeG//HoiW15HcZ6h2n77dxgN 0XDDik2Fikg5cjLpfgS9iV7s5uNjGsw= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1773316932; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=7Y43xcWc9WDZWn86JD7W/4M3jrkHAPyGG+qyrqptRKo=; b=RtFquCZhcUCumgK55Yy6Mi+Vj260c2bPPz3yQtchNN77sh+ieSJwcHh5hD079OGmGGLESh 7nNzKj5o22n17yAQ== 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 5120D3FF65 for ; Thu, 12 Mar 2026 12:02:12 +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 RghuEkSrsmk0TwAAD6G6ig (envelope-from ) for ; Thu, 12 Mar 2026 12:02:12 +0000 From: Tom de Vries To: gdb-patches@sourceware.org Subject: [PATCH] [gdb] Fix missing print frame when stepping out of function Date: Thu, 12 Mar 2026 13:02:11 +0100 Message-ID: <20260312120211.3806600-1-tdevries@suse.de> X-Mailer: git-send-email 2.51.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspamd-Action: no action X-Rspamd-Server: rspamd2.dmz-prg2.suse.org X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; FUZZY_RATELIMITED(0.00)[rspamd.com]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; RCPT_COUNT_ONE(0.00)[1]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:helo,imap1.dmz-prg2.suse.org:rdns,sourceware.org:url,suse.de:dkim,suse.de:mid]; DWL_DNSWL_BLOCKED(0.00)[suse.de:dkim]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; RCVD_TLS_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; TO_DN_NONE(0.00)[]; PREVIOUSLY_DELIVERED(0.00)[gdb-patches@sourceware.org]; DKIM_TRACE(0.00)[suse.de:+] X-Rspamd-Queue-Id: 684104D21B 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 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 + && tp->control.step_frame_id != get_frame_id (frame)) + tp->control.step_frame_id_changed = true; tp->control.step_frame_id = get_frame_id (frame); tp->control.step_stack_frame_id = get_stack_frame_id (frame); @@ -8331,7 +8336,7 @@ process_event_stop_test (struct execution_control_state *ecs) paddress (gdbarch, ecs->event_thread->control.step_range_end), ecs->event_thread->control.may_range_step); if (refresh_step_info) - set_step_info (ecs->event_thread, frame, stop_pc_sal); + set_step_info (ecs->event_thread, frame, stop_pc_sal, true); infrun_debug_printf ("keep going"); @@ -9350,6 +9355,7 @@ print_stop_location (const target_waitstatus &ws) should) carry around the function and does (or should) use that when doing a frame comparison. */ if (tp->control.stop_step + && !tp->control.step_frame_id_changed && (tp->control.step_frame_id == get_frame_id (get_current_frame ())) && (tp->control.step_start_function diff --git a/gdb/infrun.h b/gdb/infrun.h index 0a7cdadf1fa..7fc7523be3f 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -205,10 +205,11 @@ extern int thread_is_stepping_over_breakpoint (int thread); triggers a non-steppable watchpoint. */ extern int stepping_past_nonsteppable_watchpoint (void); -/* Record in TP the frame and location we're currently stepping through. */ +/* Record in TP the frame and location we're currently stepping through. If + REFRESH_P, we're refreshing step info. */ extern 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 = false); /* Notify interpreters and observers that the current inferior has stopped with signal SIG. */ diff --git a/gdb/testsuite/gdb.dwarf2/dw2-extend-inline-block.exp b/gdb/testsuite/gdb.dwarf2/dw2-extend-inline-block.exp index 9e4798b53f3..3f92c1965d8 100644 --- a/gdb/testsuite/gdb.dwarf2/dw2-extend-inline-block.exp +++ b/gdb/testsuite/gdb.dwarf2/dw2-extend-inline-block.exp @@ -52,8 +52,11 @@ get_func_info main # Create DWARF for the test. In this case, inline function 'foo' is created # with a contiguous address range that needs extending. -proc build_dwarf_for_contiguous_block { asm_file } { +proc build_dwarf_for_contiguous_block { asm_file {range_correct 0} {variant 0}} { Dwarf::assemble $asm_file { + upvar range_correct range_correct + upvar variant variant + declare_labels lines_table inline_func cu { } { @@ -83,7 +86,11 @@ proc build_dwarf_for_contiguous_block { asm_file } { DW_AT_call_file 1 data1 DW_AT_call_line $::foo_call_line data1 DW_AT_low_pc main_1 addr - DW_AT_high_pc main_3 addr + if {$range_correct} { + DW_AT_high_pc main_4 addr + } else { + DW_AT_high_pc main_3 addr + } } } } @@ -120,10 +127,15 @@ proc build_dwarf_for_contiguous_block { asm_file } { DW_LNS_copy DW_LNE_set_address main_4 + if {$variant == 1} { + DW_LNS_advance_line 1 + } DW_LNS_copy DW_LNE_set_address main_5 - DW_LNS_advance_line 1 + if {$variant == 0} { + DW_LNS_advance_line 1 + } DW_LNS_negate_stmt DW_LNS_copy @@ -146,6 +158,22 @@ proc build_dwarf_for_contiguous_block { asm_file } { } } +# Like build_dwarf_for_contiguous_block, but use a slightly different line +# info by setting variant == 1. +# Use range_correct 1, so we're not testing the fix for PR33930. + +proc build_dwarf_for_contiguous_block_2 { asm_file } { + return [build_dwarf_for_contiguous_block $asm_file 1 1] +} + +# Like build_dwarf_for_contiguous_block, but use a slightly different line +# info by setting variant == 1. +# Use range_correct 0, so we're testing the fix for PR33930. + +proc build_dwarf_for_contiguous_block_3 { asm_file } { + return [build_dwarf_for_contiguous_block $asm_file 0 1] +} + # Assuming GDB is stopped at the entry $pc for 'foo', use 'maint info # blocks' to check the block for 'foo' is correct. This function checks # 'foo' created by 'build_dwarf_for_contiguous_block'. @@ -555,6 +583,12 @@ set test_list \ [list "contiguous block" \ build_dwarf_for_contiguous_block \ check_contiguous_block] \ + [list "contiguous block 2" \ + build_dwarf_for_contiguous_block_2 \ + check_contiguous_block] \ + [list "contiguous block 3" \ + build_dwarf_for_contiguous_block_3 \ + check_contiguous_block] \ ] # Run all the tests. @@ -566,6 +600,11 @@ foreach test_spec $test_list { set build_dwarf_func [lindex $test_spec 1] set check_block_func [lindex $test_spec 2] + if {$build_dwarf_func == "build_dwarf_for_contiguous_block_3"} { + # Work around PR33930. + continue + } + with_test_prefix $prefix { set asm_file [standard_output_file ${testfile}-${suffix}.S] $build_dwarf_func $asm_file base-commit: c8b798145ff623a87ec4d39015cf832b0160899d -- 2.51.0