]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commit
gdb: fix forward/reverse search, when no lines are printed
authorAndrew Burgess <aburgess@redhat.com>
Wed, 13 Aug 2025 14:29:38 +0000 (15:29 +0100)
committerAndrew Burgess <aburgess@redhat.com>
Fri, 15 Aug 2025 10:45:51 +0000 (11:45 +0100)
commite53b88b40ed38651b50f954dfe76066822094c15
tree152297bd411eb9e6a93734547271ff8ef7e1bd15
parent1321c777e975a280d92e8aa577164f9bf9f81b8e
gdb: fix forward/reverse search, when no lines are printed

This commit continues the theme of the previous commit, restoring the
behaviour of forward-search and reverse-search to what it was before
GDB 10, but adds tests to guard the behaviour.  I believe this
restored behaviour is inline with the documentation of the two search
commands.

This time, I'm looking at what happens when no source lines end up
being printed.  This can happen for two reasons, a request is made to
list a line number outside the file, or, a request is made to list a
reverse series of lines (e.g. line 100 to line 50).

Before GDB 10, a 'list' command that resulted in no lines being
printed would not change the notion of the last line listed.  As a
result a future forward or reverse search would continue from the
previous last line.  As an example, here's current master branch
behaviour:

  (gdb) list 50
  45   /* Line 45  */
  46   /* Line 46  */
  47   /* Line 47  */
  48   /* Line 48  */
  49   /* Line 49  */
  50   /* Line 50  */
  51   /* Line 51  */
  52   /* Line 52  */
  53   /* Line 53  */
  54   /* Line 54  */
  (gdb) list 1000
  Line number 995 out of range; long-file.c has 101 lines.
  (gdb) forward-search Line
  Expression not found
  (gdb)

But on GDB 9, the forward-search instead acts like this:

  (gdb) forward-search Line
  55   /* Line 55  */
  (gdb)

Similarly, reverse-search reports "Expression not found" on master,
but would return line 53 on GDB 9.

The reverse-search result for master might be a little surprising,
surely, if we tried to list line 1000, then every line before that
should be searched.

The problem is that last_line_listed ends up being set to 995 (which
is 1000 minus half the listsize).  Then, when the reverse-search kicks
in GDB tried to read line 994, fails, and abandons the search.

This problem was introduced with commit:

  commit 8b7fcda2744145f2380af01c9db8e11986f7af6d
  Date:   Sun Dec 22 14:58:22 2019 +0100

      Fix search in TUI

This commit wants last_line_listed updated so that the search
functions would work correctly (see notes below) when GDB is in TUI
mode.  Without this commit last_line_listed would never be updated in
TUI mode, and so every search would effectively start from the
beginning of the file.

The fix I propose is to delay updating the current_source_location
until the source code has been printed successfully.  That is, just
before we leave print_source_lines_base, after a successful print.
This update happens inside the 'if (noprint)' block, a the return here
isn't really considered an error condition, this is a specific choice
_not_ to print the source code.

However, in the 'if (stopline <= line)' block, the
current_source_location is not updated, that's because this 'if'
represents an error condition.

The last_line_listed is also updated at the end of the function still,
which is the path taken in CLI mode when source lines are actually
printed.

I've added some CLI tests to confirm the forward/reverse search
behaviour.  And I've also added some TUI tests to check search works
within the TUI.  The TUI tests cover more than just the fix for this
issue.

There is one slight issue with the TUI.  At this point you should
definitively go read the previous commit.  OK, so, the forward and
reverse searches are supposed to search from the last line listed.
The previous commit fixed this for CLI mode, but for the TUI the
last_line_listed is _still_ being set to the first line displayed.
The problem is that print_source_lines_base doesn't know the size of
the TUI src window, and so, doesn't know what the last line listed
will be, and so cannot set last_line_listed correctly.

This indicates to me that setting last_line_listed from the core GDB
code is likely the wrong approach, or, at least, the way it is done
now is the wrong approach.

Currently the 'list' command converts the arguments into a set of
lines to be printed based on the CLI environment, e.g. using the
'listsize' if necessary.  But the 'listsize' doesn't make sense for
the TUI, where the src window height really overrides the 'listsize'.

The list command then calls the core GDB print_source_lines
function to do the printing, but for the TUI we don't actually print
anything, we just update the internal state (including
last_line_listed) and are done.

I think that the current interpreter, CLI or TUI, needs to get
involved in the 'list' command implementation much sooner.  This would
allow, for example, the CLI to use 'listsize' and the TUI to use the
src window height.  It might then be up to the interpreter to track
the last line listed maybe?

I mention all this only to acknowledge this issue.  The problem
existed before this commit, and continues to exist after this commit.
I'm not proposing to fix this problem right now.

The TUI forward/reverse search continue to work as well as they have
since commit 8b7fcda2744.

Approved-By: Tom Tromey <tom@tromey.com>
gdb/source.c
gdb/testsuite/gdb.base/source-search.exp
gdb/testsuite/gdb.tui/source-search.c [new file with mode: 0644]
gdb/testsuite/gdb.tui/source-search.exp [new file with mode: 0644]