[PATCH 2/2] [gdb] Handle stepping out of function into loop, case 2

Tom de Vries tdevries@suse.de
Thu Sep 5 15:06:40 GMT 2024


Consider the same test-case as in the previous commit, compiled with gcc 13.3
and -g:
...
$ g++ -g test.c
...

Using next to step out of function f steps out of the loop:
...
$ gdb -q a.out -ex start
Reading symbols from a.out...
Temporary breakpoint 1 at 0x4004fa: file test.c, line 12.
Starting program: a.out

Temporary breakpoint 1, main () at test.c:12
12	  while (f(n))
(gdb) step
f (w=@0x7fffffffdc9c: 0) at test.c:5
5	  bool result = ++count != 42;
(gdb) step
6	  return result;
(gdb) step
7	}
(gdb) next
main () at test.c:14
14	  return n;
(gdb)
...

As mentioned in the previous commit, the loop looks like:
...
  4004fa:       90                      nop
  4004fb:       48 8d 45 fc             lea    -0x4(%rbp),%rax
  4004ff:       48 89 c7                mov    %rax,%rdi
  400502:       e8 bf ff ff ff          call   4004c6 <_Z1fRi>
  400507:       84 c0                   test   %al,%al
  400509:       75 f0                   jne    4004fb <main+0x9>
  40050b:       8b 45 fc                mov    -0x4(%rbp),%eax
...
with this line info:
...
INDEX  LINE   REL-ADDRESS        UNREL-ADDRESS      IS-STMT
8      12     0x00000000004004fa 0x00000000004004fa Y
9      14     0x000000000040050b 0x000000000040050b Y
...
so we cannot expect a user stop at line 12.

However, the next also steps over all subsequent calls to f.

Change the behaviour to stop at the next call to f, by degrading the
next to a step.

Tested on x86_64-linux.

PR gdb/32000
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32000
---
 gdb/infrun.c                                   |  8 ++++++++
 gdb/testsuite/gdb.dwarf2/dw2-insn-loop-nop.exp | 14 ++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index ec9becae2f1..32bd715f289 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8183,6 +8183,14 @@ process_event_stop_test (struct execution_control_state *ecs)
     = (ecs->event_thread->current_line != stop_pc_sal.line
        || ecs->event_thread->current_symtab != stop_pc_sal.symtab);
 
+  if (different_line && execution_direction == EXEC_FORWARD
+      && ecs->event_thread->control.step_over_calls == STEP_OVER_ALL)
+    {
+      /* Stepped out of line, degrade next to step.  */
+      ecs->event_thread->control.step_over_calls
+	= STEP_OVER_UNDEBUGGABLE;
+    }
+
   bool refresh_step_info = true;
   if (different_line && ecs->event_thread->stop_pc () == stop_pc_sal.pc)
     {
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-insn-loop-nop.exp b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop-nop.exp
index 4c9f63647d5..65ee1b850ae 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-insn-loop-nop.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop-nop.exp
@@ -65,3 +65,17 @@ gdb_test_multiple step "step out of foo using step" {
 	pass $gdb_test_name
     }
 }
+
+if { ! $in_foo } {
+    return
+}
+
+gdb_test_multiple next "step out of foo using next" {
+    -re -wrap $re_foo {
+	pass $gdb_test_name
+    }
+    -re -wrap $re_main_return {
+	# Behaviour in gdb 15 and earlier.
+	fail $gdb_test_name
+    }
+}
-- 
2.35.3



More information about the Gdb-patches mailing list