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/tracepoint.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/tracepoint.c')
-rw-r--r-- | gdb/tracepoint.c | 146 |
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); } |