aboutsummaryrefslogtreecommitdiff
path: root/gdb/tracepoint.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/tracepoint.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/tracepoint.c')
-rw-r--r--gdb/tracepoint.c146
1 files changed, 124 insertions, 22 deletions
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 8ec81a3..1726d5e 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -61,6 +61,8 @@ extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
#include <unistd.h>
#endif
+extern void stop_tracing ();
+
/* Maximum length of an agent aexpression.
This accounts for the fact that packets are limited to 400 bytes
(which includes everything -- including the checksum), and assumes
@@ -144,6 +146,8 @@ static struct cmd_list_element *tfindlist;
/* List of expressions to collect by default at each tracepoint hit. */
static char *default_collect = "";
+static int disconnected_tracing;
+
static char *target_buf;
static long target_buf_size;
@@ -172,6 +176,8 @@ static struct cleanup *make_cleanup_free_actions (struct breakpoint *t);
static void free_actions_list (char **actions_list);
static void free_actions_list_cleanup_wrapper (void *);
+extern void send_disconnected_tracing_value (int value);
+
extern void _initialize_tracepoint (void);
/* Utility: returns true if "target remote" */
@@ -1627,7 +1633,7 @@ remote_set_transparent_ranges (void)
to the target. If no errors,
Tell target to start a new trace experiment. */
-void download_tracepoint (struct breakpoint *t);
+int download_tracepoint (struct breakpoint *t);
static void
trace_start_command (char *args, int from_tty)
@@ -1637,6 +1643,7 @@ trace_start_command (char *args, int from_tty)
int ix;
struct breakpoint *t;
struct trace_state_variable *tsv;
+ int any_downloaded = 0;
dont_repeat (); /* Like "run", dangerous to repeat accidentally. */
@@ -1650,10 +1657,19 @@ trace_start_command (char *args, int from_tty)
tp_vec = all_tracepoints ();
for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
{
- download_tracepoint (t);
+ t->number_on_target = 0;
+ if (download_tracepoint (t))
+ {
+ t->number_on_target = t->number;
+ any_downloaded = 1;
+ }
}
VEC_free (breakpoint_p, tp_vec);
+ /* No point in tracing without any tracepoints... */
+ if (!any_downloaded)
+ error ("No tracepoints downloaded, not starting trace");
+
/* Init any trace state variables that start with nonzero values. */
for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
@@ -1686,9 +1702,10 @@ trace_start_command (char *args, int from_tty)
error (_("Trace can only be run on remote targets."));
}
-/* Send the definition of a single tracepoint to the target. */
+/* Send the definition of a single tracepoint to the target. Return 1
+ if successful, 0 if not. */
-void
+int
download_tracepoint (struct breakpoint *t)
{
CORE_ADDR tpaddr;
@@ -1759,7 +1776,7 @@ download_tracepoint (struct breakpoint *t)
error (_("Target does not support tracepoints."));
if (!t->actions && !*default_collect)
- return;
+ return 1;
encode_actions (t, &tdp_actions, &stepping_actions);
old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
@@ -1802,6 +1819,7 @@ download_tracepoint (struct breakpoint *t)
}
}
do_cleanups (old_chain);
+ return 1;
}
/* tstop command */
@@ -1810,11 +1828,7 @@ trace_stop_command (char *args, int from_tty)
{
if (target_is_remote ())
{
- putpkt ("QTStop");
- remote_get_noisy_reply (&target_buf, &target_buf_size);
- if (strcmp (target_buf, "OK"))
- error (_("Bogus reply from target: %s"), target_buf);
- trace_running_p = 0;
+ stop_tracing ();
if (deprecated_trace_start_stop_hook)
deprecated_trace_start_stop_hook (0, from_tty);
}
@@ -1822,26 +1836,48 @@ trace_stop_command (char *args, int from_tty)
error (_("Trace can only be run on remote targets."));
}
+void
+stop_tracing ()
+{
+ putpkt ("QTStop");
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Bogus reply from target: %s"), target_buf);
+ trace_running_p = 0;
+}
+
unsigned long trace_running_p;
+void
+get_trace_status ()
+{
+ putpkt ("qTStatus");
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+
+ if (target_buf[0] != 'T' ||
+ (target_buf[1] != '0' && target_buf[1] != '1'))
+ error (_("Bogus trace status reply from target: %s"), target_buf);
+
+ /* exported for use by the GUI */
+ trace_running_p = (target_buf[1] == '1');
+}
+
/* tstatus command */
static void
trace_status_command (char *args, int from_tty)
{
if (target_is_remote ())
{
- putpkt ("qTStatus");
- remote_get_noisy_reply (&target_buf, &target_buf_size);
-
- if (target_buf[0] != 'T' ||
- (target_buf[1] != '0' && target_buf[1] != '1'))
- error (_("Bogus reply from target: %s"), target_buf);
-
- /* exported for use by the GUI */
- trace_running_p = (target_buf[1] == '1');
+ get_trace_status ();
if (trace_running_p)
- printf_filtered (_("Trace is running on the target.\n"));
+ {
+ printf_filtered (_("Trace is running on the target.\n"));
+ if (disconnected_tracing)
+ printf_filtered (_("Trace will continue if GDB disconnects.\n"));
+ else
+ printf_filtered (_("Trace will stop if GDB disconnects.\n"));
+ }
else
printf_filtered (_("Trace is not running on the target.\n"));
@@ -1856,6 +1892,24 @@ trace_status_command (char *args, int from_tty)
error (_("Trace can only be run on remote targets."));
}
+void
+disconnect_or_stop_tracing (int from_tty)
+{
+ if (trace_running_p && from_tty)
+ {
+ int cont = query (_("Trace is running. Continue tracing after detach? "));
+ /* Note that we send the query result without affecting the
+ user's setting of disconnected_tracing, so that the answer is
+ a one-time-only. */
+ send_disconnected_tracing_value (cont);
+
+ /* Also ensure that we do the equivalent of a tstop command if
+ tracing is not to continue after the detach. */
+ if (!cont)
+ stop_tracing ();
+ }
+}
+
/* Worker function for the various flavors of the tfind command. */
static void
finish_tfind_command (char **msg,
@@ -1865,6 +1919,7 @@ finish_tfind_command (char **msg,
int target_frameno = -1, target_tracept = -1;
struct frame_id old_frame_id;
char *reply;
+ struct breakpoint *tp;
old_frame_id = get_frame_id (get_current_frame ());
@@ -1926,10 +1981,12 @@ finish_tfind_command (char **msg,
error (_("Bogus reply from target: %s"), reply);
}
+ tp = get_tracepoint_by_number_on_target (target_tracept);
+
reinit_frame_cache ();
registers_changed ();
set_traceframe_num (target_frameno);
- set_tracepoint_num (target_tracept);
+ set_tracepoint_num (tp ? tp->number : target_tracept);
if (target_frameno == -1)
set_traceframe_context (NULL);
else
@@ -2064,6 +2121,7 @@ static void
trace_find_tracepoint_command (char *args, int from_tty)
{
int tdp;
+ struct breakpoint *tp;
if (target_is_remote ())
{
@@ -2080,6 +2138,13 @@ trace_find_tracepoint_command (char *args, int from_tty)
else
tdp = parse_and_eval_long (args);
+ /* If we have the tracepoint on hand, use the number that the
+ target knows about (which may be different if we disconnected
+ and reconnected). */
+ tp = get_tracepoint (tdp);
+ if (tp)
+ tdp = tp->number_on_target;
+
sprintf (target_buf, "QTFrame:tdp:%x", tdp);
finish_tfind_command (&target_buf, &target_buf_size, from_tty);
}
@@ -2550,6 +2615,32 @@ trace_dump_command (char *args, int from_tty)
discard_cleanups (old_cleanups);
}
+/* Tell the target what to do with an ongoing tracing run if GDB
+ disconnects for some reason. */
+
+void
+send_disconnected_tracing_value (int value)
+{
+ char buf[30];
+
+ /* No need to do anything special if target not active. */
+ if (!target_is_remote ())
+ return;
+
+ sprintf (buf, "QTDisconnected:%x", value);
+ putpkt (buf);
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Target does not support this command."));
+}
+
+static void
+set_disconnected_tracing (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ send_disconnected_tracing_value (disconnected_tracing);
+}
+
/* Convert the memory pointed to by mem into hex, placing result in buf.
* Return a pointer to the last char put in buf (null)
* "stolen" from sparc-stub.c
@@ -2581,7 +2672,6 @@ get_traceframe_number (void)
return traceframe_number;
}
-
/* module initialization */
void
_initialize_tracepoint (void)
@@ -2747,6 +2837,18 @@ Show the list of expressions to collect by default"), NULL,
NULL, NULL,
&setlist, &showlist);
+ add_setshow_boolean_cmd ("disconnected-tracing", no_class,
+ &disconnected_tracing, _("\
+Set whether tracing continues after GDB disconnects."), _("\
+Show whether tracing continues after GDB disconnects."), _("\
+Use this to continue a tracing run even if GDB disconnects\n\
+or detaches from the target. You can reconnect later and look at\n\
+trace data collected in the meantime."),
+ set_disconnected_tracing,
+ NULL,
+ &setlist,
+ &showlist);
+
target_buf_size = 2048;
target_buf = xmalloc (target_buf_size);
}