[RFC] Handle jumping back to first instruction in line

Message ID 20240723122104.10755-1-tdevries@suse.de
State Superseded
Headers
Series [RFC] Handle jumping back to first instruction in line |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm fail Test failed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 fail Test failed

Commit Message

Tom de Vries July 23, 2024, 12:21 p.m. UTC
  Consider test-case test.c:
...
     1	int count{0};
     2
     3	bool f(int& w)
     4	{
     5	  bool result = ++count != 42;
     6	  return result;
     7	}
     8
     9	int main()
    10	{
    11	  int n;
    12	  while (f(n))
    13	    ;
    14	  return n;
    15	}
...
compiled with debuginfo:
...
$ g++ -g test.c
...

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

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

To understand what happens, the line table for main is:
...
CU: test.c:
File name                        Line number    Starting address    View    Stmt
test.c                                    10            0x4004f3               x
test.c                                    12            0x4004fb               x
test.c                                    14            0x40050d               x
test.c                                    15            0x400510               x
test.c                                     -            0x400512
...

That info allows us to annotate main like so:
...
00000000004004f3 <main>:
line 10:
  4004f3:       55                      push   %rbp
  4004f4:       48 89 e5                mov    %rsp,%rbp
  4004f7:       48 83 ec 10             sub    $0x10,%rsp
line 12:
  4004fb:       48 8d 45 fc             lea    -0x4(%rbp),%rax
  4004ff:       48 89 c7                mov    %rax,%rdi
  400502:       e8 c0 ff ff ff          call   4004c7 <_Z1fRi>
  400507:       84 c0                   test   %al,%al
  400509:       74 02                   je     40050d <main+0x1a>
  40050b:       eb ee                   jmp    4004fb <main+0x8>
14:
  40050d:       8b 45 fc                mov    -0x4(%rbp),%eax
15:
  400510:       c9                      leave
  400511:       c3                      ret
...

When stepping out of function f, ptrace single-stepping stops at pcs 0x400507,
0x400509, 0x40050b and 0x4004fb where it re-enters the loop.

The semantics of next prescribe that it "only stops at the first instruction
of a source line", which would suggest that gdb would stop there, but
apparently it doesn't.

Fix this by handling this case in process_event_stop_test, such that we get
instead:
...
(gdb) next
6	  return result;
(gdb) next
7	}
(gdb) next
main () at test.c:12
12	  while (f(n))
(gdb)
...

In three test-cases we rely on "while (1);" to hang when stepping into it,
which is no longer the case, so use "for (int i = 0; ; ++i)" instead.

Also a fix in gdbserver is needed, in case range stepping is on.

Tested on x86_64-linux, target board unix and native-gdbserver.

PR gdb/32000
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32000
---
 gdb/infrun.c                                  |  3 +
 gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c      | 25 +++++
 gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp    | 91 +++++++++++++++++++
 .../step-bg-decr-pc-switch-thread.c           |  2 +-
 .../step-bg-decr-pc-switch-thread.exp         |  2 +-
 .../step-over-lands-on-breakpoint.c           |  2 +-
 .../step-over-trips-on-watchpoint.c           |  2 +-
 gdbserver/linux-low.cc                        |  2 +-
 8 files changed, 124 insertions(+), 5 deletions(-)
 create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c
 create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp


base-commit: 85402ee9edae1be4a3efd53b14826ab6b1061ae4
  

Comments

