public inbox for gdb-cvs@sourceware.org help / color / mirror / Atom feed
From: Tom Tromey <tromey@sourceware.org> To: gdb-cvs@sourceware.org Subject: [binutils-gdb] Simplify DAP stop-reason code Date: Mon, 11 Dec 2023 18:43:37 +0000 (GMT) [thread overview] Message-ID: <20231211184337.C2A01385842F@sourceware.org> (raw) https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7729e7c0bdd01027a003181a99d58aadd981896a commit 7729e7c0bdd01027a003181a99d58aadd981896a Author: Tom Tromey <tromey@adacore.com> Date: Fri Nov 3 13:59:10 2023 -0600 Simplify DAP stop-reason code Now that gdb adds stop-reason details to stop events, we can simplify the DAP code to emit correct stop reasons in its own events. For the most part a simple renaming of gdb reasons is sufficient; however, "pause" must still be handled specially. Diff: --- gdb/python/lib/gdb/dap/events.py | 95 ++++++++++++++++++++++++++++------------ gdb/python/lib/gdb/dap/launch.py | 4 +- gdb/python/lib/gdb/dap/next.py | 10 ++--- gdb/python/lib/gdb/dap/pause.py | 4 +- 4 files changed, 76 insertions(+), 37 deletions(-) diff --git a/gdb/python/lib/gdb/dap/events.py b/gdb/python/lib/gdb/dap/events.py index b759ba43b5f..cbefe90e4ca 100644 --- a/gdb/python/lib/gdb/dap/events.py +++ b/gdb/python/lib/gdb/dap/events.py @@ -13,7 +13,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/>. -import enum import gdb from .server import send_event @@ -148,48 +147,77 @@ def _cont(event): ) -class StopKinds(enum.Enum): - # The values here are chosen to follow the DAP spec. - STEP = "step" - BREAKPOINT = "breakpoint" - PAUSE = "pause" - EXCEPTION = "exception" - - -_expected_stop = None +_expected_pause = False @in_gdb_thread -def exec_and_expect_stop(cmd, reason): - """Indicate that a stop is expected, then execute CMD""" - global _expected_stop - _expected_stop = reason - if reason != StopKinds.PAUSE: - global _suppress_cont - _suppress_cont = True +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., + a SIGINT) will be reported as "pause" instead. + """ + global _expected_pause + _expected_pause = expected_pause + global _suppress_cont + # If we're expecting a pause, then we're definitely not + # continuing. + _suppress_cont = not expected_pause # FIXME if the call fails should we clear _suppress_cont? exec_and_log(cmd) +# Map from gdb stop reasons to DAP stop reasons. Some of these can't +# be seen ordinarily in DAP -- only if the client lets the user toggle +# some settings (e.g. stop-on-solib-events) or enter commands (e.g., +# 'until'). +stop_reason_map = { + "breakpoint-hit": "breakpoint", + "watchpoint-trigger": "data breakpoint", + "read-watchpoint-trigger": "data breakpoint", + "access-watchpoint-trigger": "data breakpoint", + "function-finished": "step", + "location-reached": "step", + "watchpoint-scope": "data breakpoint", + "end-stepping-range": "step", + "exited-signalled": "exited", + "exited": "exited", + "exited-normally": "exited", + "signal-received": "signal", + "solib-event": "solib", + "fork": "fork", + "vfork": "vfork", + "syscall-entry": "syscall-entry", + "syscall-return": "syscall-return", + "exec": "exec", + "no-history": "no-history", +} + + @in_gdb_thread def _on_stop(event): global inferior_running inferior_running = False log("entering _on_stop: " + repr(event)) - global _expected_stop + log(" details: " + repr(event.details)) obj = { "threadId": gdb.selected_thread().global_num, "allThreadsStopped": True, } if isinstance(event, gdb.BreakpointEvent): - # Ignore the expected stop, we hit a breakpoint instead. - _expected_stop = StopKinds.BREAKPOINT obj["hitBreakpointIds"] = [x.number for x in event.breakpoints] - elif _expected_stop is None: - # FIXME what is even correct here - _expected_stop = StopKinds.EXCEPTION - obj["reason"] = _expected_stop.value - _expected_stop = None + global stop_reason_map + reason = event.details["reason"] + global _expected_pause + if ( + _expected_pause + and reason == "signal-received" + and event.details["signal-name"] in ("SIGINT", "SIGSTOP") + ): + obj["reason"] = "pause" + else: + obj["reason"] = stop_reason_map[reason] + _expected_pause = False send_event("stopped", obj) @@ -204,13 +232,26 @@ _infcall_was_running = False @in_gdb_thread def _on_inferior_call(event): global _infcall_was_running + global inferior_running if isinstance(event, gdb.InferiorCallPreEvent): _infcall_was_running = inferior_running if not _infcall_was_running: _cont(None) else: - if not _infcall_was_running: - _on_stop(None) + # If the inferior is already marked as stopped here, then that + # means that the call caused some other stop, and we don't + # want to double-report it. + if not _infcall_was_running and inferior_running: + inferior_running = False + obj = { + "threadId": gdb.selected_thread().global_num, + "allThreadsStopped": True, + # DAP says any string is ok. + "reason": "function call", + } + global _expected_pause + _expected_pause = False + send_event("stopped", obj) gdb.events.stop.connect(_on_stop) diff --git a/gdb/python/lib/gdb/dap/launch.py b/gdb/python/lib/gdb/dap/launch.py index 995641bd945..7014047ff51 100644 --- a/gdb/python/lib/gdb/dap/launch.py +++ b/gdb/python/lib/gdb/dap/launch.py @@ -80,6 +80,4 @@ def config_done(**args): global _program if _program is not None: expect_process("process") - # Suppress the continue event, but don't set any particular - # expected stop. - exec_and_expect_stop("run", None) + exec_and_expect_stop("run") diff --git a/gdb/python/lib/gdb/dap/next.py b/gdb/python/lib/gdb/dap/next.py index eedc26f28a5..c06093e74ed 100644 --- a/gdb/python/lib/gdb/dap/next.py +++ b/gdb/python/lib/gdb/dap/next.py @@ -15,7 +15,7 @@ import gdb -from .events import StopKinds, exec_and_expect_stop +from .events import exec_and_expect_stop from .server import capability, request from .startup import in_gdb_thread, send_gdb, send_gdb_with_response from .state import set_thread @@ -57,7 +57,7 @@ def next( cmd = "next" if granularity == "instruction": cmd += "i" - exec_and_expect_stop(cmd, StopKinds.STEP) + exec_and_expect_stop(cmd) @capability("supportsSteppingGranularity") @@ -70,13 +70,13 @@ def step_in( cmd = "step" if granularity == "instruction": cmd += "i" - exec_and_expect_stop(cmd, StopKinds.STEP) + exec_and_expect_stop(cmd) @request("stepOut", response=False) def step_out(*, threadId: int, singleThread: bool = False, **args): _handle_thread_step(threadId, singleThread, True) - exec_and_expect_stop("finish", StopKinds.STEP) + exec_and_expect_stop("finish") # This is a server-side request because it is funny: it wants to @@ -87,5 +87,5 @@ def step_out(*, threadId: int, singleThread: bool = False, **args): @request("continue", on_dap_thread=True) def continue_request(*, threadId: int, singleThread: bool = False, **args): locked = send_gdb_with_response(lambda: _handle_thread_step(threadId, singleThread)) - send_gdb(lambda: exec_and_expect_stop("continue", None)) + send_gdb(lambda: exec_and_expect_stop("continue")) return {"allThreadsContinued": not locked} diff --git a/gdb/python/lib/gdb/dap/pause.py b/gdb/python/lib/gdb/dap/pause.py index b7e21452d69..19ff17d511b 100644 --- a/gdb/python/lib/gdb/dap/pause.py +++ b/gdb/python/lib/gdb/dap/pause.py @@ -13,10 +13,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from .events import StopKinds, exec_and_expect_stop +from .events import exec_and_expect_stop from .server import request @request("pause", response=False, expect_stopped=False) def pause(**args): - exec_and_expect_stop("interrupt -a", StopKinds.PAUSE) + exec_and_expect_stop("interrupt -a", True)
reply other threads:[~2023-12-11 18:43 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20231211184337.C2A01385842F@sourceware.org \ --to=tromey@sourceware.org \ --cc=gdb-cvs@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).