GDB (API)
|
00001 /* Remote notification in GDB protocol 00002 00003 Copyright (C) 1988-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 /* Remote async notification is sent from remote target over RSP. 00021 Each type of notification is represented by an object of 00022 'struct notif', which has a field 'pending_reply'. It is not 00023 NULL when GDB receives a notification from GDBserver, but hasn't 00024 acknowledge yet. Before GDB acknowledges the notification, 00025 GDBserver shouldn't send notification again (see the header comments 00026 in gdbserver/notif.c). 00027 00028 Notifications are processed in an almost-unified approach for both 00029 all-stop mode and non-stop mode, except the timing to process them. 00030 In non-stop mode, notifications are processed in 00031 remote_async_get_pending_events_handler, while in all-stop mode, 00032 they are processed in remote_resume. */ 00033 00034 #include "defs.h" 00035 #include "remote.h" 00036 #include "remote-notif.h" 00037 #include "observer.h" 00038 #include "event-loop.h" 00039 #include "target.h" 00040 #include "inferior.h" 00041 #include "gdbcmd.h" 00042 00043 #include <string.h> 00044 00045 int notif_debug = 0; 00046 00047 /* Supported clients of notifications. */ 00048 00049 static struct notif_client *notifs[] = 00050 { 00051 ¬if_client_stop, 00052 }; 00053 00054 gdb_static_assert (ARRAY_SIZE (notifs) == REMOTE_NOTIF_LAST); 00055 00056 static void do_notif_event_xfree (void *arg); 00057 00058 /* Parse the BUF for the expected notification NC, and send packet to 00059 acknowledge. */ 00060 00061 void 00062 remote_notif_ack (struct notif_client *nc, char *buf) 00063 { 00064 struct notif_event *event = nc->alloc_event (); 00065 struct cleanup *old_chain 00066 = make_cleanup (do_notif_event_xfree, event); 00067 00068 if (notif_debug) 00069 fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n", 00070 nc->ack_command); 00071 00072 nc->parse (nc, buf, event); 00073 nc->ack (nc, buf, event); 00074 00075 discard_cleanups (old_chain); 00076 } 00077 00078 /* Parse the BUF for the expected notification NC. */ 00079 00080 struct notif_event * 00081 remote_notif_parse (struct notif_client *nc, char *buf) 00082 { 00083 struct notif_event *event = nc->alloc_event (); 00084 struct cleanup *old_chain 00085 = make_cleanup (do_notif_event_xfree, event); 00086 00087 if (notif_debug) 00088 fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name); 00089 00090 nc->parse (nc, buf, event); 00091 00092 discard_cleanups (old_chain); 00093 return event; 00094 } 00095 00096 DEFINE_QUEUE_P (notif_client_p); 00097 00098 /* Process notifications in STATE's notification queue one by one. 00099 EXCEPT is not expected in the queue. */ 00100 00101 void 00102 remote_notif_process (struct remote_notif_state *state, 00103 struct notif_client *except) 00104 { 00105 while (!QUEUE_is_empty (notif_client_p, state->notif_queue)) 00106 { 00107 struct notif_client *nc = QUEUE_deque (notif_client_p, 00108 state->notif_queue); 00109 00110 gdb_assert (nc != except); 00111 00112 if (nc->can_get_pending_events (nc)) 00113 remote_notif_get_pending_events (nc); 00114 } 00115 } 00116 00117 static void 00118 remote_async_get_pending_events_handler (gdb_client_data data) 00119 { 00120 gdb_assert (non_stop); 00121 remote_notif_process (data, NULL); 00122 } 00123 00124 /* Remote notification handler. Parse BUF, queue notification and 00125 update STATE. */ 00126 00127 void 00128 handle_notification (struct remote_notif_state *state, char *buf) 00129 { 00130 struct notif_client *nc = NULL; 00131 int i; 00132 00133 for (i = 0; i < ARRAY_SIZE (notifs); i++) 00134 { 00135 nc = notifs[i]; 00136 if (strncmp (buf, nc->name, strlen (nc->name)) == 0 00137 && buf[strlen (nc->name)] == ':') 00138 break; 00139 } 00140 00141 /* We ignore notifications we don't recognize, for compatibility 00142 with newer stubs. */ 00143 if (nc == NULL) 00144 return; 00145 00146 if (state->pending_event[nc->id] != NULL) 00147 { 00148 /* We've already parsed the in-flight reply, but the stub for some 00149 reason thought we didn't, possibly due to timeout on its side. 00150 Just ignore it. */ 00151 if (notif_debug) 00152 fprintf_unfiltered (gdb_stdlog, 00153 "notif: ignoring resent notification\n"); 00154 } 00155 else 00156 { 00157 struct notif_event *event 00158 = remote_notif_parse (nc, buf + strlen (nc->name) + 1); 00159 00160 /* Be careful to only set it after parsing, since an error 00161 may be thrown then. */ 00162 state->pending_event[nc->id] = event; 00163 00164 /* Notify the event loop there's a stop reply to acknowledge 00165 and that there may be more events to fetch. */ 00166 QUEUE_enque (notif_client_p, state->notif_queue, nc); 00167 if (non_stop) 00168 { 00169 /* In non-stop, We mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN 00170 in order to go on what we were doing and postpone 00171 querying notification events to some point safe to do so. 00172 See details in the function comment of 00173 remote.c:remote_notif_get_pending_events. 00174 00175 In all-stop, GDB may be blocked to wait for the reply, we 00176 shouldn't return to event loop until the expected reply 00177 arrives. For example: 00178 00179 1.1) --> vCont;c 00180 GDB expects getting stop reply 'T05 thread:2'. 00181 1.2) <-- %Notif 00182 <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN> 00183 00184 After step #1.2, we return to the event loop, which 00185 notices there is a new event on the 00186 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and calls the 00187 handler, which will send 'vNotif' packet. 00188 1.3) --> vNotif 00189 It is not safe to start a new sequence, because target 00190 is still running and GDB is expecting the stop reply 00191 from stub. 00192 00193 To solve this, whenever we parse a notification 00194 successfully, we don't mark the 00195 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and let GDB blocked 00196 there as before to get the sequence done. 00197 00198 2.1) --> vCont;c 00199 GDB expects getting stop reply 'T05 thread:2' 00200 2.2) <-- %Notif 00201 <Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN> 00202 2.3) <-- T05 thread:2 00203 00204 These pending notifications can be processed later. */ 00205 mark_async_event_handler (state->get_pending_events_token); 00206 } 00207 00208 if (notif_debug) 00209 fprintf_unfiltered (gdb_stdlog, 00210 "notif: Notification '%s' captured\n", 00211 nc->name); 00212 } 00213 } 00214 00215 /* Invoke destructor of EVENT and xfree it. */ 00216 00217 void 00218 notif_event_xfree (struct notif_event *event) 00219 { 00220 if (event != NULL && event->dtr != NULL) 00221 event->dtr (event); 00222 00223 xfree (event); 00224 } 00225 00226 /* Cleanup wrapper. */ 00227 00228 static void 00229 do_notif_event_xfree (void *arg) 00230 { 00231 notif_event_xfree (arg); 00232 } 00233 00234 /* Return an allocated remote_notif_state. */ 00235 00236 struct remote_notif_state * 00237 remote_notif_state_allocate (void) 00238 { 00239 struct remote_notif_state *notif_state = xzalloc (sizeof (*notif_state)); 00240 00241 notif_state->notif_queue = QUEUE_alloc (notif_client_p, NULL); 00242 00243 /* Register async_event_handler for notification. */ 00244 00245 notif_state->get_pending_events_token 00246 = create_async_event_handler (remote_async_get_pending_events_handler, 00247 notif_state); 00248 00249 return notif_state; 00250 } 00251 00252 /* Free STATE and its fields. */ 00253 00254 void 00255 remote_notif_state_xfree (struct remote_notif_state *state) 00256 { 00257 int i; 00258 00259 QUEUE_free (notif_client_p, state->notif_queue); 00260 00261 /* Unregister async_event_handler for notification. */ 00262 if (state->get_pending_events_token != NULL) 00263 delete_async_event_handler (&state->get_pending_events_token); 00264 00265 for (i = 0; i < REMOTE_NOTIF_LAST; i++) 00266 notif_event_xfree (state->pending_event[i]); 00267 00268 xfree (state); 00269 } 00270 00271 /* -Wmissing-prototypes */ 00272 extern initialize_file_ftype _initialize_notif; 00273 00274 void 00275 _initialize_notif (void) 00276 { 00277 add_setshow_boolean_cmd ("notification", no_class, ¬if_debug, 00278 _("\ 00279 Set debugging of async remote notification."), _("\ 00280 Show debugging of async remote notification."), _("\ 00281 When non-zero, debugging output about async remote notifications" 00282 " is enabled."), 00283 NULL, 00284 NULL, 00285 &setdebuglist, &showdebuglist); 00286 }