Tom de Vries July 27, 2024, 2:33 p.m. UTC | #1
On 7/23/24 14:21, Tom de Vries wrote:
> Consider test-case test.c:
> ...
>       1	int count{0};
>       2
>       3	bool f(int& w)
>       4	{
>       5	  bool result = ++count != 42;
>       6	  return result;
>       7	}
>       8
>       9	int main()
>      10	{
>      11	  int n;
>      12	  while (f(n))
>      13	    ;
>      14	  return n;
>      15	}
> ...
> compiled with debuginfo:
> ...
> $ g++ -g test.c
> ...
> 
> Using next to step out of function f also steps out of the loop:
> ...
> $ gdb -q a.out -ex start -ex step
> Reading symbols from a.out...
> Temporary breakpoint 1 at 0x4004fb: file test.c, line 12.
> Starting program: a.out
> 
> Temporary breakpoint 1, main () at test.c:12
> 12	  while (f(n))
> f (w=@0x7fffffffdc7c: 0) at test.c:5
> 5	  bool result = ++count != 42;
> (gdb) next
> 6	  return result;
> (gdb) next
> 7	}
> (gdb) next
> main () at test.c:14
> 14	  return n;
> (gdb)
> ...
> 
> To understand what happens, the line table for main is:
> ...
> CU: test.c:
> File name                        Line number    Starting address    View    Stmt
> test.c                                    10            0x4004f3               x
> test.c                                    12            0x4004fb               x
> test.c                                    14            0x40050d               x
> test.c                                    15            0x400510               x
> test.c                                     -            0x400512
> ...
> 
> That info allows us to annotate main like so:
> ...
> 00000000004004f3 <main>:
> line 10:
>    4004f3:       55                      push   %rbp
>    4004f4:       48 89 e5                mov    %rsp,%rbp
>    4004f7:       48 83 ec 10             sub    $0x10,%rsp
> line 12:
>    4004fb:       48 8d 45 fc             lea    -0x4(%rbp),%rax
>    4004ff:       48 89 c7                mov    %rax,%rdi
>    400502:       e8 c0 ff ff ff          call   4004c7 <_Z1fRi>
>    400507:       84 c0                   test   %al,%al
>    400509:       74 02                   je     40050d <main+0x1a>
>    40050b:       eb ee                   jmp    4004fb <main+0x8>
> 14:
>    40050d:       8b 45 fc                mov    -0x4(%rbp),%eax
> 15:
>    400510:       c9                      leave
>    400511:       c3                      ret
> ...
> 
> When stepping out of function f, ptrace single-stepping stops at pcs 0x400507,
> 0x400509, 0x40050b and 0x4004fb where it re-enters the loop.
> 
> The semantics of next prescribe that it "only stops at the first instruction
> of a source line", which would suggest that gdb would stop there, but
> apparently it doesn't.
> 
> Fix this by handling this case in process_event_stop_test, such that we get
> instead:
> ...
> (gdb) next
> 6	  return result;
> (gdb) next
> 7	}
> (gdb) next
> main () at test.c:12
> 12	  while (f(n))
> (gdb)
> ...
> 
> In three test-cases we rely on "while (1);" to hang when stepping into it,
> which is no longer the case, so use "for (int i = 0; ; ++i)" instead.
> 

I ran into one more such test-case on aarch64-linux, reported by the 
linaro CI.

