diff options
author | Stan Shebs <shebs@codesourcery.com> | 2010-01-06 20:31:28 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 2010-01-06 20:31:28 +0000 |
commit | d5551862dfa8c22746642b9a7f66b076557a0325 (patch) | |
tree | 7af2dbf86156804de50363834b2290d3a999b7ec /gdb/remote.c | |
parent | 30fd33bb933183e837b6709e189f1122333b95e2 (diff) | |
download | gdb-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.c | 203 |
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) { |