Do not pass NULL to memcpy
[deliverable/binutils-gdb.git] / gdb / remote-notif.c
CommitLineData
722247f1
YQ
1/* Remote notification in GDB protocol
2
e2882c85 3 Copyright (C) 1988-2018 Free Software Foundation, Inc.
722247f1
YQ
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 "defs.h"
35#include "remote.h"
36#include "remote-notif.h"
76727919 37#include "observable.h"
722247f1
YQ
38#include "event-loop.h"
39#include "target.h"
40#include "inferior.h"
45741a9c 41#include "infrun.h"
c9b6281a 42#include "gdbcmd.h"
722247f1 43
99f0a309 44int notif_debug = 0;
722247f1
YQ
45
46/* Supported clients of notifications. */
47
48static struct notif_client *notifs[] =
49{
50 &notif_client_stop,
51};
52
f48ff2a7
YQ
53gdb_static_assert (ARRAY_SIZE (notifs) == REMOTE_NOTIF_LAST);
54
722247f1
YQ
55static void do_notif_event_xfree (void *arg);
56
57/* Parse the BUF for the expected notification NC, and send packet to
58 acknowledge. */
59
60void
6b8edb51
PA
61remote_notif_ack (remote_target *remote,
62 struct notif_client *nc, char *buf)
722247f1
YQ
63{
64 struct notif_event *event = nc->alloc_event ();
65 struct cleanup *old_chain
66 = make_cleanup (do_notif_event_xfree, event);
67
68 if (notif_debug)
69 fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
70 nc->ack_command);
71
6b8edb51
PA
72 nc->parse (remote, nc, buf, event);
73 nc->ack (remote, nc, buf, event);
722247f1
YQ
74
75 discard_cleanups (old_chain);
76}
77
78/* Parse the BUF for the expected notification NC. */
79
80struct notif_event *
6b8edb51
PA
81remote_notif_parse (remote_target *remote,
82 struct notif_client *nc, char *buf)
722247f1
YQ
83{
84 struct notif_event *event = nc->alloc_event ();
85 struct cleanup *old_chain
86 = make_cleanup (do_notif_event_xfree, event);
87
88 if (notif_debug)
89 fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
90
6b8edb51 91 nc->parse (remote, nc, buf, event);
722247f1
YQ
92
93 discard_cleanups (old_chain);
94 return event;
95}
96
722247f1
YQ
97DEFINE_QUEUE_P (notif_client_p);
98
5965e028
YQ
99/* Process notifications in STATE's notification queue one by one.
100 EXCEPT is not expected in the queue. */
722247f1
YQ
101
102void
5965e028
YQ
103remote_notif_process (struct remote_notif_state *state,
104 struct notif_client *except)
722247f1 105{
5965e028 106 while (!QUEUE_is_empty (notif_client_p, state->notif_queue))
722247f1
YQ
107 {
108 struct notif_client *nc = QUEUE_deque (notif_client_p,
5965e028 109 state->notif_queue);
722247f1
YQ
110
111 gdb_assert (nc != except);
112
6b8edb51
PA
113 if (nc->can_get_pending_events (state->remote, nc))
114 remote_notif_get_pending_events (state->remote, nc);
722247f1
YQ
115 }
116}
117
118static void
119remote_async_get_pending_events_handler (gdb_client_data data)
120{
6efcd9a8 121 gdb_assert (target_is_non_stop_p ());
19ba03f4 122 remote_notif_process ((struct remote_notif_state *) data, NULL);
722247f1
YQ
123}
124
5965e028
YQ
125/* Remote notification handler. Parse BUF, queue notification and
126 update STATE. */
722247f1
YQ
127
128void
5965e028 129handle_notification (struct remote_notif_state *state, char *buf)
722247f1 130{
62972e0b
YQ
131 struct notif_client *nc;
132 size_t i;
722247f1
YQ
133
134 for (i = 0; i < ARRAY_SIZE (notifs); i++)
135 {
62972e0b
YQ
136 const char *name = notifs[i]->name;
137
61012eef 138 if (startswith (buf, name)
62972e0b 139 && buf[strlen (name)] == ':')
722247f1
YQ
140 break;
141 }
142
143 /* We ignore notifications we don't recognize, for compatibility
144 with newer stubs. */
62972e0b 145 if (i == ARRAY_SIZE (notifs))
722247f1
YQ
146 return;
147
62972e0b
YQ
148 nc = notifs[i];
149
f48ff2a7 150 if (state->pending_event[nc->id] != NULL)
722247f1
YQ
151 {
152 /* We've already parsed the in-flight reply, but the stub for some
153 reason thought we didn't, possibly due to timeout on its side.
154 Just ignore it. */
155 if (notif_debug)
156 fprintf_unfiltered (gdb_stdlog,
157 "notif: ignoring resent notification\n");
158 }
159 else
160 {
161 struct notif_event *event
6b8edb51 162 = remote_notif_parse (state->remote, nc, buf + strlen (nc->name) + 1);
722247f1
YQ
163
164 /* Be careful to only set it after parsing, since an error
165 may be thrown then. */
f48ff2a7 166 state->pending_event[nc->id] = event;
722247f1
YQ
167
168 /* Notify the event loop there's a stop reply to acknowledge
169 and that there may be more events to fetch. */
5965e028 170 QUEUE_enque (notif_client_p, state->notif_queue, nc);
6efcd9a8 171 if (target_is_non_stop_p ())
722247f1
YQ
172 {
173 /* In non-stop, We mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
174 in order to go on what we were doing and postpone
175 querying notification events to some point safe to do so.
176 See details in the function comment of
177 remote.c:remote_notif_get_pending_events.
178
179 In all-stop, GDB may be blocked to wait for the reply, we
180 shouldn't return to event loop until the expected reply
181 arrives. For example:
182
183 1.1) --> vCont;c
184 GDB expects getting stop reply 'T05 thread:2'.
185 1.2) <-- %Notif
186 <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
187
188 After step #1.2, we return to the event loop, which
189 notices there is a new event on the
190 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and calls the
191 handler, which will send 'vNotif' packet.
192 1.3) --> vNotif
193 It is not safe to start a new sequence, because target
194 is still running and GDB is expecting the stop reply
195 from stub.
196
197 To solve this, whenever we parse a notification
198 successfully, we don't mark the
199 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and let GDB blocked
200 there as before to get the sequence done.
201
202 2.1) --> vCont;c
203 GDB expects getting stop reply 'T05 thread:2'
204 2.2) <-- %Notif
205 <Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
206 2.3) <-- T05 thread:2
207
208 These pending notifications can be processed later. */
5965e028 209 mark_async_event_handler (state->get_pending_events_token);
722247f1
YQ
210 }
211
212 if (notif_debug)
213 fprintf_unfiltered (gdb_stdlog,
214 "notif: Notification '%s' captured\n",
215 nc->name);
216 }
217}
218
f48ff2a7 219/* Invoke destructor of EVENT and xfree it. */
722247f1 220
f48ff2a7
YQ
221void
222notif_event_xfree (struct notif_event *event)
722247f1 223{
f48ff2a7 224 if (event != NULL && event->dtr != NULL)
722247f1
YQ
225 event->dtr (event);
226
227 xfree (event);
228}
229
f48ff2a7
YQ
230/* Cleanup wrapper. */
231
232static void
233do_notif_event_xfree (void *arg)
234{
19ba03f4 235 notif_event_xfree ((struct notif_event *) arg);
f48ff2a7
YQ
236}
237
5965e028
YQ
238/* Return an allocated remote_notif_state. */
239
240struct remote_notif_state *
6b8edb51 241remote_notif_state_allocate (remote_target *remote)
5965e028 242{
8d749320 243 struct remote_notif_state *notif_state = XCNEW (struct remote_notif_state);
5965e028 244
6b8edb51
PA
245 notif_state->remote = remote;
246
5965e028
YQ
247 notif_state->notif_queue = QUEUE_alloc (notif_client_p, NULL);
248
249 /* Register async_event_handler for notification. */
250
251 notif_state->get_pending_events_token
252 = create_async_event_handler (remote_async_get_pending_events_handler,
253 notif_state);
254
255 return notif_state;
256}
257
258/* Free STATE and its fields. */
259
260void
261remote_notif_state_xfree (struct remote_notif_state *state)
722247f1 262{
f48ff2a7
YQ
263 int i;
264
5965e028
YQ
265 QUEUE_free (notif_client_p, state->notif_queue);
266
267 /* Unregister async_event_handler for notification. */
268 if (state->get_pending_events_token != NULL)
269 delete_async_event_handler (&state->get_pending_events_token);
722247f1 270
f48ff2a7
YQ
271 for (i = 0; i < REMOTE_NOTIF_LAST; i++)
272 notif_event_xfree (state->pending_event[i]);
273
5965e028 274 xfree (state);
722247f1
YQ
275}
276
722247f1
YQ
277void
278_initialize_notif (void)
279{
c9b6281a
YQ
280 add_setshow_boolean_cmd ("notification", no_class, &notif_debug,
281 _("\
282Set debugging of async remote notification."), _("\
283Show debugging of async remote notification."), _("\
284When non-zero, debugging output about async remote notifications"
285" is enabled."),
286 NULL,
287 NULL,
288 &setdebuglist, &showdebuglist);
722247f1 289}
This page took 0.659269 seconds and 4 git commands to generate.