Submitted a v2 ( 
https://sourceware.org/pipermail/gdb-patches/2024-July/210730.html ).

Thanks,
- Tom

> Also a fix in gdbserver is needed, in case range stepping is on.
> 
> Tested on x86_64-linux, target board unix and native-gdbserver.
> 
> PR gdb/32000
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32000
> ---
>   gdb/infrun.c                                  |  3 +
>   gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c      | 25 +++++
>   gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp    | 91 +++++++++++++++++++
>   .../step-bg-decr-pc-switch-thread.c           |  2 +-
>   .../step-bg-decr-pc-switch-thread.exp         |  2 +-
>   .../step-over-lands-on-breakpoint.c           |  2 +-
>   .../step-over-trips-on-watchpoint.c           |  2 +-
>   gdbserver/linux-low.cc                        |  2 +-
>   8 files changed, 124 insertions(+), 5 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c
>   create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp
> 
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 06b454bf78f..7bac4a8b9ba 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -7695,6 +7695,9 @@ process_event_stop_test (struct execution_control_state *ecs)
>   	  && stop_pc != ecs->stop_func_start
>   	  && execution_direction == EXEC_REVERSE)
>   	end_stepping_range (ecs);
> +      else if (stop_pc == ecs->event_thread->control.step_range_start
> +	       && execution_direction == EXEC_FORWARD)
> +	end_stepping_range (ecs);
>         else
>   	keep_going (ecs);
>   
> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c
> new file mode 100644
> index 00000000000..f5454cf5fc9
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c
> @@ -0,0 +1,25 @@
> +/*
> +   Copyright 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/>.  */
> +
> +int
> +main (void)
> +{ /* main_start.  */
> + loop_label:
> +  asm ("main_label: .globl main_label");
> +  goto loop_label;
> +
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp
> new file mode 100644
> index 00000000000..cab078d5f65
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp
> @@ -0,0 +1,91 @@
> +# This testcase is part of GDB, the GNU debugger.
> +
> +# Copyright 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/>.
> +
> +# Check that stepping over an insn containing a loop to the start of that insn
> +# stops at the start.
> +
> +load_lib dwarf.exp
> +
> +require dwarf2_support
> +
> +standard_testfile .c .S
> +
> +lassign [function_range main $srcdir/$subdir/$srcfile] \
> +    main_start main_len
> +
> +set main_start_line [gdb_get_line_number "main_start."]
> +
> +set loop_label_line [gdb_get_line_number "loop_label:"]
> +
> +set asm_file [standard_output_file $srcfile2]
> +
> +Dwarf::assemble $asm_file {
> +    declare_labels lines_unit
> +
> +    cu {} {
> +	DW_TAG_compile_unit {
> +	    {DW_AT_name $::srcfile}
> +	    {DW_AT_stmt_list $lines_unit DW_FORM_sec_offset}
> +	} {
> +	    declare_labels int_type
> +
> +	    int_type: DW_TAG_base_type {
> +		{ DW_AT_byte_size 4 DW_FORM_sdata }
> +		{ DW_AT_encoding  @DW_ATE_signed }
> +		{ DW_AT_name int }
> +	    }
> +
> +	    DW_TAG_subprogram {
> +		{ DW_AT_name main }
> +		{ DW_AT_low_pc $::main_start DW_FORM_addr }
> +		{ DW_AT_high_pc "$::main_start + $::main_len" DW_FORM_addr }
> +		{ type :$int_type }
> +	    }
> +	}
> +    }
> +
> +    lines {} lines_unit {
> +	file_name $::srcfile 1
> +	program {
> +	    DW_LNE_set_address $::main_start
> +	    line $::main_start_line
> +	    DW_LNS_copy
> +
> +	    DW_LNE_set_address main_label
> +	    line $::loop_label_line
> +	    DW_LNS_copy
> +
> +	    DW_LNE_set_address "$::main_start + $::main_len"
> +	    DW_LNE_end_sequence
> +	}
> +    }
> +}
> +
> +if { [prepare_for_testing "failed to prepare" $testfile \
> +	  [list $srcfile $asm_file] {nodebug}] } {
> +    return
> +}
> +
> +if {![runto_main]} {
> +    return
> +}
> +
> +delete_breakpoints
> +
> +# Regression test for PR32000.  This used to hang, but it should stop at the
> +# first insn of the line.
> +gdb_test "next" "loop_label:"
> diff --git a/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.c b/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.c
> index 71cbdc0f49a..0658d164352 100644
> --- a/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.c
> +++ b/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.c
> @@ -32,7 +32,7 @@ void *
>   thread_function (void *arg)
>   {
>     NOP; /* set breakpoint here */
> -  while (1);
> +  for (int i = 0; ; ++i);
>   }
>   
>   int
> diff --git a/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.exp b/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.exp
> index 7726c7f1d47..1a830e5945c 100644
> --- a/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.exp
> +++ b/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.exp
> @@ -48,7 +48,7 @@ gdb_breakpoint [gdb_get_line_number "set breakpoint here"]
>   gdb_continue_to_breakpoint "run to nop breakpoint"
>   gdb_test "info threads" "  1 .*\\\* 2 .*" "info threads shows all threads"
>   
> -gdb_test "next" "while.*" "next over nop"
> +gdb_test "next" "for.*" "next over nop"
>   
>   gdb_test_no_output "next&" "next& over inf loop"
>   
> diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c
> index c467e512b31..a26ee67a6bf 100644
> --- a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c
> +++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c
> @@ -60,7 +60,7 @@ main ()
>        done with displaced stepping on a target that is always in
>        non-stop mode, as in that case GDB runs both threads
>        simultaneously.  */
> -  while (1); /* set wait-thread breakpoint here */
> +  for (int k = 0; ; k++); /* set wait-thread breakpoint here */
>   
>     pthread_join (child_thread, NULL);
>   
> diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
> index 1266530a245..5e5ab171dc6 100644
> --- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
> +++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
> @@ -62,7 +62,7 @@ main ()
>        done with displaced stepping on a target that is always in
>        non-stop mode, as in that case GDB runs both threads
>        simultaneously.  */
> -  while (1); /* set wait-thread breakpoint here */
> +  for (int k = 0; ; k++); /* set wait-thread breakpoint here */
>   
>     pthread_join (child_thread, NULL);
>   
> diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc
> index 266c7de8fb8..39fd3316315 100644
> --- a/gdbserver/linux-low.cc
> +++ b/gdbserver/linux-low.cc
> @@ -330,7 +330,7 @@ lwp_in_step_range (struct lwp_info *lwp)
>   {
>     CORE_ADDR pc = lwp->stop_pc;
>   
> -  return (pc >= lwp->step_range_start && pc < lwp->step_range_end);
> +  return (pc > lwp->step_range_start && pc < lwp->step_range_end);
>   }
>   
>   /* The event pipe registered as a waitable file in the event loop.  */
> 
> base-commit: 85402ee9edae1be4a3efd53b14826ab6b1061ae4
  

Patch

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 06b454bf78f..7bac4a8b9ba 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -7695,6 +7695,9 @@  process_event_stop_test (struct execution_control_state *ecs)
 	  && stop_pc != ecs->stop_func_start
 	  && execution_direction == EXEC_REVERSE)
 	end_stepping_range (ecs);
