#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
/* 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;
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" */
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)
int ix;
struct breakpoint *t;
struct trace_state_variable *tsv;
+ int any_downloaded = 0;
dont_repeat (); /* Like "run", dangerous to repeat accidentally. */
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)
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;
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,
}
}
do_cleanups (old_chain);
+ return 1;
}
/* tstop command */
{
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);
}
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"));
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,
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 ());
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
trace_find_tracepoint_command (char *args, int from_tty)
{
int tdp;
+ struct breakpoint *tp;
if (target_is_remote ())
{
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);
}
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
return traceframe_number;
}
-
/* module initialization */
void
_initialize_tracepoint (void)
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);
}