When running test-case gdb.tui/resize-2.exp with taskset -c 0, I sometimes run
into:
...
tui disable^[[40;1H^M(gdb) PASS: $exp: tui disable
^M^[[K(gdb) FAIL: $exp: two prompt redisplays after resize (timeout)
...
The test-case does "Term::resize 24 80 0" while having the settings of an
earlier "Term::resize 40 90", so both dimensions change.
When TUI is enabled, we call Term::resize with wait_for_msg == 1, and the proc:
- calls stty to change one dimension,
- waits for the message (enabled by "maint set tui-resize-message on")
confirming the resize has happened,
- calls stty to change the other dimension, and again
- waits for the message confirming the resize has happened.
Since TUI is disabled, we call Term::resize with wait_for_msg == 0 because the
message is not printed, so stty is called twice, and afterwards we check for
the results of the two resizes, which is the test that is failing.
The problem is that not waiting for a response after each stty call opens up
the possibility of the responses being merged.
Fix this by calling Term::resize twice, changing one dimension at a time, and
waiting for a single prompt redisplay after each one.
Tested on x86_64-linux.
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
PR testsuite/31822
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31822
Add a regression test for commit d68f983f88 ("Fix heap-use-after-free because
all_objfiles_removed triggers tui_display_main").
When building with address sanitizer, and reverting the commit it triggers the
heap-use-after-free.
Tested on aarch64-linux.
PR symtab/31697
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31697
After starting TUI like this with a hello world a.out:
...
$ gdb -q a.out -ex start -ex "tui enable"
...
we get:
...
┌─hello.c──────────────────────────────┐
│ 5 { │
│ 6 printf ("hello\n"); │
│ 7 │
│ 8 return 0; │
│ 9 } │
│ │
└──────────────────────────────────────┘
...
This is a regression since commit ee1e9bbb51 ("[gdb/tui] Fix displaying main
after resizing"), before which we had instead:
...
┌─hello.c──────────────────────────────┐
│ 4 main (void) │
│ 5 { │
│ > 6 [7m printf ("hello\n");[0m │
│ 7 │
│ 8 return 0; │
│ 9 } │
└──────────────────────────────────────┘
...
In other words, the problems are:
- the active line (source line 6) is no longer highlighted, and
- the active line is not vertically centered (screen line 2 out 6 instead of
screen line 3 out of 6).
Fix these problems respectively by:
- in tui_enable, instead of "tui_show_frame_info (0)" using
'tui_show_frame_info (deprecated_safe_get_selected_frame ())", and
- in tui_source_window_base::rerender, adding centering functionality.
Tested on aarch64-linux.
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
PR tui/31522
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31522
The other day on irc, we were discussing the "m_line" hack in
tui-out.c, and I mentioned that it would be nice to replace this with
a new ui_out_flag.
Later, I looked at ui_out_flag and found:
ui_source_list = (1 << 0),
... and sure enough, this is tested already.
This patch removes tui-out.[ch] and changes the TUI to use an ordinary
cli-out object without this flag set.
As far as I can tell, this doesn't affect behavior at all -- the TUI
tests all pass, and interactively I tried switching stack frames,
"list", etc, and it all seems to work.
New in v2: fixed the problem pointed out by Keith, and added a test
case for that scenario.
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
In a couple of spots, the TUI tries to center some text in the window.
Andrew noticed that the calculation is done strangely and the text
ends up somewhat to the left of center.
This patch fixes the problem.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31355
When the inferior exits, the TUI register window should clear.
Fixing this was mostly a matter of sticking an assignment into
tui_inferior_exit. However, some changes to the register window
itself were also needed.
While working on this, I realized that the TUI register window would
not work correctly when moving between frames of different
architectures. This patch attempts to fix this as well, though I have
no way to test it.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28600
Tested-By: Tom de Vries <tdevries@suse.de>
Reviewed-By: Andrew Burgess <aburgess@redhat.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
This commit is the result of the following actions:
- Running gdb/copyright.py to update all of the copyright headers to
include 2024,
- Manually updating a few files the copyright.py script told me to
update, these files had copyright headers embedded within the
file,
- Regenerating gdbsupport/Makefile.in to refresh it's copyright
date,
- Using grep to find other files that still mentioned 2023. If
these files were updated last year from 2022 to 2023 then I've
updated them this year to 2024.
I'm sure I've probably missed some dates. Feel free to fix them up as
you spot them.
When starting gdb in CLI mode, running to main and switching into the TUI regs
layout:
...
$ gdb -q a.out -ex start -ex "layout regs"
...
we get:
...
+---------------------------------+
| |
| [ Register Values Unavailable ] |
| |
+---------------------------------+
...
Fix this by handling this case in tui_data_window::rerender.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR tui/28600
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28600
The focused window is highlighted by using active-border-kind instead of
border-kind.
But if the focused window is the cmd window (which is an unboxed window), then
no highlighting is done, and it's not obvious from looking at the screen which
window has the focus. Instead, you have to notice the absence of highlighting
on boxed windows, and then infer that the focus is on the unboxed window.
That approach stops working if there are multiple unboxed windows.
Likewise if highlighting is switched off by setting active-border-kind to the
same value as border-kind.
Make it more explicit which window has the focus by mentioning it in the status
window, like so:
...
native process 8282 (src) In: main L7 PC: 0x400525
...
Tested on x86_64-linux and ppc64le-linux.
Tested-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
A TUI src window is displaying either:
- the source for the current frame,
- the source for main, or
- the string "[ No Source Available ]".
Since commit 03893ce67b ("[gdb/tui] Fix resizing of terminal to 1 or 2 lines")
we're able to resize the TUI to 1 line without crashing.
I noticed that if TUI is displaying main, and we resize to 1 line (destroying
the src window) and then back to a larger terminal (reconstructing the src
window), the TUI displays "[ No Source Available ]" instead of main.
Fix this by moving the responsibility for showing main from tui_enable to
tui_source_window_base::rerender.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
I noticed that after resizing to a narrow window, I got:
...
┌────────────────┐
│ │
│[ No Source Avail
able ] │
│ │
└────────────────┘
...
Fix this by adding two new functions:
- tui_win_info::display_string (int y, int x, const char *str)
- tui_win_info::display_string (const char *str)
that make sure that borders are not overwritten, which get us instead:
...
┌────────────────┐
│ │
│[ No Source Avai│
│ │
│ │
└────────────────┘
...
Tested on x86_64-linux.
On pinebook I ran into:
...
Running gdb.tui/tui-layout-asm-short-prog.exp ...
gdb compile failed, gdb.tui/tui-layout-asm-short-prog.S: Assembler messages:
gdb.tui/tui-layout-asm-short-prog.S:23: Error: \
junk at end of line, first unrecognized character is `,'
...
Fix this by using %progbits instead of @progbits for arm.
Approved-by: Luis Machado <luis.machado@arm.com>
Tested on x86_64-linux and pinebook.
When starting TUI in a terminal with 3 lines:
...
$ echo $LINES
3
$ gdb -q -tui
...
and resizing the terminal to 2 lines we run into a segfault.
The problem is that for the source window:
- the minimum height is 3 (the default), but
- the maximum height is only 2 because there are only 2 lines.
This discrepancy eventually leads to a call to newwin in make_window with:
...
(gdb) p height
$1 = 3
(gdb) p width
$2 = 56
(gdb) p y
$3 = -1
(gdb) p x
$4 = 0
...
which results in a nullptr.
This violates the assumption here in tui_apply_current_layout:
....
/* Get the new list of currently visible windows. */
std::vector<tui_win_info *> new_tui_windows;
applied_layout->get_windows (&new_tui_windows);
...
that get_windows only returns visible windows, which leads to tui_windows
holding a dangling pointer, which results in the segfault.
Fix this by:
- making sure get_windows only returns visible windows, and
- detecting the situation and dropping windows from the layout if
there's no room for them.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR tui/31044
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31044
When starting TUI in a terminal with 2 lines (likewise with 1 line):
...
$ echo $LINES
2
$ gdb -q -tui
...
we run into this assert in tui_apply_current_layout:
...
/* This should always be made visible by a layout. */
gdb_assert (TUI_CMD_WIN != nullptr);
...
The problem is that for the command window:
- the minimum height is 3 (the default), but
- the maximum height is only 2 because there are only 2 lines.
This discrepancy eventually leads to a call to newwin in make_window with:
...
(gdb) p height
$1 = 3
(gdb) p width
$2 = 66
(gdb) p y
$3 = -1
(gdb) p x
$4 = 0
(gdb)
...
which results in a nullptr, which eventually triggers the assert.
The easiest way to fix this is to change the minimum height of the command
window to 1. However, that would also change behaviour for the case that the
screen size is 3 lines or more. For instance, in gdb.tui/winheight.exp the
number of lines in the terminal is 24, and the test-case checks that the user
cannot increase the source window height to the point that the command window
height would be less than 3.
Fix this by calculating the minimum height of the command window as follows:
- the default (3) if max_height () allows it, and
- max_height () otherwise.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR tui/31044
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31044
I ran across this site:
https://no-color.org/
... which lobbies for tools to recognize the NO_COLOR environment
variable and disable any terminal styling when it is seen.
This patch implements this for gdb.
Regression tested on x86-64 Fedora 38.
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Reviewed-by: Kevin Buettner <kevinb@redhat.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
With CLI, a session defining a command looks like:
...
(gdb) define foo
Type commands for definition of "foo".
End with a line saying just "end".
>bar
>end
(gdb)
...
With TUI however, we get the same secondary prompts, and type the same, but
are left with:
...
(gdb) define foo
Type commands for definition of "foo".
End with a line saying just "end".
(gdb)
...
Fix this by calling tui_inject_newline_into_command_window in
gdb_readline_wrapper_line, as is done in tui_command_line_handler.
Tested on x86_64-linux.
PR tui/30636
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30636
In test-case gdb.tui/long-prompt.exp, with a prompt of 40 chars, the same size
as the terminal width, we get a superfluous newline at line 19:
...
16 (gdb) set prompt 123456789A123456789B123
17 456789C123456789>
18 123456789A123456789B123456789C123456789>
19
20 123456789A123456789B123456789C123456789>
21 set prompt (gdb)
22 (gdb)
...
as well as a superfluous repetition of the prompt at line 20 once we type the
's' starting "set prompt".
I traced the superfluous newline back to readline's readline_internal_setup,
that does:
...
/* If we're not echoing, we still want to at least print a prompt, because
rl_redisplay will not do it for us. If the calling application has a
custom redisplay function, though, let that function handle it. */
if (_rl_echoing_p == 0 && rl_redisplay_function == rl_redisplay)
...
else
{
if (rl_prompt && rl_already_prompted)
rl_on_new_line_with_prompt ();
else
rl_on_new_line ();
(*rl_redisplay_function) ();
...
and then we hit the case that calls rl_on_new_line_with_prompt, which does:
...
/* If the prompt length is a multiple of real_screenwidth, we don't know
whether the cursor is at the end of the last line, or already at the
beginning of the next line. Output a newline just to be safe. */
if (l > 0 && (l % real_screenwidth) == 0)
_rl_output_some_chars ("\n", 1);
...
This doesn't look like a readline bug, because the behaviour matches the
comment.
[ And the fact that the output of the newline doesn't happen in the scope of
tui_redisplay_readline means it doesn't get the prompt wrap detection
treatment, causing start_line to be incorrect, which causes the superfluous
repetition of the prompt. ]
I looked at ways to work around this, and managed by switching off
rl_already_prompted, which we set to 1 in tui_rl_startup_hook:
...
/* Readline hook to redisplay ourself the gdb prompt.
In the SingleKey mode, the prompt is not printed so that
the command window is cleaner. It will be displayed if
we temporarily leave the SingleKey mode. */
static int
tui_rl_startup_hook (void)
{
rl_already_prompted = 1;
if (tui_current_key_mode != TUI_COMMAND_MODE
&& !gdb_in_secondary_prompt_p (current_ui))
tui_set_key_mode (TUI_SINGLE_KEY_MODE);
tui_redisplay_readline ();
return 0;
}
...
Then I started looking at why rl_already_prompted is set to 1.
The use case for rl_already_prompted seems to be:
- app (application, the readline user) outputs prompt,
- app sets rl_already_prompted to 1, and
- app calls readline, which calls rl_on_new_line_with_prompt, which figures
out how long the prompt is, and sets a few readline variables accordingly,
which can be used in the following call to rl_redisplay_function.
AFAICT, TUI does not fit this pattern. It does not output an initial prompt,
rather it writes the prompt in every rl_redisplay_function. It doesn't use
the variables set by rl_on_new_line_with_prompt, instead it figures stuff out
by itself.
Fix this by removing the rl_already_prompted setting.
Also remove the call to tui_redisplay_readline, it's not necessary, the
function is called anyway.
Tested on x86_64-linux, no regressions.
With test-case gdb.tui/pr30056.exp, I run into:
...
sh: warning: setlocale: LC_ALL: cannot change locale (C.UTF-8)^M
...
and then subsequently into:
...
WARNING: timeout in accept_gdb_output
FAIL: gdb.tui/pr30056.exp: Control-C
...
This is on a CentOS 7 distro for powerpc64le.
Either it has no C.UTF-8 support, or it's not installed:
...
$ locale -a | grep ^C
C
$
...
Fix this by:
- adding a new proc have_host_locale, and
- using it in all test-cases using setenv LC_ALL.
Tested on powerpc64le-linux and x86_64-linux.
PR testsuite/30458 reports the following FAIL:
...
PASS: gdb.tui/wrap-line.exp: width-auto-detected: cli: wrap
^CQuit
(gdb) WARNING: timeout in accept_gdb_output
Screen Dump (size 50 columns x 24 rows, cursor at column 6, row 3):
0 Quit
1 (gdb) 7890123456789012345678901234567890123456789
2 W^CQuit
3 (gdb)
...
FAIL: gdb.tui/wrap-line.exp: width-auto-detected: cli: prompt after wrap
...
The problem is that the regexp doesn't account for the ^C:
...
gdb_assert { [Term::wait_for "^WQuit"] } "prompt after wrap"
...
The ^C occurs occasionally. This is something we'd like to fix. It's
reported as a readline problem here (
https://lists.gnu.org/archive/html/bug-readline/2023-06/msg00000.html ).
For now, fix this by updating the regexp, and likewise in another place in the
test-case where we use ^C.
Tested on x86_64-linux.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30458
The semantics of Term::wait_for is:
...
# Accept some output from gdb and update the screen. WAIT_FOR is
# a regexp matching the line to wait for. Return 0 on timeout, 1
# on success.
proc wait_for {wait_for} {
...
Note that besides the regexp, also a subsequent gdb prompt is matched.
I recently used wait_for "" in a few test-cases, thinking that this would
match just a prompt, but in fact that's not the case.
Fix this in wait_for, and add a corresponding test in gdb.tui/tuiterm-2.exp.
Tested on x86_64-linux.
When running test-case gdb.tui/long-prompt.exp with check-read1, we get:
...
(gdb) FAIL: gdb.tui/long-prompt.exp: prompt size == width + 1: \
end of screen: at last line
...
The problem is in these commands:
...
Term::command "echo \\n"
Term::command "echo \\n"
Term::command "echo \\n"
Term::command "echo \\n"
...
The last one makes the terminal scroll, and the scrolling makes the expected
output match on a different line.
Fix this by replacing the sequence with a single command:
...
Term::command "echo \\n\\n\\n\\n\\n\\n"
...
which avoids scrolling.
Tested on x86_64-linux.
There is a test-case that contains a unit test for tuiterm:
gdb.tui/tuiterm.exp.
However, this only excercises the tuiterm itself, and not the functions that
interact with it, like Term::command.
Add a new test-case gdb.tui/tuiterm-2.exp that:
- overrides proc accept_gdb_output (to be able simulate incorrect responses
while avoiding the timeout),
- overrides proc send_gdb (to be able to call Term::command without a gdb
instance, such that all tuiterm input is generated by the test-case).
- issues Term::command calls, and
- checks whether they behave correctly.
This exposes a problem in Term::command. The "prompt before command" regexp
starts with a bit that is supposed to anchor the prompt to the border:
...
set str "(^|\|)$gdb_prompt $str"
...
but that doesn't work due to insufficient escaping. Fix this by adding the
missing escape:
...
set str "(^|\\|)$gdb_prompt $str"
...
Futhermore, the "prompt after command" regexp in Term::wait_for has no
anchoring at all:
...
set prompt_wait_for "$gdb_prompt \$"
...
so add that as well.
Tested on x86_64-linux.
Say we're in TUI mode, and type "sun":
...
(gdb) sun
...
After switching to SingleKey mode using C-x s, we have just:
...
sun
...
After typing "d", we get:
...
sun
Undefined command: "sundown". Try "help".
...
The SingleKey "d" is supposed run the "down" command.
Fix this by clearing the readline line buffer when switching to SingleKey
mode.
Tested on x86_64-linux.
PR tui/30522
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30522
Reviewed-By: Tom Tromey <tom@tromey.com>
I noticed that the test-suite doesn't excercise the case in
tui_redisplay_readline that height (initially 1) is changed by this call:
...
tui_puts_internal (w, prompt, &height);
...
Add a test-case that excercises this.
Tested on x86_64-linux.
When running the test-case gdb.tui/wrap-line.exp with a build configured with
--disable-tui, we run into:
...
(gdb) PASS: gdb.tui/wrap-line.exp: width-hard-coded: set width 50
tui new-layout command-layout cmd 1^M
Undefined command: "tui". Try "help".^M
(gdb) ERROR: Undefined command "tui new-layout command-layout cmd 1".
...
Fix this by guarding the command with allow_tui_tests.
Tested on x86_64-linux.
When running test-case gdb.tui/pr30056.exp with target board
native-extended-gdbserver, I run into:
...
Quit^[[K^M^[[B(gdb) PASS: gdb.tui/pr30056.exp: Control-C
Remote debugging from host ::1, port 38810^M
^M(failed reverse-i-search)`xyz': ^M(gdb) target extended-remote \
localhost:2346^[[7GWARNING: Timed out waiting for EOF in server after \
monitor exit
...
This is due to the fact that ^C doesn't abort the reverse-i-search. This
appears to be due to a readline problem. A PR is open about this: PR
cli/30498.
Add a KFAIL for the PR, and ensure that the isearch is aborted by using ^G,
such that we have a responsive prompt to handle the "monitor exit" command
that native-extended-gdbserver issues.
Tested on x86_64-linux.
I added a cmd-only layout:
...
(gdb) tui new-layout cmd cmd 1
...
and set it:
...
(gdb) layout cmd
...
which gave me the expect result: only the cmd window in the screen.
However, after going back to layout src:
...
(gdb) layout src
...
I got a source window with only one line in it, and the cmd window taking most
of the screen.
I traced this back to tui_set_layout, where for both the old and the new
layout the fingerprint of the cmd window in the layout is taken. If the
fingerprint is the same, an effort will be done to preserve the command
window size.
The fingerprint is "VC" for both the old (cmd) and new (src) layouts, which
explains the behaviour.
I think this is essentially a bug in the finger print calculation, and it
should be "C" for the cmd layout.
Fix this by not adding a V or H in the fingerprint if the list size is one.
Tested on x86_64-linux.
Reviewed-By: Tom Tromey <tom@tromey.com>
Simon reported that the new test-case gdb.tui/pr30056.exp fails with system
readline.
This is because the test-case requires a fix in readline that's present in our
in-repo copy of readline, but most likely not in any system readline yet.
Fix this by:
- mentioning --with-system-readline or --without-system-readline in the
configuration string.
- adding a new proc with_system_readline that makes this information available
in the testsuite.
- using this in test-case gdb.tui/pr30056.exp to declare it unsupported for
--with-system-readline.
Tested on x86_64-linux.
Reported-By: Simon Marchi <simon.marchi@efficios.com>
Approved-By: Simon Marchi <simon.marchi@efficios.com>
I came across a bug in the implementation of line feed in tuiterm, and added a
unit test that exposes it.
Before sending the line feed we have:
...
Screen Dump (size 8 columns x 4 rows, cursor at column 0, row 3):
0 abcdefgh
1 ijklmnop
2 qrstuvwx
3 yz01234
...
and after it we have:
...
Screen Dump (size 8 columns x 4 rows, cursor at column 0, row 1):
0 ijklmnop
1 qrstuvwx
2 yz01234
3 yz01234
...
Note how the cursor started at row 3 and after the line feed ended up at
row 1, while it should have stayed in row 3.
Fix this by moving "incr _cur_row -1" one level up in the loop nest in
proc _ctl_0x0a.
Tested on x86_64-linux.
Consider the following scenario. We start gdb in TUI mode:
...
$ gdb -q -tui
...
and type ^R which gives us the reverse-isearch prompt in the cmd window:
...
(reverse-i-search)`':
...
and then type "foo", right-arrow-key, and ^C.
In TUI mode, gdb uses a custom rl_getc_function tui_getc.
When pressing the right-arrow-key, tui_getc:
- attempts to scroll the TUI src window, without any effect, and
- returns 0.
The intention of returning 0 is mentioned here in tui_dispatch_ctrl_char:
...
/* We intercepted the control character, so return 0 (which readline
will interpret as a no-op). */
return 0;
...
However, after this 0 is returned by the rl_read_key () call in
_rl_search_getchar, _rl_read_mbstring is called, which incorrectly interprets
0 as the first part of an utf-8 multibyte char, and tries to read the next
char.
In this state, the ^C takes effect and we run into a double free because
_rl_isearch_cleanup is called twice.
Both these issues need fixing independently, though after fixing the first we
no longer trigger the second.
The first issue is caused by the subtle difference between:
- a char array containing 0 chars, which is zero-terminated, and
- a char array containing 1 char, which is zero.
In mbrtowc terms, this is the difference between:
...
mbrtowc (&wc, "", 0, &ps);
...
which returns -2, and:
...
mbrtowc (&wc, "", 1, &ps);
...
which returns 0.
Note that _rl_read_mbstring calls _rl_get_char_len without passing it an
explicit length parameter, and consequently it cannot distinguish between the
two, and defaults to the "0 chars" choice.
Note that the same problem doesn't exist in _rl_read_mbchar.
Fix this by defaulting to the "1 char" choice in _rl_get_char_len:
...
- if (_rl_utf8locale && l > 0 && UTF8_SINGLEBYTE(*src))
+ if (_rl_utf8locale && l >= 0 && UTF8_SINGLEBYTE(*src))
...
The second problem happens when the call to _rl_search_getchar in
_rl_isearch_callback returns. At that point _rl_isearch_cleanup has already
been called from the signal handler, but we proceed regardless, using a cxt
pointer that has been freed.
Fix this by checking for "RL_ISSTATE (RL_STATE_ISEARCH)" after the call to
_rl_search_getchar:
...
c = _rl_search_getchar (cxt);
+ if (!RL_ISSTATE (RL_STATE_ISEARCH))
+ return 1;
...
Tested on x86_64-linux.
Approved-By: Chet Ramey <chet.ramey@case.edu>
PR tui/30056
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30056
Add a test-case that sets a prompt with color in TUI.
The line containing the prompt is shown by get_line_with_attrs as follows:
...
<fg:31>(gdb) <fg:default>
...
The 31 means red, but only for foreground colors, for background colors 41
means red.
Make this more readable by using color names for both foreground and
background, such that we have instead:
....
<fg:red>(gdb) <fg:default>
...
Tested on x86_64-linux.
I noticed in proc Term::_csi_m arguments that while parameters 7 and 27 are
supposed to set the reverse attribute to 1 and 0, in fact it's set to 1 in
both cases:
...
7 {
set _attrs(reverse) 1
}
...
27 {
set _attrs(reverse) 1
}
...
Fix this and add a regression test in gdb.tui/tuiterm.exp.
Tested on x86_64-linux.
Add a new proc Term::get_line_with_attrs, similar to Term::get_line, that
annotates a tuiterm line with the active attributes.
For instance, the line representing the TUI status window with attribute mode
standout looks like this with Term::get_line:
...
exec No process In: ... L?? PC: ??
...
but like this with Term::get_line_with_attrs:
...
<reverse:1>exec No process In: ... L?? PC: ?? <reverse:0>
...
Also add Term::dump_screen_with_attrs, a Term::dump_screen variant that uses
Term::get_line_with_attrs instead of Term::get_line.
Tested by re-running the TUI test-cases (gdb.tui/*.exp and gdb.python/tui*.exp)
on x86_64-linux.
Currently, for a source file containing only 5 lines, we also show line
numbers 6 and 7 if they're in scope of the source window:
...
0 +-compact-source.c----------------+
1 |___3_{ |
2 |___4_ return 0; |
3 |___5_} |
4 |___6_ |
5 |___7_ |
6 +---------------------------------+
...
Fix this by not showing line numbers not in a source file, such that we have instead:
...
0 +-compact-source.c----------------+
1 |___3_{ |
2 |___4_ return 0; |
3 |___5_} |
4 | |
5 | |
6 +---------------------------------+
...
Tested on x86_64-linux.
Suggested-By: Simon Marchi <simon.marchi@efficios.com>
Approved-By: Tom Tromey <tom@tromey.com>
The commit:
commit 08ec06d644
Date: Wed Mar 29 10:41:07 2023 +0100
gdb/testsuite: special case '^' in gdb_test pattern
Added some special handling of '^' to gdb_test -- a leading '^' will
cause the command regexp to automatically be included in the expected
output pattern.
It was pointed out that the '-wrap' flag of gdb_test_multiple is
supposed to work in the same way as gdb_test, and that the recent
changes for '^' had not been replicated for gdb_test_multiple. This
patch addresses this issue.
So, after this commit, the following two constructs should have the
same meaning:
gdb_test "command" "^output" "test name"
gdb_test_multiple "command" "test name" {
-re -wrap "^output" {
pass $gdb_test_name
}
}
In both cases the '^' will case gdb.exp to inject a regexp that
matches 'command' after the '^' and before the 'output', this is in
addition to adding the $gdb_prompt pattern after 'output' in the
normal way.
The special '^' handling is only applied when '-wrap' is used, as this
is the only mode that aims to mimic gdb_test.
While working on this patch I realised that I could actually improve
the logic for the special '^' handling in the case where the expected
output pattern is empty. I replicated these updates for both gdb_test
and gdb_test_multiple in order to keep these two paths in sync.
There were a small number of tests that needed adjustment after this
change, mostly just removing command regexps that are now added
automatically, but the gdb.base/settings.exp case was a little weird
as it turns out trying to match a single blank line is probably harder
now than it used to be -- still, I suspect this is a pretty rare case,
so I think the benefits (improved anchoring) outweigh this small
downside (IMHO).
I. Auto-detected width (xterm vs. ansi)
Say we have a terminal with a width of 40 chars:
...
$ echo $COLUMNS
40
...
With TERM=xterm, we report a width of 40 chars:
...
$ TERM=xterm gdb
(gdb) show width
Number of characters gdb thinks are in a line is 40.
...
And with TERM=ansi, a width of 39 chars:
...
$ TERM=ansi gdb
(gdb) show width
Number of characters gdb thinks are in a line is 39.
...
Gdb uses readline to auto-detect screen size, and readline decides in the
TERM=ansi case that the terminal does not have reliable auto-wrap, and
consequently decides to hide the last terminal column from the readline user
(in other words GDB), hence we get 39 instead of 40.
II. Types of wrapping
Looking a bit more in detail inside gdb, it seems there are two types of
wrapping:
- readline wrapping (in other words, prompt edit wrapping), and
- gdb output wrapping (can be observed by issuing "info sources").
This type of wrapping attempts to wrap some of the gdb output earlier
than the indicated width, to not break lines in inconvenient places.
III. Readline wrapping, auto-detected screen size
Let's investigate readline wrapping with the auto-detected screen widths.
First, let's try with xterm:
...
$ TERM=xterm gdb
(gdb) 7890123456789012345678901234567890
123
...
That looks as expected, wrapping occurs after 40 chars.
Now, let's try with ansi:
...
$ TERM=ansi gdb
(gdb) 78901234567890123456789012345678
90123
...
It looks like wrapping occurred after 38, while readline should be capable of
wrapping after 39 chars.
This is caused by readline hiding the last column, twice.
In more detail:
- readline detects the screen width: 40,
- readline hides the last column, setting the readline screen width to 39,
- readline reports 39 to gdb as screen width,
- gdb sets its width setting to 39,
- gdb sets readline screen width to 39,
- readline hides the last column, again, setting the readline screen width to
38.
This is reported as PR cli/30346.
IV. gdb output wrapping, auto-detected screen size
Say we set the terminal width to 56. With TERM=xterm, we have:
...
/home/abuild/rpmbuild/BUILD/glibc-2.31/csu/elf-init.c,
/data/vries/hello.c,
...
but with TERM=ansi:
...
/home/abuild/rpmbuild/BUILD/glibc-2.31/csu/elf-init.c, /
data/vries/hello.c,
...
So what happened here? With TERM=ansi, the width setting is auto-detected to
55, and gdb assumes the terminal inserts a line break there, which it doesn't
because the terminal width is 56.
This is reported as PR cli/30411.
V. Fix PRs
Fix both mentioned PRs by taking into account the hidden column when readline
reports the screen width in init_page_info, and updating chars_per_line
accordingly.
Note that now we report the same width for both TERM=xterm and TERM=ansi,
which is much clearer.
The point where readline respectively expects or ensures wrapping is still
indicated by "maint info screen", for xterm:
...
Number of characters readline reports are in a line is 40.
...
and ansi:
...
Number of characters readline reports are in a line is 39.
...
VI. Testing
PR cli/30346 is covered by existing regression tests gdb.base/wrap-line.exp
and gdb.tui/wrap-line.exp, so remove the KFAILs there.
I didn't manage to come up with a regression test for PR cli/30411. Perhaps
that would be easier if we had a maintenance command that echoes its arguments
while applying gdb output wrapping.
Tested on x86_64-linux.
PR cli/30346
PR cli/30411
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30346
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30411
Andrew pointed out that the behaviour as tested in gdb.tui/compact-source.exp
is incorrect:
...
0 +-compact-source.c--------------------------------------------------------+
1 |___3_{ |
2 |___4_ return 0; |
3 |___5_} |
4 |___6_ |
5 |___7_ |
6 |___8_ |
7 |___9_ |
8 +-------------------------------------------------------------------------+
...
The last line number in the source file is 5, and there are 7 lines to display
source lines, so if we'd scroll all the way down, the first line number in the
source window would be 5, and the last one would be 11.
To represent 11 we'd need 2 digits, so we expect to see ___04_ here instead of
___4_, even though all line numbers currently in the src window (3-9) can be
represented with only 1 digit.
Fix this in tui_source_window::set_contents, by updating the computation of
max_line_nr:
...
- int max_line_nr = std::max (lines_in_file, last_line_nr_in_window);
+ int max_line_nr = lines_in_file + nlines - 1;
...
Tested on x86_64-linux.
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Approved-By: Tom Tromey <tom@tromey.com>
Consider a hello.c, with less than 10 lines:
...
$ wc -l hello.c
8 hello.c
...
and compiled with -g into an a.out.
With compact-source off:
...
$ gdb -q a.out \
-ex "set tui border-kind ascii" \
-ex "maint set tui-left-margin-verbose on" \
-ex "set tui compact-source off" \
-ex "tui enable"
...
we get:
...
+-./data/hello.c-----------------------+
|___000005_{ |
|___000006_ printf ("hello\n"); |
|___000007_ return 0; |
|___000008_} |
|___000009_ |
|___000010_ |
|___000011_ |
...
but with compact-source on:
...
+-./data/hello.c-----------------------+
|___5{ |
|___6 printf ("hello\n"); |
|___7 return 0; |
|___8} |
|___9 |
|___1 |
|___1 |
...
There are a couple of problems with compact-source.
First of all the documentation mentions:
...
The default display uses more space for line numbers and starts the
source text at the next tab stop; the compact display uses only as
much space as is needed for the line numbers in the current file, and
only a single space to separate the line numbers from the source.
...
The bit about the default display and the next tab stop looks incorrect. The
source doesn't start at a tab stop, instead it uses a single space to separate
the line numbers from the source.
Then the documentation mentions that there's single space in the compact
display, but evidently that's missing.
Then there's the fact that the line numbers "10" and "11" are both abbreviated
to "1" in the compact case.
The abbreviation is due to allocating space for <lines in source>, which is
8 for this example, and takes a single digit. The line numbers though
continue past the end of the file, so fix this by allocating space for
max (<lines in source>, <last line in window>), which in this example takes 2
digits.
The missing space is due to some confusion about what the "1" here in
tui_source_window::set_contents represent:
...
double l = log10 ((double) offsets->size ());
m_digits = 1 + (int) l;
...
It could be the trailing space that's mentioned in tui-source.h:
...
/* How many digits to use when formatting the line number. This
includes the trailing space. */
int m_digits;
...
Then again, it could be part of the calculation for the number of digits
needed for printing. With this minimal example:
...
int main () {
for (int i = 8; i <= 11; ++i) {
double l = log10 ((double) i);
printf ("%d %d\n", i, (int)l);
}
return 0;
}
...
we get:
...
$ ./a.out
8 0
9 0
10 1
11 1
...
which shows that the number of digits needed for printing i is
"1 + (int)log10 ((double) i)".
Fix this by introducing named variables needed_digits and trailing_space, each
adding 1.
With the fixes, we get for compact-source on:
...
+-./data/hello.c-----------------------+
|___05_{ |
|___06_ printf ("hello\n"); |
|___07_ return 0; |
|___08_} |
|___09_ |
|___10_ |
|___11_ |
|...
Also fix the documentation and help text to actually match effect of
compact-source.
Tested on x86_64-linux.
Add a test-case that tests prompt edit wrapping behaviour in the tuiterm, both
for CLI and TUI, both with auto-detected and hard-coded width.
In the CLI case with auto-detected width we run into PR cli/30411, so add a
KFAIL for that failure mode.
Tested on x86_64-linux.
With TERM=ansi, when resizing a TUI window from LINES/COLUMNS 31/118
(maximized) to 20/78 (de-maximized), I get a garbled screen (that ^L doesn't
fix) and a message:
...
@@ resize done 0, size = 77x20
...
with the resulting width being 77 instead of the expected 78.
[ The discrepancy also manifests in CLI, filed as PR30346. ]
The discrepancy comes from tui_resize_all, where we ask readline for the
screen size:
...
rl_get_screen_size (&screenheight, &screenwidth);
...
As it happens, when TERM is set to ansi, readline decides that the terminal
cannot auto-wrap lines, and reserves one column to deal with that, and as a
result reports back one less than the actual screen width:
...
$ echo $COLUMNS
78
$ TERM=xterm gdb -ex "show width" -ex q
Number of characters gdb thinks are in a line is 78.
$ TERM=ansi gdb -ex "show width" -ex q
Number of characters gdb thinks are in a line is 77.
...
In tui_resize_all, we need the actual screen width, and using a screenwidth of
one less than the actual value garbles the screen.
This is currently not causing trouble in testing because we have a workaround
in place in proc Term::resize. If we disable the workaround:
...
- stty columns [expr {$_cols + 1}] < $::gdb_tty_name
+ stty columns $_cols < $::gdb_tty_name
...
and dump the screen we get the same type of screen garbling:
...
0 +---------------------------------------+|
1 ||
2 ||
3 ||
...
Another way to reproduce the problem is using command "maint info screen".
After starting gdb with TERM=ansi, entering TUI, and issuing the command, we
get:
...
Number of characters curses thinks are in a line is 78.
...
and after maximizing and demaximizing the window we get:
...
Number of characters curses thinks are in a line is 77.
...
If we use TERM=xterm, we do get the expected 78.
Fix this by:
- detecting when readline will report back less than the actual screen width,
- accordingly setting a new variable readline_hidden_cols,
- using readline_hidden_cols in tui_resize_all to fix the resize problem, and
- removing the workaround in Term::resize.
The test-case gdb.tui/empty.exp serves as regression test.
I've applied the same fix in tui_async_resize_screen, the new test-case
gdb.tui/resize-2.exp serves as a regression test for that change. Without
that fix, we have:
...
FAIL: gdb.tui/resize-2.exp: again: gdb width 80
...
Tested on x86_64-linux.
PR tui/30337
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30337
With a build with --disable-tui, we get:
...
(gdb) PASS: gdb.tui/main.exp: set interactive-mode off
maint set tui-left-margin-verbose on^M
Undefined maintenance set command: "tui-left-margin-verbose on". \
Try "help maintenance set".^M
(gdb) FAIL: gdb.tui/main.exp: maint set tui-left-margin-verbose on
...
Fix this by adding the missing "require allow_tui_tests".
Tested on x86_64-linux.
With test-case gdb.tui/completion.exp, we run into:
...
WARNING: timeout in accept_gdb_output
PASS: gdb.tui/completion.exp: check focus completions
...
The timeout happens in this command:
...
Term::command "layout src"
...
which waits for:
- "(gdb) layout src", and then
- "(gdb) ".
Because the "layout src" command enables the TUI there's just a prompt.
Fix this by using Term::command_no_prompt_prefix.
Tested on x86_64-linux.
With test-case gdb.tui/main.exp we run into:
...
WARNING: timeout in accept_gdb_output
PASS: gdb.tui/main.exp: show main after file
...
The problem is that this command:
...
Term::command "file [standard_output_file $testfile]"
...
tries to match "(gdb) $cmd", but due to the long file name, $cmd is split up
over two lines:
...
16 (gdb) file /data/vries/gdb/leap-15-4/build/gdb/testsuite/outputs/gdb.tui/main/ma
17 in
18 Reading symbols from /data/vries/gdb/leap-15-4/build/gdb/testsuite/outputs/gdb.t
19 ui/main/main...
20 (gdb)
...
Fix this by matching "Reading symbols from" instead.
Tested on x86_64-linux.
With test-case gdb.tui/corefile-run.exp we run into:
...
WARNING: timeout in accept_gdb_output
PASS: gdb.tui/corefile-run.exp: load corefile
...
The timeout happens in this command:
...
Term::command "core-file $core"
...
because it tries to match "(gdb) $cmd" but $cmd is split over two lines:
...
16 (gdb) core-file /data/vries/gdb/leap-15-4/build/gdb/testsuite/outputs/gdb.tui/co
17 refile-run/corefile-run.core
18 [New LWP 5370]
19 Core was generated by `/data/vries/gdb/leap-15-4/build/gdb/testsuite/outputs/gdb
20 .tui/corefile-run/coref'.
21 Program terminated with signal SIGTRAP, Trace/breakpoint trap.
22 #0 main () at tui-layout.c:21
23 (gdb)
...
Fix this by using send_gdb "$cmd\n" and wait_for "Program terminated" instead.
Tested on x86_64-linux.
Add regression tests for PR30325, one for the asm window and one for the
source window.
Use maint set tui-left-margin verbose to make the extend of the left margin
clear.
Tested on x86_64-linux.
Approved-By: Andrew Burgess <aburgess@redhat.com>
When running test-case gdb.tui/completion.exp with host board
local-remote-host-notty and target board native-gdbserver, I get:
...
FAIL: gdb.tui/completion.exp: completion of layout names: \
tab completion (timeout)
...
The test-case contains a few tests that do tab completion, which requires
readline, which is unavailable with host board local-remote-host-notty.
Fix this by adding the missing check for readline_is_used.
Tested on x86_64-linux.
When running test-case gdb.tui/tui-layout.exp with host board
local-remote-host-notty and target board native-gdbserver, I get:
...
FAIL: gdb.tui/tui-layout.exp: terminal=dumb: execution=false: layout=asm: \
layout asm (timeout)
...
The problem is that the test-case expects that the default "setenv TERM dumb"
has effect, which is not the case for remote host.
Fix this by skipping the test for remote host.
Tested on x86_64-linux.
When running test-case gdb.tui/tui-nl-filtered-output.exp with host board
local-remote-host-notty and target board native-gdbserver, I get:
...
FAIL: gdb.tui/tui-nl-filtered-output.exp: check printf output
...
The problem is that Term::enter_tui is returning 0, but the test-case doesn't
check for this, and consequently runs unsupported tests.
Fix this by adding the missing check.
Tested on x86_64-linux.