From: Toby Lloyd Davies <tlloyddavies@undo.io>
To: gdb-patches@sourceware.org
Cc: Toby Lloyd Davies <tlloyddavies@undo.io>
Subject: [PATCH 2/3] gdb: Don't stop at non-statement line after stepping into inline function
Date: Thu, 1 Feb 2024 15:21:17 +0000 [thread overview]
Message-ID: <20240201152118.598375-3-tlloyddavies@undo.io> (raw)
In-Reply-To: <20240201152118.598375-1-tlloyddavies@undo.io>
Generally when stepping we only want to stop at lines that mark the
beginning of a statement i.e. have is_stmt set. However, when we stepped
into an inline function we would always stop regardless of whether
is_stmt was set on first line of the inline function. Fix this in
infrun.c:process_event_stop_test by not immediately stopping when
entering an inline function. Then code later in the function will decide
whether to stop based on whether is_stmt is set on the line.
Additionally, check if is_stmt is set on the line after stepping from an
inline callsite in infcmd.c:prepare_one_step. This fixes the bug when
the step starts directly at the inline function callsite.
---
gdb/infcmd.c | 3 +-
gdb/infrun.c | 32 ++--
.../gdb.dwarf2/dw2-inline-stepping-3.c | 50 ++++++
.../gdb.dwarf2/dw2-inline-stepping-3.exp | 153 ++++++++++++++++++
4 files changed, 226 insertions(+), 12 deletions(-)
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.c
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.exp
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 5e5f75021f2..22ab4dbebbc 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -964,7 +964,8 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
fn = sym->print_name ();
if (sal.line == 0
- || !function_name_is_marked_for_skip (fn, sal))
+ || ((inline_skipped_frames (tp) || sal.is_stmt)
+ && !function_name_is_marked_for_skip (fn, sal)))
{
sm->count--;
return prepare_one_step (tp, sm);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index a782c115cad..927e464e479 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8104,10 +8104,10 @@ process_event_stop_test (struct execution_control_state *ecs)
if (ecs->event_thread->control.step_over_calls == STEP_OVER_ALL
|| inline_frame_is_marked_for_skip (false, ecs->event_thread))
- keep_going (ecs);
- else
- end_stepping_range (ecs);
- return;
+ {
+ keep_going (ecs);
+ return;
+ }
}
/* Look for "calls" to inlined functions, part two. If the inline
@@ -8122,25 +8122,35 @@ process_event_stop_test (struct execution_control_state *ecs)
if (ecs->event_thread->control.step_over_calls != STEP_OVER_ALL)
{
- /* For "step", we're going to stop. But if the call site
- for this inlined function is on the same source line as
- we were previously stepping, go down into the function
- first. Otherwise stop at the call site. */
+ /* For "step", if the call site for this inlined function is on the
+ same source line as we were previously stepping, go down into the
+ function first before deciding whether to stop. Otherwise stop at
+ the call site. */
if (*curr_frame_id == original_frame_id
&& call_sal.line == ecs->event_thread->current_line
&& call_sal.symtab == ecs->event_thread->current_symtab)
{
step_into_inline_frame (ecs->event_thread);
+ frame = get_current_frame ();
if (inline_frame_is_marked_for_skip (false, ecs->event_thread))
{
keep_going (ecs);
return;
}
+ else if (inline_skipped_frames (ecs->event_thread))
+ {
+ end_stepping_range (ecs);
+ return;
+ }
+ /* We are no longer at an inline function callsite.
+ We use the checks further down to determine whether to stop. */
+ }
+ else
+ {
+ end_stepping_range (ecs);
+ return;
}
-
- end_stepping_range (ecs);
- return;
}
else
{
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.c b/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.c
new file mode 100644
index 00000000000..3b6bc84fb05
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.c
@@ -0,0 +1,50 @@
+/* Copyright 2019-2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* This test relies on foo and bar being inlined into main. */
+
+volatile int global_var;
+
+static inline int __attribute__ ((always_inline))
+foo ()
+{
+ asm ("foo_label: .globl foo_label");
+ global_var++; /* foo inc global_var*/
+ asm ("foo_label2: .globl foo_label2");
+ return global_var; /* foo return global_var */
+} /* foo end */
+
+static inline int __attribute__ ((always_inline))
+bar ()
+{
+ asm ("bar_label: .globl bar_label");
+ global_var++; /* bar inc global_var*/
+ asm ("bar_label2: .globl bar_label2");
+ return global_var; /* bar return global_var */
+} /* bar end */
+
+int
+main ()
+{ /* main prologue */
+ int ans;
+ asm ("main_label: .globl main_label");
+ global_var = 0; /* main set global_var */
+ asm ("main_label2: .globl main_label2");
+ ans = foo (); /* main call foo */
+ asm ("main_label3: .globl main_label3");
+ asm ("nop"); ans = bar (); /* main call bar */
+ asm ("main_label4: .globl main_label4");
+ return ans;
+} /* main end */
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.exp b/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.exp
new file mode 100644
index 00000000000..ef864d943b3
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.exp
@@ -0,0 +1,153 @@
+# Copyright 2019-2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# This test checks that we stop at an inline callsite when returning
+# from a non-inlined function. Specifically when the first line of the
+# inline function does not have is_stmt set.
+#
+# Additionally, we check that when stepping into the inline function we
+# step past this first line without is_stmt set. We check two cases. One
+# where the inline callsite line contains no instructions (i.e. it
+# begins at the same address that the inline function begins). This
+# exercices the codepath in infcmd.c:prepare_one_step. The other is
+# when the inline callsite line contains one instruction. This exercises
+# the codepath in infrun.c:prepare_one_step.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+# The .c files use __attribute__.
+require is_c_compiler_gcc
+
+standard_testfile .c .S
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ global srcdir subdir srcfile srcfile2
+ declare_labels ranges_label lines_label foo_prog bar_prog
+
+ lassign [function_range main [list ${srcdir}/${subdir}/$srcfile]] \
+ main_start main_len
+ set main_end "$main_start + $main_len"
+
+ set foo_call_line [gdb_get_line_number "main call foo"]
+ set bar_call_line [gdb_get_line_number "main call bar"]
+
+ cu {} {
+ compile_unit {
+ {language @DW_LANG_C}
+ {name dw2-inline-stepping-2.c}
+ {low_pc 0 addr}
+ {stmt_list ${lines_label} DW_FORM_sec_offset}
+ {ranges ${ranges_label} DW_FORM_sec_offset}
+ } {
+ bar_prog: subprogram {
+ {name bar}
+ {inline 3 data1}
+ }
+ foo_prog: subprogram {
+ {name foo}
+ {inline 3 data1}
+ }
+ subprogram {
+ {external 1 flag}
+ {name main}
+ {low_pc $main_start addr}
+ {high_pc "$main_start + $main_len" addr}
+ } {
+ inlined_subroutine {
+ {abstract_origin %$foo_prog}
+ {low_pc main_label2 addr}
+ {high_pc main_label3 addr}
+ {call_file 1 data1}
+ {call_line $foo_call_line data1}
+ }
+ inlined_subroutine {
+ {abstract_origin %$bar_prog}
+ {low_pc bar_label addr}
+ {high_pc main_label4 addr}
+ {call_file 1 data1}
+ {call_line $bar_call_line data1}
+ }
+ }
+ }
+ }
+
+ lines {version 2} lines_label {
+ include_dir "${srcdir}/${subdir}"
+ file_name "$srcfile" 1
+
+ program {
+
+ DW_LNE_set_address main_label
+ line [gdb_get_line_number "main set global_var"]
+ DW_LNS_copy
+
+ DW_LNE_set_address main_label2
+ DW_LNS_negate_stmt
+ line [gdb_get_line_number "foo inc global_var"]
+ DW_LNS_copy
+ DW_LNS_negate_stmt
+
+ DW_LNE_set_address foo_label2
+ line [gdb_get_line_number "foo return global_var"]
+ DW_LNS_copy
+
+ DW_LNE_set_address main_label3
+ line [gdb_get_line_number "main call bar"]
+ DW_LNS_copy
+
+ DW_LNE_set_address bar_label
+ DW_LNS_negate_stmt
+ line [gdb_get_line_number "bar inc global_var"]
+ DW_LNS_copy
+ DW_LNS_negate_stmt
+
+ DW_LNE_set_address bar_label2
+ line [gdb_get_line_number "bar return global_var"]
+ DW_LNS_copy
+
+ DW_LNE_set_address main_label4
+ line [gdb_get_line_number "return ans"]
+ DW_LNS_copy
+
+ DW_LNE_set_address $main_end
+ DW_LNE_end_sequence
+ }
+ }
+
+ ranges {is_64 [is_64_target]} {
+ ranges_label: sequence {
+ range ${main_start} ${main_end}
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_test "next" ".* main call foo.*" "step to foo callsite"
+gdb_test "step" ".* foo return global_var.*" "step to foo inc global_var"
+
+gdb_test "next" ".*main call bar.*" "step to bar callsite"
+gdb_test "step" ".* bar return global_var.*" "step to bar inc global_var"
--
2.34.1
next prev parent reply other threads:[~2024-02-01 15:23 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-01 15:21 [PATCH 0/3] Fix inline function stepping Toby Lloyd Davies
2024-02-01 15:21 ` [PATCH 1/3] gdb: Fix missed inline callsite when the frame has changed Toby Lloyd Davies
2024-02-01 15:21 ` Toby Lloyd Davies [this message]
2024-02-01 15:43 ` [PATCH v2 2/3] gdb: Don't stop at non-statement line after stepping into inline function Toby Lloyd Davies
2024-02-01 20:45 ` [PATCH " Carl Love
2024-02-01 21:35 ` Carl Love
2024-02-01 15:21 ` [PATCH 3/3] gdb: Fix 'next' skipping over remainder of " Toby Lloyd Davies
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=20240201152118.598375-3-tlloyddavies@undo.io \
--to=tlloyddavies@undo.io \
--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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).