aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/python/lib/gdb/dap/events.py4
-rw-r--r--gdb/python/lib/gdb/dap/next.py12
-rw-r--r--gdb/python/lib/gdb/dap/server.py27
-rw-r--r--gdb/python/lib/gdb/dap/startup.py10
-rw-r--r--gdb/testsuite/gdb.dap/attach-fail.exp32
-rwxr-xr-xgdb/testsuite/gdb.tui/gdb.sh (renamed from gdb/testsuite/gdb.tui/gdb.tcl)6
-rw-r--r--gdb/testsuite/gdb.tui/pr30056.exp114
-rw-r--r--gdb/testsuite/gdb.tui/tui-long-line.c24
-rw-r--r--gdb/testsuite/gdb.tui/tui-missing-src.exp1
-rw-r--r--gdb/testsuite/gdb.tui/tuiterm-2.exp18
-rw-r--r--gdb/testsuite/gdb.tui/wrap-line.exp22
-rw-r--r--gdb/testsuite/lib/dap-support.exp4
-rw-r--r--gdb/testsuite/lib/gdb.exp4
13 files changed, 168 insertions, 110 deletions
diff --git a/gdb/python/lib/gdb/dap/events.py b/gdb/python/lib/gdb/dap/events.py
index e8f2655..778acc5 100644
--- a/gdb/python/lib/gdb/dap/events.py
+++ b/gdb/python/lib/gdb/dap/events.py
@@ -161,7 +161,7 @@ _expected_pause = False
@in_gdb_thread
-def exec_and_expect_stop(cmd, expected_pause=False, propagate_exception=False):
+def exec_and_expect_stop(cmd, expected_pause=False):
"""A wrapper for exec_and_log that sets the continue-suppression flag.
When EXPECTED_PAUSE is True, a stop that looks like a pause (e.g.,
@@ -174,7 +174,7 @@ def exec_and_expect_stop(cmd, expected_pause=False, propagate_exception=False):
# continuing.
_suppress_cont = not expected_pause
# FIXME if the call fails should we clear _suppress_cont?
- exec_and_log(cmd, propagate_exception)
+ exec_and_log(cmd)
# Map from gdb stop reasons to DAP stop reasons. Some of these can't
diff --git a/gdb/python/lib/gdb/dap/next.py b/gdb/python/lib/gdb/dap/next.py
index 898fff1..993e9d2 100644
--- a/gdb/python/lib/gdb/dap/next.py
+++ b/gdb/python/lib/gdb/dap/next.py
@@ -17,7 +17,7 @@ import gdb
from .events import exec_and_expect_stop
from .server import capability, request
-from .startup import in_gdb_thread
+from .startup import DAPException, exec_and_log, in_gdb_thread
from .state import set_thread
@@ -36,11 +36,9 @@ def _handle_thread_step(thread_id, single_thread, select=False):
result = False
arg = "off"
try:
- # This can fail, depending on the target, so catch the error
- # and report to our caller. We can't use exec_and_log because
- # that does not propagate exceptions.
- gdb.execute("set scheduler-locking " + arg, from_tty=True, to_string=True)
- except gdb.error:
+ # This can fail, depending on the target, so catch any error.
+ exec_and_log("set scheduler-locking " + arg)
+ except DAPException:
result = False
# Other DAP code may select a frame, and the "finish" command uses
# the selected frame.
@@ -76,7 +74,7 @@ def step_in(
@request("stepOut")
def step_out(*, threadId: int, singleThread: bool = False, **args):
_handle_thread_step(threadId, singleThread, True)
- exec_and_expect_stop("finish &", propagate_exception=True)
+ exec_and_expect_stop("finish &")
@request("continue")
diff --git a/gdb/python/lib/gdb/dap/server.py b/gdb/python/lib/gdb/dap/server.py
index 7dab582..98a8084 100644
--- a/gdb/python/lib/gdb/dap/server.py
+++ b/gdb/python/lib/gdb/dap/server.py
@@ -398,7 +398,7 @@ class Server:
# responses are flushed to the client before exiting.
self._write_queue.put(None)
json_writer.join()
- send_gdb("quit")
+ send_gdb(lambda: exec_and_log("quit"))
@in_dap_thread
def set_defer_events(self):
@@ -614,7 +614,7 @@ def terminate(**args):
@capability("supportTerminateDebuggee")
def disconnect(*, terminateDebuggee: bool = False, **args):
if terminateDebuggee:
- send_gdb_with_response("kill")
+ send_gdb_with_response(lambda: exec_and_log("kill"))
_server.shutdown()
@@ -633,18 +633,6 @@ def cancel(**args):
return None
-class Invoker(object):
- """A simple class that can invoke a gdb command."""
-
- def __init__(self, cmd):
- self._cmd = cmd
-
- # This is invoked in the gdb thread to run the command.
- @in_gdb_thread
- def __call__(self):
- exec_and_log(self._cmd)
-
-
class Cancellable(object):
def __init__(self, fn, result_q=None):
@@ -677,25 +665,16 @@ class Cancellable(object):
def send_gdb(cmd):
"""Send CMD to the gdb thread.
- CMD can be either a function or a string.
- If it is a string, it is passed to gdb.execute."""
- if isinstance(cmd, str):
- cmd = Invoker(cmd)
-
+ CMD is a function."""
# Post the event and don't wait for the result.
gdb.post_event(Cancellable(cmd))
def send_gdb_with_response(fn):
"""Send FN to the gdb thread and return its result.
- If FN is a string, it is passed to gdb.execute and None is
- returned as the result.
If FN throws an exception, this function will throw the
same exception in the calling thread.
"""
- if isinstance(fn, str):
- fn = Invoker(fn)
-
# Post the event and wait for the result in result_q.
result_q = DAPQueue()
gdb.post_event(Cancellable(fn, result_q))
diff --git a/gdb/python/lib/gdb/dap/startup.py b/gdb/python/lib/gdb/dap/startup.py
index ab3e8fd..0c95ada 100644
--- a/gdb/python/lib/gdb/dap/startup.py
+++ b/gdb/python/lib/gdb/dap/startup.py
@@ -204,7 +204,7 @@ def log_stack(level=LogLevel.DEFAULT):
@in_gdb_thread
-def exec_and_log(cmd, propagate_exception=False):
+def exec_and_log(cmd):
"""Execute the gdb command CMD.
If logging is enabled, log the command and its output."""
log("+++ " + cmd)
@@ -213,10 +213,10 @@ def exec_and_log(cmd, propagate_exception=False):
if output != "":
log(">>> " + output)
except gdb.error as e:
- if propagate_exception:
- raise DAPException(str(e)) from e
- else:
- log_stack()
+ # Don't normally want to see this, as it interferes with the
+ # test suite.
+ log_stack(LogLevel.FULL)
+ raise DAPException(str(e)) from e
@in_gdb_thread
diff --git a/gdb/testsuite/gdb.dap/attach-fail.exp b/gdb/testsuite/gdb.dap/attach-fail.exp
new file mode 100644
index 0000000..8992f62
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/attach-fail.exp
@@ -0,0 +1,32 @@
+# Copyright 2025 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/>.
+
+# Test "attach" failure in DAP.
+
+require can_spawn_for_attach allow_dap_tests
+
+load_lib dap-support.exp
+
+# Passing an empty remote name here will guarantee a failure without
+# trying to find a real remote.
+set id [dap_target_remote {""}]
+
+dap_check_request_and_response "configurationDone" configurationDone
+
+set resp [lindex [dap_read_response attach $id] 0]
+gdb_assert {[dict get $resp success] == "false"} \
+ "attach failed"
+
+dap_shutdown
diff --git a/gdb/testsuite/gdb.tui/gdb.tcl b/gdb/testsuite/gdb.tui/gdb.sh
index ca207ed..0079a3f 100755
--- a/gdb/testsuite/gdb.tui/gdb.tcl
+++ b/gdb/testsuite/gdb.tui/gdb.sh
@@ -1,4 +1,4 @@
-#!/usr/bin/env tclsh
+#!/bin/sh
# Copyright 2025 Free Software Foundation, Inc.
@@ -15,6 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-puts "foo\033(%5"
+printf "foo\033(%%5"
-gets stdin
+read
diff --git a/gdb/testsuite/gdb.tui/pr30056.exp b/gdb/testsuite/gdb.tui/pr30056.exp
index dd3b25c..3cf5e90 100644
--- a/gdb/testsuite/gdb.tui/pr30056.exp
+++ b/gdb/testsuite/gdb.tui/pr30056.exp
@@ -22,66 +22,72 @@ require {have_host_locale C.UTF-8}
tuiterm_env
+standard_testfile tui-long-line.c
+
+if { [build_executable "failed to prepare" $testfile $srcfile] == -1 } {
+ return
+}
+
save_vars { env(LC_ALL) } {
setenv LC_ALL C.UTF-8
# Start terminal.
- Term::clean_restart 24 80
-
- # Start TUI.
- if {![Term::enter_tui]} {
- unsupported "TUI not supported"
- return
- }
-
- # Send "^R", starting reverse-i-search.
- send_gdb "\022"
- Term::wait_for_region_contents 0 $Term::_cur_row $Term::_cols 1 \
- [string_to_regexp "(reverse-i-search)`': "]
-
- # Send "xyz".
- send_gdb "xyz"
- Term::wait_for_region_contents 0 $Term::_cur_row $Term::_cols 1 \
- [string_to_regexp "(failed reverse-i-search)`xyz': "]
-
- # Send arrow-right.
- send_gdb "\033\[C"
+ Term::clean_restart 24 80 $testfile
+}
- # We need to the arrow-right to be processed by readline, before we
- # send the following ^C. Waiting 1 ms seems to do that.
- after 1
+# Start TUI.
+if {![Term::enter_tui]} {
+ unsupported "TUI not supported"
+ return
+}
- # Send ^C.
+# Send "^R", starting reverse-i-search.
+send_gdb "\022"
+gdb_assert { [Term::wait_for_region_contents 0 $Term::_cur_row $Term::_cols 1 \
+ [string_to_regexp "(reverse-i-search)`': "]] } \
+ "reverse-i-search"
+
+# Send "xyz".
+send_gdb "xyz"
+gdb_assert { [Term::wait_for_region_contents 0 $Term::_cur_row $Term::_cols 1 \
+ [string_to_regexp "(failed reverse-i-search)`xyz': "]] } \
+ "xyz"
+
+# Send arrow-right.
+send_gdb "\033\[C"
+# Wait for arrow-right effect.
+gdb_assert { [Term::wait_for_region_contents 1 5 78 1 \
+ [string_to_regexp " ain (void)"]] } "arrow right"
+
+# Send ^C.
+send_gdb "\003"
+gdb_assert { [Term::wait_for "Quit"] } "Control-C"
+
+set test "Control-C aborts isearch"
+
+# Send "xyz", again.
+send_gdb "xyz"
+# Wait for xyx to appear.
+gdb_assert { [Term::wait_for_region_contents \
+ 0 $Term::_cur_row $Term::_cols 1 "xyz"] } \
+ "xyz, again"
+
+if { [Term::check_region_contents_p 0 $Term::_cur_row $Term::_cols 1 \
+ "^$gdb_prompt xyz"] } {
+ pass $test
+
+ # Send ^C to clear the command line.
send_gdb "\003"
- gdb_assert { [Term::wait_for "Quit"] } "Control-C"
-
- # Uncomment this to simulate that PR cli/30498 is fixed.
- #send_gdb "\007"
-
- set test "Control-C aborts isearch"
-
- # Send "xyz", again.
- send_gdb "xyz"
- # Wait for xyx to appear.
- Term::wait_for_region_contents 0 $Term::_cur_row $Term::_cols 1 "xyz"
+} else {
+ # Sending ^C currently doesn't abort the i-search.
+ fail $test
- if { [Term::check_region_contents_p 0 $Term::_cur_row $Term::_cols 1 \
- "^$gdb_prompt xyz"] } {
- pass $test
-
- # Send ^C to clear the command line.
- send_gdb "\003"
- } else {
- # Sending ^C currently doesn't abort the i-search.
- fail $test
-
- # At this point we don't have a responsive prompt. Send ^G to abort
- # the i-search.
- send_gdb "\007"
- }
-
- # We need a responsive prompt here, to deal with the "monitor exit"
- # that native-extended-gdbserver will send. Check that we have a
- # responsive prompt.
- Term::command "echo \\n"
+ # At this point we don't have a responsive prompt. Send ^G to abort
+ # the i-search.
+ send_gdb "\007"
}
+
+# We need a responsive prompt here, to deal with the "monitor exit"
+# that native-extended-gdbserver will send. Check that we have a
+# responsive prompt.
+Term::command "echo \\n"
diff --git a/gdb/testsuite/gdb.tui/tui-long-line.c b/gdb/testsuite/gdb.tui/tui-long-line.c
new file mode 100644
index 0000000..8f1d6eb
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/tui-long-line.c
@@ -0,0 +1,24 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 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)
+{
+ /* This is a comment that is meant to be longer than the usual 80 characters width of a tuiterm. */
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.tui/tui-missing-src.exp b/gdb/testsuite/gdb.tui/tui-missing-src.exp
index aca417c..ae98775 100644
--- a/gdb/testsuite/gdb.tui/tui-missing-src.exp
+++ b/gdb/testsuite/gdb.tui/tui-missing-src.exp
@@ -27,6 +27,7 @@
# Check if start command is supported.
require !use_gdb_stub
+require allow_tui_tests
tuiterm_env
diff --git a/gdb/testsuite/gdb.tui/tuiterm-2.exp b/gdb/testsuite/gdb.tui/tuiterm-2.exp
index a451834..9e3ddc7 100644
--- a/gdb/testsuite/gdb.tui/tuiterm-2.exp
+++ b/gdb/testsuite/gdb.tui/tuiterm-2.exp
@@ -152,14 +152,17 @@ with_override Term::accept_gdb_output test_accept_gdb_output {
}
}
-with_test_prefix "Unrecognized escape sequence" {
- spawn $srcdir/$subdir/gdb.tcl
- switch_gdb_spawn_id $spawn_id
+proc_with_prefix unrecognized_escape_sequence {} {
+ if { [spawn $::srcdir/$::subdir/gdb.sh] == 0 } {
+ unsupported "cannot spawn gdb.sh"
+ return
+ }
+ switch_gdb_spawn_id $spawn_id
Term::_setup 4 20
- save_vars timeout {
- set timeout 1
+ save_vars ::timeout {
+ set ::timeout 1
set line { 0 0 20 1 }
@@ -178,4 +181,9 @@ with_test_prefix "Unrecognized escape sequence" {
"echoed escape sequence"
}
Term::dump_screen
+
+ close $spawn_id
+ clear_gdb_spawn_id
}
+
+unrecognized_escape_sequence
diff --git a/gdb/testsuite/gdb.tui/wrap-line.exp b/gdb/testsuite/gdb.tui/wrap-line.exp
index a1ba706..67ad36c 100644
--- a/gdb/testsuite/gdb.tui/wrap-line.exp
+++ b/gdb/testsuite/gdb.tui/wrap-line.exp
@@ -104,29 +104,35 @@ proc test_wrap_cli_tui { auto_detected_width } {
set re1 "Number of characters gdb thinks are in a line is ($::decimal)\\."
set re2 \
"Number of characters readline reports are in a line is ($::decimal)\\."
+ set re3 \
+ "Readline wrapping mode: (\[a-z\]+) \[\^\r\n]*"
set cmd "maint info screen"
set re \
[multi_line \
"^$re1" \
$re2 \
- ".*"]
+ ".*" \
+ $re3]
gdb_test_multiple $cmd "" {
-re -wrap $re {
set gdb_width $expect_out(1,string)
set readline_width $expect_out(2,string)
+ set wrapping_mode $expect_out(3,string)
pass $gdb_test_name
}
}
- gdb_assert { $gdb_width == $::cols } "width"
+ if { $wrapping_mode == "readline" } {
+ gdb_assert { $gdb_width == $::cols } "width"
- # TERM=ansi, so readline hides the last column.
- gdb_assert { $gdb_width == [expr $readline_width + 1] }
+ # TERM=ansi, so readline hides the last column.
+ gdb_assert { $gdb_width == [expr $readline_width + 1] }
- with_test_prefix cli {
- set wrap_width $readline_width
+ with_test_prefix cli {
+ set wrap_width $readline_width
- test_wrap $wrap_width 0
+ test_wrap $wrap_width 0
+ }
}
with_test_prefix tui {
@@ -172,7 +178,7 @@ with_test_prefix width-auto-detected {
set test "startup prompt"
gdb_test_multiple "" $test {
- -re "^$gdb_prompt $" {
+ -re "^(\033\\\[6n)?$gdb_prompt $" {
pass "$test"
}
}
diff --git a/gdb/testsuite/lib/dap-support.exp b/gdb/testsuite/lib/dap-support.exp
index 2d962e6..5c078ca 100644
--- a/gdb/testsuite/lib/dap-support.exp
+++ b/gdb/testsuite/lib/dap-support.exp
@@ -231,9 +231,9 @@ proc dap_read_response {cmd num} {
set d [_dap_read_json]
if {[dict get $d type] == "response"} {
if {[dict get $d request_seq] != $num} {
- error "saw wrong request_seq in $obj"
+ error "saw wrong request_seq in $d"
} elseif {[dict get $d command] != $cmd} {
- error "saw wrong command in $obj"
+ error "saw wrong command in $d"
} else {
return [list $d $result]
}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index f05e1c8..9497850 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -3122,6 +3122,10 @@ gdb_caching_proc allow_dlmopen_tests {} {
# Return 1 if we should allow TUI-related tests.
gdb_caching_proc allow_tui_tests {} {
+ if { [istarget *-*-mingw*] } {
+ # Avoid "Cannot enable the TUI when output is not a terminal".
+ return 0
+ }
set output [remote_exec host $::GDB "$::INTERNAL_GDBFLAGS --configuration"]
return [expr {[string first "--enable-tui" $output] != -1}]
}