aboutsummaryrefslogtreecommitdiff
path: root/gdb/remote.c
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>2010-01-06 20:31:28 +0000
committerStan Shebs <shebs@codesourcery.com>2010-01-06 20:31:28 +0000
commitd5551862dfa8c22746642b9a7f66b076557a0325 (patch)
tree7af2dbf86156804de50363834b2290d3a999b7ec /gdb/remote.c
parent30fd33bb933183e837b6709e189f1122333b95e2 (diff)
downloadgdb-d5551862dfa8c22746642b9a7f66b076557a0325.zip
gdb-d5551862dfa8c22746642b9a7f66b076557a0325.tar.gz
gdb-d5551862dfa8c22746642b9a7f66b076557a0325.tar.bz2
Support disconnected tracing.
* infcmd.c (detach_command): Ask whether to stop tracing. * cli/cli-cmds.c (quit_command): Ditto. * breakpoint.h (struct breakpoint): New field number_on_target. * breakpoint.c (create_tracepoint_from_upload): New function. (get_tracepoint_by_number_on_target): New function. * remote.c (struct remote): New field disconnected_tracing. (remote_disconnected_tracing_feature): New function. (remote_protocol_features): Add DisconnectedTracing. (struct uploaded_tp): New struct. (uploaded_tps): New global. (get_uploaded_tp): New function. (find_matching_tracepoint): New function. (remote_get_tracing_state): New function. (remote_start_remote): Call it. * tracepoint.c (disconnected_tracing): New global. (trace_start_command): Initialize number_on_target. (stop_tracing): New function, split out from... (trace_stop_command): Call stop_tracing. (get_trace_status): New function, split out from... (trace_status_command): Call get_trace_status, add info on disconnection behavior. (disconnect_or_stop_tracing): New function. (finish_tfind_command): Translate from number on target. (trace_find_tracepoint_command): Translate to number on target. (send_disconnected_tracing_value): New function. (set_disconnected_tracing): New function. (_initialize_tracepoint): Add disconnected-tracing variable. * NEWS: Mention disconnected tracing. * gdb.texinfo (Starting and Stopping Trace Experiments): Document disconnected tracing. (Tracepoint Packets): Document new protocol.
Diffstat (limited to 'gdb/remote.c')
-rw-r--r--gdb/remote.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/gdb/remote.c b/gdb/remote.c
index cba9f5b..262b97f 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -202,6 +202,9 @@ static void show_remote_protocol_packet_cmd (struct ui_file *file,
static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
static ptid_t read_ptid (char *buf, char **obuf);
+struct remote_state;
+static void remote_get_tracing_state (struct remote_state *);
+
static void remote_query_supported (void);
static void remote_check_symbols (struct objfile *objfile);
@@ -301,6 +304,10 @@ struct remote_state
/* True if the stub reports support for fast tracepoints. */
int fast_tracepoints;
+ /* True if the stub can continue running a trace while GDB is
+ disconnected. */
+ int disconnected_tracing;
+
/* Nonzero if the user has pressed Ctrl-C, but the target hasn't
responded to that. */
int ctrlc_pending_p;
@@ -2922,6 +2929,13 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
remote_check_symbols (symfile_objfile);
}
+ /* Possibly the target has been engaged in a trace run started
+ previously; find out where things are at. */
+ if (rs->disconnected_tracing)
+ {
+ remote_get_tracing_state (rs);
+ }
+
/* If breakpoints are global, insert them now. */
if (gdbarch_has_global_breakpoints (target_gdbarch)
&& breakpoints_always_inserted_mode ())
@@ -3149,6 +3163,15 @@ remote_fast_tracepoint_feature (const struct protocol_feature *feature,
rs->fast_tracepoints = (support == PACKET_ENABLE);
}
+static void
+remote_disconnected_tracing_feature (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *value)
+{
+ struct remote_state *rs = get_remote_state ();
+ rs->disconnected_tracing = (support == PACKET_ENABLE);
+}
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -3179,6 +3202,8 @@ static struct protocol_feature remote_protocol_features[] = {
PACKET_ConditionalTracepoints },
{ "FastTracepoints", PACKET_DISABLE, remote_fast_tracepoint_feature,
PACKET_FastTracepoints },
+ { "DisconnectedTracing", PACKET_DISABLE, remote_disconnected_tracing_feature,
+ -1 },
{ "ReverseContinue", PACKET_DISABLE, remote_supported_packet,
PACKET_bc },
{ "ReverseStep", PACKET_DISABLE, remote_supported_packet,
@@ -9130,6 +9155,184 @@ remote_new_objfile (struct objfile *objfile)
remote_check_symbols (objfile);
}
+/* Struct to collect random info about tracepoints on the target. */
+
+struct uploaded_tp {
+ int number;
+ enum bptype type;
+ ULONGEST addr;
+ int enabled;
+ int step;
+ int pass;
+ int orig_size;
+ char *cond;
+ int cond_len;
+ struct uploaded_tp *next;
+};
+
+struct uploaded_tp *uploaded_tps;
+
+struct uploaded_tp *
+get_uploaded_tp (int num)
+{
+ struct uploaded_tp *utp;
+
+ for (utp = uploaded_tps; utp; utp = utp->next)
+ if (utp->number == num)
+ return utp;
+ utp = (struct uploaded_tp *) xmalloc (sizeof (struct uploaded_tp));
+ utp->number = num;
+ utp->next = uploaded_tps;
+ uploaded_tps = utp;
+ return utp;
+}
+
+/* Look for an existing tracepoint that seems similar enough to the
+ uploaded one. Enablement isn't checked, because the user can
+ toggle that freely, and may have done so in anticipation of the
+ next trace run. */
+
+struct breakpoint *
+find_matching_tracepoint (struct uploaded_tp *utp)
+{
+ VEC(breakpoint_p) *tp_vec = all_tracepoints ();
+ int ix;
+ struct breakpoint *t;
+
+ for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
+ {
+ if (t->type == utp->type
+ && (t->loc && t->loc->address == utp->addr)
+ && t->step_count == utp->step
+ && t->pass_count == utp->pass
+ /* FIXME also test conditionals and actions */
+ )
+ return t;
+ }
+ return NULL;
+}
+
+/* Find out everything we can about the trace run that was already
+ happening on the target. This includes both running/stopped, and
+ the tracepoints that were in use. */
+
+static void
+remote_get_tracing_state (struct remote_state *rs)
+{
+ char *p;
+ ULONGEST num, addr, step, pass, orig_size, xlen;
+ int enabled, i;
+ enum bptype type;
+ char *cond;
+ struct uploaded_tp *utp;
+ struct breakpoint *t;
+ extern void get_trace_status ();
+ extern unsigned long trace_running_p;
+
+ get_trace_status ();
+ if (trace_running_p)
+ printf_filtered (_("Trace is running on the target.\n"));
+
+ putpkt ("qTfP");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ p = rs->buf;
+ while (*p != '\0')
+ {
+ if (*p == 'T')
+ {
+ p++;
+ p = unpack_varlen_hex (p, &num);
+ p++;
+ p = unpack_varlen_hex (p, &addr);
+ p++;
+ enabled = (*p++ == 'E');
+ p++;
+ p = unpack_varlen_hex (p, &step);
+ p++;
+ p = unpack_varlen_hex (p, &pass);
+ p++;
+ type = bp_tracepoint;
+ cond = NULL;
+ while (*p)
+ {
+ if (*p == 'F')
+ {
+ type = bp_fast_tracepoint;
+ p++;
+ p = unpack_varlen_hex (p, &orig_size);
+ }
+ else if (*p == 'X')
+ {
+ p++;
+ p = unpack_varlen_hex (p, &xlen);
+ p++; /* skip the comma */
+ cond = (char *) xmalloc (xlen);
+ hex2bin (p, cond, xlen);
+ p += 2 * xlen;
+ }
+ else
+ /* Silently skip over anything else. */
+ p++;
+ }
+ utp = get_uploaded_tp (num);
+ utp->type = type;
+ utp->addr = addr;
+ utp->enabled = enabled;
+ utp->step = step;
+ utp->pass = pass;
+ utp->cond = cond;
+ utp->cond_len = xlen;
+ }
+ else if (*p == 'A')
+ {
+ p++;
+ p = unpack_varlen_hex (p, &num);
+ p++;
+ p = unpack_varlen_hex (p, &addr);
+ p++;
+ utp = get_uploaded_tp (num);
+ /* FIXME save the action */
+ }
+ else if (*p == 'S')
+ {
+ p++;
+ p = unpack_varlen_hex (p, &num);
+ p++;
+ p = unpack_varlen_hex (p, &addr);
+ p++;
+ utp = get_uploaded_tp (num);
+ /* FIXME save the action */
+ }
+ else if (*p == 'l')
+ {
+ /* No more tracepoint info, get out of the loop. */
+ break;
+ }
+ putpkt ("qTsP");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ p = rs->buf;
+ }
+ /* Got all the tracepoint info, now look for matches among what we
+ already have in GDB. */
+ for (utp = uploaded_tps; utp; utp = utp->next)
+ {
+ t = find_matching_tracepoint (utp);
+ if (t)
+ {
+ printf_filtered (_("Assuming tracepoint %d is same as target's tracepoint %d.\n"),
+ t->number, utp->number);
+ t->number_on_target = utp->number;
+ }
+ else
+ {
+ extern void create_tracepoint_from_upload (int num, ULONGEST addr);
+ create_tracepoint_from_upload (utp->number, utp->addr);
+ }
+ }
+ /* FIXME free all the space */
+ uploaded_tps = NULL;
+}
+
void
_initialize_remote (void)
{