* 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.
+2010-01-06 Stan Shebs <stan@codesourcery.com>
+
+ 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.
+
2010-01-06 Tristan Gingold <gingold@adacore.com>
* symtab.c (lookup_global_symbol_from_objfile): Rename objfile
lists inferiors that are not running yet or that have exited
already. See also "New commands" and "New options" below.
-* Trace state variables
+* New tracing features
+
+ GDB's tracepoint facility now includes several new features:
+
+ ** Trace state variables
GDB tracepoints now include support for trace state variables, which
are variables managed by the target agent during a tracing
command to create, and "info tvariables" to view; see "Trace State
Variables" in the manual for more detail.
-* Fast tracepoints
+ ** Fast tracepoints
GDB now includes an option for defining fast tracepoints, which
targets may implement more efficiently, such as by installing a jump
fast tracepoint, use the "ftrace" command, with syntax identical to
the regular trace command.
+ ** Disconnected tracing
+
+ It is now possible to detach GDB from the target while it is running
+ a trace experiment, then reconnect later to see how the experiment
+ is going. In addition, a new variable disconnected-tracing lets you
+ tell the target agent whether to continue running a trace if the
+ connection is lost unexpectedly.
+
* Changed commands
disassemble
This is a useful way to ensure essential items are not overlooked,
such as registers or a critical global variable.
+set disconnected-tracing
+show disconnected-tracing
+ If set to 1, the target is instructed to continue tracing if it
+ loses its connection to GDB. If 0, the target is to stop tracing
+ upon disconnection.
+
* New remote packets
QTDV
qTV
Get the current value of a trace state variable.
+QTDisconnected
+ Set desired tracing behavior upon disconnection.
+
+qTfP, qTsP
+ Get data about the tracepoints currently in use.
+
* Bug fixes
Process record now works correctly with hardware watchpoints.
set_tracepoint_count (breakpoint_count);
}
+extern void create_tracepoint_from_upload (int num, enum bptype type,
+ ULONGEST addr);
+
+void
+create_tracepoint_from_upload (int num, enum bptype type, ULONGEST addr)
+{
+ char buf[100];
+ struct breakpoint *tp;
+
+ sprintf (buf, "*0x%s", paddress (get_current_arch (), addr));
+ if (type == bp_fast_tracepoint)
+ ftrace_command (buf, 0);
+ else
+ trace_command (buf, 0);
+
+ /* Record that this tracepoint is numbered differently on host and
+ target. */
+ tp = get_tracepoint (tracepoint_count);
+ tp->number_on_target = num;
+}
+
/* Print information on tracepoint number TPNUM_EXP, or all if
omitted. */
return NULL;
}
+/* Find the tracepoint with the given target-side number (which may be
+ different from the tracepoint number after disconnecting and
+ reconnecting). */
+
+struct breakpoint *
+get_tracepoint_by_number_on_target (int num)
+{
+ struct breakpoint *t;
+
+ ALL_TRACEPOINTS (t)
+ if (t->number_on_target == num)
+ return t;
+
+ return NULL;
+}
+
/* Utility: parse a tracepoint number and look it up in the list.
If MULTI_P is true, there might be a range of tracepoints in ARG.
if OPTIONAL_P is true, then if the argument is missing, the most
/* Chain of action lines to execute when this tracepoint is hit. */
struct action_line *actions;
+
+ /* The number of the tracepoint on the target. */
+ int number_on_target;
};
typedef struct breakpoint *breakpoint_p;
/* Return a tracepoint with the given number if found. */
extern struct breakpoint *get_tracepoint (int num);
+extern struct breakpoint *get_tracepoint_by_number_on_target (int num);
+
/* Find a tracepoint by parsing a number in the supplied string. */
extern struct breakpoint *get_tracepoint_by_number (char **arg, int multi_p,
int optional_p);
#include "objfiles.h"
#include "source.h"
#include "disasm.h"
+extern void disconnect_or_stop_tracing (int from_tty);
#include "ui-out.h"
{
if (!quit_confirm ())
error (_("Not confirmed."));
+
+ disconnect_or_stop_tracing (from_tty);
+
quit_force (args, from_tty);
}
+2010-01-06 Stan Shebs <stan@codesourcery.com>
+
+ * gdb.texinfo (Starting and Stopping Trace Experiments): Document
+ disconnected tracing.
+ (Tracepoint Packets): Document new protocol.
+
2010-01-05 Stan Shebs <stan@codesourcery.com>
* gdb.texinfo (Create and Delete Tracepoints): Describe fast
(@value{GDBP}) @b{tstop}
@end smallexample
+@cindex disconnected tracing
+You can choose to continue running the trace experiment even if
+@value{GDBN} disconnects from the target, voluntarily or
+involuntarily. For commands such as @code{detach}, the debugger will
+ask what you want to do with the trace. But for unexpected
+terminations (@value{GDBN} crash, network outage), it would be
+unfortunate to lose hard-won trace data, so the variable
+@code{disconnected-tracing} lets you decide whether the trace should
+continue running without @value{GDBN}.
+
+@table @code
+@item set disconnected-tracing on
+@itemx set disconnected-tracing off
+@kindex set disconnected-tracing
+Choose whether a tracing run should continue to run if @value{GDBN}
+has disconnected from the target. Note that @code{detach} or
+@code{quit} will ask you directly what to do about a running trace no
+matter what this variable's setting, so the variable is mainly useful
+for handling unexpected situations, such as loss of the network.
+
+@item show disconnected-tracing
+@kindex show disconnected-tracing
+Show the current choice for disconnected tracing.
+
+@end table
+
+When you reconnect to the target, the trace experiment may or may not
+still be running; it might have filled the trace buffer in the
+meantime, or stopped for one of the other reasons. If it is running,
+it will continue after reconnection.
+
+Upon reconnection, the target will upload information about the
+tracepoints in effect. @value{GDBN} will then compare that
+information to the set of tracepoints currently defined, and attempt
+to match them up, allowing for the possibility that the numbers may
+have changed due to creation and deletion in the meantime. If one of
+the target's tracepoints does not match any in @value{GDBN}, the
+debugger will create a new tracepoint, so that you have a number with
+which to specify that tracepoint. This matching-up process is
+necessarily heuristic, and it may result in useless tracepoints being
+created; you may simply delete them if they are of no use.
@node Analyze Collected Data
@section Using the Collected Data
(if available), until the target ceases to request them.
@end table
-@item QTDP
+@item QTDisconnected
+@itemx QTDP
+@itemx QTDV
+@itemx QTfP
@itemx QTFrame
@xref{Tracepoint Packets}.
conventions above. Please don't use this packet as a model for new
packets.)
-@item QTStart
+@item QTsP
+@itemx QTStart
@itemx QTStop
@itemx QTinit
@itemx QTro
@itemx qTStatus
+@itemx qTV
@xref{Tracepoint Packets}.
@item qXfer:@var{object}:read:@var{annex}:@var{offset},@var{length}
still have the same contents they did when the tracepoint was hit, so
there's no reason for the stub to refuse to provide their contents.
+@item QTDisconnected:@var{value}
+Set the choice to what to do with the tracing run when @value{GDBN}
+disconnects from the target. A @var{value} of 1 directs the target to
+continue the tracing run, while 0 tells the target to stop tracing if
+@value{GDBN} is no longer in the picture.
+
@item qTStatus
Ask the stub if there is a trace experiment running right now.
was not collected.
@end table
+@item qTfP
+@itemx qTsP
+These packets request data about tracepoints that are being used by
+the target. @value{GDBN} sends @code{qTfP} to get the first piece
+of data, and multiple @code{qTsP} to get additional pieces. Replies
+to these packets generally take the form of the @code{QTDP} packets
+that define tracepoints. (FIXME add detailed syntax)
+
@end table
@node Host I/O Packets
#include "valprint.h"
#include "inline-frame.h"
+extern void disconnect_or_stop_tracing (int from_tty);
+
/* Functions exported for general use, in inferior.h: */
void all_registers_info (char *, int);
if (ptid_equal (inferior_ptid, null_ptid))
error (_("The program is not being run."));
+ disconnect_or_stop_tracing (from_tty);
+
target_detach (args, from_tty);
/* If the solist is global across inferiors, don't clear it when we
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);
/* 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;
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 ())
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,
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,
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)
{
#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);
}