+      else if (stop_pc == ecs->event_thread->control.step_range_start
+	       && execution_direction == EXEC_FORWARD)
+	end_stepping_range (ecs);
       else
 	keep_going (ecs);
 
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c
new file mode 100644
index 00000000000..f5454cf5fc9
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.c
@@ -0,0 +1,25 @@ 
+/*
+   Copyright 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/>.  */
+
+int
+main (void)
+{ /* main_start.  */
+ loop_label:
+  asm ("main_label: .globl main_label");
+  goto loop_label;
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp
new file mode 100644
index 00000000000..cab078d5f65
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-insn-loop.exp
@@ -0,0 +1,91 @@ 
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 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/>.
+
+# Check that stepping over an insn containing a loop to the start of that insn
+# stops at the start.
+
+load_lib dwarf.exp
+
+require dwarf2_support
+
+standard_testfile .c .S
+
+lassign [function_range main $srcdir/$subdir/$srcfile] \
+    main_start main_len
+
+set main_start_line [gdb_get_line_number "main_start."]
+
+set loop_label_line [gdb_get_line_number "loop_label:"]
+
+set asm_file [standard_output_file $srcfile2]
+
+Dwarf::assemble $asm_file {
+    declare_labels lines_unit
+
+    cu {} {
+	DW_TAG_compile_unit {
+	    {DW_AT_name $::srcfile}
+	    {DW_AT_stmt_list $lines_unit DW_FORM_sec_offset}
+	} {
+	    declare_labels int_type
+
+	    int_type: DW_TAG_base_type {
+		{ DW_AT_byte_size 4 DW_FORM_sdata }
+		{ DW_AT_encoding  @DW_ATE_signed }
+		{ DW_AT_name int }
+	    }
+
+	    DW_TAG_subprogram {
+		{ DW_AT_name main }
+		{ DW_AT_low_pc $::main_start DW_FORM_addr }
+		{ DW_AT_high_pc "$::main_start + $::main_len" DW_FORM_addr }
+		{ type :$int_type }
+	    }
+	}
+    }
+
+    lines {} lines_unit {
+	file_name $::srcfile 1
+	program {
+	    DW_LNE_set_address $::main_start
+	    line $::main_start_line
+	    DW_LNS_copy
+
+	    DW_LNE_set_address main_label
+	    line $::loop_label_line
+	    DW_LNS_copy
+
+	    DW_LNE_set_address "$::main_start + $::main_len"
+	    DW_LNE_end_sequence
+	}
+    }
+}
+
+if { [prepare_for_testing "failed to prepare" $testfile \
+	  [list $srcfile $asm_file] {nodebug}] } {
+    return
+}
+
+if {![runto_main]} {
+    return
+}
+
+delete_breakpoints
+
+# Regression test for PR32000.  This used to hang, but it should stop at the
+# first insn of the line.
+gdb_test "next" "loop_label:"
diff --git a/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.c b/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.c
index 71cbdc0f49a..0658d164352 100644
--- a/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.c
+++ b/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.c
@@ -32,7 +32,7 @@  void *
 thread_function (void *arg)
 {
   NOP; /* set breakpoint here */
-  while (1);
+  for (int i = 0; ; ++i);
 }
 
 int
diff --git a/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.exp b/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.exp
index 7726c7f1d47..1a830e5945c 100644
--- a/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.exp
+++ b/gdb/testsuite/gdb.threads/step-bg-decr-pc-switch-thread.exp
@@ -48,7 +48,7 @@  gdb_breakpoint [gdb_get_line_number "set breakpoint here"]
 gdb_continue_to_breakpoint "run to nop breakpoint"
 gdb_test "info threads" "  1 .*\\\* 2 .*" "info threads shows all threads"
 
-gdb_test "next" "while.*" "next over nop"
+gdb_test "next" "for.*" "next over nop"
 
 gdb_test_no_output "next&" "next& over inf loop"
 
diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c
index c467e512b31..a26ee67a6bf 100644
--- a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c
+++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c
@@ -60,7 +60,7 @@  main ()
      done with displaced stepping on a target that is always in
      non-stop mode, as in that case GDB runs both threads
      simultaneously.  */
-  while (1); /* set wait-thread breakpoint here */
+  for (int k = 0; ; k++); /* set wait-thread breakpoint here */
 
   pthread_join (child_thread, NULL);
 
diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
index 1266530a245..5e5ab171dc6 100644
--- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
+++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.c
@@ -62,7 +62,7 @@  main ()
      done with displaced stepping on a target that is always in
      non-stop mode, as in that case GDB runs both threads
      simultaneously.  */
-  while (1); /* set wait-thread breakpoint here */
+  for (int k = 0; ; k++); /* set wait-thread breakpoint here */
 
   pthread_join (child_thread, NULL);
 
diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc
index 266c7de8fb8..39fd3316315 100644
--- a/gdbserver/linux-low.cc
+++ b/gdbserver/linux-low.cc
@@ -330,7 +330,7 @@  lwp_in_step_range (struct lwp_info *lwp)
 {
   CORE_ADDR pc = lwp->stop_pc;
 
-  return (pc >= lwp->step_range_start && pc < lwp->step_range_end);
+  return (pc > lwp->step_range_start && pc < lwp->step_range_end);
 }
 
 /* The event pipe registered as a waitable file in the event loop.  */