1 /* Remote notification in GDB protocol
2 
3    Copyright (C) 1988-2024 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 /* Remote async notification is sent from remote target over RSP.
21    Each type of notification is represented by an object of
22    'struct notif', which has a field 'pending_reply'.  It is not
23    NULL when GDB receives a notification from GDBserver, but hasn't
24    acknowledge yet.  Before GDB acknowledges the notification,
25    GDBserver shouldn't send notification again (see the header comments
26    in gdbserver/notif.c).
27 
28    Notifications are processed in an almost-unified approach for both
29    all-stop mode and non-stop mode, except the timing to process them.
30    In non-stop mode, notifications are processed in
31    remote_async_get_pending_events_handler, while in all-stop mode,
32    they are processed in remote_resume.  */
33 
34 #include "remote.h"
35 #include "remote-notif.h"
36 #include "observable.h"
37 #include "gdbsupport/event-loop.h"
38 #include "target.h"
39 #include "inferior.h"
40 #include "infrun.h"
41 #include "cli/cli-cmds.h"
42 #include "async-event.h"
43 
44 bool notif_debug = false;
45 
46 /* Supported clients of notifications.  */
47 
48 static const notif_client *const notifs[] =
49 {
50   &notif_client_stop,
51 };
52 
53 static_assert (ARRAY_SIZE (notifs) == REMOTE_NOTIF_LAST);
54 
55 /* Parse the BUF for the expected notification NC, and send packet to
56    acknowledge.  */
57 
58 void
remote_notif_ack(remote_target * remote,const notif_client * nc,const char * buf)59 remote_notif_ack (remote_target *remote,
60                       const notif_client *nc, const char *buf)
61 {
62   notif_event_up event = nc->alloc_event ();
63 
64   if (notif_debug)
65     gdb_printf (gdb_stdlog, "notif: ack '%s'\n",
66                     nc->ack_command);
67 
68   nc->parse (remote, nc, buf, event.get ());
69   nc->ack (remote, nc, buf, std::move (event));
70 }
71 
72 /* Parse the BUF for the expected notification NC.  */
73 
74 notif_event_up
remote_notif_parse(remote_target * remote,const notif_client * nc,const char * buf)75 remote_notif_parse (remote_target *remote,
76                         const notif_client *nc, const char *buf)
77 {
78   notif_event_up event = nc->alloc_event ();
79 
80   if (notif_debug)
81     gdb_printf (gdb_stdlog, "notif: parse '%s'\n", nc->name);
82 
83   nc->parse (remote, nc, buf, event.get ());
84 
85   return event;
86 }
87 
88 /* Process notifications in STATE's notification queue one by one.
89    EXCEPT is not expected in the queue.  */
90 
91 void
remote_notif_process(struct remote_notif_state * state,const notif_client * except)92 remote_notif_process (struct remote_notif_state *state,
93                           const notif_client *except)
94 {
95   while (!state->notif_queue.empty ())
96     {
97       const notif_client *nc = state->notif_queue.front ();
98       state->notif_queue.pop_front ();
99 
100       gdb_assert (nc != except);
101 
102       if (nc->can_get_pending_events (state->remote, nc))
103           remote_notif_get_pending_events (state->remote, nc);
104     }
105 }
106 
107 static void
remote_async_get_pending_events_handler(gdb_client_data data)108 remote_async_get_pending_events_handler (gdb_client_data data)
109 {
110   remote_notif_state *notif_state = (remote_notif_state *) data;
111   clear_async_event_handler (notif_state->get_pending_events_token);
112   gdb_assert (remote_target_is_non_stop_p (notif_state->remote));
113   remote_notif_process (notif_state, NULL);
114 }
115 
116 /* Remote notification handler.  Parse BUF, queue notification and
117    update STATE.  */
118 
119 void
handle_notification(struct remote_notif_state * state,const char * buf)120 handle_notification (struct remote_notif_state *state, const char *buf)
121 {
122   const notif_client *nc;
123   size_t i;
124 
125   for (i = 0; i < ARRAY_SIZE (notifs); i++)
126     {
127       const char *name = notifs[i]->name;
128 
129       if (startswith (buf, name)
130             && buf[strlen (name)] == ':')
131           break;
132     }
133 
134   /* We ignore notifications we don't recognize, for compatibility
135      with newer stubs.  */
136   if (i == ARRAY_SIZE (notifs))
137     return;
138 
139   nc =  notifs[i];
140 
141   if (state->pending_event[nc->id] != NULL)
142     {
143       /* We've already parsed the in-flight reply, but the stub for some
144            reason thought we didn't, possibly due to timeout on its side.
145            Just ignore it.  */
146       if (notif_debug)
147           gdb_printf (gdb_stdlog,
148                         "notif: ignoring resent notification\n");
149     }
150   else
151     {
152       notif_event_up event
153           = remote_notif_parse (state->remote, nc, buf + strlen (nc->name) + 1);
154 
155       /* Be careful to only set it after parsing, since an error
156            may be thrown then.  */
157       state->pending_event[nc->id] = std::move (event);
158 
159       /* Notify the event loop there's a stop reply to acknowledge
160            and that there may be more events to fetch.  */
161       state->notif_queue.push_back (nc);
162       if (target_is_non_stop_p ())
163           {
164             /* In non-stop, We mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
165                in order to go on what we were doing and postpone
166                querying notification events to some point safe to do so.
167                See details in the function comment of
168                remote.c:remote_notif_get_pending_events.
169 
170                In all-stop, GDB may be blocked to wait for the reply, we
171                shouldn't return to event loop until the expected reply
172                arrives.  For example:
173 
174                1.1) --> vCont;c
175                  GDB expects getting stop reply 'T05 thread:2'.
176                1.2) <-- %Notif
177                  <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
178 
179                After step #1.2, we return to the event loop, which
180                notices there is a new event on the
181                REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and calls the
182                handler, which will send 'vNotif' packet.
183                1.3) --> vNotif
184                It is not safe to start a new sequence, because target
185                is still running and GDB is expecting the stop reply
186                from stub.
187 
188                To solve this, whenever we parse a notification
189                successfully, we don't mark the
190                REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and let GDB blocked
191                there as before to get the sequence done.
192 
193                2.1) --> vCont;c
194                  GDB expects getting stop reply 'T05 thread:2'
195                2.2) <-- %Notif
196                  <Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
197                2.3) <-- T05 thread:2
198 
199                These pending notifications can be processed later.  */
200             mark_async_event_handler (state->get_pending_events_token);
201           }
202 
203       if (notif_debug)
204           gdb_printf (gdb_stdlog,
205                         "notif: Notification '%s' captured\n",
206                         nc->name);
207     }
208 }
209 
210 /* Return an allocated remote_notif_state.  */
211 
212 struct remote_notif_state *
remote_notif_state_allocate(remote_target * remote)213 remote_notif_state_allocate (remote_target *remote)
214 {
215   struct remote_notif_state *notif_state = new struct remote_notif_state;
216 
217   notif_state->remote = remote;
218 
219   /* Register async_event_handler for notification.  */
220 
221   notif_state->get_pending_events_token
222     = create_async_event_handler (remote_async_get_pending_events_handler,
223                                           notif_state, "remote-notif");
224 
225   return notif_state;
226 }
227 
228 /* Free STATE and its fields.  */
229 
~remote_notif_state()230 remote_notif_state::~remote_notif_state ()
231 {
232   /* Unregister async_event_handler for notification.  */
233   if (get_pending_events_token != NULL)
234     delete_async_event_handler (&get_pending_events_token);
235 }
236 
237 void _initialize_notif ();
238 void
_initialize_notif()239 _initialize_notif ()
240 {
241   add_setshow_boolean_cmd ("notification", no_class, &notif_debug,
242                                  _("\
243 Set debugging of async remote notification."), _("\
244 Show debugging of async remote notification."), _("\
245 When non-zero, debugging output about async remote notifications"
246 " is enabled."),
247                                  NULL,
248                                  NULL,
249                                  &setdebuglist, &showdebuglist);
250 }
251