10c8a34890ed8d86e5a3041850d40b575a0edc25
1 # Copyright 2022-2023 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 from .server
import send_event
20 from .startup
import in_gdb_thread
, Invoker
, log
21 from .modules
import is_module
, make_module
27 if hasattr(event
, "exit_code"):
28 code
= event
.exit_code
38 def thread_event(event
, reason
):
43 "threadId": event
.inferior_thread
.global_num
,
49 def _new_thread(event
):
50 thread_event(event
, "started")
54 def _thread_exited(event
):
55 thread_event(event
, "exited")
59 def _new_objfile(event
):
60 if is_module(event
.new_objfile
):
65 "module": make_module(event
.new_objfile
),
70 _suppress_cont
= False
77 log("_suppress_cont case")
78 _suppress_cont
= False
83 "threadId": gdb
.selected_thread().global_num
,
84 "allThreadsContinued": True,
89 class StopKinds(enum
.Enum
):
90 # The values here are chosen to follow the DAP spec.
92 BREAKPOINT
= "breakpoint"
94 EXCEPTION
= "exception"
101 def expect_stop(reason
):
102 """Indicate that a stop is expected, for the reason given."""
103 global _expected_stop
104 _expected_stop
= reason
107 # A wrapper for Invoker that also sets the expected stop.
108 class ExecutionInvoker(Invoker
):
109 """A subclass of Invoker that sets the expected stop.
110 Note that this assumes that the command will restart the inferior,
111 so it will also cause ContinuedEvents to be suppressed."""
113 def __init__(self
, cmd
, expected
):
114 super().__init
__(cmd
)
115 self
.expected
= expected
119 expect_stop(self
.expected
)
120 global _suppress_cont
121 _suppress_cont
= True
122 # FIXME if the call fails should we clear _suppress_cont?
128 log("entering _on_stop: " + repr(event
))
129 global _expected_stop
131 "threadId": gdb
.selected_thread().global_num
,
132 "allThreadsStopped": True,
134 if isinstance(event
, gdb
.BreakpointEvent
):
135 # Ignore the expected stop, we hit a breakpoint instead.
136 _expected_stop
= StopKinds
.BREAKPOINT
137 obj
["hitBreakpointIds"] = [x
.number
for x
in event
.breakpoints
]
138 elif _expected_stop
is None:
139 # FIXME what is even correct here
140 _expected_stop
= StopKinds
.EXCEPTION
141 obj
["reason"] = _expected_stop
.value
142 _expected_stop
= None
143 send_event("stopped", obj
)
146 gdb
.events
.stop
.connect(_on_stop
)
147 gdb
.events
.exited
.connect(_on_exit
)
148 gdb
.events
.new_thread
.connect(_new_thread
)
149 gdb
.events
.thread_exited
.connect(_thread_exited
)
150 gdb
.events
.cont
.connect(_cont
)
151 gdb
.events
.new_objfile
.connect(_new_objfile
)