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