From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12570 invoked by alias); 19 Aug 2013 01:56:11 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 12523 invoked by uid 89); 19 Aug 2013 01:56:11 -0000 X-Spam-SWARE-Status: No, score=-4.5 required=5.0 tests=AWL,BAYES_00,FROM_12LTRDOM,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL autolearn=ham version=3.3.2 Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Mon, 19 Aug 2013 01:56:08 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1VBEhS-0002wA-Pj from Yao_Qi@mentor.com for gdb-patches@sourceware.org; Sun, 18 Aug 2013 18:56:06 -0700 Received: from SVR-ORW-FEM-04.mgc.mentorg.com ([147.34.97.41]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Sun, 18 Aug 2013 18:56:06 -0700 Received: from qiyao.dyndns.org (147.34.91.1) by svr-orw-fem-04.mgc.mentorg.com (147.34.97.41) with Microsoft SMTP Server id 14.2.247.3; Sun, 18 Aug 2013 18:56:06 -0700 From: Yao Qi To: Subject: [PATCH 2/6] Add annex in an async remote notification. Date: Mon, 19 Aug 2013 01:56:00 -0000 Message-ID: <1376877311-4135-3-git-send-email-yao@codesourcery.com> In-Reply-To: <1376877311-4135-1-git-send-email-yao@codesourcery.com> References: <1376877311-4135-1-git-send-email-yao@codesourcery.com> MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2013-08/txt/msg00485.txt.bz2 In order to support "Trace:status" notification and other similar usage (such as "Point:modified", about a breakpoint is modified), we introduce "annex" in the async remote notification, which is helpful to give us more details what the contents about in the async remote notification. The annex in each notification is optional. In the RSP: <-- %name:annex1:event --> vAck <-- annex2:event --> vAck <-- annex1:event --> OK As we can see above, three events of two annexes (annex1 and annex2) are sent. The parsing (receiving rsp packet) and writing (sending rsp packet) can be done on the annex level. Each annex has its own routines to send and parse packet, which is more OO. Also, annex, instead of notification, is the unit of support and they (GDB and GDBserver) can exchange their supported annexes by means of qSupported mechanism, which is done in the next patch. This patch adds "annex" to both GDB and GDBserver. I find 'struct notif_client' and 'struct notif_server' have three fields which can be shared, so additionally, we move some shared struct to common/common-notif.h. The documentation patch was approved by Eli here gdb: * common/notif-base.h: New. * Makefile.in (HFILES_NO_SRCDIR): Add "common/notif-base.h". * remote-notif.h: Include "notif-base.h". (struct notif_client) : Remove. : New. Caller update. * remote-notif.c (remote_notif_parse_1): New. (remote_notif_ack): Call remote_notif_parse_1. (remote_notif_parse): Likewise. (struct notif_client_annex): New. * remote.c (notif_client_annex_stop): New. gdb/gdbserver: * notif.h: Include "notif-base.h". (struct notif_server) : Remove. : New field. Caller update. (struct notif_annex_event): New. * notif.c (notif_write_event_1): New. (notif_write_event): Call notif_write_event_1 to write event. (notif_push): Likewise. * server.c (notif_annex_stop): New. (notif_stop): Update. gdb/doc: * gdb.texinfo (Notification Packets): Document 'annex'. --- gdb/Makefile.in | 3 +- gdb/common/notif-base.h | 79 +++++++++++++++++++++++++++++++++++++++++++++++ gdb/doc/gdb.texinfo | 12 +++++-- gdb/gdbserver/notif.c | 41 ++++++++++++++++++++---- gdb/gdbserver/notif.h | 20 ++++++----- gdb/gdbserver/server.c | 7 +++- gdb/remote-notif.c | 57 +++++++++++++++++++++++++++++----- gdb/remote-notif.h | 13 +------ gdb/remote.c | 15 +++++--- 9 files changed, 200 insertions(+), 47 deletions(-) create mode 100644 gdb/common/notif-base.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 9171940..2dc3ac0 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -854,7 +854,8 @@ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/format.h common/host-defs.h utils.h common/queue.h common/gdb_string.h \ common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \ gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h common/linux-btrace.h \ -ctf.h common/i386-cpuid.h common/i386-gcc-cpuid.h common/target-common.h +ctf.h common/i386-cpuid.h common/i386-gcc-cpuid.h common/target-common.h \ +common/notif-base.h # Header files that already have srcdir in them, or which are in objdir. diff --git a/gdb/common/notif-base.h b/gdb/common/notif-base.h new file mode 100644 index 0000000..0a3a4ed --- /dev/null +++ b/gdb/common/notif-base.h @@ -0,0 +1,79 @@ +/* Shared structs of asynchronous remote notification. + + Copyright (C) 2013 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ +#ifndef NOTIF_BASE_H +#define NOTIF_BASE_H 1 + +struct notif_event; +#ifndef GDBSERVER +struct notif_client; +#endif + +/* An annex of a notification. A notification may or may not have + annexes. */ + +struct notif_annex +{ + /* Name of this annex. If it is NULL, the notification doesn't have + annex, and the field PARSE is about the notification this annex + belongs to. For example, notification event "N1:event" doesn't + have an annex in the packet, but the notification object still has + one instance of 'notif_annex', and its field is NULL. */ + const char *name; + +#ifdef GDBSERVER + /* Write event EVENT to OWN_BUF. */ + void (*write) (struct notif_event *event, char *own_buf); +#else + /* Parse BUF to get the expected event and update EVENT. This + function may throw exception if contents in BUF is not the + expected event. */ + void (*parse) (struct notif_client *self, char *buf, + struct notif_event *event); +#endif +}; + +/* Iterate over annexes in *NOTIF by increasing INDEX from zero. */ + +#define NOTIF_ITER_ANNEX(NOTIF, INDEX, ANNEX) \ + for (INDEX = 0; (ANNEX) = &(NOTIF)->annexes[INDEX], (ANNEX)->name != NULL; INDEX++) + +/* Notification *NOTIF has annex or not. */ + +#define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL) + + +/* "Base class" of a notification. It can be extended in both GDB + and GDBserver to represent a type of notification. */ + +struct notif_base +{ + /* The notification packet, for example, '%Stop'. Note that '%' is + not in 'notif_name'. */ + const char *notif_name; + /* The name of ack packet, for example, 'vStopped'. */ + const char *ack_name; + + /* Annexes the notification has. The notification may or not have + annexes. Macro 'NOTIF_HAS_ANNEX' is to check notification has + annexes, and macro 'NOTIF_ITER_ANNEX' is to iterate over annexes + of the notification. */ + struct notif_annex *annexes; +}; + +#endif /* NOTIF_BASE_H */ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6d5dec4..375f988 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -40270,13 +40270,15 @@ transmit notifications without fear of confusing older clients. There are no notifications defined for @value{GDBN} to send at the moment, but we assume that most older stubs would ignore them, as well.) -Each notification is comprised of three parts: +Each notification is comprised of four parts: @table @samp -@item @var{name}:@var{event} +@item @var{name}[:@var{annex}]:@var{event} The notification packet is sent by the side that initiates the exchange (currently, only the stub does that), with @var{event} carrying the specific information about the notification. -@var{name} is the name of the notification. +@var{name} is the name of the notification. The @var{annex} is +specific to @var{name}; it can supply additional details about +@var{event}. @item @var{ack} The acknowledge sent by the other side, usually @value{GDBN}, to acknowledge the exchange and request the event. @@ -40339,15 +40341,17 @@ following example: @end smallexample The following notifications are defined: -@multitable @columnfractions 0.12 0.12 0.38 0.38 +@multitable @columnfractions 0.10 0.10 0.10 0.35 0.35 @item Notification @tab Ack +@tab Annex @tab Event @tab Description @item Stop @tab vStopped +@tab @tab @var{reply}. The @var{reply} has the form of a stop reply, as described in @ref{Stop Reply Packets}. Refer to @ref{Remote Non-Stop}, for information on how these notifications are acknowledged by diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c index e27746e..9300697 100644 --- a/gdb/gdbserver/notif.c +++ b/gdb/gdbserver/notif.c @@ -54,6 +54,30 @@ static struct notif_server *notifs[] = ¬if_stop, }; +/* Helper function to write EVENT of NOTIF to buffer OWN_BUF. */ + +static void +notif_write_event_1 (struct notif_base *notif, + struct notif_event *event, + char *own_buf) +{ + int annex_index = 0; + + /* If the NOTIF has annexes, extract the annex index from the + EVENT and append annex name to OWN_BUF; otherwise, NOTIF + doesn't have annex and use slot 0 of annexes for the + notification itself. */ + if (NOTIF_HAS_ANNEX (notif)) + { + annex_index + = ((struct notif_annex_event *) event)->annex_index; + sprintf (own_buf, "%s:", notif->annexes[annex_index].name); + own_buf += strlen (notif->annexes[annex_index].name) + 1; + } + + notif->annexes[annex_index].write (event, own_buf); +} + /* Write another event or an OK, if there are no more left, to OWN_BUF. */ @@ -65,7 +89,8 @@ notif_write_event (struct notif_server *notif, char *own_buf) struct notif_event *event = QUEUE_peek (notif_event_p, notif->queue); - notif->write (event, own_buf); + notif_write_event_1 ((struct notif_base *) notif, event, + own_buf); } else write_ok (own_buf); @@ -84,8 +109,9 @@ handle_notif_ack (char *own_buf, int packet_len) for (i = 0; i < ARRAY_SIZE (notifs); i++) { np = notifs[i]; - if (strncmp (own_buf, np->ack_name, strlen (np->ack_name)) == 0 - && packet_len == strlen (np->ack_name)) + if (0 == strncmp (own_buf, np->base.ack_name, + strlen (np->base.ack_name)) + && packet_len == strlen (np->base.ack_name)) break; } @@ -100,7 +126,7 @@ handle_notif_ack (char *own_buf, int packet_len) = QUEUE_deque (notif_event_p, np->queue); if (remote_debug) - fprintf (stderr, "%s: acking %d\n", np->ack_name, + fprintf (stderr, "%s: acking %d\n", np->base.ack_name, QUEUE_length (notif_event_p, np->queue)); xfree (head); @@ -120,7 +146,8 @@ notif_event_enque (struct notif_server *notif, QUEUE_enque (notif_event_p, notif->queue, event); if (remote_debug) - fprintf (stderr, "pending events: %s %d\n", notif->notif_name, + fprintf (stderr, "pending events: %s %d\n", + notif->base.notif_name, QUEUE_length (notif_event_p, notif->queue)); } @@ -142,10 +169,10 @@ notif_push (struct notif_server *np, struct notif_event *new_event) char buf[PBUFSIZ]; char *p = buf; - xsnprintf (p, PBUFSIZ, "%s:", np->notif_name); + xsnprintf (p, PBUFSIZ, "%s:", np->base.notif_name); p += strlen (p); - np->write (new_event, p); + notif_write_event_1 ((struct notif_base *) np, new_event, p); putpkt_notif (buf); } } diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h index c714e7b..037f1b0 100644 --- a/gdb/gdbserver/notif.h +++ b/gdb/gdbserver/notif.h @@ -20,6 +20,7 @@ #include "server.h" #include "target.h" #include "queue.h" +#include "notif-base.h" /* Structure holding information related to a single event. We keep a queue of these to push to GDB. It can be extended if @@ -33,25 +34,26 @@ typedef struct notif_event DECLARE_QUEUE_P (notif_event_p); +/* An event of a notification which has an annex. */ + +struct notif_annex_event +{ + struct notif_event base; + /* The index of the annex in field 'annexes' in 'notif_server'. */ + int annex_index; +}; + /* A type notification to GDB. An object of 'struct notif_server' represents a type of notification. */ typedef struct notif_server { - /* The name of ack packet, for example, 'vStopped'. */ - const char *ack_name; - - /* The notification packet, for example, '%Stop'. Note that '%' is - not in 'notif_name'. */ - const char *notif_name; + struct notif_base base; /* A queue of events to GDB. A new notif_event can be enque'ed into QUEUE at any appropriate time, and the notif_reply is deque'ed only when the ack from GDB arrives. */ QUEUE (notif_event_p) *queue; - - /* Write event EVENT to OWN_BUF. */ - void (*write) (struct notif_event *event, char *own_buf); } *notif_server_p; extern struct notif_server notif_stop; diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index a4b9129..71b860d 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -181,9 +181,14 @@ vstop_notif_reply (struct notif_event *event, char *own_buf) prepare_resume_reply (own_buf, vstop->ptid, &vstop->status); } +static struct notif_annex notif_annex_stop[] = +{ + { NULL, vstop_notif_reply, }, +}; + struct notif_server notif_stop = { - "vStopped", "Stop", NULL, vstop_notif_reply, + { "Stop", "vStopped", notif_annex_stop, }, NULL, }; static int diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c index 8b69f2f..d901a51 100644 --- a/gdb/remote-notif.c +++ b/gdb/remote-notif.c @@ -53,6 +53,44 @@ static struct notif_client *notifs[] = static void do_notif_event_xfree (void *arg); +/* Iterate over annexes in NC to match annex in BUF. */ + +static void +remote_notif_parse_1 (struct notif_client *nc, + struct notif_event *event, char *buf) +{ + const struct notif_annex *m = NULL; + const struct notif_base *base = (struct notif_base *) nc; + + if (NOTIF_HAS_ANNEX (base)) + { + int i; + + NOTIF_ITER_ANNEX (base, i, m) + { + if (strncmp (m->name, buf, strlen (base->notif_name)) == 0 + /* The annex is separated by ':' for the rest of + contents in BUF. */ + && buf[strlen (m->name)] == ':') + { + /* Pass BUF without annex and ':'. */ + m->parse (nc, buf + strlen (m->name) + 1, event); + break; + } + m = NULL; + } + } + else + { + m = &base->annexes[0]; + m->parse (nc, buf, event); + } + + if (m == NULL) + error (_("Can't parse '%s' for notif '%s'"), buf, + base->notif_name); +} + /* Parse the BUF for the expected notification NC, and send packet to acknowledge. */ @@ -65,9 +103,9 @@ remote_notif_ack (struct notif_client *nc, char *buf) if (notif_debug) fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n", - nc->ack_command); + nc->base.ack_name); - nc->parse (nc, buf, event); + remote_notif_parse_1 (nc, event, buf); nc->ack (nc, buf, event); discard_cleanups (old_chain); @@ -83,9 +121,10 @@ remote_notif_parse (struct notif_client *nc, char *buf) = make_cleanup (do_notif_event_xfree, event); if (notif_debug) - fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name); + fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", + nc->base.notif_name); - nc->parse (nc, buf, event); + remote_notif_parse_1 (nc, event, buf); discard_cleanups (old_chain); return event; @@ -157,8 +196,9 @@ handle_notification (struct remote_notif_state *state, char *buf) for (i = 0; i < ARRAY_SIZE (notifs); i++) { nc = notifs[i]; - if (strncmp (buf, nc->name, strlen (nc->name)) == 0 - && buf[strlen (nc->name)] == ':') + if (0 == strncmp (buf, nc->base.notif_name, + strlen (nc->base.notif_name)) + && buf[strlen (nc->base.notif_name)] == ':') break; nc = NULL; } @@ -180,7 +220,8 @@ handle_notification (struct remote_notif_state *state, char *buf) else { struct notif_event *event - = remote_notif_parse (nc, buf + strlen (nc->name) + 1); + = remote_notif_parse (nc, + buf + strlen (nc->base.notif_name) + 1); /* Be careful to only set it after parsing, since an error may be thrown then. */ @@ -233,7 +274,7 @@ handle_notification (struct remote_notif_state *state, char *buf) if (notif_debug) fprintf_unfiltered (gdb_stdlog, "notif: Notification '%s' captured\n", - nc->name); + nc->base.notif_name); } } diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h index 05d2613..454dce8 100644 --- a/gdb/remote-notif.h +++ b/gdb/remote-notif.h @@ -21,6 +21,7 @@ #define REMOTE_NOTIF_H #include "queue.h" +#include "notif-base.h" /* An event of a type of async remote notification. */ @@ -35,17 +36,7 @@ struct notif_event typedef struct notif_client { - /* The name of notification packet. */ - const char *name; - - /* The packet to acknowledge a previous reply. */ - const char *ack_command; - - /* Parse BUF to get the expected event and update EVENT. This - function may throw exception if contents in BUF is not the - expected event. */ - void (*parse) (struct notif_client *self, char *buf, - struct notif_event *event); + struct notif_base base; /* Send field to remote, and do some checking. If something wrong, throw an exception. */ diff --git a/gdb/remote.c b/gdb/remote.c index e50623a..9700a8e 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -5329,7 +5329,7 @@ remote_notif_stop_ack (struct notif_client *self, char *buf, struct stop_reply *stop_reply = (struct stop_reply *) event; /* acknowledge */ - putpkt ((char *) self->ack_command); + putpkt ((char *) self->base.ack_name); if (stop_reply->ws.kind == TARGET_WAITKIND_IGNORE) /* We got an unknown stop reply. */ @@ -5369,13 +5369,16 @@ remote_notif_stop_alloc_reply (void) return r; } +static struct notif_annex notif_client_annex_stop[] = +{ + { NULL, remote_notif_stop_parse, }, +}; + /* A client of notification Stop. */ struct notif_client notif_client_stop = { - "Stop", - "vStopped", - remote_notif_stop_parse, + { "Stop", "vStopped", notif_client_annex_stop, }, remote_notif_stop_ack, remote_notif_stop_can_get_pending_events, remote_notif_stop_alloc_reply, @@ -5802,7 +5805,7 @@ remote_notif_get_pending_events (struct notif_client *nc) if (notif_debug) fprintf_unfiltered (gdb_stdlog, "notif: process: '%s' ack pending event\n", - nc->name); + nc->base.notif_name); /* acknowledge */ nc->ack (nc, rs->buf, nc->pending_event); @@ -5822,7 +5825,7 @@ remote_notif_get_pending_events (struct notif_client *nc) if (notif_debug) fprintf_unfiltered (gdb_stdlog, "notif: process: '%s' no pending reply\n", - nc->name); + nc->base.notif_name); } } -- 1.7.7.6